Compare commits
	
		
			No commits in common. "bf8f1a175f0c21b56268fef38e3969d60f978b62" and "723976b37e65e1f6807f5e6496d6d492bacf9133" have entirely different histories.
		
	
	
		
			bf8f1a175f
			...
			723976b37e
		
	
		
| @ -5,14 +5,11 @@ | |||||||
| 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" | ||||||
| ) | ) | ||||||
| @ -23,8 +20,6 @@ type dataCursor struct { | |||||||
| 	index       int | 	index       int | ||||||
| 	resource    any | 	resource    any | ||||||
| 	nextFunc    Functor | 	nextFunc    Functor | ||||||
| 	cleanFunc   Functor |  | ||||||
| 	resetFunc   Functor |  | ||||||
| 	currentFunc Functor | 	currentFunc Functor | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -40,30 +35,6 @@ 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("base", ImportBuiltinsFuncs, "Base expression tools like isNil(), int(), etc.") | 	registerImport("builtins", ImportBuiltinsFuncs) | ||||||
| } | } | ||||||
| @ -142,5 +142,5 @@ func ImportImportFuncs(ctx ExprContext) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	registerImport("import", ImportImportFuncs, "Functions import() and include()") | 	registerImport("import", ImportImportFuncs) | ||||||
| } | } | ||||||
|  | |||||||
| @ -115,5 +115,5 @@ func ImportMathFuncs(ctx ExprContext) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	registerImport("math.arith", ImportMathFuncs, "Function add() and mul()") | 	registerImport("math.arith", ImportMathFuncs) | ||||||
| } | } | ||||||
|  | |||||||
| @ -164,5 +164,5 @@ func ImportOsFuncs(ctx ExprContext) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func init() { | func init() { | ||||||
| 	registerImport("os.file", ImportOsFuncs, "Operating system file functions") | 	registerImport("os", ImportOsFuncs) | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										47
									
								
								function-register.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								function-register.go
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,47 @@ | |||||||
|  | // 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,8 +6,6 @@ package expr | |||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"io" |  | ||||||
| 	"os" |  | ||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -61,24 +59,3 @@ 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 |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -1,74 +0,0 @@ | |||||||
| // 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,23 +54,14 @@ 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) | ||||||
| 		// required functions
 | 		for _, k := range []string{initName, currentName, nextName} { | ||||||
| 		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 { | 			} else if k != initName { | ||||||
| 				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) | ||||||
| 				return | 				break | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
| 		// 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 { | ||||||
| @ -107,9 +98,6 @@ 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-builtin.go
 | // operator-length.go
 | ||||||
| package expr | package expr | ||||||
| 
 | 
 | ||||||
| //-------- builtin term
 | //-------- builtin term
 | ||||||
|  | |||||||
| @ -17,67 +17,50 @@ 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 err = self.checkOperands(); err != nil { | 	if leftValue, rightValue, err = self.evalInfix(ctx); err != nil { | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	if leftValue, err = self.children[0].compute(ctx); err != nil { |  | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	indexTerm := self.children[1] | 	indexTerm := self.children[1] | ||||||
| 
 | 
 | ||||||
| 	switch unboxedValue := leftValue.(type) { | 	if isList(leftValue) { | ||||||
| 	case []any: |  | ||||||
| 		var index int | 		var index int | ||||||
| 		if index, err = verifyIndex(ctx, indexTerm, len(unboxedValue)); err == nil { | 		if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil { | ||||||
| 			v = unboxedValue[index] | 			return | ||||||
| 		} | 		} | ||||||
| 	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 = verifyIndex(ctx, indexTerm, len(unboxedValue)); err == nil { | 		if index, err = indexTerm.toInt(rightValue, "index expression value must be integer"); err != nil { | ||||||
| 			v = unboxedValue[index] | 			return | ||||||
| 		} | 		} | ||||||
| 	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 | ||||||
| 		var indexValue any | 		d, _ := leftValue.(map[any]any) | ||||||
| 		if indexValue, err = indexTerm.compute(ctx); err == nil { | 		if v, ok = d[rightValue]; !ok { | ||||||
| 			if v, ok = unboxedValue[indexValue]; !ok { |  | ||||||
| 			err = fmt.Errorf("key %v does not belong to the dictionary", rightValue) | 			err = fmt.Errorf("key %v does not belong to the dictionary", rightValue) | ||||||
| 		} | 		} | ||||||
| 		} |  | ||||||
| 	case *dataCursor: |  | ||||||
| 		if indexTerm.symbol() == SymIdentifier { |  | ||||||
| 			opName := indexTerm.source() |  | ||||||
| 			if opName == resetName { |  | ||||||
| 				err = unboxedValue.Reset() |  | ||||||
| 			} else if opName == cleanName { |  | ||||||
| 				err = unboxedValue.Clean() |  | ||||||
| 	} else { | 	} 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 | ||||||
|  | |||||||
| @ -1,57 +0,0 @@ | |||||||
| // 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 = int64(len(list)) | 		v = len(list) | ||||||
| 	} else if isString(rightValue) { | 	} else if isString(rightValue) { | ||||||
| 		s, _ := rightValue.(string) | 		s, _ := rightValue.(string) | ||||||
| 		v = int64(len(s)) | 		v = len(s) | ||||||
| 	} else if it, ok := rightValue.(Iterator); ok { | 	} else if it, ok := rightValue.(Iterator); ok { | ||||||
| 		v = int64(it.Index()) | 		v = 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,7 +96,6 @@ const ( | |||||||
| 	SymKwBut | 	SymKwBut | ||||||
| 	SymKwFunc | 	SymKwFunc | ||||||
| 	SymKwBuiltin | 	SymKwBuiltin | ||||||
| 	SymKwInclude |  | ||||||
| 	SymKwNil | 	SymKwNil | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| @ -109,7 +108,6 @@ 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) (childValue any, err error) { | func (self *term) evalPrefix(ctx ExprContext) (rightValue any, err error) { | ||||||
| 	if err = self.checkOperands(); err == nil { | 	if err = self.checkOperands(); err == nil { | ||||||
| 		childValue, err = self.children[0].compute(ctx) | 		rightValue, err = self.children[0].compute(ctx) | ||||||
| 	} | 	} | ||||||
| 	return | 	return | ||||||
| } | } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user