Compare commits

...

6 Commits

10 changed files with 172 additions and 59 deletions

View File

@ -30,7 +30,7 @@ func importGeneral(ctx ExprContext, name string, args []any) (result any, err er
dirList = addEnvImportDirs(dirList) dirList = addEnvImportDirs(dirList)
dirList = addPresetImportDirs(ctx, dirList) dirList = addPresetImportDirs(ctx, dirList)
result, err = doImport(ctx, name, dirList, NewFlatArrayIterator(args)) result, err = doImport(ctx, name, dirList, NewArrayIterator(args))
return return
} }

View File

@ -37,8 +37,8 @@ func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) {
if err = checkNumberParamExpected(name, v, it.Index()); err != nil { if err = checkNumberParamExpected(name, v, it.Index()); err != nil {
break break
} }
if array, ok := v.(*ListType); ok { if list, ok := v.(*ListType); ok {
if v, err = doAdd(ctx, name, NewFlatArrayIterator(*array)); err != nil { if v, err = doAdd(ctx, name, NewListIterator(list)); err != nil {
break break
} }
} }
@ -87,7 +87,7 @@ func doAdd(ctx ExprContext, name string, it Iterator) (result any, err error) {
} }
func addFunc(ctx ExprContext, name string, args []any) (result any, err error) { func addFunc(ctx ExprContext, name string, args []any) (result any, err error) {
result, err = doAdd(ctx, name, NewFlatArrayIterator(args)) result, err = doAdd(ctx, name, NewArrayIterator(args))
return return
} }
@ -113,8 +113,8 @@ func doMul(ctx ExprContext, name string, it Iterator) (result any, err error) {
break break
} }
if array, ok := v.(*ListType); ok { if list, ok := v.(*ListType); ok {
if v, err = doMul(ctx, name, NewFlatArrayIterator(*array)); err != nil { if v, err = doMul(ctx, name, NewListIterator(list)); err != nil {
break break
} }
} }
@ -163,7 +163,7 @@ func doMul(ctx ExprContext, name string, it Iterator) (result any, err error) {
} }
func mulFunc(ctx ExprContext, name string, args []any) (result any, err error) { func mulFunc(ctx ExprContext, name string, args []any) (result any, err error) {
result, err = doMul(ctx, name, NewFlatArrayIterator(args)) result, err = doMul(ctx, name, NewArrayIterator(args))
return return
} }

View File

@ -39,15 +39,15 @@ func joinStrFunc(ctx ExprContext, name string, args []any) (result any, err erro
if len(args) == 1 { if len(args) == 1 {
result = "" result = ""
} else if len(args) == 2 { } else if len(args) == 2 {
if ls, ok := args[1].([]any); ok { if ls, ok := args[1].(*ListType); ok {
result, err = doJoinStr(name, sep, NewFlatArrayIterator(ls)) result, err = doJoinStr(name, sep, NewListIterator(ls))
} else if it, ok := args[1].(Iterator); ok { } else if it, ok := args[1].(Iterator); ok {
result, err = doJoinStr(name, sep, it) result, err = doJoinStr(name, sep, it)
} else { } else {
err = errInvalidParameterValue(name, paramParts, args[1]) err = errInvalidParameterValue(name, paramParts, args[1])
} }
} else { } else {
result, err = doJoinStr(name, sep, NewFlatArrayIterator(args[1:])) result, err = doJoinStr(name, sep, NewArrayIterator(args[1:]))
} }
} else { } else {
err = errWrongParamType(name, paramSeparator, typeString, args[0]) err = errWrongParamType(name, paramSeparator, typeString, args[0])

View File

@ -6,33 +6,53 @@ package expr
import "io" import "io"
type FlatArrayIterator struct { type ListIterator struct {
a ListType a *ListType
index int index int
} }
func NewFlatArrayIterator(array ListType) *FlatArrayIterator { func NewListIterator(list *ListType) *ListIterator {
return &FlatArrayIterator{a: array, index: 0} return &ListIterator{a: list, index: 0}
} }
func (it *FlatArrayIterator) HasOperation(name string) bool { func NewArrayIterator(array []any) *ListIterator {
return &ListIterator{a: (*ListType)(&array), index: 0}
}
func NewAnyIterator(value any) (it *ListIterator) {
if value == nil {
it = NewArrayIterator([]any{})
} else if list, ok := value.(*ListType); ok {
it = NewListIterator(list)
} else if array, ok := value.([]any); ok {
it = NewArrayIterator(array)
} else if it1, ok := value.(*ListIterator); ok {
it = it1
} else {
it = NewArrayIterator([]any{value})
}
return
}
func (it *ListIterator) HasOperation(name string) bool {
return false return false
} }
func (it *FlatArrayIterator) CallOperation(name string, args []any) (any, error) { func (it *ListIterator) CallOperation(name string, args []any) (any, error) {
return nil, errNoOperation(name) return nil, errNoOperation(name)
} }
func (it *FlatArrayIterator) Current() (item any, err error) { func (it *ListIterator) Current() (item any, err error) {
if it.index >= 0 && it.index < len(it.a) { a := *(it.a)
item = it.a[it.index] if it.index >= 0 && it.index < len(a) {
item = a[it.index]
} else { } else {
err = io.EOF err = io.EOF
} }
return return
} }
func (it *FlatArrayIterator) Next() (item any, err error) { func (it *ListIterator) Next() (item any, err error) {
if item, err = it.Current(); err != io.EOF { if item, err = it.Current(); err != io.EOF {
it.index++ it.index++
} }
@ -45,6 +65,6 @@ func (it *FlatArrayIterator) Next() (item any, err error) {
return return
} }
func (it *FlatArrayIterator) Index() int { func (it *ListIterator) Index() int {
return it.index - 1 return it.index - 1
} }

View File

@ -42,6 +42,10 @@ func (ls *ListType) ToString(opt FmtOpt) string {
return sb.String() return sb.String()
} }
func (ls *ListType) String() string {
return ls.ToString(0)
}
// -------- list term // -------- list term
func newListTermA(args ...*term) *term { func newListTermA(args ...*term) *term {
return newListTerm(args) return newListTerm(args)

View File

@ -4,6 +4,8 @@
// operator-builtin.go // operator-builtin.go
package expr package expr
import "io"
//-------- builtin term //-------- builtin term
func newBuiltinTerm(tk *Token) (inst *term) { func newBuiltinTerm(tk *Token) (inst *term) {
@ -17,16 +19,20 @@ func newBuiltinTerm(tk *Token) (inst *term) {
} }
func evalBuiltin(ctx ExprContext, self *term) (v any, err error) { func evalBuiltin(ctx ExprContext, self *term) (v any, err error) {
var rightValue any var childValue any
if rightValue, err = self.evalPrefix(ctx); err != nil { if childValue, err = self.evalPrefix(ctx); err != nil {
return return
} }
count := 0 count := 0
if isList(rightValue) { if isString(childValue) {
list, _ := rightValue.([]any) module, _ := childValue.(string)
for i, moduleSpec := range list { count, err = ImportInContextByGlobPattern(ctx, module)
} else {
var moduleSpec any
it := NewAnyIterator(childValue)
for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() {
if module, ok := moduleSpec.(string); ok { if module, ok := moduleSpec.(string); ok {
if ImportInContext(ctx, module) { if ImportInContext(ctx, module) {
count++ count++
@ -35,15 +41,13 @@ func evalBuiltin(ctx ExprContext, self *term) (v any, err error) {
break break
} }
} else { } else {
err = self.Errorf("expected string at item nr %d, got %T", i+1, moduleSpec) err = self.Errorf("expected string at item nr %d, got %T", it.Index()+1, moduleSpec)
break break
} }
} }
} else if isString(rightValue) { if err == io.EOF {
module, _ := rightValue.(string) err = nil
count, err = ImportInContextByGlobPattern(ctx, module) }
} else {
err = self.errIncompatibleType(rightValue)
} }
if err == nil { if err == nil {
v = count v = count

View File

@ -31,16 +31,20 @@ func evalContextValue(ctx ExprContext, self *term) (v any, err error) {
} }
if sourceCtx != nil { if sourceCtx != nil {
keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' }) if formatter, ok := ctx.(Formatter); ok {
d := make(map[string]any) v = formatter.ToString(0)
for _, key := range keys { } else {
d[key], _ = sourceCtx.GetVar(key) keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' })
d := make(map[string]any)
for _, key := range keys {
d[key], _ = sourceCtx.GetVar(key)
}
keys = sourceCtx.EnumFuncs(func(name string) bool { return true })
for _, key := range keys {
d[key], _ = sourceCtx.GetFuncInfo(key)
}
v = d
} }
keys = sourceCtx.EnumFuncs(func(name string) bool { return true })
for _, key := range keys {
d[key], _ =sourceCtx.GetFuncInfo(key)
}
v = d
} else { } else {
err = self.errIncompatibleType(childValue) err = self.errIncompatibleType(childValue)
} }

View File

@ -132,7 +132,7 @@ func TestParser(t *testing.T) {
/* 110 */ {`double=func(x){2*x}; a=5; double(3+a) + 1`, int64(17), nil}, /* 110 */ {`double=func(x){2*x}; a=5; double(3+a) + 1`, int64(17), nil},
/* 111 */ {`double=func(x){2*x}; a=5; two=func() {2}; (double(3+a) + 1) * two()`, int64(34), nil}, /* 111 */ {`double=func(x){2*x}; a=5; two=func() {2}; (double(3+a) + 1) * two()`, int64(34), nil},
/* 112 */ {`import("./test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil}, /* 112 */ {`import("./test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil},
/* 113 */ {`import("test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil}, // /* 113 */ {`import("test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil},
/* 114 */ {`x ?? "default"`, "default", nil}, /* 114 */ {`x ?? "default"`, "default", nil},
/* 115 */ {`x="hello"; x ?? "default"`, "hello", nil}, /* 115 */ {`x="hello"; x ?? "default"`, "hello", nil},
/* 116 */ {`y=x ?? func(){4}; y()`, int64(4), nil}, /* 116 */ {`y=x ?? func(){4}; y()`, int64(4), nil},
@ -145,7 +145,7 @@ func TestParser(t *testing.T) {
/* 123 */ {`f=func(@y){g=func(){@x=5}; @z=g(); @y=@y+@z}; f(2); y+z`, int64(12), nil}, /* 123 */ {`f=func(@y){g=func(){@x=5}; @z=g(); @y=@y+@z}; f(2); y+z`, int64(12), nil},
/* 124 */ {`f=func(@y){g=func(){@x=5}; g(); @z=x; @y=@y+@z}; f(2); y+z`, int64(12), nil}, /* 124 */ {`f=func(@y){g=func(){@x=5}; g(); @z=x; @y=@y+@z}; f(2); y+z`, int64(12), nil},
/* 125 */ {`f=func(@y){g=func(){@x=5}; g(); @z=x; @x=@y+@z}; f(2); y+x`, int64(9), nil}, /* 125 */ {`f=func(@y){g=func(){@x=5}; g(); @z=x; @x=@y+@z}; f(2); y+x`, int64(9), nil},
/* 126 */ {`include("./test-funcs.expr"); six()`, int64(6), nil}, // /* 126 */ {`include("./test-funcs.expr"); six()`, int64(6), nil},
/* 127 */ {`import("./sample-export-all.expr"); six()`, int64(6), nil}, /* 127 */ {`import("./sample-export-all.expr"); six()`, int64(6), nil},
/* 128 */ {`1 ? {"a"} : {"b"}`, "b", nil}, /* 128 */ {`1 ? {"a"} : {"b"}`, "b", nil},
/* 129 */ {`10 ? {"a"} : {"b"} :: {"c"}`, "c", nil}, /* 129 */ {`10 ? {"a"} : {"b"} :: {"c"}`, "c", nil},
@ -162,7 +162,23 @@ func TestParser(t *testing.T) {
/* 140 */ {`{"key"}`, nil, errors.New(`[1:8] expected ":", got "}"`)}, /* 140 */ {`{"key"}`, nil, errors.New(`[1:8] expected ":", got "}"`)},
/* 141 */ {`{"key":}`, nil, errors.New(`[1:9] expected dictionary value, got "}"`)}, /* 141 */ {`{"key":}`, nil, errors.New(`[1:9] expected dictionary value, got "}"`)},
/* 142 */ {`{}`, map[any]any{}, nil}, /* 142 */ {`{}`, map[any]any{}, nil},
/* 144 */ //{`3^2`, int64(9), nil}, /* 143 */ {`1|2`, newFraction(1, 2), nil},
/* 144 */ {`1|2 + 1`, newFraction(3, 2), nil},
/* 145 */ {`1|2 - 1`, newFraction(-1, 2), nil},
/* 146 */ {`1|2 * 1`, newFraction(1, 2), nil},
/* 147 */ {`1|2 * 2|3`, newFraction(2, 6), nil},
/* 148 */ {`1|2 / 2|3`, newFraction(3, 4), nil},
/* 149 */ {`builtin "math.arith"; add(1|2, 2|3)`, newFraction(7, 6), nil},
/* 150 */ {`builtin "math.arith"; add(1|2, 1.0, 2)`, float64(3.5), nil},
/* 151 */ {`builtin "math.arith"; mul(1|2, 2|3)`, newFraction(2, 6), nil},
/* 152 */ {`builtin "math.arith"; mul(1|2, 1.0, 2)`, float64(1.0), nil},
/* 153 */ {`include "iterator.expr"; it=$(ds,3); ()it`, int64(0), nil},
/* 154 */ {`include "iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil},
/* 155 */ {`include "iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(1), nil},
/* 156 */ {`include "iterator.expr"; it=$(ds,3); it++; it++; it.reset; ()it`, int64(0), nil},
/* 157 */ {`builtin "math.arith"; include "iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil},
/* 158 */ {`builtin "math.arith"; include "iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil},
/* 159 */ {`include "file-reader.expr"; it=$(ds,"int.list"); mul(it)`, int64(12000), nil},
} }
check_env_expr_path := 113 check_env_expr_path := 113

View File

@ -4,7 +4,10 @@
// simple-func-store.go // simple-func-store.go
package expr package expr
import "fmt" import (
"fmt"
"strings"
)
type SimpleFuncStore struct { type SimpleFuncStore struct {
SimpleVarStore SimpleVarStore
@ -18,6 +21,29 @@ type funcInfo struct {
functor Functor functor Functor
} }
func (info *funcInfo) ToString(opt FmtOpt) string {
var sb strings.Builder
var i int
sb.WriteString("func(")
for i = 0; i < info.minArgs; i++ {
if i > 0 {
sb.WriteString(", ")
}
sb.WriteString(fmt.Sprintf("arg%d", i+1))
}
for ; i < info.maxArgs; i++ {
sb.WriteString(fmt.Sprintf("arg%d", i+1))
}
if info.maxArgs < 0 {
if info.minArgs > 0 {
sb.WriteString(", ")
}
sb.WriteString("...")
}
sb.WriteString(") {...}")
return sb.String()
}
func (info *funcInfo) Name() string { func (info *funcInfo) Name() string {
return info.name return info.name
} }
@ -52,6 +78,36 @@ func (ctx *SimpleFuncStore) Clone() ExprContext {
} }
} }
func funcsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) {
sb.WriteString("funcs: {\n")
first := true
for _, name := range ctx.EnumFuncs(func(name string) bool { return true }) {
if first {
first = false
} else {
sb.WriteByte(',')
sb.WriteByte('\n')
}
value, _ := ctx.GetFuncInfo(name)
sb.WriteString(strings.Repeat("\t", indent+1))
sb.WriteString(name)
sb.WriteString("=")
if formatter, ok := value.(Formatter); ok {
sb.WriteString(formatter.ToString(0))
} else {
sb.WriteString(fmt.Sprintf("%v", value))
}
}
sb.WriteString("\n}\n")
}
func (ctx *SimpleFuncStore) ToString(opt FmtOpt) string {
var sb strings.Builder
sb.WriteString(ctx.SimpleVarStore.ToString(opt))
funcsCtxToBuilder(&sb, ctx, 0)
return sb.String()
}
func (ctx *SimpleFuncStore) GetFuncInfo(name string) (info ExprFunc, exists bool) { func (ctx *SimpleFuncStore) GetFuncInfo(name string) (info ExprFunc, exists bool) {
info, exists = ctx.funcStore[name] info, exists = ctx.funcStore[name]
return return

View File

@ -79,34 +79,43 @@ func (ctx *SimpleVarStore) EnumFuncs(acceptor func(name string) (accept bool)) (
return return
} }
func CtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) {
sb.WriteString("{\n") sb.WriteString("vars: {\n")
first := true first := true
for _, name := range ctx.EnumVars(func(name string) bool { return name[0] != '_' }) { for _, name := range ctx.EnumVars(func(name string) bool { return name[0] != '_' }) {
if first {
first = false
} else {
sb.WriteByte(',')
sb.WriteByte('\n')
}
value, _ := ctx.GetVar(name) value, _ := ctx.GetVar(name)
sb.WriteString(strings.Repeat("\t", indent+1)) sb.WriteString(strings.Repeat("\t", indent+1))
sb.WriteString(name) sb.WriteString(name)
sb.WriteString("=") sb.WriteString(": ")
if _, ok := value.(Functor); ok { if f, ok := value.(Formatter); ok {
sb.WriteString(": func(){}") sb.WriteString(f.ToString(0))
} else if _, ok = value.(Functor); ok {
sb.WriteString("func(){}")
} else if _, ok = value.(map[any]any); ok { } else if _, ok = value.(map[any]any); ok {
sb.WriteString("dict{}") sb.WriteString("dict{}")
} else { } else {
sb.WriteString(fmt.Sprintf("%v", value)) sb.WriteString(fmt.Sprintf("%v", value))
} }
if first {
first = false
} else {
sb.WriteByte(',')
}
sb.WriteByte('\n')
} }
sb.WriteString(strings.Repeat("\t", indent)) sb.WriteString(strings.Repeat("\t", indent))
sb.WriteString("}\n") sb.WriteString("\n}\n")
} }
func CtxToString(ctx ExprContext, indent int) string { func varsCtxToString(ctx ExprContext, indent int) string {
var sb strings.Builder var sb strings.Builder
CtxToBuilder(&sb, ctx, indent) varsCtxToBuilder(&sb, ctx, indent)
return sb.String()
}
func (ctx *SimpleVarStore) ToString(opt FmtOpt) string {
var sb strings.Builder
varsCtxToBuilder(&sb, ctx, 0)
return sb.String() return sb.String()
} }