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 " } @" }