The switch
-expression in Minilang provides an alternative to an if
-expression with multiple elseif
branches when a single value is tested for the first match.
'switch' expression ':' expression ( 'case' expression ( ',' expression )* 'do' block )* ( 'else' block )? 'end'
For example:
fun test(X) do
if X = 1 then
"one"
elseif 2 <= X <= 3 then
"few"
elseif 4 <= X <= 7 then
"several"
else
"many"
end
end
fun test2(X) do
switch X: integer
case 1 do
"one"
case 2, 3 do
"few"
case 4 .. 7 do
"several"
else
"many"
end
end
There are a few differences, a switch
-expression needs a switch provider, in this case integer
. The provider of a switch determines how Minilang treats the switch values to find a matching branch. A switch
-expression also allows multiple values per-branch, and overall is faster than the corresponding if
-expression. Note that the values in each branch are evaluated at compile time so can't refer to local variables.
Given a switch
-expression with provider P
, the compiler uses the method compiler::switch(P, Cases...)
to implement the switch
-expression. Here Cases
is a list of lists, one list per case
containing the case values. The implementation of compiler::switch
for P
must return another function, which takes a value and return an integer index (starting at 0
) corresponding to the chosen branch.
This design allows support for new kinds of switch
-expressions to be added later, either to the language or by specific applications. Currently the following switch providers are available:
type
Case values must be types (or
nil
). A case value matches if the switch value is of the same type or a sub-type.integer
,real
Case values must be numbers or numeric ranges. A case value matches if the switch value is equal to it (for numbers) or contained in it (for ranges).
string
Case values must be strings or regular expressions. A case value matches if the switch value is equal to it (for strings) or matches it (for regular expressions).
- Any
enum
type Case values must be values of the enum type or strings corresponding to values of the enum. A case value matches if the switch value is equal to it.
- Any
flags
type Flag values must be values of the flags type, strings corresponding to values of the enum, or tuples of the previous. A case value matches if the switch value contains at least the same flags, it may have extra flags.
- Any function or macro
Any function or macro can be used as a switch provider as long as it accepts a list of lists and returns another function as described above.