Compare commits
	
		
			3 Commits
		
	
	
		
			591b4ffc19
			...
			ed973c9b7b
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ed973c9b7b | |||
| 15bbfacd47 | |||
| 04f934ab04 | 
@ -25,8 +25,7 @@ func TestExpr(t *testing.T) {
 | 
				
			|||||||
	failed := 0
 | 
						failed := 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inputs1 := []inputType{
 | 
						inputs1 := []inputType{
 | 
				
			||||||
		{`f=openFile("/tmp/test2.txt"); line=readFile(f); closeFile(f); line`, "ciao", nil},
 | 
							{`f=openFile("test-file.txt"); line=readFile(f); closeFile(f); line`, "uno", nil},
 | 
				
			||||||
		//{`f = func(op){op()}; f(func(){2})`, int64(2), nil},
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i, input := range inputs1 {
 | 
						for i, input := range inputs1 {
 | 
				
			||||||
 | 
				
			|||||||
@ -4,52 +4,10 @@
 | 
				
			|||||||
// operand-const.go
 | 
					// operand-const.go
 | 
				
			||||||
package expr
 | 
					package expr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// -------- bool const term
 | 
					// -------- const term
 | 
				
			||||||
func newBoolTerm(tk *Token) *term {
 | 
					func newConstTerm(tk *Token) *term {
 | 
				
			||||||
	return &term{
 | 
						return &term{
 | 
				
			||||||
		tk:       *tk,
 | 
							tk:       *tk,
 | 
				
			||||||
		// class:    classConst,
 | 
					 | 
				
			||||||
		// kind:     kindBool,
 | 
					 | 
				
			||||||
		parent:   nil,
 | 
					 | 
				
			||||||
		children: nil,
 | 
					 | 
				
			||||||
		position: posLeaf,
 | 
					 | 
				
			||||||
		priority: priValue,
 | 
					 | 
				
			||||||
		evalFunc: evalConst,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -------- integer const term
 | 
					 | 
				
			||||||
func newIntegerTerm(tk *Token) *term {
 | 
					 | 
				
			||||||
	return &term{
 | 
					 | 
				
			||||||
		tk:       *tk,
 | 
					 | 
				
			||||||
		parent:   nil,
 | 
					 | 
				
			||||||
		children: nil,
 | 
					 | 
				
			||||||
		position: posLeaf,
 | 
					 | 
				
			||||||
		priority: priValue,
 | 
					 | 
				
			||||||
		evalFunc: evalConst,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -------- float const term
 | 
					 | 
				
			||||||
func newFloatTerm(tk *Token) *term {
 | 
					 | 
				
			||||||
	return &term{
 | 
					 | 
				
			||||||
		tk: *tk,
 | 
					 | 
				
			||||||
		// class:    classConst,
 | 
					 | 
				
			||||||
		// kind:     kindFloat,
 | 
					 | 
				
			||||||
		parent:   nil,
 | 
					 | 
				
			||||||
		children: nil,
 | 
					 | 
				
			||||||
		position: posLeaf,
 | 
					 | 
				
			||||||
		priority: priValue,
 | 
					 | 
				
			||||||
		evalFunc: evalConst,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// -------- string const term
 | 
					 | 
				
			||||||
func newStringTerm(tk *Token) *term {
 | 
					 | 
				
			||||||
	return &term{
 | 
					 | 
				
			||||||
		tk: *tk,
 | 
					 | 
				
			||||||
		// class:    classConst,
 | 
					 | 
				
			||||||
		// kind:     kindString,
 | 
					 | 
				
			||||||
		parent:   nil,
 | 
							parent:   nil,
 | 
				
			||||||
		children: nil,
 | 
							children: nil,
 | 
				
			||||||
		position: posLeaf,
 | 
							position: posLeaf,
 | 
				
			||||||
@ -66,8 +24,9 @@ func evalConst(ctx ExprContext, self *term) (v any, err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// init
 | 
					// init
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	registerTermConstructor(SymString, newStringTerm)
 | 
						registerTermConstructor(SymString, newConstTerm)
 | 
				
			||||||
	registerTermConstructor(SymInteger, newIntegerTerm)
 | 
						registerTermConstructor(SymInteger, newConstTerm)
 | 
				
			||||||
	registerTermConstructor(SymFloat, newFloatTerm)
 | 
						registerTermConstructor(SymFloat, newConstTerm)
 | 
				
			||||||
	registerTermConstructor(SymBool, newBoolTerm)
 | 
						registerTermConstructor(SymBool, newConstTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymKwNil, newConstTerm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -63,7 +63,7 @@ func TestParser(t *testing.T) {
 | 
				
			|||||||
		/*  42 */ {`"s" + true`, nil, errors.New(`[1:6] left operand 's' [string] and right operand 'true' [bool] are not compatible with operator "+"`)},
 | 
							/*  42 */ {`"s" + true`, nil, errors.New(`[1:6] left operand 's' [string] and right operand 'true' [bool] are not compatible with operator "+"`)},
 | 
				
			||||||
		/*  43 */ {`+false`, nil, errors.New(`[1:2] prefix/postfix operator "+" do not support operand 'false' [bool]`)},
 | 
							/*  43 */ {`+false`, nil, errors.New(`[1:2] prefix/postfix operator "+" do not support operand 'false' [bool]`)},
 | 
				
			||||||
		/*  44 */ {`false // very simple expression`, false, nil},
 | 
							/*  44 */ {`false // very simple expression`, false, nil},
 | 
				
			||||||
		/*  45 */ {`1 + // Missing right operator`, nil, errors.New(`[1:4] infix operator "+" requires two not nil operands, got 1`)},
 | 
							/*  45 */ {`1 + // Missing right operator`, nil, errors.New(`[1:4] infix operator "+" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  46 */ {"", nil, errors.New(`empty expression`)},
 | 
							/*  46 */ {"", nil, errors.New(`empty expression`)},
 | 
				
			||||||
		/*  47 */ {"4!", int64(24), nil},
 | 
							/*  47 */ {"4!", int64(24), nil},
 | 
				
			||||||
		/*  48 */ {"(-4)!", nil, errors.New(`factorial of a negative integer (-4) is not allowed`)},
 | 
							/*  48 */ {"(-4)!", nil, errors.New(`factorial of a negative integer (-4) is not allowed`)},
 | 
				
			||||||
@ -78,16 +78,16 @@ func TestParser(t *testing.T) {
 | 
				
			|||||||
		/*  57 */ {`"1.5" > "7"`, false, nil},
 | 
							/*  57 */ {`"1.5" > "7"`, false, nil},
 | 
				
			||||||
		/*  58 */ {`"1.5" == "7"`, false, nil},
 | 
							/*  58 */ {`"1.5" == "7"`, false, nil},
 | 
				
			||||||
		/*  59 */ {`"1.5" != "7"`, true, nil},
 | 
							/*  59 */ {`"1.5" != "7"`, true, nil},
 | 
				
			||||||
		/*  60 */ {"1.5 < ", nil, errors.New(`[1:6] infix operator "<" requires two not nil operands, got 1`)},
 | 
							/*  60 */ {"1.5 < ", nil, errors.New(`[1:6] infix operator "<" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  61 */ {"1.5 > ", nil, errors.New(`[1:6] infix operator ">" requires two not nil operands, got 1`)},
 | 
							/*  61 */ {"1.5 > ", nil, errors.New(`[1:6] infix operator ">" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  62 */ {"1.5 <= ", nil, errors.New(`[1:6] infix operator "<=" requires two not nil operands, got 1`)},
 | 
							/*  62 */ {"1.5 <= ", nil, errors.New(`[1:6] infix operator "<=" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  63 */ {"1.5 >= ", nil, errors.New(`[1:6] infix operator ">=" requires two not nil operands, got 1`)},
 | 
							/*  63 */ {"1.5 >= ", nil, errors.New(`[1:6] infix operator ">=" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  64 */ {"1.5 != ", nil, errors.New(`[1:6] infix operator "!=" requires two not nil operands, got 1`)},
 | 
							/*  64 */ {"1.5 != ", nil, errors.New(`[1:6] infix operator "!=" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  65 */ {"1.5 == ", nil, errors.New(`[1:6] infix operator "==" requires two not nil operands, got 1`)},
 | 
							/*  65 */ {"1.5 == ", nil, errors.New(`[1:6] infix operator "==" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  66 */ {`"1.5" < `, nil, errors.New(`[1:8] infix operator "<" requires two not nil operands, got 1`)},
 | 
							/*  66 */ {`"1.5" < `, nil, errors.New(`[1:8] infix operator "<" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  67 */ {`"1.5" > `, nil, errors.New(`[1:8] infix operator ">" requires two not nil operands, got 1`)},
 | 
							/*  67 */ {`"1.5" > `, nil, errors.New(`[1:8] infix operator ">" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  68 */ {`"1.5" == `, nil, errors.New(`[1:8] infix operator "==" requires two not nil operands, got 1`)},
 | 
							/*  68 */ {`"1.5" == `, nil, errors.New(`[1:8] infix operator "==" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  69 */ {`"1.5" != `, nil, errors.New(`[1:8] infix operator "!=" requires two not nil operands, got 1`)},
 | 
							/*  69 */ {`"1.5" != `, nil, errors.New(`[1:8] infix operator "!=" requires two non-nil operands, got 1`)},
 | 
				
			||||||
		/*  70 */ {"+1.5", float64(1.5), nil},
 | 
							/*  70 */ {"+1.5", float64(1.5), nil},
 | 
				
			||||||
		/*  71 */ {"+", nil, errors.New(`[1:2] prefix operator "+" requires one not nil operand`)},
 | 
							/*  71 */ {"+", nil, errors.New(`[1:2] prefix operator "+" requires one not nil operand`)},
 | 
				
			||||||
		/*  72 */ {"4 / 0", nil, errors.New(`division by zero`)},
 | 
							/*  72 */ {"4 / 0", nil, errors.New(`division by zero`)},
 | 
				
			||||||
@ -134,7 +134,7 @@ func TestParser(t *testing.T) {
 | 
				
			|||||||
		/* 113 */ {`import("test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil},
 | 
							/* 113 */ {`import("test-funcs.expr"); (double(3+a) + 1) * two()`, int64(34), nil},
 | 
				
			||||||
		/* 114 */ {`x ?? "default"`, "default", nil},
 | 
							/* 114 */ {`x ?? "default"`, "default", nil},
 | 
				
			||||||
		/* 115 */ {`x="hello"; x ?? "default"`, "hello", nil},
 | 
							/* 115 */ {`x="hello"; x ?? "default"`, "hello", nil},
 | 
				
			||||||
		/* 116 */ {`x ?? func(){}"`, nil, errors.New(`[1:15] the right operand of a coalescing operation cannot be a function definition`)},
 | 
							/* 116 */ {`x ?? func(){}`, nil, errors.New(`[1:14] the right operand of a coalescing operation cannot be a function definition`)},
 | 
				
			||||||
		/* 117 */ {`x ?= "default"; x`, "default", nil},
 | 
							/* 117 */ {`x ?= "default"; x`, "default", nil},
 | 
				
			||||||
		/* 118 */ {`x="hello"; x ?= "default"; x`, "hello", nil},
 | 
							/* 118 */ {`x="hello"; x ?= "default"; x`, "hello", nil},
 | 
				
			||||||
		/* 119 */ {`@x="hello"; @x`, nil, errors.New(`[1:3] variable references are not allowed in top level expressions: "@x"`)},
 | 
							/* 119 */ {`@x="hello"; @x`, nil, errors.New(`[1:3] variable references are not allowed in top level expressions: "@x"`)},
 | 
				
			||||||
@ -156,6 +156,8 @@ func TestParser(t *testing.T) {
 | 
				
			|||||||
		/* 135 */ {`10 ? {"a"} :: {"b"} : {"c"}`, nil, errors.New(`[1:22] selector-case outside of a selector context`)},
 | 
							/* 135 */ {`10 ? {"a"} :: {"b"} : {"c"}`, nil, errors.New(`[1:22] selector-case outside of a selector context`)},
 | 
				
			||||||
		/* 136 */ {`1 ? {"a"} : {"b"} ? ["a"] {"A"} :["b"] {"B"}`, "B", nil},
 | 
							/* 136 */ {`1 ? {"a"} : {"b"} ? ["a"] {"A"} :["b"] {"B"}`, "B", nil},
 | 
				
			||||||
		/* 137 */ {`2 + 1 ? {"a"} : {"b"} * 3`, "2bbb", nil},
 | 
							/* 137 */ {`2 + 1 ? {"a"} : {"b"} * 3`, "2bbb", nil},
 | 
				
			||||||
 | 
							/* 138 */ {`nil`, nil, nil},
 | 
				
			||||||
 | 
							/* 139 */ {`null`, nil, errors.New(`undefined variable "null"`)},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	check_env_expr_path := 113
 | 
						check_env_expr_path := 113
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ func TestScanner(t *testing.T) {
 | 
				
			|||||||
		/* 14 */ {`:`, SymColon, nil, nil},
 | 
							/* 14 */ {`:`, SymColon, nil, nil},
 | 
				
			||||||
		/* 15 */ {`;`, SymSemiColon, nil, nil},
 | 
							/* 15 */ {`;`, SymSemiColon, nil, nil},
 | 
				
			||||||
		/* 16 */ {`.`, SymDot, nil, nil},
 | 
							/* 16 */ {`.`, SymDot, nil, nil},
 | 
				
			||||||
		/* 17 */ {`.5`, SymFloat, float64(0.5), nil},
 | 
							/* 17 */ {`0.5`, SymFloat, float64(0.5), nil},
 | 
				
			||||||
		/* 18 */ {`\\`, SymBackSlash, nil, nil},
 | 
							/* 18 */ {`\\`, SymBackSlash, nil, nil},
 | 
				
			||||||
		/* 19 */ {"`", SymBackTick, nil, nil},
 | 
							/* 19 */ {"`", SymBackTick, nil, nil},
 | 
				
			||||||
		/* 20 */ {"?", SymQuestion, nil, nil},
 | 
							/* 20 */ {"?", SymQuestion, nil, nil},
 | 
				
			||||||
@ -74,7 +74,7 @@ func TestScanner(t *testing.T) {
 | 
				
			|||||||
		scanner := NewScanner(r, nil)
 | 
							scanner := NewScanner(r, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if tk := scanner.Next(); tk == nil {
 | 
							if tk := scanner.Next(); tk == nil {
 | 
				
			||||||
			t.Errorf("%d: %q -> got = (nil), want %v (value %v [%T)", i+1, input.source, input.wantSym, input.wantValue, input.wantValue)
 | 
								t.Errorf("%d: %q -> got = (nil), want %v (value %v [%T])", i+1, input.source, input.wantSym, input.wantValue, input.wantValue)
 | 
				
			||||||
		} else if tk.Sym != input.wantSym || tk.Value != input.wantValue {
 | 
							} else if tk.Sym != input.wantSym || tk.Value != input.wantValue {
 | 
				
			||||||
			if tk.Sym == SymError && input.wantSym == tk.Sym {
 | 
								if tk.Sym == SymError && input.wantSym == tk.Sym {
 | 
				
			||||||
				if tkErr, tkOk := tk.Value.(error); tkOk {
 | 
									if tkErr, tkOk := tk.Value.(error); tkOk {
 | 
				
			||||||
 | 
				
			|||||||
@ -90,6 +90,7 @@ const (
 | 
				
			|||||||
	SymKwBut
 | 
						SymKwBut
 | 
				
			||||||
	SymKwFunc
 | 
						SymKwFunc
 | 
				
			||||||
	SymKwBuiltin
 | 
						SymKwBuiltin
 | 
				
			||||||
 | 
						SymKwNil
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var keywords map[string]Symbol
 | 
					var keywords map[string]Symbol
 | 
				
			||||||
@ -103,5 +104,6 @@ func init() {
 | 
				
			|||||||
		"FUNC":    SymKwFunc,
 | 
							"FUNC":    SymKwFunc,
 | 
				
			||||||
		"NOT":     SymKwNot,
 | 
							"NOT":     SymKwNot,
 | 
				
			||||||
		"OR":      SymKwOr,
 | 
							"OR":      SymKwOr,
 | 
				
			||||||
 | 
							"NIL":     SymKwNil,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								test-file.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								test-file.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					uno
 | 
				
			||||||
 | 
					due
 | 
				
			||||||
@ -5,6 +5,7 @@
 | 
				
			|||||||
package expr
 | 
					package expr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -17,8 +18,8 @@ func TestDevString(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	inputs := []inputType{
 | 
						inputs := []inputType{
 | 
				
			||||||
		/*   1 */ {"100", SymInteger, 100, `[55]"100"{100}`},
 | 
							/*   1 */ {"100", SymInteger, 100, fmt.Sprintf(`[%d]"100"{100}`, SymInteger)},
 | 
				
			||||||
		/*   2 */ {"+", SymPlus, nil, `[6]"+"{}`},
 | 
							/*   2 */ {"+", SymPlus, nil, fmt.Sprintf(`[%d]"+"{}`, SymPlus)},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i, input := range inputs {
 | 
						for i, input := range inputs {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user