Websites Navigation: Airbit | Shop | m-shell.net
Languages: EN | DE

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):

OpPDescription
x+y4Addition.
x-y4Subtraction.
x*y5Multiplication.
x/y5Division.
x%y5Integer remainder: x - y*trunc(x/y); if y=0, throws ExcDivideByZero.
-x6Change 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):

OpPDescription
x|y4Bitwise or.
x^y4Bitwise exclusive or.
x&y5Bitwise and.
x shl y5Bitwise shift left.
x shr y5Bitwise shift right.
~x6Bitwise 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):

OpPDescription
x + y4Concatenation: 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):

OpPDescription
x = y3true if x is equal to y.
x # y3true if x is not equal to y.
x <> y3The same as x # y.
x < y3true if x is less than y.
x <= y3true if x is less than or equal to y.
x > y3true if x is greater than y.
x >= y3true 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

v:C=x

succeeds. Section * () explains classes and class hierarchies.

The class instance test operator is (P is the precedence):

OpPDescription
x is C3true 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):

OpPDescription
x or y1Logical or: true if either x or y is true, false if both x and y are false.
x and y2Logical and: true if both x and y is true, false if either x or y are false.
not x6Logical 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.


© 2004-2011 airbit AG, CH-8008 Zürich
Document AB-M-REF-887
mShell Home  > Documentation  > Manuals