make Ctx operations immutable

This commit is contained in:
Brian Picciano 2016-08-07 09:06:46 -06:00
parent ae11b55653
commit 2433e4a175
3 changed files with 42 additions and 39 deletions

View File

@ -23,13 +23,7 @@ func (bctx BuildCtx) Build(stmts ...Statement) llvm.Value {
func (bctx BuildCtx) BuildStmt(s Statement) Expr { func (bctx BuildCtx) BuildStmt(s Statement) Expr {
m := s.Op.(Macro) m := s.Op.(Macro)
return bctx.C.Macro(m)(bctx, s.Arg)
fn := bctx.C.GetMacro(m)
if fn == nil {
panicf("unknown macro: %q", m)
}
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
@ -50,10 +44,7 @@ func (bctx BuildCtx) buildExprTill(e Expr, fn func(e Expr) bool) Expr {
case Int: case Int:
return llvmVal(llvm.ConstInt(llvm.Int64Type(), uint64(ea), false)) return llvmVal(llvm.ConstInt(llvm.Int64Type(), uint64(ea), false))
case Identifier: case Identifier:
if ev := bctx.C.GetIdentifier(ea); ev != nil { return bctx.C.Identifier(ea)
return ev
}
panicf("identifier %q not found", ea)
case Statement: case Statement:
return bctx.BuildStmt(ea) return bctx.BuildStmt(ea)
case Tuple: case Tuple:
@ -85,10 +76,7 @@ var globalCtx = &Ctx{
"bind": func(bctx BuildCtx, e Expr) Expr { "bind": func(bctx BuildCtx, e Expr) Expr {
tup := bctx.buildExprTill(e, isIdentifier).(Tuple) tup := bctx.buildExprTill(e, isIdentifier).(Tuple)
id := bctx.buildExprTill(tup[0], isIdentifier).(Identifier) id := bctx.buildExprTill(tup[0], isIdentifier).(Identifier)
if bctx.C.idents[id] != nil { *bctx.C = bctx.C.Bind(id, bctx.buildExpr(tup[1]))
panicf("identifier %q is already bound", id)
}
bctx.C.idents[id] = bctx.buildExpr(tup[1])
return nil return nil
}, },
}, },

View File

@ -14,17 +14,17 @@ type Ctx struct {
} }
// NewCtx returns a blank context instance // NewCtx returns a blank context instance
func NewCtx() *Ctx { func NewCtx() Ctx {
return &Ctx{ return Ctx{
global: globalCtx, global: globalCtx,
macros: map[Macro]MacroFn{}, macros: map[Macro]MacroFn{},
idents: map[Identifier]Expr{}, idents: map[Identifier]Expr{},
} }
} }
// GetMacro returns the MacroFn associated with the given identifier, or panics // Macro returns the MacroFn associated with the given identifier, or panics
// if the macro isn't found // if the macro isn't found
func (c *Ctx) GetMacro(m Macro) MacroFn { func (c Ctx) Macro(m Macro) MacroFn {
if fn := c.macros[m]; fn != nil { if fn := c.macros[m]; fn != nil {
return fn return fn
} }
@ -35,25 +35,39 @@ func (c *Ctx) GetMacro(m Macro) MacroFn {
return nil return nil
} }
// GetIdentifier returns the llvm.Value for the Identifier, or panics // Identifier returns the llvm.Value for the Identifier, or panics
func (c *Ctx) GetIdentifier(i Identifier) Expr { func (c Ctx) Identifier(i Identifier) Expr {
if e := c.idents[i]; e != nil {
return e
}
// The global context doesn't have any identifiers, so don't bother checking // The global context doesn't have any identifiers, so don't bother checking
return c.idents[i] panicf("identifier %q not found", i)
panic("go is dumb")
} }
// NewWith returns a new Ctx instance which imports the given macros from the func (c Ctx) cp() Ctx {
// parent cc := Ctx{
//func (c *Ctx) NewWith(mm ...Macro) *Ctx { global: c.global,
// nc := &Ctx{ macros: make(map[Macro]MacroFn, len(c.macros)),
// global: c.global, idents: make(map[Identifier]Expr, len(c.idents)),
// macros: map[Macro]MacroFn{}, }
// } for m, mfn := range c.macros {
// for _, m := range mm { cc.macros[m] = mfn
// fn := c.macros[m] }
// if fn == nil { for i, e := range c.idents {
// panicf("no macro %q found in context", m) cc.idents[i] = e
// } }
// nc.macros[m] = fn return cc
// } }
// return nc
//} // Bind returns a new Ctx which is a copy of this one, but with the given
// Identifier bound to the given Expr. Will panic if the Identifier is already
// bound
func (c Ctx) Bind(i Identifier, e Expr) Ctx {
if _, ok := c.idents[i]; ok {
panicf("identifier %q is already bound", i)
}
c = c.cp()
c.idents[i] = e
return c
}

View File

@ -22,8 +22,9 @@ func main() {
llvm.InitializeNativeAsmPrinter() llvm.InitializeNativeAsmPrinter()
// setup our context, builder, and module // setup our context, builder, and module
ctx := expr.NewCtx()
bctx := expr.BuildCtx{ bctx := expr.BuildCtx{
C: expr.NewCtx(), C: &ctx,
B: llvm.NewBuilder(), B: llvm.NewBuilder(),
M: llvm.NewModule("my_module"), M: llvm.NewModule("my_module"),
} }