Expressions
===========
Expressions are combinations of operands and operators.
Operands are values in themselves, which may be expressions surrounded by ``( )``.
Operators are logical, arithmetic, or string and the valid operators depend on the types of the operands.
Literal Values
--------------
Literal values can be individual lexical elements such as :ref:`identifiers `, :ref:`numbers `, and :ref:`strings `.
Literal arrays are sequences of comma-separated values surrounded by brackets ``[ ]``.
Example::
LET a: Array := [1, 2, 3]
Literal dictionaries are sequences of comma-separated name/value pairs surrounded by braces ``{ }``.
Example::
LET d: Dictionary := {
"one": 1,
"two": 2,
"three": 3
}
For convenience, both literal arrays and dictionaries accept a trailing comma after the final element::
LET numbers: Array := [
"zero",
"one",
"two",
]
Boolean Operators
-----------------
The following operator takes one boolean value.
======== ============
Operator Description
======== ============
``NOT`` logical negation
======== ============
The following operators take two boolean values.
======== ============
Operator Description
======== ============
``=`` equality
``<>`` inequality
``AND`` logical conjunction
``OR`` logical disjunction
======== ============
Numeric Operators
-----------------
The following operators take one number value.
======== ===========
Operator Description
======== ===========
``+`` identity (provided for symmetry with ``-``)
``-`` arithmetic negation
======== ===========
The following operators take two number values.
========== ===========
Operator Description
========== ===========
``+`` addition
``-`` subtraction
``*`` multiplication
``/`` division
``INTDIV`` integer division
``MOD`` modulo (remainder)
``^`` exponentiation
``=`` equality
``<>`` inequality
``<`` less than
``>`` greater than
``<=`` less than or equal
``>=`` greater than or equal
========== ===========
String Operators
----------------
The following operators take two string values.
======== ===========
Operator Description
======== ===========
``&`` concatenation
``=`` equality
``<>`` inequality
``<`` lexicographical less than
``>`` lexicographical greater than
``<=`` lexicographical less than or equal
``>=`` lexicographical greater than or equal
======== ===========
Array Operators
---------------
========== ===========
Operator Description
========== ===========
``IN`` membership test (*O(n)* complexity)
``NOT IN`` membership test (*O(n)* complexity)
========== ===========
Dictionary Operators
--------------------
========== ===========
Operator Description
========== ===========
``IN`` membership test (*O(log n)* complexity)
``NOT IN`` membership test (*O(log n)* complexity)
========== ===========
Object Operator
---------------
======== ===========
Operator Description
======== ===========
``ISA`` type test (``object ISA Type``)
======== ===========
Pointer Operator
----------------
======== ===========
Operator Description
======== ===========
``->`` pointer dereference
======== ===========
Operator Precedence
-------------------
The operator precedence is as follows, highest to lowest:
====================================== ===========
Operator Description
====================================== ===========
``( )`` subexpression
``^`` exponentiation
``*`` ``/`` ``MOD`` ``INTDIV`` multiplication, division, modulo
``+`` ``-`` ``&`` addition, subtraction, concatenation
``=`` ``<>`` ``<`` ``>`` ``<=`` ``>=`` comparison
``IN`` ``NOT IN`` membership
``AND`` conjunction
``OR`` disjunction
``IF`` conditional
====================================== ===========
Array Subscripts
----------------
Array subscripts are normally integers greater than or equal to zero::
LET a: Array := ["foo", "bar", "baz"]
print(a[0])
print(a[2])
Two special values may be used, ``FIRST`` and ``LAST``::
LET a: Array := ["foo", "bar", "baz"]
print(a[FIRST])
print(a[LAST])
``FIRST`` always means the same as `0` and is provided for completeness.
``LAST`` refers to the index of the last element of the array (if the array is not empty).
Array slices are also possible using the ``TO`` keyword.
Both indexes are inclusive::
LET a: Array := ["foo", "bar", "baz"]
LET b: Array := a[0 TO 1]
LET c: Array := a[LAST-1 TO LAST]
In the above example, ``b`` contains ``["foo", "bar"]`` and ``c`` contains ``["bar", "baz"]``.
Dictionary Subscripts
---------------------
Dictionary subscripts are strings::
LET d: Dictionary := {
"apple": "red",
"orange": "orange",
"banana": "yellow"
}
print(d["apple"])
print(d["banana"])
Conditional Expression
----------------------
A conditional expression is like an inline ``IF`` statement::
LET n: Number := 5
LET s: String := (IF n >= 0 THEN "positive" ELSE "negative")
The condition following ``IF`` is evaluated.
If it is true, then the ``THEN`` expression is evaluated and is the result of the expression.
Otherwise, the ``ELSE`` expression is evaluated and is the result of the expression.
The parentheses around the entire conditional expression are required.
.. note::
The branch not taken is *not* evaluated.
This means that if a branch not taken is a function call, the function will not be called.
Try Expression
--------------
A try expression is like an inline ``TRY`` statement::
LET a: Number := 5
LET b: Number := 0
LET n: Number := (TRY a / b TRAP DivideByZeroException GIVES -1)
The expression following ``TRY`` is evaluated.
If an exception is raised, then it is matched against the ``TRAP`` clauses.
A matching ``TRAP`` clause with a ``GIVES`` keyword evalues the ``GIVES`` expression and returns that as the value of the try expression.
The keyword ``DO`` can be used instead of ``GIVES``.
The ``DO`` keywords introduces a new statement block which must end with a block-exiting statement (``EXIT``, ``NEXT``, ``RAISE``, or ``RETURN``).
Expression Substitution
-----------------------
Literal strings may contain embedded expressions surrounded by the special escape ``\( )``.
These expressions are evaluated at run time.
The type of the embedded expression must have a ``.toString()`` method which will be called automatically to convert the result to a string.
Example::
LET a: Array := ["one", "two", "three"]
FOR i := 0 TO 2 DO
print("i is \(i) and the array element is \(a[i])")
END FOR
.. admonition:: TODO
formatting specifiers