Expr functions now act as closures
This commit is contained in:
parent
d84e690ef3
commit
f41ea96d17
@ -34,6 +34,7 @@ type ExprFunc interface {
|
||||
// ----Expression Context
|
||||
type ExprContext interface {
|
||||
Clone() ExprContext
|
||||
Merge(ctx ExprContext)
|
||||
GetVar(varName string) (value any, exists bool)
|
||||
SetVar(varName string, value any)
|
||||
UnsafeSetVar(varName string, value any)
|
||||
|
13
function.go
13
function.go
@ -34,7 +34,7 @@ func (functor *baseFunctor) GetFunc() ExprFunc {
|
||||
return functor.info
|
||||
}
|
||||
|
||||
// ---- Linking with the functions of Go
|
||||
// ---- Linking with Go functions
|
||||
type golangFunctor struct {
|
||||
baseFunctor
|
||||
f FuncTemplate
|
||||
@ -48,18 +48,23 @@ func (functor *golangFunctor) Invoke(ctx ExprContext, name string, args []any) (
|
||||
return functor.f(ctx, name, args)
|
||||
}
|
||||
|
||||
// ---- Linking with the functions of Expr
|
||||
// ---- Linking with Expr functions
|
||||
type exprFunctor struct {
|
||||
baseFunctor
|
||||
params []string
|
||||
expr Expr
|
||||
defCtx ExprContext
|
||||
}
|
||||
|
||||
func newExprFunctor(e Expr, params []string) *exprFunctor {
|
||||
return &exprFunctor{expr: e, params: params}
|
||||
func newExprFunctor(e Expr, params []string, ctx ExprContext) *exprFunctor {
|
||||
return &exprFunctor{expr: e, params: params, defCtx: ctx}
|
||||
}
|
||||
|
||||
func (functor *exprFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) {
|
||||
if functor.defCtx != nil {
|
||||
ctx.Merge(functor.defCtx)
|
||||
}
|
||||
|
||||
for i, p := range functor.params {
|
||||
if i < len(args) {
|
||||
arg := args[i]
|
||||
|
@ -108,11 +108,7 @@ func evalFuncDef(ctx ExprContext, self *term) (v any, err error) {
|
||||
for _, param := range self.children {
|
||||
paramList = append(paramList, param.source())
|
||||
}
|
||||
v = newExprFunctor(expr, paramList)
|
||||
// v = &funcDefFunctor{
|
||||
// params: paramList,
|
||||
// expr: expr,
|
||||
// }
|
||||
v = newExprFunctor(expr, paramList, ctx)
|
||||
} else {
|
||||
err = errors.New("invalid function definition: the body specification must be an expression")
|
||||
}
|
||||
|
@ -12,29 +12,40 @@ import (
|
||||
|
||||
type SimpleStore struct {
|
||||
varStore map[string]any
|
||||
funcStore map[string]*funcInfo
|
||||
funcStore map[string]ExprFunc
|
||||
}
|
||||
|
||||
func NewSimpleStore() *SimpleStore {
|
||||
ctx := &SimpleStore{
|
||||
varStore: make(map[string]any),
|
||||
funcStore: make(map[string]*funcInfo),
|
||||
funcStore: make(map[string]ExprFunc),
|
||||
}
|
||||
//ImportBuiltinsFuncs(ctx)
|
||||
return ctx
|
||||
}
|
||||
|
||||
func filterRefName(name string) bool { return name[0] != '@' }
|
||||
func filterPrivName(name string) bool { return name[0] != '_' }
|
||||
|
||||
func (ctx *SimpleStore) Clone() ExprContext {
|
||||
return &SimpleStore{
|
||||
varStore: CloneFilteredMap(ctx.varStore, func(name string) bool { return name[0] != '@' }),
|
||||
funcStore: CloneFilteredMap(ctx.funcStore, func(name string) bool { return name[0] != '@' }),
|
||||
varStore: CloneFilteredMap(ctx.varStore, filterRefName),
|
||||
funcStore: CloneFilteredMap(ctx.funcStore, filterRefName),
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *SimpleStore) Merge(src ExprContext) {
|
||||
for _, name := range src.EnumVars(filterRefName) {
|
||||
ctx.varStore[name], _ = src.GetVar(name)
|
||||
}
|
||||
for _, name := range src.EnumFuncs(filterRefName) {
|
||||
ctx.funcStore[name], _ = src.GetFuncInfo(name)
|
||||
}
|
||||
}
|
||||
|
||||
func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) {
|
||||
sb.WriteString("vars: {\n")
|
||||
first := true
|
||||
for _, name := range ctx.EnumVars(func(name string) bool { return name[0] != '_' }) {
|
||||
for _, name := range ctx.EnumVars(filterPrivName) {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
@ -164,7 +175,7 @@ func (ctx *SimpleStore) EnumFuncs(acceptor func(name string) (accept bool)) (fun
|
||||
|
||||
func (ctx *SimpleStore) Call(name string, args []any) (result any, err error) {
|
||||
if info, exists := ctx.funcStore[name]; exists {
|
||||
functor := info.functor
|
||||
functor := info.Functor()
|
||||
result, err = functor.Invoke(ctx, name, args)
|
||||
} else {
|
||||
err = fmt.Errorf("unknown function %s()", name)
|
||||
|
Loading…
Reference in New Issue
Block a user