Differences From Artifact [720b71facce28489]:
- File
doc/index.html
- 2010-11-25 03:32:41 - part of checkin [474c4facf0] on branch trunk - Introduced makefile to build documents. sample/macro.pmy is fully reformed. print(x) now returns x, not 0. (user: kinaba) [annotate]
To Artifact [56b12828066b590e]:
- File
doc/index.html
- 2010-11-26 05:03:10 - part of checkin [207cea338a] on branch trunk - changed hiding mechanizem of x in let x = ... for @macro layer. Old: set(x,ValueLayer,undefined) Nee: set(x,NoopLayer,null) (user: kinaba) [annotate]
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 >> @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 >> @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 >> @macro twice(x) { x; x } <
> 641 レイヤに移ることで構文木を普通に計算して色々プログラ的にいじる用途です。
> 642 </p>
584 >> def f() { twice(print("Hello")); 999 } | 643 <pre>
585 (function:173b6a0:1789720) | 644 @macro reverseArgs(e) {<b>@value</b>(
586 >> 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 >> @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");