Check-in [6ac127ddd0]
Not logged in
Overview
SHA1 Hash:6ac127ddd018bd755afda6da3b52bd5f3cac909c
Date: 2010-11-23 16:42:13
User: kinaba
Comment:new evaluator
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified .poseidon from [ce44f33cc750cc08] to [92babe531ac51123].

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

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

6 $(MODULE polemy.failure) 6 $(MODULE polemy.failure) 7 $(MODULE polemy.layer) 7 $(MODULE polemy.layer) 8 $(MODULE polemy.fresh) 8 $(MODULE polemy.fresh) 9 $(MODULE polemy.lex) 9 $(MODULE polemy.lex) 10 $(MODULE polemy.parse) 10 $(MODULE polemy.parse) 11 $(MODULE polemy.ast) 11 $(MODULE polemy.ast) 12 $(MODULE polemy.eval) 12 $(MODULE polemy.eval) > 13 $(MODULE polemy.runtime) 13 $(MODULE polemy.value) 14 $(MODULE polemy.value)

Modified main.d from [636370f08c051cf2] to [e659b2cb410288fd].

6 */ 6 */ 7 module main; 7 module main; 8 import std.stdio; 8 import std.stdio; 9 import std.algorithm; 9 import std.algorithm; 10 import std.array; 10 import std.array; 11 import polemy.value; 11 import polemy.value; 12 import polemy.failure; 12 import polemy.failure; > 13 import polemy.layer; 13 import polemy.parse; 14 import polemy.parse; 14 import polemy.ast; 15 import polemy.ast; 15 import polemy.eval; 16 import polemy.eval; 16 import polemy.layer; < 17 17 18 enum VersionNoMajor = 0; 18 enum VersionNoMajor = 0; 19 enum VersionNoMinor = 1; 19 enum VersionNoMinor = 1; 20 enum VersionNoRev = 0; 20 enum VersionNoRev = 0; 21 21 22 /// Read-Eval-Print-Loop 22 /// Read-Eval-Print-Loop 23 23 24 class REPL 24 class REPL 25 { 25 { > 26 Evaluator ev; 26 /// Load the prelude environment 27 /// Load the prelude environment 27 this() 28 this() 28 { 29 { 29 ctx = createGlobalContext(); | 30 ev = new Evaluator; 30 } 31 } 31 32 32 /// Print the version number etc. 33 /// Print the version number etc. 33 void greet() 34 void greet() 34 { 35 { 35 writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNo 36 writefln("Welcome to Polemy %d.%d.%d", VersionNoMajor, VersionNo 36 } 37 } 37 38 38 /// Run one file on the global scope 39 /// Run one file on the global scope 39 void runFile(string filename) 40 void runFile(string filename) 40 { 41 { 41 eval(parseFile(filename), ctx, false, ValueLayer); | 42 ev.evalFile(filename); 42 } 43 } 43 44 44 /// Repeat the singleInteraction 45 /// Repeat the singleInteraction 45 void replLoop() 46 void replLoop() 46 { 47 { 47 while( singleInteraction() ) {} 48 while( singleInteraction() ) {} 48 } 49 } ................................................................................................................................................................................ 74 { 75 { 75 scope(failure) 76 scope(failure) 76 { buf = ""; lineno = nextlineno; } 77 { buf = ""; lineno = nextlineno; } 77 78 78 buf ~= s; 79 buf ~= s; 79 nextlineno ++; 80 nextlineno ++; 80 try 81 try 81 { lastVal = eval(parseString(buf, "<REPL>", lineno), ctx | 82 { lastVal = ev.evalString(buf, "<REPL>", lineno); } 82 catch( UnexpectedEOF ) 83 catch( UnexpectedEOF ) 83 { return false; } // wait 84 { return false; } // wait 84 buf = ""; 85 buf = ""; 85 lineno = nextlineno; 86 lineno = nextlineno; 86 return true; 87 return true; 87 } 88 } 88 } 89 }

Modified polemy/_common.d from [05624ab3274c99f8] to [05c4f6a92646def3].

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

Modified polemy/ast.d from [73653a45c2c5d30a] to [cf8f245149fce4dc].

14 { 14 { 15 LexPosition pos; 15 LexPosition pos; 16 mixin SimpleConstructor; 16 mixin SimpleConstructor; 17 mixin SimplePatternMatch; 17 mixin SimplePatternMatch; 18 } 18 } 19 19 20 /// 20 /// 21 class IntLiteral : AST | 21 class Int : AST 22 { 22 { 23 BigInt data; 23 BigInt data; 24 mixin SimpleClass; 24 mixin SimpleClass; 25 this(LexPosition pos, int n) {super(pos); data = n;} 25 this(LexPosition pos, int n) {super(pos); data = n;} 26 this(LexPosition pos, long n) {super(pos); data = n;} 26 this(LexPosition pos, long n) {super(pos); data = n;} 27 this(LexPosition pos, BigInt n) {super(pos); data = n;} 27 this(LexPosition pos, BigInt n) {super(pos); data = n;} 28 this(LexPosition pos, string n) {super(pos); data = BigInt(n);} 28 this(LexPosition pos, string n) {super(pos); data = BigInt(n);} 29 } 29 } 30 30 31 /// 31 /// 32 class StrLiteral : AST | 32 class Str : AST 33 { 33 { 34 string data; 34 string data; 35 mixin SimpleClass; 35 mixin SimpleClass; 36 } 36 } 37 37 38 /// 38 /// 39 class VarExpression : AST | 39 class Var : AST 40 { 40 { 41 string name; 41 string name; 42 mixin SimpleClass; 42 mixin SimpleClass; 43 } 43 } 44 44 45 /// 45 /// 46 class LayExpression : AST | 46 class Lay : AST 47 { 47 { 48 Layer layer; 48 Layer layer; 49 AST expr; 49 AST expr; 50 mixin SimpleClass; 50 mixin SimpleClass; 51 } 51 } 52 52 53 /// 53 /// 54 class LetExpression : AST | 54 class Let : AST 55 { 55 { 56 string name; 56 string name; 57 Layer layer; 57 Layer layer; 58 AST init; 58 AST init; 59 AST expr; 59 AST expr; 60 mixin SimpleClass; 60 mixin SimpleClass; 61 } 61 } 62 62 63 /// 63 /// 64 class FuncallExpression : AST | 64 class App : AST 65 { 65 { 66 AST fun; 66 AST fun; 67 AST[] args; 67 AST[] args; 68 this(LexPosition pos, AST fun, AST[] args...) 68 this(LexPosition pos, AST fun, AST[] args...) 69 { super(pos); this.fun=fun; this.args=args.dup; } 69 { super(pos); this.fun=fun; this.args=args.dup; } 70 mixin SimpleClass; 70 mixin SimpleClass; 71 } 71 } ................................................................................................................................................................................ 75 { 75 { 76 string name; 76 string name; 77 Layer[] layers; 77 Layer[] layers; 78 mixin SimpleClass; 78 mixin SimpleClass; 79 } 79 } 80 80 81 /// 81 /// 82 class FunLiteral : AST | 82 class Fun : AST 83 { 83 { 84 Parameter[] params; 84 Parameter[] params; 85 AST funbody; 85 AST funbody; 86 mixin SimpleClass; 86 mixin SimpleClass; 87 } 87 } 88 88 89 /// Handy Generator for AST nodes. To use this, mixin EasyAst; 89 /// Handy Generator for AST nodes. To use this, mixin EasyAst; ................................................................................................................................................................................ 91 /*mixin*/ 91 /*mixin*/ 92 template EasyAST() 92 template EasyAST() 93 { 93 { 94 /// 94 /// 95 template genEast(T) 95 template genEast(T) 96 { T genEast(P...)(P ps) { return new T(LexPosition.dummy, ps); } 96 { T genEast(P...)(P ps) { return new T(LexPosition.dummy, ps); } 97 97 98 alias genEast!StrLiteral strl; /// | 98 alias genEast!Str strl; /// 99 alias genEast!IntLiteral intl; /// | 99 alias genEast!Int intl; /// 100 auto fun(string[] xs, AST ps) { 100 auto fun(string[] xs, AST ps) { 101 return genEast!FunLiteral(array(map!((string x){return new Param | 101 return genEast!Fun(array(map!((string x){return new Parameter(x, 102 auto funp(Parameter[] xs, AST ps) { return genEast!FunLiteral(xs,ps); } | 102 auto funp(Parameter[] xs, AST ps) { return genEast!Fun(xs,ps); } /// 103 alias genEast!VarExpression var; /// | 103 alias genEast!Var var; /// 104 alias genEast!LayExpression lay; /// | 104 alias genEast!Lay lay; /// 105 alias genEast!LetExpression let; /// | 105 alias genEast!Let let; /// 106 alias genEast!FuncallExpression call; /// | 106 alias genEast!App call; /// 107 auto param(string name, string[] lay...) { return new Parameter(name, la 107 auto param(string name, string[] lay...) { return new Parameter(name, la 108 } 108 }

Modified polemy/eval.d from [9a9618fb0277f966] to [b119954d6ce43301].

7 module polemy.eval; 7 module polemy.eval; 8 import polemy._common; 8 import polemy._common; 9 import polemy.failure; 9 import polemy.failure; 10 import polemy.ast; 10 import polemy.ast; 11 import polemy.parse; 11 import polemy.parse; 12 import polemy.value; 12 import polemy.value; 13 import polemy.layer; 13 import polemy.layer; 14 import std.typecons; < 15 import std.stdio; < 16 14 17 /// < 18 Table createGlobalContext() < > 15 class Evaluator 19 { 16 { > 17 public: 20 auto ctx = new Table; | 18 this() { theContext = new Table; } 21 ctx.set("+", ValueLayer, native( (IntValue lhs, IntValue rhs){return new < 22 ctx.set("-", ValueLayer, native( (IntValue lhs, IntValue rhs){return new < > 19 23 ctx.set("*", ValueLayer, native( (IntValue lhs, IntValue rhs){return new | 20 Value evalAST(AST e) 24 ctx.set("/", ValueLayer, native( (IntValue lhs, IntValue rhs){return new < > 21 { 25 ctx.set("%", ValueLayer, native( (IntValue lhs, IntValue rhs){return new | 22 return eval(e, ValueLayer, theContext, OverwriteCtx); 26 ctx.set("||", ValueLayer, native( (IntValue lhs, IntValue rhs){return ne < 27 ctx.set("&&", ValueLayer, native( (IntValue lhs, IntValue rhs){return ne < > 23 } > 24 28 ctx.set("<", ValueLayer, native( (Value lhs, Value rhs){return new IntVa | 25 Value evalString(S,T...)(S str, T fn_ln_cn) 29 ctx.set(">", ValueLayer, native( (Value lhs, Value rhs){return new IntVa < > 26 { 30 ctx.set("<=", ValueLayer, native( (Value lhs, Value rhs){return new IntV | 27 return evalAST(parseString(str,fn_ln_cn)); 31 ctx.set(">=", ValueLayer, native( (Value lhs, Value rhs){return new IntV < 32 ctx.set("==", ValueLayer, native( (Value lhs, Value rhs){return new IntV < > 28 } > 29 33 ctx.set("!=", ValueLayer, native( (Value lhs, Value rhs){return new IntV | 30 Value evalFile(S,T...)(S filename, T ln_cn) 34 ctx.set("print", ValueLayer, native( (Value a){ < > 31 { 35 writeln(a); | 32 return evalAST(parseFile(filename,ln_cn)); 36 return new IntValue(BigInt(0)); < 37 })); < > 33 } > 34 38 ctx.set("if", ValueLayer, native( (IntValue x, FunValue ft, FunValue fe) | 35 Table globalContext() 39 auto toRun = (x.data==0 ? fe : ft); < > 36 { 40 // [TODO] fill positional information | 37 return theContext; 41 return toRun.invoke(null, ValueLayer, toRun.definitionContext()) < 42 // return toRun.invoke(pos, lay, toRun.definitionContext()); < 43 })); < > 38 } > 39 > 40 private: 44 ctx.set("_isint", ValueLayer, native( (Value v){return new IntValue(BigI | 41 Table theContext; 45 ctx.set("_isstr", ValueLayer, native( (Value v){return new IntValue(BigI < > 42 46 ctx.set("_isfun", ValueLayer, native( (Value v){return new IntValue(BigI | 43 private: 47 ctx.set("_isundefined", ValueLayer, native( (Value v){return new IntValu | 44 enum : bool { CascadeCtx=false, OverwriteCtx=true }; 48 ctx.set("_istable", ValueLayer, native( (Value v){return new IntValue(Bi < > 45 49 ctx.set(".", ValueLayer, native( (Table t, StrValue s){ | 46 Value eval( AST e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 50 return (t.has(s.data, ValueLayer) ? t.get(s.data, ValueLayer) : < > 47 { 51 }) ); | 48 // dynamic-overload-resolution-pattern: modify here 52 ctx.set(".?", ValueLayer, native( (Table t, StrValue s){ | 49 enum funName = "eval"; 53 return new IntValue(BigInt(t.has(s.data, ValueLayer) ? 1 : 0)); | 50 alias TypeTuple!(e,lay,ctx,overwriteCtx) params; 54 }) ); < > 51 55 ctx.set(".=", ValueLayer, native( (Table t, StrValue s, Value v){ | 52 // dynamic-overload-resolution-pattern: dispatch 56 auto t2 = new Table(t, Table.Kind.NotPropagateSet); | 53 alias typeof(__traits(getOverloads, this, funName)) ovTypes; > 54 alias staticMap!(firstParam, ovTypes) fstTypes; > 55 alias DerivedToFront!(fstTypes) fstTypes_sorted; > 56 foreach(i, T; fstTypes_sorted) > 57 static if( is(T == typeof(params[0])) ) {} else if( auto > 58 return __traits(getOverloads, this, funName)[i]( > 59 > 60 // dynamic-overload-resolution-pattern: default behavior > 61 assert(false, text("eval() for ",typeid(e)," [",e.pos,"] is not > 62 } > 63 > 64 private: > 65 Value eval( Str e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) > 66 { > 67 Value v = new StrValue(e.data); > 68 if( lay==RawMacroLayer || lay==MacroLayer ) > 69 { > 70 auto ast = new Table; > 71 ast.set("pos", ValueLayer, fromPos(e.pos)); > 72 ast.set("is", ValueLayer, new StrValue("str")); 57 t2.set(s.data, ValueLayer, v); | 73 ast.set("data", ValueLayer, v); > 74 return ast; > 75 } > 76 if( lay==ValueLayer ) 58 return t2; | 77 return v; 59 }) ); < > 78 return lift(v, lay, ctx, e.pos); > 79 } > 80 > 81 Value eval( Int e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) > 82 { > 83 Value v = new IntValue(e.data); > 84 if( lay==RawMacroLayer || lay==MacroLayer ) > 85 { > 86 auto ast = new Table; > 87 ast.set("pos", ValueLayer, fromPos(e.pos)); > 88 ast.set("is", ValueLayer, new StrValue("int")); 60 ctx.set("{}", ValueLayer, native( (){ | 89 ast.set("data", ValueLayer, v); 61 return new Table; | 90 return ast; 62 }) ); < > 91 } > 92 if( lay==ValueLayer ) 63 return ctx; | 93 return v; > 94 return lift(v, lay, ctx, e.pos); 64 } | 95 } 65 | 96 66 /// Entry point of this module < > 97 Value eval( Var e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 67 | 98 { 68 Tuple!(Value,"val",Table,"ctx") evalString(S,T...)(S str, T fn_ln_cn) < > 99 if( lay==RawMacroLayer || lay==MacroLayer ) 69 { | 100 { 70 return eval( polemy.parse.parseString(str, fn_ln_cn) ); < > 101 if( ctx.has(e.name,MacroLayer) ) > 102 return ctx.get(e.name, MacroLayer, e.pos); > 103 auto ast = new Table; > 104 ast.set("pos", ValueLayer, fromPos(e.pos)); > 105 ast.set("is", ValueLayer, new StrValue("var")); > 106 ast.set("name", ValueLayer, new StrValue(e.name)); > 107 return ast; 71 } | 108 } > 109 if( lay==ValueLayer || ctx.has(e.name, lay) ) > 110 return ctx.get(e.name, lay, e.pos); > 111 return lift(ctx.get(e.name, ValueLayer, e.pos), lay, ctx, e.pos) 72 | 112 } 73 /// Entry point of this module < 74 | 113 75 Tuple!(Value,"val",Table,"ctx") evalFile(S, T...)(S filename, T ln_cn) < > 114 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 76 { | 115 { 77 return eval( polemy.parse.parseFile(filename, ln_cn) ); < > 116 Value f = eval( e.fun, lay, ctx ); > 117 if( lay==RawMacroLayer || lay==MacroLayer ) > 118 { > 119 if( auto ff = cast(FunValue)f ) > 120 return invokeFunction(ff, e.args, MacroLayer, ct > 121 Table ast = new Table; > 122 ast.set("pos", ValueLayer, fromPos(e.pos)); > 123 ast.set("is", ValueLayer, new StrValue("app")); > 124 ast.set("fun", ValueLayer, f); > 125 Table args = new Table; > 126 foreach_reverse(a; e.args) > 127 args = makeCons(eval(a, lay, ctx), args); > 128 ast.set("args", ValueLayer, args); > 129 return ast; 78 } | 130 } > 131 else 79 | 132 { 80 /// Entry point of this module < > 133 return invokeFunction(f, e.args, lay, ctx, e.pos); 81 | 134 } 82 Tuple!(Value,"val",Table,"ctx") eval(AST e) < > 135 } 83 { | 136 84 Table ctx = createGlobalContext(); < 85 return typeof(return)(eval(e, ctx, false, ValueLayer), ctx); < > 137 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) > 138 { > 139 if( lay==RawMacroLayer || lay==MacroLayer ) > 140 { > 141 Table t = new Table; > 142 t.set("pos", ValueLayer, fromPos(e.pos)); > 143 t.set("is", ValueLayer, new StrValue("fun")); > 144 t.set("funbody", ValueLayer, eval(e.funbody,lay,ctx)); > 145 Table params = new Table; > 146 foreach_reverse(p; e.params) > 147 { > 148 Table lays = new Table; > 149 foreach_reverse(l; p.layers) > 150 lays = makeCons(new StrValue(l), lays); > 151 Table kv = new Table; > 152 kv.set("name", ValueLayer, new StrValue(p.name)) > 153 kv.set("layers", ValueLayer, lays); > 154 Table cons = new Table; > 155 params = makeCons(kv, params); 86 } | 156 } > 157 t.set("params", ValueLayer, params); > 158 return t; 87 | 159 } 88 Value invokeFunction(in LexPosition pos, Value _f, AST[] args, Table callerCtx, < > 160 else 89 { | 161 { 90 if(auto f = cast(FunValue)_f) < > 162 return createNewFunction(e, ctx); > 163 } > 164 } > 165 > 166 Value eval( Lay e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 91 { 167 { 92 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa < 93 foreach(i,p; f.params()) < 94 if( p.layers.empty ) < 95 if(lay==MacroLayer) | 168 if( lay == RawMacroLayer ) > 169 { > 170 Value r = eval(e.expr, lay, ctx); > 171 auto ast = new Table; // todo: pos 96 ctx.set(p.name, lay, macroEval(args[i], | 172 ast.set("pos", ValueLayer, fromPos(e.pos)); 97 else | 173 ast.set("is", ValueLayer, new StrValue("lay")); 98 ctx.set(p.name, lay, eval(args[i], calle | 174 ast.set("layer", ValueLayer, new StrValue(e.layer)); 99 else | 175 ast.set("expr", ValueLayer, r); 100 foreach(argLay; p.layers) | 176 return ast; 101 if(argLay==MacroLayer) < 102 ctx.set(p.name, argLay, macroEva < > 177 } 103 else | 178 else 104 ctx.set(p.name, argLay, eval(arg < 105 return f.invoke(pos, lay, ctx); < > 179 return eval(e.expr, e.layer, ctx); 106 } 180 } 107 throw genex!RuntimeException(pos, "tried to call non-function"); < 108 } < 109 181 110 Value lift(in LexPosition pos, Value v, Layer lay, Table callerCtx) | 182 Value eval( Let e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 111 { < 112 // functions are automatically lifterd < 113 if( cast(FunValue) v ) < 114 return v; < 115 < 116 // similar to invoke Function, but with only one argument bound to Value < 117 Value _f = callerCtx.get(lay, SystemLayer, pos); < 118 if(auto f = cast(FunValue)_f) < 119 { 183 { 120 Table ctx = new Table(f.definitionContext(), Table.Kind.NotPropa | 184 // todo @macro let 121 auto ps = f.params(); | 185 if( lay==RawMacroLayer || lay==MacroLayer ) 122 if( ps.length != 1 ) < 123 throw genex!RuntimeException(pos, "lift function must ta < 124 if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].la < 125 { 186 { 126 ctx.set(ps[0].name, ValueLayer, v); | 187 auto ast = new Table; // todo: pos 127 return f.invoke(pos, ValueLayer, ctx); | 188 ast.set("pos", ValueLayer, fromPos(e.pos)); > 189 ast.set("is", ValueLayer, new StrValue("let")); > 190 ast.set("name", ValueLayer, new StrValue(e.name)); > 191 ast.set("layer", ValueLayer, new StrValue(e.layer)); > 192 ast.set("init", ValueLayer, eval(e.init, lay, ctx)); > 193 ast.set("expr", ValueLayer, eval(e.expr, lay, ctx)); > 194 return ast; 128 } 195 } 129 else 196 else 130 throw genex!RuntimeException(pos, "lift function must ta < 131 } < 132 throw genex!RuntimeException(pos, "tried to call non-function"); < 133 } < 134 < 135 /// Entry point of this module < 136 /// If splitCtx = true, then inner variable declaration do not overwrite ctx. < 137 /// lay is the layer ID for evaluation (standard value semantics uses ValueLayer < 138 < 139 Value eval(AST e, Table ctx, bool splitCtx, Layer lay) < 140 { < 141 return e.match( < 142 (StrLiteral e) < 143 { 197 { 144 Value v = new StrValue(e.data); | 198 if( !overwriteCtx ) 145 if( lay == ValueLayer ) < 146 return v; < 147 else < 148 return lift(e.pos,v,lay,ctx); < 149 }, < 150 (IntLiteral e) < 151 { < 152 Value v = new IntValue(e.data); < 153 if( lay == ValueLayer ) < 154 return v; < 155 else // rise < 156 return lift(e.pos,v,lay,ctx); < 157 }, < 158 (VarExpression e) < 159 { < 160 if( lay == ValueLayer ) < 161 return ctx.get(e.name, lay, e.pos); < 162 if( ctx.has(e.name, lay, e.pos) ) < 163 return ctx.get(e.name, lay, e.pos); < 164 else < 165 return lift(e.pos, ctx.get(e.name, ValueLayer, e < 166 }, < 167 (LayExpression e) < 168 { < 169 if( e.layer == MacroLayer ) < 170 return macroEval(e.expr, ctx, false); < 171 else < 172 return eval(e.expr, ctx, true, e.layer); < 173 }, < 174 (LetExpression e) < 175 { < 176 // for letrec, we need this, but should avoid overwritin < 177 // ctx.set(e.var, ValueLayer, new UndefinedValue, e.pos) < 178 if(splitCtx) < 179 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 199 ctx = new Table(ctx, Table.Kind.NotPropagateSet) 180 Value v = eval(e.init, ctx, true, lay); | 200 Value ri = eval(e.init, lay, ctx); > 201 string theLayer = e.layer.empty ? (lay==RawMacroLayer ? 181 ctx.set(e.name, (e.layer.length ? e.layer : lay), v, e.p | 202 ctx.set(e.name, theLayer, ri); 182 return eval(e.expr, ctx, false, lay); | 203 return eval(e.expr, lay, ctx, OverwriteCtx); 183 }, < 184 (FuncallExpression e) < > 204 } > 205 } 185 { | 206 186 return invokeFunction(e.pos, eval(e.fun, ctx, true, lay) < 187 }, < > 207 private: 188 (FunLiteral e) | 208 Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosi 189 { | 209 { 190 return new UserDefinedFunValue(e, ctx); | 210 if(auto f = cast(FunValue)_f) 191 }, < 192 delegate Value (AST e) < 193 { 211 { 194 throw genex!RuntimeException(e.pos, sprintf!"Unknown Kin | 212 Table newCtx = new Table(f.definitionContext(), Table.Ki > 213 foreach(i,p; f.params()) > 214 if( p.layers.empty ) > 215 newCtx.set(p.name, (lay==RawMacroLayer ? > 216 else > 217 foreach(argLay; p.layers) > 218 newCtx.set(p.name, argLay, eval( > 219 return f.invoke(pos, lay, newCtx); 195 } 220 } 196 ); | 221 throw genex!RuntimeException(pos, text("tried to call non-functi 197 } | 222 } 198 < 199 // [TODO] Optimization < 200 Value macroEval(AST e, Table ctx, bool AlwaysMacro) < 201 { < 202 Layer theLayer = ValueLayer; < 203 223 204 Table makeCons(Value a, Value d) | 224 Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null) 205 { 225 { 206 Table t = new Table; | 226 // functions are automatically lifterd 207 t.set("car", theLayer, a); | 227 if( cast(FunValue) v ) 208 t.set("cdr", theLayer, d); < 209 return t; | 228 return v; > 229 > 230 // similar to invoke Function, but with only one argument bound > 231 if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos)) > 232 { > 233 Table newCtx = new Table(f.definitionContext(), Table.Ki > 234 auto ps = f.params(); > 235 if( ps.length != 1 ) > 236 throw genex!RuntimeException(pos, "lift function > 237 if( ps[0].layers.length==0 || ps[0].layers.length==1 && > 238 { > 239 newCtx.set(ps[0].name, ValueLayer, v); > 240 return f.invoke(pos, ValueLayer, newCtx); > 241 } > 242 else > 243 throw genex!RuntimeException(pos, "lift function > 244 } > 245 throw genex!RuntimeException(pos, "tried to call non-function"); 210 } 246 } 211 247 212 Table pos = new Table; | 248 Value createNewFunction(Fun e, Table ctx) 213 if( e.pos !is null ) { < 214 pos.set("filename", theLayer, new StrValue(e.pos.filename)); < 215 pos.set("lineno", theLayer, new IntValue(BigInt(e.pos.lineno)) < 216 pos.set("column", theLayer, new IntValue(BigInt(e.pos.column)) < 217 } else { < 218 pos.set("filename", theLayer, new StrValue("nullpos")); < 219 pos.set("lineno", theLayer, new IntValue(BigInt(0))); < 220 pos.set("column", theLayer, new IntValue(BigInt(0))); < 221 } < 222 | 249 { 223 return e.match( < 224 (StrLiteral e) < > 250 class UserDefinedFunValue : FunValue 225 { 251 { 226 Table t = new Table; | 252 Fun ast; 227 t.set("pos", theLayer, pos); | 253 Table defCtx; 228 t.set("is", theLayer, new StrValue("str")); | 254 override const(Parameter[]) params() { return ast.params 229 t.set("data", theLayer, new StrValue(e.data)); | 255 override Table definitionContext() { return defCtx; } 230 return t; < > 256 231 }, | 257 this(Fun ast, Table defCtx) { this.ast=ast; this.defCtx= 232 (IntLiteral e) | 258 override string toString() const { return sprintf!"(func > 259 override bool opEquals(Object rhs_) const /// member-by- 233 { | 260 { 234 Table t = new Table; < 235 t.set("pos", theLayer, pos); | 261 if( auto rhs = cast(typeof(this))rhs_ ) 236 t.set("is", theLayer, new StrValue("int")); | 262 return this.ast==rhs.ast && this.defCtx= 237 t.set("data", theLayer, new IntValue(e.data)); | 263 assert(false, sprintf!"Cannot compare %s with %s 238 return t; < 239 }, < 240 (VarExpression e) < > 264 } > 265 override hash_t toHash() const /// member-by-member hash 241 { | 266 { 242 if( ctx.has(e.name, MacroLayer, e.pos) ) < > 267 return typeid(this.ast).getHash(&this.ast) + typ > 268 } 243 return ctx.get(e.name, MacroLayer, e.pos); | 269 override int opCmp(Object rhs_) /// member-by-member com 244 else { < > 270 { 245 Table t = new Table; | 271 if( auto rhs = cast(typeof(this))rhs_ ) 246 t.set("pos", theLayer, pos); < > 272 { 247 t.set("is", theLayer, new StrValue("var")); | 273 if(auto i = this.ast.opCmp(rhs.ast)) 248 t.set("name", theLayer, new StrValue(e.name)); < 249 return cast(Value)t; | 274 return i; > 275 return this.defCtx.opCmp(rhs.defCtx); > 276 } > 277 assert(false, sprintf!"Cannot compare %s with %s 250 } 278 } 251 }, < 252 (LayExpression e) < 253 { | 279 254 if( AlwaysMacro ) < > 280 override Value invoke(LexPosition pos, Layer lay, Table 255 { 281 { 256 Table t = new Table; | 282 if( lay == MacroLayer ) 257 t.set("pos", theLayer, pos); | 283 return eval(ast.funbody, lay, ctx); 258 t.set("is", theLayer, new StrValue("lay")); | 284 auto macroed = tableToAST(ValueLayer, eval(e.fun 259 t.set("layer", theLayer, new StrValue(e.layer)); | 285 return eval(macroed, lay, ctx); 260 t.set("expr", theLayer, macroEval(e.expr,ctx,Al < 261 return cast(Value)t; < 262 } 286 } 263 else < > 287 } > 288 return new UserDefinedFunValue(e,ctx); > 289 } 264 { | 290 265 if( e.layer == MacroLayer ) < 266 return macroEval(e.expr, ctx, false); < 267 else | 291 public: 268 return eval(e.expr, ctx, true, e.layer); | 292 /// TODO: move up 269 } < > 293 /// TDOO: to other layers? 270 }, | 294 void addPrimitive(R,T...)(string name, Layer lay, R delegate (T) dg) 271 (LetExpression e) < > 295 { > 296 class NativeFunValue : FunValue 272 { 297 { 273 Table t = new Table; | 298 Parameter[] params_data; 274 t.set("pos", theLayer, pos); | 299 override string toString() { return sprintf!"(native:%x) 275 t.set("is", theLayer, new StrValue("let")); | 300 override const(Parameter[]) params() { return params_dat 276 t.set("name", theLayer, new StrValue(e.name)); | 301 override Table definitionContext() { return new Table; } 277 t.set("init", theLayer, macroEval(e.init,ctx,AlwaysMacro | 302 this(){ 278 t.set("expr", theLayer, macroEval(e.expr,ctx,AlwaysMacro | 303 foreach(i, Ti; T) 279 return t; | 304 params_data ~= new Parameter(text(i), [] 280 }, < > 305 } 281 (FuncallExpression e) | 306 override Value invoke(LexPosition pos, Layer lay, Table 282 { | 307 { 283 Value _f = macroEval(e.fun,ctx,AlwaysMacro); | 308 if( lay != ValueLayer ) > 309 throw genex!RuntimeException(pos, "only > 310 T typed_args; > 311 foreach(i, Ti; T) { > 312 typed_args[i] = cast(Ti) ctx.get(text(i) > 313 if( typed_args[i] is null ) > 314 throw genex!RuntimeException(pos 284 | 315 } 285 if( auto f = cast(FunValue)_f ) < 286 return invokeFunction(e.pos, f, e.args, ctx, Mac < > 316 try { > 317 return dg(typed_args); > 318 } catch( RuntimeException e ) { > 319 throw e.pos is null ? new RuntimeExcepti 287 | 320 } 288 Table t = new Table; < 289 t.set("pos", theLayer, pos); < 290 t.set("is", theLayer, new StrValue("app")); < 291 t.set("fun", theLayer, _f); < 292 Table args = new Table; < 293 foreach_reverse(a; e.args) { < 294 Table cons = new Table; < 295 cons.set("car",theLayer,macroEval(a,ctx,AlwaysMa < 296 cons.set("cdr",theLayer,args); < 297 args = cons; < 298 } 321 } 299 t.set("args", theLayer, args); < 300 return cast(Value)t; < 301 }, < 302 (FunLiteral e) < 303 { < 304 Table t = new Table; < 305 t.set("pos", theLayer, pos); < 306 t.set("is", theLayer, new StrValue("fun")); < 307 t.set("funbody", theLayer, macroEval(e.funbody,ctx,Alwa < 308 Table params = new Table; < 309 foreach_reverse(p; e.params) < 310 { < 311 Table lays = new Table; < 312 foreach_reverse(lay; p.layers) < 313 lays = makeCons(new StrValue(lay), lays) < 314 Table kv = new Table; < 315 kv.set("name", theLayer, new StrValue(p.name)); < 316 kv.set("layers", theLayer, lays); < 317 Table cons = new Table; < 318 params = makeCons(kv, params); < 319 } < 320 t.set("params", theLayer, params); < 321 return t; < 322 }, < 323 delegate Value (AST e) < 324 { < 325 throw genex!RuntimeException(e.pos, sprintf!"Unknown Kin < 326 } 322 } > 323 theContext.set(name, lay, new NativeFunValue); > 324 } > 325 } > 326 > 327 version(unittest) import polemy.runtime; > 328 unittest > 329 { > 330 auto e = new Evaluator; > 331 enrollRuntimeLibrary(e); > 332 auto r = assert_nothrow( e.evalString(`var x = 21; x + x*x;`) ); > 333 assert_eq( r, new IntValue(BigInt(21+21*21)) ); > 334 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21)) > 335 assert_nothrow( e.globalContext.get("x",ValueLayer) ); > 336 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); > 337 } > 338 unittest > 339 { > 340 auto e = new Evaluator; > 341 enrollRuntimeLibrary(e); > 342 auto r = assert_nothrow( e.evalString(`var x = 21; var x = x + x*x;`) ); > 343 assert_eq( r, new IntValue(BigInt(21+21*21)) ); > 344 assert_eq( e.globalContext.get("x",ValueLayer), new IntValue(BigInt(21+2 > 345 assert_nothrow( e.globalContext.get("x",ValueLayer) ); > 346 assert_throw!RuntimeException( e.globalContext.get("y",ValueLayer) ); > 347 } > 348 unittest > 349 { > 350 auto e = new Evaluator; > 351 enrollRuntimeLibrary(e); > 352 assert_eq( e.evalString(`let x=1; let y=(let x=2); x`), new IntValue(Big > 353 assert_eq( e.evalString(`let x=1; let y=(let x=2;fun(){x}); y()`), new I > 354 } > 355 > 356 unittest > 357 { > 358 auto e = new Evaluator; > 359 enrollRuntimeLibrary(e); > 360 assert_eq( e.evalString(`@a x=1; @b x=2; @a(x)`), new IntValue(BigInt(1) > 361 assert_eq( e.evalString(`@a x=1; @b x=2; @b(x)`), new IntValue(BigInt(2) > 362 assert_eq( e.evalString(`let x=1; let _ = (@a x=2;2); x`), new IntValue( > 363 e = new Evaluator; > 364 assert_throw!Throwable( e.evalString(`let x=1; let _ = (@a x=2;2); @a(x) > 365 } > 366 > 367 unittest > 368 { > 369 auto e = new Evaluator; > 370 enrollRuntimeLibrary(e); > 371 assert_eq( e.evalString(` > 372 @@s(x){x}; > 373 @s "+" = fun(x, y) {@value( > 374 @s(x) - @s(y) 327 ); | 375 )}; > 376 @s(1 + 2) > 377 `), new IntValue(BigInt(-1)) ); > 378 } > 379 > 380 unittest > 381 { > 382 auto e = new Evaluator; > 383 enrollRuntimeLibrary(e); > 384 assert_eq( e.evalString(` > 385 @@3(x){x}; > 386 def incr(x) { x+1 }; > 387 @ 3 incr(x) {@value( if(@ 3(x)+1< 3){@ 3(x)+1}else{0} )}; > 388 def fb(n @value @3) { @3(n) }; > 389 fb(incr(incr(incr(0)))) > 390 `), new IntValue(BigInt(0)) ); 328 } 391 } 329 392 330 unittest 393 unittest 331 { 394 { 332 auto r = assert_nothrow( evalString(`var x = 21; x + x*x;`) ); | 395 auto e = new Evaluator; 333 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); | 396 enrollRuntimeLibrary(e); 334 assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21)) ); < 335 assert_nothrow( r.ctx.get("x",ValueLayer) ); | 397 assert_nothrow( e.evalString(` > 398 @macro twice(x) { x; x }; 336 assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) ); | 399 def main() { twice(1) }; 337 } < 338 unittest < 339 { < 340 auto r = assert_nothrow( evalString(`var x = 21; var x = x + x*x;`) ); < 341 assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); < 342 assert_eq( r.ctx.get("x",ValueLayer), new IntValue(BigInt(21+21*21)) ); < 343 assert_nothrow( r.ctx.get("x",ValueLayer) ); < 344 assert_throw!RuntimeException( r.ctx.get("y",ValueLayer) ); < 345 } < 346 unittest < 347 { < 348 assert_eq( evalString(`let x=1; let y=(let x=2); x`).val, new IntValue(B < 349 assert_eq( evalString(`let x=1; let y=(let x=2;fun(){x}); y()`).val, new < 350 } < 351 unittest < 352 { < 353 assert_eq( evalString(`@a x=1; @b x=2; @a(x)`).val, new IntValue(BigInt( < 354 assert_eq( evalString(`@a x=1; @b x=2; @b(x)`).val, new IntValue(BigInt( < 355 assert_eq( evalString(`let x=1; let _ = (@a x=2;2); x`).val, new IntValu < 356 assert_throw!Throwable( evalString(`let x=1; let _ = (@a x=2;2); @a(x)`) < > 400 main() > 401 `) ); 357 } 402 } 358 /* 403 /* 359 unittest 404 unittest 360 { 405 { 361 assert_eq( evalString(`var fac = fun(x){ 406 assert_eq( evalString(`var fac = fun(x){ 362 if(x) 407 if(x) 363 { x*fac(x-1); } 408 { x*fac(x-1); } ................................................................................................................................................................................ 369 if(x<2) 414 if(x<2) 370 { 1; } 415 { 1; } 371 else 416 else 372 { fib(x-1) + fib(x-2); }; 417 { fib(x-1) + fib(x-2); }; 373 }; 418 }; 374 fib(5);`).val, new IntValue(BigInt(8))); 419 fib(5);`).val, new IntValue(BigInt(8))); 375 } 420 } 376 < 377 unittest < 378 { < 379 assert_throw!Throwable( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};@s(1 < 380 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){x-y};1+2`).val, new In < 381 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};1 < 382 assert_eq( evalString(`@@s(x){x}; @s "+"=fun(x,y){@value(@s(x)-@s(y))};@ < 383 } < 384 < 385 unittest 421 unittest 386 { 422 { 387 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi 423 assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(Bi 388 // there was a bug that declaration in the first line of function defini 424 // there was a bug that declaration in the first line of function defini 389 // cannot be recursive 425 // cannot be recursive 390 assert_nothrow( evalString(`def foo() { 426 assert_nothrow( evalString(`def foo() { 391 def bar(y) { if(y<1) {0} else {bar(0)} }; 427 def bar(y) { if(y<1) {0} else {bar(0)} }; 392 bar(1) 428 bar(1) 393 }; foo()`) ); 429 }; foo()`) ); 394 } 430 } 395 */ 431 */

Modified polemy/layer.d from [91a3b7f2c4f61824] to [79038e8ac0f7ba6a].

10 10 11 /// Type for the layer ID 11 /// Type for the layer ID 12 12 13 alias string Layer; 13 alias string Layer; 14 14 15 enum : Layer 15 enum : Layer 16 { 16 { 17 SystemLayer = "(system)", /// Predefined layer for internal data | 17 SystemLayer = "(system)", /// Predefined layer for internal data 18 ValueLayer = "@value", /// Predefined layer for normal run | 18 ValueLayer = "@value", /// Predefined layer for normal run 19 MacroLayer = "@macro", /// Predefined layer for macro run | 19 MacroLayer = "@macro", /// Predefined layer for macro run > 20 RawMacroLayer = "(rawmacro)", /// Predefined layer for raw-macro run 20 } 21 }

Modified polemy/parse.d from [789e91a27a62e096] to [9df8a8a07696ff22].

98 string kwd = "@" ~ layer; 98 string kwd = "@" ~ layer; 99 string var = layer; 99 string var = layer; 100 100 101 auto e = tryEat("(") 101 auto e = tryEat("(") 102 ? parseLambdaAfterOpenParen(pos) // let var ( . 102 ? parseLambdaAfterOpenParen(pos) // let var ( . 103 : (eat("=", "after "~kwd), E(0)); // let var = . 103 : (eat("=", "after "~kwd), E(0)); // let var = . 104 if( moreDeclarationExists() ) 104 if( moreDeclarationExists() ) 105 return new LetExpression(pos, var, SystemLayer, | 105 return new Let(pos, var, SystemLayer, e, Body()) 106 else 106 else 107 return new LetExpression(pos, var, SystemLayer, | 107 return new Let(pos, var, SystemLayer, e, 108 new LayExpression(pos, SystemLayer, new | 108 new Lay(pos, SystemLayer, new Var(pos, v 109 ); 109 ); 110 } 110 } 111 else 111 else 112 { 112 { 113 string kwd = layer; 113 string kwd = layer; 114 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="va 114 if( layer.empty && !tryEat(kwd="let") && !tryEat(kwd="va 115 return null; // none of {@lay, let, var, def} oc 115 return null; // none of {@lay, let, var, def} oc ................................................................................................................................................................................ 117 auto varpos = currentPosition(); 117 auto varpos = currentPosition(); 118 string var = eatId("after "~kwd, AllowQuoted); // name o 118 string var = eatId("after "~kwd, AllowQuoted); // name o 119 119 120 auto e = tryEat("(") 120 auto e = tryEat("(") 121 ? parseLambdaAfterOpenParen(varpos) // let var 121 ? parseLambdaAfterOpenParen(varpos) // let var 122 : (eat("=", "after "~kwd), E(0)); // let var 122 : (eat("=", "after "~kwd), E(0)); // let var 123 if( moreDeclarationExists() ) 123 if( moreDeclarationExists() ) 124 return new LetExpression(pos, var, layer, e, Bod | 124 return new Let(pos, var, layer, e, Body()); 125 else 125 else 126 return new LetExpression(pos, var, layer, e, new | 126 return new Let(pos, var, layer, e, new Var(varpo 127 } 127 } 128 } 128 } 129 129 130 AST TopLevelExpression() 130 AST TopLevelExpression() 131 { 131 { 132 /// TopLevelExpression ::= Expression ([";"|"in"] Body?)? 132 /// TopLevelExpression ::= Expression ([";"|"in"] Body?)? 133 133 134 auto pos = currentPosition(); 134 auto pos = currentPosition(); 135 auto e = E(0); 135 auto e = E(0); 136 if( moreDeclarationExists() ) 136 if( moreDeclarationExists() ) 137 return new LetExpression(pos, "_", "", e, Body()); | 137 return new Let(pos, "_", "", e, Body()); 138 else 138 else 139 return e; 139 return e; 140 } 140 } 141 141 142 private bool moreDeclarationExists() 142 private bool moreDeclarationExists() 143 { 143 { 144 return (tryEat(";") || tryEat("in")) && !closingBracket(); 144 return (tryEat(";") || tryEat("in")) && !closingBracket(); ................................................................................................................................................................................ 177 return lhs; 177 return lhs; 178 178 179 auto pos = currentPosition(); 179 auto pos = currentPosition(); 180 foreach(op; operator_perferences[level]) 180 foreach(op; operator_perferences[level]) 181 if( tryEat(op) ) 181 if( tryEat(op) ) 182 if( op[0]=='.' ) 182 if( op[0]=='.' ) 183 return rec( 183 return rec( 184 new FuncallExpression(lh | 184 new App(lhs.pos, new Var 185 else 185 else 186 return rec( | 186 return rec( 187 new FuncallExpression(lhs.pos, n | 187 new App(lhs.pos, new Var 188 return lhs; 188 return lhs; 189 } 189 } 190 190 191 if( operator_perferences.length <= level ) 191 if( operator_perferences.length <= level ) 192 return Funcall(); 192 return Funcall(); 193 else 193 else 194 return rec(E(level+1)); 194 return rec(E(level+1)); ................................................................................................................................................................................ 209 throw genex!UnexpectedEOF(pos, " 209 throw genex!UnexpectedEOF(pos, " 210 args ~= E(0); 210 args ~= E(0); 211 if( !tryEat(",") ) { 211 if( !tryEat(",") ) { 212 eat(")", "after function paramet 212 eat(")", "after function paramet 213 break; 213 break; 214 } 214 } 215 } 215 } 216 e = new FuncallExpression(e.pos, e, args); | 216 e = new App(e.pos, e, args); 217 } 217 } 218 else if( tryEat("{") ) 218 else if( tryEat("{") ) 219 { 219 { 220 e = parseTableSetAfterBrace(e); 220 e = parseTableSetAfterBrace(e); 221 } 221 } 222 else 222 else 223 break; 223 break; ................................................................................................................................................................................ 230 return e; 230 return e; 231 auto pos = currentPosition(); 231 auto pos = currentPosition(); 232 for(;;) 232 for(;;) 233 { 233 { 234 string key = eatId("for table key", AllowQuoted); 234 string key = eatId("for table key", AllowQuoted); 235 eat(":", "after table key"); 235 eat(":", "after table key"); 236 AST val = E(0); 236 AST val = E(0); 237 e = new FuncallExpression(pos, new VarExpression(pos,".= | 237 e = new App(pos, new Var(pos,".="), 238 e, new StrLiteral(pos,key), val); | 238 e, new Str(pos,key), val); 239 if( !tryEat(",") ) 239 if( !tryEat(",") ) 240 { 240 { 241 eat("}", "for the end of table literal"); 241 eat("}", "for the end of table literal"); 242 break; 242 break; 243 } 243 } 244 } 244 } 245 return e; 245 return e; ................................................................................................................................................................................ 250 if( lex.empty ) 250 if( lex.empty ) 251 throw genex!UnexpectedEOF(currentPosition(), "Reached EO 251 throw genex!UnexpectedEOF(currentPosition(), "Reached EO 252 252 253 auto pos = lex.front.pos; 253 auto pos = lex.front.pos; 254 if( lex.front.quoted ) 254 if( lex.front.quoted ) 255 { 255 { 256 scope(exit) lex.popFront; 256 scope(exit) lex.popFront; 257 return new StrLiteral(pos, lex.front.str); | 257 return new Str(pos, lex.front.str); 258 } 258 } 259 if( isNumber(lex.front.str) ) 259 if( isNumber(lex.front.str) ) 260 { 260 { 261 scope(exit) lex.popFront; 261 scope(exit) lex.popFront; 262 return new IntLiteral(pos, BigInt(cast(string)lex.front. | 262 return new Int(pos, BigInt(cast(string)lex.front.str)); 263 } 263 } 264 if( tryEat("@") ) 264 if( tryEat("@") ) 265 { 265 { 266 auto lay = "@"~eatId("for layer ID"); 266 auto lay = "@"~eatId("for layer ID"); 267 eat("(", "for layered execution"); 267 eat("(", "for layered execution"); 268 auto e = Body(); 268 auto e = Body(); 269 eat(")", "after "~lay~"(..."); 269 eat(")", "after "~lay~"(..."); 270 return new LayExpression(pos, lay, e); | 270 return new Lay(pos, lay, e); 271 } 271 } 272 if( tryEat("(") ) 272 if( tryEat("(") ) 273 { 273 { 274 auto e = Body(); 274 auto e = Body(); 275 eat(")", "after parenthesized expression"); 275 eat(")", "after parenthesized expression"); 276 return e; 276 return e; 277 } 277 } 278 if( tryEat("{") ) 278 if( tryEat("{") ) 279 { 279 { 280 AST e = new FuncallExpression(pos, new VarExpression(pos | 280 AST e = new App(pos, new Var(pos,"{}")); 281 return parseTableSetAfterBrace(e); 281 return parseTableSetAfterBrace(e); 282 } 282 } 283 if( tryEat("if") ) 283 if( tryEat("if") ) 284 { 284 { 285 eat("(", "after if"); 285 eat("(", "after if"); 286 auto cond = E(0); 286 auto cond = E(0); 287 eat(")", "after if condition"); 287 eat(")", "after if condition"); ................................................................................................................................................................................ 292 auto el = doNothingExpression(); 292 auto el = doNothingExpression(); 293 auto elsePos = (lex.empty ? LexPosition.dummy : lex.fron 293 auto elsePos = (lex.empty ? LexPosition.dummy : lex.fron 294 if( tryEat("else") ) { 294 if( tryEat("else") ) { 295 eat("{", "after else"); 295 eat("{", "after else"); 296 el = Body(); 296 el = Body(); 297 eat("}", "after else body"); 297 eat("}", "after else body"); 298 } 298 } 299 return new FuncallExpression(pos, | 299 return new App(pos, 300 new VarExpression(pos, "if"), | 300 new Var(pos, "if"), 301 cond, 301 cond, 302 new FunLiteral(thenPos, [], th), | 302 new Fun(thenPos, [], th), 303 new FunLiteral(elsePos, [], el) | 303 new Fun(elsePos, [], el) 304 ); 304 ); 305 } 305 } 306 if( tryEat("case") ) 306 if( tryEat("case") ) 307 { 307 { 308 return parsePatternMatch(pos); 308 return parsePatternMatch(pos); 309 } 309 } 310 if( tryEat("fun") || tryEat("\u03BB") ) // lambda!! 310 if( tryEat("fun") || tryEat("\u03BB") ) // lambda!! 311 { 311 { 312 eat("(", "after fun"); 312 eat("(", "after fun"); 313 return parseLambdaAfterOpenParen(pos); 313 return parseLambdaAfterOpenParen(pos); 314 } 314 } 315 scope(exit) lex.popFront; 315 scope(exit) lex.popFront; 316 return new VarExpression(pos, lex.front.str); | 316 return new Var(pos, lex.front.str); 317 } 317 } 318 318 319 AST parsePatternMatch(LexPosition pos) 319 AST parsePatternMatch(LexPosition pos) 320 { 320 { 321 // case( pmExpr )cases 321 // case( pmExpr )cases 322 //==> 322 //==> 323 // let pmVar = pmExpr in (... let pmTryFirst = ... in pmTryFir 323 // let pmVar = pmExpr in (... let pmTryFirst = ... in pmTryFir 324 eat("(", "after case"); 324 eat("(", "after case"); 325 AST pmExpr = E(0); 325 AST pmExpr = E(0); 326 eat(")", "after case"); 326 eat(")", "after case"); 327 string pmVar = freshVarName(); 327 string pmVar = freshVarName(); 328 string pmTryFirst = freshVarName(); 328 string pmTryFirst = freshVarName(); 329 AST pmBody = parsePatternMatchCases(pmVar, pmTryFirst, 329 AST pmBody = parsePatternMatchCases(pmVar, pmTryFirst, 330 new FuncallExpression(pos, new VarExpression(pos, pmTryF | 330 new App(pos, new Var(pos, pmTryFirst))); 331 return new LetExpression(pos, pmVar, [], pmExpr, pmBody); | 331 return new Let(pos, pmVar, [], pmExpr, pmBody); 332 } 332 } 333 333 334 AST parsePatternMatchCases(string pmVar, string tryThisBranchVar, AST th 334 AST parsePatternMatchCases(string pmVar, string tryThisBranchVar, AST th 335 { 335 { 336 // when( pat ) { cBody } 336 // when( pat ) { cBody } 337 //==> 337 //==> 338 // ... let failBranchVar = ... in 338 // ... let failBranchVar = ... in ................................................................................................................................................................................ 343 string failBranchVar = freshVarName(); 343 string failBranchVar = freshVarName(); 344 344 345 eat("(", "after when"); 345 eat("(", "after when"); 346 auto pr = parsePattern(); 346 auto pr = parsePattern(); 347 eat(")", "after when"); 347 eat(")", "after when"); 348 eat("{", "after pattern"); 348 eat("{", "after pattern"); 349 AST cBody = Body(); 349 AST cBody = Body(); 350 AST judgement = new FuncallExpression(pos, new VarExpres | 350 AST judgement = new App(pos, new Var(pos, "if"), 351 ppTest(pmVar, pr), new FunLiteral(pos,[],ppBind( | 351 ppTest(pmVar, pr), new Fun(pos,[],ppBind(pmVar, 352 new VarExpression(pos, failBranchVar)); | 352 new Var(pos, failBranchVar)); 353 eat("}", "after pattern clause"); 353 eat("}", "after pattern clause"); 354 return parsePatternMatchCases(pmVar, failBranchVar, 354 return parsePatternMatchCases(pmVar, failBranchVar, 355 new LetExpression(pos, tryThisBranchVar, [], | 355 new Let(pos, tryThisBranchVar, [], 356 new FunLiteral(pos,[],judgement), thenDo | 356 new Fun(pos,[],judgement), thenDoThis) 357 ); 357 ); 358 } 358 } 359 else 359 else 360 { 360 { 361 auto pos = currentPosition(); 361 auto pos = currentPosition(); 362 AST doNothing = new FunLiteral(pos,[], | 362 AST doNothing = new Fun(pos,[], 363 new StrLiteral(pos, sprintf!"(pattern match fail | 363 new Str(pos, sprintf!"(pattern match failure:%s) 364 return new LetExpression(currentPosition(), tryThisBranc | 364 return new Let(currentPosition(), tryThisBranchVar, [], 365 } 365 } 366 } 366 } 367 367 368 // hageshiku tenuki 368 // hageshiku tenuki 369 abstract class SinglePattern 369 abstract class SinglePattern 370 { 370 { 371 string[] path; 371 string[] path; 372 mixin SimpleClass; 372 mixin SimpleClass; 373 private AST access(string pmVar, string[] path) { 373 private AST access(string pmVar, string[] path) { 374 auto pos = currentPosition(); 374 auto pos = currentPosition(); 375 AST e = new VarExpression(pos, pmVar); | 375 AST e = new Var(pos, pmVar); 376 foreach(p; path) 376 foreach(p; path) 377 e = new FuncallExpression(pos, new VarExpression | 377 e = new App(pos, new Var(pos, "."), e, new Str(p 378 return e; 378 return e; 379 } 379 } 380 private AST has(AST e, string k) { 380 private AST has(AST e, string k) { 381 auto pos = currentPosition(); 381 auto pos = currentPosition(); 382 return opAndAnd( 382 return opAndAnd( 383 new FuncallExpression(pos, new VarExpression(pos | 383 new App(pos, new Var(pos, "_istable"), e), 384 new FuncallExpression(pos, new VarExpression(pos | 384 new App(pos, new Var(pos, ".?"), e, new Str(pos, 385 ); 385 ); 386 } 386 } 387 private AST opAndAnd(AST a, AST b) { 387 private AST opAndAnd(AST a, AST b) { 388 if( a is null ) return b; 388 if( a is null ) return b; 389 if( b is null ) return a; 389 if( b is null ) return a; 390 auto pos = currentPosition(); 390 auto pos = currentPosition(); 391 return new FuncallExpression(pos, | 391 return new App(pos, 392 new VarExpression(pos, "if"), | 392 new Var(pos, "if"), 393 a, 393 a, 394 new FunLiteral(pos, [], b), | 394 new Fun(pos, [], b), 395 new FunLiteral(pos, [], new IntLiteral(pos, 0)) | 395 new Fun(pos, [], new Int(pos, 0)) 396 ); 396 ); 397 } 397 } 398 AST ppTest(string pmVar) { 398 AST ppTest(string pmVar) { 399 AST c = null; 399 AST c = null; 400 for(int i=0; i<path.length; ++i) 400 for(int i=0; i<path.length; ++i) 401 c = opAndAnd(c, has(access(pmVar,path[0..i]), pa 401 c = opAndAnd(c, has(access(pmVar,path[0..i]), pa 402 return c; 402 return c; ................................................................................................................................................................................ 409 } 409 } 410 class VarPattern : SinglePattern 410 class VarPattern : SinglePattern 411 { 411 { 412 string name; 412 string name; 413 mixin SimpleClass; 413 mixin SimpleClass; 414 AST ppBind(string pmVar, AST thenDoThis) { 414 AST ppBind(string pmVar, AST thenDoThis) { 415 auto pos = currentPosition(); 415 auto pos = currentPosition(); 416 return new LetExpression(pos, name, [], access(pmVar,pat | 416 return new Let(pos, name, [], access(pmVar,path), thenDo 417 } 417 } 418 } 418 } 419 class ConstantPattern : SinglePattern 419 class ConstantPattern : SinglePattern 420 { 420 { 421 AST e; 421 AST e; 422 mixin SimpleClass; 422 mixin SimpleClass; 423 AST ppTest(string pmVar) { 423 AST ppTest(string pmVar) { 424 auto pos = currentPosition(); 424 auto pos = currentPosition(); 425 return opAndAnd( super.ppTest(pmVar), 425 return opAndAnd( super.ppTest(pmVar), 426 new FuncallExpression(pos, new VarExpression(pos | 426 new App(pos, new Var(pos,"=="), access(pmVar,pat 427 ); 427 ); 428 } 428 } 429 } 429 } 430 430 431 SinglePattern[] parsePattern(string[] path = null) 431 SinglePattern[] parsePattern(string[] path = null) 432 { 432 { 433 SinglePattern[] result; 433 SinglePattern[] result; ................................................................................................................................................................................ 441 } while( tryEat(",") ); 441 } while( tryEat(",") ); 442 eat("}", "at the end of table pattern"); 442 eat("}", "at the end of table pattern"); 443 } 443 } 444 } 444 } 445 else 445 else 446 { 446 { 447 AST e = E(0); 447 AST e = E(0); 448 if(auto ev = cast(VarExpression)e) | 448 if(auto ev = cast(Var)e) 449 if(ev.name == "_") 449 if(ev.name == "_") 450 result ~= new WildPattern(path); 450 result ~= new WildPattern(path); 451 else 451 else 452 result ~= new VarPattern(path, ev.name); 452 result ~= new VarPattern(path, ev.name); 453 else 453 else 454 result ~= new ConstantPattern(path, e); 454 result ~= new ConstantPattern(path, e); 455 } 455 } ................................................................................................................................................................................ 460 { 460 { 461 auto pos = currentPosition(); 461 auto pos = currentPosition(); 462 AST cond = null; 462 AST cond = null; 463 foreach(p; pats) { 463 foreach(p; pats) { 464 AST c2 = p.ppTest(pmVar); 464 AST c2 = p.ppTest(pmVar); 465 if( c2 !is null ) 465 if( c2 !is null ) 466 cond = cond is null ? c2 466 cond = cond is null ? c2 467 : new FuncallExpression(pos, new VarExpressi | 467 : new App(pos, new Var(pos,"&&"), cond, c2); 468 } 468 } 469 return cond is null ? new IntLiteral(currentPosition(), 1) : con | 469 return cond is null ? new Int(currentPosition(), 1) : cond; 470 } 470 } 471 471 472 AST ppBind(string pmVar, SinglePattern[] pats, AST thenDoThis) 472 AST ppBind(string pmVar, SinglePattern[] pats, AST thenDoThis) 473 { 473 { 474 foreach(p; pats) 474 foreach(p; pats) 475 thenDoThis = p.ppBind(pmVar, thenDoThis); 475 thenDoThis = p.ppBind(pmVar, thenDoThis); 476 return thenDoThis; 476 return thenDoThis; 477 } 477 } 478 478 479 AST parseId() 479 AST parseId() 480 { 480 { 481 scope(exit) lex.popFront; 481 scope(exit) lex.popFront; 482 return new StrLiteral(currentPosition(), lex.front.str); | 482 return new Str(currentPosition(), lex.front.str); 483 } 483 } 484 484 485 AST parseLambdaAfterOpenParen(immutable LexPosition pos) 485 AST parseLambdaAfterOpenParen(immutable LexPosition pos) 486 { 486 { 487 Parameter[] params; 487 Parameter[] params; 488 while( !tryEat(")") ) 488 while( !tryEat(")") ) 489 { 489 { ................................................................................................................................................................................ 492 eat(")", "after function parameters"); 492 eat(")", "after function parameters"); 493 break; 493 break; 494 } 494 } 495 } 495 } 496 eat("{", "after function parameters"); 496 eat("{", "after function parameters"); 497 auto funbody = Body(); 497 auto funbody = Body(); 498 eat("}", "after function body"); 498 eat("}", "after function body"); 499 return new FunLiteral(pos, params, funbody); | 499 return new Fun(pos, params, funbody); 500 } 500 } 501 501 502 Parameter parseParam() 502 Parameter parseParam() 503 { 503 { 504 string var; 504 string var; 505 string[] lay; 505 string[] lay; 506 while( !closingBracket() && !lex.empty && lex.front.str!="," ) 506 while( !closingBracket() && !lex.empty && lex.front.str!="," ) ................................................................................................................................................................................ 554 throw genex!ParseException(currentPosition(), "identifie 554 throw genex!ParseException(currentPosition(), "identifie 555 scope(exit) lex.popFront; 555 scope(exit) lex.popFront; 556 return lex.front.str; 556 return lex.front.str; 557 } 557 } 558 558 559 AST doNothingExpression() 559 AST doNothingExpression() 560 { 560 { 561 return new StrLiteral(currentPosition(), "(empty function body)" | 561 return new Str(currentPosition(), "(empty function body)"); 562 } 562 } 563 563 564 immutable(LexPosition) currentPosition() 564 immutable(LexPosition) currentPosition() 565 { 565 { 566 return lex.empty ? null : lex.front.pos; 566 return lex.empty ? null : lex.front.pos; 567 } 567 } 568 } 568 }

Modified polemy/value.d from [0386a7dd31807f87] to [19366410c0eeb209].

43 43 44 44 45 /// 45 /// 46 abstract class FunValue : Value 46 abstract class FunValue : Value 47 { 47 { 48 const(Parameter[]) params(); 48 const(Parameter[]) params(); 49 Table definitionContext(); 49 Table definitionContext(); 50 Value invoke(in LexPosition pos, Layer lay, Table ctx); | 50 Value invoke(LexPosition pos, Layer lay, Table ctx); 51 } < 52 < 53 import polemy.eval; // circular... < 54 version = MacroCache; < 55 //version = AutoMemoization; < 56 //version = AutoRerun; < 57 < 58 /// < 59 class UserDefinedFunValue : FunValue < 60 { < 61 FunLiteral ast; < 62 Table defCtx; < 63 < 64 this(FunLiteral ast, Table defCtx) { this.ast=ast; this.defCtx=defCtx; } < 65 override string toString() const { return sprintf!"(function:%x:%x)"(cas < 66 override bool opEquals(Object rhs_) const /// member-by-member equality < 67 { < 68 if( auto rhs = cast(typeof(this))rhs_ ) < 69 return this.ast==rhs.ast && this.defCtx==rhs.defCtx; < 70 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), < 71 } < 72 override hash_t toHash() const /// member-by-member hash < 73 { < 74 return typeid(this.ast).getHash(&this.ast) + typeid(this.defCtx) < 75 } < 76 override int opCmp(Object rhs_) /// member-by-member compare < 77 { < 78 if( auto rhs = cast(typeof(this))rhs_ ) < 79 { < 80 if(auto i = this.ast.opCmp(rhs.ast)) < 81 return i; < 82 return this.defCtx.opCmp(rhs.defCtx); < 83 } < 84 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), < 85 } < 86 < 87 private AST preprocessed_funbody; < 88 private Value[Value[]][Layer] memo; < 89 < 90 override const(Parameter[]) params() { return ast.params; } < 91 override Table definitionContext() { return defCtx; } < 92 override Value invoke(in LexPosition pos, Layer lay, Table ctx) < 93 { < 94 // TODO: only auto raised ones need memo? no? < 95 // how can we integrate re-run ?? < 96 version(AutoMemoization) < 97 { < 98 Value[] memokey; < 99 if( lay != ValueLayer && lay != MacroLayer ) < 100 { < 101 foreach(i,p; ast.params) < 102 memokey ~= ctx.get(p.name, lay); // lay? < 103 if( auto memolay = lay in memo ) < 104 if( auto pv = memokey in *memolay ) < 105 return *pv; < 106 memo[lay][memokey] = lift(ast.pos,new UndValue,l < 107 } < 108 } < 109 < 110 // @macro run!!! < 111 if( lay == MacroLayer ) < 112 return macroEval(ast.funbody, ctx, false); < 113 < 114 version(MacroCache) { < 115 if( preprocessed_funbody is null ) { < 116 // .prototype!, forced macro cannot access param < 117 ctx.kill = true; scope(exit)ctx.kill=false; < 118 preprocessed_funbody = tableToAST(ValueLayer,mac < 119 } < 120 } else { < 121 if( preprocessed_funbody is null ) { < 122 // .prototype!, forced macro cannot access param < 123 ctx.kill = true; scope(exit)ctx.kill=false; < 124 preprocessed_funbody = tableToAST(ValueLayer,mac < 125 } < 126 } < 127 < 128 auto v = eval(preprocessed_funbody, ctx, true, lay); < 129 version(AutoMemoization) < 130 { < 131 if( lay != ValueLayer && lay != MacroLayer ) < 132 { < 133 memo[lay][memokey] = v; < 134 version(AutoReRun) < 135 memo[lay][memokey] = eval(preprocessed_funbody, < 136 } < 137 } < 138 return v; < 139 } < 140 } < 141 < 142 /// < 143 abstract class NativeFunValue : FunValue < 144 { < 145 Parameter[] params_data; < 146 override const(Parameter[]) params() { return params_data; } < 147 override Table definitionContext() { return new Table; } // todo: cache < 148 } < 149 < 150 /// Named Constructor for FunValue < 151 < 152 FunValue native(R,T...)(R delegate (T) dg) < 153 { < 154 return new class NativeFunValue { < 155 this() < 156 { < 157 foreach(i, Ti; T) < 158 params_data ~= new Parameter(text(i), []); < 159 } < 160 override Value invoke(in LexPosition pos, Layer lay, Table ctx) < 161 { < 162 if( lay != ValueLayer ) < 163 throw genex!RuntimeException(pos, "only "~ValueL < 164 T typed_args; < 165 foreach(i, Ti; T) { < 166 typed_args[i] = cast(Ti) ctx.get(text(i), ValueL < 167 if( typed_args[i] is null ) < 168 throw genex!RuntimeException(pos, sprint < 169 } < 170 try { < 171 return dg(typed_args); < 172 } catch( RuntimeException e ) { < 173 throw e.pos is null ? new RuntimeException(pos, < 174 } < 175 } < 176 }; < 177 } 51 } 178 52 179 /// Context (variable environment) 53 /// Context (variable environment) 180 /// Simlar to prototype chain of ECMAScript etc. 54 /// Simlar to prototype chain of ECMAScript etc. 181 /// But extended with the notion of "Layer" 55 /// But extended with the notion of "Layer" 182 56 183 class Table : Value 57 class Table : Value ................................................................................................................................................................................ 184 { 58 { 185 enum Kind {PropagateSet, NotPropagateSet}; 59 enum Kind {PropagateSet, NotPropagateSet}; 186 bool kill = false; // to refactor 60 bool kill = false; // to refactor 187 61 188 this( Table proto=null, Kind k = Kind.PropagateSet ) 62 this( Table proto=null, Kind k = Kind.PropagateSet ) 189 { this.prototype = proto; this.kind = k; } 63 { this.prototype = proto; this.kind = k; } 190 64 191 void set(string i, Layer lay, Value v, in LexPosition pos=null) | 65 void set(string i, Layer lay, Value v, LexPosition pos=null) 192 { 66 { 193 if( setIfExist(i, lay, v) ) 67 if( setIfExist(i, lay, v) ) 194 return; 68 return; 195 data[i][lay] = v; 69 data[i][lay] = v; 196 } 70 } 197 71 198 bool has(string i, Layer lay, in LexPosition pos=null) | 72 bool has(string i, Layer lay) const 199 { 73 { 200 if( i in data ) { 74 if( i in data ) { 201 if( lay !in data[i] ) 75 if( lay !in data[i] ) 202 return false; 76 return false; 203 if(kill) 77 if(kill) 204 return false; 78 return false; 205 return true; 79 return true; 206 } 80 } 207 if( prototype is null ) 81 if( prototype is null ) 208 return false; 82 return false; 209 return prototype.has(i, lay, pos); | 83 return prototype.has(i, lay); 210 } 84 } 211 85 212 Value get(string i, Layer lay, in LexPosition pos=null) | 86 Value get(string i, Layer lay, LexPosition pos=null) 213 { 87 { 214 if( i in data ) { 88 if( i in data ) { 215 // [TODO] consider forwarding to proto also in this case 89 // [TODO] consider forwarding to proto also in this case 216 if( lay !in data[i] ) 90 if( lay !in data[i] ) 217 throw genex!RuntimeException(pos, sprintf!"'%s' 91 throw genex!RuntimeException(pos, sprintf!"'%s' 218 if(kill) 92 if(kill) 219 throw genex!RuntimeException(pos, sprintf!"'%s' 93 throw genex!RuntimeException(pos, sprintf!"'%s' ................................................................................................................................................................................ 244 string result; 118 string result; 245 bool first = true; 119 bool first = true; 246 foreach(k, l2d; data) 120 foreach(k, l2d; data) 247 foreach(l,d; l2d) 121 foreach(l,d; l2d) 248 { 122 { 249 if(first) first=false; else result~=", "; 123 if(first) first=false; else result~=", "; 250 result ~= k; 124 result ~= k; > 125 if( l.empty ) > 126 result ~= "(emptylayer)"; > 127 else if( l != ValueLayer ) 251 result ~= l; | 128 result ~= l; 252 result ~= ":"; 129 result ~= ":"; 253 result ~= text(cast(Value)d); 130 result ~= text(cast(Value)d); 254 } 131 } 255 if( prototype !is null ) 132 if( prototype !is null ) 256 { 133 { 257 result ~= " / "; 134 result ~= " / "; 258 result ~= prototype.toStringWithoutParen(); 135 result ~= prototype.toStringWithoutParen(); ................................................................................................................................................................................ 371 if( nodeType is null ) 248 if( nodeType is null ) 372 throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST 249 throw genex!RuntimeException(cast(LexPosition)null, "Invalid AST 373 auto pos = extractPos(t); 250 auto pos = extractPos(t); 374 switch(nodeType.data) 251 switch(nodeType.data) 375 { 252 { 376 case "int": 253 case "int": 377 if(auto v = t.access!IntValue(theLayer, "data")) 254 if(auto v = t.access!IntValue(theLayer, "data")) 378 return new IntLiteral(pos, v.data); | 255 return new Int(pos, v.data); 379 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 256 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 380 case "str": 257 case "str": 381 if(auto v = t.access!StrValue(theLayer, "data")) 258 if(auto v = t.access!StrValue(theLayer, "data")) 382 return new StrLiteral(pos, v.data); | 259 return new Str(pos, v.data); 383 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 260 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 384 case "var": 261 case "var": 385 if(auto v = t.access!StrValue(theLayer, "name")) 262 if(auto v = t.access!StrValue(theLayer, "name")) 386 return new VarExpression(pos, v.data); | 263 return new Var(pos, v.data); 387 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 264 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 388 case "lay": 265 case "lay": 389 if(auto v = t.access!StrValue(theLayer, "layer")) 266 if(auto v = t.access!StrValue(theLayer, "layer")) 390 if(auto e = t.access!Table(theLayer, "expr")) 267 if(auto e = t.access!Table(theLayer, "expr")) 391 return new LayExpression(pos, v.data, tableToAST | 268 return new Lay(pos, v.data, tableToAST(theLayer, 392 else 269 else 393 throw genex!RuntimeException(cast(LexPosition)nu 270 throw genex!RuntimeException(cast(LexPosition)nu 394 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 271 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 395 case "let": 272 case "let": 396 if(auto n = t.access!StrValue(theLayer, "name")) 273 if(auto n = t.access!StrValue(theLayer, "name")) 397 if(auto e = t.access!Table(theLayer, "init")) 274 if(auto e = t.access!Table(theLayer, "init")) 398 if(auto b = t.access!Table(theLayer, "expr")) 275 if(auto b = t.access!Table(theLayer, "expr")) ................................................................................................................................................................................ 399 { 276 { 400 string nn = n.data; 277 string nn = n.data; 401 auto ee = tableToAST(theLayer, e); 278 auto ee = tableToAST(theLayer, e); 402 auto bb = tableToAST(theLayer, b); 279 auto bb = tableToAST(theLayer, b); 403 Layer lay=""; 280 Layer lay=""; 404 if(auto l = t.access!StrValue(theLayer, "layer")) 281 if(auto l = t.access!StrValue(theLayer, "layer")) 405 lay = l.data; 282 lay = l.data; 406 return new LetExpression(pos, nn, lay, ee, bb); | 283 return new Let(pos, nn, lay, ee, bb); 407 } 284 } 408 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 285 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 409 case "app": 286 case "app": 410 if(auto f = t.access!Table(theLayer, "fun")) 287 if(auto f = t.access!Table(theLayer, "fun")) 411 if(auto a = t.access!Table(theLayer, "args")) 288 if(auto a = t.access!Table(theLayer, "args")) 412 return new FuncallExpression(pos, tableToAST(theLayer,f) | 289 return new App(pos, tableToAST(theLayer,f), tableToASTLi 413 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 290 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 414 case "fun": 291 case "fun": 415 if(auto p = t.access!Table(theLayer, "params")) 292 if(auto p = t.access!Table(theLayer, "params")) 416 if(auto b = t.access!Table(theLayer, "funbody")) 293 if(auto b = t.access!Table(theLayer, "funbody")) 417 { 294 { 418 Parameter[] ps; 295 Parameter[] ps; 419 foreach(v; tableAsConsList(theLayer, p)) 296 foreach(v; tableAsConsList(theLayer, p)) ................................................................................................................................................................................ 436 Layer[] emp; 313 Layer[] emp; 437 ps ~= new Parameter(ss.data, emp); 314 ps ~= new Parameter(ss.data, emp); 438 continue; 315 continue; 439 } 316 } 440 throw genex!RuntimeException(cast(LexPosition)nu 317 throw genex!RuntimeException(cast(LexPosition)nu 441 } 318 } 442 auto bb = tableToAST(theLayer, b); 319 auto bb = tableToAST(theLayer, b); 443 return new FunLiteral(pos,ps,bb); | 320 return new Fun(pos,ps,bb); 444 } 321 } 445 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 322 throw genex!RuntimeException(cast(LexPosition)null, `Invalid AST 446 default: 323 default: 447 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Inv 324 throw genex!RuntimeException(cast(LexPosition)null, sprintf!`Inv 448 } 325 } 449 } 326 } > 327 > 328 Table makeCons(Value a, Value d) > 329 { > 330 Table t = new Table; > 331 t.set("car", ValueLayer, a); > 332 t.set("cdr", ValueLayer, d); > 333 return t; > 334 } > 335 > 336 Table fromPos(LexPosition pos) > 337 { > 338 Table t = new Table; > 339 if( pos !is null ) { > 340 t.set("filename", ValueLayer, new StrValue(pos.filename)); > 341 t.set("lineno", ValueLayer, new IntValue(BigInt(pos.lineno))); > 342 t.set("column", ValueLayer, new IntValue(BigInt(pos.column))); > 343 } else { > 344 t.set("filename", ValueLayer, new StrValue("nullpos")); > 345 t.set("lineno", ValueLayer, new IntValue(BigInt(0))); > 346 t.set("column", ValueLayer, new IntValue(BigInt(0))); > 347 } > 348 return t; > 349 }

Modified sample/plusminus.pmy from [2f68238d12815ac3] to [d3a50b6eb8c63c2d].

1 @@s(x){x}; 1 @@s(x){x}; 2 @s "+" = fun(x, y) {@v( | 2 @s "+" = fun(x, y) {@value( 3 @s(x) - @s(y) 3 @s(x) - @s(y) 4 )}; 4 )}; 5 5 6 print( 1 + 2 ); 6 print( 1 + 2 ); 7 print( @s(1 + 2) ); 7 print( @s(1 + 2) );

Modified tricks/tricks.d from [0eae6cc37f045c97] to [004818c087feff6a].

388 ), 6); 388 ), 6); 389 assert_eq( d2.match( 389 assert_eq( d2.match( 390 when!(D1, (x, y){return x + cast(int)y;}), 390 when!(D1, (x, y){return x + cast(int)y;}), 391 otherwise!({return 999;}), 391 otherwise!({return 999;}), 392 when!(D2, (x){return x.length;}) 392 when!(D2, (x){return x.length;}) 393 ), 999); 393 ), 999); 394 } 394 } > 395 > 396 /// Will be used for dynamic overload resolution pattern > 397 > 398 template firstParam(T) > 399 { > 400 alias ParameterTypeTuple!(T)[0] firstParam; > 401 }