Overview
SHA1 Hash: | ba11f1d551d70b17cbae9814e1e0057e558e972c |
---|---|
Date: | 2010-11-24 03:28:47 |
User: | kinaba |
Comment: | fixed the macro scoping rules concerning non-macro let |
Timelines: | family | ancestors | descendants | both | trunk |
Downloads: | Tarball | ZIP archive |
Other Links: | files | file ages | manifest |
Tags And Properties
- branch=trunk inherited from [f65680e1d2]
- sym-trunk inherited from [f65680e1d2]
Changes
Modified polemy/eval.d from [a7c677ad83621b47] to [cd1c3d2598ac30ce].
20 public: 20 public: 21 /// Initialize evaluator with empty context 21 /// Initialize evaluator with empty context 22 this() { theContext = new Table; } 22 this() { theContext = new Table; } 23 23 24 /// Evaluate the AST 24 /// Evaluate the AST 25 Value evalAST(AST e) 25 Value evalAST(AST e) 26 { 26 { 27 return eval(e, ValueLayer, theContext, OverwriteCtx); | 27 return macroAndEval(e, ValueLayer, theContext, OverwriteCtx)[0]; 28 } 28 } 29 29 30 /// Evaluate the string 30 /// Evaluate the string 31 Value evalString(S,T...)(S str, T fn_ln_cn) 31 Value evalString(S,T...)(S str, T fn_ln_cn) 32 { 32 { 33 return evalAST(parseString(str,fn_ln_cn)); 33 return evalAST(parseString(str,fn_ln_cn)); 34 } 34 } ................................................................................................................................................................................ 45 return theContext; 45 return theContext; 46 } 46 } 47 47 48 private: 48 private: 49 Table theContext; 49 Table theContext; 50 50 51 enum : bool { CascadeCtx=false, OverwriteCtx=true }; 51 enum : bool { CascadeCtx=false, OverwriteCtx=true }; > 52 52 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 53 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 53 { 54 { 54 // dynamic-overload-resolution-pattern: modify here 55 // dynamic-overload-resolution-pattern: modify here 55 enum funName = "eval"; 56 enum funName = "eval"; 56 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 57 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 57 58 58 // dynamic-overload-resolution-pattern: dispatch 59 // dynamic-overload-resolution-pattern: dispatch ................................................................................................................................................................................ 65 66 66 // dynamic-overload-resolution-pattern: default behavior 67 // dynamic-overload-resolution-pattern: default behavior 67 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not 68 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not 68 } 69 } 69 70 70 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 71 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 71 { 72 { 72 if( isMacroishLayer(lay) ) | 73 if( isASTLayer(lay) ) 73 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 74 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 74 if( lay==ValueLayer ) 75 if( lay==ValueLayer ) 75 return new StrValue(e.data); 76 return new StrValue(e.data); 76 return lift(new StrValue(e.data), lay, ctx, e.pos); 77 return lift(new StrValue(e.data), lay, ctx, e.pos); 77 } 78 } 78 79 79 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 80 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 80 { 81 { 81 if( isMacroishLayer(lay) ) | 82 if( isASTLayer(lay) ) 82 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 83 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 83 if( lay==ValueLayer ) 84 if( lay==ValueLayer ) 84 return new IntValue(e.data); 85 return new IntValue(e.data); 85 return lift(new IntValue(e.data), lay, ctx, e.pos); 86 return lift(new IntValue(e.data), lay, ctx, e.pos); 86 } 87 } 87 88 88 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 89 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 89 { 90 { 90 if( isMacroishLayer(lay) ) | 91 if( isASTLayer(lay) ) 91 if( ctx.has(e.name,MacroLayer) ) | 92 if( isMacroLayer(lay) && ctx.has(e.name,MacroLayer) ) 92 return ctx.get(e.name, MacroLayer, e.pos); 93 return ctx.get(e.name, MacroLayer, e.pos); 93 else 94 else 94 return ast2table(e, (AST e){return eval(e,lay,ct 95 return ast2table(e, (AST e){return eval(e,lay,ct 95 if( lay==ValueLayer || ctx.has(e.name, lay) ) 96 if( lay==ValueLayer || ctx.has(e.name, lay) ) 96 return ctx.get(e.name, lay, e.pos); 97 return ctx.get(e.name, lay, e.pos); 97 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 98 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 98 } 99 } 99 100 100 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 101 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 101 { 102 { 102 Value f = eval( e.fun, lay, ctx ); 103 Value f = eval( e.fun, lay, ctx ); 103 if( isMacroishLayer(lay) ) | 104 if( isASTLayer(lay) ) { 104 if( auto ff = cast(FunValue)f ) | 105 auto ff = cast(FunValue)f; > 106 if( ff !is null && isMacroLayer(lay) ) 105 return invokeFunction(ff, e.args, MacroLayer, ct | 107 return invokeFunction(ff, e.args, lay, ctx, e.po 106 else 108 else 107 return ast2table(e, (AST e){return eval(e,lay,ct 109 return ast2table(e, (AST e){return eval(e,lay,ct > 110 } 108 return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossi 111 return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossi 109 } 112 } 110 113 111 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 114 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 112 { 115 { 113 if( isMacroishLayer(lay) ) | 116 if( isASTLayer(lay) ) > 117 { > 118 // need this for correct scoping (outer scope macro vari > 119 Table newCtx = new Table(ctx, Table.Kind.NotPropagateSet > 120 foreach(p; e.params) > 121 newCtx.set(p.name, ValueLayer, new UndefinedValu 114 return ast2table(e, (AST e){return eval(e,lay,ctx);}); | 122 return ast2table(e, (AST e){return eval(e,lay,newCtx);}) > 123 } 115 else 124 else 116 return createNewFunction(e, ctx); 125 return createNewFunction(e, ctx); 117 } 126 } 118 127 119 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 128 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 120 { 129 { 121 if( isNoLayerChangeLayer(lay) ) 130 if( isNoLayerChangeLayer(lay) ) ................................................................................................................................................................................ 122 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 131 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 123 else 132 else 124 return eval(e.expr, e.layer, ctx); 133 return eval(e.expr, e.layer, ctx); 125 } 134 } 126 135 127 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 136 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 128 { 137 { 129 // todo @macro let | 138 Table newCtx = overwriteCtx ? ctx : new Table(ctx, Table.Kind.No 130 if( isMacroishLayer(lay) ) | 139 if( isASTLayer(lay) ) 131 return ast2table(e, (AST e){return eval(e,lay,ctx);}); | 140 return ast2table(e, (AST ee){ > 141 if(ee is e.expr) // need this for correct scopin > 142 newCtx.set(e.name, ValueLayer, new Undef > 143 return eval(ee,lay,newCtx); > 144 }); 132 else 145 else 133 { 146 { > 147 Value ri = eval(e.init, lay, newCtx); > 148 newCtx.set(e.name, e.layer.empty ? lay : e.layer, ri); > 149 return eval(e.expr, lay, newCtx, OverwriteCtx); > 150 } > 151 } > 152 > 153 private: > 154 // little little bit incremental macro defining version. > 155 // enables @macro foo(x)=... in ... foo ..., only at the top level of th > 156 // interpreter and functions. better than nothing :P > 157 Tuple!(Value,AST) macroAndEval( AST e_, Layer lay, Table ctx, bool overw > 158 { > 159 assert( !isASTLayer(lay) ); > 160 > 161 AST decodeAST(Value v, LexPosition pos) > 162 { > 163 // [TODO] more informative error message > 164 return polemy2d!(AST)(v, pos); > 165 } > 166 > 167 if(auto e = cast(Let)e_) > 168 { > 169 AST ai = decodeAST(eval(e.init, RawMacroLayer, ctx), e > 170 Value vi = eval(ai, lay, ctx); > 171 134 if( !overwriteCtx ) 172 if( !overwriteCtx ) 135 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 173 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 136 Value ri = eval(e.init, lay, ctx); < 137 string theLayer = e.layer.empty ? lay : e.layer; // neut | 174 string theLayer = e.layer.empty ? lay : e.layer; 138 ctx.set(e.name, theLayer, ri); | 175 ctx.set(e.name, theLayer, vi); > 176 139 return eval(e.expr, lay, ctx, OverwriteCtx); | 177 auto ave = macroAndEval( e.expr, lay, ctx, OverwriteCtx > 178 AST a = new Let(e.pos, e.name, e.layer, ai, ave[1]); > 179 return tuple(ave[0], a); > 180 } > 181 else > 182 { > 183 AST a = decodeAST(eval(e_, RawMacroLayer, ctx), e_.pos > 184 Value v = eval(a, lay, ctx); > 185 return tuple(v, a); 140 } 186 } 141 } 187 } 142 188 143 private: 189 private: 144 string getNameIfPossible(AST e) 190 string getNameIfPossible(AST e) 145 { 191 { 146 if(auto v = cast(Var)e) 192 if(auto v = cast(Var)e) ................................................................................................................................................................................ 151 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi 197 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi 152 { 198 { 153 if(auto f = cast(FunValue)_f) 199 if(auto f = cast(FunValue)_f) 154 { 200 { 155 Table newCtx = new Table(f.definitionContext(), Table.Ki 201 Table newCtx = new Table(f.definitionContext(), Table.Ki 156 foreach(i,p; f.params()) 202 foreach(i,p; f.params()) 157 if( p.layers.empty ) 203 if( p.layers.empty ) 158 newCtx.set(p.name, (lay==RawMacroLayer ? | 204 newCtx.set(p.name, isMacroLayer(lay)?Mac 159 else 205 else 160 foreach(argLay; p.layers) 206 foreach(argLay; p.layers) 161 newCtx.set(p.name, argLay, eval( 207 newCtx.set(p.name, argLay, eval( 162 scope _ = new PushCallStack(pos, callstackmsg); 208 scope _ = new PushCallStack(pos, callstackmsg); 163 return f.invoke(lay==RawMacroLayer ? MacroLayer : lay, n | 209 return f.invoke(isMacroLayer(lay)?MacroLayer:lay, newCtx 164 } 210 } 165 throw genex!RuntimeException(pos, text("tried to call non-functi 211 throw genex!RuntimeException(pos, text("tried to call non-functi 166 } 212 } 167 213 168 Value lift(Value v, Layer lay, Table ctx, LexPosition pos) 214 Value lift(Value v, Layer lay, Table ctx, LexPosition pos) 169 { 215 { 170 assert( !isMacroishLayer(lay), "lift to the @macro layer should | 216 assert( !isASTLayer(lay), "lift to the @macro layer should never 171 217 172 // functions are automatically lifterd 218 // functions are automatically lifterd 173 if( cast(FunValue) v ) 219 if( cast(FunValue) v ) 174 return v; 220 return v; 175 221 176 if( !ctx.has(lay, SystemLayer) ) 222 if( !ctx.has(lay, SystemLayer) ) 177 throw genex!RuntimeException(pos, "lift function for "~l 223 throw genex!RuntimeException(pos, "lift function for "~l ................................................................................................................................................................................ 229 return this.defCtx.opCmp(rhs.defCtx); 275 return this.defCtx.opCmp(rhs.defCtx); 230 } 276 } 231 assert(false, sprintf!"Cannot compare %s with %s 277 assert(false, sprintf!"Cannot compare %s with %s 232 } 278 } 233 279 234 override Value invoke(Layer lay, Table ctx, LexPosition 280 override Value invoke(Layer lay, Table ctx, LexPosition 235 { 281 { 236 if( lay == MacroLayer ) | 282 if( isASTLayer(lay) ) 237 return eval(ast.funbody, lay, ctx); 283 return eval(ast.funbody, lay, ctx); 238 try { < 239 if( afterMacroAST is null ) | 284 if( afterMacroAST is null ) > 285 { 240 afterMacroAST = polemy2d!(AST)(e | 286 auto va = macroAndEval(e.funbody, lay, c 241 return eval(afterMacroAST, lay, ctx); | 287 afterMacroAST = va[1]; 242 } catch( RuntimeException e ) { | 288 return va[0]; 243 throw e.pos is null ? new RuntimeExcepti < 244 } 289 } > 290 else > 291 return eval(afterMacroAST, lay, ctx); 245 } 292 } 246 293 247 AST afterMacroAST; 294 AST afterMacroAST; 248 } 295 } 249 return new UserDefinedFunValue(e,ctx); 296 return new UserDefinedFunValue(e,ctx); 250 } 297 } 251 298 ................................................................................................................................................................................ 310 } 357 } 311 unittest 358 unittest 312 { 359 { 313 auto e = new Evaluator; 360 auto e = new Evaluator; 314 enrollRuntimeLibrary(e); 361 enrollRuntimeLibrary(e); 315 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); 362 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); 316 assert_eq( r, new IntValue(BigInt(21+21*21)) ); 363 assert_eq( r, new IntValue(BigInt(21+21*21)) ); 317 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21+2 | 364 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(21+21*21) ) 318 assert_nothrow( e.globalContext.get("x",ValueLayer) ); 365 assert_nothrow( e.globalContext.get("x",ValueLayer) ); 319 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); 366 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); 320 } 367 } 321 unittest 368 unittest 322 { 369 { 323 auto e = new Evaluator; 370 auto e = new Evaluator; 324 enrollRuntimeLibrary(e); 371 enrollRuntimeLibrary(e); 325 assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(Big | 372 assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(1) 326 assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new I | 373 assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new I 327 } 374 } 328 375 329 unittest 376 unittest 330 { 377 { 331 auto e = new Evaluator; 378 auto e = new Evaluator; 332 enrollRuntimeLibrary(e); 379 enrollRuntimeLibrary(e); 333 assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1) 380 assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1)
Modified polemy/layer.d from [59dc790b72d21ee0] to [bd983db748e0ad6a].
13 13 14 enum : Layer 14 enum : Layer 15 { 15 { 16 SystemLayer = "(system)", /// Predefined layer for internal data 16 SystemLayer = "(system)", /// Predefined layer for internal data 17 ValueLayer = "@value", /// Predefined layer for normal run 17 ValueLayer = "@value", /// Predefined layer for normal run 18 MacroLayer = "@macro", /// Predefined layer for macro run (@lay() 18 MacroLayer = "@macro", /// Predefined layer for macro run (@lay() 19 RawMacroLayer = "(rawmacro)", /// Predefined layer for macro run (@lay() 19 RawMacroLayer = "(rawmacro)", /// Predefined layer for macro run (@lay() > 20 AstLayer = "(ast)", /// Predefined layer for macro run (never 20 } 21 } 21 22 22 /// True if it is macro-like layer that basically generates syntax tree 23 /// True if it is macro-like layer that basically generates syntax tree 23 24 24 bool isMacroishLayer( Layer lay ) | 25 bool isASTLayer( Layer lay ) 25 { 26 { 26 return lay==MacroLayer || lay==RawMacroLayer; | 27 return lay==MacroLayer || lay==RawMacroLayer || lay==AstLayer; 27 } 28 } 28 29 29 unittest 30 unittest 30 { 31 { 31 assert( !isMacroishLayer(SystemLayer) ); | 32 assert( !isASTLayer(SystemLayer) ); 32 assert( !isMacroishLayer(ValueLayer) ); | 33 assert( !isASTLayer(ValueLayer) ); 33 assert( isMacroishLayer(MacroLayer) ); | 34 assert( isASTLayer(MacroLayer) ); 34 assert( isMacroishLayer(RawMacroLayer) ); | 35 assert( isASTLayer(RawMacroLayer) ); > 36 assert( isASTLayer(AstLayer) ); 35 } 37 } 36 38 37 /// True if in the specified layer @lay(...) has no effect and merely produces a 39 /// True if in the specified layer @lay(...) has no effect and merely produces a 38 40 39 bool isNoLayerChangeLayer( Layer lay ) 41 bool isNoLayerChangeLayer( Layer lay ) 40 { 42 { 41 return lay==RawMacroLayer; | 43 return lay==RawMacroLayer || lay==AstLayer; 42 } 44 } 43 45 44 unittest 46 unittest 45 { 47 { 46 assert( !isNoLayerChangeLayer(SystemLayer) ); 48 assert( !isNoLayerChangeLayer(SystemLayer) ); 47 assert( !isNoLayerChangeLayer(ValueLayer) ); 49 assert( !isNoLayerChangeLayer(ValueLayer) ); 48 assert( !isNoLayerChangeLayer(MacroLayer) ); 50 assert( !isNoLayerChangeLayer(MacroLayer) ); 49 assert( isNoLayerChangeLayer(RawMacroLayer) ); 51 assert( isNoLayerChangeLayer(RawMacroLayer) ); > 52 assert( isNoLayerChangeLayer(AstLayer) ); > 53 } > 54 > 55 /// True if do macro expanstion > 56 > 57 bool isMacroLayer( Layer lay ) > 58 { > 59 return lay==MacroLayer || lay==RawMacroLayer; > 60 } > 61 > 62 unittest > 63 { > 64 assert( !isMacroLayer(SystemLayer) ); > 65 assert( !isMacroLayer(ValueLayer) ); > 66 assert( isMacroLayer(MacroLayer) ); > 67 assert( isMacroLayer(RawMacroLayer) ); > 68 assert( !isMacroLayer(AstLayer) ); 50 } 69 }
Modified polemy/parse.d from [50e0836a1ece20de] to [bacc00f3f91907a9].
114 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="va 114 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="va 115 return null; // none of {@lay, let, var, def} oc 115 return null; // none of {@lay, let, var, def} oc 116 116 117 auto varpos = currentPosition(); 117 auto varpos = currentPosition(); 118 string var = eatId("after "~kwd, AllowQuoted); // name o 118 string var = eatId("after "~kwd, AllowQuoted); // name o 119 119 120 auto e = tryEat("(") 120 auto e = tryEat("(") 121 ? parseLambdaAfterOpenParen(varpos) // let var | 121 ? parseLambdaAfterOpenParen(pos) // let var ( . 122 : (eat("=", "after "~kwd), E(0)); // let var | 122 : (eat("=", "after "~kwd), E(0)); // let var = . 123 if( moreDeclarationExists() ) 123 if( moreDeclarationExists() ) 124 return new Let(pos, var, layer, e, Body()); 124 return new Let(pos, var, layer, e, Body()); 125 else 125 else 126 return new Let(pos, var, layer, e, new Var(varpo 126 return new Let(pos, var, layer, e, new Var(varpo 127 } 127 } 128 } 128 } 129 129 ................................................................................................................................................................................ 480 480 481 AST parseId() 481 AST parseId() 482 { 482 { 483 scope(exit) lex.popFront; 483 scope(exit) lex.popFront; 484 return new Str(currentPosition(), lex.front.str); 484 return new Str(currentPosition(), lex.front.str); 485 } 485 } 486 486 487 AST parseLambdaAfterOpenParen(immutable LexPosition pos) | 487 AST parseLambdaAfterOpenParen(LexPosition pos) 488 { 488 { 489 Parameter[] params; 489 Parameter[] params; 490 while( !tryEat(")") ) 490 while( !tryEat(")") ) 491 { 491 { 492 params ~= parseParam(); 492 params ~= parseParam(); 493 if( !tryEat(",") ) { 493 if( !tryEat(",") ) { 494 eat(")", "after function parameters"); 494 eat(")", "after function parameters"); ................................................................................................................................................................................ 559 } 559 } 560 560 561 AST doNothingExpression() 561 AST doNothingExpression() 562 { 562 { 563 return new Str(currentPosition(), "(empty function body)"); 563 return new Str(currentPosition(), "(empty function body)"); 564 } 564 } 565 565 566 immutable(LexPosition) currentPosition() | 566 LexPosition currentPosition() 567 { 567 { 568 return lex.empty ? null : lex.front.pos; 568 return lex.empty ? null : lex.front.pos; 569 } 569 } 570 } 570 } 571 571 572 unittest 572 unittest 573 { 573 {
Modified polemy/valueconv.d from [2816a291e16d0986] to [94ac916389440918].
62 { 62 { 63 if(auto t = cast(Table)_v) 63 if(auto t = cast(Table)_v) 64 { 64 { 65 LexPosition pos = extractPos(t); 65 LexPosition pos = extractPos(t); 66 66 67 StrValue typ = cast(StrValue) t.access!StrValue(ValueLay 67 StrValue typ = cast(StrValue) t.access!StrValue(ValueLay 68 if( typ is null ) 68 if( typ is null ) 69 throw genex!RuntimeException(text(`Invalid AST ( | 69 throw genex!RuntimeException(callpos, text(`Inva 70 70 71 foreach(AT; ListOfASTTypes) 71 foreach(AT; ListOfASTTypes) 72 if(typ.data == typeid(AT).name.split(".")[$-1].t 72 if(typ.data == typeid(AT).name.split(".")[$-1].t 73 { 73 { 74 typeof(AT.tupleof) mems; 74 typeof(AT.tupleof) mems; 75 foreach(i,m; mems) 75 foreach(i,m; mems) 76 { 76 {
Modified sample/macro.pmy from [274d10aca22ce25f] to [977cd2f997805f91].
1 @macro twice(x) { x; x }; | 1 @macro twice = fun(x) { x; x }; 2 @macro max(x,y) { 2 @macro max(x,y) { 3 var _x = x; # no hygenic macro btw.... 3 var _x = x; # no hygenic macro btw.... 4 var _y = y; # no hygenic macro btw.... 4 var _y = y; # no hygenic macro btw.... 5 if(_x<_y){_y}else{_x} 5 if(_x<_y){_y}else{_x} 6 }; 6 }; 7 def maxNormal(x,y) { 7 def maxNormal(x,y) { 8 if(x<y){y}else{x} 8 if(x<y){y}else{x} ................................................................................................................................................................................ 11 if(x<y){y}else{x} 11 if(x<y){y}else{x} 12 }; 12 }; 13 13 14 @macro LetItBe(x, y) { let it = x in y }; 14 @macro LetItBe(x, y) { let it = x in y }; 15 15 16 @macro pow10(x) { 16 @macro pow10(x) { 17 @value( 17 @value( > 18 def pow(y, n) { > 19 if( n == 1 ) { y } > 20 else { > 21 @macro( @value(y) * @value(pow(y,n-1)) ) > 22 } > 23 } > 24 in > 25 pow(@macro(x+1),10) > 26 ) > 27 }; > 28 > 29 @macro pow10Hard(x) { > 30 @value( 18 def pow(x, n) { 31 def pow(x, n) { 19 if( n == 1 ) { x } 32 if( n == 1 ) { x } 20 else { 33 else { 21 @macro( @value(x) * @value(pow(x,n-1)) ) 34 @macro( @value(x) * @value(pow(x,n-1)) ) 22 } 35 } 23 } 36 } 24 in 37 in 25 pow(@macro(x),10) | 38 pow(@macro(x+1),10) 26 ) 39 ) 27 }; 40 }; 28 41 29 def printAndReturn(x) 42 def printAndReturn(x) 30 { 43 { 31 print(x); 44 print(x); 32 x 45 x 33 }; 46 }; 34 < 35 < 36 < 37 < 38 47 39 def main() 48 def main() 40 { 49 { 41 twice( print("foo") ); 50 twice( print("foo") ); 42 print("--------------"); 51 print("--------------"); 43 print(max(printAndReturn(100),printAndReturn(200))); 52 print(max(printAndReturn(100),printAndReturn(200))); 44 print("--------------"); 53 print("--------------"); 45 print(maxNormal(printAndReturn(100),printAndReturn(200))); 54 print(maxNormal(printAndReturn(100),printAndReturn(200))); 46 print("--------------"); 55 print("--------------"); 47 print(maxBad(printAndReturn(100),printAndReturn(200))); 56 print(maxBad(printAndReturn(100),printAndReturn(200))); 48 print("--------------"); 57 print("--------------"); 49 print( LetItBe( 1+2+3, it*it ) ); 58 print( LetItBe( 1+2+3, it*it ) ); 50 print("--------------"); 59 print("--------------"); > 60 print(pow10(1)); 51 print(pow10(2)); 61 print(pow10(2)); > 62 print("--------------"); > 63 print(pow10Hard(1)); > 64 print(pow10Hard(2)); > 65 }; > 66 > 67 main(); > 68 > 69 @macro foo(y) > 70 { > 71 fun(y){y}(300) > 72 # let y = 300 in y 52 }; 73 }; 53 74 54 main() | 75 print("--------------"); > 76 print(foo(200));