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,16 +31,20 @@ func evalContextValue(ctx ExprContext, self *term) (v any, err error) { | ||||
| 	} | ||||
| 
 | ||||
| 	if sourceCtx != nil { | ||||
| 		keys := sourceCtx.EnumVars(func(name string) bool { return name[0] != '_' }) | ||||
| 		d := make(map[string]any) | ||||
| 		for _, key := range keys { | ||||
| 			d[key], _ = sourceCtx.GetVar(key) | ||||
| 		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 { | ||||
| 				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 { | ||||
| 		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