Overview
SHA1 Hash: | 20be503cae05074ce66a474f0b525a2489d4eb8b |
---|---|
Date: | 2010-11-24 12:30:56 |
User: | kinaba |
Comment: | set up referece manual |
Timelines: | family | ancestors | descendants | both | trunk |
Downloads: | Tarball | ZIP archive |
Other Links: | files | file ages | manifest |
Tags And Properties
- branch=trunk inherited from [f65680e1d2]
- sym-trunk inherited from [f65680e1d2]
Changes
Modified .poseidon from [2aef71c310b2301f] to [836851406ea9429f].
7 7 <filter>*.d</filter> 8 8 <showemptyfolder>0</showemptyfolder> 9 9 <buildSpec> 10 10 <buildType>0</buildType> 11 11 <mainFile>main.d</mainFile> 12 12 <Args /> 13 13 <options> 14 - <dmd> -D -Dddoc -g -unittest </dmd> 14 + <dmd> -g -unittest </dmd> 15 15 <tool /> 16 16 <lib /> 17 17 <implib /> 18 - <extra>doc\candydoc\candy.ddoc doc\candydoc\modules.ddoc</extra> 18 + <extra /> 19 19 <toolextra /> 20 20 <merge>0</merge> 21 21 <nonfiles>0</nonfiles> 22 22 <useimplib>0</useimplib> 23 23 <mapfile>0</mapfile> 24 24 <gcstub>0</gcstub> 25 25 </options> ................................................................................ 48 48 </source> 49 49 <interface /> 50 50 <resource /> 51 51 <othersDMD /> 52 52 <others> 53 53 <name>build.bat</name> 54 54 <name>build.sh</name> 55 - <name>doc\candydoc\candy.ddoc</name> 55 + <name>builddoc.bat</name> 56 56 <name>doc\candydoc\modules.ddoc</name> 57 + <name>index.dd</name> 57 58 <name>readme.txt</name> 58 59 </others> 59 60 </projectFiles> 60 61 <includePaths /> 61 62 <linkLibrarys /> 62 63 <importExpressions /> 63 64 </buildSpec> 64 65 </projectDescription>
Added builddoc.bat version [3483396bbcf61fe3]
1 +@setlocal ENABLEDELAYEDEXPANSION 2 +@set ARGS= 3 +@for %%I in (main.d polemy\*.d tricks\*.d) do @set ARGS=!ARGS! %%I 4 +@if not exist bin mkdir bin 5 +@echo dmd -o- -D -Dddoc index.dd doc\candydoc\candy.ddoc doc\candydoc\modules.ddoc %ARGS% 6 +@dmd -o- -D -Dddoc index.dd doc\candydoc\candy.ddoc doc\candydoc\modules.ddoc %ARGS%
Modified doc/candydoc/modules.ddoc from [0a368b5142d88e21] to [78fbfc498c081cb1].
1 1 MODULES = 2 + $(MODULE index) 2 3 $(MODULE main) 3 4 $(MODULE tricks.tricks) 4 5 $(MODULE tricks.test) 5 6 $(MODULE polemy._common) 6 7 $(MODULE polemy.failure) 7 8 $(MODULE polemy.layer) 8 9 $(MODULE polemy.fresh)
Added index.dd version [f78a001ef162c560]
1 +Ddoc 2 +$(DDOC_AUTHORS k.inaba) 3 +$(DDOC_LICENSE NYSL 0.9982 (http://www.kmonos.net/nysl/)) 4 + 5 +<p> 6 +このファイルは、言語仕様などの簡単な説明です。 7 +</p> 8 +<p> 9 +あとついでに、左のサイドバーの "Package" タブをクリックすると実装のソースのドキュメントが読めます。 10 +</p> 11 + 12 +$(DDOC_MEMBERS 13 + 14 +$(SECTION Syntax, $(SECBODY 15 + 16 +<p> 17 +文法について。 18 +字句解析がわりと適当なので、 19 +変数宣言の変数名のところに、数字を変数名として使えて参照できない変数が作れたり、 20 +予約語は予約語として解釈され得ないところでは普通に変数名として使えちゃったりして、 21 +偶にとんでもない見かけのソースが構文解析通りますが、気にしないで適当に使って下さい。 22 +</p> 23 + 24 +$(DDOC_MEMBERS 25 + 26 +$(SECTION 文字コード, $(SECBODY 27 +<p> 28 +UTF-8 のみ対応です。 29 +</p> 30 +)) 31 + 32 +$(SECTION コメント, $(SECBODY 33 +<p> 34 +行コメントは <tt>#</tt> から改行までです。 35 +</p> 36 +<p> 37 +ブロックコメントはありません。 38 +</p> 39 +)) 40 + 41 +$(SECTION BNF, $(SECBODY 42 +<pre> 43 + ID ::= 適当に識別子っぽい文字列 44 + LAYER ::= "@" ID 45 + 46 + E ::= 47 + $(D_COMMENT # 変数宣言) 48 + | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E 49 + | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E 50 + | ("var"|"let"|"def"|LAYER) ID "=" E 51 + | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" 52 + 53 + $(D_COMMENT # リテラル) 54 + | INTEGER $(D_COMMENT # 非負整数) 55 + | STRING $(D_COMMENT # "" でくくった文字列。\" と \\ は使える) 56 + | "{" ENTRYS "}" $(D_COMMENT # テーブル) 57 + | "fun" "(" PARAMS ")" "{" E "}" $(D_COMMENT # 無名関数) 58 + | "λ" "(" PARAMS ")" "{" E "}" $(D_COMMENT # 無名関数) 59 + 60 + $(D_COMMENT # 関数呼び出し) 61 + | E "(" ARGS")" 62 + 63 + where ARGS ::= E "," ... "," E 64 + PARAMS ::= (ID|LAYER)+ "," ... "," (ID|LAYER)+ 65 + ENTRYS ::= ID ":" E "," ... "," ID ":" E 66 + 67 + $(D_COMMENT # 演算子など) 68 + | "(" E ")" $(D_COMMENT # ただの括弧) 69 + | E BINOP E $(D_COMMENT # 二項演算子いろいろ) 70 + | E "." ID $(D_COMMENT # テーブルのフィールドアクセス) 71 + | E ".?" ID $(D_COMMENT # テーブルにフィールドがあるか否か) 72 + | E "{" ENTRYS "}" $(D_COMMENT # テーブル拡張) 73 + | "if" "(" E ")" "{" E "}" 74 + | "if" "(" E ")" "{" E "}" "else "{" E "}" 75 + 76 + $(D_COMMENT # パターンマッチ) 77 + | "case" "(" E ")" ("when" "(" PATTERN ")" "{" E "}")* 78 + 79 + where PATTERN ::= 式がだいたいなんでも書ける気がする 80 + 81 + $(D_COMMENT # レイヤ指定実行) 82 + | LAYER "(" E ")" 83 +</pre> 84 +)) 85 + 86 +$(SECTION 糖衣構文, $(SECBODY 87 +<p> 88 +演算子というものはありません。内部的には全て関数呼び出し構文に書き換えられています。<tt>if</tt> もです。 89 +<br/> 90 +パターンマッチも全部 <tt>if</tt> と <tt>==</tt> と <tt>&&</tt> と 91 +<tt>.</tt> と <tt>.?</tt> を使った関数呼び出し式に書き換えられていますが、 92 +規則の詳細を説明するのが面倒なので適当に想像して下さい。 93 +他の書き換えはこんな感じです。 94 +</p> 95 +<pre> 96 + if (E) then{E} ⇒ if( E, fun(){E}, fun(){} ) 97 + if (E) then{E} else{E} ⇒ if( E, fun(){E}, fun(){E} ) 98 + E BINOP E ⇒ BINOP(E, E) 99 + { ENTRIES } ⇒ {}{ ENTRIES } 100 + {} ⇒ {}() 101 + E {ID:E, ...} ⇒ .=(E, ID, E) { ... } 102 +</pre> 103 +<p> 104 +変数宣言に色々ありますが、<tt>let</tt> と <tt>var</tt> と <tt>def</tt> は同じ扱いで、 105 +<tt>in</tt> と <tt>;</tt> は同じ扱いです。つまり 106 +</p> 107 +<pre> 108 + let x = E in E 109 + var x = E in E 110 + def x = E in E 111 + let x = E ; E 112 + var x = E ; E 113 + def x = E ; E 114 +</pre> 115 +<p> 116 +以上のどれも同じ意味なので、なんとなく関数型っぽく書きたい気分の日は <tt>let in</tt> を、 117 +手続き型っぽく書きたい気分の日は <tt>var ;</tt> を使うとよいでしょう。 118 +</p> 119 +<p> 120 +関数を宣言するときは、<tt>fun</tt> や <tt>λ</tt> を省略できます。 121 +以下の書き換えが行われます。 122 +</p> 123 +<pre> 124 + def f( ARGS ) { E }; E ⇒ def f = fun(ARGS){E}; E 125 +</pre> 126 +<p> 127 +他に、もっと手続き型っぽくための書き換え色々 128 +</p> 129 +<pre> 130 + fun () { E; E; E } ⇒ fun () { let _ = E in let _ = E in E } 131 + fun () { var x = 100 } ⇒ fun () { var x = 100; x } 132 + fun () { var x = 100; } ⇒ fun () { var x = 100; x } 133 + fun () { } ⇒ fun () { "(empty function body)" } 134 +</pre> 135 +<p> 136 +中身が空の関数に何を返させるかは適当です。今はとりあえず適当に文字列返してます。 137 +</p> 138 +)) 139 + 140 +$(SECTION 変数のスコープ規則, $(SECBODY 141 +<p> 142 +NOTE: Theres no "let rec" syntax, but still recursive definition works 143 + def f(x) { if(x==0){1}else{x*f(x-1)} } in f(10) #=> 3628800 144 + yet still the code below also works 145 + def x=21 in def x=x+x in x #=> 42. 146 + The internal scoping mechanism is a little tricky (this is for coping with 147 + the "layer" feature explained below), but I hope that it works as everyone 148 + expects in most cases, as long as you don't use the same-name-variables heavily :). 149 +</p> 150 +)) 151 + 152 +)) 153 + 154 + 155 + 156 + 157 +$(SECTION Basic Features, $(SECBODY 158 +<p> 159 +特に特徴的でもない部分を簡単にまとめ。 160 +</p> 161 +<ul> 162 + <li>静的型システムはありません。</li> 163 + <li>"ほぼ" 純粋関数型言語です。変数やテーブルのフィールドの破壊的な書き換えはできません。<br/> 164 + ただし、組み込み関数(<tt>print</tt>)と、変数のスコープ規則のマジカルな片隅に副作用があります。</li> 165 +</ul> 166 +<p> 167 +静的型システムがないのは意図的ですが、破壊的代入がないのは、単に実装がめんどかっただけなので、 168 +今後何か増えるかもしれません。増えないかもしれません。 169 +</p> 170 +$(DDOC_MEMBERS 171 +$(SECTION データ型, $(SECBODY 172 +<p> 173 +以下のデータ型があります。 174 +</p> 175 +<ul> 176 + <li>整数: <tt>0</tt>, <tt>123</tt>, <tt>456666666666666666666666666666666666666789</tt>, ...</li> 177 + <li>文字列: <tt>"hello, world!"</tt>, ...</li> 178 + <li>関数: <tt>fun(x){x+1}</tt></li> 179 + <li>テーブル: <tt>{car: 1, cdr: {car: 2, cdr: {}}}</tt></li> 180 + <li>未定義値: (テーブルの、存在しないフィールドにアクセスしたりすると作れます)</li> 181 +</ul> 182 +<p> 183 +関数はいわゆる「クロージャ」です。静的スコープで外側の環境にアクセスできます。 184 +テーブルはいわゆるプロトタイプチェーンを持っていて、 185 +自分にないフィールドの場合は親に問い合わせが行く感じになっていますが、 186 +フィールドの書き換えがないので、これは特に意味ないかもしれない…。 187 +</p> 188 +)) 189 +$(SECTION パターンマッチ, $(SECBODY 190 +pattern matching is also available. Here is an example. 191 + 192 + def adjSum(lst) 193 + { 194 + case( lst ) 195 + when( {car:x, cdr:{car: y, cdr:z}} ) { {car: x+y, cdr: adjSum(z)} } 196 + when( {car:x, cdr:{}} ) { {car: x, cdr: {}} } 197 + when( {} ) { {} } 198 + }; 199 + 200 +It is expanded to a sequence of if-then-elses prefering the first-match. 201 +Note that {a: _} pattern matches all the tables that have the .a field. 202 +It also matches to {a: 123, b: 456} having extra .b field. So, changing the 203 +order of "when"s in the above code changes the behavior. 204 +)) 205 +) 206 +)) 207 + 208 + 209 + 210 + 211 + 212 +$(SECTION Layers, $(SECBODY 213 +<pre> 214 +[Layers :: Overview] 215 + 216 + Polemy's runtime environment has many "layer"s. 217 + Usual execution run in the @value layer. 218 + 219 + >> 1 + 2 220 + 3 221 + >> @value( 1 + 2 ) 222 + 3 223 + 224 + Here you can see that @LayerName( Expression ) executes the inner Expression in 225 + the @LayerName layer. Other than @value, one other predefined layer exists: @macro. 226 + 227 + >> @macro( 1+2 ) 228 + {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 229 + is@value:app, 230 + args@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 231 + is@value:int, 232 + data@value:1}, 233 + cdr@value:{ 234 + car@value:{pos@value:{lineno@value:3, column@value:11, filename@value:<REPL>}, 235 + is@value:int, 236 + data@value:2}, 237 + cdr@value:{}}}, 238 + fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL>}, 239 + is@value:var, 240 + name@value:+}} 241 + 242 + (Sorry, this pretty printing is not available on the actual interpreter...) 243 + This evaluates the expression 1+2 in the @macro layer. In this layer, the meaning of 244 + the program is its abstract syntax tree. 245 + 246 + You can interleave layers. 247 + The root node of the abstract syntax tree is function "app"lication. 248 + 249 + >> @value(@macro( 1+2 ).is) 250 + app 251 + 252 + 253 + 254 +[Layers :: Defining a new layer] 255 + 256 + To define a new layer, you should first tell how to "lift" existing values two the new layer. 257 + Let us define the "@type" layer, where the meaning of programs is their static type. 258 + 259 + >> @@type = fun(x) { 260 + >> if( _isint(x) ) { "int" } else { 261 + >> if( _isfun(x) ) { x } else { "unknown" } } 262 + >> } 263 + (Note: polemy REPL may warn some exception here but please ignore) 264 + 265 + For simplicity, I here deal only with integers. 266 + _isint is a primitive function of Polemy that checks the dynamic type of a value. 267 + For function, leaving it untouched works well for almost all layers. 268 + 269 + >> @type( 1 ) 270 + int 271 + >> @type( 2 ) 272 + int 273 + >> @type( "foo" ) 274 + unknown 275 + 276 + Fine! Let's try to type 1+2. 277 + 278 + >> @type( 1 + 2 ) 279 + ...\value.d(119): [<REPL>:6:8] only @value layer can call native function 280 + 281 + Note that the behavior of this program is 282 + - run 1+2 in the @type layer 283 + and NOT 284 + - run 1+2 in @value and obtain 3 and run 3 in the @type. 285 + The problem is, the variable "+" is defined only in the @value layer. 286 + To carry out computation in the @type layer. We need to define it also 287 + in the @type layer. 288 + 289 + To define some variable in a specific layer, use @LayerName in place of 290 + (let|var|def)s. 291 + 292 + >> let x = 2 293 + >> @value x = 2 294 + >> @type x = "int" 295 + >> @hoge x = "fuga" 296 + 297 + For "+", do it like this. 298 + 299 + >> @type "+" = fun(x,y) {@value( 300 + >> if( @type(x)=="int" && @type(y)=="int" ) { "int" } else { "typeerror" } 301 + >> )} 302 + polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24 303 + 304 + It is just computing the return type from the input type. 305 + Not here that the intended "meaning" of if-then-else is the runtime-branching, 306 + and the meaning of "==" is the value-comparison. These are the @value layer 307 + behavior. So we have defined the function body inside @value layer. 308 + But when we refer the variables x and y, we need its @type layer meaning. 309 + Hence we use @type() there. 310 + 311 + Now we get it. 312 + 313 + >> @type( 1 + 2 ) 314 + int 315 + 316 + Well, but do we have to define the @type layer meaning for every variables??? 317 + No. After you defined @type "+", you'll automatically get the following: 318 + 319 + >> def double(x) { x + x } 320 + (function:17e4740:1789720) 321 + 322 + >> @type( double(123) ) 323 + int 324 + 325 + Every user-defined functions are automatically "lift"ed to the appropriate layer. 326 + Only primitive functions like "+" requires @yourNewLayer annotation. 327 + 328 + 329 + 330 +[Layers :: neutral-layer] 331 + 332 + let|var|def is to define a variable in the "current" layer. 333 + Not necessary to the @value layer. 334 + 335 + >> @value( let x = 1 in @value(x) ) 336 + 1 337 + 338 + >> @macro( let x = 1 in @value(x) ) 339 + polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found 340 + 341 + >> @macro( let x = 1 in @macro(x) ) 342 + {pos@value:{lineno@value:15, ... 343 + 344 + 345 + 346 +[Layers :: Layered-Parameters] 347 + 348 + >> def foo(x @macro @value) { {fst: x, snd: @macro(x)} } 349 + (function:1730360:1789720) 350 + 351 + If you annotate function parameters by @LayerNames, when you invoke the function... 352 + 353 + >> foo(1+2) 354 + {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REPL>}, 355 + is@value:app, arg@value:{... 356 + /fst@value:3 357 + /} 358 + 359 + its corresponding arguments are evaluated in the layer and passed to it. 360 + If you specify multiple layers, the argument expression is run multiple times. 361 + If you do not specify any layer for a parameter, it works in the neutral layer. 362 + 363 + 364 + 365 +[@macro layer] 366 + 367 + When function is invoked, it first run in the @macro layer, and after that, 368 + it run in the neutral layer. Here is an example. 369 + 370 + >> @macro twice(x) { x; x } 371 + >> def f() { twice(print("Hello")); 999 } 372 + (function:173b6a0:1789720) 373 + >> f() 374 + Hello 375 + Hello 376 + 999 377 + 378 + When the interpreter evaluates f(), it first executes 379 + "twice(print("Hello")); 999" 380 + in the @macro layer. Basically what it does is to just construct its syntax tree. 381 + But, since we have defined the "twice" function in the @macro layer, it is 382 + execute as a function. Resulting syntax tree is 383 + "print("Hello"); print("Hello"); 999" 384 + and this is executed on the neutral (in this example, @value) layer. 385 + This is the reason why you see two "Hello"s. 386 + 387 + 388 + 389 + [[limitations]] 390 + 391 + This @macro layer is a very primitive one, and not a perfect macro language. 392 + Two major limitations are seen in the following "it" example. 393 + 394 + >> @macro LetItBe(x, y) { let it = x in y }; 395 + 396 + The variable name is not hygenic, and so without any effort, the syntax tree "y" 397 + can access the outer variable "it". 398 + 399 + >> def foo() { LetItBe( 1+2+3, it*it ) } 400 + >> foo() 401 + 36 402 + 403 + Of course, this is not just a limitation; it can sometimes allow us to write 404 + many interesting macros. 405 + 406 + The other problem is that the macro expansion is only done at function startup. 407 + So 408 + 409 + >> LetItBe( 1+2+3, it*it ) 410 + ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value 411 + 412 + you cannot directly use the macro in the same scope as the definition. 413 + You need to wrap it up in a function (like the foo() in the above example). 414 + 415 + 416 + 417 + [[quote and unquote]] 418 + 419 + Here is more involved example of code genration. 420 + From "x", it generates "x*x*x*x*x*x*x*x*x*x". 421 + 422 + @macro pow10(x) { 423 + @value( 424 + def pow(x, n) { 425 + if( n == 1 ) { x } 426 + else { 427 + @macro( @value(x) * @value(pow(x,n-1)) ) 428 + } 429 + } 430 + in 431 + pow(@macro(x),10) 432 + ) 433 + }; 434 + 435 + Here, x is a syntax tree but n is an actual integer. If you read carefully, 436 + you should get what is going on. Basically, @macro can be considered like 437 + quasiquoting and @value to be an escape from it. 438 +</pre> 439 +)) 440 + 441 + 442 +$(SECTION Built-in Primitives, $(SECBODY 443 +<p> 444 +組み込み関数・変数の一覧。 445 +</p> 446 +$(DDOC_MEMBERS 447 + 448 +$(SECTION テーブル操作, $(SECBODY 449 + $(TABLE 450 + $(TR $(TH {}) $(TD ()) $(TD 空のテーブルを作る)) 451 + $(TR $(TH .) $(TD (t, s)) $(TD テーブル t の名前 s のフィールドの値を取得。なければ <tt>undefined</tt>)) 452 + $(TR $(TH .?) $(TD (t, s)) $(TD テーブル t に名前 s のフィールドがあれば 1、なければ 0)) 453 + $(TR $(TH .=) $(TD (t, s, v)) $(TD テーブル t を親に持ち、名前 s のフィールドに v が入ったテーブルを作る)) 454 + ) 455 +)) 456 +<br /> 457 + 458 +$(SECTION 制御フロー, $(SECBODY 459 + $(TABLE 460 + $(TR $(TH if) $(TD (n, ft, fe)) $(TD n が非 0 なら <tt>ft()</t>、0 なら <tt>fe()</tt> を実行)) 461 + ) 462 +)) 463 +<br /> 464 + 465 +$(SECTION 演算, $(SECBODY 466 + $(TABLE 467 + $(TR $(TH +) $(TD (n, m)) $(TD 整数 n と整数 m を足して返す)) 468 + $(TR $(TH -) $(TD (n, m)) $(TD 整数の引き算)) 469 + $(TR $(TH *) $(TD (n, m)) $(TD 整数の掛け算)) 470 + $(TR $(TH /) $(TD (n, m)) $(TD 整数の割り算)) 471 + $(TR $(TH %) $(TD (n, m)) $(TD 整数の剰余)) 472 + $(TR $(TH &&) $(TD (n, m)) $(TD 整数 n と m が両方非 0 なら 1、それ以外では 0)) 473 + $(TR $(TH ||) $(TD (n, m)) $(TD 整数 n と m がどちらか非 0 なら 1、それ以外では 0)) 474 + $(TR $(TH ~) $(TD (a, b)) $(TD a と b を文字列化して結合)) 475 + $(TR $(TH <) $(TD (a, b)) $(TD a と b を比較)) 476 + $(TR $(TH <=) $(TD (a, b)) $(TD a と b を比較)) 477 + $(TR $(TH >) $(TD (a, b)) $(TD a と b を比較)) 478 + $(TR $(TH >=) $(TD (a, b)) $(TD a と b を比較)) 479 + $(TR $(TH ==) $(TD (a, b)) $(TD a と b を比較)) 480 + $(TR $(TH !=) $(TD (a, b)) $(TD a と b を比較)) 481 + ) 482 +<p> 483 +注意点として、作者の趣味の問題で、<tt>&&</tt> と <tt>||</tt> は short-circuit 評価をしません。 484 +整数演算の種類が少ないのは、D 言語の std.bigint がビット演算などをサポートしてないためです。 485 +文字列が結合しかできないのは、単に手抜きです。 486 +</p> 487 +)) 488 + 489 +$(SECTION 外部とのやりとり, $(SECBODY 490 + $(TABLE 491 + $(TR $(TH print) $(TD (a)) $(TD a を文字列化標準出力に改行付きで表示)) 492 + $(TR $(TH argv) $(TD ) $(TD スクリプトに渡された引数文字列のconsリスト)) 493 + ) 494 +)) 495 +<br /> 496 + 497 +$(SECTION データ型判定, $(SECBODY 498 + $(TABLE 499 + $(TR $(TH _isint) $(TD (a)) $(TD a が整数なら 1、でなければ 0)) 500 + $(TR $(TH _isstr) $(TD (a)) $(TD a が文字列なら 1、でなければ 0)) 501 + $(TR $(TH _isfun) $(TD (a)) $(TD a が関数なら 1、でなければ 0)) 502 + $(TR $(TH _istable) $(TD (a)) $(TD a がテーブルなら 1、でなければ 0)) 503 + $(TR $(TH _isundefined) $(TD (a)) $(TD a が未定義値なら 1、でなければ 0)) 504 + ) 505 +)) 506 +) 507 +)) 508 + 509 +) 510 +Macros: 511 + TITLE=Polemy Reference Manual 512 + DOCFILENAME=index.html 513 + SECTION=$(DDOC_DECL $(DDOC_PSYMBOL $1)) $(DDOC_DECL_DD $2) 514 + SECBODY=$0
Modified polemy/eval.d from [cd1c3d2598ac30ce] to [e0978d70034e5fac].
245 245 text("non-function ", _f, " is registered as the lift function for ", lay)); 246 246 } 247 247 248 248 Value createNewFunction(Fun e, Table ctx) 249 249 { 250 250 class UserDefinedFunValue : FunValue 251 251 { 252 - Fun ast; 253 - Table defCtx; 252 + Fun ast; 253 + Table defCtx; 254 254 override const(Parameter[]) params() { return ast.params; } 255 - override Table definitionContext() { return defCtx; } 255 + override Table definitionContext() { return defCtx; } 256 256 257 257 this(Fun ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; } 258 258 override string toString() const { return sprintf!"(function:%x:%x)"(cast(void*)ast, cast(void*)defCtx); } 259 - override bool opEquals(Object rhs_) const /// member-by-member equality 260 - { 261 - if( auto rhs = cast(typeof(this))rhs_ ) 262 - return this.ast==rhs.ast && this.defCtx==rhs.defCtx; 263 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 264 - } 265 - override hash_t toHash() const /// member-by-member hash 266 - { 267 - return typeid(this.ast).getHash(&this.ast) + typeid(this.defCtx).getHash(&this.defCtx); 259 + override int opCmp(Object rhs) { 260 + if(auto r = cast(UserDefinedFunValue)rhs) { 261 + if(auto i = this.ast.opCmp(r.ast)) 262 + return i; 263 + return this.defCtx.opCmp(r.defCtx); 264 + } 265 + if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 266 + throw genex!RuntimeException("comparison with value and something other"); 268 267 } 269 - override int opCmp(Object rhs_) /// member-by-member compare 270 - { 271 - if( auto rhs = cast(typeof(this))rhs_ ) 272 - { 273 - if(auto i = this.ast.opCmp(rhs.ast)) 274 - return i; 275 - return this.defCtx.opCmp(rhs.defCtx); 276 - } 277 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 278 - } 268 + mixin SimpleToHash; 279 269 270 + AST afterMacroAST; 280 271 override Value invoke(Layer lay, Table ctx, LexPosition pos) 281 272 { 282 273 if( isASTLayer(lay) ) 283 274 return eval(ast.funbody, lay, ctx); 284 275 if( afterMacroAST is null ) 285 276 { 286 277 auto va = macroAndEval(e.funbody, lay, ctx); 287 278 afterMacroAST = va[1]; 288 279 return va[0]; 289 280 } 290 281 else 291 282 return eval(afterMacroAST, lay, ctx); 292 283 } 293 - 294 - AST afterMacroAST; 295 284 } 296 285 return new UserDefinedFunValue(e,ctx); 297 286 } 298 287 299 288 public: 300 289 /// Add primitive function to the global context 301 290 void addPrimitive(R,T...)(string name, Layer defLay, R delegate (T) dg) ................................................................................ 305 294 override const(Parameter[]) params() { return params_data; } 306 295 override Table definitionContext() { return theContext; } 307 296 308 297 override string toString() { return sprintf!"(native:%x)"(dg.funcptr); } 309 298 override int opCmp(Object rhs) { 310 299 if(auto r = cast(NativeFunValue)rhs) return typeid(typeof(dg)).compare(&dg,&r.dg); 311 300 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 312 - throw genex!RuntimeException(LexPosition.dummy, "comparison with value and somithing other"); 301 + throw genex!RuntimeException(LexPosition.dummy, "comparison with value and something other"); 313 302 } 314 303 mixin SimpleToHash; 315 304 316 305 R delegate(T) dg; 317 306 Parameter[] params_data; 318 307 319 308 this(R delegate(T) dg)
Modified polemy/failure.d from [1bc945d1d318d417] to [9cdb01160429b059].
1 -/** 1 +/** 2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Error Information for Polemy Programming Language 6 6 */ 7 7 module polemy.failure; 8 8 import polemy._common;
Modified polemy/fresh.d from [72c1e0f374b13246] to [15707244447f6971].
1 -/** 1 +/** 2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Interpreter-wise fresh ID generator. 6 6 */ 7 7 module polemy.fresh; 8 8 import polemy._common;
Modified polemy/layer.d from [bd983db748e0ad6a] to [ec0e00bb40d202e7].
1 -/** 1 +/** 2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Definition of constants related to the layers. 6 6 */ 7 7 module polemy.layer; 8 8 import polemy._common;
Modified polemy/parse.d from [bacc00f3f91907a9] to [64474993b2d6bb44].
433 433 SinglePattern[] parsePattern(string[] path = null) 434 434 { 435 435 SinglePattern[] result; 436 436 if( tryEat("{") ) 437 437 { 438 438 if( !tryEat("}") ) { 439 439 do { 440 - string key = eatId("in table pattern"); 440 + string key = eatId("in table pattern", AllowQuoted); 441 441 eat(":", "after field-id in table pattern"); 442 442 result ~= parsePattern(path ~ key); 443 443 } while( tryEat(",") ); 444 444 eat("}", "at the end of table pattern"); 445 445 } 446 446 } 447 447 else
Modified polemy/value.d from [43e26264d772abeb] to [dc69a053821951bd].
27 27 this(long n) { this.data = n; } 28 28 this(BigInt n) { this.data = n; } 29 29 this(string n) { this.data = BigInt(n); } 30 30 override string toString() const { return toDecimalString(cast(BigInt)data); } 31 31 override int opCmp(Object rhs) { 32 32 if(auto r = cast(IntValue)rhs) return data.opCmp(r.data); 33 33 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 34 - throw genex!RuntimeException(LexPosition.dummy, "comparison with value and somithing other"); 34 + throw genex!RuntimeException("comparison with value and somithing other"); 35 35 } 36 36 mixin SimpleToHash; 37 37 } 38 38 39 39 /// 40 40 class StrValue : Value 41 41 { ................................................................................ 42 42 string data; 43 43 44 44 mixin SimpleConstructor; 45 45 override string toString() const { return data; } 46 46 override int opCmp(Object rhs) { 47 47 if(auto r = cast(StrValue)rhs) return typeid(string).compare(&data, &r.data); 48 48 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 49 - throw genex!RuntimeException(LexPosition.dummy, "comparison with value and somithing other"); 49 + throw genex!RuntimeException("comparison with value and somithing other"); 50 50 } 51 51 mixin SimpleToHash; 52 52 } 53 53 54 54 /// 55 55 class UndefinedValue : Value 56 56 { 57 57 mixin SimpleConstructor; 58 58 override string toString() const { return "<undefined>"; } 59 59 override int opCmp(Object rhs) { 60 60 if(auto r = cast(StrValue)rhs) return 0; 61 61 if(auto r = cast(Value)rhs) return typeid(this).opCmp(typeid(r)); 62 - throw genex!RuntimeException(LexPosition.dummy, "comparison with value and somithing other"); 62 + throw genex!RuntimeException("comparison with value and somithing other"); 63 63 } 64 64 mixin SimpleToHash; 65 65 } 66 66 67 67 /// 68 68 abstract class FunValue : Value 69 69 {
Modified readme.txt from [78aa08fe5254309c] to [1c7e412d38c82eb6].
1 1 ----------------------------------------------------------------------------- 2 2 Polemy 0.1.0 3 3 by k.inaba (www.kmonos.net) 4 - Nov 20, 2010 4 + Nov 24, 2010 5 5 ----------------------------------------------------------------------------- 6 6 7 - 8 - 9 -<<How to Build>> 7 +[How to Build] 10 8 11 9 - Install DMD 12 10 http://www.digitalmars.com/d/2.0/changelog.html 13 11 Version 2.050 is recommended. Older or newer version may not work. 14 12 15 13 - Build 16 14 (for Windows) Run build.bat ................................................................................ 17 15 (for Unix) Run build.sh 18 16 or use your favorite build tools upon main.d and polemy/*.d. 19 17 20 18 Then you will get the executable "polemy" in the "bin" directory. 21 19 22 20 23 21 24 -<<License>> 22 +[License] 25 23 26 24 d2stacktrace/* 27 25 28 26 is written by Benjamin Thaut and licensed under 2-clause BSD License. 29 27 See http://3d.benjamin-thaut.de/?p=15 for the detail. 30 28 31 29 (this package is used only for enabling stack-traces during printing exceptions; ................................................................................ 35 33 main.d 36 34 37 35 All the other parts are written by Kazuhiro Inaba and 38 36 licensed under NYSL 0.9982 ( http://www.kmonos.net/nysl/ ). 39 37 40 38 41 39 42 -<<How to Use>> 40 +[How to Use] 43 41 44 42 > polemy 45 43 starts REPL 46 44 47 45 > polemy foo.pmy 48 46 executes foo.pmy 49 47 ................................................................................ 51 49 after executing foo.pmy, starts REPL 52 50 53 51 > polemy -l foo.pmy -l bar.pmy buz.pmy 54 52 executes foo.pmy, bar.bmy, and then buz.pmy 55 53 56 54 57 55 58 -<<Syntax>> 59 - 60 - Comment is "# ... \n" 61 - 62 - E ::= 63 - // declaration 64 - | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E 65 - | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E 66 - | ("var"|"let"|"def"|LAYER) ID "=" E 67 - | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" 68 - // literal 69 - | INTEGER 70 - | STRING 71 - | "{" ENTRYS "}" // table 72 - | "fun" "(" PARAMS ")" "{" E "}" // anonymous function 73 - // function call 74 - | E "(" ARGS")" 75 - where ARGS ::= E "," ... "," E 76 - PARAMS ::= ID LAYER* "," ... "," ID LAYER* 77 - ENTRYS ::= ID ":" E "," ... "," ID ":" E 78 - ID ::= 'a-zA-Z0-9_...'+ 79 - LAYER ::= "@" ID 80 - // operators 81 - | "(" E ")" 82 - | E "." ID // table field access 83 - | E ".?" ID // table field existence check 84 - | E "{" ENTRYS "}" // table extend (pure functionally) 85 - | E BINOP E 86 - | "if" "(" E ")" "{" E "}" 87 - | "if" "(" E ")" "{" E "}" "else "{" E "}" 88 - // layered exec 89 - | LAYER "(" E ")" 56 +[Language Reference] 90 57 91 -The following are actually rewritten to function calls: 92 - 93 - - if (E) then{E} else{E} ==> if( E, fun(){E}, fun(){E} ) 94 - - E BINOP E ==> BINOP(E, E) 95 - - E.ID ==> . (E, ID) 96 - - E.?ID ==> .?(E, ID) 97 - - {} ==> {}() 98 - - { ENTRIES } ==> {}{ ENTRIES } 99 - - E {ID:E, ...} ==> (.=(E, ID, E)) { ... } 100 - 101 -Several styles of variable declaration can be used: 102 - 103 - - fun(x){ fun(y){x} } # K-combinator 104 - - fun(x){ let f = fun(y){x} in f } # let-in style 105 - - fun(x){ var f = fun(y){x}; f } # var-; style 106 - - fun(x){ def f = fun(y){x} in f } # you can use any combination of (let|var|def)-(;|in) 107 - - fun(x){ def f(y){x} in f } # syntax sugar for function declaration 108 - - fun(x){ let f(y){x}; f } # this is also ok 109 - - fun(x){ var f(y){x} } # omitting (;|in) returns the last declared object directly 110 - - fun(x,y){x} #< this is not equal to the above ones. functions are no curried. 111 - 112 -NOTE: Theres no "let rec" syntax, but still recursive definition works 113 - def f(x) { if(x==0){1}else{x*f(x-1)} } in f(10) #=> 3628800 114 - yet still the code below also works 115 - def x=21 in def x=x+x in x #=> 42. 116 - The internal scoping mechanism is a little tricky (this is for coping with 117 - the "layer" feature explained below), but I hope that it works as everyone 118 - expects in most cases, as long as you don't use the same-name-variables heavily :). 119 - 120 -(Experimental) pattern matching is also available. Here is an example. 121 - 122 - def adjSum(lst) 123 - { 124 - case( lst ) 125 - when( {car:x, cdr:{car: y, cdr:z}} ) { {car: x+y, cdr: adjSum(z)} } 126 - when( {car:x, cdr:{}} ) { {car: x, cdr: {}} } 127 - when( {} ) { {} } 128 - }; 129 - 130 -It is expanded to a sequence of if-then-elses prefering the first-match. 131 -Note that {a: _} pattern matches all the tables that have the .a field. 132 -It also matches to {a: 123, b: 456} having extra .b field. So, changing the 133 -order of "when"s in the above code changes the behavior. 134 - 135 - 136 - 137 - 138 -<<Basic Features>> 139 - 140 - Polemy is an untyped functional programming language that has 141 - - integers: 0, 123, 456666666666666666666666666666666666666789, ... 142 - - strings: "hello, world!\n", ... 143 - - tables: {car: 1, cdr: {car: 2, cdr: {}}} 144 - - functions: fun(x){x+1} 145 - as primitive datatypes. Functions capture lexical closures. 146 - It is almost 'pure' (except the primitve function "print" and some 147 - trick inside scoping mechanisms). 148 - 149 - 150 -<<Layers :: Overview>> 151 - 152 - Polemy's runtime environment has many "layer"s. 153 - Usual execution run in the @value layer. 154 - 155 - >> 1 + 2 156 - 3 157 - >> @value( 1 + 2 ) 158 - 3 159 - 160 - Here you can see that @LayerName( Expression ) executes the inner Expression in 161 - the @LayerName layer. Other than @value, one other predefined layer exists: @macro. 162 - 163 - >> @macro( 1+2 ) 164 - {pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 165 - is@value:app, 166 - args@value:{car@value:{pos@value:{lineno@value:3, column@value:9, filename@value:<REPL>}, 167 - is@value:int, 168 - data@value:1}, 169 - cdr@value:{ 170 - car@value:{pos@value:{lineno@value:3, column@value:11, filename@value:<REPL>}, 171 - is@value:int, 172 - data@value:2}, 173 - cdr@value:{}}}, 174 - fun@value:{pos@value:{lineno@value:3, column@value:10, filename@value:<REPL>}, 175 - is@value:var, 176 - name@value:+}} 177 - 178 - (Sorry, this pretty printing is not available on the actual interpreter...) 179 - This evaluates the expression 1+2 in the @macro layer. In this layer, the meaning of 180 - the program is its abstract syntax tree. 181 - 182 - You can interleave layers. 183 - The root node of the abstract syntax tree is function "app"lication. 184 - 185 - >> @value(@macro( 1+2 ).is) 186 - app 187 - 188 - 189 - 190 -<<Layers :: Defining a new layer>> 191 - 192 - To define a new layer, you should first tell how to "lift" existing values two the new layer. 193 - Let us define the "@type" layer, where the meaning of programs is their static type. 194 - 195 - >> @@type = fun(x) { 196 - >> if( _isint(x) ) { "int" } else { 197 - >> if( _isfun(x) ) { x } else { "unknown" } } 198 - >> } 199 - (Note: polemy REPL may warn some exception here but please ignore) 200 - 201 - For simplicity, I here deal only with integers. 202 - _isint is a primitive function of Polemy that checks the dynamic type of a value. 203 - For function, leaving it untouched works well for almost all layers. 204 - 205 - >> @type( 1 ) 206 - int 207 - >> @type( 2 ) 208 - int 209 - >> @type( "foo" ) 210 - unknown 211 - 212 - Fine! Let's try to type 1+2. 213 - 214 - >> @type( 1 + 2 ) 215 - ...\value.d(119): [<REPL>:6:8] only @value layer can call native function 216 - 217 - Note that the behavior of this program is 218 - - run 1+2 in the @type layer 219 - and NOT 220 - - run 1+2 in @value and obtain 3 and run 3 in the @type. 221 - The problem is, the variable "+" is defined only in the @value layer. 222 - To carry out computation in the @type layer. We need to define it also 223 - in the @type layer. 224 - 225 - To define some variable in a specific layer, use @LayerName in place of 226 - (let|var|def)s. 227 - 228 - >> let x = 2 229 - >> @value x = 2 230 - >> @type x = "int" 231 - >> @hoge x = "fuga" 232 - 233 - For "+", do it like this. 234 - 235 - >> @type "+" = fun(x,y) {@value( 236 - >> if( @type(x)=="int" && @type(y)=="int" ) { "int" } else { "typeerror" } 237 - >> )} 238 - polemy.value.native!(IntValue,IntValue,IntValue).native.__anonclass24 239 - 240 - It is just computing the return type from the input type. 241 - Not here that the intended "meaning" of if-then-else is the runtime-branching, 242 - and the meaning of "==" is the value-comparison. These are the @value layer 243 - behavior. So we have defined the function body inside @value layer. 244 - But when we refer the variables x and y, we need its @type layer meaning. 245 - Hence we use @type() there. 246 - 247 - Now we get it. 248 - 249 - >> @type( 1 + 2 ) 250 - int 251 - 252 - Well, but do we have to define the @type layer meaning for every variables??? 253 - No. After you defined @type "+", you'll automatically get the following: 254 - 255 - >> def double(x) { x + x } 256 - (function:17e4740:1789720) 257 - 258 - >> @type( double(123) ) 259 - int 260 - 261 - Every user-defined functions are automatically "lift"ed to the appropriate layer. 262 - Only primitive functions like "+" requires @yourNewLayer annotation. 263 - 264 - 265 - 266 -<<Layers :: neutral-layer>> 267 - 268 - let|var|def is to define a variable in the "current" layer. 269 - Not necessary to the @value layer. 270 - 271 - >> @value( let x = 1 in @value(x) ) 272 - 1 273 - 274 - >> @macro( let x = 1 in @value(x) ) 275 - polemy.failure.RuntimeException: [<REPL>:14:29] variable x not found 276 - 277 - >> @macro( let x = 1 in @macro(x) ) 278 - {pos@value:{lineno@value:15, ... 279 - 280 - 281 - 282 -<<Layers :: Layered-Parameters>> 283 - 284 - >> def foo(x @macro @value) { {fst: x, snd: @macro(x)} } 285 - (function:1730360:1789720) 286 - 287 - If you annotate function parameters by @LayerNames, when you invoke the function... 288 - 289 - >> foo(1+2) 290 - {snd@value: {pos@value:{lineno@value:17, column@value:5, filename@value:<REPL>}, 291 - is@value:app, arg@value:{... 292 - /fst@value:3 293 - /} 294 - 295 - its corresponding arguments are evaluated in the layer and passed to it. 296 - If you specify multiple layers, the argument expression is run multiple times. 297 - If you do not specify any layer for a parameter, it works in the neutral layer. 298 - 299 - 300 - 301 -<<@macro layer>> 302 - 303 - When function is invoked, it first run in the @macro layer, and after that, 304 - it run in the neutral layer. Here is an example. 305 - 306 - >> @macro twice(x) { x; x } 307 - >> def f() { twice(print("Hello")); 999 } 308 - (function:173b6a0:1789720) 309 - >> f() 310 - Hello 311 - Hello 312 - 999 313 - 314 - When the interpreter evaluates f(), it first executes 315 - "twice(print("Hello")); 999" 316 - in the @macro layer. Basically what it does is to just construct its syntax tree. 317 - But, since we have defined the "twice" function in the @macro layer, it is 318 - execute as a function. Resulting syntax tree is 319 - "print("Hello"); print("Hello"); 999" 320 - and this is executed on the neutral (in this example, @value) layer. 321 - This is the reason why you see two "Hello"s. 322 - 323 - 324 - 325 - [[limitations]] 326 - 327 - This @macro layer is a very primitive one, and not a perfect macro language. 328 - Two major limitations are seen in the following "it" example. 329 - 330 - >> @macro LetItBe(x, y) { let it = x in y }; 331 - 332 - The variable name is not hygenic, and so without any effort, the syntax tree "y" 333 - can access the outer variable "it". 334 - 335 - >> def foo() { LetItBe( 1+2+3, it*it ) } 336 - >> foo() 337 - 36 338 - 339 - Of course, this is not just a limitation; it can sometimes allow us to write 340 - many interesting macros. 341 - 342 - The other problem is that the macro expansion is only done at function startup. 343 - So 344 - 345 - >> LetItBe( 1+2+3, it*it ) 346 - ...\value.d(173): [<REPL>:24:1] variable LetItBe is not set in layer @value 347 - 348 - you cannot directly use the macro in the same scope as the definition. 349 - You need to wrap it up in a function (like the foo() in the above example). 350 - 351 - 352 - 353 - [[quote and unquote]] 354 - 355 - Here is more involved example of code genration. 356 - From "x", it generates "x*x*x*x*x*x*x*x*x*x". 357 - 358 - @macro pow10(x) { 359 - @value( 360 - def pow(x, n) { 361 - if( n == 1 ) { x } 362 - else { 363 - @macro( @value(x) * @value(pow(x,n-1)) ) 364 - } 365 - } 366 - in 367 - pow(@macro(x),10) 368 - ) 369 - }; 370 - 371 - Here, x is a syntax tree but n is an actual integer. If you read carefully, 372 - you should get what is going on. Basically, @macro can be considered like 373 - quasiquoting and @value to be an escape from it. 374 - 375 - 376 - 377 -<<Primitives>> 378 - 379 - {} 0-ary create-empty-table 380 - . 2-ary table-get 381 - .? 2-ary table-has? 382 - .= 3-ary table-set 383 - 384 - if 3-ary if-then-else 385 - 386 - + - * / % || && 2-ary integer-operations (NOTE! no short-circuit for && and ||.) 387 - < > <= >= == != 2-ary generic comparison 388 - ~ 2-ary string concatenation (works also for non-string objects) 389 - 390 - print 1-ary print-to-stdout 391 - 392 - _isint _isstr _isfun _isundefined _istable 1-ary dynamic-type-test 58 + See doc/index.html (in Japanese) 393 59