Beispiel #1
0
// 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
}
Beispiel #2
0
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))
	}
}
Beispiel #3
0
func SyntaxTree(root ast.Node, indentSize int) string {
	v := prettyprinter{indentSize: indentSize}
	root.Accept(&v, nil)
	return v.buf.String()
}