Skip to content

Operations

Expressions

expression = boolean-literal / binary-literal / octal-literal / decimal-literal / decimal-dp-literal / scientific-literal / hexadecimal-literal / character-literal
expression /= type-literal
expression /= string-literal / regex-literal / array-literal / tuple-literal / dictionary-literal
expression /= identifier
expression /= parenthesis
expression /= cast
expression /= function-call
expression /= new
expression /= bracket-access / dot-access
expression /= post-increment / post-decrement / pre-increment / pre-decrement
expression /= unary-plus / unary-minus
expression /= logical-not / logical-and / logical-or
expression /= lower-than / lower-or-equal-to / greater-than / greater-or-equal-to / equal / different / strictly-equal / strictly-different
expression /= instance-of / not-instance-of / in / not-in
expression /= bitwise-not / bitwise-and / bitwise-xor / bitwise-or / left-shift / right-shift / zfill-right-shift / rotate-left / rotate-right
expression /= addition / subtraction / multiplication / exponentiation / division / remainder / modulo
expression /= ternary-conditional
expression /= assignment / left-shift-assignment / right-shift-assignment / zfill-right-shift-assignment / rotate-left-assignment / rotate-right-assignment / bitwise-not-assignment / addition-assignment / subtraction-assignment / exponentiation-assignment / multiplication-assignment / division-assignment / reminder-assignment / modulo-assignment / bitwise-and-assignment / bitwise-xor-assignment / bitwise-or-assignment / logical-and-assignment / logical-or-assignment

side-effect-expression = function-call
side-effect-expression /= new
side-effect-expression /= post-increment / post-decrement / pre-increment / pre-decrement
side-effect-expression /= assignment / left-shift-assignment / right-shift-assignment / zfill-right-shift-assignment / rotate-left-assignment / rotate-right-assignment / bitwise-not-assignment / addition-assignment / subtraction-assignment / exponentiation-assignment / multiplication-assignment / division-assignment / reminder-assignment / modulo-assignment / bitwise-and-assignment / bitwise-xor-assignment / bitwise-or-assignment / logical-and-assignment / logical-or-assignment

Each expression is typed:

  • Expressions that are a literal of a primitive type are typed according to the type given by the type inference algorithm.
  • Expressions that are String literals, Regex literals, Array literals, Tuple literals or Dictionary literals are respectively of type “String”, “Regex”, “Array”, “Tuple” and “Dictionary”.
  • Expressions that are identifiers corresponding to variables are of type of the corresponding variable.
  • Expressions that are identifiers corresponding to a function are of type of the corresponding function.
  • Expressions that are names of primitive types, or identifiers corresponding to class or interface names, are of type “type”.
  • Expressions that are combinations of other expressions are described bellow.

Operators

Notes (TODO remove)

let a = 0;
let b = 5;

let res = a < b; // (0, true, 5) chaining_tuple
type CharArray = char[] | String | StringBuilder;
  • TODO type expressions
  • TODO Regex
  • TODO String

Parenthesis

parenthesis = "(" expression ")"

Parenthesis can be wrapped around any expression without modifying its value. Because parenthesis have the highest precedence, they can be used to control the order of operations. The resulting expression is of same type as the wrapped expression.

Cast operator

cast = expression "as" expression

The cast operator is used to modify the type (and possibly the value) of the LHS expression. The resulting expression is of type given by the RHS expression that itself must be of type “type”. Type casting is further explained in the type casting section.

Function call

unnamed-argument = expression
unnamed-argument-list = unnamed-argument *("," unnamed-argument)

named-argument = identifier ":" expression
named-argument-list = named-argument *("," named-argument)

argument-list = [unnamed-argument-list / named-argument-list / unnamed-argument-list "," named-argument-list] [","]

function-call = expression "(" argument-list ")"
  • The first expression MUST be of type “function”.
  • Each argument MUST have the type defined in the function signature, or have a type implicitly castable to the type defined in the function signature.
  • Named arguments MUST appear after the unnamed ones.
  • Mandatory arguments MUST be all present.
  • Arguments not present in the function signature MUST NOT appear.
  • A trailing coma MAY appears at the end of the argument list (even if there 0 arguments).

The resulting type is the return type defined in the function signature (“void” type if there is no return type).

Example

Calling the foo function with 42 as first argument, 3.14 for bar argument and a trailing coma.

foo(42, bar: 3.14,)

Tuple operator

Tuple expression

tuple = expression "," *(expression ",") [expression]

A tuple can be defined by one ore more expressions separated by comas. When their is only one expression, the trailing coma is mandatory.

The resulting value, is a tuple containing, at the umpteenth index, the value of the umpteenth expression.

The resulting type is a tuple type having, at the umpteenth index, the type of the umpteenth expression.

tuple-typedef = "tuple" "<" [expression *("," expression)] [","] ">"

Tuple type definition

A tuple type can be defined by the tuple keyword followed by type expressions separated by comas between angle brackets.

The resulting value is a tuple type having, at the umpteenth index, the type defined by the umpteenth expression.

The resulting type is the “type” type.

Lambda operator

Anonymous function declaration

arg = [expression] identifier
arg-signature = [arg *("," arg)] [","]
lambda-function = *annotation "(" arg-signature ")" "->" expression [function-body]

The lambda operator can be used to define an anonymous function.

  • The RHS part (after the arrow) can be either:
    • an expression which will be computed and returned when the function is called (in this case, the return type is the type of the RHS expression),
    • or the return type followed by a classical function block.
  • The parameters types can be omitted, only if, by ascending the AST, they can be deduced. For example, by passing a lambda function “L” as a parameter of another function “F”, the type of “L” may be deduced by checking the signature of “F”.

The resulting type is a function type with the correct signature.

Examples

(i32 x, i32 y) -> x * y
(i32 x, i32 y) -> i32 {
    return x * y;
}

Function type declaration

function-signature-args = [expression *("," expression)] [","]
function-signature = "(" function-signature-args ")" "->" (expression / "void")

The lambda operator can be used to define an anonymous function.

The resulting type is the “type” type.

Example

(i32, i32) -> i32

“new” operator

new = "new" identifier "(" argument-list ")"

The “new” operator creates a new object from the class given by the identifier.

  • The identifier MUST refers to a class name available in the current scope.
  • The identifier MUST NOT refers to an abstract class.
  • The argument list MUST follows the same rules as if it was a function call on the constructor.

The resulting type is the class from which the object was created.

Accesses

bracket-access = expression "[" expression "]"
dot-access     = expression "." identifier
  • The umpteenth element of a tuple or array can be accessed using bracket and an integer expression. Negative indices can be used to count from the end of the tuple or array.
  • A class static field or an object field can be accessed by a dot followed by the identifier of the given field.
  • The element of a dictionary can be accessed by using brackets with a String expression corresponding to the element key. If the element is a valid identifier, it can also be accessed using a dot followed by the key.

Here is a summary of that:

type of accessed entity dot-accessible bracket-accessible type of key used in brackets
array integer
tuple integer
dictionary String or any type implicitly castable to String
object
class

If the element trying to be accessed doesn't exist or the requested index is out of range, it will either, not compile if the error can be detected at compile time, or it will throw an exception.

It exists also optional chaining operators:

optional-chaining-bracket-access = expression "?[" expression "]"
optional-chaining-dot-access     = expression "?." identifier

They work like their counterparts except that, if the element trying to be accessed doesn't exist or the requested index is out of range, they will not throw an exception but return “void”. Also, they accept void as LHS. In this case they will also return “void” (useful for chaining).

TODO destructuring (array, dic, tuple)

Increments & decrements

post-increment = identifier "++"
post-decrement = identifier "--"
pre-increment  = "++" identifier
pre-decrement  = "--" identifier

Unary plus and minus

unary-plus  = "+" expression
unary-minus = "-" expression

Logical “boolean” operators

logical-not =             "!" expression
logical-and = expression "&&" expression
logical-or  = expression "||" expression

Logical “comparison” operators

lower-than          = expression       "<"       expression
lower-or-equal-to   = expression ("<=" / %u2264) expression
greater-than        = expression       ">"       expression
greater-or-equal-to = expression (">=" / %u2265) expression
equal               = expression       "=="      expression
different           = expression       "!="      expression
strictly-equal      = expression      "==="      expression
strictly-different  = expression      "!=="      expression

Other logical operators

instance-of     = expression       "instanceof" expression
not-instance-of = expression "not" "instanceof" expression
in              = expression       "in"         expression
not-in          = expression "not" "in"         expression

Bitwise operators

bitwise-not       =             "~"  expression
bitwise-and       = expression  "&"  expression
bitwise-xor       = expression  "^"  expression
bitwise-or        = expression  "|"  expression
left-shift        = expression "<<"  expression
right-shift       = expression ">>"  expression
zfill-right-shift = expression ">>>" expression
rotate-left       = expression "rol" expression
rotate-right      = expression "ror" expression

Arithmetic operators

addition       = expression "+"  expression
subtraction    = expression "-"  expression
multiplication = expression "*"  expression
exponentiation = expression "**" expression
division       = expression "/"  expression
remainder      = expression "%"  expression
modulo         = expression "%%" expression

Ternary conditional

ternary-conditional = expression "?" expression ":" expression

Assignments

assignment                   = identifier    "=" expression
left-shift-assignment        = identifier  "<<=" expression
right-shift-assignment       = identifier  ">>=" expression
zfill-right-shift-assignment = identifier ">>>=" expression
rotate-left-assignment       = identifier "rol=" expression
rotate-right-assignment      = identifier "ror=" expression
bitwise-not-assignment       = identifier   "~=" expression
addition-assignment          = identifier   "+=" expression
subtraction-assignment       = identifier   "-=" expression
exponentiation-assignment    = identifier  "**=" expression
multiplication-assignment    = identifier   "*=" expression
division-assignment          = identifier   "/=" expression
reminder-assignment          = identifier   "%=" expression
modulo-assignment            = identifier  "%%=" expression
bitwise-and-assignment       = identifier   "&=" expression
bitwise-xor-assignment       = identifier   "^=" expression
bitwise-or-assignment        = identifier   "|=" expression
logical-and-assignment       = identifier  "&&=" expression
logical-or-assignment        = identifier  "||=" expression

Operators precedence

The various mechanisms described above have the following precedence, from highest (binding tightest) at the top, to lowest (loosest) at the bottom:

TODO update table

Priority Operator Description Associativity
15 ()
()
[]
.
++
--
parenthesis
function call
bracket access
dot access
post-increment
post-decrement
left to right
14 ++
--
+
-
!
~
pre-increment
pre-decrement
unary plus
unary minus
logical NOT
bitwise NOT
right to left
13 ** power left to right
12 *
/
%
%%
multiplication
division
remainder
modulo
11 +
-
addition
substraction
10 <<
>>
>>>
rol
ror
bitwise left shift
bitwise right shift
bitwise zero-fill right shift
bitwise left rotation
bitwise right rotation
9 <
<=
>
>=
instanceof
relational <
relational ≤
relational >
relational ≥
instanceof
8 ==
===
!=
!==
relational =
relational strict =
relational ≠
relational strict ≠
7 & bitwise AND
6 ^ bitwise XOR
5 | bitwise OR
4 && logical AND
3 || logical OR
2 ?: ternary conditional right to left
1   =  <<=  >>= >>>=
 !=   ~=   +=   -=
**=   *=   /=   %=
%%=   &=   ^=   |=
&&=  ||=
assignments

Last update: June 16, 2021