Check-in [6de3d8df3a]
Not logged in
Overview
SHA1 Hash:6de3d8df3a653292a7d25814e07c484bd36fec4a
Date: 2010-11-28 00:49:30
User: kinaba
Comment:reference manual completed
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified doc/_common.html from [99ddb75ae65a2432] to [13ff2eea23729a80].

22 22 23 23 The list of modules globaly used inside Polemy.<br><br> 24 24 25 25 </td></tr> 26 26 <tr><td id="docfooter"> 27 27 Page was generated with 28 28 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 29 - on Sat Nov 27 01:17:56 2010 29 + on Sat Nov 27 23:29:16 2010 30 30 31 31 </td></tr> 32 32 </table> 33 33 </div> 34 34 <script> 35 35 explorer.packageExplorer.addModule("index"); 36 36 explorer.packageExplorer.addModule("main");

Modified doc/ast.html from [32b42592d934edb1] to [e8eb3b6cfb2de3ee].

590 590 <script>explorer.outline.decSymbolLevel();</script> 591 591 592 592 593 593 </td></tr> 594 594 <tr><td id="docfooter"> 595 595 Page was generated with 596 596 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 597 - on Sat Nov 27 21:45:06 2010 597 + on Sat Nov 27 23:29:16 2010 598 598 599 599 </td></tr> 600 600 </table> 601 601 </div> 602 602 <script> 603 603 explorer.packageExplorer.addModule("index"); 604 604 explorer.packageExplorer.addModule("main");

Modified doc/eval.html from [e2cd33ac962dedb5] to [5a3818f4c9865916].

128 128 <script>explorer.outline.decSymbolLevel();</script> 129 129 130 130 131 131 </td></tr> 132 132 <tr><td id="docfooter"> 133 133 Page was generated with 134 134 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 135 - on Sat Nov 27 21:45:07 2010 135 + on Sat Nov 27 23:29:17 2010 136 136 137 137 </td></tr> 138 138 </table> 139 139 </div> 140 140 <script> 141 141 explorer.packageExplorer.addModule("index"); 142 142 explorer.packageExplorer.addModule("main");

Modified doc/failure.html from [1a82c4c6591961ce] to [7bfc49a4c88d9174].

178 178 <script>explorer.outline.decSymbolLevel();</script> 179 179 180 180 181 181 </td></tr> 182 182 <tr><td id="docfooter"> 183 183 Page was generated with 184 184 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 185 - on Sat Nov 27 01:17:58 2010 185 + on Sat Nov 27 23:29:18 2010 186 186 187 187 </td></tr> 188 188 </table> 189 189 </div> 190 190 <script> 191 191 explorer.packageExplorer.addModule("index"); 192 192 explorer.packageExplorer.addModule("main");

Modified doc/fresh.html from [dd1d4442ef129d46] to [914f41760cdb79ea].

46 46 <script>explorer.outline.decSymbolLevel();</script> 47 47 48 48 49 49 </td></tr> 50 50 <tr><td id="docfooter"> 51 51 Page was generated with 52 52 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 53 - on Sat Nov 27 01:17:58 2010 53 + on Sat Nov 27 23:29:18 2010 54 54 55 55 </td></tr> 56 56 </table> 57 57 </div> 58 58 <script> 59 59 explorer.packageExplorer.addModule("index"); 60 60 explorer.packageExplorer.addModule("main");

Modified doc/index.html from [7883429c0af25534] to [d0516fddd5213f2d].

417 417 Welcome to Polemy 0.1.0 418 418 &gt;&gt; 1 + 2 419 419 3 420 420 </pre> 421 421 この、普通に、数字の 1 は数字の 1 として、2 は 2 として、足し算は足し算として実行するのが、 422 422 「<tt>@value</tt> レイヤ」です。 423 423 レイヤを明示的に指定するには、<tt>レイヤ名( ... )</tt> という構文を使います。 424 -なので、以下のように書いても同じ意味です。 424 +<font color=red><b>レイヤ指定式</b></font> と読んでいます。 425 +つまり、さっきのコードは以下のようにも書けます。 425 426 <pre> 426 427 &gt;&gt; @value( 1 + 2 ) 427 428 3 428 429 </pre> 429 430 他のレイヤで動かしてみましょう。適当に。「<tt>@hoge</tt> レイヤ」で。 430 431 <pre> 431 432 &gt;&gt; @hoge( 3 ) ................................................................................ 434 435 </pre> 435 436 <p> 436 437 エラーになりました。Polemy のインタプリタは、起動時には、<tt>@value</tt> 437 438 レイヤでのコードの意味しか知りません。<tt>@hoge</tt> レイヤでは <tt>3</tt> 438 439 というのがどんな意味なのか、わかりません!というエラーが出ています。 439 440 </p> 440 441 <p> 441 -これを教えてあげるためには、<tt>@hoge</tt> レイヤの <font color=red><b>リフト関数</b></font> を定義します。 442 +これを教えてあげるためには、<tt>@hoge</tt> レイヤの <font color=red><b>リフト関数</b></font> というものを定義します。 442 443 </p> 443 444 <pre> 444 445 &gt;&gt; @@hoge = fun(x){ x*2 } 445 446 (function:1bdc5c0:1ba8580) 446 447 </pre> 447 448 <p> 448 -「<tt>@ レイヤ名 = ...</tt>」文で、 449 -</p> 450 -<pre> 451 -[Layers :: Overview] 452 - 453 - Polemy's runtime environment has many "layer"s. 454 - Usual execution run in the @value layer. 455 - 456 - &gt;&gt; 1 + 2 457 - 3 458 - &gt;&gt; @value( 1 + 2 ) 459 - 3 460 - 461 - Here you can see that @LayerName( Expression ) executes the inner Expression in 462 - the @LayerName layer. Other than @value, one other predefined layer exists: @macro. 463 - 464 - &gt;&gt; @macro( 1+2 ) 465 - {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 466 - is@value:app, 467 - args@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 468 - is@value:int, 469 - data@value:1}, 470 - cdr@value:{ 471 - car@value:{pos@value:{lineno@value:3, column@value:11, filename@value:<REPL>}, 472 - is@value:int, 473 - data@value:2}, 474 - cdr@value:{}}}, 475 - fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL>}, 476 - is@value:var, 477 - name@value:+}} 478 - 479 - (Sorry, this pretty printing is not available on the actual interpreter...) 480 - This evaluates the expression 1+2 in the @macro layer. In this layer, the meaning of 481 - the program is its abstract syntax tree. 482 - 483 - You can interleave layers. 484 - The root node of the abstract syntax tree is function "app"lication. 485 - 486 - &gt;&gt; @value(@macro( 1+2 ).is) 487 - app 488 - 489 - 490 - 491 -[Layers :: Defining a new layer] 492 - 493 - To define a new layer, you should first tell how to "lift" existing values two the new layer. 494 - Let us define the "@type" layer, where the meaning of programs is their static type. 495 - 496 - &gt;&gt; @@type = fun(x) { 497 - &gt;&gt; if( _isint(x) ) { "int" } else { 498 - &gt;&gt; if( _isfun(x) ) { x } else { "unknown" } } 499 - &gt;&gt; } 500 - (Note: polemy REPL may warn some exception here but please ignore) 501 - 502 - For simplicity, I here deal only with integers. 503 - _isint is a primitive function of Polemy that checks the dynamic type of a value. 504 - For function, leaving it untouched works well for almost all layers. 505 - 449 +<tt>@hoge</tt> レイヤでは、<tt>1</tt> というコードの意味は <tt>2</tt>、 450 +<tt>2</tt> というコードの意味は <tt>4</tt>、…、という、全部「2倍した意味」を持っていることにします。 451 +「<tt>@ レイヤ名 = ...</tt>」 という構文を使います。 452 +ここには、「<tt>@value</tt> レイヤでの値 <tt>x</tt> は <tt>@hoge</tt> レイヤではどういう意味になるか?」 453 +を計算して返す関数を登録します。 454 +これで、Polemy にも、<tt>@hoge</tt> レイヤの意味がわかるようになりました。 455 +</p> 456 +<pre> 457 + &gt;&gt; @hoge( 3 ) 458 + 6 459 +</pre> 460 +<p> 461 +では、1+2 を <tt>@hoge</tt> レイヤで動かしてみましょう。 462 +</p> 463 +<pre> 464 + &gt;&gt; @hoge( 1 + 2 ) 465 + polemy.failure.RuntimeException@C:\Develop\Projects\Polemy\polemy\eval.d(466): 466 + [<REPL>:3:7] only @value layer can call native function: + 467 + [<REPL>:3:7] + 468 +</pre> 469 +<p> 470 +まだエラーですね。これは要するに "+" の意味がわからない、と言っています。 471 +<font color=red><b>レイヤ指定変数定義式</b></font> で、"+" の意味を教えてあげます。 472 +</p> 473 +<pre> 474 + &gt;&gt; @hoge "+" = fun(x, y) {x} 475 + (function:182eca0:18435e0) 476 + &gt;&gt; @hoge( 3 + 4 ) 477 + 6 478 +</pre> 479 +<p> 480 +できました。 481 +</p> 482 +<p> 483 +他の組み込み関数の意味も決めてみましょう。この <tt>@hoge</tt> レイヤでは、 484 +引き算のつもりで書いたコードが、掛け算になってしまうのだ! 485 +</p> 486 +<pre> 487 + &gt;&gt; @hoge "-" = fun(x, y) {x * y} 488 + (function:1b4c6a0:1b4fbe0) 489 + &gt;&gt; @hoge( 5 - 6 ) 490 + polemy.failure.RuntimeException@C:\Develop\Projects\Polemy\polemy\eval.d(469): 491 + [<REPL>:3:24] only @value layer can call native function: * 492 + [<REPL>:3:24] * 493 + [<REPL>:4:8] - 494 +</pre> 495 +<p> 496 +5、の意味は 10 で 6 の意味は 12 なので、10 - 12 と見せかけて掛け算して 120 が返るのだ! 497 +と思いきや、エラーになってしまいました。なぜでしょう。それは、この "-" の定義、 498 +<code>fun(x, y) {x * y}</code> 自体が、<tt>@hoge</tt> レイヤで実行されるからです。 499 +掛け算はまだ定義していません。 500 +</p> 501 +<p> 502 +ここは、「普通の」意味の掛け算を使いたいのです。 503 +この部分については、<tt>@value</tt> レイヤで計算して欲しい。 504 +そんなときは、レイヤ指定式を使います。 505 +</p> 506 +<pre> 507 + &gt;&gt; @hoge "-" = fun(x, y) {<b>@value(@hoge(x) * @hoge(y))</b>} 508 + (function:1b086c0:1b4fbe0) 509 + &gt;&gt; @hoge( 5 - 6 ) 510 + 120 511 +</pre> 512 +<p> 513 +できました。掛け算は、<tt>@value</tt> レイヤの意味で実行します。 514 +各変数は、<tt>@hoge</tt> レイヤで計算された意味を使います、という意味になります。 515 +</p> 516 +</dd> 517 + 518 +<script>explorer.outline.writeEnabled = true;</script> 519 +<dt><span class="decl"> 520 +<span class="currsymbol">関数の自動リフト</span> 521 +<script>explorer.outline.addDecl('関数の自動リフト');</script> 522 + 523 +</span></dt> 524 +<script>explorer.outline.writeEnabled = false;</script> 525 + 526 + <dd><p> 527 +続きです。ちょっと関数を定義してみました。 528 +</p> 529 +<pre> 530 + &gt;&gt; def twoMinus(x,y,z) { x - y - z } 531 + (function:1b26420:1b4fbe0) 532 + &gt;&gt; twoMinus(1,2,3) 533 + -4 534 +</pre> 535 +<p> 536 +<tt>@value</tt> レイヤで実行すると、当然、1 から 2 と 3 を引いて、-4 です。 537 +</p> 538 +<pre> 539 + &gt;&gt; @hoge( twoMinus(1,2,3) ) 540 + 48 541 +</pre> 542 +<p> 543 +<tt>@hoge</tt> レイヤだと、2 と 4 と 6 を掛け算するので、結果は 48 です。 544 +</p> 545 +<p> 546 +1, 2, 3 のような値と、+ や - のような組み込み関数については、 547 +「<tt>@hoge</tt> レイヤでの意味」をレイヤを定義する人が決めてやる必要があります。 548 +でも、それさえ決めれば、あとはプログラム中で自分で定義した関数はすべて、 549 +Polemy 側で自動的にそのレイヤでの意味で実行できるようになります。 550 +</p> 551 +<p> 552 +レイヤ指定変数定義を使って、変数の意味をそのレイヤでだけ上書きして、 553 +違う意味を与えてやっても構いません。 554 +</p> 555 +<pre> 556 + &gt;&gt; def twoMinus(x,y,z) { x - y - z } <font color=green># @value レイヤでの定義</font> 557 + &gt;&gt; @hoge twoMinus(x,y,z) { 21 } <font color=green># @hoge レイヤでの定義</font> 558 + &gt;&gt; twoMinus(1,2,3) 559 + -4 560 + &gt;&gt; @hoge( twoMinus(1,2,3) ) 561 + 42 562 +</pre> 563 +<p> 564 +こんな感じで。 565 +</p> 566 +</dd> 567 + 568 +<script>explorer.outline.writeEnabled = true;</script> 569 +<dt><span class="decl"> 570 +<span class="currsymbol">レイヤ指定引数</span> 571 +<script>explorer.outline.addDecl('レイヤ指定引数');</script> 572 + 573 +</span></dt> 574 +<script>explorer.outline.writeEnabled = false;</script> 575 + 576 + <dd><p> 577 +ここまでのサンプルでは、コードを書いた人が、レイヤ指定式で明示的にレイヤを切り替えていました。 578 +<font color=red><b>レイヤ指定引数</b></font> を使うと、ライブラリ関数などを書くときに、 579 +「この関数の第2引数は <tt>@hoge</tt> レイヤで計算して欲しい」 580 +といった指定ができます。 581 +</p> 582 +<pre> 583 + &gt;&gt; def f(x, y <b>@hoge</b>) { x + @hoge(y) } 584 + &gt;&gt; f(1, 2) 585 + 5 586 +</pre> 587 +<p> 588 +f の第2引数は、必ず <tt>@hoge</tt> レイヤで解釈されます。 589 +</p> 590 +<pre> 591 + &gt;&gt; def ff(x, y <b>@hoge @value</b>) { x + @hoge(y) + @value(y) } 592 + &gt;&gt; ff(1, 2) 593 + 7 594 +</pre> 595 +<p> 596 +<tt>@hoge</tt> と <tt>@value</tt> の両方のレイヤで解釈して欲しい、という欲張りな人は、 597 +レイヤ指定を複数並べて下さい。 598 +</p> 599 +<p> 600 +なにもレイヤ指定がないと、<font color=red><b>ニュートラルレイヤ指定</b></font> と呼ばれ、 601 +その関数の呼び出し側が解釈されていたレイヤと同じところにセットされます。 602 +<tt>let</tt>, <tt>var</tt>, <tt>def</tt> による変数定義も同じで、 603 +<tt>@hoge x = ...</tt> とレイヤを明示するとそのレイヤでの変数の意味が定義されますが、 604 +<tt>let x = ...</tt> とレイヤ指定しないで書くと、現在解釈中のレイヤに定義、という動作をします。 605 +</p> 606 +</dd> 607 + 608 +<script>explorer.outline.writeEnabled = true;</script> 609 +<dt><span class="decl"> 610 +<span class="currsymbol">ボトムと自動メモ化</span> 611 +<script>explorer.outline.addDecl('ボトムと自動メモ化');</script> 612 + 613 +</span></dt> 614 +<script>explorer.outline.writeEnabled = false;</script> 615 + 616 + <dd><p> 617 +パターンマッチ失敗時と、"..." という式を実行したときと、再帰が無限に止まらなくなったとき、 618 +には、Polemy のコードは実行時エラーで終了します……<tt>@value</tt> レイヤならば。 619 +</p> 620 +<p> 621 +ユーザー定義レイヤでは、このような時にも実行時エラーにならず、 622 +「<font color=red><b>ボトム</b></font>」という特別な値がリフト関数に渡されます。 623 +組み込みの <tt>_isbot</tt> 関数で、ボトムかどうか判定できます。 624 +</p> 625 +<p> 626 +「再帰が無限に止まらなくなったとき」は、 627 +ある引数で呼び出された関数が、return するよりも前にまた同じ引数で呼び出されたら、 628 +ループしていると見なすことで判定しています。 629 +これを判定する実装の副作用として、ユーザー定義のレイヤでは、関数は全てメモ化されています。 630 +つまり、ある関数が2回同じ引数同じ環境で呼び出されたら、1回目の答えをキャッシュしておいて、 631 +2回目は計算をせずに即座にキャッシュをひいて答えを返します。 632 +</p> 633 +</dd> 634 + 635 +<script>explorer.outline.writeEnabled = true;</script> 636 +<dt><span class="decl"> 637 +<span class="currsymbol">まとめ</span> 638 +<script>explorer.outline.addDecl('まとめ');</script> 639 + 640 +</span></dt> 641 +<script>explorer.outline.writeEnabled = false;</script> 642 + 643 + <dd><p> 644 +まとめると、以下の機能があります。 645 +</p> 646 +<ul> 647 + <li><tt>@@layer = fun(x) { ... } in ...</tt> で、 648 + <tt>@value</tt> レイヤの値に別のレイヤでの意味を与えるリフト関数を定義</li> 649 + <li><tt>@layer x = ... in ...</tt> で、そのレイヤでのその変数の意味を定義</li> 650 + <li>どちらも let/var/def 式の特殊形なので、<tt>@@layer(x) { ... } in ...</tt> などの略記も可。</li> 651 + <li>式の途中で @layer( ... ) と書くと、レイヤを明示的に切り替えられる</li> 652 + <li>関数の仮引数に fun(x @layer){ ... } とレイヤを指定すると、 653 + 対応する実引数はそのレイヤで解釈される。</li> 654 +</ul> 655 +<p> 656 +</p> 657 +</dd> 658 + 659 +<script>explorer.outline.writeEnabled = true;</script> 660 +<dt><span class="decl"> 661 +<span class="currsymbol">例</span> 662 +<script>explorer.outline.addDecl('例');</script> 663 + 664 +</span></dt> 665 +<script>explorer.outline.writeEnabled = false;</script> 666 + 667 + <dd><p> 668 +具体的な「値」のかわりに、その「メタ情報」を取り出して、それが処理によってどう変化するか、 669 +といった情報を解析するのを主な用途として、この機能を作ってみました。 670 +プログラムでよく使われる代表的なメタ情報は、「型」です。 671 +サンプルとしては、sample/type.pmy をご覧下さい。以下、簡単な概略。 672 +</p> 673 +<pre> 674 + @@type = fun(x) { 675 + if( _isint(x) ) then "int" 676 + else if( _isstr(x) ) then "str" 677 + else if( _isbot(x) ) then "runtime error" 678 + else "type error" 679 + } 680 +</pre> 681 +<pre> 506 682 &gt;&gt; @type( 1 ) 507 683 int 508 684 &gt;&gt; @type( 2 ) 509 685 int 510 686 &gt;&gt; @type( "foo" ) 511 - unknown 512 - 513 - Fine! Let's try to type 1+2. 514 - 515 - &gt;&gt; @type( 1 + 2 ) 516 - ...\value.d(119): [<REPL>:6:8] only @value layer can call native function 517 - 518 - Note that the behavior of this program is 519 - - run 1+2 in the @type layer 520 - and NOT 521 - - run 1+2 in @value and obtain 3 and run 3 in the @type. 522 - The problem is, the variable "+" is defined only in the @value layer. 523 - To carry out computation in the @type layer. We need to define it also 524 - in the @type layer. 525 - 526 - To define some variable in a specific layer, use @LayerName in place of 527 - (let|var|def)s. 528 - 529 - &gt;&gt; let x = 2 530 - &gt;&gt; @value x = 2 531 - &gt;&gt; @type x = "int" 532 - &gt;&gt; @hoge x = "fuga" 533 - 534 - For "+", do it like this. 535 - 536 - &gt;&gt; @type "+" = fun(x,y) {@value( 537 - &gt;&gt; if( @type(x)=="int" &amp;&amp; @type(y)=="int" ) { "int" } else { "typeerror" } 538 - &gt;&gt; )} 539 - polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24 540 - 541 - It is just computing the return type from the input type. 542 - Not here that the intended "meaning" of if-then-else is the runtime-branching, 543 - and the meaning of "==" is the value-comparison. These are the @value layer 544 - behavior. So we have defined the function body inside @value layer. 545 - But when we refer the variables x and y, we need its @type layer meaning. 546 - Hence we use @type() there. 547 - 548 - Now we get it. 549 - 687 + str 688 +</pre> 689 +<p> 690 +こんな風に、値をメタ情報へ抽象化するのが、リフト関数です。 691 +</p> 692 +<p> 693 +型に抽象化したレイヤでの、組み込み関数の意味を考えましょう。 694 +"+" は、"int" と "int" を足したら "int" を返す関数です。 695 +それ以外なら"型エラー"を返します。そういう関数です。 696 +</p> 697 +<pre> 698 + var int_int_int = fun (x, y) {@value( 699 + var tx = @type(x); 700 + var ty = @type(y); 701 + if tx=="runtime error" then ty 702 + else if ty=="runtime error" then tx 703 + else if tx=="int" &amp;&amp; ty=="int" then "int" 704 + else "type error" 705 + )}; 706 + 707 + @type "+" = int_int_int; 708 + @type "-" = int_int_int; 709 + @type "&lt;" = int_int_int; 710 +</pre> 711 +<pre> 550 712 &gt;&gt; @type( 1 + 2 ) 551 713 int 552 - 553 - Well, but do we have to define the @type layer meaning for every variables??? 554 - No. After you defined @type "+", you'll automatically get the following: 555 - 556 - &gt;&gt; def double(x) { x + x } 557 - (function:17e4740:1789720) 558 - 559 - &gt;&gt; @type( double(123) ) 560 - int 561 - 562 - Every user-defined functions are automatically "lift"ed to the appropriate layer. 563 - Only primitive functions like "+" requires @yourNewLayer annotation. 564 - 565 - 566 - 567 -[Layers :: neutral-layer] 568 - 569 - let|var|def is to define a variable in the "current" layer. 570 - Not necessary to the @value layer. 571 - 572 - &gt;&gt; @value( let x = 1 in @value(x) ) 573 - 1 574 - 575 - &gt;&gt; @macro( let x = 1 in @value(x) ) 576 - polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found 577 - 578 - &gt;&gt; @macro( let x = 1 in @macro(x) ) 579 - {pos@value:{lineno@value:15, ... 580 - 581 - 582 - 583 -[Layers :: Layered-Parameters] 584 - 585 - &gt;&gt; def foo(x @macro @value) { {fst: x, snd: @macro(x)} } 586 - (function:1730360:1789720) 587 - 588 - If you annotate function parameters by @LayerNames, when you invoke the function... 589 - 590 - &gt;&gt; foo(1+2) 591 - {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REPL>}, 592 - is@value:app, arg@value:{... 593 - /fst@value:3 594 - /} 595 - 596 - its corresponding arguments are evaluated in the layer and passed to it. 597 - If you specify multiple layers, the argument expression is run multiple times. 598 - If you do not specify any layer for a parameter, it works in the neutral layer. 714 + &gt;&gt; @type( 1 + "foo" ) 715 + type error 716 +</pre> 717 +<p> 718 +「実行時エラーについては、それが起きなければ返すはずの型」を計算するという定義に、 719 +ここではしています。さらに(ちょっと手抜きで int 以外を考えていない)if の型定義を考えると、 720 +こんな雰囲気。 721 +</p> 722 +<pre> 723 + @type "if" (c, t, e) {@value( 724 + if( @type(c)=="int" || @type(c)=="runtime error" ) then 725 + @type( int_int_int(t(), e()) ) 726 + else 727 + "type error" 728 + )} 729 +</pre> 730 +<p> 731 +関数が自動リフトされるので、フィボナッチ関数の型を調べることができます。 732 +</p> 733 +<pre> 734 + &gt;&gt; def fib(x) { if x&lt;2 then 1 else fib(x-1)+fib(x-2) }; 735 + &gt;&gt; @type( fib(100000000000000) ) 736 + int 737 + &gt;&gt; def gib(x) { if x&lt;2 then 1 else gib(x-1)+gib(x-"str") }; 738 + &gt;&gt; @type( gib(100000000000000) ) 739 + type error 740 +</pre> 741 +<p> 742 +この定義で <tt>fib(100000000000000)</tt> を <tt>@value</tt> レイヤで普通に計算して、 743 +結果の型を見る、というのでは時間がいくらあっても足りません。 744 +いったん <tt>@type</tt> のメタ情報の世界に移ってから計算できるのが、レイヤ機能の肝です。 745 +</p> 746 +<p> 747 +正確には、この定義で <tt>@type</tt> レイヤに移ると fib("int") を無限に呼び出し続けて止まらなくなるのですが、 748 +そこは、自動メモ化による再帰検出でボトム値を返す機能によって、うまく止まっています。 749 +</p> 750 +<p> 751 +それでも上手く型計算ができない(あるいはすごく遅くなる)ような複雑な関数があるかもしれません。 752 +仕方がないので、型情報をアノテーションとしてつけてあげることも可能です。 753 +</p> 754 +<pre> 755 + @type f = int_int_int; 756 + def f(x,y) { ...とても型を計算できないくらい複雑な定義... }; 599 757 </pre> 758 +<p> 759 +これが、レイヤ指定変数定義の典型的な使い道です。 760 +</p> 600 761 </dd> 601 762 </dl> 602 763 <script>explorer.outline.decSymbolLevel();</script> 603 764 604 765 605 766 </dd> 606 767 ................................................................................ 617 778 <dd><p> 618 779 Polemy 言語組み込みのレイヤは <code>@value</code> と <code>@macro</code> の二つです。 619 780 (内部的にはもういくつかありますが、ユーザから直接は使えません。) 620 781 <code>@value</code> は、「普通に」普通のセマンティクスでプログラムを実行するレイヤでした。 621 782 <code>@macro</code> は、実は、<code>@value</code> よりも前に実行されるレイヤで、 622 783 「プログラムを実行するとその構文木を返す」というセマンティクスで動きます。 623 784 </p> 624 -<pre> 625 - (ここに例) 626 -</pre> 627 785 <p> 628 786 動きとしてはこうです。 629 787 </p> 630 788 <ol> 631 789 <li>関数呼び出し時(とトップレベル環境の実行開始時)に、 632 790 まず、<code>@macro</code> レイヤでコードを実行。</li> 633 791 <li>返ってきた構文木を、その関数を呼び出したときのレイヤで実行。</li> ................................................................................ 976 1134 977 1135 </span></dt> 978 1136 <script>explorer.outline.writeEnabled = false;</script> 979 1137 980 1138 <dd> <table> <tr><th>_isint</th> <td>(a)</td> <td>a が整数なら 1、でなければ 0</td></tr> 981 1139 <tr><th>_isstr</th> <td>(a)</td> <td>a が文字列なら 1、でなければ 0</td></tr> 982 1140 <tr><th>_isfun</th> <td>(a)</td> <td>a が関数なら 1、でなければ 0</td></tr> 983 - <tr><th>_istable</th> <td>(a)</td> <td>a がテーブルなら 1、でなければ 0</td></tr> 984 - <tr><th>_isundefined</th> <td>(a)</td> <td>a が未定義値なら 1、でなければ 0</td></tr> 1141 + <tr><th>_istbl</th> <td>(a)</td> <td>a がテーブルなら 1、でなければ 0</td></tr> 1142 + <tr><th>_isbot</th> <td>(a)</td> <td>a が未定義値なら 1、でなければ 0</td></tr> 985 1143 </table> 986 1144 </dd> 987 1145 </dl> 988 1146 <script>explorer.outline.decSymbolLevel();</script> 989 1147 990 1148 991 1149 </dd> ................................................................................ 994 1152 <script>explorer.outline.decSymbolLevel();</script> 995 1153 996 1154 997 1155 </td></tr> 998 1156 <tr><td id="docfooter"> 999 1157 Page was generated with 1000 1158 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 1001 - on Sat Nov 27 22:01:28 2010 1159 + on Sun Nov 28 00:45:59 2010 1002 1160 1003 1161 </td></tr> 1004 1162 </table> 1005 1163 </div> 1006 1164 <script> 1007 1165 explorer.packageExplorer.addModule("index"); 1008 1166 explorer.packageExplorer.addModule("main");

Modified doc/layer.html from [136da3cf5e90765a] to [e5a65b9174accb2e].

163 163 <script>explorer.outline.decSymbolLevel();</script> 164 164 165 165 166 166 </td></tr> 167 167 <tr><td id="docfooter"> 168 168 Page was generated with 169 169 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 170 - on Sat Nov 27 01:17:58 2010 170 + on Sat Nov 27 23:29:19 2010 171 171 172 172 </td></tr> 173 173 </table> 174 174 </div> 175 175 <script> 176 176 explorer.packageExplorer.addModule("index"); 177 177 explorer.packageExplorer.addModule("main");

Modified doc/lex.html from [4b49ee7344141eea] to [c0949ad2b1503d71].

307 307 <script>explorer.outline.decSymbolLevel();</script> 308 308 309 309 310 310 </td></tr> 311 311 <tr><td id="docfooter"> 312 312 Page was generated with 313 313 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 314 - on Sat Nov 27 01:17:59 2010 314 + on Sat Nov 27 23:29:19 2010 315 315 316 316 </td></tr> 317 317 </table> 318 318 </div> 319 319 <script> 320 320 explorer.packageExplorer.addModule("index"); 321 321 explorer.packageExplorer.addModule("main");

Modified doc/main.html from [0482b340bcdb09a1] to [b09ee9883ce14297].

62 62 <script>explorer.outline.decSymbolLevel();</script> 63 63 64 64 65 65 </td></tr> 66 66 <tr><td id="docfooter"> 67 67 Page was generated with 68 68 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 69 - on Sat Nov 27 01:17:56 2010 69 + on Sat Nov 27 23:29:15 2010 70 70 71 71 </td></tr> 72 72 </table> 73 73 </div> 74 74 <script> 75 75 explorer.packageExplorer.addModule("index"); 76 76 explorer.packageExplorer.addModule("main");

Modified doc/parse.html from [b7809106bd8bbf5f] to [71836dac82f5012f].

56 56 <script>explorer.outline.decSymbolLevel();</script> 57 57 58 58 59 59 </td></tr> 60 60 <tr><td id="docfooter"> 61 61 Page was generated with 62 62 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 63 - on Sat Nov 27 01:17:59 2010 63 + on Sat Nov 27 23:29:20 2010 64 64 65 65 </td></tr> 66 66 </table> 67 67 </div> 68 68 <script> 69 69 explorer.packageExplorer.addModule("index"); 70 70 explorer.packageExplorer.addModule("main");

Modified doc/repl.html from [06b9b45e10860394] to [e0eba4db02a405ab].

156 156 <script>explorer.outline.decSymbolLevel();</script> 157 157 158 158 159 159 </td></tr> 160 160 <tr><td id="docfooter"> 161 161 Page was generated with 162 162 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 163 - on Sat Nov 27 01:18:00 2010 163 + on Sat Nov 27 23:29:21 2010 164 164 165 165 </td></tr> 166 166 </table> 167 167 </div> 168 168 <script> 169 169 explorer.packageExplorer.addModule("index"); 170 170 explorer.packageExplorer.addModule("main");

Modified doc/runtime.html from [05c59f5e4897aa6d] to [91406278395708ce].

42 42 <script>explorer.outline.decSymbolLevel();</script> 43 43 44 44 45 45 </td></tr> 46 46 <tr><td id="docfooter"> 47 47 Page was generated with 48 48 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 49 - on Sat Nov 27 01:18:00 2010 49 + on Sat Nov 27 23:29:21 2010 50 50 51 51 </td></tr> 52 52 </table> 53 53 </div> 54 54 <script> 55 55 explorer.packageExplorer.addModule("index"); 56 56 explorer.packageExplorer.addModule("main");

Modified doc/test.html from [2826fbbbd41fd9fd] to [657ae4105e994a9f].

143 143 <script>explorer.outline.decSymbolLevel();</script> 144 144 145 145 146 146 </td></tr> 147 147 <tr><td id="docfooter"> 148 148 Page was generated with 149 149 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 150 - on Sat Nov 27 01:18:02 2010 150 + on Sat Nov 27 23:29:23 2010 151 151 152 152 </td></tr> 153 153 </table> 154 154 </div> 155 155 <script> 156 156 explorer.packageExplorer.addModule("index"); 157 157 explorer.packageExplorer.addModule("main");

Modified doc/tricks.html from [3a211e8310f22d0a] to [45f9b815486b21bd].

246 246 <script>explorer.outline.decSymbolLevel();</script> 247 247 248 248 249 249 </td></tr> 250 250 <tr><td id="docfooter"> 251 251 Page was generated with 252 252 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 253 - on Sat Nov 27 01:18:02 2010 253 + on Sat Nov 27 23:29:24 2010 254 254 255 255 </td></tr> 256 256 </table> 257 257 </div> 258 258 <script> 259 259 explorer.packageExplorer.addModule("index"); 260 260 explorer.packageExplorer.addModule("main");

Modified doc/value.html from [56bfccf06cb302b1] to [cf9c33eb37eaba08].

259 259 <script>explorer.outline.decSymbolLevel();</script> 260 260 261 261 262 262 </td></tr> 263 263 <tr><td id="docfooter"> 264 264 Page was generated with 265 265 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 266 - on Sat Nov 27 01:18:01 2010 266 + on Sat Nov 27 23:29:22 2010 267 267 268 268 </td></tr> 269 269 </table> 270 270 </div> 271 271 <script> 272 272 explorer.packageExplorer.addModule("index"); 273 273 explorer.packageExplorer.addModule("main");

Modified doc/valueconv.html from [d3b97793d6c2afdf] to [13cec2ea0c3e7792].

98 98 <script>explorer.outline.decSymbolLevel();</script> 99 99 100 100 101 101 </td></tr> 102 102 <tr><td id="docfooter"> 103 103 Page was generated with 104 104 <img src="candydoc/img/candydoc.gif" style="vertical-align:middle; position:relative; top:-1px"> 105 - on Sat Nov 27 01:18:01 2010 105 + on Sat Nov 27 23:29:23 2010 106 106 107 107 </td></tr> 108 108 </table> 109 109 </div> 110 110 <script> 111 111 explorer.packageExplorer.addModule("index"); 112 112 explorer.packageExplorer.addModule("main");

Modified index.dd from [388d91fa67a7c403] to [33d07971634f6989].

350 350 <pre> 351 351 &gt;&gt; @hoge( 1 + 2 ) 352 352 polemy.failure.RuntimeException@C:\Develop\Projects\Polemy\polemy\eval.d(466): 353 353 [<REPL>:3:7] only @value layer can call native function: + 354 354 [<REPL>:3:7] + 355 355 </pre> 356 356 <p> 357 -まだエラーですね。これは 実は、リフト関数は 357 +まだエラーですね。これは要するに "+" の意味がわからない、と言っています。 358 +$(RED $(B レイヤ指定変数定義式)) で、"+" の意味を教えてあげます。 358 359 </p> 359 360 <pre> 360 361 &gt;&gt; @hoge "+" = fun(x, y) {x} 361 -</pre> 362 -<pre> 363 -[Layers :: Overview] 364 - 365 - Polemy's runtime environment has many "layer"s. 366 - Usual execution run in the @value layer. 367 - 368 - >> 1 + 2 369 - 3 370 - >> @value( 1 + 2 ) 371 - 3 372 - 373 - Here you can see that @LayerName( Expression ) executes the inner Expression in 374 - the @LayerName layer. Other than @value, one other predefined layer exists: @macro. 375 - 376 - >> @macro( 1+2 ) 377 - {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 378 - is@value:app, 379 - args@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 380 - is@value:int, 381 - data@value:1}, 382 - cdr@value:{ 383 - car@value:{pos@value:{lineno@value:3, column@value:11, filename@value:<REPL>}, 384 - is@value:int, 385 - data@value:2}, 386 - cdr@value:{}}}, 387 - fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL>}, 388 - is@value:var, 389 - name@value:+}} 390 - 391 - (Sorry, this pretty printing is not available on the actual interpreter...) 392 - This evaluates the expression 1+2 in the @macro layer. In this layer, the meaning of 393 - the program is its abstract syntax tree. 394 - 395 - You can interleave layers. 396 - The root node of the abstract syntax tree is function "app"lication. 397 - 398 - >> @value(@macro( 1+2 ).is) 399 - app 400 - 401 - 402 - 403 -[Layers :: Defining a new layer] 404 - 405 - To define a new layer, you should first tell how to "lift" existing values two the new layer. 406 - Let us define the "@type" layer, where the meaning of programs is their static type. 407 - 408 - >> @@type = fun(x) { 409 - >> if( _isint(x) ) { "int" } else { 410 - >> if( _isfun(x) ) { x } else { "unknown" } } 411 - >> } 412 - (Note: polemy REPL may warn some exception here but please ignore) 413 - 414 - For simplicity, I here deal only with integers. 415 - _isint is a primitive function of Polemy that checks the dynamic type of a value. 416 - For function, leaving it untouched works well for almost all layers. 417 - 418 - >> @type( 1 ) 362 + (function:182eca0:18435e0) 363 + &gt;&gt; @hoge( 3 + 4 ) 364 + 6 365 +</pre> 366 +<p> 367 +できました。 368 +</p> 369 +<p> 370 +他の組み込み関数の意味も決めてみましょう。この <tt>@hoge</tt> レイヤでは、 371 +引き算のつもりで書いたコードが、掛け算になってしまうのだ! 372 +</p> 373 +<pre> 374 + &gt;&gt; @hoge "-" = fun(x, y) {x * y} 375 + (function:1b4c6a0:1b4fbe0) 376 + &gt;&gt; @hoge( 5 - 6 ) 377 + polemy.failure.RuntimeException@C:\Develop\Projects\Polemy\polemy\eval.d(469): 378 + [<REPL>:3:24] only @value layer can call native function: * 379 + [<REPL>:3:24] * 380 + [<REPL>:4:8] - 381 +</pre> 382 +<p> 383 +5、の意味は 10 で 6 の意味は 12 なので、10 - 12 と見せかけて掛け算して 120 が返るのだ! 384 +と思いきや、エラーになってしまいました。なぜでしょう。それは、この "-" の定義、 385 +<code>fun(x, y) {x * y}</code> 自体が、<tt>@hoge</tt> レイヤで実行されるからです。 386 +掛け算はまだ定義していません。 387 +</p> 388 +<p> 389 +ここは、「普通の」意味の掛け算を使いたいのです。 390 +この部分については、<tt>@value</tt> レイヤで計算して欲しい。 391 +そんなときは、レイヤ指定式を使います。 392 +</p> 393 +<pre> 394 + &gt;&gt; @hoge "-" = fun(x, y) {$(B @value(@hoge(x) * @hoge(y)))} 395 + (function:1b086c0:1b4fbe0) 396 + &gt;&gt; @hoge( 5 - 6 ) 397 + 120 398 +</pre> 399 +<p> 400 +できました。掛け算は、<tt>@value</tt> レイヤの意味で実行します。 401 +各変数は、<tt>@hoge</tt> レイヤで計算された意味を使います、という意味になります。 402 +</p> 403 +)) 404 +$(SECTION 関数の自動リフト, $(SECBODY 405 +<p> 406 +続きです。ちょっと関数を定義してみました。 407 +</p> 408 +<pre> 409 + &gt;&gt; def twoMinus(x,y,z) { x - y - z } 410 + (function:1b26420:1b4fbe0) 411 + &gt;&gt; twoMinus(1,2,3) 412 + -4 413 +</pre> 414 +<p> 415 +<tt>@value</tt> レイヤで実行すると、当然、1 から 2 と 3 を引いて、-4 です。 416 +</p> 417 +<pre> 418 + &gt;&gt; @hoge( twoMinus(1,2,3) ) 419 + 48 420 +</pre> 421 +<p> 422 +<tt>@hoge</tt> レイヤだと、2 と 4 と 6 を掛け算するので、結果は 48 です。 423 +</p> 424 +<p> 425 +1, 2, 3 のような値と、+ や - のような組み込み関数については、 426 +「<tt>@hoge</tt> レイヤでの意味」をレイヤを定義する人が決めてやる必要があります。 427 +でも、それさえ決めれば、あとはプログラム中で自分で定義した関数はすべて、 428 +Polemy 側で自動的にそのレイヤでの意味で実行できるようになります。 429 +</p> 430 +<p> 431 +レイヤ指定変数定義を使って、変数の意味をそのレイヤでだけ上書きして、 432 +違う意味を与えてやっても構いません。 433 +</p> 434 +<pre> 435 + &gt;&gt; def twoMinus(x,y,z) { x - y - z } $(D_COMMENT # @value レイヤでの定義) 436 + &gt;&gt; @hoge twoMinus(x,y,z) { 21 } $(D_COMMENT # @hoge レイヤでの定義) 437 + &gt;&gt; twoMinus(1,2,3) 438 + -4 439 + &gt;&gt; @hoge( twoMinus(1,2,3) ) 440 + 42 441 +</pre> 442 +<p> 443 +こんな感じで。 444 +</p> 445 +)) 446 +$(SECTION レイヤ指定引数, $(SECBODY 447 +<p> 448 +ここまでのサンプルでは、コードを書いた人が、レイヤ指定式で明示的にレイヤを切り替えていました。 449 +$(RED $(B レイヤ指定引数)) を使うと、ライブラリ関数などを書くときに、 450 +「この関数の第2引数は <tt>@hoge</tt> レイヤで計算して欲しい」 451 +といった指定ができます。 452 +</p> 453 +<pre> 454 + &gt;&gt; def f(x, y $(B @hoge)) { x + @hoge(y) } 455 + &gt;&gt; f(1, 2) 456 + 5 457 +</pre> 458 +<p> 459 +f の第2引数は、必ず <tt>@hoge</tt> レイヤで解釈されます。 460 +</p> 461 +<pre> 462 + &gt;&gt; def ff(x, y $(B @hoge @value)) { x + @hoge(y) + @value(y) } 463 + &gt;&gt; ff(1, 2) 464 + 7 465 +</pre> 466 +<p> 467 +<tt>@hoge</tt> と <tt>@value</tt> の両方のレイヤで解釈して欲しい、という欲張りな人は、 468 +レイヤ指定を複数並べて下さい。 469 +</p> 470 +<p> 471 +なにもレイヤ指定がないと、$(RED $(B ニュートラルレイヤ指定)) と呼ばれ、 472 +その関数の呼び出し側が解釈されていたレイヤと同じところにセットされます。 473 +<tt>let</tt>, <tt>var</tt>, <tt>def</tt> による変数定義も同じで、 474 +<tt>@hoge x = ...</tt> とレイヤを明示するとそのレイヤでの変数の意味が定義されますが、 475 +<tt>let x = ...</tt> とレイヤ指定しないで書くと、現在解釈中のレイヤに定義、という動作をします。 476 +</p> 477 +)) 478 +$(SECTION ボトムと自動メモ化, $(SECBODY 479 +<p> 480 +パターンマッチ失敗時と、"..." という式を実行したときと、再帰が無限に止まらなくなったとき、 481 +には、Polemy のコードは実行時エラーで終了します……<tt>@value</tt> レイヤならば。 482 +</p> 483 +<p> 484 +ユーザー定義レイヤでは、このような時にも実行時エラーにならず、 485 +「$(RED $(B ボトム))」という特別な値がリフト関数に渡されます。 486 +組み込みの <tt>_isbot</tt> 関数で、ボトムかどうか判定できます。 487 +</p> 488 +<p> 489 +「再帰が無限に止まらなくなったとき」は、 490 +ある引数で呼び出された関数が、return するよりも前にまた同じ引数で呼び出されたら、 491 +ループしていると見なすことで判定しています。 492 +これを判定する実装の副作用として、ユーザー定義のレイヤでは、関数は全てメモ化されています。 493 +つまり、ある関数が2回同じ引数同じ環境で呼び出されたら、1回目の答えをキャッシュしておいて、 494 +2回目は計算をせずに即座にキャッシュをひいて答えを返します。 495 +</p> 496 +)) 497 +$(SECTION まとめ, $(SECBODY 498 +<p> 499 +まとめると、以下の機能があります。 500 +</p> 501 +<ul> 502 + <li><tt>@@layer = fun(x) { ... } in ...</tt> で、 503 + <tt>@value</tt> レイヤの値に別のレイヤでの意味を与えるリフト関数を定義</li> 504 + <li><tt>@layer x = ... in ...</tt> で、そのレイヤでのその変数の意味を定義</li> 505 + <li>どちらも let/var/def 式の特殊形なので、<tt>@@layer(x) { ... } in ...</tt> などの略記も可。</li> 506 + <li>式の途中で @layer( ... ) と書くと、レイヤを明示的に切り替えられる</li> 507 + <li>関数の仮引数に fun(x @layer){ ... } とレイヤを指定すると、 508 + 対応する実引数はそのレイヤで解釈される。</li> 509 +</ul> 510 +<p> 511 +</p> 512 +)) 513 +$(SECTION 例, $(SECBODY 514 +<p> 515 +具体的な「値」のかわりに、その「メタ情報」を取り出して、それが処理によってどう変化するか、 516 +といった情報を解析するのを主な用途として、この機能を作ってみました。 517 +プログラムでよく使われる代表的なメタ情報は、「型」です。 518 +サンプルとしては、sample/type.pmy をご覧下さい。以下、簡単な概略。 519 +</p> 520 +<pre> 521 + @@type = fun(x) { 522 + if( _isint(x) ) then "int" 523 + else if( _isstr(x) ) then "str" 524 + else if( _isbot(x) ) then "runtime error" 525 + else "type error" 526 + } 527 +</pre> 528 +<pre> 529 + &gt;&gt; @type( 1 ) 419 530 int 420 - >> @type( 2 ) 531 + &gt;&gt; @type( 2 ) 421 532 int 422 - >> @type( "foo" ) 423 - unknown 424 - 425 - Fine! Let's try to type 1+2. 426 - 427 - >> @type( 1 + 2 ) 428 - ...\value.d(119): [<REPL>:6:8] only @value layer can call native function 429 - 430 - Note that the behavior of this program is 431 - - run 1+2 in the @type layer 432 - and NOT 433 - - run 1+2 in @value and obtain 3 and run 3 in the @type. 434 - The problem is, the variable "+" is defined only in the @value layer. 435 - To carry out computation in the @type layer. We need to define it also 436 - in the @type layer. 533 + &gt;&gt; @type( "foo" ) 534 + str 535 +</pre> 536 +<p> 537 +こんな風に、値をメタ情報へ抽象化するのが、リフト関数です。 538 +</p> 539 +<p> 540 +型に抽象化したレイヤでの、組み込み関数の意味を考えましょう。 541 +"+" は、"int" と "int" を足したら "int" を返す関数です。 542 +それ以外なら"型エラー"を返します。そういう関数です。 543 +</p> 544 +<pre> 545 + var int_int_int = fun (x, y) {@value( 546 + var tx = @type(x); 547 + var ty = @type(y); 548 + if tx=="runtime error" then ty 549 + else if ty=="runtime error" then tx 550 + else if tx=="int" && ty=="int" then "int" 551 + else "type error" 552 + )}; 437 553 438 - To define some variable in a specific layer, use @LayerName in place of 439 - (let|var|def)s. 440 - 441 - >> let x = 2 442 - >> @value x = 2 443 - >> @type x = "int" 444 - >> @hoge x = "fuga" 445 - 446 - For "+", do it like this. 447 - 448 - >> @type "+" = fun(x,y) {@value( 449 - >> if( @type(x)=="int" && @type(y)=="int" ) { "int" } else { "typeerror" } 450 - >> )} 451 - polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24 452 - 453 - It is just computing the return type from the input type. 454 - Not here that the intended "meaning" of if-then-else is the runtime-branching, 455 - and the meaning of "==" is the value-comparison. These are the @value layer 456 - behavior. So we have defined the function body inside @value layer. 457 - But when we refer the variables x and y, we need its @type layer meaning. 458 - Hence we use @type() there. 459 - 460 - Now we get it. 461 - 462 - >> @type( 1 + 2 ) 554 + @type "+" = int_int_int; 555 + @type "-" = int_int_int; 556 + @type "<" = int_int_int; 557 +</pre> 558 +<pre> 559 + &gt;&gt; @type( 1 + 2 ) 463 560 int 464 - 465 - Well, but do we have to define the @type layer meaning for every variables??? 466 - No. After you defined @type "+", you'll automatically get the following: 467 - 468 - >> def double(x) { x + x } 469 - (function:17e4740:1789720) 470 - 471 - >> @type( double(123) ) 472 - int 473 - 474 - Every user-defined functions are automatically "lift"ed to the appropriate layer. 475 - Only primitive functions like "+" requires @yourNewLayer annotation. 476 - 477 - 478 - 479 -[Layers :: neutral-layer] 480 - 481 - let|var|def is to define a variable in the "current" layer. 482 - Not necessary to the @value layer. 483 - 484 - >> @value( let x = 1 in @value(x) ) 485 - 1 486 - 487 - >> @macro( let x = 1 in @value(x) ) 488 - polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found 489 - 490 - >> @macro( let x = 1 in @macro(x) ) 491 - {pos@value:{lineno@value:15, ... 492 - 493 - 494 - 495 -[Layers :: Layered-Parameters] 496 - 497 - >> def foo(x @macro @value) { {fst: x, snd: @macro(x)} } 498 - (function:1730360:1789720) 499 - 500 - If you annotate function parameters by @LayerNames, when you invoke the function... 501 - 502 - >> foo(1+2) 503 - {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REPL>}, 504 - is@value:app, arg@value:{... 505 - /fst@value:3 506 - /} 507 - 508 - its corresponding arguments are evaluated in the layer and passed to it. 509 - If you specify multiple layers, the argument expression is run multiple times. 510 - If you do not specify any layer for a parameter, it works in the neutral layer. 561 + &gt;&gt; @type( 1 + "foo" ) 562 + type error 563 +</pre> 564 +<p> 565 +「実行時エラーについては、それが起きなければ返すはずの型」を計算するという定義に、 566 +ここではしています。さらに(ちょっと手抜きで int 以外を考えていない)if の型定義を考えると、 567 +こんな雰囲気。 568 +</p> 569 +<pre> 570 + @type "if" (c, t, e) {@value( 571 + if( @type(c)=="int" || @type(c)=="runtime error" ) then 572 + @type( int_int_int(t(), e()) ) 573 + else 574 + "type error" 575 + )} 576 +</pre> 577 +<p> 578 +関数が自動リフトされるので、フィボナッチ関数の型を調べることができます。 579 +</p> 580 +<pre> 581 + &gt;&gt; def fib(x) { if x<2 then 1 else fib(x-1)+fib(x-2) }; 582 + &gt;&gt; @type( fib(100000000000000) ) 583 + int 584 + &gt;&gt; def gib(x) { if x<2 then 1 else gib(x-1)+gib(x-"str") }; 585 + &gt;&gt; @type( gib(100000000000000) ) 586 + type error 587 +</pre> 588 +<p> 589 +この定義で <tt>fib(100000000000000)</tt> を <tt>@value</tt> レイヤで普通に計算して、 590 +結果の型を見る、というのでは時間がいくらあっても足りません。 591 +いったん <tt>@type</tt> のメタ情報の世界に移ってから計算できるのが、レイヤ機能の肝です。 592 +</p> 593 +<p> 594 +正確には、この定義で <tt>@type</tt> レイヤに移ると fib("int") を無限に呼び出し続けて止まらなくなるのですが、 595 +そこは、自動メモ化による再帰検出でボトム値を返す機能によって、うまく止まっています。 596 +</p> 597 +<p> 598 +それでも上手く型計算ができない(あるいはすごく遅くなる)ような複雑な関数があるかもしれません。 599 +仕方がないので、型情報をアノテーションとしてつけてあげることも可能です。 600 +</p> 601 +<pre> 602 + @type f = int_int_int; 603 + def f(x,y) { ...とても型を計算できないくらい複雑な定義... }; 511 604 </pre> 605 +<p> 606 +これが、レイヤ指定変数定義の典型的な使い道です。 607 +</p> 512 608 )) 513 609 ) 514 610 )) 515 611 516 612 517 613 $(SECTION Macro Layers, $(SECBODY 518 614 <p> 519 615 Polemy 言語組み込みのレイヤは <code>@value</code> と <code>@macro</code> の二つです。 520 616 (内部的にはもういくつかありますが、ユーザから直接は使えません。) 521 617 <code>@value</code> は、「普通に」普通のセマンティクスでプログラムを実行するレイヤでした。 522 618 <code>@macro</code> は、実は、<code>@value</code> よりも前に実行されるレイヤで、 523 619 「プログラムを実行するとその構文木を返す」というセマンティクスで動きます。 524 620 </p> 525 -<pre> 526 - (ここに例) 527 -</pre> 528 621 <p> 529 622 動きとしてはこうです。 530 623 </p> 531 624 <ol> 532 625 <li>関数呼び出し時(とトップレベル環境の実行開始時)に、 533 626 まず、<code>@macro</code> レイヤでコードを実行。</li> 534 627 <li>返ってきた構文木を、その関数を呼び出したときのレイヤで実行。</li>