Compare commits
	
		
			14 Commits
		
	
	
		
			723976b37e
			...
			bf8f1a175f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| bf8f1a175f | |||
| 6dd8283308 | |||
| 06ab303b9e | |||
| 2ccbdb2254 | |||
| c5fca70cfc | |||
| 895778f236 | |||
| 81c85afbea | |||
| 354cb79580 | |||
| 327bffa01f | |||
| c99be491df | |||
| 60effe8f1b | |||
| 824b9382be | |||
| 9ce6b7255b | |||
| 9dbf472630 | 
| @ -5,11 +5,14 @@ | |||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"io" | 	"io" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| const ( | const ( | ||||||
| 	initName    = "init" | 	initName    = "init" | ||||||
|  | 	cleanName   = "clean" | ||||||
|  | 	resetName   = "reset" | ||||||
| 	nextName    = "next" | 	nextName    = "next" | ||||||
| 	currentName = "current" | 	currentName = "current" | ||||||
| ) | ) | ||||||
| @ -20,6 +23,8 @@ type dataCursor struct { | |||||||
| 	index       int | 	index       int | ||||||
| 	resource    any | 	resource    any | ||||||
| 	nextFunc    Functor | 	nextFunc    Functor | ||||||
|  | 	cleanFunc   Functor | ||||||
|  | 	resetFunc   Functor | ||||||
| 	currentFunc Functor | 	currentFunc Functor | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -35,6 +40,30 @@ func (dc *dataCursor) String() string { | |||||||
| 	return "$(...)" | 	return "$(...)" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func (dc *dataCursor) Reset() (err error) { | ||||||
|  | 	if dc.resetFunc != nil { | ||||||
|  | 		ctx := cloneContext(dc.ctx) | ||||||
|  | 		if _, err = dc.resetFunc.Invoke(ctx, resetName, []any{}); err == nil { | ||||||
|  | 			dc.index = -1 | ||||||
|  | 		} | ||||||
|  | 		exportObjects(dc.ctx, ctx) | ||||||
|  | 	} else { | ||||||
|  | 		err = errors.New("no 'reset' function defined in the data-source") | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func (dc *dataCursor) Clean() (err error) { | ||||||
|  | 	if dc.cleanFunc != nil { | ||||||
|  | 		ctx := cloneContext(dc.ctx) | ||||||
|  | 		_, err = dc.cleanFunc.Invoke(ctx, cleanName, []any{}) | ||||||
|  | 		exportObjects(dc.ctx, ctx) | ||||||
|  | 	} else { | ||||||
|  | 		err = errors.New("no 'clean' function defined in the data-source") | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
 | func (dc *dataCursor) Current() (item any, err error) { // must return io.EOF at the last item
 | ||||||
| 	ctx := cloneContext(dc.ctx) | 	ctx := cloneContext(dc.ctx) | ||||||
| 	if item, err = dc.currentFunc.Invoke(ctx, currentName, []any{}); err == nil && item == nil { | 	if item, err = dc.currentFunc.Invoke(ctx, currentName, []any{}); err == nil && item == nil { | ||||||
|  | |||||||
| @ -55,5 +55,5 @@ func ImportBuiltinsFuncs(ctx ExprContext) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	registerImport("builtins", ImportBuiltinsFuncs) | 	registerImport("base", ImportBuiltinsFuncs, "Base expression tools like isNil(), int(), etc.") | ||||||
| } | } | ||||||
| @ -142,5 +142,5 @@ func ImportImportFuncs(ctx ExprContext) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	registerImport("import", ImportImportFuncs) | 	registerImport("import", ImportImportFuncs, "Functions import() and include()") | ||||||
| } | } | ||||||
|  | |||||||
| @ -115,5 +115,5 @@ func ImportMathFuncs(ctx ExprContext) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	registerImport("math.arith", ImportMathFuncs) | 	registerImport("math.arith", ImportMathFuncs, "Function add() and mul()") | ||||||
| } | } | ||||||
|  | |||||||
| @ -164,5 +164,5 @@ func ImportOsFuncs(ctx ExprContext) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	registerImport("os", ImportOsFuncs) | 	registerImport("os.file", ImportOsFuncs, "Operating system file functions") | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,47 +0,0 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 |  | ||||||
| // All rights reserved.
 |  | ||||||
| 
 |  | ||||||
| // function-register.go
 |  | ||||||
| package expr |  | ||||||
| 
 |  | ||||||
| import ( |  | ||||||
| 	"path/filepath" |  | ||||||
| ) |  | ||||||
| 
 |  | ||||||
| var functionRegister map[string]func(ExprContext) |  | ||||||
| 
 |  | ||||||
| func registerImport(name string, importFunc func(ExprContext)) { |  | ||||||
| 	if functionRegister == nil { |  | ||||||
| 		functionRegister = make(map[string]func(ExprContext)) |  | ||||||
| 	} |  | ||||||
| 	functionRegister[name] = importFunc |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func ImportInContext(ctx ExprContext, name string) (exists bool) { |  | ||||||
| 	var importFunc func(ExprContext) |  | ||||||
| 	if importFunc, exists = functionRegister[name]; exists { |  | ||||||
| 		importFunc(ctx) |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func ImportInContextByGlobPattern(ctx ExprContext, pattern string) (count int, err error) { |  | ||||||
| 	var matched bool |  | ||||||
| 	for name, importFunc := range functionRegister { |  | ||||||
| 		if matched, err = filepath.Match(pattern, name); err == nil { |  | ||||||
| 			if matched { |  | ||||||
| 				count++ |  | ||||||
| 				importFunc(ctx) |  | ||||||
| 			} |  | ||||||
| 		} else { |  | ||||||
| 			break |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
| 	return |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func init() { |  | ||||||
| 	if functionRegister == nil { |  | ||||||
| 		functionRegister = make(map[string]func(ExprContext)) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
							
								
								
									
										23
									
								
								helpers.go
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								helpers.go
									
									
									
									
									
								
							| @ -6,6 +6,8 @@ package expr | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"io" | ||||||
|  | 	"os" | ||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -59,3 +61,24 @@ func EvalStringV(source string, args []Arg) (result any, err error) { | |||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | func EvalStream(ctx ExprContext, r io.Reader) (result any, err error) { | ||||||
|  | 	var tree *ast | ||||||
|  | 	scanner := NewScanner(r, DefaultTranslations()) | ||||||
|  | 	parser := NewParser(ctx) | ||||||
|  | 
 | ||||||
|  | 	if tree, err = parser.Parse(scanner); err == nil { | ||||||
|  | 		result, err = tree.Eval(ctx) | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func EvalFile(ctx ExprContext, filePath string) (result any, err error) { | ||||||
|  | 	var fh *os.File | ||||||
|  | 	if fh, err = os.Open(filePath); err != nil { | ||||||
|  | 		return nil, err | ||||||
|  | 	} | ||||||
|  | 	defer fh.Close() | ||||||
|  | 	result, err = EvalStream(ctx, fh) | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | |||||||
							
								
								
									
										74
									
								
								module-register.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								module-register.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,74 @@ | |||||||
|  | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
|  | // All rights reserved.
 | ||||||
|  | 
 | ||||||
|  | // module-register.go
 | ||||||
|  | package expr | ||||||
|  | 
 | ||||||
|  | import ( | ||||||
|  | 	"fmt" | ||||||
|  | 	"path/filepath" | ||||||
|  | ) | ||||||
|  | 
 | ||||||
|  | type module struct { | ||||||
|  | 	importFunc  func(ExprContext) | ||||||
|  | 	description string | ||||||
|  | 	imported    bool | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func newModule(importFunc func(ExprContext), description string) *module { | ||||||
|  | 	return &module{importFunc, description, false} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | var moduleRegister map[string]*module | ||||||
|  | 
 | ||||||
|  | func registerImport(name string, importFunc func(ExprContext), description string) { | ||||||
|  | 	if moduleRegister == nil { | ||||||
|  | 		moduleRegister = make(map[string]*module) | ||||||
|  | 	} | ||||||
|  | 	if _, exists := moduleRegister[name]; exists { | ||||||
|  | 		panic(fmt.Errorf("module %q already registered", name)) | ||||||
|  | 	} | ||||||
|  | 	moduleRegister[name] = newModule(importFunc, description) | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func ImportInContext(ctx ExprContext, name string) (exists bool) { | ||||||
|  | 	var mod *module | ||||||
|  | 	if mod, exists = moduleRegister[name]; exists { | ||||||
|  | 		mod.importFunc(ctx) | ||||||
|  | 		mod.imported = true | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func ImportInContextByGlobPattern(ctx ExprContext, pattern string) (count int, err error) { | ||||||
|  | 	var matched bool | ||||||
|  | 	for name, mod := range moduleRegister { | ||||||
|  | 		if matched, err = filepath.Match(pattern, name); err == nil { | ||||||
|  | 			if matched { | ||||||
|  | 				count++ | ||||||
|  | 				mod.importFunc(ctx) | ||||||
|  | 				mod.imported = true | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func IterateModules(op func(name, description string, imported bool) bool) { | ||||||
|  | 	if op != nil { | ||||||
|  | 		for name, mod := range moduleRegister { | ||||||
|  | 			if !op(name, mod.description, mod.imported) { | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // ----
 | ||||||
|  | func init() { | ||||||
|  | 	if moduleRegister == nil { | ||||||
|  | 		moduleRegister = make(map[string]*module) | ||||||
|  | 	} | ||||||
|  | } | ||||||
| @ -54,14 +54,23 @@ func getDataSourceDict(ctx ExprContext, self *term) (ds map[string]Functor, err | |||||||
| 
 | 
 | ||||||
| 	if dictAny, ok := value.(map[any]any); ok { | 	if dictAny, ok := value.(map[any]any); ok { | ||||||
| 		ds = make(map[string]Functor) | 		ds = make(map[string]Functor) | ||||||
| 		for _, k := range []string{initName, currentName, nextName} { | 		// required functions
 | ||||||
|  | 		for _, k := range []string{currentName, nextName} { | ||||||
| 			if item, exists := dictAny[k]; exists && item != nil { | 			if item, exists := dictAny[k]; exists && item != nil { | ||||||
| 				if functor, ok := item.(*funcDefFunctor); ok { | 				if functor, ok := item.(*funcDefFunctor); ok { | ||||||
| 					ds[k] = functor | 					ds[k] = functor | ||||||
| 				} | 				} | ||||||
| 			} else if k != initName { | 			} else { | ||||||
| 				err = fmt.Errorf("the data-source must provide a non-nil %q operator", k) | 				err = fmt.Errorf("the data-source must provide a non-nil %q operator", k) | ||||||
| 				break | 				return | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		// Optional functions
 | ||||||
|  | 		for _, k := range []string{initName, resetName, cleanName} { | ||||||
|  | 			if item, exists := dictAny[k]; exists && item != nil { | ||||||
|  | 				if functor, ok := item.(*funcDefFunctor); ok { | ||||||
|  | 					ds[k] = functor | ||||||
|  | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 	} else { | 	} else { | ||||||
| @ -98,6 +107,9 @@ func evalIterator(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 
 | 
 | ||||||
| 	dc.nextFunc, _ = ds[nextName] | 	dc.nextFunc, _ = ds[nextName] | ||||||
| 	dc.currentFunc, _ = ds[currentName] | 	dc.currentFunc, _ = ds[currentName] | ||||||
|  | 	dc.cleanFunc, _ = ds[cleanName] | ||||||
|  | 	dc.resetFunc, _ = ds[resetName] | ||||||
|  | 
 | ||||||
| 	v = dc | 	v = dc | ||||||
| 
 | 
 | ||||||
| 	return | 	return | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
| // All rights reserved.
 | // All rights reserved.
 | ||||||
| 
 | 
 | ||||||
| // operator-length.go
 | // operator-builtin.go
 | ||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| //-------- builtin term
 | //-------- builtin term
 | ||||||
|  | |||||||
| @ -17,50 +17,67 @@ func newDotTerm(tk *Token) (inst *term) { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | func verifyIndex(ctx ExprContext, indexTerm *term, maxValue int) (index int, err error) { | ||||||
|  | 	var v int | ||||||
|  | 	var indexValue any | ||||||
|  | 	if indexValue, err = indexTerm.compute(ctx); err == nil { | ||||||
|  | 		if v, err = indexTerm.toInt(indexValue, "index expression value must be integer"); err == nil { | ||||||
|  | 			if v >= 0 && v < maxValue { | ||||||
|  | 				index = v | ||||||
|  | 			} else if index >= -maxValue { | ||||||
|  | 				index = maxValue + v | ||||||
|  | 			} else { | ||||||
|  | 				err = indexTerm.Errorf("index %d out of bounds", v) | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
| func evalDot(ctx ExprContext, self *term) (v any, err error) { | func evalDot(ctx ExprContext, self *term) (v any, err error) { | ||||||
| 	var leftValue, rightValue any | 	var leftValue, rightValue any | ||||||
| 
 | 
 | ||||||
| 	if leftValue, rightValue, err = self.evalInfix(ctx); err != nil { | 	if err = self.checkOperands(); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 	if leftValue, err = self.children[0].compute(ctx); err != nil { | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	indexTerm := self.children[1] | 	indexTerm := self.children[1] | ||||||
| 
 | 
 | ||||||
| 	if isList(leftValue) { | 	switch unboxedValue := leftValue.(type) { | ||||||
|  | 	case []any: | ||||||
| 		var index int | 		var index int | ||||||
| 		if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil { | 		if index, err = verifyIndex(ctx, indexTerm, len(unboxedValue)); err == nil { | ||||||
| 			return | 			v = unboxedValue[index] | ||||||
| 		} | 		} | ||||||
| 
 | 	case string: | ||||||
| 		list, _ := leftValue.([]any) |  | ||||||
| 		if index >= 0 && index < len(list) { |  | ||||||
| 			v = list[index] |  | ||||||
| 		} else if index >= -len(list) { |  | ||||||
| 			v = list[len(list)+index] |  | ||||||
| 		} else { |  | ||||||
| 			err = indexTerm.Errorf("index %v out of bounds", index) |  | ||||||
| 		} |  | ||||||
| 	} else if isString(leftValue) { |  | ||||||
| 		var index int | 		var index int | ||||||
| 		if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil { | 		if index, err = verifyIndex(ctx, indexTerm, len(unboxedValue)); err == nil { | ||||||
| 			return | 			v = unboxedValue[index] | ||||||
| 		} | 		} | ||||||
| 
 | 	case map[any]any: | ||||||
| 		s, _ := leftValue.(string) |  | ||||||
| 		if index >= 0 && index < len(s) { |  | ||||||
| 			v = string(s[index]) |  | ||||||
| 		} else if index >= -len(s) { |  | ||||||
| 			v = string(s[len(s)+index]) |  | ||||||
| 		} else { |  | ||||||
| 			err = indexTerm.Errorf("index %v out of bounds", index) |  | ||||||
| 		} |  | ||||||
| 	} else if isDict(leftValue) { |  | ||||||
| 		var ok bool | 		var ok bool | ||||||
| 		d, _ := leftValue.(map[any]any) | 		var indexValue any | ||||||
| 		if v, ok = d[rightValue]; !ok { | 		if indexValue, err = indexTerm.compute(ctx); err == nil { | ||||||
| 			err = fmt.Errorf("key %v does not belong to the dictionary", rightValue) | 			if v, ok = unboxedValue[indexValue]; !ok { | ||||||
|  | 				err = fmt.Errorf("key %v does not belong to the dictionary", rightValue) | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 	} else { | 	case *dataCursor: | ||||||
|  | 		if indexTerm.symbol() == SymIdentifier { | ||||||
|  | 			opName := indexTerm.source() | ||||||
|  | 			if opName == resetName { | ||||||
|  | 				err = unboxedValue.Reset() | ||||||
|  | 			} else if opName == cleanName { | ||||||
|  | 				err = unboxedValue.Clean() | ||||||
|  | 			} else { | ||||||
|  | 				err = indexTerm.Errorf("iterators do not support command %q", opName) | ||||||
|  | 			} | ||||||
|  | 			v = err == nil | ||||||
|  | 		} | ||||||
|  | 	default: | ||||||
| 		err = self.errIncompatibleTypes(leftValue, rightValue) | 		err = self.errIncompatibleTypes(leftValue, rightValue) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
|  | |||||||
							
								
								
									
										57
									
								
								operator-include.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								operator-include.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,57 @@ | |||||||
|  | // Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | ||||||
|  | // All rights reserved.
 | ||||||
|  | 
 | ||||||
|  | // operator-include.go
 | ||||||
|  | package expr | ||||||
|  | 
 | ||||||
|  | //-------- include term
 | ||||||
|  | 
 | ||||||
|  | func newIncludeTerm(tk *Token) (inst *term) { | ||||||
|  | 	return &term{ | ||||||
|  | 		tk:       *tk, | ||||||
|  | 		children: make([]*term, 0, 1), | ||||||
|  | 		position: posPrefix, | ||||||
|  | 		priority: priSign, | ||||||
|  | 		evalFunc: evalInclude, | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | func evalInclude(ctx ExprContext, self *term) (v any, err error) { | ||||||
|  | 	var childValue any | ||||||
|  | 
 | ||||||
|  | 	if childValue, err = self.evalPrefix(ctx); err != nil { | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	count := 0 | ||||||
|  | 	if isList(childValue) { | ||||||
|  | 		list, _ := childValue.([]any) | ||||||
|  | 		for i, filePathSpec := range list { | ||||||
|  | 			if filePath, ok := filePathSpec.(string); ok { | ||||||
|  | 				if v, err = EvalFile(ctx, filePath); err == nil { | ||||||
|  | 					count++ | ||||||
|  | 				} else { | ||||||
|  | 					err = self.Errorf("can't load file %q", filePath) | ||||||
|  | 					break | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				err = self.Errorf("expected string at item nr %d, got %T", i+1, filePathSpec) | ||||||
|  | 				break | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} else if isString(childValue) { | ||||||
|  | 		filePath, _ := childValue.(string) | ||||||
|  | 		v, err = EvalFile(ctx, filePath) | ||||||
|  | 	} else { | ||||||
|  | 		err = self.errIncompatibleType(childValue) | ||||||
|  | 	} | ||||||
|  | 	if err == nil { | ||||||
|  | 		v = count | ||||||
|  | 	} | ||||||
|  | 	return | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // init
 | ||||||
|  | func init() { | ||||||
|  | 	registerTermConstructor(SymKwInclude, newIncludeTerm) | ||||||
|  | } | ||||||
| @ -25,12 +25,12 @@ func evalLength(ctx ExprContext, self *term) (v any, err error) { | |||||||
| 
 | 
 | ||||||
| 	if isList(rightValue) { | 	if isList(rightValue) { | ||||||
| 		list, _ := rightValue.([]any) | 		list, _ := rightValue.([]any) | ||||||
| 		v = len(list) | 		v = int64(len(list)) | ||||||
| 	} else if isString(rightValue) { | 	} else if isString(rightValue) { | ||||||
| 		s, _ := rightValue.(string) | 		s, _ := rightValue.(string) | ||||||
| 		v = len(s) | 		v = int64(len(s)) | ||||||
| 	} else if it, ok := rightValue.(Iterator); ok { | 	} else if it, ok := rightValue.(Iterator); ok { | ||||||
| 		v = it.Index() | 		v = int64(it.Index()) | ||||||
| 	} else { | 	} else { | ||||||
| 		err = self.errIncompatibleType(rightValue) | 		err = self.errIncompatibleType(rightValue) | ||||||
| 	} | 	} | ||||||
|  | |||||||
| @ -33,7 +33,7 @@ const ( | |||||||
| 	SymBackTick                          //  22: '`'
 | 	SymBackTick                          //  22: '`'
 | ||||||
| 	SymExclamation                       //  23: '!'
 | 	SymExclamation                       //  23: '!'
 | ||||||
| 	SymQuestion                          //  24: '?'
 | 	SymQuestion                          //  24: '?'
 | ||||||
| 	SymAmpersand                         //  25: '&&'
 | 	SymAmpersand                         //  25: '&'
 | ||||||
| 	SymDoubleAmpersand                   //  26: '&&'
 | 	SymDoubleAmpersand                   //  26: '&&'
 | ||||||
| 	SymPercent                           //  27: '%'
 | 	SymPercent                           //  27: '%'
 | ||||||
| 	SymAt                                //  28: '@'
 | 	SymAt                                //  28: '@'
 | ||||||
| @ -64,7 +64,7 @@ const ( | |||||||
| 	SymCaret                             //  53: '^'
 | 	SymCaret                             //  53: '^'
 | ||||||
| 	SymDollarRound                       //  54: '$('
 | 	SymDollarRound                       //  54: '$('
 | ||||||
| 	SymOpenClosedRound                   //  55: '()'
 | 	SymOpenClosedRound                   //  55: '()'
 | ||||||
| 	SymDoubleDollar                      //  56: '$$
 | 	SymDoubleDollar                      //  56: '$$'
 | ||||||
| 	SymChangeSign | 	SymChangeSign | ||||||
| 	SymUnchangeSign | 	SymUnchangeSign | ||||||
| 	SymIdentifier | 	SymIdentifier | ||||||
| @ -96,6 +96,7 @@ const ( | |||||||
| 	SymKwBut | 	SymKwBut | ||||||
| 	SymKwFunc | 	SymKwFunc | ||||||
| 	SymKwBuiltin | 	SymKwBuiltin | ||||||
|  | 	SymKwInclude | ||||||
| 	SymKwNil | 	SymKwNil | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -108,6 +109,7 @@ func init() { | |||||||
| 		"BUILTIN": SymKwBuiltin, | 		"BUILTIN": SymKwBuiltin, | ||||||
| 		"BUT":     SymKwBut, | 		"BUT":     SymKwBut, | ||||||
| 		"FUNC":    SymKwFunc, | 		"FUNC":    SymKwFunc, | ||||||
|  | 		"INCLUDE": SymKwInclude, | ||||||
| 		"NOT":     SymKwNot, | 		"NOT":     SymKwNot, | ||||||
| 		"OR":      SymKwOr, | 		"OR":      SymKwOr, | ||||||
| 		"NIL":     SymKwNil, | 		"NIL":     SymKwNil, | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								term.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								term.go
									
									
									
									
									
								
							| @ -217,9 +217,9 @@ func (self *term) evalInfix(ctx ExprContext) (leftValue, rightValue any, err err | |||||||
| 	return | 	return | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func (self *term) evalPrefix(ctx ExprContext) (rightValue any, err error) { | func (self *term) evalPrefix(ctx ExprContext) (childValue any, err error) { | ||||||
| 	if err = self.checkOperands(); err == nil { | 	if err = self.checkOperands(); err == nil { | ||||||
| 		rightValue, err = self.children[0].compute(ctx) | 		childValue, err = self.children[0].compute(ctx) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user