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

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

566 </p> 566 </p> 567 567 568 568 569 <script>explorer.outline.incSymbolLevel();</script> 569 <script>explorer.outline.incSymbolLevel();</script> 570 <dl> 570 <dl> 571 <script>explorer.outline.writeEnabled = true;</script> 571 <script>explorer.outline.writeEnabled = true;</script> 572 <dt><span class="decl"> 572 <dt><span class="decl"> 573 <span class="currsymbol">使い方</span> | 573 <span class="currsymbol">概要</span> 574 <script>explorer.outline.addDecl('使い方');</script> | 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:pr > 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 の中で変数 > 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 </span></dt> 635 </span></dt> 577 <script>explorer.outline.writeEnabled = false;</script> 636 <script>explorer.outline.writeEnabled = false;</script> 578 637 579 <dd><pre> | 638 <dd><p> 580 When function is invoked, it first run in the @macro layer, and after that, | 639 他のレイヤ同様、<tt>@macro</tt> レイヤを実行中に <tt>@layer( ... )</tt> 構文を使うことで、 581 it run in the neutral layer. Here is an example. | 640 別のレイヤでコードを動かすこともできます。よく使う例は、<tt>@value</tt> 582 < 583 &gt;&gt; @macro twice(x) { x; x } < > 641 レイヤに移ることで構文木を普通に計算して色々プログラ的にいじる用途です。 > 642 </p> 584 &gt;&gt; def f() { twice(print("Hello")); 999 } | 643 <pre> 585 (function:173b6a0:1789720) | 644 @macro reverseArgs(e) {<b>@value</b>( 586 &gt;&gt; f() | 645 def rev(xs, acc) { 587 Hello | 646 case xs when {car:x, cdr:xs}: rev(xs, {car:x, cdr:acc}) when {}: acc 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 t < 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 } | 647 }; 612 } < 613 in < 614 pow(@macro(x),10) | 648 case @macro(e) 615 ) < > 649 when {is:"App", fun:f, args:as}: {is:"App", fun:f, args:rev(as,{})} > 650 when e: e 616 }; | 651 )}; 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. < > 652 print( reverseArgs(1-2) ); <font color=green># 2-1 == 1</font> 621 </pre> 653 </pre> 622 <p> 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 <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a> 678 <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a> 625 のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、 679 のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、 626 継承の分も合わせて 680 継承の分も合わせて 627 <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPos 681 <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPos 628 と <tt>string name;</tt> の2つのメンバがあるので 682 と <tt>string name;</tt> の2つのメンバがあるので 629 </p> 683 </p> ................................................................................................................................................................................ 632 pos: {filename:"foo.pmy", lineno:123, column:45}, 686 pos: {filename:"foo.pmy", lineno:123, column:45}, 633 name: "x" } 687 name: "x" } 634 </pre> 688 </pre> 635 <p> 689 <p> 636 こんな感じのテーブルになります。 690 こんな感じのテーブルになります。 637 クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。 691 クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。 638 配列メンバは cons リストになって入ってきます。 692 配列メンバは cons リストになって入ってきます。 > 693 自分で構文木を作る時は、<tt>pos</tt> フィールドだけは省略ても構いません。 639 </p> 694 </p> 640 </dd> 695 </dd> 641 696 642 <script>explorer.outline.writeEnabled = true;</script> 697 <script>explorer.outline.writeEnabled = true;</script> 643 <dt><span class="decl"> 698 <dt><span class="decl"> 644 <span class="currsymbol">微妙な挙動</span> | 699 <span class="currsymbol">微妙なところ</span> 645 <script>explorer.outline.addDecl('微妙な挙動');</script> | 700 <script>explorer.outline.addDecl('微妙なところ');</script> 646 701 647 </span></dt> 702 </span></dt> 648 <script>explorer.outline.writeEnabled = false;</script> 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 (rawmacro) レイヤの話 721 (rawmacro) レイヤの話 652 722 653 [[limitations]] 723 [[limitations]] 654 724 655 This @macro layer is a very primitive one, and not a perfect macro language. 725 This @macro layer is a very primitive one, and not a perfect macro language. 656 Two major limitations are seen in the following "it" example. 726 Two major limitations are seen in the following "it" example. 657 727 ................................................................................................................................................................................ 803 <script>explorer.outline.decSymbolLevel();</script> 873 <script>explorer.outline.decSymbolLevel();</script> 804 874 805 875 806 </td></tr> 876 </td></tr> 807 <tr><td id="docfooter"> 877 <tr><td id="docfooter"> 808 Page was generated with 878 Page was generated with 809 <img src="candydoc/img/candydoc.gif" style="vertical-ali 879 <img src="candydoc/img/candydoc.gif" style="vertical-ali 810 on Thu Nov 25 12:30:12 2010 | 880 on Fri Nov 26 10:02:52 2010 811 881 812 </td></tr> 882 </td></tr> 813 </table> 883 </table> 814 </div> 884 </div> 815 <script> 885 <script> 816 explorer.packageExplorer.addModule("index"); 886 explorer.packageExplorer.addModule("index"); 817 explorer.packageExplorer.addModule("main"); 887 explorer.packageExplorer.addModule("main");

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

450 <p> 450 <p> 451 <code>@macro</code> レイヤも所詮ただのレイヤですので、 451 <code>@macro</code> レイヤも所詮ただのレイヤですので、 452 上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、 452 上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、 453 構文木の生成をいじることが可能です。まさにマクロ。 453 構文木の生成をいじることが可能です。まさにマクロ。 454 </p> 454 </p> 455 455 456 $(DDOC_MEMBERS 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:pr > 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 <pre> 514 <pre> 459 When function is invoked, it first run in the @macro layer, and after that, | 515 @macro reverseArgs(e) {$(B @value)( 460 it run in the neutral layer. Here is an example. | 516 def rev(xs, acc) { 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 t < 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)) ) < > 517 case xs when {car:x, cdr:xs}: rev(xs, {car:x, cdr:acc}) when {}: acc 490 } | 518 }; 491 } < 492 in < 493 pow(@macro(x),10) | 519 case @macro(e) 494 ) < > 520 when {is:"App", fun:f, args:as}: {is:"App", fun:f, args:rev(as,{})} > 521 when e: e 495 }; | 522 )}; 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. < > 523 print( reverseArgs(1-2) ); $(D_COMMENT # 2-1 == 1) 500 </pre> 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 <p> 539 <p> 502 構文木がどのようなテーブルで渡されてくるかについては、ソースドキュメントの 540 構文木がどのようなテーブルで渡されてくるかについては、ソースドキュメントの 503 <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a> 541 <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a> 504 のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、 542 のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、 505 継承の分も合わせて 543 継承の分も合わせて 506 <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPos 544 <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPos 507 と <tt>string name;</tt> の2つのメンバがあるので 545 と <tt>string name;</tt> の2つのメンバがあるので ................................................................................................................................................................................ 511 pos: {filename:"foo.pmy", lineno:123, column:45}, 549 pos: {filename:"foo.pmy", lineno:123, column:45}, 512 name: "x" } 550 name: "x" } 513 </pre> 551 </pre> 514 <p> 552 <p> 515 こんな感じのテーブルになります。 553 こんな感じのテーブルになります。 516 クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。 554 クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。 517 配列メンバは cons リストになって入ってきます。 555 配列メンバは cons リストになって入ってきます。 > 556 自分で構文木を作る時は、<tt>pos</tt> フィールドだけは省略ても構いません。 518 </p> 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 <pre> 574 <pre> > 575 <tt>@macro</tt> レイヤと <tt>(rawmacro)</tt> レイヤという二つが協して動作しています。 522 (rawmacro) レイヤの話 576 (rawmacro) レイヤの話 523 577 524 [[limitations]] 578 [[limitations]] 525 579 526 This @macro layer is a very primitive one, and not a perfect macro language. 580 This @macro layer is a very primitive one, and not a perfect macro language. 527 Two major limitations are seen in the following "it" example. 581 Two major limitations are seen in the following "it" example. 528 582

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

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

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

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

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

98 string kwd = "@" ~ layer; 98 string kwd = "@" ~ layer; 99 string var = layer; 99 string var = layer; 100 100 101 auto e = tryEat("(") 101 auto e = tryEat("(") 102 ? parseLambdaAfterOpenParen(pos) // let var ( . 102 ? parseLambdaAfterOpenParen(pos) // let var ( . 103 : (eat("=", "after "~kwd), E(0)); // let var = . 103 : (eat("=", "after "~kwd), E(0)); // let var = . 104 if( moreDeclarationExists() ) 104 if( moreDeclarationExists() ) 105 return new Let(pos, var, SystemLayer, e, Body()) | 105 return new Let(pos, var, LiftLayer, e, Body()); 106 else 106 else 107 return new Let(pos, var, SystemLayer, e, | 107 return new Let(pos, var, LiftLayer, e, 108 new Lay(pos, SystemLayer, new Var(pos, v | 108 new Lay(pos, LiftLayer, new Var(pos, var 109 ); 109 ); 110 } 110 } 111 else 111 else 112 { 112 { 113 string kwd = layer; 113 string kwd = layer; 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 ................................................................................................................................................................................ 632 assert_eq(parseString(`def foo(x) { x+1 }; foo`), 632 assert_eq(parseString(`def foo(x) { x+1 }; foo`), 633 let("foo", "", 633 let("foo", "", 634 fun(["x"], call(var("+"), var("x"), intl(1))), 634 fun(["x"], call(var("+"), var("x"), intl(1))), 635 var("foo")) 635 var("foo")) 636 ); 636 ); 637 637 638 assert_eq(parseString(`@@type ( x ) { x }`), 638 assert_eq(parseString(`@@type ( x ) { x }`), 639 let("@type", SystemLayer, fun(["x"], var("x")), lay(SystemLayer, | 639 let("@type", LiftLayer, fun(["x"], var("x")), lay(LiftLayer, var 640 640 641 assert_eq(parseString(`{}`), call(var("{}"))); 641 assert_eq(parseString(`{}`), call(var("{}"))); 642 assert_eq(parseString(`{foo:1,"bar":2}`), 642 assert_eq(parseString(`{foo:1,"bar":2}`), 643 call(var(".="), call(var(".="), call(var("{}")), strl("foo"), in 643 call(var(".="), call(var(".="), call(var("{}")), strl("foo"), in 644 assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo 644 assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo 645 assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("f 645 assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("f 646 assert_eq(parseString(`x{y:1}`), call(var(".="),var("x"),strl("y"),intl( 646 assert_eq(parseString(`x{y:1}`), call(var(".="),var("x"),strl("y"),intl(

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

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

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

34 print( maxGreat(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 35 print( maxGreat(print(2), print(1)) ); # 2 1 2 36 36 37 ######################################## 37 ######################################## 38 print("----------"); 38 print("----------"); 39 39 40 # the variable "it" is inserted to the scope 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 print( LetItBe("myself", "when I find " ~ it ~ " in times of trouble") ); 42 print( LetItBe("myself", "when I find " ~ it ~ " in times of trouble") ); 43 43 44 ######################################## 44 ######################################## 45 print("----------"); 45 print("----------"); 46 46 47 # layerd parameter can also be used for @macro 47 # layerd parameter can also be used for @macro 48 # you can mix @macro and normal parameters!! 48 # you can mix @macro and normal parameters!!