Misty Programming Language:

Operators

Expression

expression paren_expression suffix literal suffix name suffix '@' suffix

open_expression paren_expression open_suffix literal open_suffix name open_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 intrinsic functions instead.

Parentheses can be used to explicitly control the order of evaluation of expressions.

Parenthesized Expressions

paren_expression '(' paren_filler ')'

paren_filler expression indent open_expression optional_ternary outdent

optional_ternary "" ternary

ternary linebreak "then" space expression linebreak "else" space 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 disrupts. Expressions that are indented within parens may contain line breaks before an infix operator.

Suffix Operators

suffix "" selection suffix subscript suffix invocation suffix space infix_operator space expression

open_suffix "" selection open_suffix subscript open_suffix invocation open_suffix separation infix_operator space open_expression

separation space linebreak

Refinement

.period

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

[ ]brackets

subscript '[' subscript_filler ']'

subscript_filler "" expression indent open_expression outdent

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 disrupts 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 disrupts.

stooge["first_name"][4]    # "y"
null["foo"]                # null
"foo"[0]                   # "f"
"foo"[3]                   # 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

Function Invocation

( )parens

invocation argument_list record_literal

argument_list '(' arguments ')'

arguments "" expression closed_arguments indent open_expression arguments_or_ternary outdent

closed_arguments "" ',' space expression closed_arguments

arguments_or_ternary ternary open_arguments

open_arguments "" open_expression open_arguments

Invocation. The () suffix operator invokes a function value.

function_value(arguments)

If the value is not function, it disrupts.

If a function is invoked with too few arguments, the missing arguments are null. If a function is invoked with excess arguments, the excess arguments are evaluated and then ignored.

A function invocation can pass at most 4 arguments. If you need more, consider passing a single record literal instead.

If a function is used only for its side effects, use the call statement.

{ }braces

A record literal can be used instead of an argument list. The record is passed as the only arguments. So

my_function{x: left, y: top, width: right - left, height: bottom - top, color: "black"}

does the same thing as

my_function({x: left, y: top, width: right - left, height: bottom - top, color: "black"})

Infix Operators

infix_operator '*' '/' '÷' '+' '-' '~' '≈' '=' '<>' '<' '<=' '>' '>=' '/' optional_backslash '\' '/' '|'

optional_backslash "" '\'

Multiplicative Operators

*asterisk

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

/solidus

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

÷obelus

Integer division.

3 ÷ 4     # 0
5 ÷ 4     # 1
16 ÷ 4    # 4
0 ÷ 0     # 0
0 ÷ null  # 0
3 ÷ 0     # null

Additive Operators

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

Concatenation Operators

~tilde

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 disrupts.

3 ~ 4                          # "34"
"beginning" ~ "and" ~ "end"    # "beginningandend"
"" ~ "ok"                      # "ok"
null ~ "ok"                    # disrupt
"" ~ null                      # disrupt

double tilde

Concatenation with a space. If the two operands are not texts after number conversion, then it disrupts. 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"                      # disrupt
"" ≈ null                        # disrupt
"brillig" ≈ ""                   # "brillig"

Relational Operators

The relational operators compare two values and return either true or false.

The =equal and <>not equal operators can take values of all types. Objects are equal only if they are the same object. Texts containing the same characters in the same order are equal.

The <less than<=less than or equal >greater than >=greater than or equal operators only work on a pair of numbers or a pair of texts. In all other cases they disrupt.

=

Equal. If the operands are the same then the result is true.

Examples:

if variable = "cat"               # compute result if the variable is "cat"
    set result: 10 = "10"         # result is false
fi

<>

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.

Logical Operators

/\

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 disrupt. If the left operand is not false or true, then it disrupts.

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 disrupts. If the left operand is false and the right operand is not a logical, then it disrupts.

3 < 4 \/ 6 < 5    # true

Default Operator

|

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

Operator Precedence

Operator Precedence
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"