If Syntax - Spicery/Nutmeg GitHub Wiki
Overview
if
is the first word of a conditional expression and must be matched by a corresponding end
or endif
. For example:
if tough(steak) then
fry(steak)
else
grill(steak)
endif
When this code is executed, the Nutmeg runner first executes the
condition (i.e. tough(steak)
). If this evaluates to false
then
grill(steak)
is executed, otherwise fry(steak)
is executed. The full
syntax of allowable conditional commands is quite complex. An if
statement has the form:
if CONDITION then
CONSEQUENT
elseif CONDITION then
CONSEQUENT
...
[any number of additional elseif ... then ... clauses]
...
else
CONSEQUENT
endif
The else CONSEQUENT
can be omitted if desired. The
elseif CONDITION then CONSEQUENT
can be either omitted or repeated as many
times as required. A CONDITION
is any expression, and a CONSEQUENT
is any sequence of Nutmeg statements.
The condition should, when executed, produce a result. If the result is
false
, then the corresponding consequent is ignored, and the program
moves on to the next elseif
, or if there isn't one, to the else
clause. If there is no elseif
or else
, then the program moves on to
the code following the endif
.
If the result of executing a condition is anything other than true
or
false
, then an error is raised.
if
statements can be nested inside one another, i.e. a CONDITION
or a
CONSEQUENT
of an if
statement may itself contain if
statements.
For example:
if isnumber(n) then
if n > 0 then
'positive'
else
'less than or equal to zero'
endif
endif
It is permissible, but unusual, for a CONSEQUENT
to contain no code at
all, but this must be flagged with an explicit pass
or ()
def prlist( list );
if list.isEmpty then
pass
else
println( head(list) )
prlist( tail(list) )
endif
enddef
Reversing the test - ifnot
Sometimes it is more natural to reorder the if-statement so the false
condition is dealt with first. Nutmeg provides the ifnot
variant, which is equivalent to negating the whole condition with not
. The syntax is identical to that of a normal if
except that it starts with the ifnot
keyword and finishes with end
or endifnot
.
ifnot tough(steak) then grill else fry endifnot( steak )
And that's equivalent to:
if not(tough(steak)) then grill else fry endif( steak )
Why provide this version, given that it's not even any shorter? The primary motivation is making the language self-consistent. Everywhere in the language where there is a condition, Nutmeg always provides both positive and negative versions e.g. while/whilenot, return if/ifnot. And this consistency makes the language easier to remember. Another, lesser motivation is to reduce the number of parentheses.
As a good example of this, there is also an alternative form of elseifnot
, which is equivalent to elseif
with the whole condition negated.
EBNF Grammar
IfExpression ::=
'if' IfCore ('endif'|'end') |
'ifnot' IfCore ('endifnot'|'end')
IfCore ::=
Expression ('then'|':') Statements
( ('elseif'|'elseifnot') Expression ('then'|':') Statements )* ('else' ':'? Statements)?
Behaviour
An if
statement is essentially a sequence of condition-action pairs together with an optional default action. The conditions are evaluated in order and must evaluate to true or false. As soon as a condition evaluates to true the matching action is evaluated and then the statement finishes. If no conditions match then the default action, if provided, is evaluated and the statement finishes.
The Statements
of an if-statement introduce their own lexical scopes that enclose the statement and no more. This ensures that variables introduced by the statements are only in scope where their definition is guaranteed to be executed.