Differences From Artifact [caf492581281c25d]:
- File
index.dd
- 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 [80b16f2bd31d3d7f]:
- File
index.dd
- 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]
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 + >> @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 + >> @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 + >> @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