sourcelib/Macros.xtlm

1⍝# A small macro library, an example of macros of your own (MC10). A 2⍝# macro is an ordinary function of the source text written on each 3⍝# side of its call; the text it gives replaces the call, then is read 4⍝# as code. Import it with an alias of your own, "x:" u_se< "Macros", 5⍝# and see what a program becomes with xetal expand FILE. 6 7⍝## Statements and definitions 8 9⍝# Run the statements on the right when the condition on the left 10⍝# holds; the value is @ either way (the other way round from the 11⍝# system macro u_nless<). 12⍝# >> "x:" u_se< "Macros" 13⍝# >> "1 < 2" x:w_hen< "p_rint! 7" 14⍝# 7 15⍝# @ 16ᵐw̲hen< ← { cond body → "{ @ -> (n_ot " c̲at cond c̲at ") ? @; " c̲at body c̲at "; @ } @" } 17 18⍝# Define the function named on the left (in u:) as the lambda body on 19⍝# the right, its name written as text. 20⍝# >> "x:" u_se< "Macros" 21⍝# >> "s_quare" x:d_ef< "_r * _r" 22⍝# >> u:s_quare 7 23⍝# 49 24ᵐd̲ef< ← { name body → "u:" c̲at name c̲at " := { " c̲at body c̲at " }" } 25 26⍝## Checks 27 28⍝# The line "ok: label" when the condition on the left holds, else 29⍝# "FAIL: label (cond)", the condition shown as it was written, which a 30⍝# function, given only the condition's value, cannot do. 31⍝# >> "x:" u_se< "Macros" 32⍝# >> "5 = 2 * 2" x:c_heck< "doubling" 33⍝# FAIL: doubling (5 = 2 * 2) 34ᵐc̲heck< ← { cond label → "{ @ -> (" c̲at cond c̲at ") ? \"ok: " c̲at label c̲at "\"; \"FAIL: " c̲at label c̲at " (" c̲at cond c̲at ")\" } @" } 35 36⍝## Names a macro binds 37 38⍝# Twice the expression on the right: the macro binds a local t (to 2) 39⍝# around your expression, and hygiene renames it (to g1:t, say), so a 40⍝# t of your own is still yours. 41⍝# >> "x:" u_se< "Macros" 42⍝# >> t := 5 43⍝# >> @ x:t_wice< "t + 1" 44⍝# 12 45ᵐt̲wice< ← { @ e → "{ @ -> t := 2; t * (" c̲at e c̲at ") } @" } 46 47⍝# The text on the right with it bound to the value of the expression 48⍝# on the left (an anaphoric macro: it is meant for your text, so it is 49⍝# declared below and hygiene leaves it as written). 50⍝# binds: it 51⍝# >> "x:" u_se< "Macros" 52⍝# >> "3 + 4" x:w_ith< "it * it" 53⍝# 49 54ᵐw̲ith< ← { e body → "{ @ -> it := (" c̲at e c̲at "); " c̲at body c̲at " } @" }