123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- package generator
- import (
- "github.com/jcla1/gisp/parser"
- "fmt"
- "go/ast"
- "go/token"
- )
- var anyType = makeSelectorExpr(ast.NewIdent("core"), ast.NewIdent("Any"))
- func GenerateAST(tree []parser.Node) *ast.File {
- f := &ast.File{Name: ast.NewIdent("main")}
- decls := make([]ast.Decl, 0, len(tree))
- if len(tree) < 1 {
- return f
- }
- // you can only have (ns ...) as the first form
- if isNSDecl(tree[0]) {
- name, imports := getNamespace(tree[0].(*parser.CallNode))
- f.Name = name
- if imports != nil {
- decls = append(decls, imports)
- }
- tree = tree[1:]
- }
- decls = append(decls, generateDecls(tree)...)
- f.Decls = decls
- return f
- }
- func generateDecls(tree []parser.Node) []ast.Decl {
- decls := make([]ast.Decl, len(tree))
- for i, node := range tree {
- if node.Type() != parser.NodeCall {
- panic("expected call node in root scope!")
- }
- decls[i] = evalDeclNode(node.(*parser.CallNode))
- }
- return decls
- }
- func evalDeclNode(node *parser.CallNode) ast.Decl {
- // Let's just assume that all top-level functions called will be "def"
- if node.Callee.Type() != parser.NodeIdent {
- panic("expecting call to identifier (i.e. def, defconst, etc.)")
- }
- callee := node.Callee.(*parser.IdentNode)
- switch callee.Ident {
- case "def":
- return evalDef(node)
- }
- return nil
- }
- func evalDef(node *parser.CallNode) ast.Decl {
- if len(node.Args) < 2 {
- panic(fmt.Sprintf("expecting expression to be assigned to variable: %q", node.Args[0]))
- }
- val := EvalExpr(node.Args[1])
- fn, ok := val.(*ast.FuncLit)
- ident := makeIdomaticIdent(node.Args[0].(*parser.IdentNode).Ident)
- if ok {
- if ident.Name == "main" {
- mainable(fn)
- }
- return makeFunDeclFromFuncLit(ident, fn)
- } else {
- return makeGeneralDecl(token.VAR, []ast.Spec{makeValueSpec([]*ast.Ident{ident}, []ast.Expr{val}, nil)})
- }
- }
- func isNSDecl(node parser.Node) bool {
- if node.Type() != parser.NodeCall {
- return false
- }
- call := node.(*parser.CallNode)
- if call.Callee.(*parser.IdentNode).Ident != "ns" {
- return false
- }
- if len(call.Args) < 1 {
- return false
- }
- return true
- }
- func getNamespace(node *parser.CallNode) (*ast.Ident, ast.Decl) {
- return getPackageName(node), getImports(node)
- }
- func getPackageName(node *parser.CallNode) *ast.Ident {
- if node.Args[0].Type() != parser.NodeIdent {
- panic("ns package name is not an identifier!")
- }
- return ast.NewIdent(node.Args[0].(*parser.IdentNode).Ident)
- }
- func checkNSArgs(node *parser.CallNode) bool {
- if node.Callee.Type() != parser.NodeIdent {
- return false
- }
- if callee := node.Callee.(*parser.IdentNode); callee.Ident != "ns" {
- return false
- }
- return true
- }
|