Check-in [207cea338a]
Not logged in
Overview
SHA1 Hash:207cea338aa84a755ef4d51058390f856e70419a
Date: 2010-11-26 14:03:10
User: kinaba
Comment:changed hiding mechanizem of x in let x = ... for @macro layer. Old: set(x,ValueLayer,undefined) Nee: set(x,NoopLayer,null)
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified Makefile from [300aa94f95ae54a3] to [b49249a409a1c2fd].

1 1 .PHONY : all windows doc 2 2 3 3 DC=dmd 4 4 DC_OPT=-O -release 5 5 SRC = $(wildcard *.d polemy/*.d tricks/*.d) 6 6 7 7 8 -all: 8 + 9 +posix: 9 10 $(DC) $(DC_OPT) -ofbin/polemy $(SRC) 10 11 11 12 windows: 12 13 $(DC) $(DC_OPT) -ofbin\\polemy $(SRC) 13 14 14 15 15 16

Modified doc/index.html from [720b71facce28489] to [56b12828066b590e].

566 566 </p> 567 567 568 568 569 569 <script>explorer.outline.incSymbolLevel();</script> 570 570 <dl> 571 571 <script>explorer.outline.writeEnabled = true;</script> 572 572 <dt><span class="decl"> 573 -<span class="currsymbol">使い方</span> 574 -<script>explorer.outline.addDecl('使い方');</script> 573 +<span class="currsymbol">概要</span> 574 +<script>explorer.outline.addDecl('概要');</script> 575 + 576 +</span></dt> 577 +<script>explorer.outline.writeEnabled = false;</script> 578 + 579 + <dd><p> 580 +samples/macro.pmy にいくつか使い方サンプルが置いてありますので、詳しくはそちらをどうぞ。 581 +</p> 582 +<pre> 583 + &gt;&gt; @macro( twice(print("Hello")) ) 584 + { 585 + pos: {lineno:1, column:9, filename:<REPL>}, 586 + args: [ { pos: {lineno:1, column:15, filename:<REPL>}, 587 + args: [{pos:{lineno:1, column:21, filename:<REPL>}, 588 + is:Str, 589 + data:Hello}], 590 + is: App, 591 + fun: {pos:{lineno:1, column:15, filename:<REPL>}, is:Var, name:print}} 592 + ], 593 + is: App, 594 + fun: {pos:{lineno:1, column:9, filename:<REPL>}, is:Var, name:twice} 595 + } 596 +</pre> 597 +<p> 598 +詳細は気にしなくて構いませんが、とにかく、<tt>@macro</tt> レイヤでは、 599 +基本的には、コードを実行するとそのコードの構文木がでてきます。 600 +この挙動は <tt>@macro</tt> レイヤの変数をセットすることで、カスタマイズできます。 601 +</p> 602 +<pre> 603 + &gt;&gt; @macro twice(x) { x; x } in twice(print("Hello")) 604 + Hello 605 + Hello 606 + Hello 607 +</pre> 608 +<p> 609 +(3回出力されてますが、3個目は <tt>print(x)</tt> の返値は <tt>x</tt> なので、 610 +それがREPLによって印字されているだけです。) 611 +<tt>@macro</tt> レイヤで <tt>in</tt> 以降を実行すると、<tt>print("Hello")</tt> という式を表す構文木が作られ、 612 +それが <tt>twice</tt> 関数に渡されます。<tt>twice</tt> の中身も <tt>@macro</tt> レイヤで実行されるので、 613 +構文木を作ろうとしますが、変数 <tt>x</tt> には <tt>@macro</tt> レイヤで値が入っているので、 614 +その値を読み取って構文木を作成します。 615 +結果として、2回 <tt>print("Hello")</tt> する構文木が作られて、 616 +その後で、それが <tt>@value</tt> レイヤで実行されています。 617 +</p> 618 +<p> 619 +本当にベタに構文木を作るだけなので、変数名の衝突などなどは気にしません。「衛生的でない」マクロです。 620 +</p> 621 +<pre> 622 + @macro LetItBe(x, y) { var <b>it</b> = x; y }; <font color=green># y の中で変数 it が使える</font> 623 + print( LetItBe("myself", "when I find " ~ <b>it</b> ~ " in times of trouble") ); 624 +</pre> 625 +<p> 626 +変数名に気をつけるには、組み込み関数 <tt>gensym()</tt> を使って頑張って下さい。 627 +</p> 628 +</dd> 629 + 630 +<script>explorer.outline.writeEnabled = true;</script> 631 +<dt><span class="decl"> 632 +<span class="currsymbol">レイヤ切り替え</span> 633 +<script>explorer.outline.addDecl('レイヤ切り替え');</script> 575 634 576 635 </span></dt> 577 636 <script>explorer.outline.writeEnabled = false;</script> 578 637 579 - <dd><pre> 580 - When function is invoked, it first run in the @macro layer, and after that, 581 - it run in the neutral layer. Here is an example. 582 - 583 - &gt;&gt; @macro twice(x) { x; x } 584 - &gt;&gt; def f() { twice(print("Hello")); 999 } 585 - (function:173b6a0:1789720) 586 - &gt;&gt; f() 587 - Hello 588 - Hello 589 - 999 590 - 591 - When the interpreter evaluates f(), it first executes 592 - "twice(print("Hello")); 999" 593 - in the @macro layer. Basically what it does is to just construct its syntax tree. 594 - But, since we have defined the "twice" function in the @macro layer, it is 595 - execute as a function. Resulting syntax tree is 596 - "print("Hello"); print("Hello"); 999" 597 - and this is executed on the neutral (in this example, @value) layer. 598 - This is the reason why you see two "Hello"s. 599 - 600 - [[quote and unquote]] 601 - 602 - Here is more involved example of code genration. 603 - From "x", it generates "x*x*x*x*x*x*x*x*x*x". 604 - 605 - @macro pow10(x) { 606 - @value( 607 - def pow(x, n) { 608 - if( n == 1 ) { x } 609 - else { 610 - @macro( @value(x) * @value(pow(x,n-1)) ) 611 - } 612 - } 613 - in 614 - pow(@macro(x),10) 615 - ) 616 - }; 617 - 618 - Here, x is a syntax tree but n is an actual integer. If you read carefully, 619 - you should get what is going on. Basically, @macro can be considered like 620 - quasiquoting and @value to be an escape from it. 638 + <dd><p> 639 +他のレイヤ同様、<tt>@macro</tt> レイヤを実行中に <tt>@layer( ... )</tt> 構文を使うことで、 640 +別のレイヤでコードを動かすこともできます。よく使う例は、<tt>@value</tt> 641 +レイヤに移ることで構文木を普通に計算して色々プログラム的にいじる用途です。 642 +</p> 643 +<pre> 644 + @macro reverseArgs(e) {<b>@value</b>( 645 + def rev(xs, acc) { 646 + case xs when {car:x, cdr:xs}: rev(xs, {car:x, cdr:acc}) when {}: acc 647 + }; 648 + case @macro(e) 649 + when {is:"App", fun:f, args:as}: {is:"App", fun:f, args:rev(as,{})} 650 + when e: e 651 + )}; 652 + print( reverseArgs(1-2) ); <font color=green># 2-1 == 1</font> 621 653 </pre> 622 654 <p> 655 +<tt>reverseArgs</tt> は、関数呼び出しの構文木の、引数の順番を逆転する関数です。 656 +<tt>@macro(e)</tt> によってマクロレイヤにセットされている構文木引数を取り出し、 657 +それを <tt>@value</tt> レイヤによる普通の計算プログラムで操作しています。 658 +要は、<tt>@macro(...)</tt> はいわゆる「準クオート (quasiquote)」、 659 +<tt>@value(...)</tt> は「逆クオート (unquote)」に近い働きをします。 660 +</p> 661 +<p> 662 +<tt>@layer(...)</tt> だけでなく、関数のレイヤ指定引数なども同様に使うことができるので、 663 +一部の引数は <tt>@macro</tt>、一部の引数は <tt>@value</tt> レイヤで受け取る関数を書くなど、 664 +さらに色々面白いことが可能です。 665 +</p> 666 +</dd> 667 + 668 +<script>explorer.outline.writeEnabled = true;</script> 669 +<dt><span class="decl"> 670 +<span class="currsymbol">構文木の構造</span> 671 +<script>explorer.outline.addDecl('構文木の構造');</script> 672 + 673 +</span></dt> 674 +<script>explorer.outline.writeEnabled = false;</script> 675 + 676 + <dd><p> 623 677 構文木がどのようなテーブルで渡されてくるかについては、ソースドキュメントの 624 678 <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a> 625 679 のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、 626 680 継承の分も合わせて 627 681 <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPosition</a> pos;</tt> 628 682 と <tt>string name;</tt> の2つのメンバがあるので 629 683 </p> ................................................................................ 632 686 pos: {filename:"foo.pmy", lineno:123, column:45}, 633 687 name: "x" } 634 688 </pre> 635 689 <p> 636 690 こんな感じのテーブルになります。 637 691 クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。 638 692 配列メンバは cons リストになって入ってきます。 693 +自分で構文木を作る時は、<tt>pos</tt> フィールドだけは省略しても構いません。 639 694 </p> 640 695 </dd> 641 696 642 697 <script>explorer.outline.writeEnabled = true;</script> 643 698 <dt><span class="decl"> 644 -<span class="currsymbol">微妙な挙動</span> 645 -<script>explorer.outline.addDecl('微妙な挙動');</script> 699 +<span class="currsymbol">微妙なところ</span> 700 +<script>explorer.outline.addDecl('微妙なところ');</script> 646 701 647 702 </span></dt> 648 703 <script>explorer.outline.writeEnabled = false;</script> 649 704 650 - <dd><pre> 705 + <dd><p> 706 +ここまで、<tt>@macro</tt> が本当にただの1レイヤであるかのように説明してきましたが、 707 +実はちょっと幾つかのトリックが潜んでいます。 708 +</p> 709 +<pre> 710 + &gt;&gt; @macro twice(x) {x; x} in twice(<b>@value</b>(print("Hello"))) 711 + Hello 712 + Hello 713 + Hello 714 +</pre> 715 +<p> 716 +先ほどの例に <tt>@value</tt> を増やしたものですが、これでもやはり、Hello 717 +が2回 print されるようになります。 718 +</p> 719 +<pre> 720 +<tt>@macro</tt> レイヤと <tt>(rawmacro)</tt> レイヤという二つが協調して動作しています。 651 721 (rawmacro) レイヤの話 652 722 653 723 [[limitations]] 654 724 655 725 This @macro layer is a very primitive one, and not a perfect macro language. 656 726 Two major limitations are seen in the following "it" example. 657 727 ................................................................................ 803 873 <script>explorer.outline.decSymbolLevel();</script> 804 874 805 875 806 876 </td></tr> 807 877 <tr><td id="docfooter"> 808 878 Page was generated with 809 879 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 810 - on Thu Nov 25 12:30:12 2010 880 + on Fri Nov 26 10:02:52 2010 811 881 812 882 </td></tr> 813 883 </table> 814 884 </div> 815 885 <script> 816 886 explorer.packageExplorer.addModule("index"); 817 887 explorer.packageExplorer.addModule("main");

Modified index.dd from [caf492581281c25d] to [80b16f2bd31d3d7f].

450 450 <p> 451 451 <code>@macro</code> レイヤも所詮ただのレイヤですので、 452 452 上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、 453 453 構文木の生成をいじることが可能です。まさにマクロ。 454 454 </p> 455 455 456 456 $(DDOC_MEMBERS 457 -$(SECTION 使い方, $(SECBODY 457 +$(SECTION 概要, $(SECBODY 458 +<p> 459 +samples/macro.pmy にいくつか使い方サンプルが置いてありますので、詳しくはそちらをどうぞ。 460 +</p> 461 +<pre> 462 + &gt;&gt; @macro( twice(print("Hello")) ) 463 + { 464 + pos: {lineno:1, column:9, filename:<REPL>}, 465 + args: [ { pos: {lineno:1, column:15, filename:<REPL>}, 466 + args: [{pos:{lineno:1, column:21, filename:<REPL>}, 467 + is:Str, 468 + data:Hello}], 469 + is: App, 470 + fun: {pos:{lineno:1, column:15, filename:<REPL>}, is:Var, name:print}} 471 + ], 472 + is: App, 473 + fun: {pos:{lineno:1, column:9, filename:<REPL>}, is:Var, name:twice} 474 + } 475 +</pre> 476 +<p> 477 +詳細は気にしなくて構いませんが、とにかく、<tt>@macro</tt> レイヤでは、 478 +基本的には、コードを実行するとそのコードの構文木がでてきます。 479 +この挙動は <tt>@macro</tt> レイヤの変数をセットすることで、カスタマイズできます。 480 +</p> 481 +<pre> 482 + &gt;&gt; @macro twice(x) { x; x } in twice(print("Hello")) 483 + Hello 484 + Hello 485 + Hello 486 +</pre> 487 +<p> 488 +(3回出力されてますが、3個目は <tt>print(x)</tt> の返値は <tt>x</tt> なので、 489 +それがREPLによって印字されているだけです。) 490 +<tt>@macro</tt> レイヤで <tt>in</tt> 以降を実行すると、<tt>print("Hello")</tt> という式を表す構文木が作られ、 491 +それが <tt>twice</tt> 関数に渡されます。<tt>twice</tt> の中身も <tt>@macro</tt> レイヤで実行されるので、 492 +構文木を作ろうとしますが、変数 <tt>x</tt> には <tt>@macro</tt> レイヤで値が入っているので、 493 +その値を読み取って構文木を作成します。 494 +結果として、2回 <tt>print("Hello")</tt> する構文木が作られて、 495 +その後で、それが <tt>@value</tt> レイヤで実行されています。 496 +</p> 497 +<p> 498 +本当にベタに構文木を作るだけなので、変数名の衝突などなどは気にしません。「衛生的でない」マクロです。 499 +</p> 500 +<pre> 501 + @macro LetItBe(x, y) { var $(B it) = x; y }; $(D_COMMENT # y の中で変数 it が使える) 502 + print( LetItBe("myself", "when I find " ~ $(B it) ~ " in times of trouble") ); 503 +</pre> 504 +<p> 505 +変数名に気をつけるには、組み込み関数 <tt>gensym()</tt> を使って頑張って下さい。 506 +</p> 507 +)) 508 +$(SECTION レイヤ切り替え, $(SECBODY 509 +<p> 510 +他のレイヤ同様、<tt>@macro</tt> レイヤを実行中に <tt>@layer( ... )</tt> 構文を使うことで、 511 +別のレイヤでコードを動かすこともできます。よく使う例は、<tt>@value</tt> 512 +レイヤに移ることで構文木を普通に計算して色々プログラム的にいじる用途です。 513 +</p> 458 514 <pre> 459 - When function is invoked, it first run in the @macro layer, and after that, 460 - it run in the neutral layer. Here is an example. 461 - 462 - >> @macro twice(x) { x; x } 463 - >> def f() { twice(print("Hello")); 999 } 464 - (function:173b6a0:1789720) 465 - >> f() 466 - Hello 467 - Hello 468 - 999 469 - 470 - When the interpreter evaluates f(), it first executes 471 - "twice(print("Hello")); 999" 472 - in the @macro layer. Basically what it does is to just construct its syntax tree. 473 - But, since we have defined the "twice" function in the @macro layer, it is 474 - execute as a function. Resulting syntax tree is 475 - "print("Hello"); print("Hello"); 999" 476 - and this is executed on the neutral (in this example, @value) layer. 477 - This is the reason why you see two "Hello"s. 478 - 479 - [[quote and unquote]] 480 - 481 - Here is more involved example of code genration. 482 - From "x", it generates "x*x*x*x*x*x*x*x*x*x". 483 - 484 - @macro pow10(x) { 485 - @value( 486 - def pow(x, n) { 487 - if( n == 1 ) { x } 488 - else { 489 - @macro( @value(x) * @value(pow(x,n-1)) ) 490 - } 491 - } 492 - in 493 - pow(@macro(x),10) 494 - ) 495 - }; 496 - 497 - Here, x is a syntax tree but n is an actual integer. If you read carefully, 498 - you should get what is going on. Basically, @macro can be considered like 499 - quasiquoting and @value to be an escape from it. 515 + @macro reverseArgs(e) {$(B @value)( 516 + def rev(xs, acc) { 517 + case xs when {car:x, cdr:xs}: rev(xs, {car:x, cdr:acc}) when {}: acc 518 + }; 519 + case @macro(e) 520 + when {is:"App", fun:f, args:as}: {is:"App", fun:f, args:rev(as,{})} 521 + when e: e 522 + )}; 523 + print( reverseArgs(1-2) ); $(D_COMMENT # 2-1 == 1) 500 524 </pre> 525 +<p> 526 +<tt>reverseArgs</tt> は、関数呼び出しの構文木の、引数の順番を逆転する関数です。 527 +<tt>@macro(e)</tt> によってマクロレイヤにセットされている構文木引数を取り出し、 528 +それを <tt>@value</tt> レイヤによる普通の計算プログラムで操作しています。 529 +要は、<tt>@macro(...)</tt> はいわゆる「準クオート (quasiquote)」、 530 +<tt>@value(...)</tt> は「逆クオート (unquote)」に近い働きをします。 531 +</p> 532 +<p> 533 +<tt>@layer(...)</tt> だけでなく、関数のレイヤ指定引数なども同様に使うことができるので、 534 +一部の引数は <tt>@macro</tt>、一部の引数は <tt>@value</tt> レイヤで受け取る関数を書くなど、 535 +さらに色々面白いことが可能です。 536 +</p> 537 +)) 538 +$(SECTION 構文木の構造, $(SECBODY 501 539 <p> 502 540 構文木がどのようなテーブルで渡されてくるかについては、ソースドキュメントの 503 541 <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a> 504 542 のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、 505 543 継承の分も合わせて 506 544 <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPosition</a> pos;</tt> 507 545 と <tt>string name;</tt> の2つのメンバがあるので ................................................................................ 511 549 pos: {filename:"foo.pmy", lineno:123, column:45}, 512 550 name: "x" } 513 551 </pre> 514 552 <p> 515 553 こんな感じのテーブルになります。 516 554 クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。 517 555 配列メンバは cons リストになって入ってきます。 556 +自分で構文木を作る時は、<tt>pos</tt> フィールドだけは省略しても構いません。 518 557 </p> 519 558 )) 520 -$(SECTION 微妙な挙動, $(SECBODY 559 +$(SECTION 微妙なところ, $(SECBODY 560 +<p> 561 +ここまで、<tt>@macro</tt> が本当にただの1レイヤであるかのように説明してきましたが、 562 +実はちょっと幾つかのトリックが潜んでいます。 563 +</p> 564 +<pre> 565 + &gt;&gt; @macro twice(x) {x; x} in twice($(B @value)(print("Hello"))) 566 + Hello 567 + Hello 568 + Hello 569 +</pre> 570 +<p> 571 +先ほどの例に <tt>@value</tt> を増やしたものですが、これでもやはり、Hello 572 +が2回 print されるようになります。 573 +</p> 521 574 <pre> 575 +<tt>@macro</tt> レイヤと <tt>(rawmacro)</tt> レイヤという二つが協調して動作しています。 522 576 (rawmacro) レイヤの話 523 577 524 578 [[limitations]] 525 579 526 580 This @macro layer is a very primitive one, and not a perfect macro language. 527 581 Two major limitations are seen in the following "it" example. 528 582

Modified polemy/eval.d from [bc3c32f1d9aafc10] to [74dd93745d781116].

114 114 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 115 115 { 116 116 if( isASTLayer(lay) ) 117 117 { 118 118 // need this for correct scoping (outer scope macro variables must be hidden!) 119 119 Table newCtx = new Table(ctx, Table.Kind.NotPropagateSet); 120 120 foreach(p; e.params) 121 - newCtx.set(p.name, ValueLayer, new UndefinedValue); 121 + newCtx.set(p.name, NoopLayer, null); 122 122 return ast2table(e, (AST e){return eval(e,lay,newCtx);}); 123 123 } 124 124 else 125 125 return createNewFunction(e, ctx); 126 126 } 127 127 128 128 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) ................................................................................ 136 136 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 137 137 { 138 138 Table newCtx = overwriteCtx ? ctx : new Table(ctx, Table.Kind.NotPropagateSet); 139 139 if( isASTLayer(lay) ) 140 140 return ast2table(e, (AST ee){ 141 141 // need this for correct scoping (outer scope macro variables must be hidden!) 142 142 if(ee is e.expr) 143 - newCtx.set(e.name, ValueLayer, new UndefinedValue); 143 + newCtx.set(e.name, NoopLayer, null); 144 144 return eval(ee,lay,newCtx); 145 145 }); 146 146 else 147 147 { 148 148 Value ri = eval(e.init, lay, newCtx); 149 149 newCtx.set(e.name, e.layer.empty ? lay : e.layer, ri); 150 150 return eval(e.expr, lay, newCtx, OverwriteCtx); ................................................................................ 216 216 { 217 217 assert( !isASTLayer(lay), "lift to the @macro layer should never happen" ); 218 218 219 219 // functions are automatically lifterd 220 220 if( cast(FunValue) v ) 221 221 return v; 222 222 223 - if( !ctx.has(lay, SystemLayer) ) 223 + if( !ctx.has(lay, LiftLayer) ) 224 224 throw genex!RuntimeException(pos, "lift function for "~lay~" is not registered" ); 225 225 226 226 // similar to invokeFunction, but with only one argument bound to ValueLayer 227 - auto _f = ctx.get(lay, SystemLayer, pos); 227 + auto _f = ctx.get(lay, LiftLayer, pos); 228 228 if(auto f = cast(FunValue)_f) 229 229 { 230 230 Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 231 231 auto ps = f.params(); 232 232 if( ps.length != 1 ) 233 233 throw genex!RuntimeException(pos, 234 234 text("lift function for", lay, " must take exactly one argument of ", ValueLayer));

Modified polemy/layer.d from [70a85e9a66eddacd] to [e37c83f645af4d82].

9 9 10 10 /// Type for the layer ID 11 11 12 12 alias string Layer; 13 13 14 14 enum : Layer 15 15 { 16 - SystemLayer = "(system)", /// Predefined layer for internal data 16 + LiftLayer = "(lift)", /// Predefined layer for storing lift functions 17 + NoopLayer = "(noop)", /// Predefined layer for just allocating a slot for table 17 18 ValueLayer = "@value", /// Predefined layer for normal run 18 19 MacroLayer = "@macro", /// Predefined layer for macro run (@lay() changes layer) 19 20 RawMacroLayer = "(rawmacro)", /// Predefined layer for macro run (@lay() becomes AST) 20 21 } 21 22 22 23 /// True if it is a user-defined layer 23 24 24 25 bool isUserDefinedLayer( Layer lay ) 25 26 { 26 - return lay!=SystemLayer && lay!=ValueLayer && lay!=MacroLayer && lay!=RawMacroLayer; 27 + return lay!=NoopLayer && lay!=LiftLayer && lay!=ValueLayer && lay!=MacroLayer && lay!=RawMacroLayer; 27 28 } 28 29 29 30 unittest 30 31 { 31 - assert( !isUserDefinedLayer(SystemLayer) ); 32 + assert( !isUserDefinedLayer(NoopLayer) ); 33 + assert( !isUserDefinedLayer(LiftLayer) ); 32 34 assert( !isUserDefinedLayer(ValueLayer) ); 33 35 assert( !isUserDefinedLayer(MacroLayer) ); 34 36 assert( !isUserDefinedLayer(RawMacroLayer) ); 35 37 assert( isUserDefinedLayer("@foo") ); 36 38 } 37 39 38 40 /// True if it is macro-like layer that basically generates syntax tree ................................................................................ 40 42 bool isASTLayer( Layer lay ) 41 43 { 42 44 return lay==MacroLayer || lay==RawMacroLayer; 43 45 } 44 46 45 47 unittest 46 48 { 47 - assert( !isASTLayer(SystemLayer) ); 49 + assert( !isASTLayer(NoopLayer) ); 50 + assert( !isASTLayer(LiftLayer) ); 48 51 assert( !isASTLayer(ValueLayer) ); 49 52 assert( isASTLayer(MacroLayer) ); 50 53 assert( isASTLayer(RawMacroLayer) ); 51 54 } 52 55 53 56 /// True if in the specified layer @lay(...) has no effect and merely produces a syntax tree 54 57 ................................................................................ 55 58 bool isNoLayerChangeLayer( Layer lay ) 56 59 { 57 60 return lay==RawMacroLayer; 58 61 } 59 62 60 63 unittest 61 64 { 62 - assert( !isNoLayerChangeLayer(SystemLayer) ); 65 + assert( !isNoLayerChangeLayer(NoopLayer) ); 66 + assert( !isNoLayerChangeLayer(LiftLayer) ); 63 67 assert( !isNoLayerChangeLayer(ValueLayer) ); 64 68 assert( !isNoLayerChangeLayer(MacroLayer) ); 65 69 assert( isNoLayerChangeLayer(RawMacroLayer) ); 66 70 } 67 71 68 72 /// True if do macro expanstion 69 73 ................................................................................ 70 74 bool isMacroLayer( Layer lay ) 71 75 { 72 76 return lay==MacroLayer || lay==RawMacroLayer; 73 77 } 74 78 75 79 unittest 76 80 { 77 - assert( !isMacroLayer(SystemLayer) ); 81 + assert( !isMacroLayer(NoopLayer) ); 82 + assert( !isMacroLayer(LiftLayer) ); 78 83 assert( !isMacroLayer(ValueLayer) ); 79 84 assert( isMacroLayer(MacroLayer) ); 80 85 assert( isMacroLayer(RawMacroLayer) ); 81 86 }

Modified polemy/parse.d from [38516f68b159d6bd] to [9aca36046bea5df8].

98 98 string kwd = "@" ~ layer; 99 99 string var = layer; 100 100 101 101 auto e = tryEat("(") 102 102 ? parseLambdaAfterOpenParen(pos) // let var ( ... 103 103 : (eat("=", "after "~kwd), E(0)); // let var = ... 104 104 if( moreDeclarationExists() ) 105 - return new Let(pos, var, SystemLayer, e, Body()); 105 + return new Let(pos, var, LiftLayer, e, Body()); 106 106 else 107 - return new Let(pos, var, SystemLayer, e, 108 - new Lay(pos, SystemLayer, new Var(pos, var)) 107 + return new Let(pos, var, LiftLayer, e, 108 + new Lay(pos, LiftLayer, new Var(pos, var)) 109 109 ); 110 110 } 111 111 else 112 112 { 113 113 string kwd = layer; 114 114 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="var") && !tryEat(kwd="def") ) 115 115 return null; // none of {@lay, let, var, def} occurred, it's not a declaration ................................................................................ 632 632 assert_eq(parseString(`def foo(x) { x+1 }; foo`), 633 633 let("foo", "", 634 634 fun(["x"], call(var("+"), var("x"), intl(1))), 635 635 var("foo")) 636 636 ); 637 637 638 638 assert_eq(parseString(`@@type ( x ) { x }`), 639 - let("@type", SystemLayer, fun(["x"], var("x")), lay(SystemLayer, var("@type"))) ); 639 + let("@type", LiftLayer, fun(["x"], var("x")), lay(LiftLayer, var("@type"))) ); 640 640 641 641 assert_eq(parseString(`{}`), call(var("{}"))); 642 642 assert_eq(parseString(`{foo:1,"bar":2}`), 643 643 call(var(".="), call(var(".="), call(var("{}")), strl("foo"), intl(1)), strl("bar"), intl(2))); 644 644 assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo"))); 645 645 assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("foo"))); 646 646 assert_eq(parseString(`x{y:1}`), call(var(".="),var("x"),strl("y"),intl(1)));

Modified polemy/value.d from [6fa9c2c94c01b274] to [3d0cc7f551924493].

101 101 return prototype.has(i, lay); 102 102 } 103 103 104 104 /// Return the value of index i at layer lay. Throws if it is not set 105 105 Value get(string i, Layer lay, LexPosition pos=null) 106 106 { 107 107 if( i in data ) { 108 - // [TODO] consider forwarding to proto also in this case 109 108 if( lay !in data[i] ) 110 109 throw genex!RuntimeException(pos, sprintf!"'%s' is not set in %s layer"(i,lay)); 111 110 return data[i][lay]; 112 111 } 113 112 if( prototype is null ) 114 113 throw genex!RuntimeException(pos, sprintf!"'%s' not found in %s layer"(i,lay)); 115 114 return prototype.get(i, lay, pos);

Modified sample/macro.pmy from [996468a22f9d9a8e] to [b441073a5b98679b].

34 34 print( maxGreat(print(1), print(2)) ); # 1 2 2 35 35 print( maxGreat(print(2), print(1)) ); # 2 1 2 36 36 37 37 ######################################## 38 38 print("----------"); 39 39 40 40 # the variable "it" is inserted to the scope 41 -@macro LetItBe(x, y) { let it = x in y }; 41 +@macro LetItBe(x, y) { var it = x; y }; 42 42 print( LetItBe("myself", "when I find " ~ it ~ " in times of trouble") ); 43 43 44 44 ######################################## 45 45 print("----------"); 46 46 47 47 # layerd parameter can also be used for @macro 48 48 # you can mix @macro and normal parameters!!