Difference between revisions of "Operators"

From MiniScript Wiki
Jump to navigation Jump to search
(About chained comparison)
(→‎Comparison Operators: Added chaining of ==/!=)
 
(15 intermediate revisions by 3 users not shown)
Line 3: Line 3:
 
{| class="wikitable"
 
{| class="wikitable"
 
|-
 
|-
! Operator !! Meaning
+
! Operator !! Meaning !! Precedence
 +
|-
 +
| A <c>=</c> B || assignment || 0
 +
|-
 +
| A <c>or</c> B || logical OR: true if either operand is true || 1
 +
|-
 +
| A <c>and</c> B || logical AND: true if both operands are true || 2
 +
|-
 +
| <c>not</c> A || logical negation: true if its operand is false, and vice versa || 3
 +
|-
 +
| A <c>[[isa]]</c> B || type checking || 4
 +
|-
 +
| A <c>==</c> B || equality comparison: true if operands are equal || 5
 +
|-
 +
| A <c>!=</c> B || inequality comparison: true if operands are not equal || 5
 
|-
 
|-
| A <c>=</c> B || assignment
+
| A <c>></c> B || greater-than comparison || 5
 
|-
 
|-
| A <c>or</c> B || logical OR: true if either operand is true
+
| A <c><</c> B || less-than comparison || 5
 
|-
 
|-
| A <c>and</c> B || logical AND: true if both operands are true
+
| A <c>>=</c> B || greater-than or equal-to comparison || 5
 
|-
 
|-
| <c>not</c> A || logical negation: true if its operand is false, and vice versa
+
| A <c><=</c> B || less-than or equal-to comparison || 5
 
|-
 
|-
| A <c>[[isa]]</c> B || type checking
+
| A <c>+</c> B || addition or concatenation || 6
 
|-
 
|-
| A <c>==</c> B || equality comparison: true if operands are equal
+
| A <c>-</c> B || subtraction or string trimming || 6
 +
|-
 +
| A <c>*</c> B || multiplication or replication || 7
 
|-
 
|-
| A <c>!=</c> B || inequality comparison: true if operands are not equal
+
| A <c>/</c> B || division or reduction || 7
 
|-
 
|-
| A <c>></c> B || greater-than comparison
+
| A <c>%</c> B || modulo (remainder) || 7
 
|-
 
|-
| A <c><</c> B || less-than comparison
+
| <c>-A</c> || unary minus (numeric negation) || 8
 
|-
 
|-
| A <c>>=</c> B || greater-than or equal-to comparison
+
| <c>[[new]]</c> A || instantiation || 9
 
|-
 
|-
| A <c><=</c> B || less-than or equal-to comparison
+
| <c>@</c>A || [[@ operator|address-of]] (reference function without invoking it) || 10
 
|-
 
|-
| A <c>+</c> B || addition or concatenation
+
| A <c>^</c> B || power: A raised to the power of B || 11
 
|-
 
|-
| A <c>-</c> B || subtraction or string trimming
+
| <c>A[</c>B<c>]</c> || indexing || 12
 
|-
 
|-
| A <c>*</c> B || multiplication or replication
+
| <c>A[</c>B<c>:</c>C<c>]</c> || slicing || 12
 
|-
 
|-
| A <c>/</c> B || division or reduction
+
| <c>A(</c>B, C...<c>)</c> || [[Function#Calling_a_Function | calling a function]] || 12
 
|-
 
|-
| <c>-</c>A || unary minus (numeric negation)
+
| A<c>.</c>B || [[Dot syntax|dot operator]] || 12
 +
|}
 +
 
 +
== Chaining Operators ==
 +
 
 +
Most binary operators in MiniScript can be combined into chains, for example <c>39 + 2 + 1</c>.  The details depend on the type of operator:
 +
 
 +
=== Arithmetic Operators ===
 +
 
 +
In an expression involving a chain of arithmetic operators, the highest-precedent operators are evaluated first, as in standard algebra.  You can always use parentheses to break such a chain into smaller chunks, forcing a different evaluation order.
 +
 
 +
{| class="wikitable"
 
|-
 
|-
| <c>[[new]]</c> A || instantiation
+
! Code !! Result
 
|-
 
|-
| <c>@</c>A || address-of (reference function without invoking it)
+
| <c>2 + 5 * 8</c> || 42
 
|-
 
|-
| A <c>^</c> B || power: A raised to the power of B
+
| <c>(2 + 5) * 8</c> || 56
 
|-
 
|-
| A<c>.</c>B || [[Dot syntax|dot operator]]
+
| <c>3 ^ 2 + 4 ^ 2</c> || 25
 
|}
 
|}
  
== Chained comparison ==
+
=== Comparison Operators ===
  
Operators <c>></c>, <c><</c>, <c>>=</c> and <c><=</c> support chaining:
+
In the case of comparison operators (<c>==</c>, <c>!=</c>, <c>></c>, <c><</c>, <c>>=</c> and <c><=</c>), operands are compared in pairs from left to right.  All comparisons must be true for the complete chained expression to be considered true.  The most common use of this is to check whether a variable is in a certain range, with an expression like <c>0 < x < 10</c>, which is true only if <c>x</c> is between 0 and 10 (non-inclusive).
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Code !! Given !! Result || Read As
 +
|-
 +
| <c>0 < x < 10</c> || x = 5 || true || x is between 0 and 10
 +
|-
 +
| <c>0 < x < 10</c> || x = 10 || false || x is between 0 and 10
 +
|-
 +
| <c>0 < x <= 10</c> || x = 10 || true || x is between 0 and 10 (including 10)
 +
|-
 +
| <c>0 < x < 10 < y</c> || x = 5; y = 15 || true || x is between 0 and 10, and 10 is less than y
 +
|-
 +
| <c>0 < x == 5 < y</c> || x = 5; y = 15 || true || <c>0 < x</c> ''and'' <c>x == 5</c> ''and'' <c>5 < y</c>
 +
|}
 +
 
 +
=== Dot Operator ===
 +
 
 +
A chain of [[Dot syntax|dot operations]] is evaluated one step at a time left to right.
 +
 
 +
For example, given the code:
 +
<ms>foo.bar.baz</ms>
 +
 
 +
MiniScript proceeds in the following steps:
 +
# <c>foo.bar</c> is evaluated by looking up "bar" in <c>foo</c> (and in the event that this references a function, it's invoked with <c>[[self]]</c> bound to <c>foo</c>.
 +
# <c>.baz</c> is evaluated by looking up "baz" in the result of step 1 (which should be a map). (And if "baz" references a function, it's invoked with <c>[[self]]</c> bound to the map from step 1.)
 +
 
 +
This can continue for an arbitrarily long chain of dot operators.
 +
 
 +
== Math-assignment operators ==
 +
 
 +
In version ''1.6'' the math-assignment operators were added. They overwrite the value of the first operand variable with the result of the operation when performing the operator without assignment.
  
 
<ms>
 
<ms>
 
x = 42
 
x = 42
if 13 < x <= 100 then  // same as if (13 < x) and (x <= 100) ...
+
x += 13  // x = x + 13
print "foo"
+
print x  // 55
end if
+
 
 +
s = "hello.ms"
 +
s -= ".ms"  // s = s - ".ms"
 +
print s  // "hello"
 +
</ms>
 +
 
 +
{| class="wikitable"
 +
|-
 +
! Operator !! Meaning
 +
|-
 +
| A <c>+=</c> B || A = A + B
 +
|-
 +
| A <c>-=</c> B || A = A - B
 +
|-
 +
| A <c>*=</c> B || A = A * B
 +
|-
 +
| A <c>/=</c> B || A = A / B
 +
|-
 +
| A <c>%=</c> B || A = A % B
 +
|-
 +
| A <c>^=</c> B || A = A ^ B
 +
|}
 +
 
 +
== Tricky spaces ==
 +
 
 +
MiniScript allows an expression to be the entire statement (which is useful in [[REPL]] where it evaluates the expression and immediately prints the result).
 +
 
 +
<ms>
 +
4 + 5          // REPL prints 9
 +
 
 +
f = function(x,y)
 +
x + y      // the result is "dropped"
 +
end function
 +
f 4, 5          // prints nothing
 +
 
 
</ms>
 
</ms>
 +
 +
There are a few cases when using different spacing around operators in such expressions may make MiniScript confuse it with a function call:
 +
 +
<ms>
 +
X[Y]            // Index X with key Y
 +
X [Y]          // Call function X with argument [Y]
 +
 +
X-Y            // Subtract Y from X
 +
X- Y            // Subtract Y from X
 +
X -Y            // Call function X with argument -Y
 +
X - Y          // Subtract Y from X
 +
</ms>
 +
 +
Follow a simple convention to avoid such problems: put spaces around arithmetic operators and if possible don't use a space between an unary operator and its operand.
  
 
[[Category:Language]]
 
[[Category:Language]]

Latest revision as of 21:35, 20 November 2023

MiniScript defines the following operators (listed in order from lowest to highest precedence):

Operator Meaning Precedence
A = B assignment 0
A or B logical OR: true if either operand is true 1
A and B logical AND: true if both operands are true 2
not A logical negation: true if its operand is false, and vice versa 3
A isa B type checking 4
A == B equality comparison: true if operands are equal 5
A != B inequality comparison: true if operands are not equal 5
A > B greater-than comparison 5
A < B less-than comparison 5
A >= B greater-than or equal-to comparison 5
A <= B less-than or equal-to comparison 5
A + B addition or concatenation 6
A - B subtraction or string trimming 6
A * B multiplication or replication 7
A / B division or reduction 7
A % B modulo (remainder) 7
-A unary minus (numeric negation) 8
new A instantiation 9
@A address-of (reference function without invoking it) 10
A ^ B power: A raised to the power of B 11
A[B] indexing 12
A[B:C] slicing 12
A(B, C...) calling a function 12
A.B dot operator 12

Chaining Operators

Most binary operators in MiniScript can be combined into chains, for example 39 + 2 + 1. The details depend on the type of operator:

Arithmetic Operators

In an expression involving a chain of arithmetic operators, the highest-precedent operators are evaluated first, as in standard algebra. You can always use parentheses to break such a chain into smaller chunks, forcing a different evaluation order.

Code Result
2 + 5 * 8 42
(2 + 5) * 8 56
3 ^ 2 + 4 ^ 2 25

Comparison Operators

In the case of comparison operators (==, !=, >, <, >= and <=), operands are compared in pairs from left to right. All comparisons must be true for the complete chained expression to be considered true. The most common use of this is to check whether a variable is in a certain range, with an expression like 0 < x < 10, which is true only if x is between 0 and 10 (non-inclusive).

Code Given Result Read As
0 < x < 10 x = 5 true x is between 0 and 10
0 < x < 10 x = 10 false x is between 0 and 10
0 < x <= 10 x = 10 true x is between 0 and 10 (including 10)
0 < x < 10 < y x = 5; y = 15 true x is between 0 and 10, and 10 is less than y
0 < x == 5 < y x = 5; y = 15 true 0 < x and x == 5 and 5 < y

Dot Operator

A chain of dot operations is evaluated one step at a time left to right.

For example, given the code:

foo.bar.baz

MiniScript proceeds in the following steps:

  1. foo.bar is evaluated by looking up "bar" in foo (and in the event that this references a function, it's invoked with self bound to foo.
  2. .baz is evaluated by looking up "baz" in the result of step 1 (which should be a map). (And if "baz" references a function, it's invoked with self bound to the map from step 1.)

This can continue for an arbitrarily long chain of dot operators.

Math-assignment operators

In version 1.6 the math-assignment operators were added. They overwrite the value of the first operand variable with the result of the operation when performing the operator without assignment.

x = 42
x += 13  // x = x + 13
print x  // 55

s = "hello.ms"
s -= ".ms"  // s = s - ".ms"
print s  // "hello"
Operator Meaning
A += B A = A + B
A -= B A = A - B
A *= B A = A * B
A /= B A = A / B
A %= B A = A % B
A ^= B A = A ^ B

Tricky spaces

MiniScript allows an expression to be the entire statement (which is useful in REPL where it evaluates the expression and immediately prints the result).

4 + 5           // REPL prints 9

f = function(x,y)
	x + y       // the result is "dropped"
end function
f 4, 5          // prints nothing

There are a few cases when using different spacing around operators in such expressions may make MiniScript confuse it with a function call:

X[Y]            // Index X with key Y
X [Y]           // Call function X with argument [Y]

X-Y             // Subtract Y from X
X- Y            // Subtract Y from X
X -Y            // Call function X with argument -Y
X - Y           // Subtract Y from X

Follow a simple convention to avoid such problems: put spaces around arithmetic operators and if possible don't use a space between an unary operator and its operand.