Operators¶
Overview¶
Larol provides a set of unary and binary operators.
Syntax¶
someFunction()
someStructCapability.someField
someStructCapability.someFunction()
someSliceCapability[someIndexValue]
(1 + 1)
!someBool
~someInt
-someInt
#someSliceCapability
move someLocalVariable
read someHandle
write someHandle
alloc SomeStructType
alloc SomeType[SomeLength]
someFunctionPointer == anotherFunctionPointer
2 * 3
9 / 3
7 % 3
2 + 3
9 - 3
10 << 2
32 >> 1
2 < 3
2 <= 3
4 > 5
4 >= 5
1 == 1
2 != 3
3 | 2
3 & 2
true || false
true && true
Rules¶
Precedence and Associativity¶
| Precedence | Operator | Associativity |
|---|---|---|
| 1 | (), ., [], f() | Left-to-right |
| 2 | !, ~, - (unary), #, alloc, move, read, write | Right-to-left |
| 3 | *, /, % | Left-to-right |
| 4 | +, - | Left-to-right |
| 5 | <<, >> | Left-to-right |
| 6 | <, <=, >, >= | Left-to-right |
| 7 | ==, != | Left-to-right |
| 8 | & | Left-to-right |
| 9 | \| | Left-to-right |
| 10 | && | Left-to-right |
| 11 | \|\| | Left-to-right |
Grouping¶
Parenthesised expressions MUST override default precedence and evaluate the enclosed expression first.
Integer Overflow¶
Runtime integer overflow on arithmetic operators (+, -, *) MUST wrap according to two's complement arithmetic. Division by zero MUST cause a fatal error.
Function Call¶
The function call operator MUST invoke the target function with the supplied arguments. The function call operator MUST be usable on member functions via the capability.functionName() syntax. When calling a member function, the capability expression serves as the implicit this argument. A read capability for a struct type MAY call member functions whose implicit this resolves to read StructType. A read capability MUST NOT call member functions whose implicit this resolves to write StructType. A write capability MAY call member functions whose implicit this resolves to either read StructType or write StructType. The function call operator MUST be usable on function pointer values via the pointerName(args) syntax.
When a handle-typed expression is passed as a function argument, move MUST be used: foo(move h). After the call, the source variable MUST be invalidated. move MUST NOT be used on non-handle argument types.
Field Access¶
The field access operator MUST access the named field of the operand (a struct capability). The field access operator MUST NOT be used on handle types (&T).
Index¶
The index operator MUST index into a slice capability or slice handle using the supplied value and produce the element at that position.
Logical NOT¶
The logical NOT operator MUST logically negate a boolean value, producing false if the operand is true and true if the operand is false.
Bitwise NOT¶
The bitwise NOT operator MUST apply a bitwise NOT to any integer type, flipping every bit.
Arithmetic Negation¶
The arithmetic negation operator MUST negate a numeric value arithmetically. Arithmetic negation MUST be supported for all integer and floating-point types.
Length Of (#)¶
The length of operator MUST produce the number of elements in a slice capability or slice handle.
Move¶
The move operator MUST only be applied to an lvalue. The move operator MUST invalidate the source lvalue and produce its value as an rvalue.
Read¶
The read operator MUST only be applied to a handle type. The read operator MUST produce a read capability for the handle's owned object/memory. The read operator MUST be applicable to expressions that evaluate to a handle value, including handle-typed variable references and handle member field access results. Applying the read operator to a handle-valued expression MUST NOT constitute a handle copy; the compiler MUST access the underlying object directly to produce the capability.
Multithreading may be supported in future versions; additional rules may apply at that time.
Write¶
The write operator MUST only be applied to a handle type. The write operator MUST produce a write capability for the handle's owned object/memory. A write capability for a struct handle MUST provide read-write access to the struct's fields. A write capability for a slice handle MUST provide read-write access to the slice's elements. The write operator MUST be applicable to expressions that evaluate to a handle value, including handle-typed variable references and handle member field access results. Applying the write operator to a handle-valued expression MUST NOT constitute a handle copy; the compiler MUST access the underlying object directly to produce the capability.
Multithreading may be supported in future versions; additional rules may apply at that time.
Alloc¶
Use of alloc MUST only be permitted within a region scope.
alloc SomeStructType MUST allocate a struct of the given type within the current region by calling larol_alloc; this MUST produce a struct handle for the given type.
alloc SomeType[SomeLength] MUST allocate a slice of the given element type and length within the current region by calling larol_alloc_slice; this MUST produce a slice handle for the given element type. The provided length MUST NOT be negative. A length of zero MUST be permitted, the larol_alloc_slice function SHOULD NOT be called for slice allocations with length of zero.
Multiply¶
The multiply operator MUST multiply two numeric values and produce their product.
Divide¶
The divide operator MUST divide the left operand by the right operand and produce the quotient. For integer division, the quotient MUST be truncated toward zero (i.e., the fractional part is discarded).
Remainder¶
The remainder operator MUST divide the left operand by the right operand and produce the remainder. For integer operands, the sign of the remainder MUST match the sign of the left operand (the dividend). Truncation toward zero MUST be used.
Add¶
The add operator MUST add two numeric values and produce their sum.
Subtract¶
The subtract operator MUST subtract the right operand from the left operand and produce the difference.
Left Shift¶
The left shift operator MUST shift the bits of the left operand to the left by the number of positions given by the right operand. Vacated bits MUST be filled with zero.
Right Shift¶
The right shift operator MUST shift the bits of the left operand to the right by the number of positions given by the right operand. If the left operand is a signed type, the shift MUST be arithmetic (sign-extending). If the left operand is an unsigned type, the shift MUST be logical (zero-filling).
Less Than¶
The less than operator MUST produce true if the left operand is strictly less than the right operand, otherwise false.
Less Than or Equal¶
The less than or equal operator MUST produce true if the left operand is less than or equal to the right operand, otherwise false.
Greater Than¶
The greater than operator MUST produce true if the left operand is strictly greater than the right operand, otherwise false.
Greater Than or Equal¶
The greater than or equal operator MUST produce true if the left operand is greater than or equal to the right operand, otherwise false.
Equal¶
The equal operator MUST produce true if both operands are equal, otherwise false. The equal operator MUST be permitted on primitive types, function pointer types, and struct handle types. Two struct handles are equal if and only if they reference the same allocation or are both null.
Not Equal¶
The not equal operator MUST produce true if the operands are not equal, otherwise false. The not equal operator MUST be permitted on primitive types, function pointer types, and struct handle types.
Bitwise AND¶
The bitwise AND operator MUST apply a bitwise AND to two integer values, producing a value where each bit is set only if the corresponding bit is set in both operands.
Bitwise OR¶
The bitwise OR operator MUST apply a bitwise OR to two integer values, producing a value where each bit is set if the corresponding bit is set in either operand.
Logical AND¶
The logical AND operator MUST produce true only if both operands are true. The logical AND operator MUST short-circuit and not evaluate the right operand if the left operand is false.
Logical OR¶
The logical OR operator MUST produce true if either operand is true. The logical OR operator MUST short-circuit and not evaluate the right operand if the left operand is true.