The body of a function contains zero or more statements. This section describes the statement types.
statement
=> augment_statement
=> assignment_statement
=> break_statement
=> do_statement
=> for_statement
=> if_statement
=> invocation_statement
=> raise_statement
=> return_statement
=> while_statement
augment_statement
=> lvalue augmentation
=> self augmentation
lvalue
=> name [(subscription | invocation)*
subscription]
The augment statement is a special case of the augment expression used as a statement. It can assign many values to an object at once.
Example:
$ {
first : 'Moe'
last : 'Howard'
}
# same result as
# $.first : 'Moe'
# $.last : 'Howard'
assignment_statement
=> (lvalue ':')+ expression
=> lvalue ('+:' | '-:' | '~:'
| '~~~:') expression
=> self subscription (':' | '+:' | '-:' | '~:' | '~~~:')
expression
An assignment statement is of the form
lvalue assignment_operator expression
An lvalue is a variable name or parameter name or a dot expression
or a subscript expression. An lvalue cannot be a literal or
any other kind of expression. If the name was declared with
define then a compile time error will result.
name name.member name[subscript]
The $ operator allows a method to modify its object even
if the reference to the object is fixed. See Functions.
$.member : 2 # Change the value of the object's member property to 2. var self : $ # Capture the self reference. self.member : 3 # Throw a fix exception if the object is fixed.
The assignment operators are
: +: -: ~: ~~~:
The assignment operators cannot be used in expressions. They can only be used in assignment statements.
:Normal assignment. These can be cascaded to assign a value of an expression to multiple lvalues.
In some programming languages, this operation has been associated with
the = operator. In Misty, : is
used for assignment, and = is used exclusively for comparison.
Example:
i : 5 # i is 5 x : y : z : 0 # x is 0 and y is 0 and z is 0 a[5] : temp : [] # a[5] and temp are the same empty array
+:Increment. The lvalue is replaced by the sum of the lvalue and the value of the expression.
Example:
i : 2 i +: 1 # i is 3
-:Decrement. The lvalue is replaced by the difference of the lvalue and the value of the expression.
Example:
i : 8 i -: 2 # i is 6
~:Concatenate. The lvalue and the value of the expression
are both converted to texts (using the ~ prefix operator) and
then concatenated together, replacing the lvalue.
Example:
price : '$' price ~: 3 + 4 # price is '$7'
~~~:Concatenate with space. The lvalue and the value of the expression
are both converted to texts (using the ~ prefix operator)
and then concatenated together with a space between them, replacing the
lvalue.
Example:
price : '$' price ~~~: 3 + 4 # price is '$ 7'
break statementbreak_statement => 'break' [label]
The break statement is used to terminate loops. It can be used
with the do, for, and while statements.
It causes execution to continue with the statement following the od
that closes the loop. The break can optionally be followed by a
loop label, making it possible to break out of outer loops when loops are nested.
The loop label must match a loop that contains the break.
Example:
variable i, j
variable found : false
outer : for i to n do
for j to m do
if a[i][j] = target then
found : true
break outer
fi
od
od
define or def statementdefine_statement => ('define'
| 'def') name (':' expression
| parameter_list body)
The define statement defines a read-only variable within
the current function. The variable is read-only, but the value it contains
may be mutable. Names that are defined with the define statement
cannot be changed with the assignment operators. If the value is mutable,
then the value's members or elements can be changed with assignment operators.
The define statement cannot be used within a loop or if
statement.
The define statement can be used to define functions (see Functions).
Also see the variable statement below.
Example:
define pi : 3.1415926
define stack : []
stack.push(pi) # Push pi onto the stack.
# stack is [3.1415926] # stack has been modified
stack : [] # Illegal statement, stack cannot be replaced.
define triple(n) {
return n * 3
}
do statementdo_statement => [label ':']
loop_body
loop_body => 'do' statement+
'od'
label => name
The do statement defines a loop. Like all loop statements,
it is bracketed with od. The body of the loop can contain
one or more statements. It cannot contain a define or variable
statement. The running of the loop must be terminated explicitly with
a break, return, or raise statement.
Example:
variable a : []
do
a.push(expression())
if token.id = ')' then
break
fi
advance(',')
od
for statementfor_statement => [label ':']
'for' induction for_clause loop_body
for_clause
=> 'in' expression
=> ['from' expression] ('to' | 'thru')
expression ['by' expression]
induction => name
The for statement is like the do statement,
but provides a great deal of convenience for writing common loops. The
for statement makes use of an induction variable that changes
on each iteration of the loop. The induction variable must have been declared
as a variable in the same function as the for statement.
The induction variable cannot be assigned to within the body of the loop.
If the loop terminates early because of break, then the
induction variable will retain its value as of the time of the break.
Otherwise, after the loop completes its final interation, the induction variable
will be null. The body cannot contain a define
or variable statement.
for toThe for to statement makes it easy to step through a sequence
of numbers.
for i from f to t by b do
...
od
The sample above is equivalent to
i : f
var temp_to : t
var temp_by : b
do
if i >= temp_to then
break
fi
...
i +: temp_by
od
The from part is optional. The default is 0.
The by part is optional. The default is 1. It must
be greater than zero.
Notice that the loop will stop before the index variable reaches the to
value. The to value and by value are only computed
once, at the beginning of the loop. (This is different than the practice in
the C for statement, which can recalculate the limit and increment
on every iteration.)
Example:
variable counter
variable digits : ''
for counter to 10 do
digits ~: counter
od
# digits is '0123456789'
for thruThe for thru statement is similar to the for
to statement. The difference is in the test that breaks the loop.
for i from f thru t by b do
...
od
is equivalent to
var i : f
temp_thru : t
temp_by : b
do
if i > temp_thru then
break
fi
...
i +: temp_by
od
The from part is optional; the default is 0. The
by part is optional; the default is 1.
The index variable must be local to the current function.
Notice that the loop will stop when the index variable exceeds the thru
value.
Example:
variable counter
variable result : ''
for counter from 1 thru 10 do
result ~~~: counter
od
# result is '1 2 3 4 5 6 7 8 9 10'
result : []
for i from 0 to 10 by 3 do
result.append(i)
od
# result is [0, 3, 6, 9]
for inThe for in statement loops through the values
of an array or a function.
label : for value in collection do
...
od
If the collection is an array, it loops on the range of subscripts contained
in the array. If the collection is a function, then the function is called
once per iteration and the value it returns is assigned to the loop variable.
The loop ends when the function returns null.
If the collection is neither an array nor a function, then a 'type'
exception is raised.
It is equivalent to
if collection is array then
temp_value : null
temp_length : length collection
variable temp_counter : 0
do
if temp_counter >= temp_length then
break
fi
value : collection[temp_counter]
...
temp_counter +: 1
od
elif collection is function then
function () {
do
temp_value : collection()
if temp_value is null then
exit
fi
value : temp_value
...
od
exception e
if e = 'done' then
return
else
raise e
fi
}()
else
raise 'type'
fi
if statementif_statement => 'if' expression
consequence
('elif' expression consequence)*
['else' statement*]
'fi'
consequence
=> 'then' statement*
=> case+
case => 'case' expression
(',' expression)* 'then' statement*
The if statement allows for the conditional execution of statements.
if expression
case value1, value2 then
...matching...
else
...not matching...
fi
The case part can have one or more expressions, separated
by commas. If any of the expressions are eq (equal)
to the first expression, then the following statements are
executed. Multiple cases can be listed. If no cases match, then the else
statements are executed. The else part is optional.
Example:
if first_name
case 'Curly', 'Moe', 'Shemp' then
last_name : 'Howard'
case 'Larry' then
last_name : 'Fine'
else
last_name : '(unknown)'
fi
Unlike the switch statement in some languages, the break
statement is not needed to prevent fallthru. The break statement
is only used to break out of loops.
If there is a single case, the if can be simplified. If the first
expression is falsy (false, null, or the empty text)
then the else statements are executed. Otherwise, if the first
expression is truthy then the then statements are executed.
Example:
if d = 0 then
raise 'range'
else
return int(q / d)
fi
The else part can be replaced with an elif
part. This makes it possible to have alternatives without deeply nested
ifs.
Example:
if char list[k].op = 'j' then
list[k].yz -: 1
elif list[k].op = 'opx' then
list[k].yz -: 1
k +: 1
fi
The if statement creates forks in the control flow of a
function. An if statement cannot contain variable
and define statements.
invocation statementinvocation_statement
=> lvalue invocation
=> self subscription+ invocation (subscription*
invocation)*
The invocation statement is used to call a function or method
and discard its return value. See Functions.
raise statementraise_statement => 'raise' (text
| exception_constant)
The raise statement raises an exception, sending control
to an exception handler. The operand must be a non-empty text (the type
of the exception).
The raise statement causes control to go to the exception
part of the function. If control is already in the exception
part, or if there is no exception part, then control goes
to the most recent function in the calling chain that has an exception
part. See Functions.
return statementreturn_statement => 'return' [expression]
The return statement provides for the normal exit of a function
and the specification of its return value. If the function does not create any function objects and if the function does not have an exception handler, and if the expression is a function invocation, then the tail recursion optimization will be performed. This can have a significant performance advantage.
Example:
define double(number) {
return number * 2
}
variable or var statementvariable_statement => ('variable'
| 'var') name (':' expression)
The variable statement defines a name within the current
function. That name can be used to hold any value. If an initial value
is not specified, then the initial value is null. It differs
from the define statement in that the value can be replaced
by an assignment operator. Thevariable statement cannot be
placed within a loop or if statement.
Example:
variable total : 0 variable i variable j variable k
while statementwhile_statement => [label ':']
'while' expression loop_body
The while statement is a slightly more convenient form of
do statement. Testing at the top, the loop continues as long
as the condition is true. The body cannot contain a define
or variable statement.
label : while condition do
...
od
It is equivalent to
label : do
if not condition then
break
fi
...
od