File Annotation
Not logged in
20be503cae 2010-11-24        kinaba: Ddoc
20be503cae 2010-11-24        kinaba: $(DDOC_AUTHORS k.inaba)
20be503cae 2010-11-24        kinaba: $(DDOC_LICENSE NYSL 0.9982 (http://www.kmonos.net/nysl/))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: このファイルは、言語仕様などの簡単な説明です。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: あとついでに、左のサイドバーの "Package" タブをクリックすると実装のソースのドキュメントが読めます。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(DDOC_MEMBERS
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION Syntax, $(SECBODY
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 文法について。
20be503cae 2010-11-24        kinaba: 字句解析がわりと適当なので、
20be503cae 2010-11-24        kinaba: 変数宣言の変数名のところに、数字を変数名として使えて参照できない変数が作れたり、
20be503cae 2010-11-24        kinaba: 予約語は予約語として解釈され得ないところでは普通に変数名として使えちゃったりして、
20be503cae 2010-11-24        kinaba: 偶にとんでもない見かけのソースが構文解析通りますが、気にしないで適当に使って下さい。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(DDOC_MEMBERS
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION 文字コード, $(SECBODY
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: UTF-8 のみ対応です。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION コメント, $(SECBODY
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 行コメントは <tt>#</tt> から改行までです。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: ブロックコメントはありません。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION BNF, $(SECBODY
20be503cae 2010-11-24        kinaba: <pre>
20be503cae 2010-11-24        kinaba:  ID    ::= 適当に識別子っぽい文字列
20be503cae 2010-11-24        kinaba:  LAYER ::= "@" ID
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:  E ::=
20be503cae 2010-11-24        kinaba:    $(D_COMMENT # 変数宣言)
f7e9e77316 2010-11-26        kinaba:      | DECL "=" E (";"|"in") E
f7e9e77316 2010-11-26        kinaba:      | DECL "(" PARAMS ")" "{" E "}" (";"|"in") E
f7e9e77316 2010-11-26        kinaba:      | DECL "=" E
f7e9e77316 2010-11-26        kinaba:      | DECL "(" PARAMS ")" "{" E "}"
f7e9e77316 2010-11-26        kinaba: 
f7e9e77316 2010-11-26        kinaba:          where DECL ::= ("var"|"let"|"def"|LAYER) ID | "@" LAYER
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    $(D_COMMENT # リテラル)
20be503cae 2010-11-24        kinaba:      | INTEGER                        $(D_COMMENT # 非負整数)
20be503cae 2010-11-24        kinaba:      | STRING                         $(D_COMMENT # "" でくくった文字列。\" と \\ は使える)
20be503cae 2010-11-24        kinaba:      | "{" ENTRYS "}"                 $(D_COMMENT # テーブル)
20be503cae 2010-11-24        kinaba:      | "fun" "(" PARAMS ")" "{" E "}" $(D_COMMENT # 無名関数)
20be503cae 2010-11-24        kinaba:      |  "λ" "(" PARAMS ")" "{" E "}" $(D_COMMENT # 無名関数)
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    $(D_COMMENT # 関数呼び出し)
20be503cae 2010-11-24        kinaba:      | E "(" ARGS")"
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:          where    ARGS ::= E "," ... "," E
20be503cae 2010-11-24        kinaba:                 PARAMS ::= (ID|LAYER)+ "," ... "," (ID|LAYER)+
20be503cae 2010-11-24        kinaba:                 ENTRYS ::= ID ":" E    "," ... "," ID ":" E
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    $(D_COMMENT # 演算子など)
20be503cae 2010-11-24        kinaba:      | "(" E ")"                 $(D_COMMENT # ただの括弧)
f7e9e77316 2010-11-26        kinaba:      | "..."                     $(D_COMMENT # これを実行するとdie)
20be503cae 2010-11-24        kinaba:      | E BINOP E                 $(D_COMMENT # 二項演算子いろいろ)
20be503cae 2010-11-24        kinaba:      | E "."  ID                 $(D_COMMENT # テーブルのフィールドアクセス)
20be503cae 2010-11-24        kinaba:      | E ".?" ID                 $(D_COMMENT # テーブルにフィールドがあるか否か)
20be503cae 2010-11-24        kinaba:      | E "{" ENTRYS "}"          $(D_COMMENT # テーブル拡張)
3ae09b8cbf 2010-11-24        kinaba:      | "if" E ("then"|":"|"then" ":") E
3ae09b8cbf 2010-11-24        kinaba:      | "if" E ("then"|":"|"then" ":") E "else" ":"? E
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    $(D_COMMENT # パターンマッチ)
3ae09b8cbf 2010-11-24        kinaba:      | "case" E ("when" PATTERN ":" E )*
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:          where PATTERN ::= 式がだいたいなんでも書ける気がする
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    $(D_COMMENT # レイヤ指定実行)
20be503cae 2010-11-24        kinaba:      | LAYER "(" E ")"
20be503cae 2010-11-24        kinaba: </pre>
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION 糖衣構文, $(SECBODY
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 演算子というものはありません。内部的には全て関数呼び出し構文に書き換えられています。<tt>if</tt> もです。
20be503cae 2010-11-24        kinaba: <br/>
20be503cae 2010-11-24        kinaba: パターンマッチも全部 <tt>if</tt> と <tt>==</tt> と <tt>&amp;&amp;</tt> と
20be503cae 2010-11-24        kinaba: <tt>.</tt> と <tt>.?</tt> を使った関数呼び出し式に書き換えられていますが、
20be503cae 2010-11-24        kinaba: 規則の詳細を説明するのが面倒なので適当に想像して下さい。
20be503cae 2010-11-24        kinaba: 他の書き換えはこんな感じです。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <pre>
3ae09b8cbf 2010-11-24        kinaba:     if E then E         ⇒ if( E, fun(){E}, fun(){} )
3ae09b8cbf 2010-11-24        kinaba:     if E then E else E  ⇒ if( E, fun(){E}, fun(){E} )
8caee17864 2010-11-24        kinaba:     E BINOP E           ⇒ BINOP(E, E)
8caee17864 2010-11-24        kinaba:     { ENTRIES }         ⇒ {}{ ENTRIES }
8caee17864 2010-11-24        kinaba:     {}                  ⇒ {}()
8caee17864 2010-11-24        kinaba:     E {ID:E, ...}       ⇒ .=(E, ID, E) { ... }
20be503cae 2010-11-24        kinaba: </pre>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 変数宣言に色々ありますが、<tt>let</tt> と <tt>var</tt> と <tt>def</tt> は同じ扱いで、
20be503cae 2010-11-24        kinaba: <tt>in</tt> と <tt>;</tt> は同じ扱いです。つまり
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <pre>
20be503cae 2010-11-24        kinaba:    let x = E in E
20be503cae 2010-11-24        kinaba:    var x = E in E
20be503cae 2010-11-24        kinaba:    def x = E in E
20be503cae 2010-11-24        kinaba:    let x = E ; E
20be503cae 2010-11-24        kinaba:    var x = E ; E
20be503cae 2010-11-24        kinaba:    def x = E ; E
20be503cae 2010-11-24        kinaba: </pre>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 以上のどれも同じ意味なので、なんとなく関数型っぽく書きたい気分の日は <tt>let in</tt> を、
3ae09b8cbf 2010-11-24        kinaba: 手続き型っぽく書きたい気分の日は <tt>var ;</tt> を使うとよいと思います。
3ae09b8cbf 2010-11-24        kinaba: <tt>if then else</tt> も微妙にコロンがあったりなかったりバリエーションがありますが好みで使います。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 関数を宣言するときは、<tt>fun</tt> や <tt>λ</tt> を省略できます。
20be503cae 2010-11-24        kinaba: 以下の書き換えが行われます。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <pre>
20be503cae 2010-11-24        kinaba:    def f( ARGS ) { E }; E   ⇒   def f = fun(ARGS){E}; E
20be503cae 2010-11-24        kinaba: </pre>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 他に、もっと手続き型っぽくための書き換え色々
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <pre>
20be503cae 2010-11-24        kinaba:    fun () { E; E; E      }   ⇒   fun () { let _ = E in let _ = E in E }
20be503cae 2010-11-24        kinaba:    fun () { var x = 100  }   ⇒   fun () { var x = 100; x }
20be503cae 2010-11-24        kinaba:    fun () { var x = 100; }   ⇒   fun () { var x = 100; x }
20be503cae 2010-11-24        kinaba:    fun () { }                ⇒   fun () { "(empty function body)" }
20be503cae 2010-11-24        kinaba: </pre>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 中身が空の関数に何を返させるかは適当です。今はとりあえず適当に文字列返してます。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION 変数のスコープ規則, $(SECBODY
20be503cae 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: 基本的には、let によって常識的な感じに変数のスコープがネストします。
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
8caee17864 2010-11-24        kinaba:    let x=21 in let x=x+x in x    $(D_COMMENT # 42)
8caee17864 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: 一方で、"let rec" のような特別な構文はありませんが、
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
3ae09b8cbf 2010-11-24        kinaba:    let f = fun(x) { if x==0 then 1 else x*f(x-1) } in f(10)  $(D_COMMENT # 3628800)
8caee17864 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: 再帰的な関数定義なども、おそらく意図されたとおりに動きます。
8caee17864 2010-11-24        kinaba: 内部の詳細は、諸般の事情により、
8caee17864 2010-11-24        kinaba: マジカルで破壊的なスコープ規則になっているのですが、
8caee17864 2010-11-24        kinaba: 同名の変数を激しく重ねて使ったりしなければ、
8caee17864 2010-11-24        kinaba: だいたい自然な動きをすると思います、たぶん、はい。
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: ひとつだけ不可思議な動きをするのは、以下のケースです。
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
8caee17864 2010-11-24        kinaba:    let x = 1 in
8caee17864 2010-11-24        kinaba:    let f = fun() {x} in
8caee17864 2010-11-24        kinaba:    let x = 2 in
8caee17864 2010-11-24        kinaba:       f()    $(D_COMMENT # 2!!)
8caee17864 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: let-in を縦にチェインしたときだけ、同名変数を破壊的に上書きします
8caee17864 2010-11-24        kinaba: (再帰関数の定義が"うまく"いっているのはこの上書きのためです)。
8caee17864 2010-11-24        kinaba: なんでこんなことになっているかというと、
8caee17864 2010-11-24        kinaba: 後で説明する「レイヤ」を使ったときに
8caee17864 2010-11-24        kinaba: <tt>let foo = ... in @lay foo = ... in ...</tt>
8caee17864 2010-11-24        kinaba: で他レイヤに重ね書きするためであります。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: ))
8caee17864 2010-11-24        kinaba: )
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION Basic Features, $(SECBODY
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 特に特徴的でもない部分を簡単にまとめ。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <ul>
20be503cae 2010-11-24        kinaba:   <li>静的型システムはありません。</li>
20be503cae 2010-11-24        kinaba:   <li>"ほぼ" 純粋関数型言語です。変数やテーブルのフィールドの破壊的な書き換えはできません。<br/>
20be503cae 2010-11-24        kinaba:       ただし、組み込み関数(<tt>print</tt>)と、変数のスコープ規則のマジカルな片隅に副作用があります。</li>
20be503cae 2010-11-24        kinaba: </ul>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 静的型システムがないのは意図的ですが、破壊的代入がないのは、単に実装がめんどかっただけなので、
20be503cae 2010-11-24        kinaba: 今後何か増えるかもしれません。増えないかもしれません。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: $(DDOC_MEMBERS
20be503cae 2010-11-24        kinaba: $(SECTION データ型, $(SECBODY
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 以下のデータ型があります。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: <ul>
20be503cae 2010-11-24        kinaba:   <li>整数:     <tt>0</tt>, <tt>123</tt>, <tt>456666666666666666666666666666666666666789</tt>, ...</li>
20be503cae 2010-11-24        kinaba:   <li>文字列:   <tt>"hello, world!"</tt>, ...</li>
20be503cae 2010-11-24        kinaba:   <li>関数:     <tt>fun(x){x+1}</tt></li>
20be503cae 2010-11-24        kinaba:   <li>テーブル: <tt>{car: 1, cdr: {car: 2, cdr: {}}}</tt></li>
f7e9e77316 2010-11-26        kinaba:   <li>未定義値: (特殊なケースで作られます。「レイヤ」の説明参照のこと。)</li>
20be503cae 2010-11-24        kinaba: </ul>
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 関数はいわゆる「クロージャ」です。静的スコープで外側の環境にアクセスできます。
20be503cae 2010-11-24        kinaba: テーブルはいわゆるプロトタイプチェーンを持っていて、
20be503cae 2010-11-24        kinaba: 自分にないフィールドの場合は親に問い合わせが行く感じになっていますが、
20be503cae 2010-11-24        kinaba: フィールドの書き換えがないので、これは特に意味ないかもしれない…。
c0158c9281 2010-11-24        kinaba: </p>
c0158c9281 2010-11-24        kinaba: <p>
c0158c9281 2010-11-24        kinaba: また、リストを扱うために、いわゆる「cons リスト」を使います。
c0158c9281 2010-11-24        kinaba: 空リストを <tt>{}</tt>、1個以上要素があるものを <tt>{car: 先頭要素, cdr: 二番目以降のリスト}</tt>
c0158c9281 2010-11-24        kinaba: という形で。この形でリストを扱わなければならないという決まりはありませんが、
c0158c9281 2010-11-24        kinaba: この形は特別扱いされて <tt>print</tt> で綺麗に出力されたりします。
8caee17864 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: $(SECTION パターンマッチ, $(SECBODY
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: 適当に実装されたパターンマッチがあります。
8caee17864 2010-11-24        kinaba: リストの 2n 番目と 2n+1 番目を足して長さを半分にする関数:
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
8caee17864 2010-11-24        kinaba:     def adjSum(lst)
8caee17864 2010-11-24        kinaba:     {
3ae09b8cbf 2010-11-24        kinaba:       case lst
3ae09b8cbf 2010-11-24        kinaba:         when {car:x, cdr:{car: y, cdr:z}}: {car: x+y, cdr: adjSum(z)}
3ae09b8cbf 2010-11-24        kinaba:         when {car:x, cdr:{}}: lst
3ae09b8cbf 2010-11-24        kinaba:         when {}: {}
8caee17864 2010-11-24        kinaba:     }
8caee17864 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: 動かすときには、処理系がそれっぽい if-then-else に展開しています。
8caee17864 2010-11-24        kinaba: <tt>when</tt> を上から試していって、最初にマッチしたところを実行します。
f7e9e77316 2010-11-26        kinaba: どれにもマッチしないとエラーでプログラム終了します。
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
8caee17864 2010-11-24        kinaba:    PAT ::= "_"                                      $(D_COMMENT # ワイルドカード)
8caee17864 2010-11-24        kinaba:          | ID                                       $(D_COMMENT # 変数パターン)
8caee17864 2010-11-24        kinaba:          | "{" ID ":" PAT "," ... "," ID : PAT "}"  $(D_COMMENT # テーブルパターン)
8caee17864 2010-11-24        kinaba:          | E                                        $(D_COMMENT # 値パターン)
8caee17864 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: 変数パターンは常にマッチして、値をその変数に束縛します。
8caee17864 2010-11-24        kinaba: ワイルドカードも常にマッチしますが、変数束縛しません。
8caee17864 2010-11-24        kinaba: 値パターンは、任意の式が書けます。その式を評価した結果と <tt>==</tt> ならマッチします。
8caee17864 2010-11-24        kinaba: 外で束縛された変数を値パターンとして配置、は直接はできないので
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
8caee17864 2010-11-24        kinaba:    var x = 123;
3ae09b8cbf 2010-11-24        kinaba:    case foo
3ae09b8cbf 2010-11-24        kinaba:      when {val: x+0}: ... $(D_COMMENT # これは {val:123} と同じ)
3ae09b8cbf 2010-11-24        kinaba:      when {val: x}:   ... $(D_COMMENT # これは任意の foo.?val なら常にマッチ)
8caee17864 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: 適当にちょっと複雑な式にしてやるとよいかも(裏技)。
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: テーブルパターンは、書かれたキーが全てあればマッチします。
8caee17864 2010-11-24        kinaba: <tt>{a: _}</tt> は、<tt>.a</tt> を持ってさえいればマッチするので、
8caee17864 2010-11-24        kinaba: <tt>{a: 123, b: 456}</tt> なんかにもマッチします。
8caee17864 2010-11-24        kinaba: なので、リストに対するパターンを書くときには、car/cdr の場合を先に書かないと
3ae09b8cbf 2010-11-24        kinaba: <tt>when {}</tt> を上に書くと全部マッチしちゃいます。注意。
8caee17864 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: )
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION Layers, $(SECBODY
20be503cae 2010-11-24        kinaba: <pre>
20be503cae 2010-11-24        kinaba: [Layers :: Overview]
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   Polemy's runtime environment has many "layer"s.
20be503cae 2010-11-24        kinaba:   Usual execution run in the @value layer.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> 1 + 2
20be503cae 2010-11-24        kinaba:     3
20be503cae 2010-11-24        kinaba:     >> @value( 1 + 2 )
20be503cae 2010-11-24        kinaba:     3
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   Here you can see that @LayerName( Expression ) executes the inner Expression in
20be503cae 2010-11-24        kinaba:   the @LayerName layer. Other than @value, one other predefined layer exists: @macro.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @macro( 1+2 )
20be503cae 2010-11-24        kinaba:     {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>},
20be503cae 2010-11-24        kinaba:       is@value:app,
20be503cae 2010-11-24        kinaba:     args@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>},
20be503cae 2010-11-24        kinaba:                             is@value:int,
20be503cae 2010-11-24        kinaba:                           data@value:1},
20be503cae 2010-11-24        kinaba:                 cdr@value:{
20be503cae 2010-11-24        kinaba:                   car@value:{pos@value:{lineno@value:3, column@value:11, filename@value:<REPL>},
20be503cae 2010-11-24        kinaba:                               is@value:int,
20be503cae 2010-11-24        kinaba:                             data@value:2},
20be503cae 2010-11-24        kinaba:                   cdr@value:{}}},
20be503cae 2010-11-24        kinaba:      fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL>},
20be503cae 2010-11-24        kinaba:                  is@value:var,
20be503cae 2010-11-24        kinaba:                name@value:+}}
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   (Sorry, this pretty printing is not available on the actual interpreter...)
20be503cae 2010-11-24        kinaba:   This evaluates the expression 1+2 in the @macro layer. In this layer, the meaning of
20be503cae 2010-11-24        kinaba:   the program is its abstract syntax tree.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   You can interleave layers.
20be503cae 2010-11-24        kinaba:   The root node of the abstract syntax tree is function "app"lication.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @value(@macro( 1+2 ).is)
20be503cae 2010-11-24        kinaba:     app
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: [Layers :: Defining a new layer]
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   To define a new layer, you should first tell how to "lift" existing values two the new layer.
20be503cae 2010-11-24        kinaba:   Let us define the "@type" layer, where the meaning of programs is their static type.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @@type = fun(x) {
20be503cae 2010-11-24        kinaba:     >>   if( _isint(x) ) { "int" } else {
20be503cae 2010-11-24        kinaba:     >>   if( _isfun(x) ) { x } else { "unknown" } }
20be503cae 2010-11-24        kinaba:     >> }
20be503cae 2010-11-24        kinaba:     (Note: polemy REPL may warn some exception here but please ignore)
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   For simplicity, I here deal only with integers.
20be503cae 2010-11-24        kinaba:   _isint is a primitive function of Polemy that checks the dynamic type of a value.
20be503cae 2010-11-24        kinaba:   For function, leaving it untouched works well for almost all layers.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @type( 1 )
20be503cae 2010-11-24        kinaba:     int
20be503cae 2010-11-24        kinaba:     >> @type( 2 )
20be503cae 2010-11-24        kinaba:     int
20be503cae 2010-11-24        kinaba:     >> @type( "foo" )
20be503cae 2010-11-24        kinaba:     unknown
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   Fine! Let's try to type 1+2.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @type( 1 + 2 )
20be503cae 2010-11-24        kinaba:     ...\value.d(119): [<REPL>:6:8] only @value layer can call native function
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   Note that the behavior of this program is
20be503cae 2010-11-24        kinaba:     - run 1+2 in the @type layer
20be503cae 2010-11-24        kinaba:   and NOT
20be503cae 2010-11-24        kinaba:     - run 1+2 in @value and obtain 3 and run 3 in the @type.
20be503cae 2010-11-24        kinaba:   The problem is, the variable "+" is defined only in the @value layer.
20be503cae 2010-11-24        kinaba:   To carry out computation in the @type layer. We need to define it also
20be503cae 2010-11-24        kinaba:   in the @type layer.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   To define some variable in a specific layer, use @LayerName in place of
20be503cae 2010-11-24        kinaba:   (let|var|def)s.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> let x = 2
20be503cae 2010-11-24        kinaba:     >> @value x = 2
20be503cae 2010-11-24        kinaba:     >> @type x = "int"
20be503cae 2010-11-24        kinaba:     >> @hoge x = "fuga"
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   For "+", do it like this.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @type "+" = fun(x,y) {@value(
20be503cae 2010-11-24        kinaba:     >>   if( @type(x)=="int" && @type(y)=="int" ) { "int" } else { "typeerror" }
20be503cae 2010-11-24        kinaba:     >> )}
20be503cae 2010-11-24        kinaba:     polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   It is just computing the return type from the input type.
20be503cae 2010-11-24        kinaba:   Not here that the intended "meaning" of if-then-else is the runtime-branching,
20be503cae 2010-11-24        kinaba:   and the meaning of "==" is the value-comparison. These are the @value layer
20be503cae 2010-11-24        kinaba:   behavior. So we have defined the function body inside @value layer.
20be503cae 2010-11-24        kinaba:   But when we refer the variables x and y, we need its @type layer meaning.
20be503cae 2010-11-24        kinaba:   Hence we use @type() there.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   Now we get it.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @type( 1 + 2 )
20be503cae 2010-11-24        kinaba:     int
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   Well, but do we have to define the @type layer meaning for every variables???
20be503cae 2010-11-24        kinaba:   No. After you defined @type "+", you'll automatically get the following:
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> def double(x) { x + x }
20be503cae 2010-11-24        kinaba:     (function:17e4740:1789720)
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @type( double(123) )
20be503cae 2010-11-24        kinaba:     int
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   Every user-defined functions are automatically "lift"ed to the appropriate layer.
20be503cae 2010-11-24        kinaba:   Only primitive functions like "+" requires @yourNewLayer annotation.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: [Layers :: neutral-layer]
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   let|var|def is to define a variable in the "current" layer.
20be503cae 2010-11-24        kinaba:   Not necessary to the @value layer.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @value( let x = 1 in @value(x) )
20be503cae 2010-11-24        kinaba:     1
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @macro( let x = 1 in @value(x) )
20be503cae 2010-11-24        kinaba:     polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> @macro( let x = 1 in @macro(x) )
20be503cae 2010-11-24        kinaba:     {pos@value:{lineno@value:15, ...
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: [Layers :: Layered-Parameters]
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> def foo(x @macro @value) { {fst: x, snd: @macro(x)} }
20be503cae 2010-11-24        kinaba:     (function:1730360:1789720)
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   If you annotate function parameters by @LayerNames, when you invoke the function...
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:     >> foo(1+2)
20be503cae 2010-11-24        kinaba:     {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REPL>},
20be503cae 2010-11-24        kinaba:                   is@value:app, arg@value:{...
20be503cae 2010-11-24        kinaba:     /fst@value:3
20be503cae 2010-11-24        kinaba:     /}
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:   its corresponding arguments are evaluated in the layer and passed to it.
20be503cae 2010-11-24        kinaba:   If you specify multiple layers, the argument expression is run multiple times.
20be503cae 2010-11-24        kinaba:   If you do not specify any layer for a parameter, it works in the neutral layer.
8caee17864 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: ))
8caee17864 2010-11-24        kinaba: 
8caee17864 2010-11-24        kinaba: 
8caee17864 2010-11-24        kinaba: $(SECTION Macro Layers, $(SECBODY
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: Polemy 言語組み込みのレイヤは <code>@value</code> と <code>@macro</code> の二つです。
8caee17864 2010-11-24        kinaba: (内部的にはもういくつかありますが、ユーザから直接は使えません。)
8caee17864 2010-11-24        kinaba: <code>@value</code> は、「普通に」普通のセマンティクスでプログラムを実行するレイヤでした。
8caee17864 2010-11-24        kinaba: <code>@macro</code> は、実は、<code>@value</code> よりも前に実行されるレイヤで、
8caee17864 2010-11-24        kinaba: 「プログラムを実行するとその構文木を返す」というセマンティクスで動きます。
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
8caee17864 2010-11-24        kinaba:     (ここに例)
8caee17864 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: 動きとしてはこうです。
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <ol>
8caee17864 2010-11-24        kinaba: <li>関数呼び出し時(とトップレベル環境の実行開始時)に、
8caee17864 2010-11-24        kinaba: 	まず、<code>@macro</code> レイヤでコードを実行。</li>
8caee17864 2010-11-24        kinaba: <li>返ってきた構文木を、<code>@value</code> レイヤ、
8caee17864 2010-11-24        kinaba: 	またはその関数を呼び出したときのレイヤで実行。</li>
8caee17864 2010-11-24        kinaba: </ol>
8caee17864 2010-11-24        kinaba: <p>
8caee17864 2010-11-24        kinaba: <code>@macro</code> レイヤも所詮ただのレイヤですので、
8caee17864 2010-11-24        kinaba: 上で説明した方法で <code>@macro</code> レイヤに関数などを登録しておくことで、
8caee17864 2010-11-24        kinaba: 構文木の生成をいじることが可能です。まさにマクロ。
8caee17864 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: 
8caee17864 2010-11-24        kinaba: $(DDOC_MEMBERS
207cea338a 2010-11-26        kinaba: $(SECTION 概要, $(SECBODY
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: samples/macro.pmy にいくつか使い方サンプルが置いてありますので、詳しくはそちらをどうぞ。
207cea338a 2010-11-26        kinaba: </p>
207cea338a 2010-11-26        kinaba: <pre>
207cea338a 2010-11-26        kinaba:     &gt;&gt; @macro( twice(print("Hello")) )
207cea338a 2010-11-26        kinaba:     {
207cea338a 2010-11-26        kinaba:       pos: {lineno:1, column:9, filename:<REPL>},
207cea338a 2010-11-26        kinaba:      args: [ { pos: {lineno:1, column:15, filename:<REPL>},
207cea338a 2010-11-26        kinaba:               args: [{pos:{lineno:1, column:21, filename:<REPL>},
207cea338a 2010-11-26        kinaba:                        is:Str,
207cea338a 2010-11-26        kinaba:                      data:Hello}],
207cea338a 2010-11-26        kinaba:                 is: App,
207cea338a 2010-11-26        kinaba:                fun: {pos:{lineno:1, column:15, filename:<REPL>}, is:Var, name:print}}
207cea338a 2010-11-26        kinaba:            ],
207cea338a 2010-11-26        kinaba:        is: App,
207cea338a 2010-11-26        kinaba:       fun: {pos:{lineno:1, column:9, filename:<REPL>}, is:Var, name:twice}
207cea338a 2010-11-26        kinaba:     }
207cea338a 2010-11-26        kinaba: </pre>
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: 詳細は気にしなくて構いませんが、とにかく、<tt>@macro</tt> レイヤでは、
207cea338a 2010-11-26        kinaba: 基本的には、コードを実行するとそのコードの構文木がでてきます。
207cea338a 2010-11-26        kinaba: この挙動は <tt>@macro</tt> レイヤの変数をセットすることで、カスタマイズできます。
207cea338a 2010-11-26        kinaba: </p>
207cea338a 2010-11-26        kinaba: <pre>
207cea338a 2010-11-26        kinaba:     &gt;&gt; @macro twice(x) { x; x } in twice(print("Hello"))
207cea338a 2010-11-26        kinaba:     Hello
207cea338a 2010-11-26        kinaba:     Hello
207cea338a 2010-11-26        kinaba:     Hello
207cea338a 2010-11-26        kinaba: </pre>
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: (3回出力されてますが、3個目は <tt>print(x)</tt> の返値は <tt>x</tt> なので、
207cea338a 2010-11-26        kinaba: それがREPLによって印字されているだけです。)
207cea338a 2010-11-26        kinaba: <tt>@macro</tt> レイヤで <tt>in</tt> 以降を実行すると、<tt>print("Hello")</tt> という式を表す構文木が作られ、
207cea338a 2010-11-26        kinaba: それが <tt>twice</tt> 関数に渡されます。<tt>twice</tt> の中身も <tt>@macro</tt> レイヤで実行されるので、
207cea338a 2010-11-26        kinaba: 構文木を作ろうとしますが、変数 <tt>x</tt> には <tt>@macro</tt> レイヤで値が入っているので、
207cea338a 2010-11-26        kinaba: その値を読み取って構文木を作成します。
207cea338a 2010-11-26        kinaba: 結果として、2回 <tt>print("Hello")</tt> する構文木が作られて、
207cea338a 2010-11-26        kinaba: その後で、それが <tt>@value</tt> レイヤで実行されています。
207cea338a 2010-11-26        kinaba: </p>
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: 本当にベタに構文木を作るだけなので、変数名の衝突などなどは気にしません。「衛生的でない」マクロです。
207cea338a 2010-11-26        kinaba: </p>
207cea338a 2010-11-26        kinaba: <pre>
207cea338a 2010-11-26        kinaba:     @macro LetItBe(x, y) { var $(B it) = x; y };  $(D_COMMENT # y の中で変数 it が使える)
207cea338a 2010-11-26        kinaba:     print( LetItBe("myself",  "when I find " ~ $(B it) ~ " in times of trouble") );
207cea338a 2010-11-26        kinaba: </pre>
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: 変数名に気をつけるには、組み込み関数 <tt>gensym()</tt> を使って頑張って下さい。
207cea338a 2010-11-26        kinaba: </p>
207cea338a 2010-11-26        kinaba: ))
207cea338a 2010-11-26        kinaba: $(SECTION レイヤ切り替え, $(SECBODY
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: 他のレイヤ同様、<tt>@macro</tt> レイヤを実行中に <tt>@layer( ... )</tt> 構文を使うことで、
207cea338a 2010-11-26        kinaba: 別のレイヤでコードを動かすこともできます。よく使う例は、<tt>@value</tt>
207cea338a 2010-11-26        kinaba: レイヤに移ることで構文木を普通に計算して色々プログラム的にいじる用途です。
207cea338a 2010-11-26        kinaba: </p>
c0158c9281 2010-11-24        kinaba: <pre>
207cea338a 2010-11-26        kinaba:     @macro reverseArgs(e) {$(B @value)(
207cea338a 2010-11-26        kinaba:         def rev(xs, acc) {
207cea338a 2010-11-26        kinaba:           case xs when {car:x, cdr:xs}: rev(xs, {car:x, cdr:acc}) when {}: acc
207cea338a 2010-11-26        kinaba:         };
207cea338a 2010-11-26        kinaba:         case @macro(e)
207cea338a 2010-11-26        kinaba:           when {is:"App", fun:f, args:as}: {is:"App", fun:f, args:rev(as,{})}
207cea338a 2010-11-26        kinaba:           when e: e
207cea338a 2010-11-26        kinaba:     )};
207cea338a 2010-11-26        kinaba:     print( reverseArgs(1-2) ); $(D_COMMENT # 2-1 == 1)
c0158c9281 2010-11-24        kinaba: </pre>
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: <tt>reverseArgs</tt> は、関数呼び出しの構文木の、引数の順番を逆転する関数です。
207cea338a 2010-11-26        kinaba: <tt>@macro(e)</tt> によってマクロレイヤにセットされている構文木引数を取り出し、
207cea338a 2010-11-26        kinaba: それを <tt>@value</tt> レイヤによる普通の計算プログラムで操作しています。
207cea338a 2010-11-26        kinaba: 要は、<tt>@macro(...)</tt> はいわゆる「準クオート (quasiquote)」、
207cea338a 2010-11-26        kinaba: <tt>@value(...)</tt> は「逆クオート (unquote)」に近い働きをします。
207cea338a 2010-11-26        kinaba: </p>
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: <tt>@layer(...)</tt> だけでなく、関数のレイヤ指定引数なども同様に使うことができるので、
207cea338a 2010-11-26        kinaba: 一部の引数は <tt>@macro</tt>、一部の引数は <tt>@value</tt> レイヤで受け取る関数を書くなど、
207cea338a 2010-11-26        kinaba: さらに色々面白いことが可能です。
207cea338a 2010-11-26        kinaba: </p>
207cea338a 2010-11-26        kinaba: ))
207cea338a 2010-11-26        kinaba: $(SECTION 構文木の構造, $(SECBODY
c0158c9281 2010-11-24        kinaba: <p>
c0158c9281 2010-11-24        kinaba: 構文木がどのようなテーブルで渡されてくるかについては、ソースドキュメントの
c0158c9281 2010-11-24        kinaba: <a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/ast.html">polemy.ast</a>
c0158c9281 2010-11-24        kinaba: のページをご覧下さい。例えば変数名を表す <code>Var</code> クラスには、
c0158c9281 2010-11-24        kinaba: 継承の分も合わせて
c0158c9281 2010-11-24        kinaba: <tt><a href="http://www.kmonos.net/repos/polemy/doc/tip/doc/failure.html">LexPosition</a> pos;</tt>
c0158c9281 2010-11-24        kinaba: と <tt>string name;</tt> の2つのメンバがあるので
c0158c9281 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
c0158c9281 2010-11-24        kinaba:     { is:   "Var",
c0158c9281 2010-11-24        kinaba:       pos:  {filename:"foo.pmy", lineno:123, column:45},
c0158c9281 2010-11-24        kinaba:       name: "x" }
8caee17864 2010-11-24        kinaba: </pre>
c0158c9281 2010-11-24        kinaba: <p>
c0158c9281 2010-11-24        kinaba: こんな感じのテーブルになります。
c0158c9281 2010-11-24        kinaba: クラス名が <tt>is</tt> フィールドに、メンバ変数はそのままの名前で入ります。
c0158c9281 2010-11-24        kinaba: 配列メンバは cons リストになって入ってきます。
207cea338a 2010-11-26        kinaba: 自分で構文木を作る時は、<tt>pos</tt> フィールドだけは省略しても構いません。
c0158c9281 2010-11-24        kinaba: </p>
8caee17864 2010-11-24        kinaba: ))
207cea338a 2010-11-26        kinaba: $(SECTION 微妙なところ, $(SECBODY
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: ここまで、<tt>@macro</tt> が本当にただの1レイヤであるかのように説明してきましたが、
207cea338a 2010-11-26        kinaba: 実はちょっと幾つかのトリックが潜んでいます。
207cea338a 2010-11-26        kinaba: </p>
207cea338a 2010-11-26        kinaba: <pre>
207cea338a 2010-11-26        kinaba:     &gt;&gt; @macro twice(x) {x; x} in twice($(B @value)(print("Hello")))
207cea338a 2010-11-26        kinaba:     Hello
207cea338a 2010-11-26        kinaba:     Hello
207cea338a 2010-11-26        kinaba:     Hello
207cea338a 2010-11-26        kinaba: </pre>
207cea338a 2010-11-26        kinaba: <p>
207cea338a 2010-11-26        kinaba: 先ほどの例に <tt>@value</tt> を増やしたものですが、これでもやはり、Hello
207cea338a 2010-11-26        kinaba: が2回 print されるようになります。
207cea338a 2010-11-26        kinaba: </p>
8caee17864 2010-11-24        kinaba: <pre>
207cea338a 2010-11-26        kinaba: <tt>@macro</tt> レイヤと <tt>(rawmacro)</tt> レイヤという二つが協調して動作しています。
8caee17864 2010-11-24        kinaba:    (rawmacro) レイヤの話
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:       [[limitations]]
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    This @macro layer is a very primitive one, and not a perfect macro language.
20be503cae 2010-11-24        kinaba:    Two major limitations are seen in the following "it" example.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:      >> @macro LetItBe(x, y) { let it = x in y };
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    The variable name is not hygenic, and so without any effort, the syntax tree "y"
20be503cae 2010-11-24        kinaba:    can access the outer variable "it".
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:      >> def foo() { LetItBe( 1+2+3, it*it ) }
20be503cae 2010-11-24        kinaba:      >> foo()
20be503cae 2010-11-24        kinaba:      36
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    Of course, this is not just a limitation; it can sometimes allow us to write
20be503cae 2010-11-24        kinaba:    many interesting macros.
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    The other problem is that the macro expansion is only done at function startup.
20be503cae 2010-11-24        kinaba:    So
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:      >> LetItBe( 1+2+3, it*it )
20be503cae 2010-11-24        kinaba:      ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba:    you cannot directly use the macro in the same scope as the definition.
20be503cae 2010-11-24        kinaba:    You need to wrap it up in a function (like the foo() in the above example).
20be503cae 2010-11-24        kinaba: </pre>
8caee17864 2010-11-24        kinaba: ))
8caee17864 2010-11-24        kinaba: )
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION Built-in Primitives, $(SECBODY
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 組み込み関数・変数の一覧。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: $(DDOC_MEMBERS
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION テーブル操作, $(SECBODY
20be503cae 2010-11-24        kinaba:   $(TABLE
20be503cae 2010-11-24        kinaba:     $(TR $(TH {}) $(TD ()) $(TD 空のテーブルを作る))
20be503cae 2010-11-24        kinaba:     $(TR $(TH .) $(TD (t, s)) $(TD テーブル t の名前 s のフィールドの値を取得。なければ <tt>undefined</tt>))
20be503cae 2010-11-24        kinaba:     $(TR $(TH .?) $(TD (t, s)) $(TD テーブル t に名前 s のフィールドがあれば 1、なければ 0))
20be503cae 2010-11-24        kinaba:     $(TR $(TH .=) $(TD (t, s, v)) $(TD テーブル t を親に持ち、名前 s のフィールドに v が入ったテーブルを作る))
20be503cae 2010-11-24        kinaba:   )
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: <br />
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION 制御フロー, $(SECBODY
20be503cae 2010-11-24        kinaba:   $(TABLE
20be503cae 2010-11-24        kinaba:     $(TR $(TH if) $(TD (n, ft, fe)) $(TD n が非 0 なら <tt>ft()</t>、0 なら <tt>fe()</tt> を実行))
20be503cae 2010-11-24        kinaba:   )
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: <br />
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION 演算, $(SECBODY
20be503cae 2010-11-24        kinaba:   $(TABLE
20be503cae 2010-11-24        kinaba:     $(TR $(TH +) $(TD (n, m)) $(TD 整数 n と整数 m を足して返す))
20be503cae 2010-11-24        kinaba:     $(TR $(TH -) $(TD (n, m)) $(TD 整数の引き算))
20be503cae 2010-11-24        kinaba:     $(TR $(TH *) $(TD (n, m)) $(TD 整数の掛け算))
20be503cae 2010-11-24        kinaba:     $(TR $(TH /) $(TD (n, m)) $(TD 整数の割り算))
20be503cae 2010-11-24        kinaba:     $(TR $(TH %) $(TD (n, m)) $(TD 整数の剰余))
20be503cae 2010-11-24        kinaba:     $(TR $(TH &amp;&amp;) $(TD (n, m)) $(TD 整数 n と m が両方非 0 なら 1、それ以外では 0))
20be503cae 2010-11-24        kinaba:     $(TR $(TH ||) $(TD (n, m)) $(TD 整数 n と m がどちらか非 0 なら 1、それ以外では 0))
20be503cae 2010-11-24        kinaba:     $(TR $(TH ~) $(TD (a, b)) $(TD a と b を文字列化して結合))
20be503cae 2010-11-24        kinaba:     $(TR $(TH &lt;) $(TD (a, b)) $(TD a と b を比較))
20be503cae 2010-11-24        kinaba:     $(TR $(TH &lt;=) $(TD (a, b)) $(TD a と b を比較))
20be503cae 2010-11-24        kinaba:     $(TR $(TH &gt;) $(TD (a, b)) $(TD a と b を比較))
20be503cae 2010-11-24        kinaba:     $(TR $(TH &gt;=) $(TD (a, b)) $(TD a と b を比較))
20be503cae 2010-11-24        kinaba:     $(TR $(TH ==) $(TD (a, b)) $(TD a と b を比較))
20be503cae 2010-11-24        kinaba:     $(TR $(TH !=) $(TD (a, b)) $(TD a と b を比較))
20be503cae 2010-11-24        kinaba:   )
20be503cae 2010-11-24        kinaba: <p>
20be503cae 2010-11-24        kinaba: 注意点として、作者の趣味の問題で、<tt>&amp;&amp;</tt> と <tt>||</tt> は short-circuit 評価をしません。
20be503cae 2010-11-24        kinaba: 整数演算の種類が少ないのは、D 言語の std.bigint がビット演算などをサポートしてないためです。
20be503cae 2010-11-24        kinaba: 文字列が結合しかできないのは、単に手抜きです。
20be503cae 2010-11-24        kinaba: </p>
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION 外部とのやりとり, $(SECBODY
20be503cae 2010-11-24        kinaba:   $(TABLE
474c4facf0 2010-11-25        kinaba:     $(TR $(TH print) $(TD (a)) $(TD a を文字列化標準出力に改行付きで表示して、a を返す))
20be503cae 2010-11-24        kinaba:     $(TR $(TH argv) $(TD ) $(TD スクリプトに渡された引数文字列のconsリスト))
c75f0d5f1e 2010-11-24        kinaba:     $(TR $(TH gensym) $(TD ()) $(TD エセgensym。変数名として他とかぶらなそうな文字列を返します))
f9c31f3cd8 2010-11-24        kinaba:     $(TR $(TH rand) $(TD (n)) $(TD 0 以上 n 未満の自然数を31bit以内でランダムに生成します))
20be503cae 2010-11-24        kinaba:   )
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: <br />
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: $(SECTION データ型判定, $(SECBODY
20be503cae 2010-11-24        kinaba:   $(TABLE
20be503cae 2010-11-24        kinaba:     $(TR $(TH _isint) $(TD (a)) $(TD a が整数なら 1、でなければ 0))
20be503cae 2010-11-24        kinaba:     $(TR $(TH _isstr) $(TD (a)) $(TD a が文字列なら 1、でなければ 0))
20be503cae 2010-11-24        kinaba:     $(TR $(TH _isfun) $(TD (a)) $(TD a が関数なら 1、でなければ 0))
20be503cae 2010-11-24        kinaba:     $(TR $(TH _istable) $(TD (a)) $(TD a がテーブルなら 1、でなければ 0))
20be503cae 2010-11-24        kinaba:     $(TR $(TH _isundefined) $(TD (a)) $(TD a が未定義値なら 1、でなければ 0))
20be503cae 2010-11-24        kinaba:   )
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: )
20be503cae 2010-11-24        kinaba: ))
20be503cae 2010-11-24        kinaba: 
20be503cae 2010-11-24        kinaba: )
20be503cae 2010-11-24        kinaba: Macros:
20be503cae 2010-11-24        kinaba:     TITLE=Polemy Reference Manual
20be503cae 2010-11-24        kinaba:     DOCFILENAME=index.html
20be503cae 2010-11-24        kinaba:     SECTION=$(DDOC_DECL $(DDOC_PSYMBOL $1)) $(DDOC_DECL_DD $2)
20be503cae 2010-11-24        kinaba:     SECBODY=$0