whileSome proc1(): proc2() none: proc3()
where proc2 is called while proc1() is true but proc3 is called if proc1() evaluates false on the first attempted iteration?
You don't need a macro.
while true:
if proc1():
proc2()
else:
proc3()
break
If the pattern is recurrent you can use template:
template myPattern(proc1, proc2, proc3: untyped): untyped =
while true:
if proc1():
proc2()
else:
proc3()
break
Thanks, but I think your solution always calls proc3. It should only be called if proc2 is never called. That's ok.
I'm trying to determine if macros can implement procedural control flow structures that have extra colon-clauses. I actually want to replace proc1() with a bool expression and proc2() and proc3() with statement sequences.
All of procs are untyped, so those don't get resolved during transformation.
You can put boolean expression in place of proc1, but afaik, you can only have statement sequences in proc3 in template.
You can add multiple statement lists to templates with do:
template test(a, b, c): untyped =
c
a
b
test:
echo "2"
do:
echo "3"
do:
echo "1"
You can do anything with macros, but in your case, you need the do notation like Hlaaftana showed and templates are enough:
proc yes(): bool = true
proc no(): bool = false
template myPattern(proc1, proc2, proc3: untyped): untyped =
var wasProc2Called = false
if proc1():
proc2
wasProc2Called = true
else:
proc3
myPattern(no): # myPattern(no)
# if yes
echo "statement 1"
echo "statement 2"
do: # If no
echo "statement 3"
echo "statement 4"
If you want the second keyword be "none" and not "do", you can use 2 templates/macros and a variable to pass state between them, like:
var whileSomeNone: bool
template whileSome*(condition: typed, body: untyped) =
whileSomeNone = condition
if whileSomeNone:
while true:
body
if not condition: break
template none*(body: untyped) =
if not whileSomeNone:
body
No check is performed here that none follows whileSome, as downside.
May be used nested:
import whilesome
var a = 3 # set to >=7 for "none" branch
var b = 7
proc c: bool =
return a < b
whileSome(c()):
echo a
inc a
var i = 0 # set to >=3 for "none" branch
whileSome(i<3):
echo "i=", i
inc i
none:
echo "i >= 3 initially!"
none:
echo "No items to display!"