Differences From Artifact [b31646ec7576a8a6]:
- File
sample/macro.pmy
- 2010-11-24 12:14:00 - part of checkin [3ae09b8cbf] on branch trunk - changed if-then-else syntax (user: kinaba) [annotate]
To Artifact [996468a22f9d9a8e]:
- File
sample/macro.pmy
- 2010-11-25 03:32:41 - part of checkin [474c4facf0] on branch trunk - Introduced makefile to build documents. sample/macro.pmy is fully reformed. print(x) now returns x, not 0. (user: kinaba) [annotate]
1 -@macro twice = fun(x) { x; x };
2 -@macro max(x,y) {
3 - var _x = x; # no hygenic macro btw....
4 - var _y = y; # no hygenic macro btw....
5 - if(_x<_y)then _y else _x
6 -};
7 -def maxNormal(x,y) {
8 - if(x<y)
9 - then: y
10 - else: x
11 -};
1 +########################################
2 +print("----------");
3 +
4 +@macro twice = fun(x) { x; x }; # Hello Hello
5 +twice( print("Hello") );
6 +
7 +########################################
8 +print("----------");
9 +
12 10 @macro maxBad(x,y) {
13 - if x<y: y else: x
11 + if x<y then y else x
12 +};
13 +@macro maxGood(x,y) {
14 + var _x = x; # NOTE: no hygenic macro
15 + var _y = y;
16 + if _x < _y then _y else _x
14 17 };
15 -
16 -@macro LetItBe(x, y) { let it = x in y };
17 -
18 -@macro pow10(x) {
19 - @value(
20 - def pow(y, n) {
21 - if( n == 1 ) then y
22 - else
23 - @macro( @value(y) * @value(pow(y,n-1)) )
24 - }
25 - in
26 - pow(@macro(x+1),10)
27 - )
18 +def maxFun(x,y) {
19 + if x<y then y else x
28 20 };
21 +@macro maxGreat(x,y){@value(
22 + var nx = gensym(); # generate fresh symbol
23 + var ny = gensym();
24 + @macro _x = @macro(nx) {name: nx}; # cheating to create {is:"Var" .. }
25 + @macro _y = @macro(ny) {name: ny}; # at macro layer
26 + {is: "Let", name: nx, layer: "", init: @macro(x), expr:
27 + {is: "Let", name: ny, layer: "", init: @macro(y), expr:
28 + @macro(if _x < _y then _y else _x)}} # the expression
29 +)};
29 30
30 -@macro pow10Hard(x) {
31 - @value(
32 - def pow(x, n) {
33 - if( n == 1 ) then x
34 - else
35 - @macro( @value(x) * @value(pow(x,n-1)) )
36 - }
37 - in
38 - pow(@macro(x+1),10)
39 - )
31 +print( maxGood(print(1), print(2)) ); # 1 2 2
32 +print( maxBad(print(1), print(2)) ); # 1 2 2 2
33 +print( maxFun(print(1), print(2)) ); # 1 2 2
34 +print( maxGreat(print(1), print(2)) ); # 1 2 2
35 +print( maxGreat(print(2), print(1)) ); # 2 1 2
36 +
37 +########################################
38 +print("----------");
39 +
40 +# the variable "it" is inserted to the scope
41 +@macro LetItBe(x, y) { let it = x in y };
42 +print( LetItBe("myself", "when I find " ~ it ~ " in times of trouble") );
43 +
44 +########################################
45 +print("----------");
46 +
47 +# layerd parameter can also be used for @macro
48 +# you can mix @macro and normal parameters!!
49 +def 3way(n, c1 @macro, c2 @macro, c3 @macro)
50 +{
51 + case n*n
52 + when 0: c1
53 + when 1: c2
54 + when 4: c3
40 55 };
41 56
42 -def printAndReturn(x)
43 -{
44 - print(x);
45 - x
46 -};
57 +3way( rand(3), print("One"), print("Two"), print("Three") );
58 +3way( rand(3), print("One"), print("Two"), print("Three") );
59 +3way( rand(3), print("One"), print("Two"), print("Three") );
60 +
61 +########################################
62 +print("----------");
63 +
64 +# Conversely, we can mix @value parameter in the macro definition
65 +@macro times(n @value, e) { @value(
66 + if n == 1 then
67 + @macro(e)
68 + else
69 + @macro(e; times(n-1,e))
70 +)};
71 +times(7, print("Ichimen no Nanohana"));
72 +
73 +# Here, n is bound to the integer 7, not the AST of it.
74 +
75 +########################################
76 +print("----------");
77 +
78 +# Explicit manipulation of AST.
79 +# Reverse the order of arguments of the function call expression
80 +@macro reverseArgs(e) {@value(
81 + def rev(xs, acc) {
82 + case xs when {car:x, cdr:xs}: rev(xs, {car:x, cdr:acc}) when {}: acc
83 + };
84 + case @macro(e)
85 + when {is:"App", fun:f, args:as}: {is:"App", fun:f, args:rev(as,{})}
86 + when e : e
87 +)};
88 +print( reverseArgs(1+2) ); # 2+1 == 3
89 +print( reverseArgs(1-2) ); # 2-1 == 1
90 +
91 +########################################
92 +print("----------");
93 +
94 +# Both prints "original". Macro respects the neutral layer's "let y="
95 +# and "fun(y)". It does not alter the inner scope y
96 +@macro test1(y) { fun(y){y}("original") };
97 +@macro test2(y) { let y = "original" in y };
98 +print( test1("replaced?") );
99 +print( test2("replaced?") );
100 +
101 +########################################
102 +print("----------");
103 +
104 +# Macro expansion is done only at the first call.
105 +# So by using @macro parameter, it can remember the argument
106 +# of the first call.
107 +def remember1( x @macro, y ) { if x == y then "yes" else "no" };
108 +print( remember1(1, 1) ); # yes 1 == 1
109 +print( remember1(2,1) ); # yes "1" == 1
110 +print( remember1(2,2) ); # no "1" != 2
111 +
112 +# exactly the same function, but called in different order
113 +def remember2( x @macro, y ) { if x == y then "yes" else "no" };
114 +print( remember2(2, 2) ); # yes "2" == 2
115 +print( remember2(2, 1) ); # no "2" != 1
116 +print( remember2(1, 1) ); # no "2" != 1
117 +
118 +# Is this a good thing or a bad thing??
47 119
48 -def main()
49 -{
50 - twice( print("foo") );
51 - print("--------------");
52 - print(max(printAndReturn(100),printAndReturn(200)));
53 - print("--------------");
54 - print(maxNormal(printAndReturn(100),printAndReturn(200)));
55 - print("--------------");
56 - print(maxBad(printAndReturn(100),printAndReturn(200)));
57 - print("--------------");
58 - print( LetItBe( 1+2+3, it*it ) );
59 - print("--------------");
60 - print(pow10(1));
61 - print(pow10(2));
62 - print("--------------");
63 - print(pow10Hard(1));
64 - print(pow10Hard(2));
65 -};
120 +########################################
121 +print("----------");
66 122
67 -main();
123 +# Trick to extract the AST of a function
124 +def foo(x) { x + x };
125 +print( @macro(@value(foo)(arg1)) ); # prints AST for "arg1 + arg1"
68 126
69 -@macro foo(y)
70 -{
71 - fun(y){y}(300)
72 -# let y = 300 in y
73 -};
74 -
75 -print("--------------");
76 -print(foo(200));
127 +# If we wrote @macro(foo(arg1)), it is the AST of "foo(arg1)"
128 +# Here, by @value(foo) we obtain the "usual" behavior of foo,
129 +# not the macro-like bahavior to construct AST "foo(??)".
130 +# But still, by @macro( ... ) layer, the "usual" function is run in
131 +# macro mode.