Check-in [36c517dfc4]
Not logged in
Overview
SHA1 Hash:36c517dfc4f61f6da464ea77ab97c1f36f382279
Date: 2010-11-23 19:09:03
User: kinaba
Comment:refactored d-value and polemy-value conversion
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified .poseidon from [92babe531ac51123] to [2aef71c310b2301f].

35 35 <name>polemy\ast.d</name> 36 36 <name>polemy\eval.d</name> 37 37 <name>polemy\failure.d</name> 38 38 <name>polemy\fresh.d</name> 39 39 <name>polemy\layer.d</name> 40 40 <name>polemy\lex.d</name> 41 41 <name>polemy\parse.d</name> 42 + <name>polemy\repl.d</name> 42 43 <name>polemy\runtime.d</name> 43 44 <name>polemy\value.d</name> 45 + <name>polemy\valueconv.d</name> 44 46 <name>tricks\test.d</name> 45 47 <name>tricks\tricks.d</name> 46 48 </source> 47 49 <interface /> 48 50 <resource /> 49 51 <othersDMD /> 50 52 <others>

Modified doc/candydoc/modules.ddoc from [5f7a14107fdf7182] to [0a368b5142d88e21].

5 5 $(MODULE polemy._common) 6 6 $(MODULE polemy.failure) 7 7 $(MODULE polemy.layer) 8 8 $(MODULE polemy.fresh) 9 9 $(MODULE polemy.lex) 10 10 $(MODULE polemy.parse) 11 11 $(MODULE polemy.ast) 12 + $(MODULE polemy.value) 13 + $(MODULE polemy.valueconv) 12 14 $(MODULE polemy.eval) 13 15 $(MODULE polemy.runtime) 14 - $(MODULE polemy.value) 16 + $(MODULE polemy.repl)

Modified main.d from [cbf6e2570b5a90b0] to [f44d615cc4428107].

1 1 /** 2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 (http://www.kmonos.net/nysl/) 4 4 * 5 5 * Entry point for Polemy interpreter. 6 6 */ 7 7 module main; 8 +import polemy.repl; 8 9 import std.stdio; 9 10 import std.algorithm; 10 11 import std.array; 11 -import polemy.value; 12 -import polemy.failure; 13 -import polemy.layer; 14 -import polemy.parse; 15 -import polemy.ast; 16 -import polemy.eval; 17 -import polemy.runtime; 18 - 19 -enum VersionNoMajor = 0; 20 -enum VersionNoMinor = 1; 21 -enum VersionNoRev = 0; 22 - 23 -/// Read-Eval-Print-Loop 24 - 25 -class REPL 26 -{ 27 -Evaluator ev; 28 - /// Load the prelude environment 29 - this() 30 - { 31 - ev = new Evaluator; 32 - enrollRuntimeLibrary(ev); 33 - } 34 - 35 - /// Print the version number etc. 36 - void greet() 37 - { 38 - writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNoMinor, VersionNoRev); 39 - } 40 - 41 - /// Run one file on the global scope 42 - void runFile(string filename) 43 - { 44 - ev.evalFile(filename); 45 - } 46 - 47 - /// Repeat the singleInteraction 48 - void replLoop() 49 - { 50 - while( singleInteraction() ) {} 51 - } 52 - 53 - /// Read one line from stdin, and do some reaction 54 - bool singleInteraction() 55 - { 56 - writef(">> ", lineno); 57 - string line = readln(); 58 - if( line.startsWith("exit") || line.startsWith("quit") ) 59 - return false; 60 - try { 61 - if( tryRun(line) ) 62 - writeln(lastVal); 63 - } catch(Throwable e) { 64 - writeln(e); 65 - } 66 - return true; 67 - } 68 - 69 -private: 70 - Table ctx; 71 - string buf; 72 - Value lastVal; 73 - int lineno = 1; 74 - int nextlineno = 1; 75 - 76 - bool tryRun( string s ) 77 - { 78 - scope(failure) 79 - { buf = ""; lineno = nextlineno; } 80 - 81 - buf ~= s; 82 - nextlineno ++; 83 - try 84 - { lastVal = ev.evalString(buf, "<REPL>", lineno); } 85 - catch( UnexpectedEOF ) 86 - { return false; } // wait 87 - buf = ""; 88 - lineno = nextlineno; 89 - return true; 90 - } 91 -} 92 12 93 13 /// Advance args[] to point the argument list fed to the script. 94 14 /// Returns the name of the source file to run, or returns "" if 95 15 /// no filename was given. Also, returns to libs[] the list of 96 16 /// library source to load. 97 17 98 18 string parseArgv(ref string[] args, out string[] libs) ................................................................................ 118 38 /// Entry point. 119 39 120 40 void main( string[] args ) 121 41 { 122 42 string[] libs; 123 43 string src = parseArgv(args, libs); 124 44 125 - auto r = new REPL; 45 + auto r = new REPL(args); 126 46 if( src.empty ) 127 47 r.greet(); 128 48 foreach(lb; libs) 129 49 r.runFile(lb); 130 50 if( src.empty ) 131 51 r.replLoop(); 132 52 else 133 53 r.runFile(src); 134 54 }

Modified polemy/_common.d from [05c4f6a92646def3] to [6dc6c83f7a158b25].

10 10 public import std.algorithm; 11 11 public import std.array; 12 12 public import std.bigint; 13 13 public import std.conv : text; 14 14 public import std.exception; 15 15 public import std.range; 16 16 public import std.stdio : DBG = writeln; 17 +public import std.traits; 17 18 public import std.typecons; 18 19 public import std.typetuple;

Modified polemy/eval.d from [5a9949a1eb8839b1] to [ca0ab118700475a8].

7 7 module polemy.eval; 8 8 import polemy._common; 9 9 import polemy.failure; 10 10 import polemy.ast; 11 11 import polemy.parse; 12 12 import polemy.value; 13 13 import polemy.layer; 14 +import polemy.value; 15 +import polemy.valueconv; 14 16 15 17 /// Objects for maitaining global environment and evaluation of expression on it 16 18 class Evaluator 17 19 { 18 20 public: 19 21 /// Initialize evaluator with empty context 20 22 this() { theContext = new Table; }

Modified polemy/layer.d from [62182a8e7452f9e8] to [f9c1f3b744698d72].

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; 9 -import polemy.failure; 10 9 11 10 /// Type for the layer ID 12 11 13 12 alias string Layer; 14 13 15 14 enum : Layer 16 15 { 17 16 SystemLayer = "(system)", /// Predefined layer for internal data 18 17 ValueLayer = "@value", /// Predefined layer for normal run 19 18 MacroLayer = "@macro", /// Predefined layer for macro run (@lay() changes layer) 20 19 RawMacroLayer = "(rawmacro)", /// Predefined layer for macro run (@lay() becomes AST) 21 20 } 22 21 22 +/// True if it is macro-like layer that basically generates syntax tree 23 + 23 24 bool isMacroishLayer( Layer lay ) 24 25 { 25 26 return lay==MacroLayer || lay==RawMacroLayer; 26 27 } 28 + 29 +/// True if in the specified layer @lay(...) has no effect and merely produces a syntax tree 27 30 28 31 bool isNoLayerChangeLayer( Layer lay ) 29 32 { 30 33 return lay==RawMacroLayer; 31 34 }

Added polemy/repl.d version [4d8d31e11afa4a19]

1 +/** 2 + * Authors: k.inaba 3 + * License: NYSL 0.9982 (http://www.kmonos.net/nysl/) 4 + * 5 + * Read-Eval-Print-Loop 6 + */ 7 +module polemy.repl; 8 +import polemy.failure; 9 +import polemy.layer; 10 +import polemy.eval; 11 +import polemy.runtime; 12 +import polemy.value; 13 +import polemy.valueconv; 14 +import std.stdio; 15 +import std.string; 16 + 17 +enum VersionNoMajor = 0; /// Version Number 18 +enum VersionNoMinor = 1; /// Version Number 19 +enum VersionNoRev = 0; /// Version Number 20 + 21 +/// Read-Eval-Print-Loop 22 + 23 +class REPL 24 +{ 25 + /// Load the prelude environment 26 + this(string[] args) 27 + { 28 + ev = new Evaluator; 29 + ev.globalContext.set("argv", ValueLayer, d2polemy(args)); 30 + enrollRuntimeLibrary(ev); 31 + } 32 + 33 + /// Print the version number etc. 34 + void greet() 35 + { 36 + writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNoMinor, VersionNoRev); 37 + } 38 + 39 + /// Run one file on the global scope 40 + void runFile(string filename) 41 + { 42 + ev.evalFile(filename); 43 + } 44 + 45 + /// Repeat the singleInteraction 46 + void replLoop() 47 + { 48 + while( singleInteraction() ) {} 49 + } 50 + 51 + /// Read one line from stdin, and do some reaction 52 + bool singleInteraction() 53 + { 54 + writef(">> ", lineno); 55 + string line = readln(); 56 + if( line.startsWith("exit") || line.startsWith("quit") ) 57 + return false; 58 + try { 59 + if( tryRun(line) ) 60 + writeln(lastVal); 61 + } catch(Throwable e) { 62 + writeln(e); 63 + } 64 + return true; 65 + } 66 + 67 +private: 68 + Evaluator ev; 69 + Table ctx; 70 + string buf; 71 + Value lastVal; 72 + int lineno = 1; 73 + int nextlineno = 1; 74 + 75 + bool tryRun( string s ) 76 + { 77 + scope(failure) 78 + { buf = ""; lineno = nextlineno; } 79 + 80 + buf ~= s; 81 + nextlineno ++; 82 + try 83 + { lastVal = ev.evalString(buf, "<REPL>", lineno); } 84 + catch( UnexpectedEOF ) 85 + { return false; } // wait 86 + buf = ""; 87 + lineno = nextlineno; 88 + return true; 89 + } 90 +}

Added polemy/runtime.d version [7110e96fc2a7a412]

1 +/** 2 + * Authors: k.inaba 3 + * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 + * 5 + * Runtime library for Polemy programming language. 6 + */ 7 +module polemy.runtime; 8 +import polemy._common; 9 +import polemy.layer; 10 +import polemy.value; 11 +import polemy.eval; 12 +import std.stdio; 13 + 14 +/// enroll the native implementations of primitive functions 15 + 16 +void enrollRuntimeLibrary( Evaluator e ) 17 +{ 18 + e.addPrimitive("+", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} ); 19 + e.addPrimitive("-", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data - rhs.data);} ); 20 + e.addPrimitive("*", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data * rhs.data);} ); 21 + e.addPrimitive("/", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data / rhs.data);} ); 22 + e.addPrimitive("%", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data % rhs.data);} ); 23 + e.addPrimitive("||", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 || rhs.data!=0);} ); 24 + e.addPrimitive("&&", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 && rhs.data!=0);} ); 25 + e.addPrimitive("<", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs < rhs);} ); 26 + e.addPrimitive(">", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs > rhs);} ); 27 + e.addPrimitive("<=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs <= rhs);} ); 28 + e.addPrimitive(">=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs >= rhs);} ); 29 + e.addPrimitive("==", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs == rhs);} ); 30 + e.addPrimitive("!=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs != rhs);} ); 31 + e.addPrimitive("print", ValueLayer, (Value a){ 32 + writeln(a); 33 + return new IntValue(0); 34 + }); 35 + e.addPrimitive("if", ValueLayer, (IntValue x, FunValue ft, FunValue fe){ 36 + auto toRun = (x.data==0 ? fe : ft); 37 + // [TODO] fill positional information 38 + return toRun.invoke(ValueLayer, toRun.definitionContext(), null); 39 + }); 40 + e.addPrimitive("_isint", ValueLayer, (Value v){return new IntValue(cast(IntValue)v !is null);} ); 41 + e.addPrimitive("_isstr", ValueLayer, (Value v){return new IntValue(cast(StrValue)v !is null);} ); 42 + e.addPrimitive("_isfun", ValueLayer, (Value v){return new IntValue(cast(FunValue)v !is null);} ); 43 + e.addPrimitive("_isundefined", ValueLayer, (Value v){return new IntValue(cast(UndefinedValue)v !is null);} ); 44 + e.addPrimitive("_istable", ValueLayer, (Value v){return new IntValue(cast(Table)v !is null);} ); 45 + e.addPrimitive(".", ValueLayer, (Table t, StrValue s){ 46 + return (t.has(s.data, ValueLayer) ? t.get(s.data, ValueLayer) : new UndefinedValue); 47 + }); 48 + e.addPrimitive(".?", ValueLayer, (Table t, StrValue s){ 49 + return new IntValue(t.has(s.data, ValueLayer)); 50 + }); 51 + e.addPrimitive(".=", ValueLayer, (Table t, StrValue s, Value v){ 52 + auto t2 = new Table(t, Table.Kind.NotPropagateSet); 53 + t2.set(s.data, ValueLayer, v); 54 + return t2; 55 + }); 56 + e.addPrimitive("{}", ValueLayer, (){ 57 + return new Table; 58 + }); 59 +}

Modified polemy/value.d from [b6c76b48bfdecce6] to [6d85ee04f34c61b7].

5 5 * Runtime data structures for Polemy programming language. 6 6 */ 7 7 module polemy.value; 8 8 import polemy._common; 9 9 import polemy.failure; 10 10 import polemy.ast; 11 11 import polemy.layer; 12 -import std.string; 13 12 14 13 /// Runtime values of Polemy 15 14 16 15 abstract class Value 17 16 { 18 17 override bool opEquals(Object rhs) { return 0==opCmp(rhs); } 19 18 } 20 19 21 20 /// 22 21 class IntValue : Value 23 22 { 24 23 BigInt data; 25 24 25 + this(bool n) { this.data = n?1:0; } 26 26 this(int n) { this.data = n; } 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); ................................................................................ 216 216 assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) ); 217 217 assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(555)) ); 218 218 assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) ); 219 219 assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) ); 220 220 221 221 // [TODO] define the semantics and test @layers 222 222 } 223 - 224 -immutable(LexPosition) extractPos( Table t ) 225 -{ 226 - Layer theLayer = ValueLayer; 227 - if(auto tt = t.access!Table(theLayer, "pos")) 228 - { 229 - auto fn = tt.access!StrValue(theLayer, "filename"); 230 - auto ln = tt.access!IntValue(theLayer, "lineno"); 231 - auto cl = tt.access!IntValue(theLayer, "column"); 232 - if(fn !is null && ln !is null && cl !is null) 233 - return new immutable(LexPosition)(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt); 234 - } 235 - return null; 236 -} 237 - 238 -Value[] tableAsConsList( Layer theLayer, Table t ) 239 -{ 240 - Value[] result; 241 - while(t) 242 - if(auto v = t.access!Value(theLayer, "car")) 243 - { 244 - result ~= v; 245 - t = t.access!Table(theLayer, "cdr"); 246 - } 247 - else 248 - break; 249 - return result; 250 -} 251 - 252 -AST[] tableToASTList( Layer theLayer, Table t ) 253 -{ 254 - AST[] result; 255 - foreach(v; tableAsConsList(theLayer, t)) 256 - if(auto t = cast(Table)v) 257 - result ~= tableToAST(theLayer,t); 258 - else 259 - throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (non-table in cons-list)"); 260 - return result; 261 -} 262 - 263 -AST tableToAST( Layer theLayer, Value vvvv ) 264 -{ 265 - Table t = cast(Table)vvvv; 266 - if( t is null ) 267 - throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (not a table)"); 268 - 269 - auto nodeType = t.access!StrValue(theLayer, "is"); 270 - if( nodeType is null ) 271 - throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}"); 272 - auto pos = extractPos(t); 273 - switch(nodeType.data) 274 - { 275 - case "int": 276 - if(auto v = t.access!IntValue(theLayer, "data")) 277 - return new Int(pos, v.data); 278 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`); 279 - case "str": 280 - if(auto v = t.access!StrValue(theLayer, "data")) 281 - return new Str(pos, v.data); 282 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`); 283 - case "var": 284 - if(auto v = t.access!StrValue(theLayer, "name")) 285 - return new Var(pos, v.data); 286 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`); 287 - case "lay": 288 - if(auto v = t.access!StrValue(theLayer, "layer")) 289 - if(auto e = t.access!Table(theLayer, "expr")) 290 - return new Lay(pos, v.data, tableToAST(theLayer,e)); 291 - else 292 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`); 293 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`); 294 - case "let": 295 - if(auto n = t.access!StrValue(theLayer, "name")) 296 - if(auto e = t.access!Table(theLayer, "init")) 297 - if(auto b = t.access!Table(theLayer, "expr")) 298 - { 299 - string nn = n.data; 300 - auto ee = tableToAST(theLayer, e); 301 - auto bb = tableToAST(theLayer, b); 302 - Layer lay=""; 303 - if(auto l = t.access!StrValue(theLayer, "layer")) 304 - lay = l.data; 305 - return new Let(pos, nn, lay, ee, bb); 306 - } 307 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`); 308 - case "app": 309 - if(auto f = t.access!Table(theLayer, "fun")) 310 - if(auto a = t.access!Table(theLayer, "args")) 311 - return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); 312 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`); 313 - case "fun": 314 - if(auto p = t.access!Table(theLayer, "params")) 315 - if(auto b = t.access!Table(theLayer, "funbody")) 316 - { 317 - Parameter[] ps; 318 - foreach(v; tableAsConsList(theLayer, p)) 319 - { 320 - if(auto tt = cast(Table)v) 321 - if(auto ss = tt.access!StrValue(theLayer, "name")) 322 - if(auto ll = tt.access!Table(theLayer, "layers")) 323 - { 324 - Layer[] ls; 325 - foreach(lll; tableAsConsList(theLayer, ll)) 326 - if(auto l = cast(StrValue)lll) 327 - ls ~= l.data; 328 - else 329 - throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll)); 330 - ps ~= new Parameter(ss.data, ls); 331 - continue; 332 - } 333 - else 334 - { 335 - Layer[] emp; 336 - ps ~= new Parameter(ss.data, emp); 337 - continue; 338 - } 339 - throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v)); 340 - } 341 - auto bb = tableToAST(theLayer, b); 342 - return new Fun(pos,ps,bb); 343 - } 344 - throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`); 345 - default: 346 - throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data)); 347 - } 348 -} 349 - 350 -Table makeCons(Value a, Value d) 351 -{ 352 - Table t = new Table; 353 - t.set("car", ValueLayer, a); 354 - t.set("cdr", ValueLayer, d); 355 - return t; 356 -} 357 - 358 -Table fromPos(LexPosition pos) 359 -{ 360 - Table t = new Table; 361 - if( pos !is null ) { 362 - t.set("filename", ValueLayer, new StrValue(pos.filename)); 363 - t.set("lineno", ValueLayer, new IntValue(pos.lineno)); 364 - t.set("column", ValueLayer, new IntValue(pos.column)); 365 - } else { 366 - t.set("filename", ValueLayer, new StrValue("nullpos")); 367 - t.set("lineno", ValueLayer, new IntValue(0)); 368 - t.set("column", ValueLayer, new IntValue(0)); 369 - } 370 - return t; 371 -} 372 - 373 -/// Convert AST to Table so that it can be used in Polemy 374 -/// TODO: generalize to DValue2PolemyValue 375 - 376 -Value ast2table(T)(T e, Value delegate(AST) rec) 377 -{ 378 - assert( typeid(e) == typeid(T) ); 379 - 380 - static if(is(T==BigInt) || is(T==long) || is(T==int)) 381 - return new IntValue(e); 382 - else 383 - static if(is(T==string)) 384 - return new StrValue(e); 385 - else 386 - static if(is(T S : S[])) 387 - { 388 - Table lst = new Table; 389 - foreach_reverse(a; e) 390 - static if(is(S : AST)) 391 - lst = makeCons(rec(a), lst); 392 - else 393 - lst = makeCons(ast2table(a,rec), lst); 394 - return lst; 395 - } 396 - else 397 - static if(is(T : AST)) 398 - { 399 - auto t = new Table; 400 - t.set("pos", ValueLayer, fromPos(e.pos)); 401 - t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1].tolower())); 402 - foreach(i,m; e.tupleof) 403 - static if(is(typeof(m) : AST)) 404 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); 405 - else 406 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); 407 - return t; 408 - } 409 - else 410 - static if(is(T == class)) 411 - { 412 - auto t = new Table; 413 - foreach(i,m; e.tupleof) 414 - static if(is(typeof(m) : AST)) 415 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); 416 - else 417 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); 418 - return t; 419 - } 420 - else 421 - static assert(false, "unknown type <"~T.stringof~"> during AST encoding"); 422 -}

Added polemy/valueconv.d version [76bd90b6c3824480]

1 +/** 2 + * Authors: k.inaba 3 + * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 + * 5 + * Convert values between Polemy and D 6 + */ 7 +module polemy.valueconv; 8 +import polemy._common; 9 +import polemy.failure; 10 +import polemy.ast; 11 +import polemy.layer; 12 +import polemy.value; 13 +import std.string; 14 + 15 +LexPosition extractPos( Table t ) 16 +{ 17 + Layer theLayer = ValueLayer; 18 + if(auto tt = t.access!Table(theLayer, "pos")) 19 + { 20 + auto fn = tt.access!StrValue(theLayer, "filename"); 21 + auto ln = tt.access!IntValue(theLayer, "lineno"); 22 + auto cl = tt.access!IntValue(theLayer, "column"); 23 + if(fn !is null && ln !is null && cl !is null) 24 + return new LexPosition(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt); 25 + } 26 + return null; 27 +} 28 + 29 +Value[] tableAsConsList( Layer theLayer, Table t ) 30 +{ 31 + Value[] result; 32 + while(t) 33 + if(auto v = t.access!Value(theLayer, "car")) 34 + { 35 + result ~= v; 36 + t = t.access!Table(theLayer, "cdr"); 37 + } 38 + else 39 + break; 40 + return result; 41 +} 42 + 43 +AST[] tableToASTList( Layer theLayer, Table t ) 44 +{ 45 + AST[] result; 46 + foreach(v; tableAsConsList(theLayer, t)) 47 + if(auto t = cast(Table)v) 48 + result ~= tableToAST(theLayer,t); 49 + else 50 + throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (non-table in cons-list)"); 51 + return result; 52 +} 53 + 54 +AST tableToAST( Layer theLayer, Value vvvv ) 55 +{ 56 + Table t = cast(Table)vvvv; 57 + if( t is null ) 58 + throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (not a table)"); 59 + 60 + auto nodeType = t.access!StrValue(theLayer, "is"); 61 + if( nodeType is null ) 62 + throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}"); 63 + auto pos = extractPos(t); 64 + switch(nodeType.data) 65 + { 66 + case "int": 67 + if(auto v = t.access!IntValue(theLayer, "data")) 68 + return new Int(pos, v.data); 69 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`); 70 + case "str": 71 + if(auto v = t.access!StrValue(theLayer, "data")) 72 + return new Str(pos, v.data); 73 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`); 74 + case "var": 75 + if(auto v = t.access!StrValue(theLayer, "name")) 76 + return new Var(pos, v.data); 77 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`); 78 + case "lay": 79 + if(auto v = t.access!StrValue(theLayer, "layer")) 80 + if(auto e = t.access!Table(theLayer, "expr")) 81 + return new Lay(pos, v.data, tableToAST(theLayer,e)); 82 + else 83 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`); 84 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`); 85 + case "let": 86 + if(auto n = t.access!StrValue(theLayer, "name")) 87 + if(auto e = t.access!Table(theLayer, "init")) 88 + if(auto b = t.access!Table(theLayer, "expr")) 89 + { 90 + string nn = n.data; 91 + auto ee = tableToAST(theLayer, e); 92 + auto bb = tableToAST(theLayer, b); 93 + Layer lay=""; 94 + if(auto l = t.access!StrValue(theLayer, "layer")) 95 + lay = l.data; 96 + return new Let(pos, nn, lay, ee, bb); 97 + } 98 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`); 99 + case "app": 100 + if(auto f = t.access!Table(theLayer, "fun")) 101 + if(auto a = t.access!Table(theLayer, "args")) 102 + return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a)); 103 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`); 104 + case "fun": 105 + if(auto p = t.access!Table(theLayer, "params")) 106 + if(auto b = t.access!Table(theLayer, "funbody")) 107 + { 108 + Parameter[] ps; 109 + foreach(v; tableAsConsList(theLayer, p)) 110 + { 111 + if(auto tt = cast(Table)v) 112 + if(auto ss = tt.access!StrValue(theLayer, "name")) 113 + if(auto ll = tt.access!Table(theLayer, "layers")) 114 + { 115 + Layer[] ls; 116 + foreach(lll; tableAsConsList(theLayer, ll)) 117 + if(auto l = cast(StrValue)lll) 118 + ls ~= l.data; 119 + else 120 + throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll)); 121 + ps ~= new Parameter(ss.data, ls); 122 + continue; 123 + } 124 + else 125 + { 126 + Layer[] emp; 127 + ps ~= new Parameter(ss.data, emp); 128 + continue; 129 + } 130 + throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v)); 131 + } 132 + auto bb = tableToAST(theLayer, b); 133 + return new Fun(pos,ps,bb); 134 + } 135 + throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`); 136 + default: 137 + throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data)); 138 + } 139 +} 140 + 141 +/// Cons of two pairs 142 + 143 +Table makeCons(Value a, Value d) 144 +{ 145 + Table t = new Table; 146 + t.set("car", ValueLayer, a); 147 + t.set("cdr", ValueLayer, d); 148 + return t; 149 +} 150 + 151 +/// Experimental!!! Convert D value (except AST) to Polemy Value 152 + 153 +Value d2polemy(T)(T e) 154 +{ 155 + return ast2table(e, delegate Value(AST){ assert(false); }); 156 +} 157 + 158 +/// Convert AST to Table so that it can be used in Polemy 159 + 160 +Value ast2table(T)(T e, Value delegate(AST) rec) 161 +{ 162 + static if(is(T==BigInt) || isIntegral!(T)) 163 + return new IntValue(e); 164 + else 165 + static if(is(Unqual!(T)==string)) 166 + return new StrValue(e); 167 + else 168 + static if(is(T S : S[])) 169 + { 170 + Table lst = new Table; 171 + foreach_reverse(a; e) 172 + static if(is(S : AST)) 173 + lst = makeCons(rec(a), lst); 174 + else 175 + lst = makeCons(ast2table(a,rec), lst); 176 + return lst; 177 + } 178 + else 179 + static if(is(T : AST)) 180 + { 181 + assert( typeid(e) == typeid(T), text("abstracted: ", typeid(e), " vs ", typeid(T)) ); 182 + auto t = new Table; 183 + t.set("pos", ValueLayer, ast2table(e.pos,rec)); 184 + t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1].tolower())); 185 + foreach(i,m; e.tupleof) 186 + static if(is(typeof(m) : AST)) 187 + t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); 188 + else 189 + t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); 190 + return t; 191 + } 192 + else 193 + static if(is(T == class)) 194 + { 195 + auto t = new Table; 196 + foreach(i,m; e.tupleof) 197 + static if(is(typeof(m) : AST)) 198 + t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); 199 + else 200 + t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); 201 + return t; 202 + } 203 + else 204 + static assert(false, "unknown type <"~T.stringof~"> during AST encoding"); 205 +}