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