// Compile receives the root node of the AST and generates code // for the "main" function from it. // Any type of Node is accepted, either a block representing the program // or a single expression. // func Compile(root ast.Node, filename string) (res *FuncProto, err error) { defer func() { if r := recover(); r != nil { if cerr, ok := r.(*CompileError); ok { err = cerr } else { panic(r) } } }() var c compiler c.filename = filename c.mainFunc = newFuncProto(filename) c.block = newCompilerBlock(c.mainFunc, kBlockContextFunc, nil) root.Accept(&c, nil) c.functionReturnGuard() res = c.mainFunc return }
func (c *compiler) branchConditionHelper(cond, then, else_ ast.Node, reg int) { ternaryData := exprdata{true, reg + 1, reg + 1} cond.Accept(c, &ternaryData) condr := ternaryData.regb jmpInstr := c.emitAsBx(OpJmpfalse, condr, 0, c.lastLine) thenLabel := c.newLabel() ternaryData = exprdata{false, reg, reg} then.Accept(c, &ternaryData) c.modifyAsBx(jmpInstr, OpJmpfalse, condr, c.labelOffset(thenLabel)) if else_ != nil { successInstr := c.emitAsBx(OpJmp, 0, 0, c.lastLine) elseLabel := c.newLabel() ternaryData = exprdata{false, reg, reg} else_.Accept(c, &ternaryData) c.modifyAsBx(successInstr, OpJmp, 0, c.labelOffset(elseLabel)) } }
func SyntaxTree(root ast.Node, indentSize int) string { v := prettyprinter{indentSize: indentSize} root.Accept(&v, nil) return v.buf.String() }