Overview
SHA1 Hash: | 2134cd44cc68f372bd694e0ebc28adb2c95052e0 |
---|---|
Date: | 2010-11-23 22:55:15 |
User: | kinaba |
Comment: | further clean-up for polemy2d |
Timelines: | family | ancestors | descendants | both | trunk |
Downloads: | Tarball | ZIP archive |
Other Links: | files | file ages | manifest |
Tags And Properties
- branch=trunk inherited from [f65680e1d2]
- sym-trunk inherited from [f65680e1d2]
Changes
Modified polemy/ast.d from [f7a981003352ec6b] to [2e3f1e0044f7841f].
89 89 { 90 90 Parameter[] params; 91 91 AST funbody; 92 92 93 93 mixin SimpleClass; 94 94 } 95 95 96 +/// List of AST Types 97 + 98 +alias TypeTuple!(Int,Str,Var,Lay,Let,App,Fun) ListOfASTTypes; 99 + 96 100 /// Handy Generator for AST nodes. To use this, mixin EasyAst; 97 101 98 102 /*mixin*/ 99 103 template EasyAST() 100 104 { 101 105 /// 102 106 template genEast(T)
Modified polemy/eval.d from [ca0ab118700475a8] to [a7c677ad83621b47].
98 98 } 99 99 100 100 Value eval( App e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 101 101 { 102 102 Value f = eval( e.fun, lay, ctx ); 103 103 if( isMacroishLayer(lay) ) 104 104 if( auto ff = cast(FunValue)f ) 105 - return invokeFunction(ff, e.args, MacroLayer, ctx, e.pos); 105 + return invokeFunction(ff, e.args, MacroLayer, ctx, e.pos, getNameIfPossible(e.fun)); 106 106 else 107 107 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 108 - return invokeFunction(f, e.args, lay, ctx, e.pos); 108 + return invokeFunction(f, e.args, lay, ctx, e.pos, getNameIfPossible(e.fun)); 109 109 } 110 110 111 111 Value eval( Fun e, Layer lay, Table ctx, bool overwriteCtx=CascadeCtx ) 112 112 { 113 113 if( isMacroishLayer(lay) ) 114 114 return ast2table(e, (AST e){return eval(e,lay,ctx);}); 115 115 else ................................................................................ 137 137 string theLayer = e.layer.empty ? lay : e.layer; // neutral layer 138 138 ctx.set(e.name, theLayer, ri); 139 139 return eval(e.expr, lay, ctx, OverwriteCtx); 140 140 } 141 141 } 142 142 143 143 private: 144 - Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosition pos=null) 144 + string getNameIfPossible(AST e) 145 + { 146 + if(auto v = cast(Var)e) 147 + return v.name; 148 + return ""; 149 + } 150 + 151 + Value invokeFunction(Value _f, AST[] args, Layer lay, Table ctx, LexPosition pos, string callstackmsg) 145 152 { 146 153 if(auto f = cast(FunValue)_f) 147 154 { 148 155 Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 149 156 foreach(i,p; f.params()) 150 157 if( p.layers.empty ) 151 158 newCtx.set(p.name, (lay==RawMacroLayer ? MacroLayer : lay), eval(args[i], lay, ctx)); 152 159 else 153 160 foreach(argLay; p.layers) 154 161 newCtx.set(p.name, argLay, eval(args[i], argLay, ctx)); 162 + scope _ = new PushCallStack(pos, callstackmsg); 155 163 return f.invoke(lay==RawMacroLayer ? MacroLayer : lay, newCtx, pos); 156 164 } 157 165 throw genex!RuntimeException(pos, text("tried to call non-function: ",_f)); 158 166 } 159 167 160 - Value lift(Value v, Layer lay, Table ctx, LexPosition pos=null) 168 + Value lift(Value v, Layer lay, Table ctx, LexPosition pos) 161 169 { 162 - assert( !isMacroishLayer(lay), "lift to the @macro layer should not happen" ); 170 + assert( !isMacroishLayer(lay), "lift to the @macro layer should never happen" ); 163 171 164 172 // functions are automatically lifterd 165 173 if( cast(FunValue) v ) 166 174 return v; 167 175 168 - // similar to invoke Function, but with only one argument bound to ValueLayer 169 - if(auto f = cast(FunValue)ctx.get(lay, SystemLayer, pos)) 176 + if( !ctx.has(lay, SystemLayer) ) 177 + throw genex!RuntimeException(pos, "lift function for "~lay~" is not registered" ); 178 + 179 + // similar to invokeFunction, but with only one argument bound to ValueLayer 180 + auto _f = ctx.get(lay, SystemLayer, pos); 181 + if(auto f = cast(FunValue)_f) 170 182 { 171 183 Table newCtx = new Table(f.definitionContext(), Table.Kind.NotPropagateSet); 172 184 auto ps = f.params(); 173 185 if( ps.length != 1 ) 174 - throw genex!RuntimeException(pos, "lift function must take exactly one argument at "~ValueLayer~" layer"); 186 + throw genex!RuntimeException(pos, 187 + text("lift function for", lay, " must take exactly one argument of ", ValueLayer)); 175 188 if( ps[0].layers.length==0 || ps[0].layers.length==1 && ps[0].layers[0]==ValueLayer ) 176 189 { 177 190 newCtx.set(ps[0].name, ValueLayer, v); 191 + scope _ = new PushCallStack(pos, lay); 178 192 return f.invoke(ValueLayer, newCtx, pos); 179 193 } 180 194 else 181 - throw genex!RuntimeException(pos, "lift function must take exactly one argument at "~ValueLayer~" layer"); 195 + throw genex!RuntimeException(pos, 196 + text("lift function for", lay, " must take exactly one argument of ", ValueLayer)); 182 197 } 183 - throw genex!RuntimeException(pos, "tried to call non-function"); 198 + throw genex!RuntimeException(pos, 199 + text("non-function ", _f, " is registered as the lift function for ", lay)); 184 200 } 185 201 186 202 Value createNewFunction(Fun e, Table ctx) 187 203 { 188 204 class UserDefinedFunValue : FunValue 189 205 { 190 206 Fun ast; ................................................................................ 215 231 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 216 232 } 217 233 218 234 override Value invoke(Layer lay, Table ctx, LexPosition pos) 219 235 { 220 236 if( lay == MacroLayer ) 221 237 return eval(ast.funbody, lay, ctx); 222 - if( afterMacroAST is null ) 223 - afterMacroAST = tableToAST(ValueLayer, eval(e.funbody, RawMacroLayer, ctx)); 224 - return eval(afterMacroAST, lay, ctx); 238 + try { 239 + if( afterMacroAST is null ) 240 + afterMacroAST = polemy2d!(AST)(eval(e.funbody, RawMacroLayer, ctx), pos); 241 + return eval(afterMacroAST, lay, ctx); 242 + } catch( RuntimeException e ) { 243 + throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line, e.next) : e; 244 + } 225 245 } 226 246 227 247 AST afterMacroAST; 228 248 } 229 249 return new UserDefinedFunValue(e,ctx); 230 250 } 231 251
Modified polemy/failure.d from [701f5b1b899607f2] to [1bc945d1d318d417].
17 17 { 18 18 immutable string filename; /// name of the source file 19 19 immutable int lineno; /// 1-origin 20 20 immutable int column; /// 1-origin 21 21 22 22 mixin SimpleClass; 23 23 override string toString() const 24 - { 25 - return sprintf!("%s:%d:%d")(filename, lineno, column); 26 - } 27 - 24 + { return sprintf!("%s:%d:%d")(filename, lineno, column); } 28 25 static LexPosition dummy; 29 26 static this(){ dummy = new LexPosition("<unnamed>",0,0); } 30 27 } 31 28 32 29 unittest 33 30 { 34 31 auto p = new LexPosition("hello.cpp", 123, 45); ................................................................................ 50 47 51 48 /*mixin*/ 52 49 template ExceptionWithPosition() 53 50 { 54 51 LexPosition pos; 55 52 this( LexPosition pos, string msg, string file=null, size_t line=0, Throwable next=null ) 56 53 { 57 - if(pos is null) 58 - super(sprintf!("[??] %s")(msg), file, line, next); 59 - else 60 - super(sprintf!("[%s] %s")(pos, msg), file, line, next); 54 + string fullmsg = pos is null ? sprintf!("\n[??] %s")(msg) 55 + : sprintf!("\n[%s] %s")(pos, msg); 56 + for(int i=0; i<callstack_pos.length || i<callstack_msg.length; ++i) 57 + { 58 + LexPosition p = (i<callstack_pos.length ? callstack_pos[i] : null); 59 + string m = (i<callstack_msg.length ? callstack_msg[i] : null); 60 + fullmsg ~= p is null ? sprintf!("\n[??] %s")(m) 61 + : sprintf!("\n[%s] %s")(p, m); 62 + } 63 + super(fullmsg, file, line, next); 61 64 this.pos = pos; 65 + } 66 + this( string msg, string file=null, size_t line=0, Throwable next=null ) 67 + { 68 + this(null, msg, file, line, next); 62 69 } 63 70 } 64 71 65 -class UnexpectedEOF : Exception { mixin ExceptionWithPosition; } /// EOF during lexing/parsing 66 -class LexException : Exception { mixin ExceptionWithPosition; } /// Lexer errors 67 -class ParseException : Exception { mixin ExceptionWithPosition; } /// Parser errors 72 +class UnexpectedEOF : Exception { mixin ExceptionWithPosition; } /// EOF during lexing/parsing 73 +class LexException : Exception { mixin ExceptionWithPosition; } /// Lexer errors 74 +class ParseException : Exception { mixin ExceptionWithPosition; } /// Parser errors 68 75 class RuntimeException : Exception { mixin ExceptionWithPosition; } /// Evaluator errors 76 + 77 +/// Per-thread call stack management. 78 +/// This scoped class's ctor&dtor maintain the callstack. 79 +/// TODO: make it "per-evaluator" !!!!!!!!!!! 80 + 81 +scope class PushCallStack 82 +{ 83 + this(LexPosition pos, string msg) { callstackEnterFunction(pos,msg); } 84 + ~this() { callstackLeaveFunction(); } 85 +} 86 + 87 +LexPosition[] callstack_pos; 88 +string[] callstack_msg; 89 + 90 +private void callstackEnterFunction(LexPosition pos, string msg) 91 +{ 92 + callstack_pos ~= pos; 93 + callstack_msg ~= msg; 94 +} 95 + 96 +private void callstackLeaveFunction() 97 +{ 98 + callstack_pos.length -= 1; 99 + callstack_msg.length -= 1; 100 +}
Modified polemy/parse.d from [b6858e7b65012cb1] to [50e0836a1ece20de].
152 152 // [TODO] make this customizable from program 153 153 private static string[][] operator_perferences = [ 154 154 ["||"], 155 155 ["&&"], 156 156 ["!="], 157 157 ["=="], 158 158 ["<","<=",">",">="], 159 -// ["|"], 160 -// ["^"], 161 -// ["&"], 162 -// ["<<", ">>", "<<<", ">>>"], 159 + ["|"], 160 + ["^"], 161 + ["&"], 162 + ["<<", ">>", "<<<", ">>>"], 163 163 ["+","-"], 164 164 ["~"], 165 165 ["*","/","%"], 166 -// ["^^","**"], 166 + ["^^","**"], 167 167 [".",".?"] 168 168 ]; 169 169 170 170 AST E(size_t level) 171 171 { 172 172 /// Expression ::= (Binary left-associative operators over) Funcall 173 173
Modified polemy/runtime.d from [6af5a0863b67aa85] to [641d49d7fd647519].
1 + 1 2 /** 2 3 * Authors: k.inaba 3 4 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 5 * 5 6 * Runtime library for Polemy programming language. 6 7 */ 7 8 module polemy.runtime; 8 9 import polemy._common; 9 10 import polemy.layer; 11 +import polemy.failure; 10 12 import polemy.value; 11 13 import polemy.eval; 12 14 import std.stdio; 13 15 14 16 /// enroll the native implementations of primitive functions 15 17 16 18 void enrollRuntimeLibrary( Evaluator e ) 17 19 { 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, (Value lhs, Value rhs){return new StrValue(lhs.toString ~ rhs.toString);} ); 24 - e.addPrimitive("||", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 || rhs.data!=0);} ); 25 - e.addPrimitive("&&", ValueLayer, (IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 && rhs.data!=0);} ); 20 + // arithmetic operations 21 + e.addPrimitive("+", ValueLayer, 22 + (IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} ); 23 + e.addPrimitive("-", ValueLayer, 24 + (IntValue lhs, IntValue rhs){return new IntValue(lhs.data - rhs.data);} ); 25 + e.addPrimitive("*", ValueLayer, 26 + (IntValue lhs, IntValue rhs){return new IntValue(lhs.data * rhs.data);} ); 27 + e.addPrimitive("/", ValueLayer, 28 + (IntValue lhs, IntValue rhs){ 29 + if( rhs.data == 0 ) 30 + throw genex!RuntimeException("division by 0"); 31 + return new IntValue(lhs.data / rhs.data); 32 + }); 33 + e.addPrimitive("%", ValueLayer, 34 + (IntValue lhs, IntValue rhs){return new IntValue(lhs.data % rhs.data);} ); 35 + e.addPrimitive("||", ValueLayer, 36 + (IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 || rhs.data!=0);} ); 37 + e.addPrimitive("&&", ValueLayer, 38 + (IntValue lhs, IntValue rhs){return new IntValue(lhs.data!=0 && rhs.data!=0);} ); 39 + // string operation(s) 40 + e.addPrimitive("~", ValueLayer, 41 + (Value lhs, Value rhs){return new StrValue(lhs.toString ~ rhs.toString);} ); 42 + // comparison 26 43 e.addPrimitive("<", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs < rhs);} ); 27 44 e.addPrimitive(">", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs > rhs);} ); 28 45 e.addPrimitive("<=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs <= rhs);} ); 29 46 e.addPrimitive(">=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs >= rhs);} ); 30 47 e.addPrimitive("==", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs == rhs);} ); 31 48 e.addPrimitive("!=", ValueLayer, (Value lhs, Value rhs){return new IntValue(lhs != rhs);} ); 32 - e.addPrimitive("print", ValueLayer, (Value a){ 33 - writeln(a); 34 - return new IntValue(0); 35 - }); 49 + // control flow 36 50 e.addPrimitive("if", ValueLayer, (IntValue x, FunValue ft, FunValue fe){ 37 51 auto toRun = (x.data==0 ? fe : ft); 38 - // [TODO] fill positional information 39 52 return toRun.invoke(ValueLayer, toRun.definitionContext(), null); 40 53 }); 41 - e.addPrimitive("_isint", ValueLayer, (Value v){return new IntValue(cast(IntValue)v !is null);} ); 42 - e.addPrimitive("_isstr", ValueLayer, (Value v){return new IntValue(cast(StrValue)v !is null);} ); 43 - e.addPrimitive("_isfun", ValueLayer, (Value v){return new IntValue(cast(FunValue)v !is null);} ); 44 - e.addPrimitive("_isundefined", ValueLayer, (Value v){return new IntValue(cast(UndefinedValue)v !is null);} ); 45 - e.addPrimitive("_istable", ValueLayer, (Value v){return new IntValue(cast(Table)v !is null);} ); 54 + // type test 55 + e.addPrimitive("_isint", ValueLayer, 56 + (Value v){return new IntValue(cast(IntValue)v !is null);} ); 57 + e.addPrimitive("_isstr", ValueLayer, 58 + (Value v){return new IntValue(cast(StrValue)v !is null);} ); 59 + e.addPrimitive("_isfun", ValueLayer, 60 + (Value v){return new IntValue(cast(FunValue)v !is null);} ); 61 + e.addPrimitive("_isundefined", ValueLayer, 62 + (Value v){return new IntValue(cast(UndefinedValue)v !is null);} ); 63 + e.addPrimitive("_istable", ValueLayer, 64 + (Value v){return new IntValue(cast(Table)v !is null);} ); 65 + // table 46 66 e.addPrimitive(".", ValueLayer, (Table t, StrValue s){ 47 67 return (t.has(s.data, ValueLayer) ? t.get(s.data, ValueLayer) : new UndefinedValue); 48 68 }); 49 69 e.addPrimitive(".?", ValueLayer, (Table t, StrValue s){ 50 70 return new IntValue(t.has(s.data, ValueLayer)); 51 71 }); 52 72 e.addPrimitive(".=", ValueLayer, (Table t, StrValue s, Value v){ ................................................................................ 53 73 auto t2 = new Table(t, Table.Kind.NotPropagateSet); 54 74 t2.set(s.data, ValueLayer, v); 55 75 return t2; 56 76 }); 57 77 e.addPrimitive("{}", ValueLayer, (){ 58 78 return new Table; 59 79 }); 80 + // IO 81 + e.addPrimitive("print", ValueLayer, (Value a){ writeln(a); return new IntValue(0); }); 60 82 }
Modified polemy/value.d from [6d85ee04f34c61b7] to [43e26264d772abeb].
75 75 /// Context (variable environment) 76 76 /// Simlar to prototype chain of ECMAScript etc. 77 77 /// But extended with the notion of "Layer" 78 78 79 79 class Table : Value 80 80 { 81 81 enum Kind {PropagateSet, NotPropagateSet}; 82 - bool kill = false; // to refactor 83 82 84 83 this( Table proto=null, Kind k = Kind.PropagateSet ) 85 84 { this.prototype = proto; this.kind = k; } 86 85 87 - void set(string i, Layer lay, Value v, LexPosition pos=null) 86 + void set(string i, Layer lay, Value v) 88 87 { 89 88 if( setIfExist(i, lay, v) ) 90 89 return; 91 90 data[i][lay] = v; 92 91 } 93 92 94 93 bool has(string i, Layer lay) const 95 94 { 96 - if( i in data ) { 97 - if( lay !in data[i] ) 98 - return false; 99 - if(kill) 100 - return false; 101 - return true; 102 - } 95 + if( i in data ) 96 + return !!(lay in data[i]); 103 97 if( prototype is null ) 104 98 return false; 105 99 return prototype.has(i, lay); 106 100 } 107 101 108 102 Value get(string i, Layer lay, LexPosition pos=null) 109 103 { 110 104 if( i in data ) { 111 105 // [TODO] consider forwarding to proto also in this case 112 106 if( lay !in data[i] ) 113 - throw genex!RuntimeException(pos, sprintf!"'%s' is not set in layer %s"(i,lay)); 114 - if(kill) 115 - throw genex!RuntimeException(pos, sprintf!"'%s' is killed in macro"(i)); 107 + throw genex!RuntimeException(pos, sprintf!"'%s' is not set in %s layer"(i,lay)); 116 108 return data[i][lay]; 117 109 } 118 110 if( prototype is null ) 119 - throw new RuntimeException(pos, sprintf!"'%s' not found"(i)); 111 + throw genex!RuntimeException(pos, sprintf!"'%s' not found in %s layer"(i,lay)); 120 112 return prototype.get(i, lay, pos); 121 113 } 122 114 123 115 T access(T,S...)( Layer lay, string path, S rest ) 124 116 { 125 117 static if( rest.length == 0 ) 126 118 { ................................................................................ 155 147 { 156 148 result ~= " / "; 157 149 result ~= prototype.toStringWithoutParen(); 158 150 } 159 151 return result; 160 152 } 161 153 162 - string toString() const 154 + string toString() 163 155 { 156 + if( isList() ) 157 + return text(toList()); 164 158 return "{" ~ toStringWithoutParen() ~ "}"; 165 159 } 160 + 161 +public: 162 + /// Is this an empty table? 163 + bool empty() 164 + { 165 + return data.length==0 && (prototype is null || prototype.empty); 166 + } 167 + 168 + /// Can be seen as a cons-list? 169 + bool isList() 170 + { 171 + Table t = this; 172 + while(t.has("car", ValueLayer) && t.has("cdr", ValueLayer)) 173 + if(auto tt = cast(Table)t.get("cdr", ValueLayer)) 174 + t = tt; 175 + else 176 + return false; 177 + return t.empty; 178 + } 179 + 180 + /// Regard table as a cons-list and convert to an array 181 + Value[] toList() 182 + { 183 + Value[] result; 184 + Table t = this; 185 + while(t.has("car", ValueLayer) && t.has("cdr", ValueLayer)) 186 + { 187 + result ~= t.get("car", ValueLayer); 188 + if(auto tt = cast(Table)t.get("cdr", ValueLayer)) 189 + t = tt; 190 + else 191 + throw genex!RuntimeException("this table is not a cons-list"); 192 + } 193 + if( t.empty ) 194 + return result; 195 + throw genex!RuntimeException("this table is not a cons-list"); 196 + } 166 197 167 198 private: 168 199 Table prototype; 169 200 Kind kind; 170 201 Value[Layer][string] data; 171 202 172 203 bool setIfExist(string i, Layer lay, Value v) ................................................................................ 185 216 unittest 186 217 { 187 218 Table c0 = new Table; 188 219 Table c01 = new Table(c0, Table.Kind.NotPropagateSet); 189 220 Table c012 = new Table(c01, Table.Kind.PropagateSet); 190 221 Table c013 = new Table(c01, Table.Kind.PropagateSet); 191 222 192 - assert_nothrow( c012.set("x", ValueLayer, new IntValue(BigInt(12))) ); 223 + assert_nothrow( c012.set("x", ValueLayer, new IntValue(12)) ); 193 224 assert_throw!RuntimeException( c013.get("x", ValueLayer) ); 194 - assert_nothrow( c013.set("x", ValueLayer, new IntValue(BigInt(13))) ); 195 - assert_eq( c013.get("x", ValueLayer), new IntValue(BigInt(13)) ); 196 - assert_eq( c012.get("x", ValueLayer), new IntValue(BigInt(12)) ); 225 + assert_nothrow( c013.set("x", ValueLayer, new IntValue(13)) ); 226 + assert_eq( c013.get("x", ValueLayer), new IntValue(13) ); 227 + assert_eq( c012.get("x", ValueLayer), new IntValue(12) ); 197 228 assert_throw!RuntimeException( c01.get("x", ValueLayer) ); 198 229 199 - assert_nothrow( c01.set("y", ValueLayer, new IntValue(BigInt(1))) ); 200 - assert_eq( c013.get("y", ValueLayer), new IntValue(BigInt(1)) ); 201 - assert_eq( c012.get("y", ValueLayer), new IntValue(BigInt(1)) ); 202 - assert_eq( c01.get("y", ValueLayer), new IntValue(BigInt(1)) ); 230 + assert_nothrow( c01.set("y", ValueLayer, new IntValue(1)) ); 231 + assert_eq( c013.get("y", ValueLayer), new IntValue(1) ); 232 + assert_eq( c012.get("y", ValueLayer), new IntValue(1) ); 233 + assert_eq( c01.get("y", ValueLayer), new IntValue(1) ); 234 + 235 + assert_nothrow( c0.set("z", ValueLayer, new IntValue(0)) ); 236 + assert_eq( c013.get("z", ValueLayer), new IntValue(0) ); 237 + assert_eq( c012.get("z", ValueLayer), new IntValue(0) ); 238 + assert_eq( c01.get("z", ValueLayer), new IntValue(0) ); 239 + assert_eq( c0.get("z", ValueLayer), new IntValue(0) ); 203 240 204 - assert_nothrow( c0.set("z", ValueLayer, new IntValue(BigInt(0))) ); 205 - assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) ); 206 - assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(0)) ); 207 - assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) ); 208 - assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) ); 241 + assert_nothrow( c012.set("y", ValueLayer, new IntValue(444)) ); 242 + assert_eq( c013.get("y", ValueLayer), new IntValue(444) ); 243 + assert_eq( c012.get("y", ValueLayer), new IntValue(444) ); 244 + assert_eq( c01.get("y", ValueLayer), new IntValue(444) ); 209 245 210 - assert_nothrow( c012.set("y", ValueLayer, new IntValue(BigInt(444))) ); 211 - assert_eq( c013.get("y", ValueLayer), new IntValue(BigInt(444)) ); 212 - assert_eq( c012.get("y", ValueLayer), new IntValue(BigInt(444)) ); 213 - assert_eq( c01.get("y", ValueLayer), new IntValue(BigInt(444)) ); 214 - 215 - assert_nothrow( c012.set("z", ValueLayer, new IntValue(BigInt(555))) ); 216 - assert_eq( c013.get("z", ValueLayer), new IntValue(BigInt(0)) ); 217 - assert_eq( c012.get("z", ValueLayer), new IntValue(BigInt(555)) ); 218 - assert_eq( c01.get("z", ValueLayer), new IntValue(BigInt(0)) ); 219 - assert_eq( c0.get("z", ValueLayer), new IntValue(BigInt(0)) ); 246 + assert_nothrow( c012.set("z", ValueLayer, new IntValue(555)) ); 247 + assert_eq( c013.get("z", ValueLayer), new IntValue(0) ); 248 + assert_eq( c012.get("z", ValueLayer), new IntValue(555) ); 249 + assert_eq( c01.get("z", ValueLayer), new IntValue(0) ); 250 + assert_eq( c0.get("z", ValueLayer), new IntValue(0) ); 220 251 221 252 // [TODO] define the semantics and test @layers 222 253 }
Modified polemy/valueconv.d from [76bd90b6c3824480] to [2816a291e16d0986].
10 10 import polemy.ast; 11 11 import polemy.layer; 12 12 import polemy.value; 13 13 import std.string; 14 14 15 15 LexPosition extractPos( Table t ) 16 16 { 17 - Layer theLayer = ValueLayer; 18 - if(auto tt = t.access!Table(theLayer, "pos")) 17 + if(auto tt = t.access!Table(ValueLayer, "pos")) 19 18 { 20 - auto fn = tt.access!StrValue(theLayer, "filename"); 21 - auto ln = tt.access!IntValue(theLayer, "lineno"); 22 - auto cl = tt.access!IntValue(theLayer, "column"); 19 + auto fn = tt.access!StrValue(ValueLayer, "filename"); 20 + auto ln = tt.access!IntValue(ValueLayer, "lineno"); 21 + auto cl = tt.access!IntValue(ValueLayer, "column"); 23 22 if(fn !is null && ln !is null && cl !is null) 24 23 return new LexPosition(fn.data,cast(int)ln.data.toInt,cast(int)cl.data.toInt); 25 24 } 26 25 return null; 27 26 } 28 27 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 -} 28 +/// Experimental!! Convert Polemy value to D Value 42 29 43 -AST[] tableToASTList( Layer theLayer, Table t ) 30 +T polemy2d(T)(Value _v, LexPosition callpos=null) 44 31 { 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 -} 32 + static if(is(T==BigInt)) 33 + { 34 + if(auto v = cast(IntValue)_v) 35 + return v.data; 36 + } 37 + else 38 + static if(isIntegral!(T)) 39 + { 40 + if(auto v = cast(IntValue)_v) 41 + return cast(T) v.data.toLong(); 42 + } 43 + else 44 + static if(is(T==string)) 45 + { 46 + if(auto v = cast(StrValue)_v) 47 + return v.data; 48 + } 49 + else 50 + static if(is(T S : S[])) 51 + { 52 + if(auto t = cast(Table)_v) 53 + { 54 + S[] result; 55 + foreach(e; t.toList()) 56 + result ~= polemy2d!(S)(e, callpos); 57 + return result; 58 + } 59 + } 60 + else 61 + static if(is(T == AST)) 62 + { 63 + if(auto t = cast(Table)_v) 64 + { 65 + LexPosition pos = extractPos(t); 53 66 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)"); 67 + StrValue typ = cast(StrValue) t.access!StrValue(ValueLayer, "is"); 68 + if( typ is null ) 69 + throw genex!RuntimeException(text(`Invalid AST (no "is" field): `, _v)); 59 70 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) 71 + foreach(AT; ListOfASTTypes) 72 + if(typ.data == typeid(AT).name.split(".")[$-1].tolower()) 73 + { 74 + typeof(AT.tupleof) mems; 75 + foreach(i,m; mems) 76 + { 77 + string name = AT.tupleof[i].stringof.split(".")[$-1]; 78 + Value vm = t.access!Value(ValueLayer, name); 79 + if( vm is null ) 80 + throw genex!RuntimeException(callpos, 81 + text(`Invalid AST (no "`,name,`" field) for "`, typ, `" node: `, _v)); 82 + mems[i] = polemy2d!(typeof(m))(vm, callpos); 83 + } 84 + return new AT(pos,mems); 85 + } 86 + throw genex!RuntimeException(callpos, text(`Invalid AST (unknown "is" field): `, typ)); 87 + } 88 + throw genex!RuntimeException(callpos, text(`Invalid AST (not a table): `, _v)); 89 + } 90 + else 91 + static if(is(T == class)) 65 92 { 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")) 93 + if(auto t = cast(Table)_v) 89 94 { 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); 95 + typeof(T.tupleof) mems; 96 + foreach(i,m; mems) 97 + mems[i] = polemy2d!(typeof(m))(t.get(T.tupleof[i].stringof.split(".")[$-1], ValueLayer), callpos); 98 + return new T(mems); 97 99 } 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 100 } 101 + else 102 + static assert(false, "unknown type <"~T.stringof~"> during polemy2d decoding"); 103 + throw genex!RuntimeException(callpos, text("Cannot convert ",_v," to ",T.stringof)); 139 104 } 140 105 141 106 /// Cons of two pairs 142 107 143 108 Table makeCons(Value a, Value d) 144 109 { 145 110 Table t = new Table; 146 111 t.set("car", ValueLayer, a); 147 112 t.set("cdr", ValueLayer, d); 148 113 return t; 149 114 } 150 115 151 -/// Experimental!!! Convert D value (except AST) to Polemy Value 116 +/// Experimental!! Convert D value (except AST) to Polemy Value 152 117 153 118 Value d2polemy(T)(T e) 154 119 { 155 120 return ast2table(e, delegate Value(AST){ assert(false); }); 156 121 } 157 122 158 123 /// Convert AST to Table so that it can be used in Polemy ................................................................................ 180 145 { 181 146 assert( typeid(e) == typeid(T), text("abstracted: ", typeid(e), " vs ", typeid(T)) ); 182 147 auto t = new Table; 183 148 t.set("pos", ValueLayer, ast2table(e.pos,rec)); 184 149 t.set("is" , ValueLayer, new StrValue(typeid(e).name.split(".")[$-1].tolower())); 185 150 foreach(i,m; e.tupleof) 186 151 static if(is(typeof(m) : AST)) 187 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, rec(m)); 152 + t.set(e.tupleof[i].stringof.split(".")[$-1], ValueLayer, rec(m)); 188 153 else 189 - t.set(e.tupleof[i].stringof[2..$], ValueLayer, ast2table(m,rec)); 154 + t.set(e.tupleof[i].stringof.split(".")[$-1], ValueLayer, ast2table(m,rec)); 190 155 return t; 191 156 } 192 157 else 193 158 static if(is(T == class)) 194 159 { 195 160 auto t = new Table; 196 161 foreach(i,m; e.tupleof)