Compare commits
	
		
			17 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5ecf81412e | |||
| ff4db34f7b | |||
| 0f848071c2 | |||
| 6b3351b324 | |||
| 760c1ee6da | |||
| 5ab6876ea1 | |||
| 6268abda8c | |||
| d25bd325b7 | |||
| 01c04feea5 | |||
| 6fc689c46c | |||
| eccb0c4dc9 | |||
| e43823740f | |||
| 526982a564 | |||
| 252514943e | |||
| 32686fac62 | |||
| 52a627c747 | |||
| d91e7eb979 | 
@ -33,7 +33,7 @@ func NewDict(dictAny map[any]any) (dict *DictType) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newDict(dictAny map[any]*term) (dict *DictType) {
 | 
					func newDict(dictAny map[any]*term) (dict *DictType) {
 | 
				
			||||||
	// TODO Change wi a call to NewDict()
 | 
						// TODO Change with a call to NewDict()
 | 
				
			||||||
	var d DictType
 | 
						var d DictType
 | 
				
			||||||
	if dictAny != nil {
 | 
						if dictAny != nil {
 | 
				
			||||||
		d = make(DictType, len(dictAny))
 | 
							d = make(DictType, len(dictAny))
 | 
				
			||||||
 | 
				
			|||||||
@ -439,8 +439,8 @@ _non-empty-list_ = "**[**" _any-value_ {"**,**" _any-value_} "**]**" +
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
| [blue]`+` | _Join_ | Joins two lists | [blue]`[1,2] + [3]` -> _[1,2,3]_
 | 
					| [blue]`+` | _Join_ | Joins two lists | [blue]`[1,2] + [3]` -> _[1,2,3]_
 | 
				
			||||||
| [blue]`-` | _Difference_ | Left list without elements in the right list  | [blue]`[1,2,3] - [2]` -> _[1,3]_
 | 
					| [blue]`-` | _Difference_ | Left list without elements in the right list  | [blue]`[1,2,3] - [2]` -> _[1,3]_
 | 
				
			||||||
| [blue]`>>` | _Front insertion_ | Insert an item in front | [blue]`0 >> [1,2]` -> _[0,1,2]_
 | 
					| [blue]`+>` | _Front insertion_ | Insert an item in front | [blue]`0 +> [1,2]` -> _[0,1,2]_
 | 
				
			||||||
| [blue]`<<` | _Back insertion_ | Insert an item at end | [blue]`[1,2] << 3` -> _[1,2,3]_
 | 
					| [blue]`<+` | _Back insertion_ | Insert an item at end | [blue]`[1,2] <+ 3` -> _[1,2,3]_
 | 
				
			||||||
| [blue]`[]` | _Item at index_ | Item at given position | [blue]`[1,2,3][1]` -> _2_
 | 
					| [blue]`[]` | _Item at index_ | Item at given position | [blue]`[1,2,3][1]` -> _2_
 | 
				
			||||||
| [blue]`in` | _Item in list_ | True if item is in list | [blue]`2 in [1,2,3]` -> _true_ +
 | 
					| [blue]`in` | _Item in list_ | True if item is in list | [blue]`2 in [1,2,3]` -> _true_ +
 | 
				
			||||||
[blue]`6 in [1,2,3]` -> _false_
 | 
					[blue]`6 in [1,2,3]` -> _false_
 | 
				
			||||||
@ -735,14 +735,17 @@ NOTE: These operators have a high priority, in particular higher than the operat
 | 
				
			|||||||
The table below shows all supported operators by decreasing priorities.
 | 
					The table below shows all supported operators by decreasing priorities.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.Operators priorities
 | 
					.Operators priorities
 | 
				
			||||||
[cols="^2,^2,^2,^5,^6"]
 | 
					[cols="^3,^2,^2,^5,^6"]
 | 
				
			||||||
|===
 | 
					|===
 | 
				
			||||||
| Priority | Operators     | Position | Operation | Operands and results
 | 
					| Priority | Operator     | Position | Operation | Operands and results
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.2+|*ITEM*| [blue]`[`...`]` | _Postfix_ | _List item_| _list_ `[`  _integer_ `]` -> _any_
 | 
					.2+|*ITEM*| [blue]`[`...`]` | _Postfix_ | _List item_| _list_ `[`  _integer_ `]` -> _any_
 | 
				
			||||||
| [blue]`[`...`]` | _Postfix_ | _Dict item_ | _dict_ `[` _any_ `]` -> _any_
 | 
					| [blue]`[`...`]` | _Postfix_ | _Dict item_ | _dict_ `[` _any_ `]` -> _any_
 | 
				
			||||||
.2+|*INC*| [blue]`++` | _Postfix_ | _Post increment_| _integer-variable_ `++` -> _integer_
 | 
					.5+|*INC/DEC*| [blue]`++` | _Postfix_ | _Iterator next item_ | _iterator_ `++` -> _any_
 | 
				
			||||||
| [blue]`++` | _Postfix_ | _Next item_ | _iterator_ `++` -> _any_
 | 
					| [blue]`++` | _Postfix_ | _Post increment_| _integer-variable_ `++` -> _integer_
 | 
				
			||||||
 | 
					| [blue]`++` | _Prefix_ | _Pre increment_ | `++` _integer-variable_ -> _integer_
 | 
				
			||||||
 | 
					| [blue]`--` | _Postfix_ | _Post decrement_ | _integer-variable_ `--` -> _integer_
 | 
				
			||||||
 | 
					| [blue]`--` | _Prefix_ | _Pre decrement_ | `--` _integer-variable_ -> _integer_
 | 
				
			||||||
.3+|*DEFAULT*| [blue]`??` | _Infix_ | _Default value_| _variable_ `??` _any-expr_ -> _any_
 | 
					.3+|*DEFAULT*| [blue]`??` | _Infix_ | _Default value_| _variable_ `??` _any-expr_ -> _any_
 | 
				
			||||||
| [blue]`?=` | _Infix_ | _Default/assign value_| _variable_ `?=` _any-expr_ -> _any_
 | 
					| [blue]`?=` | _Infix_ | _Default/assign value_| _variable_ `?=` _any-expr_ -> _any_
 | 
				
			||||||
| [blue]`?!` | _Infix_ | _Alternate value_| _variable_ `?!` _any-expr_ -> _any_
 | 
					| [blue]`?!` | _Infix_ | _Alternate value_| _variable_ `?!` _any-expr_ -> _any_
 | 
				
			||||||
@ -751,13 +754,17 @@ The table below shows all supported operators by decreasing priorities.
 | 
				
			|||||||
.3+|*SIGN*| [blue]`+`, [blue]`-` | _Prefix_ | _Change-sign_| (`+`\|`-`) _number_ -> _number_
 | 
					.3+|*SIGN*| [blue]`+`, [blue]`-` | _Prefix_ | _Change-sign_| (`+`\|`-`) _number_ -> _number_
 | 
				
			||||||
| [blue]`#` | _Prefix_ | _Lenght-of_ | `#` _collection_ -> _integer_
 | 
					| [blue]`#` | _Prefix_ | _Lenght-of_ | `#` _collection_ -> _integer_
 | 
				
			||||||
| [blue]`#` | _Prefix_ | _Size-of_ | `#` _iterator_ -> _integer_
 | 
					| [blue]`#` | _Prefix_ | _Size-of_ | `#` _iterator_ -> _integer_
 | 
				
			||||||
 | 
					.2+|*BIT SHIFT*| [blue]`<<` | _Infix_ | _Left-Shift_ | _integer_ `<<` _integer_ -> _integer_
 | 
				
			||||||
 | 
					| [blue]`>>` | _Infix_ | _Right-Shift_ | _integer_ `>>` _iterator_ -> _integer_
 | 
				
			||||||
.2+|*SELECT*| [blue]`? : ::` | _Multi-Infix_ | _Case-Selector_ | _any-expr_ `?` _case-list_ _case-expr_ `:` _case-list_ _case-expr_ ... `::` _default-expr_ -> _any_
 | 
					.2+|*SELECT*| [blue]`? : ::` | _Multi-Infix_ | _Case-Selector_ | _any-expr_ `?` _case-list_ _case-expr_ `:` _case-list_ _case-expr_ ... `::` _default-expr_ -> _any_
 | 
				
			||||||
| [blue]`? : ::` | _Multi-Infix_ | _Index-Selector_ | _int-expr_ `?` _case-expr_ `:` _case-expr_ ... `::` _default-expr_ -> _any_
 | 
					| [blue]`? : ::` | _Multi-Infix_ | _Index-Selector_ | _int-expr_ `?` _case-expr_ `:` _case-expr_ ... `::` _default-expr_ -> _any_
 | 
				
			||||||
.1+|*FRACT*| [blue]`:` | _Infix_ | _Fraction_ | _integer_ `:` _integer_ -> _fraction_
 | 
					.1+|*FRACT*| [blue]`:` | _Infix_ | _Fraction_ | _integer_ `:` _integer_ -> _fraction_
 | 
				
			||||||
.5+|*PROD*| [blue]`*` | _Infix_ | _Product_ | _number_ `*` _number_ -> _number_
 | 
					.7+|*PROD*| [blue]`*` | _Infix_ | _Product_ | _number_ `*` _number_ -> _number_
 | 
				
			||||||
| [blue]`*` | _Infix_ | _String-repeat_ | _string_ `*` _integer_ -> _string_
 | 
					| [blue]`*` | _Infix_ | _String-repeat_ | _string_ `*` _integer_ -> _string_
 | 
				
			||||||
| [blue]`/` | _Infix_ | _Division_ | _number_ `/` _number_ -> _number_
 | 
					| [blue]`/` | _Infix_ | _Division_ | _number_ `/` _number_ -> _number_
 | 
				
			||||||
| [blue]`./` | _Infix_ | _Float-division_ | __number__ `./` _number_ -> _float_
 | 
					| [blue]`./` | _Infix_ | _Float-division_ | __number__ `./` _number_ -> _float_
 | 
				
			||||||
 | 
					| [blue]`/` | _Infix_ | _Split_ | _string_ `/` _string_ -> _list_
 | 
				
			||||||
 | 
					| [blue]`/` | _Infix_ | _Split_ | _string_ `/` integer -> _list_
 | 
				
			||||||
| [blue]`%` | _Infix_ | _Integer-remainder_ | _integer_ `%` _integer_ -> _integer_
 | 
					| [blue]`%` | _Infix_ | _Integer-remainder_ | _integer_ `%` _integer_ -> _integer_
 | 
				
			||||||
.6+|*SUM*| [blue]`+` | _Infix_ | _Sum_ | _number_ `+` _number_ -> _number_
 | 
					.6+|*SUM*| [blue]`+` | _Infix_ | _Sum_ | _number_ `+` _number_ -> _number_
 | 
				
			||||||
| [blue]`+` | _Infix_ |  _String-concat_ | (_string_\|_number_) `+` (_string_\|_number_) -> _string_
 | 
					| [blue]`+` | _Infix_ |  _String-concat_ | (_string_\|_number_) `+` (_string_\|_number_) -> _string_
 | 
				
			||||||
@ -765,9 +772,10 @@ The table below shows all supported operators by decreasing priorities.
 | 
				
			|||||||
| [blue]`+` | _Infix_ |  _Dict-join_ | _dict_ `+` _dict_ -> _dict_
 | 
					| [blue]`+` | _Infix_ |  _Dict-join_ | _dict_ `+` _dict_ -> _dict_
 | 
				
			||||||
| [blue]`-` | _Infix_ | _Subtraction_ | _number_ `-` _number_ -> _number_
 | 
					| [blue]`-` | _Infix_ | _Subtraction_ | _number_ `-` _number_ -> _number_
 | 
				
			||||||
| [blue]`-` | _Infix_ | _List-difference_ | _list_ `-` _list_ -> _list_
 | 
					| [blue]`-` | _Infix_ | _List-difference_ | _list_ `-` _list_ -> _list_
 | 
				
			||||||
.3+|*BINARY*| [blue]`&` | _Infix_ | _Binary And_ | _number_ `&` _number_ -> _number_
 | 
					.1+|*BITWISE NOT*| [blue]`~` | _Prefix_ | _Binary Not_ | `~` _integer_ -> _integer_
 | 
				
			||||||
| [blue]`\|` | _Infix_ | _Binary Or_ | _number_ `\|` _number_ -> _number_
 | 
					.1+|*BITWISE AND*| [blue]`&` | _Infix_ | _Binary And_ | _integer_ `&` _integer_ -> _integer_
 | 
				
			||||||
| [blue]`~` | _Prefix_ | _Binary Not_ | `~` _number_ -> _number_
 | 
					.2+|*BITWISE OR*| [blue]`\|` | _Infix_ | _Binary Or_ | _integer_ `\|` _integer_ -> _integer_
 | 
				
			||||||
 | 
					| [blue]`^` | _Infix_ | _Binary Xor_ | _integer_ `^` _integer_ -> _integer_
 | 
				
			||||||
.8+|*RELATION*| [blue]`<` | _Infix_ | _Less_ | _comparable_ `<` _comparable_ -> _boolean_
 | 
					.8+|*RELATION*| [blue]`<` | _Infix_ | _Less_ | _comparable_ `<` _comparable_ -> _boolean_
 | 
				
			||||||
| [blue]`\<=` | _Infix_ |  _less-equal_ | _comparable_ `\<=` _comparable_ -> _boolean_
 | 
					| [blue]`\<=` | _Infix_ |  _less-equal_ | _comparable_ `\<=` _comparable_ -> _boolean_
 | 
				
			||||||
| [blue]`>` | _Infix_ |  _Greater_ | _comparable_ `>` _comparable_ -> _boolean_
 | 
					| [blue]`>` | _Infix_ |  _Greater_ | _comparable_ `>` _comparable_ -> _boolean_
 | 
				
			||||||
@ -776,20 +784,54 @@ The table below shows all supported operators by decreasing priorities.
 | 
				
			|||||||
| [blue]`!=` | _Infix_ |  _Not-equal_ | _comparable_ `!=` _comparable_ -> _boolean_
 | 
					| [blue]`!=` | _Infix_ |  _Not-equal_ | _comparable_ `!=` _comparable_ -> _boolean_
 | 
				
			||||||
| [blue]`in` | _Infix_ |  _Member-of-list_ | _any_ `in` _list_ -> _boolean_
 | 
					| [blue]`in` | _Infix_ |  _Member-of-list_ | _any_ `in` _list_ -> _boolean_
 | 
				
			||||||
| [blue]`in` | _Infix_ |  _Key-of-dict_ | _any_ `in` _dict_ -> _boolean_
 | 
					| [blue]`in` | _Infix_ |  _Key-of-dict_ | _any_ `in` _dict_ -> _boolean_
 | 
				
			||||||
.1+|*NOT*| [blue]`not` | _Prefix_ | _Not_ | `not` _boolean_ -> _boolean_
 | 
					.1+|*LOGIC NOT*| [blue]`not` | _Prefix_ | _Not_ | `not` _boolean_ -> _boolean_
 | 
				
			||||||
.2+|*AND*| [blue]`and` | _Infix_ | _And_ | _boolean_ `and` _boolean_ -> _boolean_
 | 
					.2+|*LOGIC AND*| [blue]`and` | _Infix_ | _And_ | _boolean_ `and` _boolean_ -> _boolean_
 | 
				
			||||||
| [blue]`&&` | _Infix_ | _And_ | _boolean_ `&&` _boolean_ -> _boolean_
 | 
					| [blue]`&&` | _Infix_ | _And_ | _boolean_ `&&` _boolean_ -> _boolean_
 | 
				
			||||||
.2+|*OR*| [blue]`or` | _Infix_ | _Or_ | _boolean_ `or` _boolean_ -> _boolean_
 | 
					.2+|*LOGIC OR*| [blue]`or` | _Infix_ | _Or_ | _boolean_ `or` _boolean_ -> _boolean_
 | 
				
			||||||
| [blue]`\|\|` | _Infix_ | _Or_ | _boolean_ `\|\|` _boolean_ -> _boolean_
 | 
					| [blue]`\|\|` | _Infix_ | _Or_ | _boolean_ `\|\|` _boolean_ -> _boolean_
 | 
				
			||||||
.3+|*ASSIGN*| [blue]`=` | _Infix_ | _Assignment_ | _identifier_ `=` _any_ -> _any_
 | 
					.2+|*INSERT*| [blue]`+>` | _Infix_ | _Prepend_ | _any_ `+>` _list_ -> _list_
 | 
				
			||||||
| [blue]`>>` | _Infix_ | _Front-insert_ | _any_ `>>` _list_ -> _list_
 | 
					| [blue]`<+` | _Infix_ | _Append_ | _list_ `<+` _any_ -> _list_
 | 
				
			||||||
| [blue]`<<` | _Infix_ | _Back-insert_ | _list_ `<<` _any_ -> _list_
 | 
					.2+|*ASSIGN*| [blue]`=` | _Infix_ | _Assignment_ | _identifier_ `=` _any_ -> _any_
 | 
				
			||||||
 | 
					4+| _See also the table of special allocation operators below_
 | 
				
			||||||
.1+|*BUT*| [blue]`but` | _Infix_ | _But_ | _any_ `but` _any_ -> _any_
 | 
					.1+|*BUT*| [blue]`but` | _Infix_ | _But_ | _any_ `but` _any_ -> _any_
 | 
				
			||||||
.1+|*RANGE*| [blue]`:` | _Infix_ | _Index-range_ | _integer_ `:` _integer_ -> _integer-pair_
 | 
					.1+|*RANGE*| [blue]`:` | _Infix_ | _Index-range_ | _integer_ `:` _integer_ -> _integer-pair_
 | 
				
			||||||
|===
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//^1^ Experimental
 | 
					//^1^ Experimental
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.Special assignment perators
 | 
				
			||||||
 | 
					[cols="^2,^2,^4,^6"]
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					| Priority | Operator    | Operation |Equivalent operation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.9+|*ASSIGN*| [blue]`+=` | _Sum & Assign_ | _var_ `\+=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `+` _expr_
 | 
				
			||||||
 | 
					| [blue]`-=` | _Subtract & Assign_ | _var_ `-=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `-` _expr_
 | 
				
			||||||
 | 
					| [blue]`*=` | _Multiply & Assign_ | _var_ `\*=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `*` _expr_
 | 
				
			||||||
 | 
					| [blue]`/=` | _Divide & Assign_ | _var_ `/=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `/` _expr_
 | 
				
			||||||
 | 
					| [blue]`%=` | _Remainder & Assign_ | _var_ `%=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `%` _expr_
 | 
				
			||||||
 | 
					| [blue]`&=` | _Bitwise and & Assign_ | _var_ `&=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `&` _expr_
 | 
				
			||||||
 | 
					| [blue]`\|=` | _Bitwise or & Assign_ | _var_ `\|=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `\|` _expr_
 | 
				
			||||||
 | 
					| [blue]`<\<=` | _Left shift & Assign_ | _var_ `<\<=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `<<` _expr_
 | 
				
			||||||
 | 
					| [blue]`>>=` | _Right shift & Assign_ | _var_ `>>=` _expr_  +
 | 
				
			||||||
 | 
					short for +
 | 
				
			||||||
 | 
					_var_ `=` _value-of-var_ `>>` _expr_
 | 
				
			||||||
 | 
					|===
 | 
				
			||||||
 | 
					
 | 
				
			||||||
== Functions
 | 
					== Functions
 | 
				
			||||||
Functions in _Expr_ are very similar to functions available in many programming languages. Currently, _Expr_ supports two types of function, _expr-functions_ and _go-functions_.
 | 
					Functions in _Expr_ are very similar to functions available in many programming languages. Currently, _Expr_ supports two types of function, _expr-functions_ and _go-functions_.
 | 
				
			||||||
@ -840,7 +882,7 @@ _param-name_ = _identifier_
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=== _Golang_ function definition
 | 
					=== _Golang_ function definition
 | 
				
			||||||
Description of how to define Golan functions and how to bind them to _Expr_ are topics treated in another document that I'll write, one day, maybe.
 | 
					Description of how to define Golang functions and how to bind them to _Expr_ are topics covered in another document that I'll write, one day, maybe.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
=== Function calls
 | 
					=== Function calls
 | 
				
			||||||
To call a function, either Expr or Golang type, it is necessary to specify its name and, at least, its required parameters.
 | 
					To call a function, either Expr or Golang type, it is necessary to specify its name and, at least, its required parameters.
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										226
									
								
								doc/Expr.html
									
									
									
									
									
								
							
							
						
						
									
										226
									
								
								doc/Expr.html
									
									
									
									
									
								
							@ -1380,16 +1380,16 @@ dev-expr <span class="nt">--</span> Expressions calculator v1.10.0<span class="o
 | 
				
			|||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2,3] - [2]</code> → <em>[1,3]</em></p></td>
 | 
					<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2,3] - [2]</code> → <em>[1,3]</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">>></code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">+></code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Front insertion</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Front insertion</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Insert an item in front</p></td>
 | 
					<td class="tableblock halign-left valign-top"><p class="tableblock">Insert an item in front</p></td>
 | 
				
			||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">0 >> [1,2]</code> → <em>[0,1,2]</em></p></td>
 | 
					<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">0 +> [1,2]</code> → <em>[0,1,2]</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><<</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><+</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Back insertion</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Back insertion</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Insert an item at end</p></td>
 | 
					<td class="tableblock halign-left valign-top"><p class="tableblock">Insert an item at end</p></td>
 | 
				
			||||||
<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2] << 3</code> → <em>[1,2,3]</em></p></td>
 | 
					<td class="tableblock halign-left valign-top"><p class="tableblock"><code class="blue">[1,2] <+ 3</code> → <em>[1,2,3]</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">[]</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">[]</code></p></td>
 | 
				
			||||||
@ -1900,16 +1900,16 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<table class="tableblock frame-all grid-all stretch">
 | 
					<table class="tableblock frame-all grid-all stretch">
 | 
				
			||||||
<caption class="title">Table 8. Operators priorities</caption>
 | 
					<caption class="title">Table 8. Operators priorities</caption>
 | 
				
			||||||
<colgroup>
 | 
					<colgroup>
 | 
				
			||||||
<col style="width: 11.7647%;">
 | 
					<col style="width: 16.6666%;">
 | 
				
			||||||
<col style="width: 11.7647%;">
 | 
					<col style="width: 11.1111%;">
 | 
				
			||||||
<col style="width: 11.7647%;">
 | 
					<col style="width: 11.1111%;">
 | 
				
			||||||
<col style="width: 29.4117%;">
 | 
					<col style="width: 27.7777%;">
 | 
				
			||||||
<col style="width: 35.2942%;">
 | 
					<col style="width: 33.3335%;">
 | 
				
			||||||
</colgroup>
 | 
					</colgroup>
 | 
				
			||||||
<thead>
 | 
					<thead>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<th class="tableblock halign-center valign-top">Priority</th>
 | 
					<th class="tableblock halign-center valign-top">Priority</th>
 | 
				
			||||||
<th class="tableblock halign-center valign-top">Operators</th>
 | 
					<th class="tableblock halign-center valign-top">Operator</th>
 | 
				
			||||||
<th class="tableblock halign-center valign-top">Position</th>
 | 
					<th class="tableblock halign-center valign-top">Position</th>
 | 
				
			||||||
<th class="tableblock halign-center valign-top">Operation</th>
 | 
					<th class="tableblock halign-center valign-top">Operation</th>
 | 
				
			||||||
<th class="tableblock halign-center valign-top">Operands and results</th>
 | 
					<th class="tableblock halign-center valign-top">Operands and results</th>
 | 
				
			||||||
@ -1930,7 +1930,13 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>dict</em> <code>[</code> <em>any</em> <code>]</code> → <em>any</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>dict</em> <code>[</code> <em>any</em> <code>]</code> → <em>any</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>INC</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top" rowspan="5"><p class="tableblock"><strong>INC/DEC</strong></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">++</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Postfix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Iterator next item</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>iterator</em> <code>++</code> → <em>any</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">++</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">++</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Postfix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Postfix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Post increment</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Post increment</em></p></td>
 | 
				
			||||||
@ -1938,9 +1944,21 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">++</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">++</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Pre increment</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code>++</code> <em>integer-variable</em> → <em>integer</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">--</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Postfix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Postfix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Next item</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Post decrement</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>iterator</em> <code>++</code> → <em>any</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer-variable</em> <code>--</code> → <em>integer</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">--</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Pre decrement</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code>--</code> <em>integer-variable</em> → <em>integer</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>DEFAULT</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>DEFAULT</strong></p></td>
 | 
				
			||||||
@ -1988,6 +2006,19 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>#</code> <em>iterator</em> → <em>integer</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code>#</code> <em>iterator</em> → <em>integer</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>BIT SHIFT</strong></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><<</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Left-Shift</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code><<</code> <em>integer</em> → <em>integer</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">>></code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Right-Shift</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>>></code> <em>iterator</em> → <em>integer</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>SELECT</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>SELECT</strong></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">? : ::</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">? : ::</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Multi-Infix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Multi-Infix</em></p></td>
 | 
				
			||||||
@ -2008,7 +2039,7 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>:</code> <em>integer</em> → <em>fraction</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>:</code> <em>integer</em> → <em>fraction</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="5"><p class="tableblock"><strong>PROD</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top" rowspan="7"><p class="tableblock"><strong>PROD</strong></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">*</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">*</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Product</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Product</em></p></td>
 | 
				
			||||||
@ -2033,6 +2064,18 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>./</code> <em>number</em> → <em>float</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>./</code> <em>number</em> → <em>float</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">/</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Split</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>string</em> <code>/</code> <em>string</em> → <em>list</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">/</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Split</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>string</em> <code>/</code> integer → <em>list</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">%</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">%</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Integer-remainder</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Integer-remainder</em></p></td>
 | 
				
			||||||
@ -2076,23 +2119,31 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code>-</code> <em>list</em> → <em>list</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code>-</code> <em>list</em> → <em>list</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>BINARY</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>BITWISE NOT</strong></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&</code></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary And</em></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>&</code> <em>number</em> → <em>number</em></p></td>
 | 
					 | 
				
			||||||
</tr>
 | 
					 | 
				
			||||||
<tr>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">|</code></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Or</em></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>|</code> <em>number</em> → <em>number</em></p></td>
 | 
					 | 
				
			||||||
</tr>
 | 
					 | 
				
			||||||
<tr>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">~</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">~</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Not</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Not</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>~</code> <em>number</em> → <em>number</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code>~</code> <em>integer</em> → <em>integer</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>BITWISE AND</strong></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary And</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>&</code> <em>integer</em> → <em>integer</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>BITWISE OR</strong></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">|</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Or</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>|</code> <em>integer</em> → <em>integer</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">^</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Xor</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>^</code> <em>integer</em> → <em>integer</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="8"><p class="tableblock"><strong>RELATION</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top" rowspan="8"><p class="tableblock"><strong>RELATION</strong></p></td>
 | 
				
			||||||
@ -2144,14 +2195,14 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>in</code> <em>dict</em> → <em>boolean</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>in</code> <em>dict</em> → <em>boolean</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>NOT</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>LOGIC NOT</strong></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">not</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">not</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Not</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Not</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>not</code> <em>boolean</em> → <em>boolean</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code>not</code> <em>boolean</em> → <em>boolean</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>AND</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>LOGIC AND</strong></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">and</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">and</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>And</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>And</em></p></td>
 | 
				
			||||||
@ -2164,7 +2215,7 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>&&</code> <em>boolean</em> → <em>boolean</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>&&</code> <em>boolean</em> → <em>boolean</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>OR</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>LOGIC OR</strong></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">or</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">or</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Or</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Or</em></p></td>
 | 
				
			||||||
@ -2177,23 +2228,27 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>||</code> <em>boolean</em> → <em>boolean</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>boolean</em> <code>||</code> <em>boolean</em> → <em>boolean</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>ASSIGN</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>INSERT</strong></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">+></code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prepend</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>+></code> <em>list</em> → <em>list</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><+</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Append</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code><+</code> <em>any</em> → <em>list</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top" rowspan="2"><p class="tableblock"><strong>ASSIGN</strong></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">=</code></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">=</code></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Assignment</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Assignment</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>identifier</em> <code>=</code> <em>any</em> → <em>any</em></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>identifier</em> <code>=</code> <em>any</em> → <em>any</em></p></td>
 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">>></code></p></td>
 | 
					<td class="tableblock halign-center valign-top" colspan="4"><p class="tableblock"><em>See also the table of special allocation operators below</em></p></td>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Front-insert</em></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>any</em> <code>>></code> <em>list</em> → <em>list</em></p></td>
 | 
					 | 
				
			||||||
</tr>
 | 
					 | 
				
			||||||
<tr>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><<</code></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Back-insert</em></p></td>
 | 
					 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code><<</code> <em>any</em> → <em>list</em></p></td>
 | 
					 | 
				
			||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
<tr>
 | 
					<tr>
 | 
				
			||||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>BUT</strong></p></td>
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>BUT</strong></p></td>
 | 
				
			||||||
@ -2211,6 +2266,89 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
</tr>
 | 
					</tr>
 | 
				
			||||||
</tbody>
 | 
					</tbody>
 | 
				
			||||||
</table>
 | 
					</table>
 | 
				
			||||||
 | 
					<table class="tableblock frame-all grid-all stretch">
 | 
				
			||||||
 | 
					<caption class="title">Table 9. Special assignment perators</caption>
 | 
				
			||||||
 | 
					<colgroup>
 | 
				
			||||||
 | 
					<col style="width: 14.2857%;">
 | 
				
			||||||
 | 
					<col style="width: 14.2857%;">
 | 
				
			||||||
 | 
					<col style="width: 28.5714%;">
 | 
				
			||||||
 | 
					<col style="width: 42.8572%;">
 | 
				
			||||||
 | 
					</colgroup>
 | 
				
			||||||
 | 
					<thead>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<th class="tableblock halign-center valign-top">Priority</th>
 | 
				
			||||||
 | 
					<th class="tableblock halign-center valign-top">Operator</th>
 | 
				
			||||||
 | 
					<th class="tableblock halign-center valign-top">Operation</th>
 | 
				
			||||||
 | 
					<th class="tableblock halign-center valign-top">Equivalent operation</th>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					</thead>
 | 
				
			||||||
 | 
					<tbody>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top" rowspan="9"><p class="tableblock"><strong>ASSIGN</strong></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">+=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Sum & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>+=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code>+</code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">-=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Subtract & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>-=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code>-</code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">*=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Multiply & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>*=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code>*</code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">/=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Divide & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>/=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code>/</code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">%=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Remainder & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>%=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code>%</code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Bitwise and & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>&=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code>&</code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">|=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Bitwise or & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>|=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code>|</code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><<=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Left shift & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code><<=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code><<</code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					<tr>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">>>=</code></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Right shift & Assign</em></p></td>
 | 
				
			||||||
 | 
					<td class="tableblock halign-center valign-top"><p class="tableblock"><em>var</em> <code>>>=</code> <em>expr</em> <br>
 | 
				
			||||||
 | 
					short for<br>
 | 
				
			||||||
 | 
					<em>var</em> <code>=</code> <em>value-of-var</em> <code>>></code> <em>expr</em></p></td>
 | 
				
			||||||
 | 
					</tr>
 | 
				
			||||||
 | 
					</tbody>
 | 
				
			||||||
 | 
					</table>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<div class="sect1">
 | 
					<div class="sect1">
 | 
				
			||||||
@ -2282,7 +2420,7 @@ These operators have a high priority, in particular higher than the operator <co
 | 
				
			|||||||
<div class="sect2">
 | 
					<div class="sect2">
 | 
				
			||||||
<h3 id="_golang_function_definition"><a class="anchor" href="#_golang_function_definition"></a><a class="link" href="#_golang_function_definition">6.2. <em>Golang</em> function definition</a></h3>
 | 
					<h3 id="_golang_function_definition"><a class="anchor" href="#_golang_function_definition"></a><a class="link" href="#_golang_function_definition">6.2. <em>Golang</em> function definition</a></h3>
 | 
				
			||||||
<div class="paragraph">
 | 
					<div class="paragraph">
 | 
				
			||||||
<p>Description of how to define Golan functions and how to bind them to <em>Expr</em> are topics treated in another document that I’ll write, one day, maybe.</p>
 | 
					<p>Description of how to define Golang functions and how to bind them to <em>Expr</em> are topics covered in another document that I’ll write, one day, maybe.</p>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
<div class="sect2">
 | 
					<div class="sect2">
 | 
				
			||||||
@ -2461,7 +2599,7 @@ g(@p):any{}`
 | 
				
			|||||||
</div>
 | 
					</div>
 | 
				
			||||||
<div id="footer">
 | 
					<div id="footer">
 | 
				
			||||||
<div id="footer-text">
 | 
					<div id="footer-text">
 | 
				
			||||||
Last updated 2024-12-23 07:20:48 +0100
 | 
					Last updated 2025-01-05 12:15:58 +0100
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</body>
 | 
					</body>
 | 
				
			||||||
 | 
				
			|||||||
@ -183,6 +183,16 @@ func evalOpAssign(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			|||||||
				v, err = divValues(opTerm, leftValue, rightValue)
 | 
									v, err = divValues(opTerm, leftValue, rightValue)
 | 
				
			||||||
			case SymPercEqual:
 | 
								case SymPercEqual:
 | 
				
			||||||
				v, err = remainderValues(opTerm, leftValue, rightValue)
 | 
									v, err = remainderValues(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
								case SymAmpersandEqual:
 | 
				
			||||||
 | 
									v, err = bitwiseAnd(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
								case SymVertBarEqual:
 | 
				
			||||||
 | 
									v, err = bitwiseOr(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
								case SymCaretEqual:
 | 
				
			||||||
 | 
									v, err = bitwiseXor(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
								case SymDoubleLessEqual:
 | 
				
			||||||
 | 
									v, err = bitLeftShift(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
								case SymDoubleGreaterEqual:
 | 
				
			||||||
 | 
									v, err = bitRightShift(opTerm, leftValue, rightValue)
 | 
				
			||||||
			default:
 | 
								default:
 | 
				
			||||||
				err = opTerm.Errorf("unsupported assign operator %q", opTerm.source())
 | 
									err = opTerm.Errorf("unsupported assign operator %q", opTerm.source())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -201,4 +211,10 @@ func init() {
 | 
				
			|||||||
	registerTermConstructor(SymMinusEqual, newOpAssignTerm)
 | 
						registerTermConstructor(SymMinusEqual, newOpAssignTerm)
 | 
				
			||||||
	registerTermConstructor(SymStarEqual, newOpAssignTerm)
 | 
						registerTermConstructor(SymStarEqual, newOpAssignTerm)
 | 
				
			||||||
	registerTermConstructor(SymSlashEqual, newOpAssignTerm)
 | 
						registerTermConstructor(SymSlashEqual, newOpAssignTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymPercEqual, newOpAssignTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymDoubleLessEqual, newOpAssignTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymDoubleGreaterEqual, newOpAssignTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymAmpersandEqual, newOpAssignTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymVertBarEqual, newOpAssignTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymCaretEqual, newOpAssignTerm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,104 +0,0 @@
 | 
				
			|||||||
// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | 
					 | 
				
			||||||
// All rights reserved.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// operator-binary.go
 | 
					 | 
				
			||||||
package expr
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//-------- NOT term
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newBinNotTerm(tk *Token) (inst *term) {
 | 
					 | 
				
			||||||
	return &term{
 | 
					 | 
				
			||||||
		tk:       *tk,
 | 
					 | 
				
			||||||
		children: make([]*term, 0, 1),
 | 
					 | 
				
			||||||
		position: posPrefix,
 | 
					 | 
				
			||||||
		priority: priBinary,
 | 
					 | 
				
			||||||
		evalFunc: evalBinaryNot,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func evalBinaryNot(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
					 | 
				
			||||||
	var value any
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if value, err = opTerm.evalPrefix(ctx); err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if IsInteger(value) {
 | 
					 | 
				
			||||||
		i, _ := value.(int64)
 | 
					 | 
				
			||||||
		v = ^i
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		err = opTerm.errIncompatibleType(value)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//-------- Binary AND term
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newBinAndTerm(tk *Token) (inst *term) {
 | 
					 | 
				
			||||||
	return &term{
 | 
					 | 
				
			||||||
		tk:       *tk,
 | 
					 | 
				
			||||||
		children: make([]*term, 0, 2),
 | 
					 | 
				
			||||||
		position: posInfix,
 | 
					 | 
				
			||||||
		priority: priBinary,
 | 
					 | 
				
			||||||
		evalFunc: evalBinaryAnd,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func evalBinaryAnd(ctx ExprContext, self *term) (v any, err error) {
 | 
					 | 
				
			||||||
	var leftValue, rightValue any
 | 
					 | 
				
			||||||
	var leftInt, rightInt int64
 | 
					 | 
				
			||||||
	var lok, rok bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	leftInt, lok = leftValue.(int64)
 | 
					 | 
				
			||||||
	rightInt, rok = rightValue.(int64)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if lok && rok {
 | 
					 | 
				
			||||||
		v = leftInt & rightInt
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		err = self.errIncompatibleTypes(leftValue, rightValue)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//-------- Binary OR term
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func newBinOrTerm(tk *Token) (inst *term) {
 | 
					 | 
				
			||||||
	return &term{
 | 
					 | 
				
			||||||
		tk:       *tk,
 | 
					 | 
				
			||||||
		children: make([]*term, 0, 2),
 | 
					 | 
				
			||||||
		position: posInfix,
 | 
					 | 
				
			||||||
		priority: priBinary,
 | 
					 | 
				
			||||||
		evalFunc: evalBinaryOr,
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func evalBinaryOr(ctx ExprContext, self *term) (v any, err error) {
 | 
					 | 
				
			||||||
	var leftValue, rightValue any
 | 
					 | 
				
			||||||
	var leftInt, rightInt int64
 | 
					 | 
				
			||||||
	var lok, rok bool
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if leftValue, rightValue, err = self.evalInfix(ctx); err != nil {
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	leftInt, lok = leftValue.(int64)
 | 
					 | 
				
			||||||
	rightInt, rok = rightValue.(int64)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if lok && rok {
 | 
					 | 
				
			||||||
		v = leftInt | rightInt
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		err = self.errIncompatibleTypes(leftValue, rightValue)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// init
 | 
					 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	registerTermConstructor(SymTilde, newBinNotTerm)
 | 
					 | 
				
			||||||
	registerTermConstructor(SymAmpersand, newBinAndTerm)
 | 
					 | 
				
			||||||
	registerTermConstructor(SymVertBar, newBinOrTerm)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
							
								
								
									
										154
									
								
								operator-bitwise.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										154
									
								
								operator-bitwise.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,154 @@
 | 
				
			|||||||
 | 
					// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | 
				
			||||||
 | 
					// All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// operator-bitwise.go
 | 
				
			||||||
 | 
					package expr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//-------- Bitwise NOT term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newBitwiseNotTerm(tk *Token) (inst *term) {
 | 
				
			||||||
 | 
						return &term{
 | 
				
			||||||
 | 
							tk:       *tk,
 | 
				
			||||||
 | 
							children: make([]*term, 0, 1),
 | 
				
			||||||
 | 
							position: posPrefix,
 | 
				
			||||||
 | 
							priority: priBitwiseNot,
 | 
				
			||||||
 | 
							evalFunc: evalBitwiseNot,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func evalBitwiseNot(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
 | 
						var value any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if value, err = opTerm.evalPrefix(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if IsInteger(value) {
 | 
				
			||||||
 | 
							i, _ := value.(int64)
 | 
				
			||||||
 | 
							v = ^i
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = opTerm.errIncompatibleType(value)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//-------- Bitwise AND term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newBitwiseAndTerm(tk *Token) (inst *term) {
 | 
				
			||||||
 | 
						return &term{
 | 
				
			||||||
 | 
							tk:       *tk,
 | 
				
			||||||
 | 
							children: make([]*term, 0, 2),
 | 
				
			||||||
 | 
							position: posInfix,
 | 
				
			||||||
 | 
							priority: priBitwiseAnd,
 | 
				
			||||||
 | 
							evalFunc: evalBitwiseAnd,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func bitwiseAnd(opTerm *term, leftValue, rightValue any) (v any, err error) {
 | 
				
			||||||
 | 
						var leftInt, rightInt int64
 | 
				
			||||||
 | 
						var lok, rok bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						leftInt, lok = leftValue.(int64)
 | 
				
			||||||
 | 
						rightInt, rok = rightValue.(int64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if lok && rok {
 | 
				
			||||||
 | 
							v = leftInt & rightInt
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func evalBitwiseAnd(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
 | 
						var leftValue, rightValue any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						v, err = bitwiseAnd(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//-------- Bitwise OR term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newBitwiseOrTerm(tk *Token) (inst *term) {
 | 
				
			||||||
 | 
						return &term{
 | 
				
			||||||
 | 
							tk:       *tk,
 | 
				
			||||||
 | 
							children: make([]*term, 0, 2),
 | 
				
			||||||
 | 
							position: posInfix,
 | 
				
			||||||
 | 
							priority: priBitwiseOr,
 | 
				
			||||||
 | 
							evalFunc: evalBitwiseOr,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func bitwiseOr(opTerm *term, leftValue, rightValue any) (v any, err error) {
 | 
				
			||||||
 | 
						var leftInt, rightInt int64
 | 
				
			||||||
 | 
						var lok, rok bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						leftInt, lok = leftValue.(int64)
 | 
				
			||||||
 | 
						rightInt, rok = rightValue.(int64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if lok && rok {
 | 
				
			||||||
 | 
							v = leftInt | rightInt
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func evalBitwiseOr(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
 | 
						var leftValue, rightValue any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v, err = bitwiseOr(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//-------- Bitwise XOR term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newBitwiseXorTerm(tk *Token) (inst *term) {
 | 
				
			||||||
 | 
						return &term{
 | 
				
			||||||
 | 
							tk:       *tk,
 | 
				
			||||||
 | 
							children: make([]*term, 0, 2),
 | 
				
			||||||
 | 
							position: posInfix,
 | 
				
			||||||
 | 
							priority: priBitwiseOr,
 | 
				
			||||||
 | 
							evalFunc: evalBitwiseXor,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func bitwiseXor(opTerm *term, leftValue, rightValue any) (v any, err error) {
 | 
				
			||||||
 | 
						var leftInt, rightInt int64
 | 
				
			||||||
 | 
						var lok, rok bool
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						leftInt, lok = leftValue.(int64)
 | 
				
			||||||
 | 
						rightInt, rok = rightValue.(int64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if lok && rok {
 | 
				
			||||||
 | 
							v = leftInt ^ rightInt
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func evalBitwiseXor(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
 | 
						var leftValue, rightValue any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v, err = bitwiseXor(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// init
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						registerTermConstructor(SymTilde, newBitwiseNotTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymAmpersand, newBitwiseAndTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymVertBar, newBitwiseOrTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymCaret, newBitwiseXorTerm)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -7,7 +7,6 @@ package expr
 | 
				
			|||||||
//https://www.youmath.it/lezioni/algebra-elementare/lezioni-di-algebra-e-aritmetica-per-scuole-medie/553-dalle-frazioni-a-numeri-decimali.html
 | 
					//https://www.youmath.it/lezioni/algebra-elementare/lezioni-di-algebra-e-aritmetica-per-scuole-medie/553-dalle-frazioni-a-numeri-decimali.html
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -41,7 +40,7 @@ func evalFraction(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if den == 0 {
 | 
						if den == 0 {
 | 
				
			||||||
		err = errors.New("division by zero")
 | 
							err = opTerm.errDivisionByZero()
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -4,15 +4,15 @@
 | 
				
			|||||||
// operator-insert.go
 | 
					// operator-insert.go
 | 
				
			||||||
package expr
 | 
					package expr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//-------- insert term
 | 
					//-------- prepend term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func newInsertTerm(tk *Token) (inst *term) {
 | 
					func newPrependTerm(tk *Token) (inst *term) {
 | 
				
			||||||
	return &term{
 | 
						return &term{
 | 
				
			||||||
		tk:       *tk,
 | 
							tk:       *tk,
 | 
				
			||||||
		children: make([]*term, 0, 2),
 | 
							children: make([]*term, 0, 2),
 | 
				
			||||||
		position: posInfix,
 | 
							position: posInfix,
 | 
				
			||||||
		priority: priAssign,
 | 
							priority: priInsert,
 | 
				
			||||||
		evalFunc: evalInsert,
 | 
							evalFunc: evalPrepend,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -21,12 +21,12 @@ func newAppendTerm(tk *Token) (inst *term) {
 | 
				
			|||||||
		tk:       *tk,
 | 
							tk:       *tk,
 | 
				
			||||||
		children: make([]*term, 0, 2),
 | 
							children: make([]*term, 0, 2),
 | 
				
			||||||
		position: posInfix,
 | 
							position: posInfix,
 | 
				
			||||||
		priority: priAssign,
 | 
							priority: priInsert,
 | 
				
			||||||
		evalFunc: evalAppend,
 | 
							evalFunc: evalAppend,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func evalInsert(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
					func evalPrepend(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
	var leftValue, rightValue any
 | 
						var leftValue, rightValue any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
 | 
						if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
 | 
				
			||||||
@ -40,10 +40,6 @@ func evalInsert(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			|||||||
		if opTerm.children[1].symbol() == SymVariable {
 | 
							if opTerm.children[1].symbol() == SymVariable {
 | 
				
			||||||
			ctx.UnsafeSetVar(opTerm.children[1].source(), v)
 | 
								ctx.UnsafeSetVar(opTerm.children[1].source(), v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if IsInteger(leftValue) && IsInteger(rightValue) {
 | 
					 | 
				
			||||||
		leftInt := leftValue.(int64)
 | 
					 | 
				
			||||||
		rightInt := rightValue.(int64)
 | 
					 | 
				
			||||||
		v = leftInt >> rightInt
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
							err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -64,10 +60,6 @@ func evalAppend(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			|||||||
		if opTerm.children[0].symbol() == SymVariable {
 | 
							if opTerm.children[0].symbol() == SymVariable {
 | 
				
			||||||
			ctx.UnsafeSetVar(opTerm.children[0].source(), v)
 | 
								ctx.UnsafeSetVar(opTerm.children[0].source(), v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if IsInteger(leftValue) && IsInteger(rightValue) {
 | 
					 | 
				
			||||||
		leftInt := leftValue.(int64)
 | 
					 | 
				
			||||||
		rightInt := rightValue.(int64)
 | 
					 | 
				
			||||||
		v = leftInt << rightInt
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
							err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -94,6 +86,6 @@ func evalAppend(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// init
 | 
					// init
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	registerTermConstructor(SymInsert, newInsertTerm)
 | 
						registerTermConstructor(SymPlusGreater, newPrependTerm)
 | 
				
			||||||
	registerTermConstructor(SymAppend, newAppendTerm)
 | 
						registerTermConstructor(SymLessPlus, newAppendTerm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@ func newIterValueTerm(tk *Token) (inst *term) {
 | 
				
			|||||||
		tk:       *tk,
 | 
							tk:       *tk,
 | 
				
			||||||
		children: make([]*term, 0, 1),
 | 
							children: make([]*term, 0, 1),
 | 
				
			||||||
		position: posPrefix,
 | 
							position: posPrefix,
 | 
				
			||||||
		priority: priIterValue,
 | 
							priority: priDereference,
 | 
				
			||||||
		evalFunc: evalIterValue,
 | 
							evalFunc: evalIterValue,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -34,5 +34,5 @@ func evalIterValue(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			|||||||
// init
 | 
					// init
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	//	registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
 | 
						//	registerTermConstructor(SymOpenClosedRound, newIterValueTerm)
 | 
				
			||||||
	registerTermConstructor(SymCaret, newIterValueTerm)
 | 
						registerTermConstructor(SymDereference, newIterValueTerm)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -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-post-inc.go
 | 
					// operator-post-inc-dec.go
 | 
				
			||||||
package expr
 | 
					package expr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// -------- post increment term
 | 
					// -------- post increment term
 | 
				
			||||||
							
								
								
									
										69
									
								
								operator-pre-inc-dec.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								operator-pre-inc-dec.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | 
				
			||||||
 | 
					// All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// operator-pre-inc-dec.go
 | 
				
			||||||
 | 
					package expr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -------- pre increment term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newPreIncTerm(tk *Token) *term {
 | 
				
			||||||
 | 
						return &term{
 | 
				
			||||||
 | 
							tk:       *tk,
 | 
				
			||||||
 | 
							parent:   nil,
 | 
				
			||||||
 | 
							children: make([]*term, 0, 1),
 | 
				
			||||||
 | 
							position: posPrefix,
 | 
				
			||||||
 | 
							priority: priIncDec,
 | 
				
			||||||
 | 
							evalFunc: evalPreInc,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func evalPreInc(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
 | 
						var childValue any
 | 
				
			||||||
 | 
						if childValue, err = opTerm.evalPrefix(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
 | 
				
			||||||
 | 
							i := childValue.(int64) + 1
 | 
				
			||||||
 | 
							ctx.SetVar(opTerm.children[0].source(), i)
 | 
				
			||||||
 | 
							v = i
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = opTerm.errIncompatibleType(childValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// -------- pre decrement term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newPreDecTerm(tk *Token) *term {
 | 
				
			||||||
 | 
						return &term{
 | 
				
			||||||
 | 
							tk:       *tk,
 | 
				
			||||||
 | 
							parent:   nil,
 | 
				
			||||||
 | 
							children: make([]*term, 0, 1),
 | 
				
			||||||
 | 
							position: posPrefix,
 | 
				
			||||||
 | 
							priority: priIncDec,
 | 
				
			||||||
 | 
							evalFunc: evalPreDec,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func evalPreDec(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
 | 
						var childValue any
 | 
				
			||||||
 | 
						if childValue, err = opTerm.evalPrefix(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if IsInteger(childValue) && opTerm.children[0].symbol() == SymVariable {
 | 
				
			||||||
 | 
							i := childValue.(int64) - 1
 | 
				
			||||||
 | 
							ctx.SetVar(opTerm.children[0].source(), i)
 | 
				
			||||||
 | 
							v = i
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = opTerm.errIncompatibleType(childValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// init
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						registerTermConstructor(SymPreInc, newPreIncTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymPreDec, newPreDecTerm)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -5,7 +5,6 @@
 | 
				
			|||||||
package expr
 | 
					package expr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -69,7 +68,7 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
 | 
				
			|||||||
		if IsFloat(leftValue) || IsFloat(rightValue) {
 | 
							if IsFloat(leftValue) || IsFloat(rightValue) {
 | 
				
			||||||
			d := numAsFloat(rightValue)
 | 
								d := numAsFloat(rightValue)
 | 
				
			||||||
			if d == 0.0 {
 | 
								if d == 0.0 {
 | 
				
			||||||
				err = errors.New("division by zero")
 | 
									err = opTerm.errDivisionByZero()
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				v = numAsFloat(leftValue) / d
 | 
									v = numAsFloat(leftValue) / d
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -78,11 +77,36 @@ func divValues(opTerm *term, leftValue, rightValue any) (v any, err error) {
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			leftInt, _ := leftValue.(int64)
 | 
								leftInt, _ := leftValue.(int64)
 | 
				
			||||||
			if rightInt, _ := rightValue.(int64); rightInt == 0 {
 | 
								if rightInt, _ := rightValue.(int64); rightInt == 0 {
 | 
				
			||||||
				err = errors.New("division by zero")
 | 
									err = opTerm.errDivisionByZero()
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				v = leftInt / rightInt
 | 
									v = leftInt / rightInt
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						} else if IsString(leftValue) && IsString(rightValue) {
 | 
				
			||||||
 | 
							source := leftValue.(string)
 | 
				
			||||||
 | 
							sep := rightValue.(string)
 | 
				
			||||||
 | 
							v = ListFromStrings(strings.Split(source, sep))
 | 
				
			||||||
 | 
						} else if IsString(leftValue) && IsInteger(rightValue) {
 | 
				
			||||||
 | 
							source := leftValue.(string)
 | 
				
			||||||
 | 
							partSize := int(rightValue.(int64))
 | 
				
			||||||
 | 
							if partSize == 0 {
 | 
				
			||||||
 | 
								err = opTerm.errDivisionByZero()
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								partCount := len(source) / partSize
 | 
				
			||||||
 | 
								remainder := len(source) % partSize
 | 
				
			||||||
 | 
								listSize := partCount
 | 
				
			||||||
 | 
								if remainder > 0 {
 | 
				
			||||||
 | 
									listSize++
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								parts := make([]any, 0, listSize)
 | 
				
			||||||
 | 
								for i := 0; i < partCount; i++ {
 | 
				
			||||||
 | 
									parts = append(parts, source[i*partSize:(i+1)*partSize])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if remainder > 0 {
 | 
				
			||||||
 | 
									parts = append(parts, source[len(source)-remainder:])
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								v = newList(parts)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
							err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -121,7 +145,7 @@ func evalDivideAsFloat(ctx ExprContext, floatDivTerm *term) (v any, err error) {
 | 
				
			|||||||
	if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
 | 
						if isNumOrFract(leftValue) && isNumOrFract(rightValue) {
 | 
				
			||||||
		d := numAsFloat(rightValue)
 | 
							d := numAsFloat(rightValue)
 | 
				
			||||||
		if d == 0.0 {
 | 
							if d == 0.0 {
 | 
				
			||||||
			err = errors.New("division by zero")
 | 
								err = floatDivTerm.errDivisionByZero()
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			v = numAsFloat(leftValue) / d
 | 
								v = numAsFloat(leftValue) / d
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@ -146,7 +170,7 @@ func remainderValues(opTerm *term, leftValue, rightValue any) (v any, err error)
 | 
				
			|||||||
	if IsInteger(leftValue) && IsInteger(rightValue) {
 | 
						if IsInteger(leftValue) && IsInteger(rightValue) {
 | 
				
			||||||
		rightInt, _ := rightValue.(int64)
 | 
							rightInt, _ := rightValue.(int64)
 | 
				
			||||||
		if rightInt == 0 {
 | 
							if rightInt == 0 {
 | 
				
			||||||
			err = errors.New("division by zero")
 | 
								err = opTerm.errDivisionByZero()
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			leftInt, _ := leftValue.(int64)
 | 
								leftInt, _ := leftValue.(int64)
 | 
				
			||||||
			v = leftInt % rightInt
 | 
								v = leftInt % rightInt
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										77
									
								
								operator-shift.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								operator-shift.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,77 @@
 | 
				
			|||||||
 | 
					// Copyright (c) 2024 Celestino Amoroso (celestino.amoroso@gmail.com).
 | 
				
			||||||
 | 
					// All rights reserved.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// operator-shift.go
 | 
				
			||||||
 | 
					package expr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//-------- bit right shift term
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newRightShiftTerm(tk *Token) (inst *term) {
 | 
				
			||||||
 | 
						return &term{
 | 
				
			||||||
 | 
							tk:       *tk,
 | 
				
			||||||
 | 
							children: make([]*term, 0, 2),
 | 
				
			||||||
 | 
							position: posInfix,
 | 
				
			||||||
 | 
							priority: priBinShift,
 | 
				
			||||||
 | 
							evalFunc: evalRightShift,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func bitRightShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
 | 
				
			||||||
 | 
						if IsInteger(leftValue) && IsInteger(rightValue) {
 | 
				
			||||||
 | 
							leftInt := leftValue.(int64)
 | 
				
			||||||
 | 
							rightInt := rightValue.(int64)
 | 
				
			||||||
 | 
							v = leftInt >> rightInt
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func evalRightShift(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
 | 
						var leftValue, rightValue any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v, err = bitRightShift(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newLeftShiftTerm(tk *Token) (inst *term) {
 | 
				
			||||||
 | 
						return &term{
 | 
				
			||||||
 | 
							tk:       *tk,
 | 
				
			||||||
 | 
							children: make([]*term, 0, 2),
 | 
				
			||||||
 | 
							position: posInfix,
 | 
				
			||||||
 | 
							priority: priBinShift,
 | 
				
			||||||
 | 
							evalFunc: evalLeftShift,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func bitLeftShift(opTerm *term, leftValue, rightValue any) (v any, err error) {
 | 
				
			||||||
 | 
						if IsInteger(leftValue) && IsInteger(rightValue) {
 | 
				
			||||||
 | 
							leftInt := leftValue.(int64)
 | 
				
			||||||
 | 
							rightInt := rightValue.(int64)
 | 
				
			||||||
 | 
							v = leftInt << rightInt
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							err = opTerm.errIncompatibleTypes(leftValue, rightValue)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func evalLeftShift(ctx ExprContext, opTerm *term) (v any, err error) {
 | 
				
			||||||
 | 
						var leftValue, rightValue any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if leftValue, rightValue, err = opTerm.evalInfix(ctx); err != nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						v, err = bitLeftShift(opTerm, leftValue, rightValue)
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// init
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						registerTermConstructor(SymDoubleGreater, newRightShiftTerm)
 | 
				
			||||||
 | 
						registerTermConstructor(SymDoubleLess, newLeftShiftTerm)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										51
									
								
								parser.go
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								parser.go
									
									
									
									
									
								
							@ -409,6 +409,23 @@ func listSubTree(tree *ast, listTerm *term, allowIndeces bool) (root *term, err
 | 
				
			|||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func changePrefix(tk *Token) {
 | 
				
			||||||
 | 
						switch tk.Sym {
 | 
				
			||||||
 | 
						case SymMinus:
 | 
				
			||||||
 | 
							tk.SetSymbol(SymChangeSign)
 | 
				
			||||||
 | 
						case SymPlus:
 | 
				
			||||||
 | 
							tk.SetSymbol(SymUnchangeSign)
 | 
				
			||||||
 | 
						case SymStar:
 | 
				
			||||||
 | 
							tk.SetSymbol(SymDereference)
 | 
				
			||||||
 | 
						case SymExclamation:
 | 
				
			||||||
 | 
							tk.SetSymbol(SymNot)
 | 
				
			||||||
 | 
						case SymDoublePlus:
 | 
				
			||||||
 | 
							tk.SetSymbol(SymPreInc)
 | 
				
			||||||
 | 
						case SymDoubleMinus:
 | 
				
			||||||
 | 
							tk.SetSymbol(SymPreDec)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymbols ...Symbol) (tree *ast, err error) {
 | 
					func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymbols ...Symbol) (tree *ast, err error) {
 | 
				
			||||||
	var selectorTerm *term = nil
 | 
						var selectorTerm *term = nil
 | 
				
			||||||
	var currentTerm *term = nil
 | 
						var currentTerm *term = nil
 | 
				
			||||||
@ -437,14 +454,16 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		//fmt.Println("Token:", tk)
 | 
							//fmt.Println("Token:", tk)
 | 
				
			||||||
		if firstToken {
 | 
							if firstToken {
 | 
				
			||||||
			if tk.Sym == SymMinus {
 | 
								changePrefix(tk)
 | 
				
			||||||
				tk.Sym = SymChangeSign
 | 
								// if tk.Sym == SymMinus {
 | 
				
			||||||
			} else if tk.Sym == SymPlus {
 | 
								// 	tk.Sym = SymChangeSign
 | 
				
			||||||
				tk.Sym = SymUnchangeSign
 | 
								// } else if tk.Sym == SymPlus {
 | 
				
			||||||
			} else if tk.IsSymbol(SymExclamation) {
 | 
								// 	tk.Sym = SymUnchangeSign
 | 
				
			||||||
				err = tk.Errorf("postfix opertor %q requires an operand on its left", tk)
 | 
								// } else if tk.IsSymbol(SymStar) {
 | 
				
			||||||
				break
 | 
								// 	tk.SetSymbol(SymDereference)
 | 
				
			||||||
			}
 | 
								// } else if tk.IsSymbol(SymExclamation) {
 | 
				
			||||||
 | 
								// 	tk.SetSymbol(SymNot)
 | 
				
			||||||
 | 
								// }
 | 
				
			||||||
			firstToken = false
 | 
								firstToken = false
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -452,9 +471,12 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
 | 
				
			|||||||
		case SymOpenRound:
 | 
							case SymOpenRound:
 | 
				
			||||||
			var subTree *ast
 | 
								var subTree *ast
 | 
				
			||||||
			if subTree, err = parser.parseGeneral(scanner, ctx, SymClosedRound); err == nil {
 | 
								if subTree, err = parser.parseGeneral(scanner, ctx, SymClosedRound); err == nil {
 | 
				
			||||||
				subTree.root.priority = priValue
 | 
									exprTerm := newExprTerm(subTree.root)
 | 
				
			||||||
				err = tree.addTerm(newExprTerm(subTree.root))
 | 
									err = tree.addTerm(exprTerm)
 | 
				
			||||||
				currentTerm = subTree.root
 | 
									currentTerm = exprTerm
 | 
				
			||||||
 | 
									// subTree.root.priority = priValue
 | 
				
			||||||
 | 
									// err = tree.addTerm(newExprTerm(subTree.root))
 | 
				
			||||||
 | 
									// currentTerm = subTree.root
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case SymFuncCall:
 | 
							case SymFuncCall:
 | 
				
			||||||
			var funcCallTerm *term
 | 
								var funcCallTerm *term
 | 
				
			||||||
@ -478,7 +500,7 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
 | 
				
			|||||||
					currentTerm = mapTerm
 | 
										currentTerm = mapTerm
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual:
 | 
							case SymEqual, SymPlusEqual, SymMinusEqual, SymStarEqual, SymSlashEqual, SymPercEqual, SymAmpersandEqual, SymVertBarEqual, SymDoubleLessEqual, SymDoubleGreaterEqual, SymCaretEqual:
 | 
				
			||||||
			currentTerm, err = tree.addToken(tk)
 | 
								currentTerm, err = tree.addToken(tk)
 | 
				
			||||||
			firstToken = true
 | 
								firstToken = true
 | 
				
			||||||
		case SymFuncDef:
 | 
							case SymFuncDef:
 | 
				
			||||||
@ -515,15 +537,12 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
 | 
				
			|||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				// if hasFlag(ctx, allowIndex) {
 | 
					 | 
				
			||||||
				// 	tk.Sym = SymRange
 | 
					 | 
				
			||||||
				// }
 | 
					 | 
				
			||||||
				currentTerm, err = tree.addToken(tk)
 | 
									currentTerm, err = tree.addToken(tk)
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
				if tk.IsOneOfA(SymColon, SymRange) {
 | 
									if tk.IsOneOfA(SymColon, SymRange) {
 | 
				
			||||||
					// Colon outside a selector term acts like a separator
 | 
										// Colon outside a selector term acts like a separator
 | 
				
			||||||
					firstToken = true
 | 
										firstToken = true
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			currentTerm, err = tree.addToken(tk)
 | 
								currentTerm, err = tree.addToken(tk)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										43
									
								
								scanner.go
									
									
									
									
									
								
							
							
						
						
									
										43
									
								
								scanner.go
									
									
									
									
									
								
							@ -124,6 +124,8 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
 | 
				
			|||||||
				tk = scanner.moveOn(SymDoublePlus, ch, next)
 | 
									tk = scanner.moveOn(SymDoublePlus, ch, next)
 | 
				
			||||||
			} else if next == '=' {
 | 
								} else if next == '=' {
 | 
				
			||||||
				tk = scanner.moveOn(SymPlusEqual, ch, next)
 | 
									tk = scanner.moveOn(SymPlusEqual, ch, next)
 | 
				
			||||||
 | 
								} else if next == '>' {
 | 
				
			||||||
 | 
									tk = scanner.moveOn(SymPlusGreater, ch, next)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				tk = scanner.makeToken(SymPlus, ch)
 | 
									tk = scanner.makeToken(SymPlus, ch)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -167,13 +169,19 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
 | 
				
			|||||||
		case '|':
 | 
							case '|':
 | 
				
			||||||
			if next, _ := scanner.peek(); next == '|' {
 | 
								if next, _ := scanner.peek(); next == '|' {
 | 
				
			||||||
				tk = scanner.moveOn(SymDoubleVertBar, ch, next)
 | 
									tk = scanner.moveOn(SymDoubleVertBar, ch, next)
 | 
				
			||||||
 | 
								} else if next, _ = scanner.peek(); next == '=' {
 | 
				
			||||||
 | 
									tk = scanner.moveOn(SymVertBarEqual, ch, next)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				tk = scanner.makeToken(SymVertBar, ch)
 | 
									tk = scanner.makeToken(SymVertBar, ch)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case ',':
 | 
							case ',':
 | 
				
			||||||
			tk = scanner.makeToken(SymComma, ch)
 | 
								tk = scanner.makeToken(SymComma, ch)
 | 
				
			||||||
		case '^':
 | 
							case '^':
 | 
				
			||||||
 | 
								if next, _ := scanner.peek(); next == '=' {
 | 
				
			||||||
 | 
									tk = scanner.moveOn(SymCaretEqual, ch, next)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
				tk = scanner.makeToken(SymCaret, ch)
 | 
									tk = scanner.makeToken(SymCaret, ch)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		case ':':
 | 
							case ':':
 | 
				
			||||||
			if next, _ := scanner.peek(); next == ':' {
 | 
								if next, _ := scanner.peek(); next == ':' {
 | 
				
			||||||
				tk = scanner.moveOn(SymDoubleColon, ch, next)
 | 
									tk = scanner.moveOn(SymDoubleColon, ch, next)
 | 
				
			||||||
@ -232,11 +240,17 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
 | 
				
			|||||||
		case '&':
 | 
							case '&':
 | 
				
			||||||
			if next, _ := scanner.peek(); next == '&' {
 | 
								if next, _ := scanner.peek(); next == '&' {
 | 
				
			||||||
				tk = scanner.moveOn(SymDoubleAmpersand, ch, next)
 | 
									tk = scanner.moveOn(SymDoubleAmpersand, ch, next)
 | 
				
			||||||
 | 
								} else if next, _ = scanner.peek(); next == '=' {
 | 
				
			||||||
 | 
									tk = scanner.moveOn(SymAmpersandEqual, ch, next)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				tk = scanner.makeToken(SymAmpersand, ch)
 | 
									tk = scanner.makeToken(SymAmpersand, ch)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case '%':
 | 
							case '%':
 | 
				
			||||||
 | 
								if next, _ := scanner.peek(); next == '=' {
 | 
				
			||||||
 | 
									tk = scanner.moveOn(SymPercEqual, ch, next)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
				tk = scanner.makeToken(SymPercent, ch)
 | 
									tk = scanner.makeToken(SymPercent, ch)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		case '#':
 | 
							case '#':
 | 
				
			||||||
			tk = scanner.makeToken(SymHash, ch)
 | 
								tk = scanner.makeToken(SymHash, ch)
 | 
				
			||||||
		case '@':
 | 
							case '@':
 | 
				
			||||||
@ -265,9 +279,18 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
 | 
				
			|||||||
			if next, _ := scanner.peek(); next == '=' {
 | 
								if next, _ := scanner.peek(); next == '=' {
 | 
				
			||||||
				tk = scanner.moveOn(SymLessOrEqual, ch, next)
 | 
									tk = scanner.moveOn(SymLessOrEqual, ch, next)
 | 
				
			||||||
			} else if next == '<' {
 | 
								} else if next == '<' {
 | 
				
			||||||
				tk = scanner.moveOn(SymAppend, ch, next)
 | 
									scanner.readChar()
 | 
				
			||||||
 | 
									next2, _ := scanner.readChar()
 | 
				
			||||||
 | 
									scanner.unreadChar()
 | 
				
			||||||
 | 
									if next2 == '=' {
 | 
				
			||||||
 | 
										tk = scanner.moveOn(SymDoubleLessEqual, ch, next, next2)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										tk = scanner.accept(SymDoubleLess, ch, next)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			} else if next == '>' {
 | 
								} else if next == '>' {
 | 
				
			||||||
				tk = scanner.moveOn(SymLessGreater, ch, next)
 | 
									tk = scanner.moveOn(SymLessGreater, ch, next)
 | 
				
			||||||
 | 
								} else if next == '+' {
 | 
				
			||||||
 | 
									tk = scanner.moveOn(SymLessPlus, ch, next)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				tk = scanner.makeToken(SymLess, ch)
 | 
									tk = scanner.makeToken(SymLess, ch)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -275,7 +298,14 @@ func (scanner *scanner) fetchNextToken() (tk *Token) {
 | 
				
			|||||||
			if next, _ := scanner.peek(); next == '=' {
 | 
								if next, _ := scanner.peek(); next == '=' {
 | 
				
			||||||
				tk = scanner.moveOn(SymGreaterOrEqual, ch, next)
 | 
									tk = scanner.moveOn(SymGreaterOrEqual, ch, next)
 | 
				
			||||||
			} else if next == '>' {
 | 
								} else if next == '>' {
 | 
				
			||||||
				tk = scanner.moveOn(SymInsert, ch, next)
 | 
									scanner.readChar()
 | 
				
			||||||
 | 
									next2, _ := scanner.readChar()
 | 
				
			||||||
 | 
									scanner.unreadChar()
 | 
				
			||||||
 | 
									if next2 == '=' {
 | 
				
			||||||
 | 
										tk = scanner.moveOn(SymDoubleGreaterEqual, ch, next, next2)
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										tk = scanner.accept(SymDoubleGreater, ch, next)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				tk = scanner.makeToken(SymGreater, ch)
 | 
									tk = scanner.makeToken(SymGreater, ch)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@ -630,9 +660,16 @@ func (scanner *scanner) translate(sym Symbol) Symbol {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) {
 | 
					func (scanner *scanner) moveOn(sym Symbol, chars ...byte) (tk *Token) {
 | 
				
			||||||
	tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
 | 
						tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
 | 
				
			||||||
	for i := 1; i < len(chars); i++ {
 | 
						// for i := 1; i < len(chars); i++ {
 | 
				
			||||||
 | 
						if len(chars) > 1 {
 | 
				
			||||||
		scanner.readChar()
 | 
							scanner.readChar()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						// }
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (scanner *scanner) accept(sym Symbol, chars ...byte) (tk *Token) {
 | 
				
			||||||
 | 
						tk = NewToken(scanner.row, scanner.column, scanner.translate(sym), string(chars))
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										175
									
								
								symbol-map.go
									
									
									
									
									
								
							
							
						
						
									
										175
									
								
								symbol-map.go
									
									
									
									
									
								
							@ -14,7 +14,7 @@ type symbolClass int16
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	symClassOperator symbolClass = iota
 | 
						symClassOperator symbolClass = iota
 | 
				
			||||||
	symClassPostOp
 | 
						symClassCommand
 | 
				
			||||||
	symClassIdentifier
 | 
						symClassIdentifier
 | 
				
			||||||
	symClassDelimiter
 | 
						symClassDelimiter
 | 
				
			||||||
	symClassParenthesis
 | 
						symClassParenthesis
 | 
				
			||||||
@ -26,75 +26,85 @@ const (
 | 
				
			|||||||
type symbolSpec struct {
 | 
					type symbolSpec struct {
 | 
				
			||||||
	repr   string
 | 
						repr   string
 | 
				
			||||||
	kind   symbolClass
 | 
						kind   symbolClass
 | 
				
			||||||
 | 
						opType termPosition
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	symbolMap = map[Symbol]symbolSpec{
 | 
						symbolMap = map[Symbol]symbolSpec{
 | 
				
			||||||
		SymUnknown:         {"<unknown>", symClassOther}, //  -1: Unknown symbol
 | 
							SymUnknown:            {"<unknown>", symClassOther, posLeaf},  //  -1: Unknown symbol
 | 
				
			||||||
		SymNone:            {"<null>", symClassOther},    //   0: Null value for variable of type symbol
 | 
							SymNone:               {"<null>", symClassOther, posLeaf},     //   0: Null value for variable of type symbol
 | 
				
			||||||
		SymError:           {"<error>", symClassOther},   //   1: Error reading from stream
 | 
							SymError:              {"<error>", symClassOther, posLeaf},    //   1: Error reading from stream
 | 
				
			||||||
		SymEos:             {"<eos>", symClassOther},     //   2: End of stream
 | 
							SymEos:                {"<eos>", symClassOther, posLeaf},      //   2: End of stream
 | 
				
			||||||
		SymMinus:           {"-", symClassOperator},      //   3: '-'
 | 
							SymMinus:              {"-", symClassOperator, posInfix},      //   3: '-'
 | 
				
			||||||
		SymMinusEqual:      {"-=", symClassOperator},     //   4: '-='
 | 
							SymMinusEqual:         {"-=", symClassOperator, posInfix},     //   4: '-='
 | 
				
			||||||
		SymDoubleMinus:     {"--", symClassOperator},     //   5: '--'
 | 
							SymDoubleMinus:        {"--", symClassOperator, posPostfix},   //   5: '--'
 | 
				
			||||||
		SymPlus:            {"+", symClassOperator},      //   6: '+'
 | 
							SymPlus:               {"+", symClassOperator, posInfix},      //   6: '+'
 | 
				
			||||||
		SymPlusEqual:       {"+=", symClassOperator},     //   7: '+='
 | 
							SymPlusEqual:          {"+=", symClassOperator, posInfix},     //   7: '+='
 | 
				
			||||||
		SymDoublePlus:      {"++", symClassOperator},     //   8: '++'
 | 
							SymDoublePlus:         {"++", symClassOperator, posPostfix},   //   8: '++'
 | 
				
			||||||
		SymStar:            {"*", symClassOperator},      //   9: '*'
 | 
							SymStar:               {"*", symClassOperator, posInfix},      //   9: '*'
 | 
				
			||||||
		SymDoubleStar:      {"**", symClassOperator},     //  10: '**'
 | 
							SymDoubleStar:         {"**", symClassOperator, posInfix},     //  10: '**'
 | 
				
			||||||
		SymSlash:           {"/", symClassOperator},      //  11: '/'
 | 
							SymSlash:              {"/", symClassOperator, posInfix},      //  11: '/'
 | 
				
			||||||
		SymBackSlash:       {"\\", symClassOperator},     //  12: '\'
 | 
							SymBackSlash:          {"\\", symClassOperator, posLeaf},      //  12: '\'
 | 
				
			||||||
		SymVertBar:         {"|", symClassOperator},      //  13: '|'
 | 
							SymVertBar:            {"|", symClassOperator, posInfix},      //  13: '|'
 | 
				
			||||||
		SymDoubleVertBar:   {"||", symClassOperator},     //  14: '||'
 | 
							SymDoubleVertBar:      {"||", symClassOperator, posInfix},     //  14: '||'
 | 
				
			||||||
		SymComma:           {",", symClassOperator},      //  15: ','
 | 
							SymComma:              {",", symClassOperator, posInfix},      //  15: ','
 | 
				
			||||||
		SymColon:           {":", symClassOperator},      //  16: ':'
 | 
							SymColon:              {":", symClassOperator, posInfix},      //  16: ':'
 | 
				
			||||||
		SymSemiColon:       {";", symClassOperator},      //  17: ';'
 | 
							SymSemiColon:          {";", symClassOperator, posInfix},      //  17: ';'
 | 
				
			||||||
		SymDot:             {".", symClassOperator},      //  18: '.'
 | 
							SymDot:                {".", symClassOperator, posInfix},      //  18: '.'
 | 
				
			||||||
		SymDotSlash:        {"./", symClassOperator},     //  19: './'
 | 
							SymDotSlash:           {"./", symClassOperator, posInfix},     //  19: './'
 | 
				
			||||||
		SymQuote:           {"'", symClassDelimiter},     //  20: '\''
 | 
							SymQuote:              {"'", symClassDelimiter, posLeaf},      //  20: '\''
 | 
				
			||||||
		SymDoubleQuote:     {"\"", symClassDelimiter},    //  21: '"'
 | 
							SymDoubleQuote:        {"\"", symClassDelimiter, posLeaf},     //  21: '"'
 | 
				
			||||||
		SymBackTick:        {"`", symClassOperator},      //  22: '`'
 | 
							SymBackTick:           {"`", symClassDelimiter, posLeaf},      //  22: '`'
 | 
				
			||||||
		SymExclamation:     {"!", symClassPostOp},        //  23: '!'
 | 
							SymExclamation:        {"!", symClassOperator, posPostfix},    //  23: '!'
 | 
				
			||||||
		SymQuestion:        {"?", symClassOperator},      //  24: '?'
 | 
							SymQuestion:           {"?", symClassOperator, posInfix},      //  24: '?'
 | 
				
			||||||
		SymAmpersand:       {"&", symClassOperator},      //  25: '&'
 | 
							SymAmpersand:          {"&", symClassOperator, posInfix},      //  25: '&'
 | 
				
			||||||
		SymDoubleAmpersand: {"&&", symClassOperator},     //  26: '&&'
 | 
							SymDoubleAmpersand:    {"&&", symClassOperator, posInfix},     //  26: '&&'
 | 
				
			||||||
		SymPercent:         {"%", symClassOperator},      //  27: '%'
 | 
							SymPercent:            {"%", symClassOperator, posInfix},      //  27: '%'
 | 
				
			||||||
		SymAt:              {"@", symClassOperator},      //  28: '@'
 | 
							SymAt:                 {"@", symClassOperator, posPrefix},     //  28: '@'
 | 
				
			||||||
		SymUndescore:       {"_", symClassOperator},      //  29: '_'
 | 
							SymUndescore:          {"_", symClassIdentifier, posLeaf},     //  29: '_'
 | 
				
			||||||
		SymEqual:           {"=", symClassOperator},      //  30: '='
 | 
							SymEqual:              {"=", symClassOperator, posInfix},      //  30: '='
 | 
				
			||||||
		SymDoubleEqual:     {"==", symClassOperator},     //  31: '=='
 | 
							SymDoubleEqual:        {"==", symClassOperator, posInfix},     //  31: '=='
 | 
				
			||||||
		SymLess:            {"<", symClassOperator},      //  32: '<'
 | 
							SymLess:               {"<", symClassOperator, posInfix},      //  32: '<'
 | 
				
			||||||
		SymLessOrEqual:     {"<=", symClassOperator},     //  33: '<='
 | 
							SymLessOrEqual:        {"<=", symClassOperator, posInfix},     //  33: '<='
 | 
				
			||||||
		SymGreater:         {">", symClassOperator},      //  34: '>'
 | 
							SymGreater:            {">", symClassOperator, posInfix},      //  34: '>'
 | 
				
			||||||
		SymGreaterOrEqual:  {">=", symClassOperator},     //  35: '>='
 | 
							SymGreaterOrEqual:     {">=", symClassOperator, posInfix},     //  35: '>='
 | 
				
			||||||
		SymLessGreater:     {"<>", symClassOperator},     //  36: '<>'
 | 
							SymLessGreater:        {"<>", symClassOperator, posInfix},     //  36: '<>'
 | 
				
			||||||
		SymNotEqual:        {"!=", symClassOperator},     //  37: '!='
 | 
							SymNotEqual:           {"!=", symClassOperator, posInfix},     //  37: '!='
 | 
				
			||||||
		SymDollar:          {"$", symClassOperator},      //  38: '$'
 | 
							SymDollar:             {"$", symClassOperator, posPrefix},     //  38: '$'
 | 
				
			||||||
		SymHash:            {"#", symClassOperator},      //  39: '#'
 | 
							SymHash:               {"#", symClassOperator, posPrefix},     //  39: '#'
 | 
				
			||||||
		SymOpenRound:       {"(", symClassParenthesis},   //  40: '('
 | 
							SymOpenRound:          {"(", symClassParenthesis, posPrefix},  //  40: '('
 | 
				
			||||||
		SymClosedRound:     {")", symClassParenthesis},   //  41: ')'
 | 
							SymClosedRound:        {")", symClassParenthesis, posPostfix}, //  41: ')'
 | 
				
			||||||
		SymOpenSquare:      {"[", symClassParenthesis},   //  42: '['
 | 
							SymOpenSquare:         {"[", symClassParenthesis, posPrefix},  //  42: '['
 | 
				
			||||||
		SymClosedSquare:    {"]", symClassParenthesis},   //  43: ']'
 | 
							SymClosedSquare:       {"]", symClassParenthesis, posPostfix}, //  43: ']'
 | 
				
			||||||
		SymOpenBrace:       {"{", symClassParenthesis},   //  44: '{'
 | 
							SymOpenBrace:          {"{", symClassParenthesis, posPrefix},  //  44: '{'
 | 
				
			||||||
		SymClosedBrace:     {"}", symClassParenthesis},   //  45: '}'
 | 
							SymClosedBrace:        {"}", symClassParenthesis, posPostfix}, //  45: '}'
 | 
				
			||||||
		SymTilde:           {"~", symClassOperator},      //  46: '~'
 | 
							SymTilde:              {"~", symClassOperator, posPrefix},     //  46: '~'
 | 
				
			||||||
		SymDoubleQuestion:  {"??", symClassOperator},     //  47: '??'
 | 
							SymDoubleQuestion:     {"??", symClassOperator, posInfix},     //  47: '??'
 | 
				
			||||||
		SymQuestionEqual:   {"?=", symClassOperator},     //  48: '?='
 | 
							SymQuestionEqual:      {"?=", symClassOperator, posInfix},     //  48: '?='
 | 
				
			||||||
		SymQuestionExclam:  {"?!", symClassOperator},     //  49: '?!'
 | 
							SymQuestionExclam:     {"?!", symClassOperator, posInfix},     //  49: '?!'
 | 
				
			||||||
		SymDoubleAt:        {"@@", symClassOperator},     //  50: '@@'
 | 
							SymDoubleAt:           {"@@", symClassCommand, posLeaf},       //  50: '@@'
 | 
				
			||||||
		SymDoubleColon:     {"::", symClassOperator},     //  51: '::'
 | 
							SymDoubleColon:        {"::", symClassOperator, posInfix},     //  51: '::'
 | 
				
			||||||
		SymInsert:          {">>", symClassOperator},     //  52: '>>'
 | 
							SymDoubleGreater:      {">>", symClassOperator, posInfix},     //  52: '>>'
 | 
				
			||||||
		SymAppend:          {"<<", symClassOperator},     //  53: '<<'
 | 
							SymDoubleLess:         {"<<", symClassOperator, posInfix},     //  53: '<<'
 | 
				
			||||||
		SymCaret:           {"^", symClassOperator},      //  54: '^'
 | 
							SymCaret:              {"^", symClassOperator, posInfix},      //  54: '^'
 | 
				
			||||||
		SymDollarRound:     {"$(", symClassOperator},     //  55: '$('
 | 
							SymDollarRound:        {"$(", symClassOperator, posPrefix},    //  55: '$('
 | 
				
			||||||
		SymOpenClosedRound: {"()", symClassPostOp},       //  56: '()'
 | 
							SymOpenClosedRound:    {"()", symClassOperator, posPostfix},   //  56: '()'
 | 
				
			||||||
		SymDoubleDollar:    {"$$", symClassOperator},     //  57: '$$'
 | 
							SymDoubleDollar:       {"$$", symClassCommand, posLeaf},       //  57: '$$'
 | 
				
			||||||
		SymDoubleDot:       {"..", symClassOperator},     //  58: '..'
 | 
							SymDoubleDot:          {"..", symClassOperator, posInfix},     //  58: '..'
 | 
				
			||||||
		SymTripleDot:       {"...", symClassOperator},    //  59: '...'
 | 
							SymTripleDot:          {"...", symClassOperator, posPostfix},  //  59: '...'
 | 
				
			||||||
		SymStarEqual:       {"*=", symClassOperator},     //  60: '*='
 | 
							SymStarEqual:          {"*=", symClassOperator, posInfix},     //  60: '*='
 | 
				
			||||||
		SymSlashEqual:      {"/=", symClassOperator},     //  61: '/='
 | 
							SymSlashEqual:         {"/=", symClassOperator, posInfix},     //  61: '/='
 | 
				
			||||||
		SymPercEqual:       {"%=", symClassOperator},     //  62: '%='
 | 
							SymPercEqual:          {"%=", symClassOperator, posInfix},     //  62: '%='
 | 
				
			||||||
 | 
							SymDoubleLessEqual:    {"<<=", symClassOperator, posInfix},    //  63: '<<='
 | 
				
			||||||
 | 
							SymDoubleGreaterEqual: {">>=", symClassOperator, posInfix},    //  64: '>>='
 | 
				
			||||||
 | 
							SymAmpersandEqual:     {"&=", symClassOperator, posInfix},     //  65: '&='
 | 
				
			||||||
 | 
							SymVertBarEqual:       {"|=", symClassOperator, posInfix},     //  65: '|='
 | 
				
			||||||
 | 
							SymCaretEqual:         {"^=", symClassOperator, posInfix},     //  66: '^='
 | 
				
			||||||
 | 
							SymPlusGreater:        {"+>", symClassOperator, posInfix},     //  67: '+>'
 | 
				
			||||||
 | 
							SymLessPlus:           {"<+", symClassOperator, posInfix},     //  68: '<+'
 | 
				
			||||||
 | 
							SymPreInc:             {"++", symClassOperator, posPrefix},    //    : '++'
 | 
				
			||||||
 | 
							SymPreDec:             {"--", symClassOperator, posPrefix},    //    : '--'
 | 
				
			||||||
		// SymChangeSign
 | 
							// SymChangeSign
 | 
				
			||||||
		// SymUnchangeSign
 | 
							// SymUnchangeSign
 | 
				
			||||||
		// SymIdentifier
 | 
							// SymIdentifier
 | 
				
			||||||
@ -121,17 +131,17 @@ func init() {
 | 
				
			|||||||
		// // SymClosedComment                     //   0: '*/'
 | 
							// // SymClosedComment                     //   0: '*/'
 | 
				
			||||||
		// // SymOneLineComment                    //   0: '//'
 | 
							// // SymOneLineComment                    //   0: '//'
 | 
				
			||||||
		// keywordBase
 | 
							// keywordBase
 | 
				
			||||||
		SymKwAnd:     {"and", symClassOperator},
 | 
							SymKwAnd:     {"and", symClassOperator, posInfix},
 | 
				
			||||||
		SymKwNot:     {"not", symClassOperator},
 | 
							SymKwNot:     {"not", symClassOperator, posInfix},
 | 
				
			||||||
		SymKwOr:      {"or", symClassOperator},
 | 
							SymKwOr:      {"or", symClassOperator, posInfix},
 | 
				
			||||||
		SymKwBut:     {"but", symClassOperator},
 | 
							SymKwBut:     {"but", symClassOperator, posInfix},
 | 
				
			||||||
		SymKwFunc:    {"func(", symClassDeclaration},
 | 
							SymKwFunc:    {"func(", symClassDeclaration, posPrefix},
 | 
				
			||||||
		SymKwBuiltin: {"builtin", symClassOperator},
 | 
							SymKwBuiltin: {"builtin", symClassOperator, posPrefix},
 | 
				
			||||||
		SymKwPlugin:  {"plugin", symClassOperator},
 | 
							SymKwPlugin:  {"plugin", symClassOperator, posPrefix},
 | 
				
			||||||
		SymKwIn:      {"in", symClassOperator},
 | 
							SymKwIn:      {"in", symClassOperator, posInfix},
 | 
				
			||||||
		SymKwInclude: {"include", symClassOperator},
 | 
							SymKwInclude: {"include", symClassOperator, posPrefix},
 | 
				
			||||||
		SymKwNil:     {"nil", symClassValue},
 | 
							SymKwNil:     {"nil", symClassValue, posLeaf},
 | 
				
			||||||
		SymKwUnset:   {"unset", symClassOperator},
 | 
							SymKwUnset:   {"unset", symClassOperator, posPrefix},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -169,12 +179,19 @@ func StringEndsWithOperator(s string) bool {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func endingOperator(s string) (sym Symbol) {
 | 
					func endingOperator(s string) (sym Symbol) {
 | 
				
			||||||
 | 
						var matchLength = 0
 | 
				
			||||||
	sym = SymNone
 | 
						sym = SymNone
 | 
				
			||||||
	lower := strings.ToLower(s)
 | 
						lower := strings.TrimRight(strings.ToLower(s), " \t")
 | 
				
			||||||
	for symbol, spec := range symbolMap {
 | 
						for symbol, spec := range symbolMap {
 | 
				
			||||||
		if spec.kind == symClassOperator && strings.HasSuffix(lower, spec.repr) {
 | 
							if strings.HasSuffix(lower, spec.repr) {
 | 
				
			||||||
 | 
								if len(spec.repr) > matchLength {
 | 
				
			||||||
 | 
									matchLength = len(spec.repr)
 | 
				
			||||||
 | 
									if spec.kind == symClassOperator && (spec.opType == posInfix || spec.opType == posPrefix) {
 | 
				
			||||||
					sym = symbol
 | 
										sym = symbol
 | 
				
			||||||
			break
 | 
									} else {
 | 
				
			||||||
 | 
										sym = SymNone
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										14
									
								
								symbol.go
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								symbol.go
									
									
									
									
									
								
							@ -60,8 +60,8 @@ const (
 | 
				
			|||||||
	SymQuestionExclam                       //  49: '?!'
 | 
						SymQuestionExclam                       //  49: '?!'
 | 
				
			||||||
	SymDoubleAt                             //  50: '@@'
 | 
						SymDoubleAt                             //  50: '@@'
 | 
				
			||||||
	SymDoubleColon                          //  51: '::'
 | 
						SymDoubleColon                          //  51: '::'
 | 
				
			||||||
	SymInsert                            //  52: '>>'
 | 
						SymDoubleGreater                        //  52: '>>'
 | 
				
			||||||
	SymAppend                            //  53: '<<'
 | 
						SymDoubleLess                           //  53: '<<'
 | 
				
			||||||
	SymCaret                                //  54: '^'
 | 
						SymCaret                                //  54: '^'
 | 
				
			||||||
	SymDollarRound                          //  55: '$('
 | 
						SymDollarRound                          //  55: '$('
 | 
				
			||||||
	SymOpenClosedRound                      //  56: '()'
 | 
						SymOpenClosedRound                      //  56: '()'
 | 
				
			||||||
@ -71,8 +71,18 @@ const (
 | 
				
			|||||||
	SymStarEqual                            //  60: '*='
 | 
						SymStarEqual                            //  60: '*='
 | 
				
			||||||
	SymSlashEqual                           //  61: '/='
 | 
						SymSlashEqual                           //  61: '/='
 | 
				
			||||||
	SymPercEqual                            //  62: '%='
 | 
						SymPercEqual                            //  62: '%='
 | 
				
			||||||
 | 
						SymDoubleLessEqual                      //  63: '<<='
 | 
				
			||||||
 | 
						SymDoubleGreaterEqual                   //  64: '>>='
 | 
				
			||||||
 | 
						SymAmpersandEqual                       //  65: '&='
 | 
				
			||||||
 | 
						SymVertBarEqual                         //  65: '|='
 | 
				
			||||||
 | 
						SymCaretEqual                           //  66: '^='
 | 
				
			||||||
 | 
						SymPlusGreater                          //  67: '+>'
 | 
				
			||||||
 | 
						SymLessPlus                             //  68: '<+'
 | 
				
			||||||
	SymChangeSign
 | 
						SymChangeSign
 | 
				
			||||||
	SymUnchangeSign
 | 
						SymUnchangeSign
 | 
				
			||||||
 | 
						SymDereference
 | 
				
			||||||
 | 
						SymPreInc
 | 
				
			||||||
 | 
						SymPreDec
 | 
				
			||||||
	SymIdentifier
 | 
						SymIdentifier
 | 
				
			||||||
	SymBool
 | 
						SymBool
 | 
				
			||||||
	SymInteger
 | 
						SymInteger
 | 
				
			||||||
 | 
				
			|||||||
@ -26,12 +26,13 @@ func TestBool(t *testing.T) {
 | 
				
			|||||||
		/*  12 */ {`true or false`, true, nil},
 | 
							/*  12 */ {`true or false`, true, nil},
 | 
				
			||||||
		/*  13 */ {`true or []`, true, nil},
 | 
							/*  13 */ {`true or []`, true, nil},
 | 
				
			||||||
		/*  14 */ {`[] or false`, nil, errors.New(`got list as left operand type of 'OR' operator, it must be bool`)},
 | 
							/*  14 */ {`[] or false`, nil, errors.New(`got list as left operand type of 'OR' operator, it must be bool`)},
 | 
				
			||||||
 | 
							/*  15 */ {`!true`, false, nil},
 | 
				
			||||||
		/*  13 */ //{`true or []`, nil, errors.New(`[1:8] left operand 'true' [bool] and right operand '[]' [list] are not compatible with operator "OR"`)},
 | 
							/*  13 */ //{`true or []`, nil, errors.New(`[1:8] left operand 'true' [bool] and right operand '[]' [list] are not compatible with operator "OR"`)},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// t.Setenv("EXPR_PATH", ".")
 | 
						// t.Setenv("EXPR_PATH", ".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// runTestSuiteSpec(t, section, inputs, 1)
 | 
						// runTestSuiteSpec(t, section, inputs, 15)
 | 
				
			||||||
	runTestSuite(t, section, inputs)
 | 
						runTestSuite(t, section, inputs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,9 @@ func TestExpr(t *testing.T) {
 | 
				
			|||||||
		/*  15 */ {`a=3; a*=2)+1; a`, nil, `[1:11] unexpected token ")"`},
 | 
							/*  15 */ {`a=3; a*=2)+1; a`, nil, `[1:11] unexpected token ")"`},
 | 
				
			||||||
		/*  16 */ {`v=[2]; a=1; v[a-=1]=5; v[0]`, int64(5), nil},
 | 
							/*  16 */ {`v=[2]; a=1; v[a-=1]=5; v[0]`, int64(5), nil},
 | 
				
			||||||
		/*  17 */ {`true ? {"a"} :: {"b"}`, "a", nil},
 | 
							/*  17 */ {`true ? {"a"} :: {"b"}`, "a", nil},
 | 
				
			||||||
		/*  18 */ {`
 | 
							/*  18 */ {`$$`, NewDict(map[any]any{"variables": NewDict(nil), "functions": NewDict(nil)}), nil},
 | 
				
			||||||
 | 
							///*  19 */ {`$$global`, NewDict(map[any]any{"variables": NewDict(nil), "functions": NewDict(nil)}), nil},
 | 
				
			||||||
 | 
							/*  19 */ {`
 | 
				
			||||||
		ds={
 | 
							ds={
 | 
				
			||||||
			"init":func(@end){@current=0 but true},
 | 
								"init":func(@end){@current=0 but true},
 | 
				
			||||||
			//"current":func(){current},
 | 
								//"current":func(){current},
 | 
				
			||||||
@ -44,6 +46,6 @@ func TestExpr(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// t.Setenv("EXPR_PATH", ".")
 | 
						// t.Setenv("EXPR_PATH", ".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// runTestSuiteSpec(t, section, inputs, 6, 7, 8, 9)
 | 
						// runTestSuiteSpec(t, section, inputs, 18)
 | 
				
			||||||
	runTestSuite(t, section, inputs)
 | 
						runTestSuite(t, section, inputs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ func TestFractionsParser(t *testing.T) {
 | 
				
			|||||||
		/*  12 */ {`builtin "math.arith"; add(1:2, 1.0, 2)`, float64(3.5), nil},
 | 
							/*  12 */ {`builtin "math.arith"; add(1:2, 1.0, 2)`, float64(3.5), nil},
 | 
				
			||||||
		/*  13 */ {`builtin "math.arith"; mul(1:2, 2:3)`, newFraction(2, 6), nil},
 | 
							/*  13 */ {`builtin "math.arith"; mul(1:2, 2:3)`, newFraction(2, 6), nil},
 | 
				
			||||||
		/*  14 */ {`builtin "math.arith"; mul(1:2, 1.0, 2)`, float64(1.0), nil},
 | 
							/*  14 */ {`builtin "math.arith"; mul(1:2, 1.0, 2)`, float64(1.0), nil},
 | 
				
			||||||
		/*  15 */ {`1:0`, nil, `division by zero`},
 | 
							/*  15 */ {`1:0`, nil, `[1:3] division by zero`},
 | 
				
			||||||
		/*  16 */ {`fract(-0.5)`, newFraction(-1, 2), nil},
 | 
							/*  16 */ {`fract(-0.5)`, newFraction(-1, 2), nil},
 | 
				
			||||||
		/*  17 */ {`fract("")`, (*FractionType)(nil), `bad syntax`},
 | 
							/*  17 */ {`fract("")`, (*FractionType)(nil), `bad syntax`},
 | 
				
			||||||
		/*  18 */ {`fract("-1")`, newFraction(-1, 1), nil},
 | 
							/*  18 */ {`fract("-1")`, newFraction(-1, 1), nil},
 | 
				
			||||||
@ -34,7 +34,7 @@ func TestFractionsParser(t *testing.T) {
 | 
				
			|||||||
		/*  21 */ {`fract(1,0)`, nil, `fract(): division by zero`},
 | 
							/*  21 */ {`fract(1,0)`, nil, `fract(): division by zero`},
 | 
				
			||||||
		/*  22 */ {`string(1:2)`, "1:2", nil},
 | 
							/*  22 */ {`string(1:2)`, "1:2", nil},
 | 
				
			||||||
		/*  23 */ {`1+1:2+0.5`, float64(2), nil},
 | 
							/*  23 */ {`1+1:2+0.5`, float64(2), nil},
 | 
				
			||||||
		/*  24 */ {`1:(2-2)`, nil, `division by zero`},
 | 
							/*  24 */ {`1:(2-2)`, nil, `[1:3] division by zero`},
 | 
				
			||||||
		/*  25 */ {`[0,1][1-1]:1`, newFraction(0, 1), nil},
 | 
							/*  25 */ {`[0,1][1-1]:1`, newFraction(0, 1), nil},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// runTestSuiteSpec(t, section, inputs, 25)
 | 
						// runTestSuiteSpec(t, section, inputs, 25)
 | 
				
			||||||
 | 
				
			|||||||
@ -9,10 +9,10 @@ import "testing"
 | 
				
			|||||||
func TestIteratorParser(t *testing.T) {
 | 
					func TestIteratorParser(t *testing.T) {
 | 
				
			||||||
	section := "Iterator"
 | 
						section := "Iterator"
 | 
				
			||||||
	inputs := []inputType{
 | 
						inputs := []inputType{
 | 
				
			||||||
		/*   1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); ^it`, int64(0), nil},
 | 
							/*   1 */ {`include "test-resources/iterator.expr"; it=$(ds,3); *it`, int64(0), nil},
 | 
				
			||||||
		/*   2 */ {`include "test-resources/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 "test-resources/iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(3), nil},
 | 
							/*   3 */ {`include "test-resources/iterator.expr"; it=$(ds,3); it++; it++; #it`, int64(3), nil},
 | 
				
			||||||
		/*   4 */ {`include "test-resources/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 "test-resources/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 "test-resources/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 "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); mul(it)`, int64(12000), nil},
 | 
							/*   7 */ {`builtin "math.arith"; include "test-resources/file-reader.expr"; it=$(ds,"test-resources/int.list"); mul(it)`, int64(12000), nil},
 | 
				
			||||||
 | 
				
			|||||||
@ -23,8 +23,8 @@ func TestListParser(t *testing.T) {
 | 
				
			|||||||
		/*   9 */ {`mul([1,4,3.0,2])`, float64(24.0), nil},
 | 
							/*   9 */ {`mul([1,4,3.0,2])`, float64(24.0), nil},
 | 
				
			||||||
		/*  10 */ {`add([1,"hello"])`, nil, `add(): param nr 2 (2 in 1) has wrong type string, number expected`},
 | 
							/*  10 */ {`add([1,"hello"])`, nil, `add(): param nr 2 (2 in 1) has wrong type string, number expected`},
 | 
				
			||||||
		/*  11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil},
 | 
							/*  11 */ {`[a=1,b=2,c=3] but a+b+c`, int64(6), nil},
 | 
				
			||||||
		/*  12 */ {`[1,2,3] << 2+2`, newListA(int64(1), int64(2), int64(3), int64(4)), nil},
 | 
							/*  12 */ {`[1,2,3] <+ 2+2`, newListA(int64(1), int64(2), int64(3), int64(4)), nil},
 | 
				
			||||||
		/*  13 */ {`2-1 >> [2,3]`, newListA(int64(1), int64(2), int64(3)), nil},
 | 
							/*  13 */ {`2-1 +> [2,3]`, newListA(int64(1), int64(2), int64(3)), nil},
 | 
				
			||||||
		/*  14 */ {`[1,2,3][1]`, int64(2), nil},
 | 
							/*  14 */ {`[1,2,3][1]`, int64(2), nil},
 | 
				
			||||||
		/*  15 */ {`ls=[1,2,3] but ls[1]`, int64(2), nil},
 | 
							/*  15 */ {`ls=[1,2,3] but ls[1]`, int64(2), nil},
 | 
				
			||||||
		/*  16 */ {`ls=[1,2,3] but ls[-1]`, int64(3), nil},
 | 
							/*  16 */ {`ls=[1,2,3] but ls[-1]`, int64(3), nil},
 | 
				
			||||||
@ -33,25 +33,25 @@ func TestListParser(t *testing.T) {
 | 
				
			|||||||
		/*  19 */ {`["a", "b", "c"]`, newList([]any{"a", "b", "c"}), nil},
 | 
							/*  19 */ {`["a", "b", "c"]`, newList([]any{"a", "b", "c"}), nil},
 | 
				
			||||||
		/*  20 */ {`#["a", "b", "c"]`, int64(3), nil},
 | 
							/*  20 */ {`#["a", "b", "c"]`, int64(3), nil},
 | 
				
			||||||
		/*  21 */ {`"b" in ["a", "b", "c"]`, true, nil},
 | 
							/*  21 */ {`"b" in ["a", "b", "c"]`, true, nil},
 | 
				
			||||||
		/*  22 */ {`a=[1,2]; (a)<<3`, newListA(int64(1), int64(2), int64(3)), nil},
 | 
							/*  22 */ {`a=[1,2]; (a)<+3`, newListA(int64(1), int64(2), int64(3)), nil},
 | 
				
			||||||
		/*  23 */ {`a=[1,2]; (a)<<3; a`, newListA(int64(1), int64(2)), nil},
 | 
							/*  23 */ {`a=[1,2]; (a)<+3; a`, newListA(int64(1), int64(2)), nil},
 | 
				
			||||||
		/*  24 */ {`["a","b","c","d"][1]`, "b", nil},
 | 
							/*  24 */ {`["a","b","c","d"][1]`, "b", nil},
 | 
				
			||||||
		/*  25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`},
 | 
							/*  25 */ {`["a","b","c","d"][1,1]`, nil, `[1:19] one index only is allowed`},
 | 
				
			||||||
		/*  26 */ {`[0,1,2,3,4][:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
 | 
							/*  26 */ {`[0,1,2,3,4][:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
 | 
				
			||||||
		/*  27 */ {`["a", "b", "c"] << ;`, nil, `[1:18] infix operator "<<" requires two non-nil operands, got 1`},
 | 
							/*  27 */ {`["a", "b", "c"] <+ ;`, nil, `[1:18] infix operator "<+" requires two non-nil operands, got 1`},
 | 
				
			||||||
		/*  28 */ {`2 << 3;`, int64(16), nil},
 | 
							/*  28 */ {`2 << 3;`, int64(16), nil},
 | 
				
			||||||
		/*  29 */ {`but >> ["a", "b", "c"]`, nil, `[1:6] infix operator ">>" requires two non-nil operands, got 0`},
 | 
							/*  29 */ {`but +> ["a", "b", "c"]`, nil, `[1:6] infix operator "+>" requires two non-nil operands, got 0`},
 | 
				
			||||||
		/*  30 */ {`2 >> 3;`, int64(0), nil},
 | 
							/*  30 */ {`2 >> 3;`, int64(0), nil},
 | 
				
			||||||
		/*  31 */ {`a=[1,2]; a<<3`, newListA(int64(1), int64(2), int64(3)), nil},
 | 
							/*  31 */ {`a=[1,2]; a<+3`, newListA(int64(1), int64(2), int64(3)), nil},
 | 
				
			||||||
		/*  33 */ {`a=[1,2]; 5>>a`, newListA(int64(5), int64(1), int64(2)), nil},
 | 
							/*  32 */ {`a=[1,2]; 5+>a`, newListA(int64(5), int64(1), int64(2)), nil},
 | 
				
			||||||
		/*  34 */ {`L=[1,2]; L[0]=9; L`, newListA(int64(9), int64(2)), nil},
 | 
							/*  33 */ {`L=[1,2]; L[0]=9; L`, newListA(int64(9), int64(2)), nil},
 | 
				
			||||||
		/*  35 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`},
 | 
							/*  34 */ {`L=[1,2]; L[5]=9; L`, nil, `index 5 out of bounds (0, 1)`},
 | 
				
			||||||
		/*  36 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [list]`},
 | 
							/*  35 */ {`L=[1,2]; L[]=9; L`, nil, `[1:12] index/key specification expected, got [] [list]`},
 | 
				
			||||||
		/*  37 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`},
 | 
							/*  36 */ {`L=[1,2]; L[nil]=9;`, nil, `[1:12] index/key is nil`},
 | 
				
			||||||
		/*  38 */ {`[0,1,2,3,4][2:3]`, newListA(int64(2)), nil},
 | 
							/*  37 */ {`[0,1,2,3,4][2:3]`, newListA(int64(2)), nil},
 | 
				
			||||||
		/*  39 */ {`[0,1,2,3,4][3:-1]`, newListA(int64(3)), nil},
 | 
							/*  38 */ {`[0,1,2,3,4][3:-1]`, newListA(int64(3)), nil},
 | 
				
			||||||
		/*  40 */ {`[0,1,2,3,4][-3:-1]`, newListA(int64(2), int64(3)), nil},
 | 
							/*  30 */ {`[0,1,2,3,4][-3:-1]`, newListA(int64(2), int64(3)), nil},
 | 
				
			||||||
		/*  41 */ {`[0,1,2,3,4][0:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
 | 
							/*  40 */ {`[0,1,2,3,4][0:]`, newListA(int64(0), int64(1), int64(2), int64(3), int64(4)), nil},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// t.Setenv("EXPR_PATH", ".")
 | 
						// t.Setenv("EXPR_PATH", ".")
 | 
				
			||||||
 | 
				
			|||||||
@ -14,10 +14,29 @@ func TestOperator(t *testing.T) {
 | 
				
			|||||||
		/*   1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`},
 | 
							/*   1 */ {`a=1; unset "a"; a`, nil, `undefined variable or function "a"`},
 | 
				
			||||||
		/*   2 */ {`a=1; unset ["a", "b"]`, int64(1), nil},
 | 
							/*   2 */ {`a=1; unset ["a", "b"]`, int64(1), nil},
 | 
				
			||||||
		/*   3 */ {`f=func(){3}; unset "f()"`, int64(1), nil},
 | 
							/*   3 */ {`f=func(){3}; unset "f()"`, int64(1), nil},
 | 
				
			||||||
 | 
							/*   4 */ {`a=1; a<<=1+0`, int64(2), nil},
 | 
				
			||||||
 | 
							/*   5 */ {`a=2; a>>=1+0`, int64(1), nil},
 | 
				
			||||||
 | 
							/*   6 */ {`1<<1`, int64(2), nil},
 | 
				
			||||||
 | 
							/*   7 */ {`1>>1`, int64(0), nil},
 | 
				
			||||||
 | 
							/*   8 */ {`1|2`, int64(3), nil},
 | 
				
			||||||
 | 
							/*   9 */ {`a=1; a|=2`, int64(3), nil},
 | 
				
			||||||
 | 
							/*  10 */ {`3&1`, int64(1), nil},
 | 
				
			||||||
 | 
							/*  11 */ {`a=3; a&=1`, int64(1), nil},
 | 
				
			||||||
 | 
							/*  12 */ {`~1`, int64(-2), nil},
 | 
				
			||||||
 | 
							/*  13 */ {`0x10`, int64(16), nil},
 | 
				
			||||||
 | 
							/*  14 */ {`0x1X`, nil, `[1:5] two adjacent operators: "1" and "X"`},
 | 
				
			||||||
 | 
							/*  15 */ {`0o10`, int64(8), nil},
 | 
				
			||||||
 | 
							/*  16 */ {`0b10`, int64(2), nil},
 | 
				
			||||||
 | 
							/*  17 */ {`~true`, nil, `[1:2] prefix/postfix operator "~" do not support operand 'true' [bool]`},
 | 
				
			||||||
 | 
							/*  18 */ {`1^2`, int64(3), nil},
 | 
				
			||||||
 | 
							/*  19 */ {`3^2`, int64(1), nil},
 | 
				
			||||||
 | 
							/*  19 */ {`a=1; a^=2`, int64(3), nil},
 | 
				
			||||||
 | 
							/*  20 */ {`a=1; ++a`, int64(2), nil},
 | 
				
			||||||
 | 
							/*  21 */ {`a=1; --a`, int64(0), nil},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// t.Setenv("EXPR_PATH", ".")
 | 
						// t.Setenv("EXPR_PATH", ".")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//runTestSuiteSpec(t, section, inputs, 3)
 | 
						// runTestSuiteSpec(t, section, inputs, 4)
 | 
				
			||||||
	runTestSuite(t, section, inputs)
 | 
						runTestSuite(t, section, inputs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -78,8 +78,8 @@ func TestGeneralParser(t *testing.T) {
 | 
				
			|||||||
		/*  64 */ {`"1.5" != `, nil, `[1:8] infix operator "!=" requires two non-nil operands, got 1`},
 | 
							/*  64 */ {`"1.5" != `, nil, `[1:8] infix operator "!=" requires two non-nil operands, got 1`},
 | 
				
			||||||
		/*  65 */ {"+1.5", float64(1.5), nil},
 | 
							/*  65 */ {"+1.5", float64(1.5), nil},
 | 
				
			||||||
		/*  66 */ {"+", nil, `[1:2] prefix operator "+" requires one non-nil operand`},
 | 
							/*  66 */ {"+", nil, `[1:2] prefix operator "+" requires one non-nil operand`},
 | 
				
			||||||
		/*  67 */ {"4 / 0", nil, `division by zero`},
 | 
							/*  67 */ {"4 / 0", nil, `[1:4] division by zero`},
 | 
				
			||||||
		/*  68 */ {"4.0 / 0", nil, `division by zero`},
 | 
							/*  68 */ {"4.0 / 0", nil, `[1:6] division by zero`},
 | 
				
			||||||
		/*  69 */ {"4.0 / \n2", float64(2.0), nil},
 | 
							/*  69 */ {"4.0 / \n2", float64(2.0), nil},
 | 
				
			||||||
		/*  70 */ {`123`, int64(123), nil},
 | 
							/*  70 */ {`123`, int64(123), nil},
 | 
				
			||||||
		/*  71 */ {`1.`, float64(1.0), nil},
 | 
							/*  71 */ {`1.`, float64(1.0), nil},
 | 
				
			||||||
@ -142,6 +142,6 @@ func TestGeneralParser(t *testing.T) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// t.Setenv("EXPR_PATH", ".")
 | 
						// t.Setenv("EXPR_PATH", ".")
 | 
				
			||||||
	//runTestSuiteSpec(t, section, inputs, 130)
 | 
						// runTestSuiteSpec(t, section, inputs, 114)
 | 
				
			||||||
	runTestSuite(t, section, inputs)
 | 
						runTestSuite(t, section, inputs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestStringsParser(t *testing.T) {
 | 
					func TestStringsParser(t *testing.T) {
 | 
				
			||||||
 | 
						section := "String"
 | 
				
			||||||
	inputs := []inputType{
 | 
						inputs := []inputType{
 | 
				
			||||||
		/*  1 */ {`"uno" + "due"`, `unodue`, nil},
 | 
							/*  1 */ {`"uno" + "due"`, `unodue`, nil},
 | 
				
			||||||
		/*  2 */ {`"uno" + 2`, `uno2`, nil},
 | 
							/*  2 */ {`"uno" + 2`, `uno2`, nil},
 | 
				
			||||||
@ -16,6 +17,12 @@ func TestStringsParser(t *testing.T) {
 | 
				
			|||||||
		/*  4 */ {`"uno" * (2+1)`, `unounouno`, nil},
 | 
							/*  4 */ {`"uno" * (2+1)`, `unounouno`, nil},
 | 
				
			||||||
		/*  5 */ {`"abc"[1]`, `b`, nil},
 | 
							/*  5 */ {`"abc"[1]`, `b`, nil},
 | 
				
			||||||
		/*  6 */ {`#"abc"`, int64(3), nil},
 | 
							/*  6 */ {`#"abc"`, int64(3), nil},
 | 
				
			||||||
 | 
							/*  7 */ {`"192.168.0.240" / "."`, newListA("192", "168", "0", "240"), nil},
 | 
				
			||||||
 | 
							/*  8 */ {`("192.168.0.240" / ".")[1]`, "168", nil},
 | 
				
			||||||
 | 
							/*  9 */ {`"AF3B0Dz" / 2`, newListA("AF", "3B", "0D", "z"), nil},
 | 
				
			||||||
 | 
							/* 10 */ {`"AF3B0Dz" / 0`, nil, "[1:12] division by zero"},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	runTestSuite(t, "String", inputs)
 | 
					
 | 
				
			||||||
 | 
						// runTestSuiteSpec(t, section, inputs, 8)
 | 
				
			||||||
 | 
						runTestSuite(t, section, inputs)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										11
									
								
								term.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								term.go
									
									
									
									
									
								
							@ -15,21 +15,26 @@ const (
 | 
				
			|||||||
	priRange
 | 
						priRange
 | 
				
			||||||
	priBut
 | 
						priBut
 | 
				
			||||||
	priAssign
 | 
						priAssign
 | 
				
			||||||
 | 
						priInsert
 | 
				
			||||||
	priOr
 | 
						priOr
 | 
				
			||||||
	priAnd
 | 
						priAnd
 | 
				
			||||||
	priNot
 | 
						priNot
 | 
				
			||||||
	priRelational
 | 
						priRelational
 | 
				
			||||||
	priBinary
 | 
						priBitwiseOr
 | 
				
			||||||
 | 
						priBitwiseAnd
 | 
				
			||||||
 | 
						priBitwiseNot
 | 
				
			||||||
	priSum
 | 
						priSum
 | 
				
			||||||
	priProduct
 | 
						priProduct
 | 
				
			||||||
	priFraction
 | 
						priFraction
 | 
				
			||||||
	priSelector
 | 
						priSelector
 | 
				
			||||||
 | 
						priBinShift
 | 
				
			||||||
	priSign
 | 
						priSign
 | 
				
			||||||
	priFact
 | 
						priFact
 | 
				
			||||||
	priIterValue
 | 
						priIterValue
 | 
				
			||||||
	priDefault
 | 
						priDefault
 | 
				
			||||||
	priIncDec
 | 
						priIncDec
 | 
				
			||||||
	priDot
 | 
						priDot
 | 
				
			||||||
 | 
						priDereference
 | 
				
			||||||
	priValue
 | 
						priValue
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -199,6 +204,10 @@ func (term *term) errIncompatibleType(value any) error {
 | 
				
			|||||||
		term.source(), value, TypeName(value))
 | 
							term.source(), value, TypeName(value))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (term *term) errDivisionByZero() error {
 | 
				
			||||||
 | 
						return term.tk.Errorf("division by zero")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (term *term) Errorf(template string, args ...any) (err error) {
 | 
					func (term *term) Errorf(template string, args ...any) (err error) {
 | 
				
			||||||
	err = term.tk.Errorf(template, args...)
 | 
						err = term.tk.Errorf(template, args...)
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										4
									
								
								token.go
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								token.go
									
									
									
									
									
								
							@ -79,6 +79,10 @@ func (tk *Token) IsSymbol(sym Symbol) bool {
 | 
				
			|||||||
	return tk.Sym == sym
 | 
						return tk.Sym == sym
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (tk *Token) SetSymbol(sym Symbol) {
 | 
				
			||||||
 | 
						tk.Sym = sym
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (tk *Token) Errorf(template string, args ...any) (err error) {
 | 
					func (tk *Token) Errorf(template string, args ...any) (err error) {
 | 
				
			||||||
	err = fmt.Errorf(fmt.Sprintf("[%d:%d] ", tk.row, tk.col)+template, args...)
 | 
						err = fmt.Errorf(fmt.Sprintf("[%d:%d] ", tk.row, tk.col)+template, args...)
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user