function definition and usage rationalized
This commit is contained in:
parent
d545a35acf
commit
e5f63c3d9d
@ -7,7 +7,7 @@ package expr
|
|||||||
const (
|
const (
|
||||||
typeAny = "any"
|
typeAny = "any"
|
||||||
typeBoolean = "boolean"
|
typeBoolean = "boolean"
|
||||||
typeFloat = "decimal"
|
typeFloat = "float"
|
||||||
typeFraction = "fraction"
|
typeFraction = "fraction"
|
||||||
typeHandle = "handle"
|
typeHandle = "handle"
|
||||||
typeInt = "integer"
|
typeInt = "integer"
|
||||||
|
@ -24,7 +24,7 @@ func exportFunc(ctx ExprContext, name string, info ExprFunc) {
|
|||||||
}
|
}
|
||||||
// ctx.RegisterFunc(name, info.Functor(), info.MinArgs(), info.MaxArgs())
|
// ctx.RegisterFunc(name, info.Functor(), info.MinArgs(), info.MaxArgs())
|
||||||
// ctx.RegisterFuncInfo(name, info)
|
// ctx.RegisterFuncInfo(name, info)
|
||||||
ctx.RegisterFunc2(name, info.Functor(), info.ReturnType(), info.Params())
|
ctx.RegisterFunc(name, info.Functor(), info.ReturnType(), info.Params())
|
||||||
}
|
}
|
||||||
|
|
||||||
func exportObjects(destCtx, sourceCtx ExprContext) {
|
func exportObjects(destCtx, sourceCtx ExprContext) {
|
||||||
|
24
context.go
24
context.go
@ -4,28 +4,11 @@
|
|||||||
// context.go
|
// context.go
|
||||||
package expr
|
package expr
|
||||||
|
|
||||||
// ---- Function template
|
|
||||||
type FuncTemplate func(ctx ExprContext, name string, args []any) (result any, err error)
|
|
||||||
|
|
||||||
// ---- Functor interface
|
// ---- Functor interface
|
||||||
type Functor interface {
|
type Functor interface {
|
||||||
Invoke(ctx ExprContext, name string, args []any) (result any, err error)
|
Invoke(ctx ExprContext, name string, args []any) (result any, err error)
|
||||||
}
|
SetFunc(info ExprFunc)
|
||||||
|
GetFunc() ExprFunc
|
||||||
type simpleFunctor struct {
|
|
||||||
f FuncTemplate
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSimpleFunctor(f FuncTemplate) *simpleFunctor {
|
|
||||||
return &simpleFunctor{f: f}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (functor *simpleFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) {
|
|
||||||
return functor.f(ctx, name, args)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (functor *simpleFunctor) ToString(opt FmtOpt) string {
|
|
||||||
return "func() {<body>}"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- Function Param Info
|
// ---- Function Param Info
|
||||||
@ -39,6 +22,7 @@ type ExprFuncParam interface {
|
|||||||
|
|
||||||
// ---- Function Info
|
// ---- Function Info
|
||||||
type ExprFunc interface {
|
type ExprFunc interface {
|
||||||
|
Formatter
|
||||||
Name() string
|
Name() string
|
||||||
MinArgs() int
|
MinArgs() int
|
||||||
MaxArgs() int
|
MaxArgs() int
|
||||||
@ -59,5 +43,5 @@ type ExprContext interface {
|
|||||||
Call(name string, args []any) (result any, err error)
|
Call(name string, args []any) (result any, err error)
|
||||||
// RegisterFunc(name string, f Functor, minArgs, maxArgs int)
|
// RegisterFunc(name string, f Functor, minArgs, maxArgs int)
|
||||||
RegisterFuncInfo(info ExprFunc)
|
RegisterFuncInfo(info ExprFunc)
|
||||||
RegisterFunc2(name string, f Functor, returnType string, param []ExprFuncParam) error
|
RegisterFunc(name string, f Functor, returnType string, param []ExprFuncParam) error
|
||||||
}
|
}
|
||||||
|
60
func-base.go
60
func-base.go
@ -54,6 +54,24 @@ func isDictionaryFunc(ctx ExprContext, name string, args []any) (result any, err
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func boolFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
||||||
|
switch v := args[0].(type) {
|
||||||
|
case int64:
|
||||||
|
result = (v != 0)
|
||||||
|
case *fraction:
|
||||||
|
result = v.num != 0
|
||||||
|
case float64:
|
||||||
|
result = v != 0.0
|
||||||
|
case bool:
|
||||||
|
result = v
|
||||||
|
case string:
|
||||||
|
result = len(v) > 0
|
||||||
|
default:
|
||||||
|
err = errCantConvert(name, v, "bool")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func intFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
func intFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
||||||
switch v := args[0].(type) {
|
switch v := args[0].(type) {
|
||||||
case int64:
|
case int64:
|
||||||
@ -144,34 +162,20 @@ func ImportBuiltinsFuncs(ctx ExprContext) {
|
|||||||
newFuncParam(paramValue),
|
newFuncParam(paramValue),
|
||||||
}
|
}
|
||||||
|
|
||||||
// ctx.RegisterFunc("isNil", &simpleFunctor{f: isNilFunc}, 1, 1)
|
ctx.RegisterFunc("isNil", newGolangFunctor(isNilFunc), typeBoolean, anyParams)
|
||||||
ctx.RegisterFunc2("isNil", newSimpleFunctor(isNilFunc), typeBoolean, anyParams)
|
ctx.RegisterFunc("isInt", newGolangFunctor(isIntFunc), typeBoolean, anyParams)
|
||||||
// ctx.RegisterFunc("isInt", &simpleFunctor{f: isIntFunc}, 1, 1)
|
ctx.RegisterFunc("isFloat", newGolangFunctor(isFloatFunc), typeBoolean, anyParams)
|
||||||
ctx.RegisterFunc2("isInt", newSimpleFunctor(isIntFunc), typeBoolean, anyParams)
|
ctx.RegisterFunc("isBool", newGolangFunctor(isBoolFunc), typeBoolean, anyParams)
|
||||||
// ctx.RegisterFunc("isFloat", &simpleFunctor{f: isFloatFunc}, 1, 1)
|
ctx.RegisterFunc("isString", newGolangFunctor(isStringFunc), typeBoolean, anyParams)
|
||||||
ctx.RegisterFunc2("isFloat", newSimpleFunctor(isFloatFunc), typeBoolean, anyParams)
|
ctx.RegisterFunc("isFract", newGolangFunctor(isFractionFunc), typeBoolean, anyParams)
|
||||||
// ctx.RegisterFunc("isBool", &simpleFunctor{f: isBoolFunc}, 1, 1)
|
ctx.RegisterFunc("isRational", newGolangFunctor(isRationalFunc), typeBoolean, anyParams)
|
||||||
ctx.RegisterFunc2("isBool", newSimpleFunctor(isBoolFunc), typeBoolean, anyParams)
|
ctx.RegisterFunc("isList", newGolangFunctor(isListFunc), typeBoolean, anyParams)
|
||||||
// ctx.RegisterFunc("isString", &simpleFunctor{f: isStringFunc}, 1, 1)
|
ctx.RegisterFunc("isDict", newGolangFunctor(isDictionaryFunc), typeBoolean, anyParams)
|
||||||
ctx.RegisterFunc2("isString", newSimpleFunctor(isStringFunc), typeBoolean, anyParams)
|
|
||||||
// ctx.RegisterFunc("isFraction", &simpleFunctor{f: isFractionFunc}, 1, 1)
|
ctx.RegisterFunc("bool", newGolangFunctor(boolFunc), typeBoolean, anyParams)
|
||||||
//ctx.RegisterFunc2("isFraction", &simpleFunctor{f: isFractionFunc}, typeBoolean, anyParams)
|
ctx.RegisterFunc("int", newGolangFunctor(intFunc), typeInt, anyParams)
|
||||||
// ctx.RegisterFunc("isFract", &simpleFunctor{f: isFractionFunc}, 1, 1)
|
ctx.RegisterFunc("dec", newGolangFunctor(decFunc), typeFloat, anyParams)
|
||||||
ctx.RegisterFunc2("isFract", newSimpleFunctor(isFractionFunc), typeBoolean, anyParams)
|
ctx.RegisterFunc("fract", newGolangFunctor(fractFunc), typeFraction, []ExprFuncParam{
|
||||||
// ctx.RegisterFunc("isRational", &simpleFunctor{f: isRationalFunc}, 1, 1)
|
|
||||||
ctx.RegisterFunc2("isRational", newSimpleFunctor(isRationalFunc), typeBoolean, anyParams)
|
|
||||||
// ctx.RegisterFunc("isList", &simpleFunctor{f: isListFunc}, 1, 1)
|
|
||||||
ctx.RegisterFunc2("isList", newSimpleFunctor(isListFunc), typeBoolean, anyParams)
|
|
||||||
// ctx.RegisterFunc("isDictionary", &simpleFunctor{f: isDictionaryFunc}, 1, 1)
|
|
||||||
//ctx.RegisterFunc2("isDictionary", &simpleFunctor{f: isDictionaryFunc}, typeBoolean, anyParams)
|
|
||||||
// ctx.RegisterFunc("isDict", &simpleFunctor{f: isDictionaryFunc}, 1, 1)
|
|
||||||
ctx.RegisterFunc2("isDict", newSimpleFunctor(isDictionaryFunc), typeBoolean, anyParams)
|
|
||||||
//ctx.RegisterFunc("int", &simpleFunctor{f: intFunc}, 1, 1)
|
|
||||||
ctx.RegisterFunc2("int", newSimpleFunctor(intFunc), typeInt, anyParams)
|
|
||||||
// ctx.RegisterFunc("dec", &simpleFunctor{f: decFunc}, 1, 1)
|
|
||||||
ctx.RegisterFunc2("dec", newSimpleFunctor(decFunc), typeFloat, anyParams)
|
|
||||||
// ctx.RegisterFunc("fract", &simpleFunctor{f: fractFunc}, 1, 2)
|
|
||||||
ctx.RegisterFunc2("fract", newSimpleFunctor(fractFunc), typeFraction, []ExprFuncParam{
|
|
||||||
newFuncParam(paramValue),
|
newFuncParam(paramValue),
|
||||||
newFuncParamFlagDef("denominator", pfOptional, 1),
|
newFuncParamFlagDef("denominator", pfOptional, 1),
|
||||||
})
|
})
|
||||||
|
@ -137,12 +137,10 @@ func doImport(ctx ExprContext, name string, dirList []string, it Iterator) (resu
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ImportImportFuncs(ctx ExprContext) {
|
func ImportImportFuncs(ctx ExprContext) {
|
||||||
// ctx.RegisterFunc("import", &simpleFunctor{f: importFunc}, 1, -1)
|
ctx.RegisterFunc("import", newGolangFunctor(importFunc), typeAny, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("import", newSimpleFunctor(importFunc), typeAny, []ExprFuncParam{
|
|
||||||
newFuncParamFlag(typeFilepath, pfRepeat),
|
newFuncParamFlag(typeFilepath, pfRepeat),
|
||||||
})
|
})
|
||||||
//ctx.RegisterFunc("importAll", &simpleFunctor{f: importAllFunc}, 1, -1)
|
ctx.RegisterFunc("importAll", newGolangFunctor(importAllFunc), typeAny, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("importAll", newSimpleFunctor(importAllFunc), typeAny, []ExprFuncParam{
|
|
||||||
newFuncParamFlag(typeFilepath, pfRepeat),
|
newFuncParamFlag(typeFilepath, pfRepeat),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -167,13 +167,11 @@ func mulFunc(ctx ExprContext, name string, args []any) (result any, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ImportMathFuncs(ctx ExprContext) {
|
func ImportMathFuncs(ctx ExprContext) {
|
||||||
//ctx.RegisterFunc("add", &simpleFunctor{f: addFunc}, 0, -1)
|
ctx.RegisterFunc("add", &golangFunctor{f: addFunc}, typeNumber, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("add", &simpleFunctor{f: addFunc}, typeNumber, []ExprFuncParam{
|
|
||||||
newFuncParamFlagDef(paramValue, pfOptional|pfRepeat, 0),
|
newFuncParamFlagDef(paramValue, pfOptional|pfRepeat, 0),
|
||||||
})
|
})
|
||||||
|
|
||||||
// ctx.RegisterFunc("mul", &simpleFunctor{f: mulFunc}, 0, -1)
|
ctx.RegisterFunc("mul", &golangFunctor{f: mulFunc}, typeNumber, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("mul", &simpleFunctor{f: mulFunc}, typeNumber, []ExprFuncParam{
|
|
||||||
newFuncParamFlagDef(paramValue, pfOptional|pfRepeat, 1),
|
newFuncParamFlagDef(paramValue, pfOptional|pfRepeat, 1),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
18
func-os.go
18
func-os.go
@ -158,30 +158,24 @@ func readFileFunc(ctx ExprContext, name string, args []any) (result any, err err
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ImportOsFuncs(ctx ExprContext) {
|
func ImportOsFuncs(ctx ExprContext) {
|
||||||
// ctx.RegisterFunc("openFile", &simpleFunctor{f: openFileFunc}, 1, 1)
|
ctx.RegisterFunc("openFile", newGolangFunctor(openFileFunc), typeHandle, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("openFile", newSimpleFunctor(openFileFunc), typeHandle, []ExprFuncParam{
|
|
||||||
newFuncParam(typeFilepath),
|
newFuncParam(typeFilepath),
|
||||||
})
|
})
|
||||||
// ctx.RegisterFunc("appendFile", &simpleFunctor{f: appendFileFunc}, 1, 1)
|
ctx.RegisterFunc("appendFile", newGolangFunctor(appendFileFunc), typeHandle, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("appendFile", newSimpleFunctor(appendFileFunc), typeHandle, []ExprFuncParam{
|
|
||||||
newFuncParam(typeFilepath),
|
newFuncParam(typeFilepath),
|
||||||
})
|
})
|
||||||
// ctx.RegisterFunc("createFile", &simpleFunctor{f: createFileFunc}, 1, 1)
|
ctx.RegisterFunc("createFile", newGolangFunctor(createFileFunc), typeHandle, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("createFile", newSimpleFunctor(createFileFunc), typeHandle, []ExprFuncParam{
|
|
||||||
newFuncParam(typeFilepath),
|
newFuncParam(typeFilepath),
|
||||||
})
|
})
|
||||||
// ctx.RegisterFunc("writeFile", &simpleFunctor{f: writeFileFunc}, 1, -1)
|
ctx.RegisterFunc("writeFile", newGolangFunctor(writeFileFunc), typeInt, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("writeFile", newSimpleFunctor(writeFileFunc), typeInt, []ExprFuncParam{
|
|
||||||
newFuncParam(typeHandle),
|
newFuncParam(typeHandle),
|
||||||
newFuncParamFlagDef(typeItem, pfOptional|pfRepeat, ""),
|
newFuncParamFlagDef(typeItem, pfOptional|pfRepeat, ""),
|
||||||
})
|
})
|
||||||
// ctx.RegisterFunc("readFile", &simpleFunctor{f: readFileFunc}, 1, 2)
|
ctx.RegisterFunc("readFile", newGolangFunctor(readFileFunc), typeString, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("readFile", newSimpleFunctor(readFileFunc), typeString, []ExprFuncParam{
|
|
||||||
newFuncParam(typeHandle),
|
newFuncParam(typeHandle),
|
||||||
newFuncParamFlagDef("limitCh", pfOptional, "\\n"),
|
newFuncParamFlagDef("limitCh", pfOptional, "\\n"),
|
||||||
})
|
})
|
||||||
//ctx.RegisterFunc("closeFile", &simpleFunctor{f: closeFileFunc}, 1, 1)
|
ctx.RegisterFunc("closeFile", newGolangFunctor(closeFileFunc), typeBoolean, []ExprFuncParam{
|
||||||
ctx.RegisterFunc2("closeFile", newSimpleFunctor(closeFileFunc), typeBoolean, []ExprFuncParam{
|
|
||||||
newFuncParam(typeHandle),
|
newFuncParam(typeHandle),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -183,33 +183,33 @@ func splitStrFunc(ctx ExprContext, name string, args []any) (result any, err err
|
|||||||
|
|
||||||
// Import above functions in the context
|
// Import above functions in the context
|
||||||
func ImportStringFuncs(ctx ExprContext) {
|
func ImportStringFuncs(ctx ExprContext) {
|
||||||
ctx.RegisterFunc2("joinStr", newSimpleFunctor(joinStrFunc), typeString, []ExprFuncParam{
|
ctx.RegisterFunc("joinStr", newGolangFunctor(joinStrFunc), typeString, []ExprFuncParam{
|
||||||
newFuncParam(paramSeparator),
|
newFuncParam(paramSeparator),
|
||||||
newFuncParamFlagDef(paramItem, pfOptional|pfRepeat, ""),
|
newFuncParamFlagDef(paramItem, pfOptional|pfRepeat, ""),
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.RegisterFunc2("subStr", newSimpleFunctor(subStrFunc), typeString, []ExprFuncParam{
|
ctx.RegisterFunc("subStr", newGolangFunctor(subStrFunc), typeString, []ExprFuncParam{
|
||||||
newFuncParam(paramSource),
|
newFuncParam(paramSource),
|
||||||
newFuncParamFlagDef(paramStart, pfOptional, 0),
|
newFuncParamFlagDef(paramStart, pfOptional, 0),
|
||||||
newFuncParamFlagDef(paramCount, pfOptional, -1),
|
newFuncParamFlagDef(paramCount, pfOptional, -1),
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.RegisterFunc2("splitStr", newSimpleFunctor(splitStrFunc), "list of "+typeString, []ExprFuncParam{
|
ctx.RegisterFunc("splitStr", newGolangFunctor(splitStrFunc), "list of "+typeString, []ExprFuncParam{
|
||||||
newFuncParam(paramSource),
|
newFuncParam(paramSource),
|
||||||
newFuncParamFlagDef(paramSeparator, pfOptional, ""),
|
newFuncParamFlagDef(paramSeparator, pfOptional, ""),
|
||||||
newFuncParamFlagDef(paramCount, pfOptional, -1),
|
newFuncParamFlagDef(paramCount, pfOptional, -1),
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.RegisterFunc2("trimStr", newSimpleFunctor(trimStrFunc), typeString, []ExprFuncParam{
|
ctx.RegisterFunc("trimStr", newGolangFunctor(trimStrFunc), typeString, []ExprFuncParam{
|
||||||
newFuncParam(paramSource),
|
newFuncParam(paramSource),
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.RegisterFunc2("startsWithStr", newSimpleFunctor(startsWithStrFunc), typeBoolean, []ExprFuncParam{
|
ctx.RegisterFunc("startsWithStr", newGolangFunctor(startsWithStrFunc), typeBoolean, []ExprFuncParam{
|
||||||
newFuncParam(paramSource),
|
newFuncParam(paramSource),
|
||||||
newFuncParamFlag(paramPrefix, pfRepeat),
|
newFuncParamFlag(paramPrefix, pfRepeat),
|
||||||
})
|
})
|
||||||
|
|
||||||
ctx.RegisterFunc2("endsWithStr", newSimpleFunctor(endsWithStrFunc), typeBoolean, []ExprFuncParam{
|
ctx.RegisterFunc("endsWithStr", newGolangFunctor(endsWithStrFunc), typeBoolean, []ExprFuncParam{
|
||||||
newFuncParam(paramSource),
|
newFuncParam(paramSource),
|
||||||
newFuncParamFlag(paramSuffix, pfRepeat),
|
newFuncParamFlag(paramSuffix, pfRepeat),
|
||||||
})
|
})
|
||||||
|
232
function.go
Normal file
232
function.go
Normal file
@ -0,0 +1,232 @@
|
|||||||
|
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||||
|
// All rights reserved.
|
||||||
|
|
||||||
|
// function.go
|
||||||
|
package expr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ---- Function template
|
||||||
|
type FuncTemplate func(ctx ExprContext, name string, args []any) (result any, err error)
|
||||||
|
|
||||||
|
// ---- Common functor definition
|
||||||
|
type baseFunctor struct {
|
||||||
|
info ExprFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (functor *baseFunctor) ToString(opt FmtOpt) (s string) {
|
||||||
|
if functor.info != nil {
|
||||||
|
s = functor.info.ToString(opt)
|
||||||
|
} else {
|
||||||
|
s = "func() {<body>}"
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (functor *baseFunctor) SetFunc(info ExprFunc) {
|
||||||
|
functor.info = info
|
||||||
|
}
|
||||||
|
|
||||||
|
func (functor *baseFunctor) GetFunc() ExprFunc {
|
||||||
|
return functor.info
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Linking with the functions of Go
|
||||||
|
type golangFunctor struct {
|
||||||
|
baseFunctor
|
||||||
|
f FuncTemplate
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGolangFunctor(f FuncTemplate) *golangFunctor {
|
||||||
|
return &golangFunctor{f: f}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (functor *golangFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) {
|
||||||
|
return functor.f(ctx, name, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Linking with the functions of Expr
|
||||||
|
type exprFunctor struct {
|
||||||
|
baseFunctor
|
||||||
|
params []string
|
||||||
|
expr Expr
|
||||||
|
}
|
||||||
|
|
||||||
|
func newExprFunctor(e Expr, params []string) *exprFunctor {
|
||||||
|
return &exprFunctor{expr: e, params: params}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (functor *exprFunctor) 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 funcArg, ok := arg.(Functor); ok {
|
||||||
|
// ctx.RegisterFunc(p, functor, 0, -1)
|
||||||
|
ctx.RegisterFunc(p, funcArg, typeAny, []ExprFuncParam{
|
||||||
|
newFuncParam(paramValue),
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ctx.UnsafeSetVar(p, arg)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ctx.UnsafeSetVar(p, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result, err = functor.expr.eval(ctx, false)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- Function Parameters
|
||||||
|
type paramFlags uint16
|
||||||
|
|
||||||
|
const (
|
||||||
|
pfOptional paramFlags = 1 << iota
|
||||||
|
pfRepeat
|
||||||
|
)
|
||||||
|
|
||||||
|
type funcParamInfo struct {
|
||||||
|
name string
|
||||||
|
flags paramFlags
|
||||||
|
defaultValue any
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFuncParam(name string) ExprFuncParam {
|
||||||
|
return &funcParamInfo{name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFuncParamFlag(name string, flags paramFlags) ExprFuncParam {
|
||||||
|
return &funcParamInfo{name: name, flags: flags}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFuncParamFlagDef(name string, flags paramFlags, defValue any) *funcParamInfo {
|
||||||
|
return &funcParamInfo{name: name, flags: flags, defaultValue: defValue}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (param *funcParamInfo) Name() string {
|
||||||
|
return param.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (param *funcParamInfo) Type() string {
|
||||||
|
return "any"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (param *funcParamInfo) IsOptional() bool {
|
||||||
|
return (param.flags & pfOptional) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (param *funcParamInfo) IsRepeat() bool {
|
||||||
|
return (param.flags & pfRepeat) != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (param *funcParamInfo) DefaultValue() any {
|
||||||
|
return param.defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Functions
|
||||||
|
type funcInfo struct {
|
||||||
|
name string
|
||||||
|
minArgs int
|
||||||
|
maxArgs int
|
||||||
|
functor Functor
|
||||||
|
params []ExprFuncParam
|
||||||
|
returnType string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newFuncInfo(name string, functor Functor, returnType string, params []ExprFuncParam) (info *funcInfo, err error) {
|
||||||
|
var minArgs = 0
|
||||||
|
var maxArgs = 0
|
||||||
|
if params != nil {
|
||||||
|
for _, p := range params {
|
||||||
|
if maxArgs == -1 {
|
||||||
|
return nil, fmt.Errorf("no more params can be specified after the ellipsis symbol: %q", p.Name())
|
||||||
|
}
|
||||||
|
if p.IsOptional() {
|
||||||
|
maxArgs++
|
||||||
|
} else if maxArgs == minArgs {
|
||||||
|
minArgs++
|
||||||
|
maxArgs++
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("can't specify non-optional param after optional ones: %q", p.Name())
|
||||||
|
}
|
||||||
|
if p.IsRepeat() {
|
||||||
|
maxArgs = -1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info = &funcInfo{
|
||||||
|
name: name, minArgs: minArgs, maxArgs: maxArgs, functor: functor, returnType: returnType, params: params,
|
||||||
|
}
|
||||||
|
functor.SetFunc(info)
|
||||||
|
return info, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func newUnnamedFuncInfo(functor Functor, returnType string, params []ExprFuncParam) (info *funcInfo, err error) {
|
||||||
|
return newFuncInfo("unnamed", functor, returnType, params)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *funcInfo) Params() []ExprFuncParam {
|
||||||
|
return info.params
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *funcInfo) ReturnType() string {
|
||||||
|
return info.returnType
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *funcInfo) ToString(opt FmtOpt) string {
|
||||||
|
var sb strings.Builder
|
||||||
|
if len(info.Name()) == 0 {
|
||||||
|
sb.WriteString("func")
|
||||||
|
} else {
|
||||||
|
sb.WriteString(info.Name())
|
||||||
|
}
|
||||||
|
sb.WriteByte('(')
|
||||||
|
if info.params != nil {
|
||||||
|
for i, p := range info.params {
|
||||||
|
if i > 0 {
|
||||||
|
sb.WriteString(", ")
|
||||||
|
}
|
||||||
|
sb.WriteString(p.Name())
|
||||||
|
|
||||||
|
if p.IsOptional() {
|
||||||
|
sb.WriteByte('=')
|
||||||
|
if s, ok := p.DefaultValue().(string); ok {
|
||||||
|
sb.WriteByte('"')
|
||||||
|
sb.WriteString(s)
|
||||||
|
sb.WriteByte('"')
|
||||||
|
} else {
|
||||||
|
sb.WriteString(fmt.Sprintf("%v", p.DefaultValue()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if info.maxArgs < 0 {
|
||||||
|
sb.WriteString(" ...")
|
||||||
|
}
|
||||||
|
sb.WriteString("): ")
|
||||||
|
if len(info.returnType) > 0 {
|
||||||
|
sb.WriteString(info.returnType)
|
||||||
|
} else {
|
||||||
|
sb.WriteString(typeAny)
|
||||||
|
}
|
||||||
|
sb.WriteString(" {<body>}")
|
||||||
|
return sb.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *funcInfo) Name() string {
|
||||||
|
return info.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *funcInfo) MinArgs() int {
|
||||||
|
return info.minArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *funcInfo) MaxArgs() int {
|
||||||
|
return info.maxArgs
|
||||||
|
}
|
||||||
|
|
||||||
|
func (info *funcInfo) Functor() Functor {
|
||||||
|
return info.functor
|
||||||
|
}
|
@ -38,9 +38,9 @@ func EvalStringV(source string, args []Arg) (result any, err error) {
|
|||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
if isFunc(arg.Value) {
|
if isFunc(arg.Value) {
|
||||||
if f, ok := arg.Value.(FuncTemplate); ok {
|
if f, ok := arg.Value.(FuncTemplate); ok {
|
||||||
functor := newSimpleFunctor(f)
|
functor := newGolangFunctor(f)
|
||||||
// ctx.RegisterFunc(arg.Name, functor, 0, -1)
|
// ctx.RegisterFunc(arg.Name, functor, 0, -1)
|
||||||
ctx.RegisterFunc2(arg.Name, functor, typeAny, []ExprFuncParam{
|
ctx.RegisterFunc(arg.Name, functor, typeAny, []ExprFuncParam{
|
||||||
newFuncParamFlagDef(paramValue, pfOptional|pfRepeat, 0),
|
newFuncParamFlagDef(paramValue, pfOptional|pfRepeat, 0),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -76,30 +76,30 @@ func newFuncDefTerm(tk *Token, args []*term) *term {
|
|||||||
|
|
||||||
// -------- eval func def
|
// -------- eval func def
|
||||||
// TODO
|
// TODO
|
||||||
type funcDefFunctor struct {
|
// type funcDefFunctor struct {
|
||||||
params []string
|
// params []string
|
||||||
expr Expr
|
// expr Expr
|
||||||
}
|
// }
|
||||||
|
|
||||||
func (funcDef *funcDefFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) {
|
// func (funcDef *funcDefFunctor) Invoke(ctx ExprContext, name string, args []any) (result any, err error) {
|
||||||
for i, p := range funcDef.params {
|
// for i, p := range funcDef.params {
|
||||||
if i < len(args) {
|
// if i < len(args) {
|
||||||
arg := args[i]
|
// arg := args[i]
|
||||||
if functor, ok := arg.(Functor); ok {
|
// if functor, ok := arg.(Functor); ok {
|
||||||
// ctx.RegisterFunc(p, functor, 0, -1)
|
// // ctx.RegisterFunc(p, functor, 0, -1)
|
||||||
ctx.RegisterFunc2(p, functor, typeAny, []ExprFuncParam{
|
// ctx.RegisterFunc2(p, functor, typeAny, []ExprFuncParam{
|
||||||
newFuncParam(paramValue),
|
// newFuncParam(paramValue),
|
||||||
})
|
// })
|
||||||
} else {
|
// } else {
|
||||||
ctx.UnsafeSetVar(p, arg)
|
// ctx.UnsafeSetVar(p, arg)
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
ctx.UnsafeSetVar(p, nil)
|
// ctx.UnsafeSetVar(p, nil)
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
result, err = funcDef.expr.eval(ctx, false)
|
// result, err = funcDef.expr.eval(ctx, false)
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
|
|
||||||
func evalFuncDef(ctx ExprContext, self *term) (v any, err error) {
|
func evalFuncDef(ctx ExprContext, self *term) (v any, err error) {
|
||||||
bodySpec := self.value()
|
bodySpec := self.value()
|
||||||
@ -108,10 +108,11 @@ func evalFuncDef(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
for _, param := range self.children {
|
for _, param := range self.children {
|
||||||
paramList = append(paramList, param.source())
|
paramList = append(paramList, param.source())
|
||||||
}
|
}
|
||||||
v = &funcDefFunctor{
|
v = newExprFunctor(expr, paramList)
|
||||||
params: paramList,
|
// v = &funcDefFunctor{
|
||||||
expr: expr,
|
// params: paramList,
|
||||||
}
|
// expr: expr,
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
err = errors.New("invalid function definition: the body specification must be an expression")
|
err = errors.New("invalid function definition: the body specification must be an expression")
|
||||||
}
|
}
|
||||||
|
@ -74,7 +74,8 @@ func getDataSourceDict(ctx ExprContext, self *term, firstChildValue any) (ds map
|
|||||||
ds = make(map[string]Functor)
|
ds = make(map[string]Functor)
|
||||||
for keyAny, item := range *dictAny {
|
for keyAny, item := range *dictAny {
|
||||||
if key, ok := keyAny.(string); ok {
|
if key, ok := keyAny.(string); ok {
|
||||||
if functor, ok := item.(*funcDefFunctor); ok {
|
//if functor, ok := item.(*funcDefFunctor); ok {
|
||||||
|
if functor, ok := item.(Functor); ok {
|
||||||
ds[key] = functor
|
ds[key] = functor
|
||||||
if index := slices.Index(requiredFields, key); index >= 0 {
|
if index := slices.Index(requiredFields, key); index >= 0 {
|
||||||
foundFields |= 1 << index
|
foundFields |= 1 << index
|
||||||
|
@ -34,14 +34,15 @@ func evalAssign(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
funcName := rightChild.source()
|
funcName := rightChild.source()
|
||||||
if info, exists, _ := GetFuncInfo(ctx, funcName); exists {
|
if info, exists, _ := GetFuncInfo(ctx, funcName); exists {
|
||||||
// ctx.RegisterFuncInfo(info)
|
// ctx.RegisterFuncInfo(info)
|
||||||
ctx.RegisterFunc2(leftTerm.source(), info.Functor(), info.ReturnType(), info.Params())
|
ctx.RegisterFunc(leftTerm.source(), info.Functor(), info.ReturnType(), info.Params())
|
||||||
} else if funcDef, ok := functor.(*funcDefFunctor); ok {
|
} else if funcDef, ok := functor.(*exprFunctor); ok {
|
||||||
paramCount := len(funcDef.params)
|
paramSpecs := ForAll(funcDef.params, newFuncParam)
|
||||||
paramSpecs := make([]ExprFuncParam, paramCount)
|
// paramCount := len(funcDef.params)
|
||||||
for i := range paramSpecs {
|
// paramSpecs := make([]ExprFuncParam, paramCount)
|
||||||
paramSpecs[i] = newFuncParam(funcDef.params[i])
|
// for i := range paramSpecs {
|
||||||
}
|
// paramSpecs[i] = newFuncParam(funcDef.params[i])
|
||||||
ctx.RegisterFunc2(leftTerm.source(), functor, typeAny, paramSpecs)
|
// }
|
||||||
|
ctx.RegisterFunc(leftTerm.source(), functor, typeAny, paramSpecs)
|
||||||
} else {
|
} else {
|
||||||
err = self.Errorf("unknown function %s()", funcName)
|
err = self.Errorf("unknown function %s()", funcName)
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ func evalAssignCoalesce(ctx ExprContext, self *term) (v any, err error) {
|
|||||||
} else if rightValue, err = self.children[1].compute(ctx); err == nil {
|
} else if rightValue, err = self.children[1].compute(ctx); err == nil {
|
||||||
if functor, ok := rightValue.(Functor); ok {
|
if functor, ok := rightValue.(Functor); ok {
|
||||||
//ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
|
//ctx.RegisterFunc(leftTerm.source(), functor, 0, -1)
|
||||||
ctx.RegisterFunc2(leftTerm.source(), functor, typeAny, []ExprFuncParam{
|
ctx.RegisterFunc(leftTerm.source(), functor, typeAny, []ExprFuncParam{
|
||||||
newFuncParamFlag(paramValue, pfOptional|pfRepeat),
|
newFuncParamFlag(paramValue, pfOptional|pfRepeat),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
142
simple-store.go
142
simple-store.go
@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
|
|
||||||
// simple-func-store.go
|
// simple-store.go
|
||||||
package expr
|
package expr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -15,117 +15,6 @@ type SimpleStore struct {
|
|||||||
funcStore map[string]*funcInfo
|
funcStore map[string]*funcInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
type paramFlags uint16
|
|
||||||
|
|
||||||
const (
|
|
||||||
pfOptional paramFlags = 1 << iota
|
|
||||||
pfRepeat
|
|
||||||
)
|
|
||||||
|
|
||||||
type funcParamInfo struct {
|
|
||||||
name string
|
|
||||||
flags paramFlags
|
|
||||||
defaultValue any
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFuncParam(name string) *funcParamInfo {
|
|
||||||
return &funcParamInfo{name: name}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFuncParamFlag(name string, flags paramFlags) *funcParamInfo {
|
|
||||||
return &funcParamInfo{name: name, flags: flags}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newFuncParamFlagDef(name string, flags paramFlags, defValue any) *funcParamInfo {
|
|
||||||
return &funcParamInfo{name: name, flags: flags, defaultValue: defValue}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (param *funcParamInfo) Name() string {
|
|
||||||
return param.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (param *funcParamInfo) Type() string {
|
|
||||||
return "any"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (param *funcParamInfo) IsOptional() bool {
|
|
||||||
return (param.flags & pfOptional) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (param *funcParamInfo) IsRepeat() bool {
|
|
||||||
return (param.flags & pfRepeat) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (param *funcParamInfo) DefaultValue() any {
|
|
||||||
return param.defaultValue
|
|
||||||
}
|
|
||||||
|
|
||||||
type funcInfo struct {
|
|
||||||
name string
|
|
||||||
minArgs int
|
|
||||||
maxArgs int
|
|
||||||
functor Functor
|
|
||||||
params []ExprFuncParam
|
|
||||||
returnType string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *funcInfo) Params() []ExprFuncParam {
|
|
||||||
return info.params
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *funcInfo) ReturnType() string {
|
|
||||||
return info.returnType
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *funcInfo) ToString(opt FmtOpt) string {
|
|
||||||
var sb strings.Builder
|
|
||||||
sb.WriteByte('(')
|
|
||||||
if info.params != nil {
|
|
||||||
for i, p := range info.params {
|
|
||||||
if i > 0 {
|
|
||||||
sb.WriteString(", ")
|
|
||||||
}
|
|
||||||
sb.WriteString(p.Name())
|
|
||||||
if p.IsOptional() {
|
|
||||||
sb.WriteByte('=')
|
|
||||||
if s, ok := p.DefaultValue().(string); ok {
|
|
||||||
sb.WriteByte('"')
|
|
||||||
sb.WriteString(s)
|
|
||||||
sb.WriteByte('"')
|
|
||||||
} else {
|
|
||||||
sb.WriteString(fmt.Sprintf("%v", p.DefaultValue()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if info.maxArgs < 0 {
|
|
||||||
sb.WriteString(" ...")
|
|
||||||
}
|
|
||||||
sb.WriteString(") -> ")
|
|
||||||
if len(info.returnType) > 0 {
|
|
||||||
sb.WriteString(info.returnType)
|
|
||||||
} else {
|
|
||||||
sb.WriteString(typeAny)
|
|
||||||
}
|
|
||||||
return sb.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *funcInfo) Name() string {
|
|
||||||
return info.name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *funcInfo) MinArgs() int {
|
|
||||||
return info.minArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *funcInfo) MaxArgs() int {
|
|
||||||
return info.maxArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (info *funcInfo) Functor() Functor {
|
|
||||||
return info.functor
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewSimpleStore() *SimpleStore {
|
func NewSimpleStore() *SimpleStore {
|
||||||
ctx := &SimpleStore{
|
ctx := &SimpleStore{
|
||||||
varStore: make(map[string]any),
|
varStore: make(map[string]any),
|
||||||
@ -251,31 +140,12 @@ func (ctx *SimpleStore) RegisterFuncInfo(info ExprFunc) {
|
|||||||
ctx.funcStore[info.Name()], _ = info.(*funcInfo)
|
ctx.funcStore[info.Name()], _ = info.(*funcInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *SimpleStore) RegisterFunc2(name string, functor Functor, returnType string, params []ExprFuncParam) error {
|
func (ctx *SimpleStore) RegisterFunc(name string, functor Functor, returnType string, params []ExprFuncParam) (err error) {
|
||||||
var minArgs = 0
|
var info *funcInfo
|
||||||
var maxArgs = 0
|
if info, err = newFuncInfo(name, functor, returnType, params); err == nil {
|
||||||
if params != nil {
|
ctx.funcStore[name] = info
|
||||||
for _, p := range params {
|
|
||||||
if maxArgs == -1 {
|
|
||||||
return fmt.Errorf("no more params can be specified after the ellipsis symbol: %q", p.Name())
|
|
||||||
}
|
|
||||||
if p.IsOptional() {
|
|
||||||
maxArgs++
|
|
||||||
} else if maxArgs == minArgs {
|
|
||||||
minArgs++
|
|
||||||
maxArgs++
|
|
||||||
} else {
|
|
||||||
return fmt.Errorf("can't specify non-optional param after optional ones: %q", p.Name())
|
|
||||||
}
|
|
||||||
if p.IsRepeat() {
|
|
||||||
maxArgs = -1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ctx.funcStore[name] = &funcInfo{
|
return
|
||||||
name: name, minArgs: minArgs, maxArgs: maxArgs, functor: functor, returnType: returnType, params: params,
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctx *SimpleStore) EnumFuncs(acceptor func(name string) (accept bool)) (funcNames []string) {
|
func (ctx *SimpleStore) EnumFuncs(acceptor func(name string) (accept bool)) (funcNames []string) {
|
||||||
|
Loading…
Reference in New Issue
Block a user