~mna/snow

ae3f184c649091c5d5f826f91f62e1c71fcd7807 — Martin Angers 1 year, 8 months ago 89925d5
pkg/codegen: not sure that approach works...
1 files changed, 63 insertions(+), 4 deletions(-)

M pkg/codegen/treebuild.go
M pkg/codegen/treebuild.go => pkg/codegen/treebuild.go +63 -4
@@ 1,6 1,7 @@
package codegen

import (
	"fmt"
	goast "go/ast"

	"git.sr.ht/~mna/snow/pkg/semantic"


@@ 12,6 13,9 @@ type treebuilder struct {
	curGoFile   *goast.File
	gofiles     []*goast.File
	nodeToGoAST map[semantic.Node][]goast.Node

	// single statement generated by visiting e.g. a Block, If or Guard.
	stmt goast.Stmt
}

func (tb *treebuilder) Visit(n semantic.Node) semantic.Visitor {


@@ 51,14 55,69 @@ func (tb *treebuilder) Visit(n semantic.Node) semantic.Visitor {
		}

	case *semantic.Fn:

	case *semantic.Struct:
	case *semantic.Var:

	case *semantic.Block:
	case *semantic.Return:
	case *semantic.Assign:
	case *semantic.ExprStmt:
		// block may have multiple associated statements (e.g. in a generic fn)
		ns := tb.nodeToGoAST[n]
		if len(ns) != 1 {
			panic(fmt.Sprintf("block statement should have 1 associated Go node, got %d", len(ns)))
		}
		block := ns[0].(*goast.BlockStmt)

		for _, stmt := range n.Stmts {
			semantic.Walk(tb, stmt)
			gons := tb.nodeToGoAST[stmt]
			for _, gon := range gons {
				if _, ok := gon.(topLevelNode); ok {
					tb.curGoFile.Decls = append(tb.curGoFile.Decls, gon.(goast.Decl))
				} else {
					block.List = append(block.List, gon.(goast.Stmt))
				}
			}
		}
		tb.stmt = block

	case *semantic.If:
		// if should have a single associated statement
		ns := tb.nodeToGoAST[n]
		if len(ns) != 1 {
			panic(fmt.Sprintf("if statement should have 1 associated Go node, got %d", len(ns)))
		}
		ifs := ns[0].(*goast.IfStmt)

		semantic.Walk(tb, n.Body)
		ifs.Body = tb.stmt.(*goast.BlockStmt)
		if n.Else != nil {
			semantic.Walk(tb, n.Else)
			ifs.Else = tb.stmt
		}
		tb.stmt = ifs

	case *semantic.Guard:
		// guard should have a single associated statement
		ns := tb.nodeToGoAST[n]
		if len(ns) != 1 {
			panic(fmt.Sprintf("guard statement should have 1 associated Go node, got %d", len(ns)))
		}
		ifs := ns[0].(*goast.IfStmt)
		semantic.Walk(tb, n.Else)
		ifs.Else = tb.stmt
		tb.stmt = ifs

	case *semantic.Var, *semantic.Return, *semantic.Assign, *semantic.ExprStmt:
		ns := tb.nodeToGoAST[n]
		if len(ns) != 1 {
			panic(fmt.Sprintf("statement should have 1 associated Go node, got %d", len(ns)))
		}
		var stmt goast.Stmt
		if gd, ok := ns[0].(*goast.GenDecl); ok {
			stmt = &goast.DeclStmt{Decl: gd}
		} else {
			stmt = ns[0].(goast.Stmt)
		}
		tb.stmt = stmt
	}
	return nil
}