Compare commits
6 Commits
2c55167dd0
...
0bca3333aa
Author | SHA1 | Date | |
---|---|---|---|
0bca3333aa | |||
02b7a6df6c | |||
8d9963207e | |||
f9486fa1bd | |||
360ebce015 | |||
dc9eca83e8 |
@ -30,7 +30,7 @@ func importGeneral(ctx ExprContext, name string, args []any) (result any, err er
|
||||
|
||||
dirList = addEnvImportDirs(dirList)
|
||||
dirList = addPresetImportDirs(ctx, dirList)
|
||||
result, err = doImport(ctx, name, dirList, NewFlatArrayIterator(args))
|
||||
result, err = doImport(ctx, name, dirList, NewArrayIterator(args))
|
||||
return
|
||||
}
|
||||
|
||||
|
12
func-math.go
12
func-math.go
@ -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 {
|
||||
break
|
||||
}
|
||||
if array, ok := v.(*ListType); ok {
|
||||
if v, err = doAdd(ctx, name, NewFlatArrayIterator(*array)); err != nil {
|
||||
if list, ok := v.(*ListType); ok {
|
||||
if v, err = doAdd(ctx, name, NewListIterator(list)); err != nil {
|
||||
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) {
|
||||
result, err = doAdd(ctx, name, NewFlatArrayIterator(args))
|
||||
result, err = doAdd(ctx, name, NewArrayIterator(args))
|
||||
return
|
||||
}
|
||||
|
||||
@ -113,8 +113,8 @@ func doMul(ctx ExprContext, name string, it Iterator) (result any, err error) {
|
||||
break
|
||||
}
|
||||
|
||||
if array, ok := v.(*ListType); ok {
|
||||
if v, err = doMul(ctx, name, NewFlatArrayIterator(*array)); err != nil {
|
||||
if list, ok := v.(*ListType); ok {
|
||||
if v, err = doMul(ctx, name, NewListIterator(list)); err != nil {
|
||||
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) {
|
||||
result, err = doMul(ctx, name, NewFlatArrayIterator(args))
|
||||
result, err = doMul(ctx, name, NewArrayIterator(args))
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -39,15 +39,15 @@ func joinStrFunc(ctx ExprContext, name string, args []any) (result any, err erro
|
||||
if len(args) == 1 {
|
||||
result = ""
|
||||
} else if len(args) == 2 {
|
||||
if ls, ok := args[1].([]any); ok {
|
||||
result, err = doJoinStr(name, sep, NewFlatArrayIterator(ls))
|
||||
if ls, ok := args[1].(*ListType); ok {
|
||||
result, err = doJoinStr(name, sep, NewListIterator(ls))
|
||||
} else if it, ok := args[1].(Iterator); ok {
|
||||
result, err = doJoinStr(name, sep, it)
|
||||
} else {
|
||||
err = errInvalidParameterValue(name, paramParts, args[1])
|
||||
}
|
||||
} else {
|
||||
result, err = doJoinStr(name, sep, NewFlatArrayIterator(args[1:]))
|
||||
result, err = doJoinStr(name, sep, NewArrayIterator(args[1:]))
|
||||
}
|
||||
} else {
|
||||
err = errWrongParamType(name, paramSeparator, typeString, args[0])
|
||||
|
42
iter-list.go
42
iter-list.go
@ -6,33 +6,53 @@ package expr
|
||||
|
||||
import "io"
|
||||
|
||||
type FlatArrayIterator struct {
|
||||
a ListType
|
||||
type ListIterator struct {
|
||||
a *ListType
|
||||
index int
|
||||
}
|
||||
|
||||
func NewFlatArrayIterator(array ListType) *FlatArrayIterator {
|
||||
return &FlatArrayIterator{a: array, index: 0}
|
||||
func NewListIterator(list *ListType) *ListIterator {
|
||||
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
|
||||
}
|
||||
|
||||
func (it *FlatArrayIterator) CallOperation(name string, args []any) (any, error) {
|
||||
func (it *ListIterator) CallOperation(name string, args []any) (any, error) {
|
||||
return nil, errNoOperation(name)
|
||||
}
|
||||
|
||||
func (it *FlatArrayIterator) Current() (item any, err error) {
|
||||
if it.index >= 0 && it.index < len(it.a) {
|
||||
item = it.a[it.index]
|
||||
func (it *ListIterator) Current() (item any, err error) {
|
||||
a := *(it.a)
|
||||
if it.index >= 0 && it.index < len(a) {
|
||||
item = a[it.index]
|
||||
} else {
|
||||
err = io.EOF
|
||||
}
|
||||
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 {
|
||||
it.index++
|
||||
}
|
||||
@ -45,6 +65,6 @@ func (it *FlatArrayIterator) Next() (item any, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (it *FlatArrayIterator) Index() int {
|
||||
func (it *ListIterator) Index() int {
|
||||
return it.index - 1
|
||||
}
|
||||
|
@ -42,6 +42,10 @@ func (ls *ListType) ToString(opt FmtOpt) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (ls *ListType) String() string {
|
||||
return ls.ToString(0)
|
||||
}
|
||||
|
||||
// -------- list term
|
||||
func newListTermA(args ...*term) *term {
|
||||
return newListTerm(args)
|
||||
|
@ -4,6 +4,8 @@
|
||||
// operator-builtin.go
|
||||
package expr
|
||||
|
||||
import "io"
|
||||
|
||||
//-------- builtin 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) {
|
||||
var rightValue any
|
||||
var childValue any
|
||||
|
||||
if rightValue, err = self.evalPrefix(ctx); err != nil {
|
||||
if childValue, err = self.evalPrefix(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
count := 0
|
||||
if isList(rightValue) {
|
||||
list, _ := rightValue.([]any)
|
||||
for i, moduleSpec := range list {
|
||||
if isString(childValue) {
|
||||
module, _ := childValue.(string)
|
||||
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 ImportInContext(ctx, module) {
|
||||
count++
|
||||
@ -35,15 +41,13 @@ func evalBuiltin(ctx ExprContext, self *term) (v any, err error) {
|
||||
break
|
||||
}
|
||||
} 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
|
||||
}
|
||||
}
|
||||
} else if isString(rightValue) {
|
||||
module, _ := rightValue.(string)
|
||||
count, err = ImportInContextByGlobPattern(ctx, module)
|
||||
} else {
|
||||
err = self.errIncompatibleType(rightValue)
|
||||
if err == io.EOF {
|
||||
err = nil
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
v = count
|
||||
|
@ -31,6 +31,9 @@ func evalContextValue(ctx ExprContext, self *term) (v any, err error) {
|
||||
}
|
||||
|
||||
if sourceCtx != nil {
|
||||
if formatter, ok := ctx.(Formatter); ok {
|
||||
v = formatter.ToString(0)
|
||||
} else {
|
||||
keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' })
|
||||
d := make(map[string]any)
|
||||
for _, key := range keys {
|
||||
@ -38,9 +41,10 @@ func evalContextValue(ctx ExprContext, self *term) (v any, err error) {
|
||||
}
|
||||
keys = sourceCtx.EnumFuncs(func(name string) bool { return true })
|
||||
for _, key := range keys {
|
||||
d[key], _ =sourceCtx.GetFuncInfo(key)
|
||||
d[key], _ = sourceCtx.GetFuncInfo(key)
|
||||
}
|
||||
v = d
|
||||
}
|
||||
} else {
|
||||
err = self.errIncompatibleType(childValue)
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ func TestParser(t *testing.T) {
|
||||
/* 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},
|
||||
/* 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},
|
||||
/* 115 */ {`x="hello"; x ?? "default"`, "hello", 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},
|
||||
/* 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},
|
||||
/* 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},
|
||||
/* 128 */ {`1 ? {"a"} : {"b"}`, "b", 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 "}"`)},
|
||||
/* 141 */ {`{"key":}`, nil, errors.New(`[1:9] expected dictionary value, got "}"`)},
|
||||
/* 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
|
||||
|
||||
|
@ -4,7 +4,10 @@
|
||||
// simple-func-store.go
|
||||
package expr
|
||||
|
||||
import "fmt"
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type SimpleFuncStore struct {
|
||||
SimpleVarStore
|
||||
@ -18,6 +21,29 @@ type funcInfo struct {
|
||||
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 {
|
||||
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) {
|
||||
info, exists = ctx.funcStore[name]
|
||||
return
|
||||
|
@ -79,34 +79,43 @@ func (ctx *SimpleVarStore) EnumFuncs(acceptor func(name string) (accept bool)) (
|
||||
return
|
||||
}
|
||||
|
||||
func CtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) {
|
||||
sb.WriteString("{\n")
|
||||
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] != '_' }) {
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
sb.WriteByte(',')
|
||||
sb.WriteByte('\n')
|
||||
}
|
||||
|
||||
value, _ := ctx.GetVar(name)
|
||||
sb.WriteString(strings.Repeat("\t", indent+1))
|
||||
sb.WriteString(name)
|
||||
sb.WriteString("=")
|
||||
if _, ok := value.(Functor); ok {
|
||||
sb.WriteString(": func(){}")
|
||||
sb.WriteString(": ")
|
||||
if f, ok := value.(Formatter); ok {
|
||||
sb.WriteString(f.ToString(0))
|
||||
} else if _, ok = value.(Functor); ok {
|
||||
sb.WriteString("func(){}")
|
||||
} else if _, ok = value.(map[any]any); ok {
|
||||
sb.WriteString("dict{}")
|
||||
} else {
|
||||
sb.WriteString(fmt.Sprintf("%v", value))
|
||||
}
|
||||
if first {
|
||||
first = false
|
||||
} else {
|
||||
sb.WriteByte(',')
|
||||
}
|
||||
sb.WriteByte('\n')
|
||||
}
|
||||
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
|
||||
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()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user