114 lines
2 KiB
Go
114 lines
2 KiB
Go
package ucl
|
|
|
|
type evalCtx struct {
|
|
root *evalCtx
|
|
parent *evalCtx
|
|
commands map[string]invokable
|
|
macros map[string]macroable
|
|
vars map[string]Object
|
|
pseudoVars map[string]pseudoVar
|
|
}
|
|
|
|
func (ec *evalCtx) forkAndIsolate() *evalCtx {
|
|
newEc := &evalCtx{parent: ec}
|
|
newEc.root = newEc
|
|
return newEc
|
|
}
|
|
|
|
func (ec *evalCtx) fork() *evalCtx {
|
|
return &evalCtx{parent: ec, root: ec.root}
|
|
}
|
|
|
|
func (ec *evalCtx) addCmd(name string, inv invokable) {
|
|
if ec.root.commands == nil {
|
|
ec.root.commands = make(map[string]invokable)
|
|
}
|
|
|
|
ec.root.commands[name] = inv
|
|
}
|
|
|
|
func (ec *evalCtx) addMacro(name string, inv macroable) {
|
|
if ec.root.macros == nil {
|
|
ec.root.macros = make(map[string]macroable)
|
|
}
|
|
|
|
ec.root.macros[name] = inv
|
|
}
|
|
|
|
func (ec *evalCtx) setVar(name string, val Object) bool {
|
|
if ec == nil || ec.vars == nil {
|
|
return false
|
|
}
|
|
|
|
if _, ok := ec.vars[name]; ok {
|
|
ec.vars[name] = val
|
|
return true
|
|
}
|
|
|
|
return ec.parent.setVar(name, val)
|
|
}
|
|
|
|
func (ec *evalCtx) setOrDefineVar(name string, val Object) {
|
|
if ec.setVar(name, val) {
|
|
return
|
|
}
|
|
|
|
if ec.vars == nil {
|
|
ec.vars = make(map[string]Object)
|
|
}
|
|
ec.vars[name] = val
|
|
}
|
|
|
|
func (ec *evalCtx) getVar(name string) (Object, bool) {
|
|
if ec.vars == nil {
|
|
if ec.parent == nil {
|
|
return nil, false
|
|
}
|
|
return ec.parent.getVar(name)
|
|
}
|
|
|
|
if v, ok := ec.vars[name]; ok {
|
|
return v, true
|
|
} else if ec.parent != nil {
|
|
return ec.parent.getVar(name)
|
|
}
|
|
|
|
return nil, false
|
|
}
|
|
|
|
func (ec *evalCtx) getPseudoVar(name string) (pseudoVar, bool) {
|
|
if ec.root.pseudoVars == nil {
|
|
return nil, false
|
|
}
|
|
pvar, ok := ec.root.pseudoVars[name]
|
|
return pvar, ok
|
|
}
|
|
|
|
func (ec *evalCtx) lookupInvokable(name string) invokable {
|
|
if ec == nil {
|
|
return nil
|
|
}
|
|
|
|
for e := ec; e != nil; e = e.parent {
|
|
if cmd, ok := e.commands[name]; ok {
|
|
return cmd
|
|
}
|
|
}
|
|
|
|
return ec.parent.lookupInvokable(name)
|
|
}
|
|
|
|
func (ec *evalCtx) lookupMacro(name string) macroable {
|
|
if ec == nil {
|
|
return nil
|
|
}
|
|
|
|
for e := ec; e != nil; e = e.parent {
|
|
if cmd, ok := e.macros[name]; ok {
|
|
return cmd
|
|
}
|
|
}
|
|
|
|
return ec.parent.lookupMacro(name)
|
|
}
|