// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com). // All rights reserved. // operand-func.go package expr import ( "errors" ) // -------- function call term func newFuncCallTerm(tk *Token, args []*term) *term { return &term{ tk: *tk, parent: nil, children: args, position: posLeaf, priority: priValue, evalFunc: evalFuncCall, } } // -------- eval func call func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) { ctx := parentCtx.Clone() name, _ := self.tk.Value.(string) params := make([]any, len(self.children)) for i, tree := range self.children { var param any if param, err = tree.compute(ctx); err != nil { break } params[i] = param } if err == nil { if v, err = ctx.Call(name, params); err == nil { exportAll := isEnabled(ctx, control_export_all) // Export variables for _, refName := range ctx.EnumVars(func(name string) bool { return exportAll || name[0] == '@' }) { refValue, _ := ctx.GetVar(refName) exportVar(parentCtx, refName, refValue) } // Export functions for _, refName := range ctx.EnumFuncs(func(name string) bool { return exportAll || name[0] == '@' }) { if info, _ := ctx.GetFuncInfo(refName); info != nil { exportFunc(parentCtx, refName, info) } } } } return } func exportVar(ctx ExprContext, name string, value any) { if name[0] == '@' { name = name[1:] } ctx.setVar(name, value) } func exportFunc(ctx ExprContext, name string, info ExprFunc) { if name[0] == '@' { name = name[1:] } ctx.RegisterFunc(name, info.Functor(), info.MinArgs(), info.MaxArgs()) } // -------- function definition term func newFuncDefTerm(tk *Token, args []*term) *term { return &term{ tk: *tk, parent: nil, children: args, // arg[0]=formal-param-list, arg[1]=*ast position: posLeaf, priority: priValue, evalFunc: evalFuncDef, } } // -------- eval func def // TODO type funcDefFunctor struct { params []string expr Expr } func (functor *funcDefFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) { for i, p := range functor.params { if i < len(args) { arg := args[i] if functor, ok := arg.(Functor); ok { ctx.RegisterFunc(p, functor, 0, -1) } else { ctx.setVar(p, arg) } } else { ctx.setVar(p, nil) } } result, err = functor.expr.eval(ctx, false) return } func evalFuncDef(ctx ExprContext, self *term) (v any, err error) { bodySpec := self.value() if expr, ok := bodySpec.(*ast); ok { paramList := make([]string, 0, len(self.children)) for _, param := range self.children { paramList = append(paramList, param.source()) // if paramName, ok := param.value().(string); ok { // paramList = append(paramList, paramName) // } else { // err = fmt.Errorf("invalid function definition: formal param nr %d must be an identifier", i+1) // break // } } v = &funcDefFunctor{ params: paramList, expr: expr, } } else { err = errors.New("invalid function definition: the body specification must be an expression") } return }