M pkg/codegen/codegen.go => pkg/codegen/codegen.go +5 -4
@@ 81,12 81,13 @@ func ExecUnit(outDir string, unit *semantic.Unit) ([]string, error) {
}
semantic.Walk(t, unit)
- // TODO: temp, just to avoid errors, will require 4.
- gofiles := make([]*goast.File, len(unit.Files))
-
- // TODO: 4
// 4. build the Go AST tree from the Snow-associated nodes so that relative
// position of nodes respects the snow source
+ tb := &treebuilder{
+ nodeToGoAST: t.nodeToGoAST,
+ }
+ semantic.Walk(tb, unit)
+ gofiles := tb.gofiles
// 5. walk the Go AST and assign valid positions to nodes
fset := token.NewFileSet()
A pkg/codegen/treebuild.go => pkg/codegen/treebuild.go +64 -0
@@ 0,0 1,64 @@
+package codegen
+
+import (
+ goast "go/ast"
+
+ "git.sr.ht/~mna/snow/pkg/semantic"
+)
+
+// The treebuilder builds the Go AST from the nodes associated with the
+// abstract semantic graph in the translator phase.
+type treebuilder struct {
+ curGoFile *goast.File
+ gofiles []*goast.File
+ nodeToGoAST map[semantic.Node][]goast.Node
+}
+
+func (tb *treebuilder) Visit(n semantic.Node) semantic.Visitor {
+ switch n := n.(type) {
+ case *semantic.Unit:
+ for _, f := range n.Files {
+ semantic.Walk(tb, f)
+ tb.gofiles = append(tb.gofiles, tb.curGoFile)
+ }
+
+ case *semantic.File:
+ // file node should have its goast.File as first node, rest should be added
+ // to the file's declarations.
+ ns := tb.nodeToGoAST[n]
+ tb.curGoFile = ns[0].(*goast.File)
+ for i := 1; i < len(ns); i++ {
+ tb.curGoFile.Decls = append(tb.curGoFile.Decls, ns[i].(goast.Decl))
+ }
+
+ decls := make([]semantic.Decl, 0, len(n.Vars)+len(n.Structs)+len(n.Fns))
+ for _, v := range n.Vars {
+ semantic.Walk(tb, v)
+ decls = append(decls, v)
+ }
+ for _, str := range n.Structs {
+ semantic.Walk(tb, str)
+ decls = append(decls, str)
+ }
+ for _, fn := range n.Fns {
+ semantic.Walk(tb, fn)
+ decls = append(decls, fn)
+ }
+ for _, decl := range decls {
+ for _, gons := range tb.nodeToGoAST[decl] {
+ tb.curGoFile.Decls = append(tb.curGoFile.Decls, gons.(goast.Decl))
+ }
+ }
+
+ case *semantic.Fn:
+ case *semantic.Struct:
+ case *semantic.Var:
+ case *semantic.Block:
+ case *semantic.Return:
+ case *semantic.Assign:
+ case *semantic.ExprStmt:
+ case *semantic.If:
+ case *semantic.Guard:
+ }
+ return nil
+}