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 {
|
||||||
@ -124,7 +130,6 @@ func (dict *DictType) merge(second *DictType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (dict *DictType) setItem(key any, value any) (err error) {
|
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