Compare commits
	
		
			4 Commits
		
	
	
		
			33d70d6d1a
			...
			1757298eb4
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1757298eb4 | |||
| 54041552d4 | |||
| 5302907dcf | |||
| eb4b17f078 | 
| @ -42,3 +42,17 @@ func (functor *exprFunctor) Invoke(ctx ExprContext, name string, args []any) (re | |||||||
| 	result, err = functor.expr.Eval(ctx) | 	result, err = functor.expr.Eval(ctx) | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | 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 | ||||||
|  | } | ||||||
|  | |||||||
| @ -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("openFile") | 		err = errMissingFilePath("appendFile") | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| @ -187,24 +187,24 @@ func readFileFunc(ctx ExprContext, name string, args []any) (result any, err err | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func ImportOsFuncs(ctx ExprContext) { | func ImportOsFuncs(ctx ExprContext) { | ||||||
| 	ctx.RegisterFunc("openFile", NewGolangFunctor(openFileFunc), TypeHandle, []ExprFuncParam{ | 	ctx.RegisterFunc("fileOpen", NewGolangFunctor(openFileFunc), TypeHandle, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamFilepath), | 		NewFuncParam(ParamFilepath), | ||||||
| 	}) | 	}) | ||||||
| 	ctx.RegisterFunc("appendFile", NewGolangFunctor(appendFileFunc), TypeHandle, []ExprFuncParam{ | 	ctx.RegisterFunc("fileAppend", NewGolangFunctor(appendFileFunc), TypeHandle, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamFilepath), | 		NewFuncParam(ParamFilepath), | ||||||
| 	}) | 	}) | ||||||
| 	ctx.RegisterFunc("createFile", NewGolangFunctor(createFileFunc), TypeHandle, []ExprFuncParam{ | 	ctx.RegisterFunc("fileCreate", NewGolangFunctor(createFileFunc), TypeHandle, []ExprFuncParam{ | ||||||
| 		NewFuncParam(ParamFilepath), | 		NewFuncParam(ParamFilepath), | ||||||
| 	}) | 	}) | ||||||
| 	ctx.RegisterFunc("writeFile", NewGolangFunctor(writeFileFunc), TypeInt, []ExprFuncParam{ | 	ctx.RegisterFunc("fileWrite", NewGolangFunctor(writeFileFunc), TypeInt, []ExprFuncParam{ | ||||||
| 		NewFuncParam(TypeHandle), | 		NewFuncParam(TypeHandle), | ||||||
| 		NewFuncParamFlagDef(TypeItem, PfDefault|PfRepeat, ""), | 		NewFuncParamFlagDef(TypeItem, PfDefault|PfRepeat, ""), | ||||||
| 	}) | 	}) | ||||||
| 	ctx.RegisterFunc("readFile", NewGolangFunctor(readFileFunc), TypeString, []ExprFuncParam{ | 	ctx.RegisterFunc("fileRead", NewGolangFunctor(readFileFunc), TypeString, []ExprFuncParam{ | ||||||
| 		NewFuncParam(TypeHandle), | 		NewFuncParam(TypeHandle), | ||||||
| 		NewFuncParamFlagDef("limitCh", PfDefault, "\n"), | 		NewFuncParamFlagDef("limitCh", PfDefault, "\n"), | ||||||
| 	}) | 	}) | ||||||
| 	ctx.RegisterFunc("closeFile", NewGolangFunctor(closeFileFunc), TypeBoolean, []ExprFuncParam{ | 	ctx.RegisterFunc("fileClose", NewGolangFunctor(closeFileFunc), TypeBoolean, []ExprFuncParam{ | ||||||
| 		NewFuncParam(TypeHandle), | 		NewFuncParam(TypeHandle), | ||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  | |||||||
| @ -25,11 +25,11 @@ func errTooMuchParams(funcName string, maxArgs, argCount int) (err error) { | |||||||
| // --- General errors
 | // --- General errors
 | ||||||
| 
 | 
 | ||||||
| func errCantConvert(funcName string, value any, kind string) error { | func errCantConvert(funcName string, value any, kind string) error { | ||||||
| 	return fmt.Errorf("%s(): can't convert %s to %s", funcName, typeName(value), kind) | 	return fmt.Errorf("%s(): can't convert %s to %s", funcName, TypeName(value), kind) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errExpectedGot(funcName string, kind string, value any) error { | func errExpectedGot(funcName string, kind string, value any) error { | ||||||
| 	return fmt.Errorf("%s() expected %s, got %s (%v)", funcName, kind, typeName(value), value) | 	return fmt.Errorf("%s() expected %s, got %s (%v)", funcName, kind, TypeName(value), value) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errFuncDivisionByZero(funcName string) error { | func errFuncDivisionByZero(funcName string) error { | ||||||
| @ -47,9 +47,9 @@ func errMissingRequiredParameter(funcName, paramName string) error { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errInvalidParameterValue(funcName, paramName string, paramValue any) error { | func errInvalidParameterValue(funcName, paramName string, paramValue any) error { | ||||||
| 	return fmt.Errorf("%s() invalid value %s (%v) for parameter %q", funcName, typeName(paramValue), paramValue, paramName) | 	return fmt.Errorf("%s() invalid value %s (%v) for parameter %q", funcName, TypeName(paramValue), paramValue, paramName) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func errWrongParamType(funcName, paramName, paramType string, paramValue any) error { | func errWrongParamType(funcName, paramName, paramType string, paramValue any) error { | ||||||
| 	return fmt.Errorf("%s() the %q parameter must be a %s, got a %s (%v)", funcName, paramName, paramType, typeName(paramValue), paramValue) | 	return fmt.Errorf("%s() the %q parameter must be a %s, got a %s (%v)", funcName, paramName, paramType, TypeName(paramValue), paramValue) | ||||||
| } | } | ||||||
|  | |||||||
| @ -12,6 +12,12 @@ import ( | |||||||
| 
 | 
 | ||||||
| type DictType map[any]any | type DictType map[any]any | ||||||
| 
 | 
 | ||||||
|  | func MakeDict() (dict *DictType) { | ||||||
|  | 	d := make(DictType) | ||||||
|  | 	dict = &d | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func newDict(dictAny map[any]*term) (dict *DictType) { | func newDict(dictAny map[any]*term) (dict *DictType) { | ||||||
| 	var d DictType | 	var d DictType | ||||||
| 	if dictAny != nil { | 	if dictAny != nil { | ||||||
| @ -127,4 +133,3 @@ func (dict *DictType) setItem(key any, value any) (err error) { | |||||||
| 	(*dict)[key] = value | 	(*dict)[key] = value | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 |  | ||||||
|  | |||||||
| @ -51,7 +51,7 @@ type Typer interface { | |||||||
| 	TypeName() string | 	TypeName() string | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func typeName(v any) (name string) { | func TypeName(v any) (name string) { | ||||||
| 	if v == nil { | 	if v == nil { | ||||||
| 		name = "nil" | 		name = "nil" | ||||||
| 	} else if typer, ok := v.(Typer); ok { | 	} else if typer, ok := v.(Typer); ok { | ||||||
|  | |||||||
| @ -20,7 +20,7 @@ const ( | |||||||
| 
 | 
 | ||||||
| func checkStringParamExpected(funcName string, paramValue any, paramPos int) (err error) { | func checkStringParamExpected(funcName string, paramValue any, paramPos int) (err error) { | ||||||
| 	if !(IsString(paramValue) /*|| isList(paramValue)*/) { | 	if !(IsString(paramValue) /*|| isList(paramValue)*/) { | ||||||
| 		err = fmt.Errorf("%s(): param nr %d has wrong type %s, string expected", funcName, paramPos+1, typeName(paramValue)) | 		err = fmt.Errorf("%s(): param nr %d has wrong type %s, string expected", funcName, paramPos+1, TypeName(paramValue)) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ func assignCollectionItem(ctx ExprContext, collectionTerm, keyListTerm *term, va | |||||||
| 	if keyListValue, err = keyListTerm.compute(ctx); err != nil { | 	if keyListValue, err = keyListTerm.compute(ctx); err != nil { | ||||||
| 		return | 		return | ||||||
| 	} else if keyList, ok = keyListValue.(*ListType); !ok || len(*keyList) != 1 { | 	} else if keyList, ok = keyListValue.(*ListType); !ok || len(*keyList) != 1 { | ||||||
| 		err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, typeName(keyListValue)) | 		err = keyListTerm.Errorf("index/key specification expected, got %v [%s]", keyListValue, TypeName(keyListValue)) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 	if keyValue = (*keyList)[0]; keyValue == nil { | 	if keyValue = (*keyList)[0]; keyValue == nil { | ||||||
| @ -41,7 +41,7 @@ func assignCollectionItem(ctx ExprContext, collectionTerm, keyListTerm *term, va | |||||||
| 		if index, ok := keyValue.(int64); ok { | 		if index, ok := keyValue.(int64); ok { | ||||||
| 			err = collection.setItem(index, value) | 			err = collection.setItem(index, value) | ||||||
| 		} else { | 		} else { | ||||||
| 			err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, typeName(keyValue)) | 			err = keyListTerm.Errorf("integer expected, got %v [%s]", keyValue, TypeName(keyValue)) | ||||||
| 		} | 		} | ||||||
| 	case *DictType: | 	case *DictType: | ||||||
| 		err = collection.setItem(keyValue, value) | 		err = collection.setItem(keyValue, value) | ||||||
|  | |||||||
| @ -41,7 +41,7 @@ func evalBuiltin(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 					break | 					break | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				err = self.Errorf("expected string at item nr %d, got %s", it.Index()+1, typeName(moduleSpec)) | 				err = self.Errorf("expected string at item nr %d, got %s", it.Index()+1, TypeName(moduleSpec)) | ||||||
| 				break | 				break | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  | |||||||
| @ -5,9 +5,7 @@ | |||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" |  | ||||||
| 	"io" | 	"io" | ||||||
| 	"plugin" |  | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| //-------- plugin term
 | //-------- plugin term
 | ||||||
| @ -22,48 +20,6 @@ func newPluginTerm(tk *Token) (inst *term) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func importPlugin(ctx ExprContext, dirList []string, name string) (err error) { |  | ||||||
| 	var filePath string |  | ||||||
| 	var p *plugin.Plugin |  | ||||||
| 	var sym plugin.Symbol |  | ||||||
| 	var moduleName string |  | ||||||
| 	var importFunc func(ctx ExprContext) |  | ||||||
| 	var ok bool |  | ||||||
| 
 |  | ||||||
| 	decoratedName := fmt.Sprintf("expr-%s-plugin.so", name) |  | ||||||
| 
 |  | ||||||
| 	if filePath, err = makeFilepath(decoratedName, dirList); err != nil { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if p, err = plugin.Open(filePath); err != nil { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if sym, err = p.Lookup("MODULE_NAME"); err != nil { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if moduleName = *sym.(*string); moduleName == "" { |  | ||||||
| 		err = fmt.Errorf("plugin %q does not provide a valid module name", decoratedName) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if sym, err = p.Lookup("ImportFuncs"); err != nil { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	if importFunc, ok = sym.(func(ExprContext)); !ok { |  | ||||||
| 		err = fmt.Errorf("plugin %q does not provide a valid import function", decoratedName) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	registerPlugin(moduleName, p) |  | ||||||
| 	importFunc(globalCtx) |  | ||||||
| 
 |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func evalPlugin(ctx ExprContext, self *term) (v any, err error) { | func evalPlugin(ctx ExprContext, self *term) (v any, err error) { | ||||||
| 	var childValue any | 	var childValue any | ||||||
| 	var moduleSpec any | 	var moduleSpec any | ||||||
| @ -77,12 +33,12 @@ func evalPlugin(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 	it := NewAnyIterator(childValue) | 	it := NewAnyIterator(childValue) | ||||||
| 	for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() { | 	for moduleSpec, err = it.Next(); err == nil; moduleSpec, err = it.Next() { | ||||||
| 		if module, ok := moduleSpec.(string); ok { | 		if module, ok := moduleSpec.(string); ok { | ||||||
| 			if err = importPlugin(ctx, dirList, module); err != nil { | 			if err = importPlugin(dirList, module); err != nil { | ||||||
| 				break | 				break | ||||||
| 			} | 			} | ||||||
| 			count++ | 			count++ | ||||||
| 		} else { | 		} else { | ||||||
| 			err = self.Errorf("expected string as item nr %d, got %s", it.Index()+1, typeName(moduleSpec)) | 			err = self.Errorf("expected string as item nr %d, got %s", it.Index()+1, TypeName(moduleSpec)) | ||||||
| 			break | 			break | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | |||||||
							
								
								
									
										64
									
								
								plugins.go
									
									
									
									
									
								
							
							
						
						
									
										64
									
								
								plugins.go
									
									
									
									
									
								
							| @ -25,6 +25,70 @@ func pluginExists(name string) (exists bool) { | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func importPlugin( /*ctx ExprContext,*/ dirList []string, name string) (err error) { | ||||||
|  | 	var filePath string | ||||||
|  | 	var p *plugin.Plugin | ||||||
|  | 	var sym plugin.Symbol | ||||||
|  | 	var moduleName string | ||||||
|  | 	var importFunc func(ExprContext) | ||||||
|  | 	var ok bool | ||||||
|  | 
 | ||||||
|  | 	decoratedName := fmt.Sprintf("expr-%s-plugin.so", name) | ||||||
|  | 
 | ||||||
|  | 	if filePath, err = makeFilepath(decoratedName, dirList); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if p, err = plugin.Open(filePath); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if sym, err = p.Lookup("MODULE_NAME"); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if moduleName = *sym.(*string); moduleName == "" { | ||||||
|  | 		err = fmt.Errorf("plugin %q does not provide a valid module name", decoratedName) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if sym, err = p.Lookup("DEPENDENCIES"); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if deps := *sym.(*[]string); len(deps) > 0 { | ||||||
|  | 		// var count int
 | ||||||
|  | 		if err = loadModules(dirList, deps); err != nil { | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if sym, err = p.Lookup("ImportFuncs"); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	if importFunc, ok = sym.(func(ExprContext)); !ok { | ||||||
|  | 		err = fmt.Errorf("plugin %q does not provide a valid import function", decoratedName) | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	registerPlugin(moduleName, p) | ||||||
|  | 	importFunc(globalCtx) | ||||||
|  | 
 | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func loadModules(dirList []string, moduleNames []string) (err error) { | ||||||
|  | 	for _, name := range moduleNames { | ||||||
|  | 		if err1 := importPlugin(dirList, name); err1 != nil { | ||||||
|  | 			if !ImportInContext(name) { | ||||||
|  | 				err = err1 | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func init() { | func init() { | ||||||
| 	pluginRegister = make(map[string]*plugin.Plugin) | 	pluginRegister = make(map[string]*plugin.Plugin) | ||||||
| } | } | ||||||
|  | |||||||
| @ -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=openFile("test-file.txt"); line=readFile(f); closeFile(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 */ {` | ||||||
|  | |||||||
| @ -13,13 +13,13 @@ func TestFuncOs(t *testing.T) { | |||||||
| 	section := "Func-OS" | 	section := "Func-OS" | ||||||
| 	inputs := []inputType{ | 	inputs := []inputType{ | ||||||
| 		/*   1 */ {`builtin "os.file"`, int64(1), nil}, | 		/*   1 */ {`builtin "os.file"`, int64(1), nil}, | ||||||
| 		/*   2 */ {`builtin "os.file"; handle=openFile("/etc/hosts"); closeFile(handle)`, true, nil}, | 		/*   2 */ {`builtin "os.file"; handle=fileOpen("/etc/hosts"); fileClose(handle)`, true, nil}, | ||||||
| 		/*   3 */ {`builtin "os.file"; handle=openFile("/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=createFile("/tmp/dummy"); closeFile(handle)`, true, nil}, | 		/*   4 */ {`builtin "os.file"; handle=fileCreate("/tmp/dummy"); fileClose(handle)`, true, nil}, | ||||||
| 		/*   5 */ {`builtin "os.file"; handle=appendFile("/tmp/dummy"); writeFile(handle, "bye-bye"); closeFile(handle)`, true, nil}, | 		/*   5 */ {`builtin "os.file"; handle=fileAppend("/tmp/dummy"); fileWrite(handle, "bye-bye"); fileClose(handle)`, true, nil}, | ||||||
| 		/*   6 */ {`builtin "os.file"; handle=openFile("/tmp/dummy"); word=readFile(handle, "-"); closeFile(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=readFile(nil, "-")`, nil, errors.New(`readFileFunc(): invalid file handle`)}, | 		/*   7 */ {`builtin "os.file"; word=fileRead(nil, "-")`, nil, errors.New(`readFileFunc(): invalid file handle`)}, | ||||||
| 		/*   7 */ {`builtin "os.file"; writeFile(nil, "bye")`, nil, errors.New(`writeFileFunc(): 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", ".")
 | ||||||
|  | |||||||
| @ -8,15 +8,15 @@ import "testing" | |||||||
| 
 | 
 | ||||||
| func TestIteratorParser(t *testing.T) { | func TestIteratorParser(t *testing.T) { | ||||||
| 	inputs := []inputType{ | 	inputs := []inputType{ | ||||||
| 		/*   1 */ {`include "iterator.expr"; it=$(ds,3); ()it`, int64(0), nil}, | 		/*   1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); ()it`, int64(0), nil}, | ||||||
| 		/*   2 */ {`include "iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil}, | 		/*   2 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++`, int64(1), nil}, | ||||||
| 		/*   3 */ {`include "iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(2), nil}, | 		/*   3 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(2), nil}, | ||||||
| 		/*   4 */ {`include "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 "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 "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 "file-reader.expr"; it=$(ds,"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 "file-reader.expr"; it=$(ds,"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 "file-reader.expr"; it=$(ds,"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{
 | ||||||
|  | |||||||
| @ -203,7 +203,7 @@ func doTest(t *testing.T, section string, input *inputType, count int) (good boo | |||||||
| 	eq := reflect.DeepEqual(gotResult, input.wantResult) | 	eq := reflect.DeepEqual(gotResult, input.wantResult) | ||||||
| 
 | 
 | ||||||
| 	if !eq /*gotResult != input.wantResult*/ { | 	if !eq /*gotResult != input.wantResult*/ { | ||||||
| 		t.Errorf("%d: %q -> result = %v [%s], want = %v [%s]", count, input.source, gotResult, typeName(gotResult), input.wantResult, typeName(input.wantResult)) | 		t.Errorf("%d: %q -> result = %v [%s], want = %v [%s]", count, input.source, gotResult, TypeName(gotResult), input.wantResult, TypeName(input.wantResult)) | ||||||
| 		good = false | 		good = false | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								term.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								term.go
									
									
									
									
									
								
							| @ -156,15 +156,15 @@ func (self *term) toInt(computedValue any, valueDescription string) (i int, err | |||||||
| 	if index64, ok := computedValue.(int64); ok { | 	if index64, ok := computedValue.(int64); ok { | ||||||
| 		i = int(index64) | 		i = int(index64) | ||||||
| 	} else { | 	} else { | ||||||
| 		err = self.Errorf("%s, got %s (%v)", valueDescription, typeName(computedValue), computedValue) | 		err = self.Errorf("%s, got %s (%v)", valueDescription, TypeName(computedValue), computedValue) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (self *term) errIncompatibleTypes(leftValue, rightValue any) error { | func (self *term) errIncompatibleTypes(leftValue, rightValue any) error { | ||||||
| 	leftType := typeName(leftValue) | 	leftType := TypeName(leftValue) | ||||||
| 	leftText := getFormatted(leftValue, Truncate) | 	leftText := getFormatted(leftValue, Truncate) | ||||||
| 	rightType := typeName(rightValue) | 	rightType := TypeName(rightValue) | ||||||
| 	rightText := getFormatted(rightValue, Truncate) | 	rightText := getFormatted(rightValue, Truncate) | ||||||
| 	return self.tk.Errorf( | 	return self.tk.Errorf( | ||||||
| 		"left operand '%s' [%s] and right operand '%s' [%s] are not compatible with operator %q", | 		"left operand '%s' [%s] and right operand '%s' [%s] are not compatible with operator %q", | ||||||
| @ -176,7 +176,7 @@ func (self *term) errIncompatibleTypes(leftValue, rightValue any) error { | |||||||
| func (self *term) errIncompatibleType(value any) error { | func (self *term) errIncompatibleType(value any) error { | ||||||
| 	return self.tk.Errorf( | 	return self.tk.Errorf( | ||||||
| 		"prefix/postfix operator %q do not support operand '%v' [%s]", | 		"prefix/postfix operator %q do not support operand '%v' [%s]", | ||||||
| 		self.source(), value, typeName(value)) | 		self.source(), value, TypeName(value)) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (self *term) Errorf(template string, args ...any) (err error) { | func (self *term) Errorf(template string, args ...any) (err error) { | ||||||
|  | |||||||
| @ -1,13 +1,13 @@ | |||||||
| builtin ["os.file", "base"]; | builtin ["os.file", "base"]; | ||||||
| 
 | 
 | ||||||
| readInt=func(fh){ | readInt=func(fh){ | ||||||
| 	line=readFile(fh); | 	line=fileRead(fh); | ||||||
| 	line ? [nil] {nil} :: {int(line)} | 	line ? [nil] {nil} :: {int(line)} | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| ds={ | ds={ | ||||||
| 	"init":func(filename){ | 	"init":func(filename){ | ||||||
| 		fh=openFile(filename); | 		fh=fileOpen(filename); | ||||||
| 		fh ? [nil] {nil} :: { @current=readInt(fh); @prev=@current }; | 		fh ? [nil] {nil} :: { @current=readInt(fh); @prev=@current }; | ||||||
| 		fh | 		fh | ||||||
| 	}, | 	}, | ||||||
| @ -20,7 +20,7 @@ ds={ | |||||||
| 			:: {@prev=current; @current=readInt(fh) but current} | 			:: {@prev=current; @current=readInt(fh) but current} | ||||||
| 	}, | 	}, | ||||||
| 	"clean":func(fh){ | 	"clean":func(fh){ | ||||||
| 		closeFile(fh) | 		fileClose(fh) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
							
								
								
									
										2
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								utils.go
									
									
									
									
									
								
							| @ -207,7 +207,7 @@ func toInt(value any, description string) (i int, err error) { | |||||||
| 	} else if valueInt, ok := value.(int); ok { | 	} else if valueInt, ok := value.(int); ok { | ||||||
| 		i = valueInt | 		i = valueInt | ||||||
| 	} else { | 	} else { | ||||||
| 		err = fmt.Errorf("%s expected integer, got %s (%v)", description, typeName(value), value) | 		err = fmt.Errorf("%s expected integer, got %s (%v)", description, TypeName(value), value) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user