expression
paren_expression suffix
literal suffix
name suffix
'@'
suffix
Expressions are made up of names and literals, fortified by infix (or binary), suffix, and ternary operators. The Misty language does not have prefix operators, using functions instead
Parentheses can be used to explicitly control the order of evaluation of expressions.
paren_expression
'('
paren_filler ')'
paren_filler expression indent expression ternary outdent
ternary
""
then_else
then_else
linebreak "then "
expression linebreak "else "
expression
Expressions can be wrapped in parentheses to clarify or alter the order of evaluation.
A parenthesized expression can also contain a short-circuiting ternary operation. If the first operand is true
, then the second operand is evaluated. If the first operand is false
, then the third operand is evaluated. If the first operand is neither true
nor false
, then it fails.
suffix
""
selection suffix
subscript suffix
invocation suffix
space infix_operator space expression
selection
'.'
name
Selection. This identifies a field in a value. It is mostly used with records.
stooge.last_name # "Howard" stooge.first_name # "Curly"
Selection is a short form of subscription. If the thing being selected is a text that is a valid identifier, then the selection is an alias.
stooge.last_name = stooge["last_name"] # true
subscript
'['
subscript_filler ']'
subscript_filler
""
indent expression outdent
expression
Subscription. The expression in the brackets selects a field of a record or an element of an array, or a character of a text.
object type | subscript type |
---|---|
record | text or stone record |
array | non-negative integer |
text | non-negative integer |
On retrieval, if the record does not contain the key, then null
will be returned. On storage, it fails if the record is immutable. On storage to a mutable array, if the key
is not a number or if the key violates the bounds of the array, or if the key is not the correct type, then it fails.
stooge["first_name"][4] # "y" null["foo"] # null
Mutable arrays can also retrieve and delete the last element of an array with the empty subscript.
def my_array: ["a", "b"] my_array[] # "b" my_array[] # "a" my_array[] # null
invocation
'('
argument_list ')'
argument_list
""
spreadable_expression closed_arguments
indent expression opener outdent
spreadable_expression expression spreadable
spreadable
""
"..."
closed_arguments
""
','
space expression spreadable closed_arguments
opener then_else spreadable open_arguments
open_arguments
""
linebreak expression spreadable open_arguments
Invocation. The ( )
suffix operator invokes a function value.
function_value
(
arguments)
If the value is not function, it fails.
If a function is invoked with too few arguments, the missing arguments are null
. If a function is invoked with too many arguments, it fails.
infix_operator
'*'
'/'
'÷'
'%'
'+'
'-'
">>>"
"<<<"
'~'
'≈'
'='
'≠'
'<'
'≤'
'>'
'≥'
"/\"
"\/"
'|'
Multiplication. If it can be determined at compile time that either operand is zero, the other operand might not be evaluated.
3 * 4 # 12 0.10 * 20 # 2 0 * null # 0
Division.
3 / 4 # 0.75 5 / 4 # 1.25 16 / 4 # 4 0 / 0 # 0 3 / 0 # null 0 / null # 0 1 / null # null null / 4 # null
Integer division.
3 ÷ 4 # 0 5 ÷ 4 # 1 16 ÷ 4 # 4 0 ÷ 0 # 0 3 ÷ 0 # null
Modulo. The result of
a
%
b
is
a
-
(b * floor(
a/
b)
)
If a is 0
, then the result is 0
. If b is 0
, or if either operand is not a number,
then the result is null
. a and b are not required to
be integers. The result will have the same sign as b.
3 % 4 # 3 13 % 4 # 1 0 % null # 0 1 % null # null null % 4 # null 1 % 0 # null 0 % 0 # 0
These operators work only for numbers. If either operand is not a number,
or if the operation creates a value that is too majestic to be contained
in a Misty number, then the result is null
.
Addition. If either operand is not a number, the result is null
.
3 + 4 # 7 3 + null # null null + 0 # null
Subtraction. If either operand is not a number, the result is null
.
3 - 4 # -1 3 - null # null
Maximum. The result is the larger of the two operands. If either operand is
not a number, the result is null
.
3 >>> 4 # 4
>>>
can be used with <<<
to constrain values
within an acceptable range.
2 >>> 3 <<< 7 # 3 4 >>> 3 <<< 7 # 4 5 >>> 3 <<< 7 # 5 1 >>> null # null null >>> 1 # null
To determine if a value lies between two other values, uses relational operators.
if 3 ≤ value ≤ 7 ... fi
Minimum. The result is the smaller of the two operands. If either operand is
not a number, the result is null
.
3 <<< 4 # 3
Concatenation. Make a new text that combines the two texts. If an operand is a number, convert it to text. If after this conversion either operand is not text, then it fails.
3 ~ 4 # "34" "beginning" ~ "and" ~ "end" # "beginningandend" "" ~ "ok" # "ok" null ~ "ok" # fail "" ~ null # fail
Concatenation with a space. If the two operands are not texts after number conversion, then it fails. Make a new text
that combines the two texts with a space between. If the first operand
is ""
, then the result is the second
operand. If the second operand is ""
,
then the result is the first operand.
3 ≈ 4 # "3 4" "beginning" ≈ "and" ≈ "end" # "beginning and end" "" ≈ "ok" # "ok" null ≈ "ok" # fail "" ≈ null # fail "brillig" ≈ "" # "brillig"
Relational operators can be strung together in useful ways, so that
a = b = c = d
has a similar result to
a = b /\ b = c /\ c = d
Equal. If the operands are the same then the result is true
.
Examples:
if a = b = null # compute result if a and b are both null let result: 10 = "10" # result is false
Not equal. If the operands are not the same, then the result is false
.
Less than.
If the operands both numbers or both texts, then if the left operand is less than
the right operand, then the result is true
. If the left operand
is greater than or equal to the right operand the result is false
.
Less than or equal.
Greater than.
Greater than or equal.
Short-circuit And. If the left operand is false
, then the result is false
and the right operand will not be evaluated.
If the left operand is true
and the right
operand is false
, then the result is false
.
If the left operand is true
and the right operand is true
, then the result is true
.
If the left operand is true
and the right operand is not false
or true
, then fail.
If the left operand is not false
or true
, then it fails.
3 < 4 /\ 5 < 6 # true
Short-circuit Or. If the left operand is true
, then the result is true
and the right operand is not evaluated.
If the left operand is false
and the right operand is false
, then the result is false
.
If the left operand is false
and the right operand is true
, then the result is true
.
If the left operand is not a logical, then it fails. If the left operand is false
and the right operand is not a logical, then it fails.
3 < 4 \/ 6 < 5 # true
Short-circuit Default. If the left operand is not null
, then the result
is the left operand. Otherwise, the result is the right operand.
var foo: null # foo is null foo | 0 # 0
highest | . [ ] ( ) |
| |
|
* / ÷ % |
|
+ - >>> <<< |
|
~ ≈ |
|
= ≠ <
> ≤ ≥
|
|
/\ \/
|
|
lowest | ( then else ) |
Operators group left to right. The selection, subscript, and invocation operators have the highest precedence (tightest). The ternary operator has the lowest precedence. Grouping can be made explicit with parens.
"$" ~ 3 + 4 // "$7"