Diff
Not logged in

Differences From Artifact [b31646ec7576a8a6]:

To Artifact [996468a22f9d9a8e]:


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.