proc newPE[T](pCode: static[PatCode]; index: Natural; pNext: ref PE; val: T): ref PE =
new(result)
result[] = PE(pCode: pCode, index: index, pNext: pNext)
when pCode in pcAlt..pcArbnoX:
result.alt = val
when pCode == pcRpat:
result.patRef = val
.
.
.
This works fine but it would be more elegant and consistent with the run-time pattern code uses to use a case statement. Is there a form of case which evaluates at compile-time in the same manner as when?
macro compile_time(e: untyped): stmt =
# Homework for the reader
compile_time case i
of 213:
echo "1"
of 21: echo "2"
of 2: echo "3"
else: echo "4"
Isn't it just a macro away? ;) (c) AraqI think right now when ... elif ... else ... works reasonably well as an approximation. The main short-coming is that you can't do exhaustiveness checks; other than that, a separate compile-time case statement doesn't really buy you anything.
But if you want to try it, here's a very simple example of a macro (only works for one alternative per branch and only does very basic checking of the underlying case statement).
import macros
macro ccase(caseStmt: untyped): untyped =
expectKind caseStmt, nnkCaseStmt
let tmp = genSym(nskConst)
let caseexpr = caseStmt[0]
result = quote do:
const `tmp` = `caseexpr`
result.add(newNimNode(nnkWhenStmt))
for i in 1..len(caseStmt)-1:
if caseStmt[i].kind == nnkOfBranch:
result[1].add(newTree(nnkElifBranch,
newTree(nnkInfix, newIdentNode(!"=="), tmp, caseStmt[i][0]),
caseStmt[i][1]))
else:
result[1].add(newTree(nnkElse, caseStmt[i][0]))
const i = 0
ccase case i
of 1: discard
of 2: echo "foo"
else: echo "bar"
Using when...elif...else is OK (although I wasn't expecting elif to work, I tried elwhen, else when etc. before using lots of separate when statements) but it is not consistent with other parts of the code in which a case statement is used for equivalent run-time selection. Basically, I have to write and maintain two types of key-selection code in parsing-type modules; one for run-time selection and a different one for compile-time: this is harder to write and harder to maintain.
Does the compiler/VM support the case statement directly? If so wouldn't it also be more efficient if a compile-time case were used rather than when...elif...else for large numbers of options? assuming that the case is implemented as a perfect hash-table or equivalent. Maybe there wouldn't be much point to this as the time to create and maintain the perfect hash mechanism in the compiler/VM would be greater than just using when...elif...else in which case the macro approach would be fine and I could invest some time to complete it.