Diff
Not logged in

Differences From Artifact [b31646ec7576a8a6]:

To Artifact [996468a22f9d9a8e]:


> 1 ######################################## > 2 print("----------"); > 3 1 @macro twice = fun(x) { x; x }; | 4 @macro twice = fun(x) { x; x }; # Hello Hello 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 | 5 twice( print("Hello") ); 6 }; < 7 def maxNormal(x,y) { < > 6 > 7 ######################################## 8 if(x<y) | 8 print("----------"); 9 then: y < 10 else: x < 11 }; < > 9 12 @macro maxBad(x,y) { 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) { < > 18 def maxFun(x,y) { 21 if( n == 1 ) then y | 19 if x<y then y else x 22 else < 23 @macro( @value(y) * @value(pow(y,n-1)) ) < 24 } < 25 in < 26 pow(@macro(x+1),10) < 27 ) < 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 print( maxGood(print(1), print(2)) ); # 1 2 2 31 @value( | 32 print( maxBad(print(1), print(2)) ); # 1 2 2 2 32 def pow(x, n) { | 33 print( maxFun(print(1), print(2)) ); # 1 2 2 33 if( n == 1 ) then x | 34 print( maxGreat(print(1), print(2)) ); # 1 2 2 34 else | 35 print( maxGreat(print(2), print(1)) ); # 2 1 2 35 @macro( @value(x) * @value(pow(x,n-1)) ) < 36 } | 36 > 37 ######################################## 37 in | 38 print("----------"); 38 pow(@macro(x+1),10) < 39 ) | 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) | 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") ); 43 { | 60 > 61 ######################################## 44 print(x); | 62 print("----------"); 45 x | 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)) 46 }; | 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 {}: > 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") ); < > 120 ######################################## 51 print("--------------"); | 121 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 }; < 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 > 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 69 @macro foo(y) | 131 # macro mode. 70 { < 71 fun(y){y}(300) < 72 # let y = 300 in y < 73 }; < 74 < 75 print("--------------"); < 76 print(foo(200)); <