Diff
Not logged in

Differences From Artifact [78aa08fe5254309c]:

To Artifact [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