Index: .poseidon
==================================================================
--- .poseidon
+++ .poseidon
@@ -37,12 +37,14 @@
polemy\failure.d
polemy\fresh.d
polemy\layer.d
polemy\lex.d
polemy\parse.d
+ polemy\repl.d
polemy\runtime.d
polemy\value.d
+ polemy\valueconv.d
tricks\test.d
tricks\tricks.d
Index: doc/candydoc/modules.ddoc
==================================================================
--- doc/candydoc/modules.ddoc
+++ doc/candydoc/modules.ddoc
@@ -7,8 +7,10 @@
$(MODULE polemy.layer)
$(MODULE polemy.fresh)
$(MODULE polemy.lex)
$(MODULE polemy.parse)
$(MODULE polemy.ast)
+ $(MODULE polemy.value)
+ $(MODULE polemy.valueconv)
$(MODULE polemy.eval)
$(MODULE polemy.runtime)
- $(MODULE polemy.value)
+ $(MODULE polemy.repl)
Index: main.d
==================================================================
--- main.d
+++ main.d
@@ -3,94 +3,14 @@
* License: NYSL 0.9982 (http://www.kmonos.net/nysl/)
*
* Entry point for Polemy interpreter.
*/
module main;
+import polemy.repl;
import std.stdio;
import std.algorithm;
import std.array;
-import polemy.value;
-import polemy.failure;
-import polemy.layer;
-import polemy.parse;
-import polemy.ast;
-import polemy.eval;
-import polemy.runtime;
-
-enum VersionNoMajor = 0;
-enum VersionNoMinor = 1;
-enum VersionNoRev = 0;
-
-/// Read-Eval-Print-Loop
-
-class REPL
-{
-Evaluator ev;
- /// Load the prelude environment
- this()
- {
- ev = new Evaluator;
- enrollRuntimeLibrary(ev);
- }
-
- /// Print the version number etc.
- void greet()
- {
- writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNoMinor, VersionNoRev);
- }
-
- /// Run one file on the global scope
- void runFile(string filename)
- {
- ev.evalFile(filename);
- }
-
- /// Repeat the singleInteraction
- void replLoop()
- {
- while( singleInteraction() ) {}
- }
-
- /// Read one line from stdin, and do some reaction
- bool singleInteraction()
- {
- writef(">> ", lineno);
- string line = readln();
- if( line.startsWith("exit") || line.startsWith("quit") )
- return false;
- try {
- if( tryRun(line) )
- writeln(lastVal);
- } catch(Throwable e) {
- writeln(e);
- }
- return true;
- }
-
-private:
- Table ctx;
- string buf;
- Value lastVal;
- int lineno = 1;
- int nextlineno = 1;
-
- bool tryRun( string s )
- {
- scope(failure)
- { buf = ""; lineno = nextlineno; }
-
- buf ~= s;
- nextlineno ++;
- try
- { lastVal = ev.evalString(buf, "", lineno); }
- catch( UnexpectedEOF )
- { return false; } // wait
- buf = "";
- lineno = nextlineno;
- return true;
- }
-}
/// Advance args[] to point the argument list fed to the script.
/// Returns the name of the source file to run, or returns "" if
/// no filename was given. Also, returns to libs[] the list of
/// library source to load.
@@ -120,15 +40,15 @@
void main( string[] args )
{
string[] libs;
string src = parseArgv(args, libs);
- auto r = new REPL;
+ auto r = new REPL(args);
if( src.empty )
r.greet();
foreach(lb; libs)
r.runFile(lb);
if( src.empty )
r.replLoop();
else
r.runFile(src);
}
Index: polemy/_common.d
==================================================================
--- polemy/_common.d
+++ polemy/_common.d
@@ -12,7 +12,8 @@
public import std.bigint;
public import std.conv : text;
public import std.exception;
public import std.range;
public import std.stdio : DBG = writeln;
+public import std.traits;
public import std.typecons;
public import std.typetuple;
Index: polemy/eval.d
==================================================================
--- polemy/eval.d
+++ polemy/eval.d
@@ -9,10 +9,12 @@
import polemy.failure;
import polemy.ast;
import polemy.parse;
import polemy.value;
import polemy.layer;
+import polemy.value;
+import polemy.valueconv;
/// Objects for maitaining global environment and evaluation of expression on it
class Evaluator
{
public:
Index: polemy/layer.d
==================================================================
--- polemy/layer.d
+++ polemy/layer.d
@@ -4,11 +4,10 @@
*
* Definition of constants related to the layers.
*/
module polemy.layer;
import polemy._common;
-import polemy.failure;
/// Type for the layer ID
alias string Layer;
@@ -18,14 +17,18 @@
ValueLayer = "@value", /// Predefined layer for normal run
MacroLayer = "@macro", /// Predefined layer for macro run (@lay() changes layer)
RawMacroLayer = "(rawmacro)", /// Predefined layer for macro run (@lay() becomes AST)
}
+/// True if it is macro-like layer that basically generates syntax tree
+
bool isMacroishLayer( Layer lay )
{
return lay==MacroLayer || lay==RawMacroLayer;
}
+
+/// True if in the specified layer @lay(...) has no effect and merely produces a syntax tree
bool isNoLayerChangeLayer( Layer lay )
{
return lay==RawMacroLayer;
}
ADDED polemy/repl.d
Index: polemy/repl.d
==================================================================
--- polemy/repl.d
+++ polemy/repl.d
@@ -0,0 +1,90 @@
+/**
+ * Authors: k.inaba
+ * License: NYSL 0.9982 (http://www.kmonos.net/nysl/)
+ *
+ * Read-Eval-Print-Loop
+ */
+module polemy.repl;
+import polemy.failure;
+import polemy.layer;
+import polemy.eval;
+import polemy.runtime;
+import polemy.value;
+import polemy.valueconv;
+import std.stdio;
+import std.string;
+
+enum VersionNoMajor = 0; /// Version Number
+enum VersionNoMinor = 1; /// Version Number
+enum VersionNoRev = 0; /// Version Number
+
+/// Read-Eval-Print-Loop
+
+class REPL
+{
+ /// Load the prelude environment
+ this(string[] args)
+ {
+ ev = new Evaluator;
+ ev.globalContext.set("argv", ValueLayer, d2polemy(args));
+ enrollRuntimeLibrary(ev);
+ }
+
+ /// Print the version number etc.
+ void greet()
+ {
+ writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNoMinor, VersionNoRev);
+ }
+
+ /// Run one file on the global scope
+ void runFile(string filename)
+ {
+ ev.evalFile(filename);
+ }
+
+ /// Repeat the singleInteraction
+ void replLoop()
+ {
+ while( singleInteraction() ) {}
+ }
+
+ /// Read one line from stdin, and do some reaction
+ bool singleInteraction()
+ {
+ writef(">> ", lineno);
+ string line = readln();
+ if( line.startsWith("exit") || line.startsWith("quit") )
+ return false;
+ try {
+ if( tryRun(line) )
+ writeln(lastVal);
+ } catch(Throwable e) {
+ writeln(e);
+ }
+ return true;
+ }
+
+private:
+ Evaluator ev;
+ Table ctx;
+ string buf;
+ Value lastVal;
+ int lineno = 1;
+ int nextlineno = 1;
+
+ bool tryRun( string s )
+ {
+ scope(failure)
+ { buf = ""; lineno = nextlineno; }
+
+ buf ~= s;
+ nextlineno ++;
+ try
+ { lastVal = ev.evalString(buf, "", lineno); }
+ catch( UnexpectedEOF )
+ { return false; } // wait
+ buf = "";
+ lineno = nextlineno;
+ return true;
+ }
+}
ADDED polemy/runtime.d
Index: polemy/runtime.d
==================================================================
--- polemy/runtime.d
+++ polemy/runtime.d
@@ -0,0 +1,59 @@
+/**
+ * Authors: k.inaba
+ * License: NYSL 0.9982 http://www.kmonos.net/nysl/
+ *
+ * Runtime library for Polemy programming language.
+ */
+module polemy.runtime;
+import polemy._common;
+import polemy.layer;
+import polemy.value;
+import polemy.eval;
+import std.stdio;
+
+/// enroll the native implementations of primitive functions
+
+void enrollRuntimeLibrary( Evaluator e )
+{
+ e.addPrimitive("+", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} );
+ e.addPrimitive("-", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data - rhs.data);} );
+ e.addPrimitive("*", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data * rhs.data);} );
+ e.addPrimitive("/", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data / rhs.data);} );
+ e.addPrimitive("%", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data % rhs.data);} );
+ e.addPrimitive("||", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 || rhs.data!=0);} );
+ e.addPrimitive("&&", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 && rhs.data!=0);} );
+ e.addPrimitive("<", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs < rhs);} );
+ e.addPrimitive(">", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs > rhs);} );
+ e.addPrimitive("<=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs <= rhs);} );
+ e.addPrimitive(">=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs >= rhs);} );
+ e.addPrimitive("==", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs == rhs);} );
+ e.addPrimitive("!=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs != rhs);} );
+ e.addPrimitive("print", ValueLayer, (Value a){
+ writeln(a);
+ return new IntValue(0);
+ });
+ e.addPrimitive("if", ValueLayer, (IntValue x, FunValue ft, FunValue fe){
+ auto toRun = (x.data==0 ? fe : ft);
+ // [TODO] fill positional information
+ return toRun.invoke(ValueLayer, toRun.definitionContext(), null);
+ });
+ e.addPrimitive("_isint", ValueLayer, (Value v){return new IntValue(cast(IntValue)v !is null);} );
+ e.addPrimitive("_isstr", ValueLayer, (Value v){return new IntValue(cast(StrValue)v !is null);} );
+ e.addPrimitive("_isfun", ValueLayer, (Value v){return new IntValue(cast(FunValue)v !is null);} );
+ e.addPrimitive("_isundefined", ValueLayer, (Value v){return new IntValue(cast(UndefinedValue)v !is null);} );
+ e.addPrimitive("_istable", ValueLayer, (Value v){return new IntValue(cast(Table)v !is null);} );
+ e.addPrimitive(".", ValueLayer, (Table t, StrValue s){
+ return (t.has(s.data, ValueLayer) ? t.get(s.data, ValueLayer) : new UndefinedValue);
+ });
+ e.addPrimitive(".?", ValueLayer, (Table t, StrValue s){
+ return new IntValue(t.has(s.data, ValueLayer));
+ });
+ e.addPrimitive(".=", ValueLayer, (Table t, StrValue s, Value v){
+ auto t2 = new Table(t, Table.Kind.NotPropagateSet);
+ t2.set(s.data, ValueLayer, v);
+ return t2;
+ });
+ e.addPrimitive("{}", ValueLayer, (){
+ return new Table;
+ });
+}
Index: polemy/value.d
==================================================================
--- polemy/value.d
+++ polemy/value.d
@@ -7,11 +7,10 @@
module polemy.value;
import polemy._common;
import polemy.failure;
import polemy.ast;
import polemy.layer;
-import std.string;
/// Runtime values of Polemy
abstract class Value
{
@@ -21,10 +20,11 @@
///
class IntValue : Value
{
BigInt data;
+ this(bool n) { this.data = n?1:0; }
this(int n) { this.data = n; }
this(long n) { this.data = n; }
this(BigInt n) { this.data = n; }
this(string n) { this.data = BigInt(n); }
override string toString() const { return toDecimalString(cast(BigInt)data); }
@@ -218,205 +218,5 @@
assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) );
assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) );
// [TODO] define the semantics and test @layers
}
-
-immutable(LexPosition) extractPos( Table t )
-{
- Layer theLayer = ValueLayer;
- if(auto tt = t.access!Table(theLayer, "pos"))
- {
- auto fn = tt.access!StrValue(theLayer, "filename");
- auto ln = tt.access!IntValue(theLayer, "lineno");
- auto cl = tt.access!IntValue(theLayer, "column");
- if(fn !is null && ln !is null && cl !is null)
- return new immutable(LexPosition)(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt);
- }
- return null;
-}
-
-Value[] tableAsConsList( Layer theLayer, Table t )
-{
- Value[] result;
- while(t)
- if(auto v = t.access!Value(theLayer, "car"))
- {
- result ~= v;
- t = t.access!Table(theLayer, "cdr");
- }
- else
- break;
- return result;
-}
-
-AST[] tableToASTList( Layer theLayer, Table t )
-{
- AST[] result;
- foreach(v; tableAsConsList(theLayer, t))
- if(auto t = cast(Table)v)
- result ~= tableToAST(theLayer,t);
- else
- throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (non-table in cons-list)");
- return result;
-}
-
-AST tableToAST( Layer theLayer, Value vvvv )
-{
- Table t = cast(Table)vvvv;
- if( t is null )
- throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (not a table)");
-
- auto nodeType = t.access!StrValue(theLayer, "is");
- if( nodeType is null )
- throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}");
- auto pos = extractPos(t);
- switch(nodeType.data)
- {
- case "int":
- if(auto v = t.access!IntValue(theLayer, "data"))
- return new Int(pos, v.data);
- throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`);
- case "str":
- if(auto v = t.access!StrValue(theLayer, "data"))
- return new Str(pos, v.data);
- throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`);
- case "var":
- if(auto v = t.access!StrValue(theLayer, "name"))
- return new Var(pos, v.data);
- throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`);
- case "lay":
- if(auto v = t.access!StrValue(theLayer, "layer"))
- if(auto e = t.access!Table(theLayer, "expr"))
- return new Lay(pos, v.data, tableToAST(theLayer,e));
- else
- throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`);
- throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`);
- case "let":
- if(auto n = t.access!StrValue(theLayer, "name"))
- if(auto e = t.access!Table(theLayer, "init"))
- if(auto b = t.access!Table(theLayer, "expr"))
- {
- string nn = n.data;
- auto ee = tableToAST(theLayer, e);
- auto bb = tableToAST(theLayer, b);
- Layer lay="";
- if(auto l = t.access!StrValue(theLayer, "layer"))
- lay = l.data;
- return new Let(pos, nn, lay, ee, bb);
- }
- throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`);
- case "app":
- if(auto f = t.access!Table(theLayer, "fun"))
- if(auto a = t.access!Table(theLayer, "args"))
- return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a));
- throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`);
- case "fun":
- if(auto p = t.access!Table(theLayer, "params"))
- if(auto b = t.access!Table(theLayer, "funbody"))
- {
- Parameter[] ps;
- foreach(v; tableAsConsList(theLayer, p))
- {
- if(auto tt = cast(Table)v)
- if(auto ss = tt.access!StrValue(theLayer, "name"))
- if(auto ll = tt.access!Table(theLayer, "layers"))
- {
- Layer[] ls;
- foreach(lll; tableAsConsList(theLayer, ll))
- if(auto l = cast(StrValue)lll)
- ls ~= l.data;
- else
- throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll));
- ps ~= new Parameter(ss.data, ls);
- continue;
- }
- else
- {
- Layer[] emp;
- ps ~= new Parameter(ss.data, emp);
- continue;
- }
- throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v));
- }
- auto bb = tableToAST(theLayer, b);
- return new Fun(pos,ps,bb);
- }
- throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`);
- default:
- throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data));
- }
-}
-
-Table makeCons(Value a, Value d)
-{
- Table t = new Table;
- t.set("car", ValueLayer, a);
- t.set("cdr", ValueLayer, d);
- return t;
-}
-
-Table fromPos(LexPosition pos)
-{
- Table t = new Table;
- if( pos !is null ) {
- t.set("filename", ValueLayer, new StrValue(pos.filename));
- t.set("lineno", ValueLayer, new IntValue(pos.lineno));
- t.set("column", ValueLayer, new IntValue(pos.column));
- } else {
- t.set("filename", ValueLayer, new StrValue("nullpos"));
- t.set("lineno", ValueLayer, new IntValue(0));
- t.set("column", ValueLayer, new IntValue(0));
- }
- return t;
-}
-
-/// Convert AST to Table so that it can be used in Polemy
-/// TODO: generalize to DValue2PolemyValue
-
-Value ast2table(T)(T e, Value delegate(AST) rec)
-{
- assert( typeid(e) == typeid(T) );
-
- static if(is(T==BigInt) || is(T==long) || is(T==int))
- return new IntValue(e);
- else
- static if(is(T==string))
- return new StrValue(e);
- else
- static if(is(T S : S[]))
- {
- Table lst = new Table;
- foreach_reverse(a; e)
- static if(is(S : AST))
- lst = makeCons(rec(a), lst);
- else
- lst = makeCons(ast2table(a,rec), lst);
- return lst;
- }
- else
- static if(is(T : AST))
- {
- auto t = new Table;
- t.set("pos", ValueLayer, fromPos(e.pos));
- t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1].tolower()));
- foreach(i,m; e.tupleof)
- static if(is(typeof(m) : AST))
- t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m));
- else
- t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec));
- return t;
- }
- else
- static if(is(T == class))
- {
- auto t = new Table;
- foreach(i,m; e.tupleof)
- static if(is(typeof(m) : AST))
- t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m));
- else
- t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec));
- return t;
- }
- else
- static assert(false, "unknown type <"~T.stringof~"> during AST encoding");
-}
ADDED polemy/valueconv.d
Index: polemy/valueconv.d
==================================================================
--- polemy/valueconv.d
+++ polemy/valueconv.d
@@ -0,0 +1,205 @@
+/**
+ * Authors: k.inaba
+ * License: NYSL 0.9982 http://www.kmonos.net/nysl/
+ *
+ * Convert values between Polemy and D
+ */
+module polemy.valueconv;
+import polemy._common;
+import polemy.failure;
+import polemy.ast;
+import polemy.layer;
+import polemy.value;
+import std.string;
+
+LexPosition extractPos( Table t )
+{
+ Layer theLayer = ValueLayer;
+ if(auto tt = t.access!Table(theLayer, "pos"))
+ {
+ auto fn = tt.access!StrValue(theLayer, "filename");
+ auto ln = tt.access!IntValue(theLayer, "lineno");
+ auto cl = tt.access!IntValue(theLayer, "column");
+ if(fn !is null && ln !is null && cl !is null)
+ return new LexPosition(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt);
+ }
+ return null;
+}
+
+Value[] tableAsConsList( Layer theLayer, Table t )
+{
+ Value[] result;
+ while(t)
+ if(auto v = t.access!Value(theLayer, "car"))
+ {
+ result ~= v;
+ t = t.access!Table(theLayer, "cdr");
+ }
+ else
+ break;
+ return result;
+}
+
+AST[] tableToASTList( Layer theLayer, Table t )
+{
+ AST[] result;
+ foreach(v; tableAsConsList(theLayer, t))
+ if(auto t = cast(Table)v)
+ result ~= tableToAST(theLayer,t);
+ else
+ throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (non-table in cons-list)");
+ return result;
+}
+
+AST tableToAST( Layer theLayer, Value vvvv )
+{
+ Table t = cast(Table)vvvv;
+ if( t is null )
+ throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST (not a table)");
+
+ auto nodeType = t.access!StrValue(theLayer, "is");
+ if( nodeType is null )
+ throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST {is:(not string)}");
+ auto pos = extractPos(t);
+ switch(nodeType.data)
+ {
+ case "int":
+ if(auto v = t.access!IntValue(theLayer, "data"))
+ return new Int(pos, v.data);
+ throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"int", data:(not int)}`);
+ case "str":
+ if(auto v = t.access!StrValue(theLayer, "data"))
+ return new Str(pos, v.data);
+ throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"str", data:(not string)}`);
+ case "var":
+ if(auto v = t.access!StrValue(theLayer, "name"))
+ return new Var(pos, v.data);
+ throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"var", name:(not string)}`);
+ case "lay":
+ if(auto v = t.access!StrValue(theLayer, "layer"))
+ if(auto e = t.access!Table(theLayer, "expr"))
+ return new Lay(pos, v.data, tableToAST(theLayer,e));
+ else
+ throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", expr:(not table)}`);
+ throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"lay", layer:(not string)}`);
+ case "let":
+ if(auto n = t.access!StrValue(theLayer, "name"))
+ if(auto e = t.access!Table(theLayer, "init"))
+ if(auto b = t.access!Table(theLayer, "expr"))
+ {
+ string nn = n.data;
+ auto ee = tableToAST(theLayer, e);
+ auto bb = tableToAST(theLayer, b);
+ Layer lay="";
+ if(auto l = t.access!StrValue(theLayer, "layer"))
+ lay = l.data;
+ return new Let(pos, nn, lay, ee, bb);
+ }
+ throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"let", name:"???", init:"???", expr:"???"}`);
+ case "app":
+ if(auto f = t.access!Table(theLayer, "fun"))
+ if(auto a = t.access!Table(theLayer, "args"))
+ return new App(pos, tableToAST(theLayer,f), tableToASTList(theLayer,a));
+ throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"app", fun:???, args:???}`);
+ case "fun":
+ if(auto p = t.access!Table(theLayer, "params"))
+ if(auto b = t.access!Table(theLayer, "funbody"))
+ {
+ Parameter[] ps;
+ foreach(v; tableAsConsList(theLayer, p))
+ {
+ if(auto tt = cast(Table)v)
+ if(auto ss = tt.access!StrValue(theLayer, "name"))
+ if(auto ll = tt.access!Table(theLayer, "layers"))
+ {
+ Layer[] ls;
+ foreach(lll; tableAsConsList(theLayer, ll))
+ if(auto l = cast(StrValue)lll)
+ ls ~= l.data;
+ else
+ throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(lll));
+ ps ~= new Parameter(ss.data, ls);
+ continue;
+ }
+ else
+ {
+ Layer[] emp;
+ ps ~= new Parameter(ss.data, emp);
+ continue;
+ }
+ throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {bad fun params %s}`(v));
+ }
+ auto bb = tableToAST(theLayer, b);
+ return new Fun(pos,ps,bb);
+ }
+ throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST {is:"fun", param:???, body:???}`);
+ default:
+ throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Invalid AST {is: "%s"} unknown`(nodeType.data));
+ }
+}
+
+/// Cons of two pairs
+
+Table makeCons(Value a, Value d)
+{
+ Table t = new Table;
+ t.set("car", ValueLayer, a);
+ t.set("cdr", ValueLayer, d);
+ return t;
+}
+
+/// Experimental!!! Convert D value (except AST) to Polemy Value
+
+Value d2polemy(T)(T e)
+{
+ return ast2table(e, delegate Value(AST){ assert(false); });
+}
+
+/// Convert AST to Table so that it can be used in Polemy
+
+Value ast2table(T)(T e, Value delegate(AST) rec)
+{
+ static if(is(T==BigInt) || isIntegral!(T))
+ return new IntValue(e);
+ else
+ static if(is(Unqual!(T)==string))
+ return new StrValue(e);
+ else
+ static if(is(T S : S[]))
+ {
+ Table lst = new Table;
+ foreach_reverse(a; e)
+ static if(is(S : AST))
+ lst = makeCons(rec(a), lst);
+ else
+ lst = makeCons(ast2table(a,rec), lst);
+ return lst;
+ }
+ else
+ static if(is(T : AST))
+ {
+ assert( typeid(e) == typeid(T), text("abstracted: ", typeid(e), " vs ", typeid(T)) );
+ auto t = new Table;
+ t.set("pos", ValueLayer, ast2table(e.pos,rec));
+ t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1].tolower()));
+ foreach(i,m; e.tupleof)
+ static if(is(typeof(m) : AST))
+ t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m));
+ else
+ t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec));
+ return t;
+ }
+ else
+ static if(is(T == class))
+ {
+ auto t = new Table;
+ foreach(i,m; e.tupleof)
+ static if(is(typeof(m) : AST))
+ t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m));
+ else
+ t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec));
+ return t;
+ }
+ else
+ static assert(false, "unknown type <"~T.stringof~"> during AST encoding");
+}