Compare commits
	
		
			No commits in common. "866de759dd2e754ee45a111427d4e726851596b2" and "24e6a293b0ef3d84224f5e7bd87c27b9ae6eed77" have entirely different histories.
		
	
	
		
			866de759dd
			...
			24e6a293b0
		
	
		
| @ -43,16 +43,16 @@ func (functor *exprFunctor) Invoke(ctx ExprContext, name string, args []any) (re | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // func CallExprFunction(parentCtx ExprContext, funcName string, params ...any) (v any, err error) {
 | func CallExprFunction(parentCtx ExprContext, funcName string, params ...any) (v any, err error) { | ||||||
| // 	ctx := cloneContext(parentCtx)
 | 	ctx := cloneContext(parentCtx) | ||||||
| // 	ctx.SetParent(parentCtx)
 | 	ctx.SetParent(parentCtx) | ||||||
| 
 | 
 | ||||||
| // 	if err == nil {
 | 	if err == nil { | ||||||
| // 		if err = checkFunctionCall(ctx, funcName, ¶ms); err == nil {
 | 		if err = checkFunctionCall(ctx, funcName, ¶ms); err == nil { | ||||||
| // 			if v, err = ctx.Call(funcName, params); err == nil {
 | 			if v, err = ctx.Call(funcName, params); err == nil { | ||||||
| // 				exportObjects(parentCtx, ctx)
 | 				exportObjects(parentCtx, ctx) | ||||||
| // 			}
 | 			} | ||||||
| // 		}
 | 		} | ||||||
| // 	}
 | 	} | ||||||
| // 	return
 | 	return | ||||||
| // }
 | } | ||||||
|  | |||||||
| @ -68,7 +68,7 @@ func createFileFunc(ctx ExprContext, name string, args []any) (result any, err e | |||||||
| 			result = &osWriter{fh: fh, writer: bufio.NewWriter(fh)} | 			result = &osWriter{fh: fh, writer: bufio.NewWriter(fh)} | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		err = errMissingFilePath(name) | 		err = errMissingFilePath("createFile") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -80,7 +80,7 @@ func openFileFunc(ctx ExprContext, name string, args []any) (result any, err err | |||||||
| 			result = &osReader{fh: fh, reader: bufio.NewReader(fh)} | 			result = &osReader{fh: fh, reader: bufio.NewReader(fh)} | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		err = errMissingFilePath(name) | 		err = errMissingFilePath("openFile") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -92,7 +92,7 @@ func appendFileFunc(ctx ExprContext, name string, args []any) (result any, err e | |||||||
| 			result = &osWriter{fh: fh, writer: bufio.NewWriter(fh)} | 			result = &osWriter{fh: fh, writer: bufio.NewWriter(fh)} | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| 		err = errMissingFilePath(name) | 		err = errMissingFilePath("appendFile") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -118,13 +118,13 @@ func closeFileFunc(ctx ExprContext, name string, args []any) (result any, err er | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 	if err == nil && (handle == nil || invalidFileHandle != nil) { | 	if err == nil && (handle == nil || invalidFileHandle != nil) { | ||||||
| 		err = errInvalidFileHandle(name, handle) | 		err = errInvalidFileHandle("closeFileFunc", handle) | ||||||
| 	} | 	} | ||||||
| 	result = err == nil | 	result = err == nil | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func fileWriteTextFunc(ctx ExprContext, name string, args []any) (result any, err error) { | func writeFileFunc(ctx ExprContext, name string, args []any) (result any, err error) { | ||||||
| 	var handle osHandle | 	var handle osHandle | ||||||
| 	var invalidFileHandle any | 	var invalidFileHandle any | ||||||
| 	var ok bool | 	var ok bool | ||||||
| @ -142,12 +142,12 @@ func fileWriteTextFunc(ctx ExprContext, name string, args []any) (result any, er | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err == nil && (handle == nil || invalidFileHandle != nil) { | 	if err == nil && (handle == nil || invalidFileHandle != nil) { | ||||||
| 		err = errInvalidFileHandle(name, invalidFileHandle) | 		err = errInvalidFileHandle("writeFileFunc", invalidFileHandle) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func fileReadTextFunc(ctx ExprContext, name string, args []any) (result any, err error) { | func readFileFunc(ctx ExprContext, name string, args []any) (result any, err error) { | ||||||
| 	var handle osHandle | 	var handle osHandle | ||||||
| 	var invalidFileHandle any | 	var invalidFileHandle any | ||||||
| 	var ok bool | 	var ok bool | ||||||
| @ -165,50 +165,23 @@ func fileReadTextFunc(ctx ExprContext, name string, args []any) (result any, err | |||||||
| 				limit = s[0] | 				limit = s[0] | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			v, err = r.reader.ReadString(limit) | 			if v, err = r.reader.ReadString(limit); err == nil { | ||||||
| 			if err == io.EOF { | 				if len(v) > 0 && v[len(v)-1] == limit { | ||||||
| 				err = nil |  | ||||||
| 			} |  | ||||||
| 			if len(v) > 0 { |  | ||||||
| 				if v[len(v)-1] == limit { |  | ||||||
| 					result = v[0 : len(v)-1] | 					result = v[0 : len(v)-1] | ||||||
| 				} else { | 				} else { | ||||||
| 					result = v | 					result = v | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
|  | 			if err == io.EOF { | ||||||
|  | 				err = nil | ||||||
|  | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			invalidFileHandle = handle | 			invalidFileHandle = handle | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err == nil && (handle == nil || invalidFileHandle != nil) { | 	if err == nil && (handle == nil || invalidFileHandle != nil) { | ||||||
| 		err = errInvalidFileHandle(name, invalidFileHandle) | 		err = errInvalidFileHandle("readFileFunc", invalidFileHandle) | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func fileReadTextAllFunc(ctx ExprContext, name string, args []any) (result any, err error) { |  | ||||||
| 	var handle osHandle |  | ||||||
| 	var invalidFileHandle any |  | ||||||
| 	var ok bool |  | ||||||
| 
 |  | ||||||
| 	result = nil |  | ||||||
| 	if handle, ok = args[0].(osHandle); !ok || args[0] == nil { |  | ||||||
| 		invalidFileHandle = args[0] |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if handle != nil { |  | ||||||
| 		if r, ok := handle.(*osReader); ok { |  | ||||||
| 			var b []byte |  | ||||||
| 			b, err = io.ReadAll(r.reader) |  | ||||||
| 			result = string(b) |  | ||||||
| 		} else { |  | ||||||
| 			invalidFileHandle = handle |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if err == nil && (handle == nil || invalidFileHandle != nil) { |  | ||||||
| 		err = errInvalidFileHandle(name, invalidFileHandle) |  | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -217,30 +190,21 @@ func ImportOsFuncs(ctx ExprContext) { | |||||||
| 	ctx.RegisterFunc("fileOpen", NewGolangFunctor(openFileFunc), TypeHandle, []ExprFuncParam{ | 	ctx.RegisterFunc("fileOpen", NewGolangFunctor(openFileFunc), TypeHandle, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamFilepath), | 		NewFuncParam(ParamFilepath), | ||||||
| 	}) | 	}) | ||||||
| 
 |  | ||||||
| 	ctx.RegisterFunc("fileAppend", NewGolangFunctor(appendFileFunc), TypeHandle, []ExprFuncParam{ | 	ctx.RegisterFunc("fileAppend", NewGolangFunctor(appendFileFunc), TypeHandle, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamFilepath), | 		NewFuncParam(ParamFilepath), | ||||||
| 	}) | 	}) | ||||||
| 
 |  | ||||||
| 	ctx.RegisterFunc("fileCreate", NewGolangFunctor(createFileFunc), TypeHandle, []ExprFuncParam{ | 	ctx.RegisterFunc("fileCreate", NewGolangFunctor(createFileFunc), TypeHandle, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamFilepath), | 		NewFuncParam(ParamFilepath), | ||||||
| 	}) | 	}) | ||||||
| 
 | 	ctx.RegisterFunc("fileWrite", NewGolangFunctor(writeFileFunc), TypeInt, []ExprFuncParam{ | ||||||
| 	ctx.RegisterFunc("fileClose", NewGolangFunctor(closeFileFunc), TypeBoolean, []ExprFuncParam{ |  | ||||||
| 		NewFuncParam(TypeHandle), |  | ||||||
| 	}) |  | ||||||
| 
 |  | ||||||
| 	ctx.RegisterFunc("fileWriteText", NewGolangFunctor(fileWriteTextFunc), TypeInt, []ExprFuncParam{ |  | ||||||
| 		NewFuncParam(TypeHandle), | 		NewFuncParam(TypeHandle), | ||||||
| 		NewFuncParamFlagDef(TypeItem, PfDefault|PfRepeat, ""), | 		NewFuncParamFlagDef(TypeItem, PfDefault|PfRepeat, ""), | ||||||
| 	}) | 	}) | ||||||
| 
 | 	ctx.RegisterFunc("fileRead", NewGolangFunctor(readFileFunc), TypeString, []ExprFuncParam{ | ||||||
| 	ctx.RegisterFunc("fileReadText", NewGolangFunctor(fileReadTextFunc), TypeString, []ExprFuncParam{ |  | ||||||
| 		NewFuncParam(TypeHandle), | 		NewFuncParam(TypeHandle), | ||||||
| 		NewFuncParamFlagDef("limitCh", PfDefault, "\n"), | 		NewFuncParamFlagDef("limitCh", PfDefault, "\n"), | ||||||
| 	}) | 	}) | ||||||
| 
 | 	ctx.RegisterFunc("fileClose", NewGolangFunctor(closeFileFunc), TypeBoolean, []ExprFuncParam{ | ||||||
| 	ctx.RegisterFunc("fileReadTextAll", NewGolangFunctor(fileReadTextAllFunc), TypeString, []ExprFuncParam{ |  | ||||||
| 		NewFuncParam(TypeHandle), | 		NewFuncParam(TypeHandle), | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  | |||||||
| @ -41,9 +41,3 @@ func exportObjects(destCtx, sourceCtx ExprContext) { | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| func exportObjectsToParent(sourceCtx ExprContext) { |  | ||||||
| 	if parentCtx := sourceCtx.GetParent(); parentCtx != nil { |  | ||||||
| 		exportObjects(parentCtx, sourceCtx) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -40,7 +40,6 @@ type ExprContext interface { | |||||||
| 	SetParent(ctx ExprContext) | 	SetParent(ctx ExprContext) | ||||||
| 	GetParent() (ctx ExprContext) | 	GetParent() (ctx ExprContext) | ||||||
| 	GetVar(varName string) (value any, exists bool) | 	GetVar(varName string) (value any, exists bool) | ||||||
| 	GetLast() any |  | ||||||
| 	SetVar(varName string, value any) | 	SetVar(varName string, value any) | ||||||
| 	UnsafeSetVar(varName string, value any) | 	UnsafeSetVar(varName string, value any) | ||||||
| 	EnumVars(func(name string) (accept bool)) (varNames []string) | 	EnumVars(func(name string) (accept bool)) (varNames []string) | ||||||
|  | |||||||
							
								
								
									
										39
									
								
								function.go
									
									
									
									
									
								
							
							
						
						
									
										39
									
								
								function.go
									
									
									
									
									
								
							| @ -199,42 +199,3 @@ func (info *funcInfo) MaxArgs() int { | |||||||
| func (info *funcInfo) Functor() Functor { | func (info *funcInfo) Functor() Functor { | ||||||
| 	return info.functor | 	return info.functor | ||||||
| } | } | ||||||
| 
 |  | ||||||
| // ----- Call a function ---
 |  | ||||||
| 
 |  | ||||||
| func checkFunctionCall(ctx ExprContext, name string, varParams *[]any) (err error) { |  | ||||||
| 	if info, exists, owner := GetFuncInfo(ctx, name); exists { |  | ||||||
| 		passedCount := len(*varParams) |  | ||||||
| 		if info.MinArgs() > passedCount { |  | ||||||
| 			err = ErrTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount) |  | ||||||
| 		} |  | ||||||
| 		for i, p := range info.Params() { |  | ||||||
| 			if i >= passedCount { |  | ||||||
| 				if !p.IsDefault() { |  | ||||||
| 					break |  | ||||||
| 				} |  | ||||||
| 				*varParams = append(*varParams, p.DefaultValue()) |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		if err == nil && info.MaxArgs() >= 0 && info.MaxArgs() < len(*varParams) { |  | ||||||
| 			err = ErrTooMuchParams(name, info.MaxArgs(), len(*varParams)) |  | ||||||
| 		} |  | ||||||
| 		if err == nil && owner != ctx { |  | ||||||
| 			ctx.RegisterFuncInfo(info) |  | ||||||
| 		} |  | ||||||
| 	} else { |  | ||||||
| 		err = fmt.Errorf("unknown function %s()", name) |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func CallFunction(parentCtx ExprContext, name string, params []any) (result any, err error) { |  | ||||||
| 	ctx := cloneContext(parentCtx) |  | ||||||
| 	ctx.SetParent(parentCtx) |  | ||||||
| 
 |  | ||||||
| 	if err = checkFunctionCall(ctx, name, ¶ms); err == nil { |  | ||||||
| 		result, err = ctx.Call(name, params) |  | ||||||
| 		exportObjectsToParent(ctx) |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ package expr | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"fmt" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| // -------- function call term
 | // -------- function call term
 | ||||||
| @ -21,7 +22,35 @@ func newFuncCallTerm(tk *Token, args []*term) *term { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // -------- eval func call
 | // -------- eval func call
 | ||||||
| func evalFuncCall(ctx ExprContext, self *term) (v any, err error) { | func checkFunctionCall(ctx ExprContext, name string, varParams *[]any) (err error) { | ||||||
|  | 	if info, exists, owner := GetFuncInfo(ctx, name); exists { | ||||||
|  | 		passedCount := len(*varParams) | ||||||
|  | 		if info.MinArgs() > passedCount { | ||||||
|  | 			err = ErrTooFewParams(name, info.MinArgs(), info.MaxArgs(), passedCount) | ||||||
|  | 		} | ||||||
|  | 		for i, p := range info.Params() { | ||||||
|  | 			if i >= passedCount { | ||||||
|  | 				if !p.IsDefault() { | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 				*varParams = append(*varParams, p.DefaultValue()) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		if err == nil && info.MaxArgs() >= 0 && info.MaxArgs() < len(*varParams) { | ||||||
|  | 			err = ErrTooMuchParams(name, info.MaxArgs(), len(*varParams)) | ||||||
|  | 		} | ||||||
|  | 		if err == nil && owner != ctx { | ||||||
|  | 			ctx.RegisterFuncInfo(info) | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		err = fmt.Errorf("unknown function %s()", name) | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func evalFuncCall(parentCtx ExprContext, self *term) (v any, err error) { | ||||||
|  | 	ctx := cloneContext(parentCtx) | ||||||
|  | 	ctx.SetParent(parentCtx) | ||||||
| 	name, _ := self.tk.Value.(string) | 	name, _ := self.tk.Value.(string) | ||||||
| 	params := make([]any, len(self.children), len(self.children)+5) | 	params := make([]any, len(self.children), len(self.children)+5) | ||||||
| 	for i, tree := range self.children { | 	for i, tree := range self.children { | ||||||
| @ -33,7 +62,11 @@ func evalFuncCall(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		v, err = CallFunction(ctx, name, params) | 		if err = checkFunctionCall(ctx, name, ¶ms); err == nil { | ||||||
|  | 			if v, err = ctx.Call(name, params); err == nil { | ||||||
|  | 				exportObjects(parentCtx, ctx) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
| @ -87,14 +87,13 @@ func evalIndex(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 				v = string(unboxedValue[index]) | 				v = string(unboxedValue[index]) | ||||||
| 			} | 			} | ||||||
| 		case *DictType: | 		case *DictType: | ||||||
| /* 			var ok bool | 			var ok bool | ||||||
| 			var indexValue any | 			var indexValue any | ||||||
| 			if indexValue, err = verifyKey(indexTerm, indexList); err == nil { | 			if indexValue, err = verifyKey(indexTerm, indexList); err == nil { | ||||||
| 				if v, ok = (*unboxedValue)[indexValue]; !ok { | 				if v, ok = (*unboxedValue)[indexValue]; !ok { | ||||||
| 					err = indexTerm.Errorf("key %v does not belong to the dictionary", rightValue) | 					err = indexTerm.Errorf("key %v does not belong to the dictionary", rightValue) | ||||||
| 				} | 				} | ||||||
| 			} */ | 			} | ||||||
| 			v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue) |  | ||||||
| 		default: | 		default: | ||||||
| 			err = self.errIncompatibleTypes(leftValue, rightValue) | 			err = self.errIncompatibleTypes(leftValue, rightValue) | ||||||
| 		} | 		} | ||||||
| @ -114,29 +113,6 @@ func evalIndex(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 		default: | 		default: | ||||||
| 			err = self.errIncompatibleTypes(leftValue, rightValue) | 			err = self.errIncompatibleTypes(leftValue, rightValue) | ||||||
| 		} | 		} | ||||||
| 	} else if IsDict(leftValue) { |  | ||||||
| 		d := leftValue.(*DictType) |  | ||||||
| 
 |  | ||||||
| 		/* 		var ok bool |  | ||||||
| 		   		var indexValue any |  | ||||||
| 		   		if indexValue, err = verifyKey(indexTerm, indexList); err == nil { |  | ||||||
| 		   			if v, ok = (*d)[indexValue]; !ok { |  | ||||||
| 		   				err = indexTerm.Errorf("key %v does not belong to the dictionary", rightValue) |  | ||||||
| 		   			} |  | ||||||
| 		   		}*/ |  | ||||||
| 		v, err = getDictItem(d, indexTerm, indexList, rightValue) |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func getDictItem(d *DictType, indexTerm *term, indexList *ListType, rightValue any) (v any, err error) { |  | ||||||
| 	var ok bool |  | ||||||
| 	var indexValue any |  | ||||||
| 
 |  | ||||||
| 	if indexValue, err = verifyKey(indexTerm, indexList); err == nil { |  | ||||||
| 		if v, ok = (*d)[indexValue]; !ok { |  | ||||||
| 			err = indexTerm.Errorf("key %v does not belong to the dictionary", rightValue) |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
| @ -29,7 +29,7 @@ func pluginExists(name string) (exists bool) { | |||||||
| 
 | 
 | ||||||
| func makePluginName(name string) (decorated string) { | func makePluginName(name string) (decorated string) { | ||||||
| 	var template string | 	var template string | ||||||
| 	if execName, err := os.Executable(); err != nil || strings.Index(execName, "debug") < 0 { | 	if execName, err := os.Executable(); err != nil || !strings.HasSuffix(execName, ".debug") { | ||||||
| 		template = "expr-%s-plugin.so" | 		template = "expr-%s-plugin.so" | ||||||
| 	} else { | 	} else { | ||||||
| 		template = "expr-%s-plugin.so.debug" | 		template = "expr-%s-plugin.so.debug" | ||||||
|  | |||||||
| @ -7,7 +7,7 @@ package expr | |||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"slices" | 	"slices" | ||||||
| 	// "strings"
 | //	"strings"
 | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| type SimpleStore struct { | type SimpleStore struct { | ||||||
| @ -50,7 +50,6 @@ func (ctx *SimpleStore) Merge(src ExprContext) { | |||||||
| 		ctx.funcStore[name], _ = src.GetFuncInfo(name) | 		ctx.funcStore[name], _ = src.GetFuncInfo(name) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 |  | ||||||
| /* | /* | ||||||
| func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | ||||||
| 	sb.WriteString("vars: {\n") | 	sb.WriteString("vars: {\n") | ||||||
| @ -166,11 +165,6 @@ func (ctx *SimpleStore) GetVar(varName string) (v any, exists bool) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (ctx *SimpleStore) GetLast() (v any) { |  | ||||||
| 	v = ctx.varStore["last"] |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func (ctx *SimpleStore) UnsafeSetVar(varName string, value any) { | func (ctx *SimpleStore) UnsafeSetVar(varName string, value any) { | ||||||
| 	// fmt.Printf("[%p] setVar(%v, %v)\n", ctx, varName, value)
 | 	// fmt.Printf("[%p] setVar(%v, %v)\n", ctx, varName, value)
 | ||||||
| 	ctx.varStore[varName] = value | 	ctx.varStore[varName] = value | ||||||
|  | |||||||
| @ -16,10 +16,10 @@ func TestFuncOs(t *testing.T) { | |||||||
| 		/*   2 */ {`builtin "os.file"; handle=fileOpen("/etc/hosts"); fileClose(handle)`, true, nil}, | 		/*   2 */ {`builtin "os.file"; handle=fileOpen("/etc/hosts"); fileClose(handle)`, true, nil}, | ||||||
| 		/*   3 */ {`builtin "os.file"; handle=fileOpen("/etc/hostsX")`, nil, errors.New(`open /etc/hostsX: no such file or directory`)}, | 		/*   3 */ {`builtin "os.file"; handle=fileOpen("/etc/hostsX")`, nil, errors.New(`open /etc/hostsX: no such file or directory`)}, | ||||||
| 		/*   4 */ {`builtin "os.file"; handle=fileCreate("/tmp/dummy"); fileClose(handle)`, true, nil}, | 		/*   4 */ {`builtin "os.file"; handle=fileCreate("/tmp/dummy"); fileClose(handle)`, true, nil}, | ||||||
| 		/*   5 */ {`builtin "os.file"; handle=fileAppend("/tmp/dummy"); fileWriteText(handle, "bye-bye"); fileClose(handle)`, true, nil}, | 		/*   5 */ {`builtin "os.file"; handle=fileAppend("/tmp/dummy"); fileWrite(handle, "bye-bye"); fileClose(handle)`, true, nil}, | ||||||
| 		/*   6 */ {`builtin "os.file"; handle=fileOpen("/tmp/dummy"); word=fileReadText(handle, "-"); fileClose(handle);word`, "bye", nil}, | 		/*   6 */ {`builtin "os.file"; handle=fileOpen("/tmp/dummy"); word=fileRead(handle, "-"); fileClose(handle);word`, "bye", nil}, | ||||||
| 		/*   7 */ {`builtin "os.file"; word=fileReadText(nil, "-")`, nil, errors.New(`fileReadText(): invalid file handle`)}, | 		/*   7 */ {`builtin "os.file"; word=fileRead(nil, "-")`, nil, errors.New(`readFileFunc(): invalid file handle`)}, | ||||||
| 		/*   7 */ {`builtin "os.file"; fileWriteText(nil, "bye")`, nil, errors.New(`fileWriteText(): invalid file handle`)}, | 		/*   7 */ {`builtin "os.file"; fileWrite(nil, "bye")`, nil, errors.New(`writeFileFunc(): invalid file handle`)}, | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	// t.Setenv("EXPR_PATH", ".")
 | 	// t.Setenv("EXPR_PATH", ".")
 | ||||||
|  | |||||||
| @ -31,7 +31,6 @@ func TestDictParser(t *testing.T) { | |||||||
| 		/*  8 */ {`D={"a":1, "b":2}; D["a"]=9; D`, map[any]any{"a": 9, "b": 2}, nil}, | 		/*  8 */ {`D={"a":1, "b":2}; D["a"]=9; D`, map[any]any{"a": 9, "b": 2}, nil}, | ||||||
| 		/*  9 */ {`D={"a":1, "b":2}; D["z"]=9; D`, map[any]any{"z": 9, "a": 1, "b": 2}, nil}, | 		/*  9 */ {`D={"a":1, "b":2}; D["z"]=9; D`, map[any]any{"z": 9, "a": 1, "b": 2}, nil}, | ||||||
| 		/* 10 */ {`D={"a":1, "b":2}; D[nil]=9`, nil, errors.New(`[1:21] index/key is nil`)}, | 		/* 10 */ {`D={"a":1, "b":2}; D[nil]=9`, nil, errors.New(`[1:21] index/key is nil`)}, | ||||||
| 		/* 11 */ {`D={"a":1, "b":2}; D["a"]`, int64(1), nil}, |  | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	succeeded := 0 | 	succeeded := 0 | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ func TestExpr(t *testing.T) { | |||||||
| 	inputs := []inputType{ | 	inputs := []inputType{ | ||||||
| 		/*   1 */ {`0?{}`, nil, nil}, | 		/*   1 */ {`0?{}`, nil, nil}, | ||||||
| 		/*   2 */ {`fact=func(n){(n)?{1}::{n*fact(n-1)}}; fact(5)`, int64(120), nil}, | 		/*   2 */ {`fact=func(n){(n)?{1}::{n*fact(n-1)}}; fact(5)`, int64(120), nil}, | ||||||
| 		/*   3 */ {`builtin "os.file"; f=fileOpen("test-file.txt"); line=fileReadText(f); fileClose(f); line`, "uno", nil}, | 		/*   3 */ {`builtin "os.file"; f=fileOpen("test-file.txt"); line=fileRead(f); fileClose(f); line`, "uno", nil}, | ||||||
| 		/*   4 */ {`mynot=func(v){int(v)?{true}::{false}}; mynot(0)`, true, nil}, | 		/*   4 */ {`mynot=func(v){int(v)?{true}::{false}}; mynot(0)`, true, nil}, | ||||||
| 		/*   5 */ {`1 ? {1} : [1+0] {3*(1+1)}`, int64(6), nil}, | 		/*   5 */ {`1 ? {1} : [1+0] {3*(1+1)}`, int64(6), nil}, | ||||||
| 		/*   6 */ {` | 		/*   6 */ {` | ||||||
|  | |||||||
| @ -14,9 +14,9 @@ func TestIteratorParser(t *testing.T) { | |||||||
| 		/*   4 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; it.reset; ()it`, int64(0), nil}, | 		/*   4 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; it.reset; ()it`, int64(0), nil}, | ||||||
| 		/*   5 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil}, | 		/*   5 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); add(it)`, int64(6), nil}, | ||||||
| 		/*   6 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil}, | 		/*   6 */ {`builtin "math.arith"; include "test-resources/iterator.expr"; it=$(ds,3); mul(it)`, int64(0), nil}, | ||||||
| 		/*   7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); mul(it)`, int64(12000), nil}, | 		/*   7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"int.list"); mul(it)`, int64(12000), nil}, | ||||||
| 		/*   8 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it++; it.index`, int64(0), nil}, | 		/*   8 */ {`include "test-resources/file-reader.expr"; it=$(ds,"int.list"); it++; it.index`, int64(0), nil}, | ||||||
| 		/*  10 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it.clean`, true, nil}, | 		/*  10 */ {`include "test-resources/file-reader.expr"; it=$(ds,"int.list"); it.clean`, true, nil}, | ||||||
| 		/*  11 */ {`it=$(1,2,3); it++`, int64(1), nil}, | 		/*  11 */ {`it=$(1,2,3); it++`, int64(1), nil}, | ||||||
| 	} | 	} | ||||||
| 	// inputs1 := []inputType{
 | 	// inputs1 := []inputType{
 | ||||||
|  | |||||||
| @ -1,22 +1,23 @@ | |||||||
| builtin ["os.file", "base"]; | builtin ["os.file", "base"]; | ||||||
| 
 | 
 | ||||||
| readInt=func(fh){ | readInt=func(fh){ | ||||||
| 	line=fileReadText(fh); | 	line=fileRead(fh); | ||||||
| 	line ? [nil] {nil} :: {int(line)} | 	line ? [nil] {nil} :: {int(line)} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ds={ | ds={ | ||||||
| 	"init":func(filename){ | 	"init":func(filename){ | ||||||
| 		fh=fileOpen(filename); | 		fh=fileOpen(filename); | ||||||
| 		fh ? [nil] {nil} :: { @current=readInt(fh) }; | 		fh ? [nil] {nil} :: { @current=readInt(fh); @prev=@current }; | ||||||
| 		fh | 		fh | ||||||
| 	}, | 	}, | ||||||
| 	"current":func(){ | 	"current":func(){ | ||||||
| 		current | 		prev | ||||||
| 	}, | 	}, | ||||||
| 	"next":func(fh){ | 	"next":func(fh){ | ||||||
| 		@current=readInt(fh); | 		current ?  | ||||||
| 		current | 			[nil] {current} | ||||||
|  | 			:: {@prev=current; @current=readInt(fh) but current} | ||||||
| 	}, | 	}, | ||||||
| 	"clean":func(fh){ | 	"clean":func(fh){ | ||||||
| 		fileClose(fh) | 		fileClose(fh) | ||||||
| @ -24,9 +25,9 @@ ds={ | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| //;f=$(ds, "int.list") | //;f=$(ds, "int.list") | ||||||
| 
 | /* | ||||||
| //;f++ | ;f++ | ||||||
| //;f++ | ;f++ | ||||||
| //;f++ | ;f++ | ||||||
| //*/ | */ | ||||||
| //;add(f) | //;add(f) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user