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 | ||||
| } | ||||
| 
 | ||||
| // func CallExprFunction(parentCtx ExprContext, funcName string, params ...any) (v any, err error) {
 | ||||
| // 	ctx := cloneContext(parentCtx)
 | ||||
| // 	ctx.SetParent(parentCtx)
 | ||||
| func CallExprFunction(parentCtx ExprContext, funcName string, params ...any) (v any, err error) { | ||||
| 	ctx := cloneContext(parentCtx) | ||||
| 	ctx.SetParent(parentCtx) | ||||
| 
 | ||||
| // 	if err == nil {
 | ||||
| // 		if err = checkFunctionCall(ctx, funcName, ¶ms); err == nil {
 | ||||
| // 			if v, err = ctx.Call(funcName, params); err == nil {
 | ||||
| // 				exportObjects(parentCtx, ctx)
 | ||||
| // 			}
 | ||||
| // 		}
 | ||||
| // 	}
 | ||||
| // 	return
 | ||||
| // }
 | ||||
| 	if err == nil { | ||||
| 		if err = checkFunctionCall(ctx, funcName, ¶ms); err == nil { | ||||
| 			if v, err = ctx.Call(funcName, params); err == nil { | ||||
| 				exportObjects(parentCtx, ctx) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	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)} | ||||
| 		} | ||||
| 	} else { | ||||
| 		err = errMissingFilePath(name) | ||||
| 		err = errMissingFilePath("createFile") | ||||
| 	} | ||||
| 	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)} | ||||
| 		} | ||||
| 	} else { | ||||
| 		err = errMissingFilePath(name) | ||||
| 		err = errMissingFilePath("openFile") | ||||
| 	} | ||||
| 	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)} | ||||
| 		} | ||||
| 	} else { | ||||
| 		err = errMissingFilePath(name) | ||||
| 		err = errMissingFilePath("appendFile") | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @ -118,13 +118,13 @@ func closeFileFunc(ctx ExprContext, name string, args []any) (result any, err er | ||||
| 		} | ||||
| 	} | ||||
| 	if err == nil && (handle == nil || invalidFileHandle != nil) { | ||||
| 		err = errInvalidFileHandle(name, handle) | ||||
| 		err = errInvalidFileHandle("closeFileFunc", handle) | ||||
| 	} | ||||
| 	result = err == nil | ||||
| 	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 invalidFileHandle any | ||||
| 	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) { | ||||
| 		err = errInvalidFileHandle(name, invalidFileHandle) | ||||
| 		err = errInvalidFileHandle("writeFileFunc", invalidFileHandle) | ||||
| 	} | ||||
| 	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 invalidFileHandle any | ||||
| 	var ok bool | ||||
| @ -165,50 +165,23 @@ func fileReadTextFunc(ctx ExprContext, name string, args []any) (result any, err | ||||
| 				limit = s[0] | ||||
| 			} | ||||
| 
 | ||||
| 			v, err = r.reader.ReadString(limit) | ||||
| 			if err == io.EOF { | ||||
| 				err = nil | ||||
| 			} | ||||
| 			if len(v) > 0 { | ||||
| 				if v[len(v)-1] == limit { | ||||
| 			if v, err = r.reader.ReadString(limit); err == nil { | ||||
| 				if len(v) > 0 && v[len(v)-1] == limit { | ||||
| 					result = v[0 : len(v)-1] | ||||
| 				} else { | ||||
| 					result = v | ||||
| 				} | ||||
| 			} | ||||
| 			if err == io.EOF { | ||||
| 				err = nil | ||||
| 			} | ||||
| 		} else { | ||||
| 			invalidFileHandle = handle | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if err == nil && (handle == nil || invalidFileHandle != nil) { | ||||
| 		err = errInvalidFileHandle(name, 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) | ||||
| 		err = errInvalidFileHandle("readFileFunc", invalidFileHandle) | ||||
| 	} | ||||
| 	return | ||||
| } | ||||
| @ -217,30 +190,21 @@ func ImportOsFuncs(ctx ExprContext) { | ||||
| 	ctx.RegisterFunc("fileOpen", NewGolangFunctor(openFileFunc), TypeHandle, []ExprFuncParam{ | ||||
| 		NewFuncParam(ParamFilepath), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("fileAppend", NewGolangFunctor(appendFileFunc), TypeHandle, []ExprFuncParam{ | ||||
| 		NewFuncParam(ParamFilepath), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("fileCreate", NewGolangFunctor(createFileFunc), TypeHandle, []ExprFuncParam{ | ||||
| 		NewFuncParam(ParamFilepath), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("fileClose", NewGolangFunctor(closeFileFunc), TypeBoolean, []ExprFuncParam{ | ||||
| 		NewFuncParam(TypeHandle), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("fileWriteText", NewGolangFunctor(fileWriteTextFunc), TypeInt, []ExprFuncParam{ | ||||
| 	ctx.RegisterFunc("fileWrite", NewGolangFunctor(writeFileFunc), TypeInt, []ExprFuncParam{ | ||||
| 		NewFuncParam(TypeHandle), | ||||
| 		NewFuncParamFlagDef(TypeItem, PfDefault|PfRepeat, ""), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("fileReadText", NewGolangFunctor(fileReadTextFunc), TypeString, []ExprFuncParam{ | ||||
| 	ctx.RegisterFunc("fileRead", NewGolangFunctor(readFileFunc), TypeString, []ExprFuncParam{ | ||||
| 		NewFuncParam(TypeHandle), | ||||
| 		NewFuncParamFlagDef("limitCh", PfDefault, "\n"), | ||||
| 	}) | ||||
| 
 | ||||
| 	ctx.RegisterFunc("fileReadTextAll", NewGolangFunctor(fileReadTextAllFunc), TypeString, []ExprFuncParam{ | ||||
| 	ctx.RegisterFunc("fileClose", NewGolangFunctor(closeFileFunc), TypeBoolean, []ExprFuncParam{ | ||||
| 		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) | ||||
| 	GetParent() (ctx ExprContext) | ||||
| 	GetVar(varName string) (value any, exists bool) | ||||
| 	GetLast() any | ||||
| 	SetVar(varName string, value any) | ||||
| 	UnsafeSetVar(varName string, value any) | ||||
| 	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 { | ||||
| 	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 ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| ) | ||||
| 
 | ||||
| // -------- function call term
 | ||||
| @ -21,7 +22,35 @@ func newFuncCallTerm(tk *Token, args []*term) *term { | ||||
| } | ||||
| 
 | ||||
| // -------- 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) | ||||
| 	params := make([]any, len(self.children), len(self.children)+5) | ||||
| 	for i, tree := range self.children { | ||||
| @ -33,7 +62,11 @@ func evalFuncCall(ctx ExprContext, self *term) (v any, err error) { | ||||
| 	} | ||||
| 
 | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| @ -87,14 +87,13 @@ func evalIndex(ctx ExprContext, self *term) (v any, err error) { | ||||
| 				v = string(unboxedValue[index]) | ||||
| 			} | ||||
| 		case *DictType: | ||||
| /* 			var ok bool | ||||
| 			var ok bool | ||||
| 			var indexValue any | ||||
| 			if indexValue, err = verifyKey(indexTerm, indexList); err == nil { | ||||
| 				if v, ok = (*unboxedValue)[indexValue]; !ok { | ||||
| 					err = indexTerm.Errorf("key %v does not belong to the dictionary", rightValue) | ||||
| 				} | ||||
| 			} */ | ||||
| 			v, err = getDictItem(unboxedValue, indexTerm, indexList, rightValue) | ||||
| 			} | ||||
| 		default: | ||||
| 			err = self.errIncompatibleTypes(leftValue, rightValue) | ||||
| 		} | ||||
| @ -114,29 +113,6 @@ func evalIndex(ctx ExprContext, self *term) (v any, err error) { | ||||
| 		default: | ||||
| 			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 | ||||
| } | ||||
|  | ||||
| @ -29,7 +29,7 @@ func pluginExists(name string) (exists bool) { | ||||
| 
 | ||||
| func makePluginName(name string) (decorated 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" | ||||
| 	} else { | ||||
| 		template = "expr-%s-plugin.so.debug" | ||||
|  | ||||
| @ -50,7 +50,6 @@ func (ctx *SimpleStore) Merge(src ExprContext) { | ||||
| 		ctx.funcStore[name], _ = src.GetFuncInfo(name) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* | ||||
| func varsCtxToBuilder(sb *strings.Builder, ctx ExprContext, indent int) { | ||||
| 	sb.WriteString("vars: {\n") | ||||
| @ -166,11 +165,6 @@ func (ctx *SimpleStore) GetVar(varName string) (v any, exists bool) { | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (ctx *SimpleStore) GetLast() (v any) { | ||||
| 	v = ctx.varStore["last"] | ||||
| 	return | ||||
| } | ||||
| 
 | ||||
| func (ctx *SimpleStore) UnsafeSetVar(varName string, value any) { | ||||
| 	// fmt.Printf("[%p] setVar(%v, %v)\n", ctx, 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}, | ||||
| 		/*   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}, | ||||
| 		/*   5 */ {`builtin "os.file"; handle=fileAppend("/tmp/dummy"); fileWriteText(handle, "bye-bye"); fileClose(handle)`, true, nil}, | ||||
| 		/*   6 */ {`builtin "os.file"; handle=fileOpen("/tmp/dummy"); word=fileReadText(handle, "-"); fileClose(handle);word`, "bye", nil}, | ||||
| 		/*   7 */ {`builtin "os.file"; word=fileReadText(nil, "-")`, nil, errors.New(`fileReadText(): invalid file handle`)}, | ||||
| 		/*   7 */ {`builtin "os.file"; fileWriteText(nil, "bye")`, nil, errors.New(`fileWriteText(): invalid file handle`)}, | ||||
| 		/*   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=fileRead(handle, "-"); fileClose(handle);word`, "bye", nil}, | ||||
| 		/*   7 */ {`builtin "os.file"; word=fileRead(nil, "-")`, nil, errors.New(`readFileFunc(): invalid file handle`)}, | ||||
| 		/*   7 */ {`builtin "os.file"; fileWrite(nil, "bye")`, nil, errors.New(`writeFileFunc(): invalid file handle`)}, | ||||
| 	} | ||||
| 
 | ||||
| 	// 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}, | ||||
| 		/*  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`)}, | ||||
| 		/* 11 */ {`D={"a":1, "b":2}; D["a"]`, int64(1), nil}, | ||||
| 	} | ||||
| 
 | ||||
| 	succeeded := 0 | ||||
|  | ||||
| @ -14,7 +14,7 @@ func TestExpr(t *testing.T) { | ||||
| 	inputs := []inputType{ | ||||
| 		/*   1 */ {`0?{}`, nil, 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}, | ||||
| 		/*   5 */ {`1 ? {1} : [1+0] {3*(1+1)}`, int64(6), nil}, | ||||
| 		/*   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}, | ||||
| 		/*   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}, | ||||
| 		/*   7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"test-resources/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}, | ||||
| 		/*  10 */ {`include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); it.clean`, true, 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,"int.list"); it++; it.index`, int64(0), 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}, | ||||
| 	} | ||||
| 	// inputs1 := []inputType{
 | ||||
|  | ||||
| @ -1,22 +1,23 @@ | ||||
| builtin ["os.file", "base"]; | ||||
| 
 | ||||
| readInt=func(fh){ | ||||
| 	line=fileReadText(fh); | ||||
| 	line=fileRead(fh); | ||||
| 	line ? [nil] {nil} :: {int(line)} | ||||
| }; | ||||
| 
 | ||||
| ds={ | ||||
| 	"init":func(filename){ | ||||
| 		fh=fileOpen(filename); | ||||
| 		fh ? [nil] {nil} :: { @current=readInt(fh) }; | ||||
| 		fh ? [nil] {nil} :: { @current=readInt(fh); @prev=@current }; | ||||
| 		fh | ||||
| 	}, | ||||
| 	"current":func(){ | ||||
| 		current | ||||
| 		prev | ||||
| 	}, | ||||
| 	"next":func(fh){ | ||||
| 		@current=readInt(fh); | ||||
| 		current | ||||
| 		current ?  | ||||
| 			[nil] {current} | ||||
| 			:: {@prev=current; @current=readInt(fh) but current} | ||||
| 	}, | ||||
| 	"clean":func(fh){ | ||||
| 		fileClose(fh) | ||||
| @ -24,9 +25,9 @@ ds={ | ||||
| } | ||||
| 
 | ||||
| //;f=$(ds, "int.list") | ||||
| 
 | ||||
| //;f++ | ||||
| //;f++ | ||||
| //;f++ | ||||
| //*/ | ||||
| /* | ||||
| ;f++ | ||||
| ;f++ | ||||
| ;f++ | ||||
| */ | ||||
| //;add(f) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user