2016-07-29 00:39:18 +00:00
|
|
|
package expr
|
|
|
|
|
2016-08-06 18:20:53 +00:00
|
|
|
// MacroFn is a compiler function which takes in an existing Expr and returns
|
|
|
|
// the llvm Value for it
|
2016-08-09 01:43:05 +00:00
|
|
|
type MacroFn func(BuildCtx, Ctx, Expr) Expr
|
2016-08-05 18:34:17 +00:00
|
|
|
|
2016-08-06 18:20:53 +00:00
|
|
|
// 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 {
|
2016-08-06 18:20:53 +00:00
|
|
|
global *Ctx
|
|
|
|
macros map[Macro]MacroFn
|
2016-08-07 00:40:55 +00:00
|
|
|
idents map[Identifier]Expr
|
2016-08-06 18:20:53 +00:00
|
|
|
}
|
2016-08-05 18:34:17 +00:00
|
|
|
|
2016-08-06 18:20:53 +00:00
|
|
|
// NewCtx returns a blank context instance
|
2016-08-07 15:06:46 +00:00
|
|
|
func NewCtx() Ctx {
|
|
|
|
return Ctx{
|
2016-08-06 18:20:53 +00:00
|
|
|
global: globalCtx,
|
|
|
|
macros: map[Macro]MacroFn{},
|
2016-08-07 00:40:55 +00:00
|
|
|
idents: map[Identifier]Expr{},
|
2016-08-06 18:20:53 +00:00
|
|
|
}
|
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
|
2016-08-06 18:20:53 +00:00
|
|
|
// if the macro isn't found
|
2016-08-07 15:06:46 +00:00
|
|
|
func (c Ctx) Macro(m Macro) MacroFn {
|
2016-08-06 18:20:53 +00:00
|
|
|
if fn := c.macros[m]; fn != nil {
|
|
|
|
return fn
|
2016-07-29 00:39:18 +00:00
|
|
|
}
|
2016-08-06 18:20:53 +00:00
|
|
|
if fn := c.global.macros[m]; fn != nil {
|
|
|
|
return fn
|
2016-07-29 00:39:18 +00:00
|
|
|
}
|
2016-08-06 18:20:53 +00:00
|
|
|
panicf("macro %q not found in context", m)
|
2016-07-29 00:39:18 +00:00
|
|
|
return nil
|
|
|
|
}
|
2016-08-06 18:20:53 +00:00
|
|
|
|
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
|
|
|
|
}
|
2016-08-06 18:20:53 +00:00
|
|
|
// 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")
|
|
|
|
}
|
|
|
|
|
2016-08-09 01:43:05 +00:00
|
|
|
// 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-06 18:20:53 +00:00
|
|
|
}
|
|
|
|
|
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
|
2016-08-09 01:43:05 +00:00
|
|
|
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
|
|
|
|
}
|