diff --git a/expr/build.go b/expr/build.go index 0df1159..0ed5de5 100644 --- a/expr/build.go +++ b/expr/build.go @@ -40,7 +40,10 @@ func (bctx BuildCtx) buildExpr(e Expr) Expr { case Int: return llvmVal(llvm.ConstInt(llvm.Int64Type(), uint64(ea), false)) case Identifier: - return bctx.buildExpr(bctx.C.GetIdentifier(ea)) + if v, ok := bctx.C.GetIdentifier(ea); ok { + return llvmVal(v) + } + return ea case Statement: return bctx.BuildStmt(ea) case Tuple: diff --git a/expr/ctx.go b/expr/ctx.go index 1538586..da3b979 100644 --- a/expr/ctx.go +++ b/expr/ctx.go @@ -38,13 +38,12 @@ func (c *Ctx) GetMacro(m Macro) MacroFn { } // GetIdentifier returns the llvm.Value for the Identifier, or panics -func (c *Ctx) GetIdentifier(i Identifier) llvm.Value { +func (c *Ctx) GetIdentifier(i Identifier) (llvm.Value, bool) { if v, ok := c.idents[i]; ok { - return v + return v, true } // The global context doesn't have any identifiers, so don't bother checking - panicf("identifier %q not found in context", i) - return llvm.Value{} + return llvm.Value{}, false } // NewWith returns a new Ctx instance which imports the given macros from the diff --git a/expr/expr.go b/expr/expr.go index 32866d0..f820ffb 100644 --- a/expr/expr.go +++ b/expr/expr.go @@ -141,6 +141,19 @@ type Statement struct { Op, Arg Expr } +// NewStatement returns a Statement whose Op is the first Expr. If the given +// list is empty Arg will be nil, if its length is one Arg will be that single +// Expr, otherwise Arg will be a Tuple of the list +func NewStatement(e Expr, ee ...Expr) Statement { + s := Statement{Op: e} + if len(ee) > 1 { + s.Arg = NewTuple(ee...) + } else if len(ee) == 1 { + s.Arg = ee[0] + } + return s +} + func (s Statement) String() string { return fmt.Sprintf("(%v %s)", s.Op, s.Arg) } diff --git a/main.go b/main.go index 8054686..e2052d8 100644 --- a/main.go +++ b/main.go @@ -29,10 +29,17 @@ func main() { } // do the work in the function - tup := expr.NewTuple(expr.Int(1), expr.Int(2)) - addMacro := expr.Macro("add") - stmt := expr.Statement{Op: addMacro, Arg: tup} - stmt = expr.Statement{Op: addMacro, Arg: expr.NewTuple(stmt, expr.Int(3))} + add := expr.Macro("add") + bind := expr.Macro("bind") + idA := expr.Identifier("A") + idB := expr.Identifier("B") + idC := expr.Identifier("C") + stmts := []expr.Statement{ + expr.NewStatement(bind, idA, expr.NewStatement(add, expr.Int(1), expr.Int(2))), + expr.NewStatement(bind, idB, expr.Int(3)), + expr.NewStatement(bind, idC, expr.NewStatement(add, idA, idB)), + expr.NewStatement(add, idC, idC), + } //block := expr.Block([]expr.Expr{stmt}) //fn := block.LLVMVal(expr.RootCtx, lctx) @@ -41,7 +48,7 @@ func main() { mainFn := llvm.AddFunction(bctx.M, "main", llvm.FunctionType(llvm.Int64Type(), []llvm.Type{}, false)) mainBlock := llvm.AddBasicBlock(mainFn, "entry") bctx.B.SetInsertPoint(mainBlock, mainBlock.FirstInstruction()) - v := bctx.Build(stmt) + v := bctx.Build(stmts...) bctx.B.CreateRet(v) //ret := lctx.B.CreateCall(fn, []llvm.Value{}, "")