compile/switch
Symbol: compile/switch
Syntax: (switch VALUE [COMPARE-LIST BODY...] ... [else: BODY...])
Use-case: Multi-way equality branching against one discriminant value.
VALUE is evaluated once, then each clause compares one or more candidate values
from COMPARE-LIST against VALUE in order. On first match, that clause body
is evaluated and returned. If no clause matches, else: is used when present;
otherwise the form yields None.
Behaviour: Requires at least one argument (VALUE). Compiles VALUE once
and keeps it on the stack across case checks. For each non-else clause, the
clause test must be a pair/list (COMPARE-LIST); otherwise SpecialError is
raised ("switch compare must be a list of values"). For each element of that
list, the compiler emits one compare path against VALUE:
match (
SWITCH_EQnot taken): emitsJUMP body_label, then runs the clause body onceno match (
SWITCH_EQtaken): pops only candidate value, keepsVALUE, jumps to the next candidate (or next clause after the last candidate)
Clause bodies are compiled via helper_begin. The else: clause must be last.
Entering else: pops the retained VALUE before compiling its body. After any
successful clause, control jumps to a shared done label. If no clause matches
and no else is present, the remaining VALUE is popped and None is pushed.
The head may be written as switch or compile/switch; compiler lookup resolves
switch to compile/switch.
Expected lowered shape from layout/switch:
(switch VALUE
((COND1 COND2 ...) (begin BODY...))
(else: (begin BODY...)))
This shape is valid because each clause body is still a list of forms for
helper_begin; when it contains one compile/begin form, that form performs
the sequencing.
Examples:
;; Direct s-expression form
(switch 5
[[1] "one"]
[[2] "two"]
[[5 6] "five-or-six"]
[else: "meh"])
;; -> "five-or-six"
;; No match with else
(switch 5
[[1] "one"]
[[2 3] "two-or-three"]
[else: "meh"])
;; -> "meh"
;; No match and no else
(switch 5
[[1] "one"]
[[2] "two"])
;; -> None
Also: layout handler switch.