make Ctx operations immutable
This commit is contained in:
parent
ae11b55653
commit
2433e4a175
@ -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
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
60
expr/ctx.go
60
expr/ctx.go
@ -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
|
||||||
|
}
|
||||||
|
3
main.go
3
main.go
@ -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"),
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user