# Operators¶

Corporate accounts payable, Nina speaking! Just a moment!

—Nina, corporate accounts payable, Office Space

The expression subset of the Monte grammar is presented here in operator precedence order, meaning that later constructs bind tighter than earlier constructs. For example, expr “+” expr is presented before expr “*” expr, so * binds tighter than +. Therefore, a + b * c + d is equivalent to a + (b * c) + d. All the constructs in presented in the same section have the same precedence.

Monte has a rich set of operators above and beyond those in Kernel-Monte. All operators are overloadable, but overloading follows a very simple set of rules: Operators expand to message passing, and the message is generally passed to the left-hand operand, except for a few cases where the message is passed to a helper object which implements the operation. In object capability shorthand, we are asking the object on the left what it thinks of the object on the right.

There are some special rules about the behavior of the basic operators because of E’s distributed security.

Todo

special operator rules because of security

## Sequence¶

sequence

A sequence expressions evaluates to the value of its last item:

>>> { 4; "x"; "y" }
"y"

## Assignment and Definition¶

assign

lval

Assignment is right associative. The list update on the right happens before the definition on the left:

>>> def color := ["red", "green", "blue"].diverge()
... def c := color[1] := "yellow"
... c
"yellow"

### Indexed Update Expansion¶

An indexed update expands to a call to put:

>>> m`x[i] := 1`.expand()
m`x.put(i, def ares_1 := 1); ares_1`

### Augmented Assignment Expansion¶

VerbAssignExpr

All binary operators which pass a message to the left-hand operand can be used as augmented assignment operators. For example, augmented addition is legal:

>>> { var x := "augmenting "; x += "addition!"; x }

Behind the scenes, the compiler transforms augmented operators:

Monte permits this augmented construction for any verb, not just those used by operators. For example, the with verb of lists can be used to incrementally build a list:

>>> { var l := []; for i in (1..10) { l with= (i) }; l }
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

And even non-unary messages can get in on the fun, with a properly placed pair of parentheses:

>>> { var x := 7; x modPow= (129, 3) }
1

Todo

VERB_ASSIGN lexical details

### Assignment operators¶

>>> var x := 5; [ x += 2, x -= 1, x *= 2, x **= 3 ]
[7, 6, 12, 1728]
>>> var x := 50; [ x //= 3, x %= 7, x /= 4]
[16, 2, 0.500000]
>>> var x := 5; [ x ^= 3, x |= 15, x &= 7, x <<= 3, x >>= 2]
[6, 15, 7, 56, 14]

## Conditional-Or¶

logical_or

Monte uses C syntax for the basic logical operators:

>>> false || true
true

Evaluates left to right until it finds a true condition.

>>> {((1 =~ x) || (2 =~ x)); x}
1
>>> {((1 =~ [x, y]) || (2 =~ x)); x}
2

## Conditional-And¶

logical_and

### Logical Expansion¶

Boolean conditionals expand to if expressions:

>>> m`a || b`.expand()
m`if (a) { true } else if (b) { true } else { false }`

>>> m`a && b`.expand()
m`if (a) { if (b) { true } else { false } } else { false }`

## Comparisons and Bitwise/Logical Operators¶

comp

order

These are non-associative: x == y == z is a syntax error.

>>> false == true
false
>>> false != true
true

You can compare with a pattern and use the resulting bindings:

>>> [1, "x"] =~ [_ :Int, _ :Str]
true

>>> [1, 2] =~ [a, b]; b
2

>>> "<p>" =~ `<@tag>`; tag
"p"

>>> "<p>" !~ `</@tag>`
true

Comparison is more strict than you might expect:

>>> 3 == "3"
false

>>> 1 + 1 == 2.0
false

We also have negated implication operator:

>>> true &! false
true

Boolean Comparisons (non-associative):

>>> false & true
false

>>> false | true
true

>>> false ^ true
true

### Comparison Expansion¶

Comparisons expand to use of a helper object:

::
>>> m`x == y`.expand()
m`_equalizer.sameEver(x, y)`
>>> m`x != y`.expand()
m`_equalizer.sameEver(x, y).not()`
>>> m`"value" =~ pattern`.expand()
m`def sp_1 := "value"; def [ok_2, &&pattern] := escape fail_3 { def pattern exit fail_3 := sp_1; _makeList.run(true, &&pattern) } catch problem_4 { def via (_slotToBinding) &&broken_5 := Ref.broken(problem_4); _makeList.run(false, &&broken_5) }; ok_2`
>>> m`"value" !~ pattern`.expand()
m`(def sp_1 := "value"; def [ok_2, &&pattern] := escape fail_3 { def pattern exit fail_3 := sp_1; _makeList.run(true, &&pattern) } catch problem_4 { def via (_slotToBinding) &&broken_5 := Ref.broken(problem_4); _makeList.run(false, &&broken_5) }; ok_2).not()`
>>> m`x ^ y`.expand()
m`x.xor(y)`
>>> m`x & y`.expand()
m`x.and(y)`
>>> m`x | y`.expand()
m`x.or(y)`
>>> m`x &! y`.expand()
m`x.butNot(y)`

## Partial Ordering¶

CompareExpr

Monte has the usual ordering operators:

>>> 3 < 2
false
>>> 3 > 2
true
>>> 3 < 3
false
>>> 3 <= 3
true

They are non-associative and only partial:

>>> try { 3 < "3" } catch _ { "ouch! no order defined" }
"ouch! no order defined"

Use <=> aka asBigAs to compare magnitudes:

>>> 2.0 <=> 1 + 1
true

>>> 2 + 1 <=> 3.0
true

### Ordering Expansion¶

Ordering operators expand to use of a helper object:

>>> m`3 < 2`.expand()
m`_comparer.lessThan(3, 2)`

>>> m`2.0 <=> 1 + 1`.expand()

## Interval¶

RangeExpr

Non-associative.

We can build a half-open interval with the range operator:

>>> [for x in (1..!4) x * 2]
[2, 4, 6]

Or we can build closed intervals with the inclusive range operator:

>>> [for x in (1..4) x * 2]
[2, 4, 6, 8]

Half-open intervals are more typical, though they are in most ways equivalent to closed intervals:

>>> (0..!10) <=> (0..9)
true

Expansion:

>>> m`lo..hi`.expand()
m`_makeOrderedSpace.op__thru(lo, hi)`

>>> m`lo..!hi`.expand()
m`_makeOrderedSpace.op__till(lo, hi)`

## Shift¶

shift

Left associative.

Among built-in data types, this is only defined on integers, and has the traditional meaning but with no precision limit.

Expansion:

>>> m`i << bits`.expand()
m`i.shiftLeft(bits)`

>>> m`i >> bits`.expand()
m`i.shiftRight(bits)`

Left associative.

::
>>> [1, 2] + [3, 4]
[1, 2, 3, 4]
>>> "abc" + "def"
"abcdef"
>>> ["square" => 4] | ["triangle" => 3]
["square" => 4, "triangle" => 3]
>>> def sides := ["square" => 4, "triangle" => 3]
... sides.without("square")
["triangle" => 3]

Expansion:

>>> m`x + y`.expand()

>>> m`x - y`.expand()
m`x.subtract(y)`

## Multiplicative¶

multiplicativeExpr

Left associative.

>>> 2 * 3
6

Modular exponentiation:

>>> 5 ** 3 % 13
8

expansion:

>>> m`base ** exp % mod`.expand()
m`base.modPow(exp, mod)`

## Exponentiation¶

exponentiationExpr

Non-associative.

>>> 2 ** 3
8

Expansion:

>>> m`2 ** 3`.expand()
m`2.pow(3)`

## Unary Prefix¶

prefix

SlotExpr

BindingExpr

Monte has logical, bitwise, and arithmetic negation operators:

>>> - (1 + 3)
-4
>>> ~ 0xff
-256
>>> ! true
false

Todo

discuss, doctest SlotExpression &x, BindingExpression &&x

Expansions:

>>> m`! false`.expand()
m`false.not()`

## Unary Postfix¶

MetaExpr

CoerceExpr

meta.getState()
meta.context()

A guard can be used as an operator to coerce a value:

>>> 1 :Int
1

## Call¶

calls

call

send

curryTail

index

verb

argList

Todo

named args in argList

There are two ways to pass a message. First, the immediate call:

>>> { def x := 2; def result := x.add(3) }
5

And, second, the eventual send:

>>> { def x; def prom := x<-message(3); null }
null

Calls may be curried:

>>> { def x := 2; def xplus := x.add; xplus(4) }
6

Todo

discuss matchers in object expressions

### Call Expansion¶

Function call syntax elaborates to a call to run ( and likewise vice-versa):

>>> m`f(x)`.expand()
m`f.run(x)`

Indexing elaborates to a call to get:

>>> { object parity { to get(n) { return n % 2 }}; parity[3] }
1

M is a helper object that provides several runtime services. It can pass messages on behalf of other objects and quote strings.

Eventual send syntax expands to calls to M:

>>> m`target<-verb(args)`.expand()
m`M.send(target, "verb", _makeList.run(args), _makeMap.fromPairs(_makeList.run()))`

>>> m`target<-verb(args, "name" := namedArg)`.expand()
m`M.send(target, "verb", _makeList.run(args), _makeMap.fromPairs(_makeList.run()))`