Prev: Arrays
Expressions
Generally speaking, expressions define (arithmetic, bitwise, comparison, or logical) operations on (variable, literal, or function result) operands.
Operands
In
m, there are four types of operands:
- Designators: the operand is the value of a variable or array element, e.g. count, list[i], or a class instance field.
- Function Calls: the operand is the result of a function call, e.g. io.read(f, 10), math.sin(x). Functions are explained in sections * () and * ().
- Literals: the operand is a literal, i.e. an explicit value, e.g. 42, "Hello".
- Expression: the operand is an expression in parentheses, e.g. (7.2*x), (not exists[key]).
Operation Precedence
Each operation has a precedence defining the order in which operations are executed: as a general rule, arithmetic and bitwise operations are executed before comparisons, and comparisons are executed before boolean operations. Within each group, multiplicative operations have higher precedence than additive ones. Operations of equal precedence are executed from left to right. The order of execution can be changed by grouping subexpressions into parentheses.
t=3; s=7; m="aha";
print t + 5*s - 2/4 // multiplicative before additive
→ 37.5
print s&4 > t|4 // bitwise before comparison
→ false
print 13>s or m>"b" // comparison before boolean ops
→ true
print (20+t)*(s-24) // parentheses change the order
→ -391
|
Arithmetic Operators
The arithmetic operators are (P is the precedence):
| Op | P | Description |
| x+y | 4 | Addition. |
| x-y | 4 | Subtraction. |
| x*y | 5 | Multiplication. |
| x/y | 5 | Division. |
| x%y | 5 | Integer remainder: x - y*trunc(x/y); if y=0, throws ExcDivideByZero. |
| -x | 6 | Change sign of x. |
| |
print 22 / 7
→ 3.142857149
print 97 % 11
→ 9
print 97 % -11
→ 9
print -97 % 11
→ -9
|
Except for %, these operations never throw an exception if an invalid operation is attempted or overflow or underflow occurs. Instead, the result becomes (negative or positive) infinity, or zero:
x=1e200;
print x*x
→ Inf
print -2/0
→ -Inf
print 1/x/x
→ 0
|
Bitwise Operators
Bitwise operators work on integer numbers, treating them like signed binary numbers of 32 bits. Such operations are typically used to represent sets of binary states (e.g. flags) in a single value, or for hardware related operations.
The bitwise operators are (P is the precedence):
| Op | P | Description |
| x|y | 4 | Bitwise or. |
| x^>y | 4 | Bitwise exclusive or. |
| x&>y | 5 | Bitwise and. |
| x shl y | 5 | Bitwise shift left. |
| x shr y | 5 | Bitwise shift right. |
| ~>x | 6 | Bitwise not. |
| |
print 1|2|4|8
→ 15
print 10&(2|4)
→ 2
print 14^11
→ 5
print ~(14&11) & (14|11) // ~(a&b) & (a|b) = a^b
→ 5
print 13 shl 4 // 13*16
→ 208
print 341 shr 2 // trunc(341 / 4)
→ 85
print ~0 // set all bits in signed integer
→ -1
print -5 & ~19
→ -24
|
Concatenation Operator
The concatenation operator concatenates two strings or a string with the string representation of another value (P is the precedence):
| Op | P | Description |
| x + y | 4 | Concatenation: x followed by y. |
| |
Note that if neither of the two operands is a string, the two operands are assumed to be numbers and added.
print "One" + "Two"
→ OneTwo
print "x=" + 3/4
→ x=0.75
|
Comparison Operators
Comparing two operands always produces a boolean value. Testing for equality and inequality works for all pairs of operands. Operands of different types (e.g. a number and a string) are never equal.
Only numbers and strings can be ordered, i.e. compared for less or greater than. Strings are ordered by their UNICODE® character values, which orders uppercase before lowercase, and does not produce a general lexical ordering. Use .collate to lexically compare strings.
Trying to order operands other than numbers or strings throws ExcNotComparable.
Two arrays are only equal if they are the same array. .equal compares two arrays element by element.
null is only equal to itself.
The comparison operators are (P is the precedence):
| Op | P | Description |
| x = y | 3 | true if x is equal to y. |
| x # y | 3 | true if x is not equal to y. |
| x <> y | 3 | The same as x # y>. |
| x < y | 3 | true if x is less than y. |
| x <= y | 3 | true if x is less than or equal to y. |
| x > y | 3 | true if x is greater than y. |
| x >= y | 3 | true if x is greater than or equal to y. |
| |
print 7>5
→ true
print "o" + "ne" = "one"
→ true
print "two" < "three"
→ false
print "Two" < "three" // no lexical ordering
→ true
print 14 = "a"
→ false
print 13 # "b"
→ true
print 13 < "14"
→ ExcNotComparable thrown
|
Class Instance Tests
The class instance test checks whether an expression is an instance of a given class. In other words, x is C tests whether an assignment
succeeds. Section * () explains classes and class hierarchies.
The class instance test operator is (P is the precedence):
| Op | P | Description |
| x is C | 3 | true if x is an instance of class C, or is null. |
| |
// declare a simple class hierarchy
class C end
class D is C end
// numbers and strings are never class instances
print 7 is C,"hello" is D
→ false false
// test actual instances
x=C()
print x is C, x is D
→ true false
x=D()
print x is C, x is D
→ true true
// null is an instance of all classes
x=null
print x is C, x is D
→ true true
|
Boolean Operators
The boolean operators are (P is the precedence):
| Op | P | Description |
| x or y | 1 | Logical or: true if either x or y is true, false if both x and y are false. |
| x and y | 2 | Logical and: true if both x and y is true, false if either x or y are false. |
| not x | 6 | Logical not: true if x is false, false if x is true. |
| |
print false or false, false or true, true or false,
true or true
→ false true true true
print false and false, false and true, true and false,
true and true
→ false false false true
print not false, not true
→ true false
|
The second operand is only evaluated if the first operand doesn't already determine the result. This is often useful when doing combined checks, as it avoids evaluation of invalid expressions:
ok=m#0 and 17%m = 3 // deadly 17%0 is never evaluated
|
| | |
Expression := Predicate {or Predicate} .
Predicate := Comparison {and Comparison} .
Comparison :=
Sum [('=' | '<>' | '#' | '<' | '>' | '<=' | '>=') Sum] |
is ClassIdentifier] .
Sum := Product {('+' | '-' | '|' | '^') Product} .
Product := Factor {('*' | '/' | '%' | '&' | shl | shr) Factor} .
Factor := ['-' | '~' | not ]
(Designator | FunctionCall | IndirectFunctionCall |
InstanceCreation | Literal | '(' Expression ')' ) .
|
|
See * () for an explanation of class identifiers and instance creation.
Next: Statements© 2004-2011 airbit AG, CH-8008 Zürich
Document AB-M-REF-887