Diff
Not logged in

Differences From Artifact [dc242393e80db0b7]:

To Artifact [a076bfb1003e4c62]:


16 16 17 <b>Authors:</b><br> 17 <b>Authors:</b><br> 18 k.inaba<br><br> 18 k.inaba<br><br> 19 <b>License:</b><br> 19 <b>License:</b><br> 20 NYSL 0.9982 (http://www.kmonos.net/nysl/)<br><br> 20 NYSL 0.9982 (http://www.kmonos.net/nysl/)<br><br> 21 21 22 <p> 22 <p> 23 このファイルは、言語仕様などの簡単な説明です。 | 23 左のサイドバーの "Package" タブをクリックすると実装のソースのドキュメントが読めます。 24 </p> 24 </p> 25 <p> 25 <p> 26 とついでに、左イドバーの "Package" タブをクリックすると実装のソースのドキュメントが読めます。 | 26 のファイルは、言語仕様などやや辞書的な説明です。<br /> > 27 もっとざっくりとした、言語デザインの方向性の魂的なもについては、 > 28 「メタプログラミングの会」の発表スライドをご覧下さい > 29 </p> > 30 <p> > 31 あと、 やたらとマクロの章が長くなっていますが、 この部分は、 > 32 レイヤ機能を入れたら自動的にすごく自然にマクロが入るーと思って、 > 33 おまけで実装してみた程度のものです。 > 34 あんまり重要ではないので、適当にスルーして下さいませ > 35 単に、適当に入れたら適当で微妙な部分が多く残ってしまたので注意書きが増えているだけで…。 27 </p> 36 </p> 28 37 29 38 30 <script>explorer.outline.incSymbolLevel();</script> 39 <script>explorer.outline.incSymbolLevel();</script> 31 <dl> 40 <dl> 32 <script>explorer.outline.writeEnabled = true;</script> 41 <script>explorer.outline.writeEnabled = true;</script> 33 <dt><span class="decl"> 42 <dt><span class="decl"> ................................................................................................................................................................................ 236 </pre> 245 </pre> 237 <p> 246 <p> 238 let-in を縦にチェインしたときだけ、同名変数を破壊的に上書きします 247 let-in を縦にチェインしたときだけ、同名変数を破壊的に上書きします 239 (再帰関数の定義が"うまく"いっているのはこの上書きのためです)。 248 (再帰関数の定義が"うまく"いっているのはこの上書きのためです)。 240 なんでこんなことになっているかというと、 249 なんでこんなことになっているかというと、 241 後で説明する「レイヤ」を使ったときに 250 後で説明する「レイヤ」を使ったときに 242 <tt>let foo = ... in @lay foo = ... in ...</tt> 251 <tt>let foo = ... in @lay foo = ... in ...</tt> 243 で他レイヤに重ね書きするためあります。 | 252 で他レイヤに重ね書きするためのつもりです。詳しくは後で 244 </p> 253 </p> 245 </dd> 254 </dd> 246 </dl> 255 </dl> 247 <script>explorer.outline.decSymbolLevel();</script> 256 <script>explorer.outline.decSymbolLevel();</script> 248 257 249 258 250 </dd> 259 </dd> ................................................................................................................................................................................ 288 以下のデータ型があります。 297 以下のデータ型があります。 289 </p> 298 </p> 290 <ul> 299 <ul> 291 <li>整数: <tt>0</tt>, <tt>123</tt>, <tt>456666666666666666666666666666666666 300 <li>整数: <tt>0</tt>, <tt>123</tt>, <tt>456666666666666666666666666666666666 292 <li>文字列: <tt>"hello, world!"</tt>, ...</li> 301 <li>文字列: <tt>"hello, world!"</tt>, ...</li> 293 <li>関数: <tt>fun(x){x+1}</tt></li> 302 <li>関数: <tt>fun(x){x+1}</tt></li> 294 <li>テーブル: <tt>{car: 1, cdr: {car: 2, cdr: {}}}</tt></li> 303 <li>テーブル: <tt>{car: 1, cdr: {car: 2, cdr: {}}}</tt></li> 295 <li>未定義値: (特殊なケースで作られます。「レイヤ」の説明参照のこと。)</li> | 304 <li>ボトム: (特殊なケースで作られます。「レイヤ」の説明参照のこと。)</li> 296 </ul> 305 </ul> 297 <p> 306 <p> 298 関数はいわゆる「クロージャ」です。静的スコープで外側の環境にアクセスできます。 307 関数はいわゆる「クロージャ」です。静的スコープで外側の環境にアクセスできます。 299 テーブルはいわゆるプロトタイプチェーンを持っていて、 308 テーブルはいわゆるプロトタイプチェーンを持っていて、 300 自分にないフィールドの場合は親に問い合わせが行く感じになっていますが、 309 自分にないフィールドの場合は親に問い合わせが行く感じになっていますが、 301 フィールドの書き換えがないので、これは特に意味ないかもしれない…。 310 フィールドの書き換えがないので、これは特に意味ないかもしれない…。 302 </p> 311 </p> ................................................................................................................................................................................ 556 </pre> 565 </pre> 557 <p> 566 <p> 558 動きとしてはこうです。 567 動きとしてはこうです。 559 </p> 568 </p> 560 <ol> 569 <ol> 561 <li>関数呼び出し時(とトップレベル環境の実行開始時)に、 570 <li>関数呼び出し時(とトップレベル環境の実行開始時)に、 562 まず、<code>@macro</code> レイヤでコードを実行。</li> 571 まず、<code>@macro</code> レイヤでコードを実行。</li> 563 <li>返ってきた構文木を、<code>@value</code> レイヤ、 < 564 またはその関数を呼び出したときのレイヤで実行。</li> | 572 <li>返ってきた構文木を、その関数を呼び出したときのレイヤで実行。</li> 565 </ol> 573 </ol> 566 <p> 574 <p> 567 <code>@macro</code> レイヤも所詮ただのレイヤですので、 575 <code>@macro</code> レイヤも所詮ただのレイヤですので、 568 上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、 576 上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、 569 構文木の生成をいじることが可能です。まさにマクロ。 577 構文木の生成をいじることが可能です。まさにマクロ。 570 </p> 578 </p> 571 579 ................................................................................................................................................................................ 655 )}; 663 )}; 656 print( reverseArgs(1-2) ); <font color=green># 2-1 == 1</font> 664 print( reverseArgs(1-2) ); <font color=green># 2-1 == 1</font> 657 </pre> 665 </pre> 658 <p> 666 <p> 659 <tt>reverseArgs</tt> は、関数呼び出しの構文木の、引数の順番を逆転する関数です。 667 <tt>reverseArgs</tt> は、関数呼び出しの構文木の、引数の順番を逆転する関数です。 660 <tt>@macro(e)</tt> によってマクロレイヤにセットされている構文木引数を取り出し、 668 <tt>@macro(e)</tt> によってマクロレイヤにセットされている構文木引数を取り出し、 661 それを <tt>@value</tt> レイヤによる普通の計算プログラムで操作しています。 669 それを <tt>@value</tt> レイヤによる普通の計算プログラムで操作しています。 662 要は、<tt>@macro(...)</tt> はいわゆる「準クオート (quasiquote)」、 | 670 <tt>@macro(...)</tt> はいわゆる「準クオート (quasiquote)」、 663 <tt>@value(...)</tt> は「逆クオート (unquote)」に近い働きをします。 | 671 <tt>@value(...)</tt> は「逆クオート (unquote)」にちょっと近いかもしれません 664 </p> 672 </p> 665 <p> 673 <p> 666 <tt>@layer(...)</tt> だけでなく、関数のレイヤ指定引数なども同様に使うことができるので、 674 <tt>@layer(...)</tt> だけでなく、関数のレイヤ指定引数なども同様に使うことができるので、 667 一部の引数は <tt>@macro</tt>、一部の引数は <tt>@value</tt> レイヤで受け取る関数を書くなど、 675 一部の引数は <tt>@macro</tt>、一部の引数は <tt>@value</tt> レイヤで受け取る関数を書くなど、 668 さらに色々面白いことが可能です。 676 さらに色々面白いことが可能です。 669 </p> 677 </p> 670 </dd> 678 </dd> ................................................................................................................................................................................ 696 配列メンバは cons リストになって入ってきます。 704 配列メンバは cons リストになって入ってきます。 697 自分で構文木を作る時は、<tt>pos</tt> フィールドだけは省略しても構いません。 705 自分で構文木を作る時は、<tt>pos</tt> フィールドだけは省略しても構いません。 698 </p> 706 </p> 699 </dd> 707 </dd> 700 708 701 <script>explorer.outline.writeEnabled = true;</script> 709 <script>explorer.outline.writeEnabled = true;</script> 702 <dt><span class="decl"> 710 <dt><span class="decl"> 703 <span class="currsymbol">微妙なところ</span> | 711 <span class="currsymbol">微妙なところ</span> 704 <script>explorer.outline.addDecl('微妙なところ');</script> | 712 <script>explorer.outline.addDecl('微妙なところ');</script> 705 713 706 </span></dt> 714 </span></dt> 707 <script>explorer.outline.writeEnabled = false;</script> 715 <script>explorer.outline.writeEnabled = false;</script> 708 716 709 <dd><p> 717 <dd><p> 710 ここまで、<tt>@macro</tt> が本当にただの1レイヤあるかのように説明してきましたが、 | 718 ここまで、<tt>@macro</tt> が本当にただの1レイヤ説明してきましたが、 711 実はちょっと幾つかのトリックが潜んでいます。 | 719 実はちょっとトリックが潜んでいます。 712 </p> 720 </p> 713 <pre> 721 <pre> 714 &gt;&gt; @macro twice(x) {x; x} in twice(<b>@value</b>(print("Hello"))) 722 &gt;&gt; @macro twice(x) {x; x} in twice(<b>@value</b>(print("Hello"))) 715 Hello 723 Hello 716 Hello 724 Hello 717 Hello 725 Hello 718 </pre> 726 </pre> 719 <p> 727 <p> 720 先ほどの例に <tt>@value</tt> を増やしたものですが、これでもやはり、Hello 728 先ほどの例に <tt>@value</tt> を増やしたものですが、これでもやはり、Hello 721 が2回 print されるようになります。 | 729 が2回 print されるようになります。これは本来はおかしな話で、<tt>print("Hello")</tt> > 730 は <tt>@value</tt> レイヤで実行されて値に落ちるはずなので、1回しか print されないはず。 > 731 </p> > 732 <p> > 733 実は、Polemy の中では、<tt>@macro</tt> レイヤと <tt>(rawmacro)</tt> > 734 レイヤという二つの異なるマクロ用レイヤが動いています > 735 </p> > 736 <ul> > 737 <li><tt>(rawmacro)</tt> も <tt>@macro</tt> も、コードを動かすとそ構文木を返す意味論。</li> > 738 <li>ただし、<tt>(rawmacro)</tt> も <tt>@macro</tt> も、 > 739 <tt>@macro</tt> レイヤに値のセットされた変数をみつけたとは、 > 740 その変数という構文木を作るのではなく、変数の内容を展開。</li> > 741 <li>また <tt>@macro</tt> は、 > 742 レイヤ指定式を見ると実行レイヤを切り替て、構文木生成モードをやめてしまう。</li> > 743 <li><tt>(rawmacro)</tt> は、 > 744 レイヤ指定式を見ても実行レイヤを切り替えないで構文木にする。</li> > 745 </ul> > 746 <p> > 747 ユーザーから直接 <tt>(rawmacro)</tt> は呼べませんが、 > 748 「関数やトップレベル実行開始前のマクロ処理は <tt>(rawmacro)</tt> で実行開始」 > 749 「<tt>@macro</tt> レイヤ以外で呼び出した関数の仮引数に <tt>@macro</tt> がついていたら、 > 750 その実引数は <tt>(rawmacro)</tt> で実行」 > 751 という2つのタイミングで <tt>(rawmacro)</tt> が動き出します > 752 <tt>(rawmacro)</tt> が <tt>@macro</tt> レイヤから変数を見つけてマロし始める時に、 > 753 そこで <tt>@macro</tt> に動作が移ります。 > 754 </p> > 755 <p> > 756 こうなっているのは、全部がレイヤ指定式に反応する <tt>@macro</tt> の動作だと、 > 757 レイヤを使ったプログラムが全て <tt>@value</tt> 実行時ではなく、 > 758 マクロ展開の時点で動き始めてしまって、おかしなことにるためです。 > 759 色々考えた結果、とりあえずこの中途半端な混合が具合がいのではないかということになりました。 > 760 </p> > 761 </dd> > 762 > 763 <script>explorer.outline.writeEnabled = true;</script> > 764 <dt><span class="decl"> > 765 <span class="currsymbol">微妙なところ2</span> > 766 <script>explorer.outline.addDecl('微妙なところ2');</script> > 767 > 768 </span></dt> > 769 <script>explorer.outline.writeEnabled = false;</script> > 770 > 771 <dd><p> > 772 「関数実行開始時に、まずマクロレイヤを実行」と書きまたが、この時、関数内関数まで辿りにいくので、 > 773 何重にもネストした関数を使っていると、内側の関数は、重にもマクロ展開が走ってしまいます。 > 774 これはなにかおかしい気がしますね。Scheme などはどうなっいるのか調べないと…。 > 775 </p> > 776 </dd> > 777 > 778 <script>explorer.outline.writeEnabled = true;</script> > 779 <dt><span class="decl"> > 780 <span class="currsymbol">微妙なところ3</span> > 781 <script>explorer.outline.addDecl('微妙なところ3');</script> > 782 > 783 </span></dt> > 784 <script>explorer.outline.writeEnabled = false;</script> > 785 > 786 <dd><p> > 787 これはエラーになります。 722 </p> 788 </p> 723 <pre> 789 <pre> 724 <tt>@macro</tt> レイヤと <tt>(rawmacro)</tt> レイヤという二つが協調して動作しています。 | 790 &gt;&gt; let _ = (@macro twice(x) {x;x} in twice(print("Hello"))) 725 (rawmacro) レイヤの話 | 791 polemy.failure.RuntimeException@C:\Develop\Projects\Polemy\polemy\value.d(10 726 < 727 [[limitations]] < 728 < 729 This @macro layer is a very primitive one, and not a perfect macro language. < 730 Two major limitations are seen in the following "it" example. < 731 < 732 &gt;&gt; @macro LetItBe(x, y) { let it = x in y }; < 733 < 734 The variable name is not hygenic, and so without any effort, the syntax tree < 735 can access the outer variable "it". < 736 < 737 &gt;&gt; def foo() { LetItBe( 1+2+3, it*it ) } < 738 &gt;&gt; foo() < 739 36 < 740 < 741 Of course, this is not just a limitation; it can sometimes allow us to write < 742 many interesting macros. < 743 < 744 The other problem is that the macro expansion is only done at function startu < 745 So < 746 < 747 &gt;&gt; LetItBe( 1+2+3, it*it ) < 748 ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value < 749 < 750 you cannot directly use the macro in the same scope as the definition. < 751 You need to wrap it up in a function (like the foo() in the above example). < > 792 [<REPL>:2:35] 'twice' is not set in @value layer 752 </pre> 793 </pre> > 794 <p> > 795 どういうことかというと、<tt>@macro</tt> で定義したマクロはつから使えるようになるかという話で、 > 796 この <tt>@macro twice(x) {x;x} in ...</tt> の部分は <tt>@value</tt> レイヤの式なので、 > 797 まずこの式全体のマクロ展開が終わったあとにしか実行さないのです。<tt>twice</tt> > 798 がマクロと見なされはじめるのは、<tt>@macro</tt> 実行が終わた後。 > 799 なので、 > 800 例えば <tt>twice(print("Hello"))</tt> の部分を無名関数にラップしてやれば、 > 801 マクロ展開を遅らせられて、 ちゃんと実行ができます。 > 802 </p> > 803 <p> > 804 これだと余りにも不便なので、関数のトップレベルの変数言式の列についてだけは、 > 805 <tt>@macro</tt> と <tt>@value</tt> の評価を交互にインターリーブるようにしました。 > 806 「関数やREPLのトップレベルの最初に宣言したマクロだけはその関数内で即座に使える」わけです。 > 807 これも Scheme の let-syntax などなどの動きを調べて勉強しないと…。 > 808 </p> 753 </dd> 809 </dd> 754 </dl> 810 </dl> 755 <script>explorer.outline.decSymbolLevel();</script> 811 <script>explorer.outline.decSymbolLevel();</script> 756 812 757 813 758 </dd> 814 </dd> 759 815 ................................................................................................................................................................................ 877 <script>explorer.outline.decSymbolLevel();</script> 933 <script>explorer.outline.decSymbolLevel();</script> 878 934 879 935 880 </td></tr> 936 </td></tr> 881 <tr><td id="docfooter"> 937 <tr><td id="docfooter"> 882 Page was generated with 938 Page was generated with 883 <img src="candydoc/img/candydoc.gif" style="vertical-ali 939 <img src="candydoc/img/candydoc.gif" style="vertical-ali 884 on Fri Nov 26 16:41:52 2010 | 940 on Sat Nov 27 01:54:49 2010 885 941 886 </td></tr> 942 </td></tr> 887 </table> 943 </table> 888 </div> 944 </div> 889 <script> 945 <script> 890 explorer.packageExplorer.addModule("index"); 946 explorer.packageExplorer.addModule("index"); 891 explorer.packageExplorer.addModule("main"); 947 explorer.packageExplorer.addModule("main");