fix how Identifiers are evaluated

This commit is contained in:
Brian Picciano 2016-08-06 18:10:31 -06:00
parent fcdbd3139c
commit 4fc4d48412
2 changed files with 21 additions and 6 deletions

View File

@ -29,11 +29,21 @@ func (bctx BuildCtx) BuildStmt(s Statement) Expr {
panicf("unknown macro: %q", m) panicf("unknown macro: %q", m)
} }
return fn(bctx, bctx.buildExpr(s.Arg)) return fn(bctx, s.Arg)
} }
// may return nil if e is a Statement which has no return // may return nil if e is a Statement which has no return
func (bctx BuildCtx) buildExpr(e Expr) Expr { func (bctx BuildCtx) buildExpr(e Expr) Expr {
return bctx.buildExprTill(e, func(Expr) bool { return false })
}
// like buildExpr, but will stop short and stop recursing when the function
// returns true
func (bctx BuildCtx) buildExprTill(e Expr, fn func(e Expr) bool) Expr {
if fn(e) {
return e
}
switch ea := e.(type) { switch ea := e.(type) {
case llvmVal: case llvmVal:
return e return e
@ -43,12 +53,12 @@ func (bctx BuildCtx) buildExpr(e Expr) Expr {
if v, ok := bctx.C.GetIdentifier(ea); ok { if v, ok := bctx.C.GetIdentifier(ea); ok {
return llvmVal(v) return llvmVal(v)
} }
return ea panicf("identifier %q not found", ea)
case Statement: case Statement:
return bctx.BuildStmt(ea) return bctx.BuildStmt(ea)
case Tuple: case Tuple:
for i := range ea { for i := range ea {
ea[i] = bctx.buildExpr(ea[i]) ea[i] = bctx.buildExprTill(ea[i], fn)
} }
return ea return ea
default: default:
@ -66,15 +76,15 @@ func (bctx BuildCtx) buildVal(e Expr) llvm.Value {
var globalCtx = &Ctx{ var globalCtx = &Ctx{
macros: map[Macro]MacroFn{ macros: map[Macro]MacroFn{
"add": func(bctx BuildCtx, e Expr) Expr { "add": func(bctx BuildCtx, e Expr) Expr {
tup := e.(Tuple) tup := bctx.buildExpr(e).(Tuple)
a := bctx.buildVal(tup[0]) a := bctx.buildVal(tup[0])
b := bctx.buildVal(tup[1]) b := bctx.buildVal(tup[1])
return llvmVal(bctx.B.CreateAdd(a, b, "")) return llvmVal(bctx.B.CreateAdd(a, b, ""))
}, },
"bind": func(bctx BuildCtx, e Expr) Expr { "bind": func(bctx BuildCtx, e Expr) Expr {
tup := e.(Tuple) tup := bctx.buildExprTill(e, isIdentifier).(Tuple)
id := bctx.buildExpr(tup[0]).(Identifier) id := bctx.buildExprTill(tup[0], isIdentifier).(Identifier)
bctx.C.idents[id] = bctx.buildVal(tup[1]) bctx.C.idents[id] = bctx.buildVal(tup[1])
return nil return nil
}, },

View File

@ -95,6 +95,11 @@ func (id Identifier) equal(e equaler) bool {
return ok && idid == id return ok && idid == id
} }
func isIdentifier(e Expr) bool {
_, ok := e.(Identifier)
return ok
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Macro is an identifier for a macro which can be used to transform // Macro is an identifier for a macro which can be used to transform