Artifact Content
Not logged in

Artifact b441073a5b98679b30c73ae0f4b5e4cd5aebdf8c


     1  ########################################
     2  print("----------");
     3  
     4  @macro twice = fun(x) { x; x }; # Hello Hello
     5  twice( print("Hello") );
     6  
     7  ########################################
     8  print("----------");
     9  
    10  @macro maxBad(x,y) {
    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
    17  };
    18  def maxFun(x,y) {
    19  	if x<y then y else x
    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  )};
    30  
    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) { var it = x; 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
    55  };
    56  
    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??
   119  
   120  ########################################
   121  print("----------");
   122  
   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"
   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
   131  # macro mode.