2024-04-14 08:16:01 +02:00
= Expr
Expressions calculator
:authors: Celestino Amoroso
:docinfo: shared
:encoding: utf-8
:toc: right
:toclevels: 4
//:toc-title: Indice Generale
:icons: font
:icon-set: fi
:numbered:
//:table-caption: Tabella
//:figure-caption: Diagramma
:docinfo1:
:sectlinks:
:sectanchors:
:source-highlighter: rouge
// :rouge-style: ThankfulEyes
:rouge-style: gruvbox
// :rouge-style: colorful
//:rouge-style: monokay
toc::[]
2024-05-20 06:59:49 +02:00
#TODO: Work in progress (last update on 2024/05/20, 06:58 a.m.)#
2024-04-19 14:30:40 +02:00
2024-04-14 08:16:01 +02:00
== Expr
_Expr_ is a GO package capable of analysing, interpreting and calculating expressions.
2024-05-10 06:39:48 +02:00
=== Concepts and terminology
#TODO#
image::expression-diagram.png[]
2024-05-07 07:22:32 +02:00
=== `dev-expr` test tool
2024-05-16 07:11:20 +02:00
`dev-expr` is a simple program that can be used to evaluate expressions interactively. As its name suggests, it was created for testing purpose. In fact, in additon to the automatic verification test suite based on the Go test framework, `dev-expr` provides an important aid for quickly testing of new features during their development.
2024-05-07 07:22:32 +02:00
2024-05-16 07:11:20 +02:00
`dev-expr` can work as a _REPL_, _**R**ead-**E**xecute-**P**rint-**L**oop_, or it can process expression acquired from files or standard input.
2024-05-10 06:39:48 +02:00
The program can be downloaded from https://git.portale-stac.it/go-pkg/-/packages/generic/dev-expr/[dev-expr].
2024-05-07 07:22:32 +02:00
Here are some examples of execution.
.Run `dev-expr` in REPL mode and ask for help
[source,shell]
----
2024-05-17 07:31:13 +02:00
# Type 'exit' or Ctrl+D to quit the program.
2024-05-07 07:22:32 +02:00
2024-05-16 07:11:20 +02:00
[user]$ ./dev-expr
expr -- Expressions calculator v1.7.1(build 2),2024/05/16 (celestino.amoroso@portale-stac.it)
Based on the Expr package v0.10.0
Type help to get the list of available commands
2024-05-07 07:22:32 +02:00
See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc
>>> help
--- REPL commands:
2024-05-16 07:11:20 +02:00
source -- Load a file as input
tty -- Enable/Disable ansi output <1>
2024-05-08 07:51:01 +02:00
base -- Set the integer output base: 2, 8, 10, or 16
exit -- Exit the program
2024-05-07 07:22:32 +02:00
help -- Show command list
ml -- Enable/Disable multi-line output
mods -- List builtin modules
--- Command line options:
-b <builtin> Import builtin modules.
<builtin> can be a list of module names or a glob-pattern.
Use the special value 'all' or the pattern '*' to import all modules.
-e <expression> Evaluate <expression> instead of standard-input
-i Force REPL operation when all -e occurences have been processed
-h, --help, help Show this help menu
-m, --modules List all builtin modules
-p Print prefix form
-t Print tree form <2>
2024-05-08 07:51:01 +02:00
>>>
2024-05-07 07:22:32 +02:00
----
<1> Only available for single fraction values
<2> Work in progress
.REPL examples
[source,shell]
----
2024-05-16 07:11:20 +02:00
[user]$ ./dev-expr
expr -- Expressions calculator v1.7.1(build 2),2024/05/16 (celestino.amoroso@portale-stac.it)
Based on the Expr package v0.10.0
Type help to get the list of available commands
See also https://git.portale-stac.it/go-pkg/expr/src/branch/main/README.adoc
2024-05-07 07:22:32 +02:00
>>> 2+3
5
>>> 2+3*(4-1.5)
9.5
>>> 0xFD + 0b1 + 0o1 <1>
255
>>> 1|2 + 2|3 <2>
7|6
>>> ml <3>
>>> 1|2 + 2|3
7
-
6
>>> 1+2 but 5|2+0.5 <4>
3
>>> 1+2; 5|2+0.5 <5>
3
>>>
----
<1> Number bases: 0x = hexadecimal, 0o = octal, 0b = binary.
<2> Fractions: numerator | denominator.
<3> Activate multi-line output of fractions.
<4> But operator, see <<_but_operator>>.
<5> Multi-expression: the same result of the previous single expression but this it is obtained with two separated calculations.
2024-04-14 08:16:01 +02:00
== Data types
_Expr_ supports numerical, string, relational, boolean expressions, and mixed-type lists.
=== Numbers
2024-05-15 22:06:26 +02:00
_Expr_ supports three type of numbers:
. [blue]#Integers#
. [blue]#Floats#
2024-05-17 15:46:56 +02:00
. [blue]#Factions#
2024-05-15 22:06:26 +02:00
In mixed operations involving integers, fractions and floats, automatic type promotion to the largest type take place.
==== Integers
__Expr__'s integers are a subset of the integer set. Internally they are stored as Golang _int64_ values.
.Integer literal syntax
====
*_integer_* = [_sign_] _digit-seq_ +
_sign_ = "**+**" | "**-**" +
_digit-seq_ = _dec-seq_ | _bin-seq_ | _oct-seq_ | _hex-seq_ +
_dec-seq_ = {__dec-digit__} +
_dec-digit_ = "**0**"|"**1**"|...|"**9**" +
_bin-seq_ = "**0b**"{__bin-digit__} +
_bin-digit_ = "**0**"|"**1**" +
_oct-seq_ = "**0o**"{__oct-digit__} +
_oct-digit_ = "**0**"|"**1**"|...|"**7**" +
_hex-seq_ = "**0x**"{__hex-digit__} +
_hex-digit_ = "**0**"|"**1**"|...|"**9**"|"**a**"|...|"**z**"|"**A**"|...|"**Z**"
====
Value range: *-9223372036854775808* to *9223372036854775807*
2024-04-14 08:16:01 +02:00
.Arithmetic operators
[cols="^1,^2,6,4"]
|===
| Symbol | Operation | Description | Examples
2024-05-15 22:06:26 +02:00
| [blue]`+` | _sum_ | Add two values | [blue]`-1 + 2` -> 1
| [blue]`-` | _subtraction_ | Subtract the right value from the left one | [blue]`3 - 1` -> 2
| [blue]`*` | _product_ | Multiply two values | [blue]`-1 * 2` -> -2
| [blue]`/` | _Division_ | Divide the left value by the right one^(*)^ | [blue]`-10 / 2` -> 5
| [blue]`%` | _Modulo_ | Remainder of the integer division | [blue]`5 % 2` -> 1
|===
2024-04-14 08:16:01 +02:00
2024-05-15 22:06:26 +02:00
^(*)^ See also the _float division_ [blue]`./` below.
2024-04-14 08:16:01 +02:00
2024-05-15 22:06:26 +02:00
==== Floats
__Expr__'s floats are a subset of the rational number set. Note that they can't hold the exact value of an unlimited number; floats can only approximate them. Internally floats are stored as Golang's _float64_ values.
2024-04-14 08:16:01 +02:00
2024-05-15 22:06:26 +02:00
.Float literal syntax
====
*_float_* = [_sign_] _dec-seq_ "**.**" [_dec-seq_] [("**e**"|"**E**") [_sign_] _dec-seq_] +
_sign_ = "**+**" | "**-**" +
_dec-seq_ = _see-integer-literal-syntax_
====
2024-04-14 08:16:01 +02:00
2024-05-16 07:11:20 +02:00
.Examples
`>>>` [blue]`1.0` +
[green]`1` +
`>>>` [blue]`0.123` +
[green]`0.123` +
`>>>` [blue]`4.5e+3` +
[green]`4500` +
`>>>` [blue]`4.5E-33` +
[green]`4.5e-33` +
`>>>` [blue]`4.5E-3` +
[green]`0.0045` +
`>>>` [blue]`4.5E10` +
2024-05-17 15:46:56 +02:00
[green]`4.5e+10`
2024-05-16 07:11:20 +02:00
2024-04-14 08:16:01 +02:00
2024-05-15 22:06:26 +02:00
.Arithmetic operators
[cols="^1,^2,6,4"]
|===
| Symbol | Operation | Description | Examples
| [blue]`+` | _sum_ | Add two values | [blue]`4 + 0.5` -> 4.5
| [blue]`-` | _subtraction_ | Subtract the right value from the left one | [blue]`4 - 0.5` -> 3.5
| [blue]`*` | _product_ | Multiply two values | [blue]`4 * 0.5` -> 2.0
| [blue]`/` | _Division_ | Divide the left value by the right one | [blue]`1.0 / 2` -> 0.5
| [blue]`./`| _Float division_ | Force float division | [blue]`-1 ./ 2` -> -0.5
|===
2024-04-14 08:16:01 +02:00
2024-05-15 22:06:26 +02:00
==== Fractions
2024-05-10 04:49:03 +02:00
_Expr_ also supports fractions. Fraction literals are made with two integers separated by a vertical bar `|`.
2024-05-09 07:20:22 +02:00
2024-05-15 22:06:26 +02:00
.Fraction literal syntax
====
*_fraction_* = [__sign__] (_num-den-spec_ | _float-spec_) +
_sign_ = "**+**" | "**-**" +
_num-den-spec_ = _digit-seq_ "**|**" _digit-seq_ +
_float-spec_ = _dec-seq_ "**.**" [_dec-seq_] "**(**" _dec-seq_ "**)**" +
_dec-seq_ = _see-integer-literal-syntax_ +
2024-05-17 15:46:56 +02:00
_digit-seq_ = _see-integer-literal-syntax_
2024-05-15 22:06:26 +02:00
====
2024-05-09 07:20:22 +02:00
.Examples
// [source,go]
// ----
`>>>` [blue]`1 | 2` +
[green]`1|2` +
2024-05-16 07:11:20 +02:00
`>>>` [blue]`4|6` [gray]_// Fractions are always reduced to their lowest terms_ +
[green]`2|3` +
2024-05-09 07:20:22 +02:00
`>>>` [blue]`1|2 + 2|3` +
[green]`7|6` +
`>>>` [blue]`1|2 * 2|3` +
[green]`1|3` +
`>>>` [blue]`1|2 / 1|3` +
[green]`3|2` +
2024-05-16 07:11:20 +02:00
`>>>` [blue]`1|2 ./ 1|3` [gray]_// Force decimal division_ +
2024-05-09 07:20:22 +02:00
[green]`1.5` +
`>>>` [blue]`-1|2` +
[green]`-1|2` +
2024-05-16 07:11:20 +02:00
`>>>` [blue]`1|-2` [gray]_// Invalid sign specification_ +
2024-05-09 07:20:22 +02:00
[red]_Eval Error: [1:3] infix operator "|" requires two non-nil operands, got 1_ +
`>>>` [blue]`1|(-2)` +
[green]`-1|2`
// ----
Fractions can be used together with integers and floats in expressions.
2024-05-17 07:31:13 +02:00
.Examples
2024-05-09 07:20:22 +02:00
`>>>` [blue]`1|2 + 5` +
[green]`11|2` +
`>>>` [blue]`4 - 1|2` +
[green]`7|2` +
`>>>` [blue]`1.0 + 1|2` +
2024-05-17 15:46:56 +02:00
[green]`1.5`
2024-05-09 07:20:22 +02:00
=== Strings
2024-05-16 07:11:20 +02:00
Strings are character sequences enclosed between two double quote [blue]`"`.
.Examples
`>>>` [blue]`"I'm a string"` +
[green]`I'm a string` +
`>>>` [blue]`"123abc?!"` +
[green]`123abc?!` +
`>>>` [blue]`"123\nabc"` +
[green]`123` +
[green]`abc` +
`>>>` [blue]`"123\tabc"` +
[green]`123{nbsp}{nbsp}{nbsp}{nbsp}abc`
2024-04-14 08:16:01 +02:00
Some arithmetic operators can also be used with strings.
.String operators
[cols="^1,^2,6,4"]
|===
| Symbol | Operation | Description | Examples
2024-05-20 06:59:49 +02:00
| [blue]`+` | _concatenation_ | Join two strings or two _stringable_ values | [blue]`"one" + "two"` -> _"onetwo"_ +
[blue]`"one" + 2` -> _"one2"_
2024-04-14 08:16:01 +02:00
2024-05-20 06:59:49 +02:00
| [blue]`*` | _repeat_ | Make _n_ copy of a string | [blue]`"one" * 2` -> _"oneone"_
2024-04-14 08:16:01 +02:00
|===
2024-05-11 06:35:32 +02:00
The items of strings can be accessed using the dot `.` operator.
.Item access syntax
2024-05-16 07:11:20 +02:00
====
_item_ = _string-expr_ "**.**" _integer-expr_
====
2024-05-11 06:35:32 +02:00
.String examples
2024-05-20 06:59:49 +02:00
`>>>` [blue]`s="abc"` [gray]_// assign the string to variable s_ +
2024-05-11 20:14:54 +02:00
[green]`abc` +
2024-05-20 06:59:49 +02:00
`>>>` [blue]`s.1` [gray]_// char at position 1 (starting from 0)_ +
2024-05-11 20:14:54 +02:00
[green]`b` +
2024-05-20 06:59:49 +02:00
`>>>` [blue]`s.(-1)` [gray]_// char at position -1, the rightmost one_ +
2024-05-11 20:14:54 +02:00
[green]`c` +
2024-05-20 06:59:49 +02:00
`>>>` [blue]`\#s` [gray]_// number of chars_ +
2024-05-11 20:14:54 +02:00
[gren]`3` +
2024-05-20 06:59:49 +02:00
`>>>` [blue]`#"abc"` [gray]_// number of chars_ +
2024-05-17 15:46:56 +02:00
[green]`3`
2024-04-14 08:16:01 +02:00
2024-05-17 07:31:13 +02:00
=== Booleans
2024-05-16 07:11:20 +02:00
Boolean data type has two values only: [blue]_true_ and [blue]_false_. Relational and boolean expressions result in boolean values.
2024-04-14 08:16:01 +02:00
.Relational operators
[cols="^1,^2,6,4"]
|===
| Symbol | Operation | Description | Examples
2024-05-16 07:11:20 +02:00
| [blue]`==` | _Equal_ | True if the left value is equal to the right one | [blue]`5 == 2` -> _false_ +
[blue]`"a" == "a"` -> _true_
| [blue]`!=` | _Not Equal_ | True if the left value is NOT equal to the right one | [blue]`5 != 2` -> _true_ +
[blue]`"a" != "a"` -> _false_
| [blue]`<` | _Less_ | True if the left value is less than the right one | [blue]`5 < 2` -> _false_ +
[blue]`"a" < "b"` -> _true_
| [blue]`\<=` | _Less or Equal_ | True if the left value is less than or equal to the right one | [blue]`5 \<= 2` -> _false_ +
[blue]`"b" \<= "b"` -> _true_
| [blue]`>` | _Greater_ | True if the left value is greater than the right one | [blue]`5 > 2` -> _true_ +
[blue]`"a" < "b"` -> _false_
| [blue]`>=` | _Greater or Equal_ | True if the left value is greater than or equal to the right one | [blue]`5 >= 2` -> _true_ +
[blue]`"b" \<= "b"` -> _true_
2024-04-14 08:16:01 +02:00
|===
.Boolean operators
[cols="^2,^2,5,4"]
|===
| Symbol | Operation | Description | Examples
2024-05-16 07:11:20 +02:00
| [blue]`NOT` | _Not_ | True if the right value is false | [blue]`NOT true` -> _false_ +
[blue]`NOT (2 < 1)` -> _true_
2024-04-14 08:16:01 +02:00
2024-05-16 07:11:20 +02:00
| [blue]`AND` / [blue]`&&` | _And_ | True if both left and right values are true | [blue]`false && true` -> _false_ +
[blue]`"a" < "b" AND NOT (2 < 1)` -> _true_
2024-04-14 08:16:01 +02:00
2024-05-16 07:11:20 +02:00
| [blue]`OR` / [blue]`\|\|` | _Or_ | True if at least one of the left and right values integers true| [blue]`false or true` -> _true_ +
[blue]`"a" == "b" OR (2 == 1)` -> _false_
2024-04-14 08:16:01 +02:00
|===
[CAUTION]
====
2024-05-16 07:11:20 +02:00
Currently, boolean operations are evaluated using _short cut evaluation_. This means that, if the left expression of the [blue]`and` and [blue]`or` operators is sufficient to establish the result of the whole operation, the right expression would not evaluated at all.
2024-04-14 08:16:01 +02:00
.Example
[source,go]
----
2 > (a=1) or (a=8) > 0; a // <1>
----
<1> This multi-expression returns _1_ because in the first expression the left value of [blue]`or` is _true_ and as a conseguence its right value is not computed. Therefore the _a_ variable only receives the integer _1_.
====
2024-05-10 04:49:03 +02:00
=== Lists
2024-05-17 07:31:13 +02:00
_Expr_ supports list of mixed-type values, also specified by normal expressions. Internally, _Expr_'s lists are Go arrays.
2024-04-14 08:16:01 +02:00
2024-05-17 07:31:13 +02:00
.List literal syntax
====
*_list_* = _empty-list_ | _non-empty-list_ +
_empty-list_ = "**[]**" +
_non-empty-list_ = "**[**" _any-value_ {"**,**" _any-value} "**]**" +
====
.Examples
`>>>` [blue]`[1,2,3]` [gray]_// List of integers_ +
[green]`[1, 2, 3]` +
`>>>` [blue]`["one", "two", "three"]` [gray]_// List of strings_ +
[green]`["one", "two", "three"]` +
`>>>` [blue]`["one", 2, false, 4.1]` [gray]_// List of mixed-types_ +
[green]`["one", 2, false, 4.1]` +
`>>>` [blue]`["one"+1, 2.0*(9-2)]` [gray]_// List of expressions_ +
[green]`["one1", 14]` +
`>>>` [blue]`[ [1,"one"], [2,"two"]]` [gray]_// List of lists_ +
[green]`[[1, "one"], [2, "two"]]`
2024-04-14 08:16:01 +02:00
.List operators
[cols="^2,^2,5,4"]
|===
| Symbol | Operation | Description | Examples
2024-05-17 07:31:13 +02:00
| [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]_
2024-05-20 06:59:49 +02:00
| [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]`.` | _List item_ | 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]`6 in [1,2,3]` -> _false_
2024-04-14 08:16:01 +02:00
|===
2024-05-10 04:49:03 +02:00
The items of array can be accessed using the dot `.` operator.
.Item access syntax
2024-05-17 07:31:13 +02:00
====
2024-05-20 06:59:49 +02:00
_item_ = _list-expr_ "**.**" _integer-expr_
2024-05-17 07:31:13 +02:00
====
2024-05-10 04:49:03 +02:00
.Items of list
2024-05-11 20:14:54 +02:00
`>>>` [blue]`[1,2,3].1` +
[green]`2` +
`>>>` [blue]`list=[1,2,3]; list.1` +
[green]`2` +
`>>>` [blue]`["one","two","three"].1` +
[green]`two` +
`>>>` [blue]`list=["one","two","three"]; list.(2-1)` +
[green]`two` +
`>>>` [blue]`list.(-1)` +
[green]`three` +
`>>>` [blue]`list.(10)` +
[red]`Eval Error: [1:9] index 10 out of bounds` +
`>>>` [blue]`#list` +
2024-05-20 06:59:49 +02:00
[green]`3` +
`>>>` [blue]`index=2; ["a", "b", "c", "d"].index` +
[green]`c`
2024-05-10 04:49:03 +02:00
2024-05-17 07:31:13 +02:00
=== Dictionaries
2024-05-20 06:59:49 +02:00
The _dictionary_, or _dict_, data-type is set of pairs _key/value_. It is also known as _map_ or _associative array_.
2024-05-09 07:20:22 +02:00
2024-05-20 06:59:49 +02:00
Dictionary literals are sequences of pairs separated by comma [blue]`,` enclosed between brace brackets.
2024-05-09 07:20:22 +02:00
2024-05-17 07:31:13 +02:00
.Dict literal syntax
====
*_dict_* = _empty-dict_ | _non-empty-dict_ +
_empty-dict_ = "**{}**" +
_non-empty-dict_ = "**{**" _key-scalar_ "**:**" _any-value_ {"**,**" _key-scalar_ "**:**" _any-value} "**}**" +
====
.Examples
`>>>` [blue]`{1:"one", 2:"two"}` +
2024-05-20 06:59:49 +02:00
[green]`{1: "one", 2: "two"}` +
2024-05-17 07:31:13 +02:00
`>>>` [blue]`{"one":1, "two": 2}` +
2024-05-20 06:59:49 +02:00
[green]`{"one": 1, "two": 2}` +
`>>>` [blue]`{"sum":1+2+3, "prod":1*2*3}` +
[green]`{"sum": 6, "prod": 6}`
.Dict operators
[cols="^2,^2,4,5"]
|===
| Symbol | Operation | Description | Examples
| [blue]`+` | _Join_ | Joins two dicts | [blue]`{1:"one"}+{6:"six"}` -> _{1: "one", 6: "six"}_
| [blue]`.` | _Dict item value_ | Item value of given key | [blue]`{"one":1, "two":2}."two"` -> _2_
| [blue]`in` | _Key in dict_ | True if key is in dict | [blue]`"one" in {"one":1, "two":2}` -> _true_ +
[blue]`"six" in {"one":1, "two":2}` -> _false_
|===
2024-05-09 07:20:22 +02:00
2024-04-14 08:16:01 +02:00
== Variables
2024-05-20 06:59:49 +02:00
_Expr_, like most programming languages, supports variables. A variable is an identifier with an assigned value. Variables are stored in _contexts_.
2024-05-17 07:31:13 +02:00
.Variable literal syntax
====
*_variable_* = _identifier_ "*=*" _any-value_ +
_identifier_ = _alpha_ {(_alpha_)|_dec-digit_|"*_*"} +
__alpha__ = "*a*"|"*b*"|..."*z*"|"*A*"|"*B*"|..."*Z*"
====
NOTE: The assign operator [blue]`=` returns the value assigned to the variable.
2024-04-14 08:16:01 +02:00
.Examples
2024-05-17 07:31:13 +02:00
`>>>` [blue]`a=1` +
[green]`1` +
`>>>` [blue]`a_b=1+2` +
[green]`1+2` +
`>>>` [blue]`a_b` +
[green]`3` +
`>>>` [blue]`x = 5.2 * (9-3)` [gray]_// The assigned value has the approximation error typical of the float data-type_ +
[green]`31.200000000000003` +
`>>>` [blue]`x = 1; y = 2*x` +
[green]`2` +
`>>>` [blue]`_a=2` +
[red]`Parse Error: [1:2] unexpected token "_"` +
`>>>` [blue]`1=2` +
[red]`Parse Error: assign operator ("=") must be preceded by a variable`
2024-04-14 08:16:01 +02:00
== Other operations
=== [blue]`;` operator
2024-05-17 07:31:13 +02:00
The semicolon operator [blue]`;` is an infixed pseudo-operator. It evaluates the left expression first and then the right expression. The value of the latter is the final result.
An expression that contains [blue]`;` is called a _multi-expression_ and each component expressione is called a _sub-expression_.
2024-04-14 08:16:01 +02:00
IMPORTANT: Technically [blue]`;` is not treated as a real operator. It acts as a separator in lists of expressions.
TIP: [blue]`;` can be used to set some variables before the final calculation.
.Example
2024-05-17 07:31:13 +02:00
`>>>` [blue]`a=1; b=2; c=3; a+b+c` +
[green]`6`
The value of each sub-expression is stored in the automatica variable _last_.
.Example
`>>>` [blue]`2+3; b=last+10; last` +
[green]`15`
2024-04-14 08:16:01 +02:00
=== [blue]`but` operator
2024-05-20 06:59:49 +02:00
[blue]`but` is an infixed operator. Its operands can be expressions of any type. It evaluates the left expression first, then the right expression. The value of the right expression is the final result.
.Examples
[blue]`5 but 2` +
[green]`2` +
[blue]`x=2*3 but x-1` +
[green]`5`.
2024-04-14 08:16:01 +02:00
2024-05-20 06:59:49 +02:00
[blue]`but` behavior is very similar to [blue]`;`. The only difference is that [blue]`;` is not a true operator and can't be used inside parenthesis [blue]`(` and [blue]`)`.
2024-04-14 08:16:01 +02:00
=== Assignment operator [blue]`=`
2024-05-20 06:59:49 +02:00
The assignment operator [blue]`=` is used to define variables or to change their value in the evaluation context (see _ExprContext_).
2024-04-14 08:16:01 +02:00
The value on the left side of [blue]`=` must be an identifier. The value on the right side can be any expression and it becomes the result of the assignment operation.
.Example
2024-05-17 15:46:56 +02:00
`>>>` [blue]`a=15+1`
[green]`16`
2024-04-14 08:16:01 +02:00
=== Selector operator [blue]`? : ::`
The _selector operator_ is very similar to the _switch/case/default_ statement available in many programming languages.
2024-05-17 15:46:56 +02:00
.Selector literal Syntax
_selector-operator_ = _select-expression_ "*?*" _selector-case_ { "*:*" _selector-case_ } ["*::*" _default-multi-expression_] +
_selector-case_ = [_match-list_] _case-value_ +
_match-list_ = "*[*" _item_ {"*,*" _items_} "*]*" +
_item_ = _expression_ +
_case-multi-expression_ = "*{*" _multi-expression_ "*}*" +
_multi-expression_ = _expression_ { "*;*" _expression_ } +
_default-multi-expression_ = _multi-expression_
2024-04-14 08:16:01 +02:00
2024-05-17 15:46:56 +02:00
In other words, the selector operator evaluates the _select-expression_ on the left-hand side of the [blue]`?` symbol; it then compares the result obtained with the values listed in the __match-list__'s, from left to right. If the comparision finds a match with a value in a _match-list_, the associated _case-multi-expression_ is evaluted, and its result will be the final result of the selection operation.
2024-05-06 04:24:17 +02:00
2024-05-17 15:46:56 +02:00
The match lists are optional. In that case, the position, from left to right, of the _selector-case_ is used as _match-list_. Of course, that only works if the _select-expression_ results in an integer.
2024-05-06 04:24:17 +02:00
2024-05-17 15:46:56 +02:00
The [blue]`:` symbol (colon) is the separator of the selector-cases. Note that if the value of the _select-expression_ does not match any _match-list_, an error will be issued. Therefore, it is strongly recommended to provide a default (multi-)expression introduced by the [blue]`::` symbol (double-colon). Also note that the default expression has no _match-list_.
2024-05-06 04:24:17 +02:00
.Examples
2024-05-17 15:46:56 +02:00
`>>>` [blue]`1 ? {"a"} : {"b"}` +
[green]`b` +
`>>>` [blue]`10 ? {"a"} : {"b"} :: {"c"}` +
[green]`c' +
[green]`>>>` [blue]`10 ? {"a"} :[true, 2+8] {"b"} :: {"c"}` +
[green]`b` +
`>>>` [blue]`10 ? {"a"} :[true, 2+8] {"b"} ::[10] {"c"}` +
[red]`Parse Error: [1:34] case list in default clause` +
[green]`>>>` [blue]`10 ? {"a"} :[10] {x="b" but x} :: {"c"}` +
[green]`b` +
`>>>` [blue]`10 ? {"a"} :[10] {x="b"; x} :: {"c"}` +
[green]`b` +
`>>>` [blue]`10 ? {"a"} : {"b"}` +
2024-05-11 20:14:54 +02:00
[red]`Eval Error: [1:3] no case catches the value (10) of the selection expression`
2024-05-17 15:46:56 +02:00
=== Variable default value [blue]`??` and [blue]`?=`
The left operand of these two operators must be a variable. The right operator can be any expression. They return the value of the variable if this is define; otherwise they return the value of the right expression.
IMPORTANT: If the left variable is defined, the right expression is not evuated at all.
The [blue]`??` do not change the status of the left variable.
The [blue]`?=` assigns the calculated value of the right expression to the left variable.
.Examples
`>>>` [blue]`var ?? (1+2)`'
[green]`3` +
`>>>` [blue]`var` +
[red]`Eval Error: undefined variable or function "var"` +
`>>>` [blue]`var ?= (1+2)` +
[green]`3` +
`>>>` [blue]`var` +
[green]`3`
NOTE: These operators have a high priority, in particular higher than the operator [blue]`=`.
2024-04-14 08:16:01 +02:00
== Priorities of operators
The table below shows all supported operators by decreasing priorities.
.Operators priorities
2024-05-20 06:59:49 +02:00
[cols="^2,^2,^2,^5,^6"]
2024-04-14 08:16:01 +02:00
|===
| Priority | Operators | Position | Operation | Operands and results
2024-05-20 06:59:49 +02:00
.2+|*ITEM*| [blue]`.` | _Infix_ | _List item_| _list_ `"."` _integer_ -> _any_
| [blue]`.` | _Infix_ | _Dict item_ | _dict_ `""` _any_ -> _any_
2024-05-06 04:24:17 +02:00
.2+|*INC*| [blue]`++` | _Postfix_ | _Post increment_| _integer-variable_ `"++"` -> _integer_
| [blue]`++` | _Postfix_ | _Next item_ | _iterator_ `"++"` -> _any_
.1+|*FACT*| [blue]`!` | _Postfix_ | _Factorial_| _integer_ `"!"` -> _integer_
.3+|*SIGN*| [blue]`+`, [blue]`-` | _Prefix_ | _Change-sign_| (`"+"`\|`"-"`) _number_ -> _number_
| [blue]`#` | _Prefix_ | _Lenght-of_ | `"#"` _collection_ -> _integer_
| [blue]`#` | _Prefix_ | _Size-of_ | `"#"` _iterator_ -> _integer_
.5+|*PROD*| [blue]`*` | _Infix_ | _Product_ | _number_ `"*"` _number_ -> _number_
| [blue]`*` | _Infix_ | _String-repeat_ | _string_ `"*"` _integer_ -> _string_
| [blue]`/` | _Infix_ | _Division_ | _number_ `"/"` _number_ -> _number_
| [blue]`./` | _Infix_ | _Float-division_ | __number__ `"./"` _number_ -> _float_
| [blue]`%` | _Infix_ | _Integer-remainder_ | _integer_ `"%"` _integer_ -> _integer_
2024-05-20 06:59:49 +02:00
.6+|*SUM*| [blue]`+` | _Infix_ | _Sum_ | _number_ `"+"` _number_ -> _number_
2024-05-06 04:24:17 +02:00
| [blue]`+` | _Infix_ | _String-concat_ | (_string_\|_number_) `"+"` (_string_\|_number_) -> _string_
| [blue]`+` | _Infix_ | _List-join_ | _list_ `"+"` _list_ -> _list_
2024-05-20 06:59:49 +02:00
| [blue]`+` | _Infix_ | _Dict-join_ | _dict_ `"+"` _dict_ -> _dict_
2024-05-06 04:24:17 +02:00
| [blue]`-` | _Infix_ | _Subtraction_ | _number_ `"-"` _number_ -> _number_
| [blue]`-` | _Infix_ | _List-difference_ | _list_ `"-"` _list_ -> _list_
2024-05-20 06:59:49 +02:00
.8+|*RELATION*| [blue]`<` | _Infix_ | _less_ | _comparable_ `"<"` _comparable_ -> _boolean_
2024-05-06 04:24:17 +02:00
| [blue]`\<=` | _Infix_ | _less-equal_ | _comparable_ `"\<="` _comparable_ -> _boolean_
| [blue]`>` | _Infix_ | _greater_ | _comparable_ `">"` _comparable_ -> _boolean_
| [blue]`>=` | _Infix_ | _greater-equal_ | _comparable_ `">="` _comparable_ -> _boolean_
| [blue]`==` | _Infix_ | _equal_ | _comparable_ `"=="` _comparable_ -> _boolean_
| [blue]`!=` | _Infix_ | _not-equal_ | _comparable_ `"!="` _comparable_ -> _boolean_
2024-05-20 06:59:49 +02:00
| [blue]`in` | _Infix_ | _member-of-list_ | _any_ `"in"` _list_ -> _boolean_
| [blue]`in` | _Infix_ | _key-of-dict_ | _any_ `"in"` _dict_ -> _boolean_
2024-05-06 04:24:17 +02:00
.1+|*NOT*| [blue]`not` | _Prefix_ | _not_ | `"not"` _boolean_ -> _boolean_
.2+|*AND*| [blue]`and` | _Infix_ | _and_ | _boolean_ `"and"` _boolean_ -> _boolean_
| [blue]`&&` | _Infix_ | _and_ | _boolean_ `"&&"` _boolean_ -> _boolean_
.2+|*OR*| [blue]`or` | _Infix_ | _or_ | _boolean_ `"or"` _boolean_ -> _boolean_
| [blue]`\|\|` | _Infix_ | _or_ | _boolean_ `"\|\|"` _boolean_ -> _boolean_
2024-05-20 06:59:49 +02:00
.3+|*ASSIGN*| [blue]`=` | _Infix_ | _assignment_ | _identifier_ "=" _any_ -> _any_
| [blue]`>>` | _Infix_ | _front-insert_ | _any_ ">>" _list_ -> _list_
| [blue]`<<` | _Infix_ | _back-insert_ | _list_ "<<" _any_ -> _list_
.1+|*BUT*| [blue]`but` | _Infix_ | _but_ | _any_ "but" _any_ -> _any_
2024-04-14 08:16:01 +02:00
|===
== Functions
Functions in _Expr_ are very similar to functions in many programming languages.
In _Expr_ functions compute values in a local context (scope) that do not make effects on the calling context. This is the normal behavior. Using the reference operator [blue]`@` it is possibile to export local definition to the calling context.
=== Function calls
#TODO: function calls operations#
=== Function definitions
#TODO: function definitions operations#
== Builtins
#TODO: builtins#
=== Builtin functions
=== [blue]_import()_
[blue]_import([grey]#<source-file>#)_ loads the multi-expression contained in the specified source and returns its value.