ginger/expr/ctx.go

73 lines
1.8 KiB
Go
Raw Permalink Normal View History

2016-07-29 00:39:18 +00:00
package expr
// MacroFn is a compiler function which takes in an existing Expr and returns
// the llvm Value for it
type MacroFn func(BuildCtx, Ctx, Expr) Expr
// Ctx contains all the Macros and Identifiers available. A Ctx also keeps a
// reference to the global context, which has a number of macros available for
// all contexts to use.
2016-07-29 00:39:18 +00:00
type Ctx struct {
global *Ctx
macros map[Macro]MacroFn
idents map[Identifier]Expr
}
// NewCtx returns a blank context instance
2016-08-07 15:06:46 +00:00
func NewCtx() Ctx {
return Ctx{
global: globalCtx,
macros: map[Macro]MacroFn{},
idents: map[Identifier]Expr{},
}
2016-07-29 00:39:18 +00:00
}
2016-08-07 15:06:46 +00:00
// Macro returns the MacroFn associated with the given identifier, or panics
// if the macro isn't found
2016-08-07 15:06:46 +00:00
func (c Ctx) Macro(m Macro) MacroFn {
if fn := c.macros[m]; fn != nil {
return fn
2016-07-29 00:39:18 +00:00
}
if fn := c.global.macros[m]; fn != nil {
return fn
2016-07-29 00:39:18 +00:00
}
panicf("macro %q not found in context", m)
2016-07-29 00:39:18 +00:00
return nil
}
2016-08-07 15:06:46 +00:00
// Identifier returns the llvm.Value for the Identifier, or panics
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
2016-08-07 15:06:46 +00:00
panicf("identifier %q not found", i)
panic("go is dumb")
}
// Copy returns a deep copy of the Ctx
func (c Ctx) Copy() Ctx {
2016-08-07 15:06:46 +00:00
cc := Ctx{
global: c.global,
macros: make(map[Macro]MacroFn, len(c.macros)),
idents: make(map[Identifier]Expr, len(c.idents)),
}
for m, mfn := range c.macros {
cc.macros[m] = mfn
}
for i, e := range c.idents {
cc.idents[i] = e
}
return cc
}
2016-08-07 15:06:46 +00:00
// 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) {
2016-08-07 15:06:46 +00:00
if _, ok := c.idents[i]; ok {
panicf("identifier %q is already bound", i)
}
c.idents[i] = e
}