Check-in [0569f7b8c2]
Not logged in
Overview
SHA1 Hash:0569f7b8c23ef9b26e3b3cb4aae86b9fb0dbf2a5
Date: 2010-11-07 23:34:29
User: kinaba
Comment:- Added function literal evaluator (i.e., closure). - Workaround for d2stacktrace's infinite-loop bug. (when std.demangle.demangle use exception inside it, it will go into an infinite loop. to avoid this, I choose to unset TraceHandler during stacktrace generation. This is far from the complete solution, but at least it should work as expected under single-thread environment...)
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified d2stacktrace/stacktrace.d from [02abce9abb958e1c] to [059fc11fc8a1312c].

232 232 info.length = info.length + 1; 233 233 info[info.length-1] = str; 234 234 } 235 235 } 236 236 } 237 237 238 238 static Throwable.TraceInfo TraceHandler(void* ptr){ 239 - StackTrace trace = new StackTrace(); 240 - return trace.GetCallstack(); 239 + // modified by k.inaba to avoid a throw inside std.demangle.demangle 240 + // not quite thread safe 241 + Runtime.traceHandler(&core.runtime.defaultTraceHandler); 242 + scope(exit) Runtime.traceHandler(&TraceHandler); 243 + 244 + StackTrace trace = new StackTrace(); 245 + return trace.GetCallstack(); 241 246 } 242 247 243 248 public: 244 249 static this(){ 245 250 Runtime.traceHandler(&TraceHandler); 246 251 SetUnhandledExceptionFilter(&UnhandeledExceptionFilterHandler); 247 252 } ................................................................................ 360 365 } 361 366 } 362 367 363 368 free(Symbol); 364 369 return stack; 365 370 } 366 371 }; 372 +

Modified polemy/_common.d from [0abd8de4d8be4f44] to [935cc3e03ebe462f].

6 6 */ 7 7 module polemy._common; 8 8 public import std.array; 9 9 public import std.range; 10 10 public import std.algorithm; 11 11 public import std.conv : to; 12 12 public import std.bigint; 13 +public import std.exception; 13 14 public import polemy.tricks;

Modified polemy/eval.d from [c5ee9ab6830c78bd] to [cea762cacb86424f].

2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Evaluator for Polemy programming language. 6 6 */ 7 7 module polemy.eval; 8 8 import polemy._common; 9 +import polemy.lex : LexPosition; 9 10 import polemy.ast; 10 11 import polemy.parse; 11 12 import polemy.runtime; 13 +import std.typecons; 12 14 13 15 Context createGlobalContext() 14 16 { 15 17 auto ctx = new Context; 16 - ctx.add("+", new PrimitiveFunction(delegate Value(Value[] args){ 18 + ctx.add("+", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 17 19 if( args.length != 2 ) 18 - throw new PolemyRuntimeException("+ takes two arguments!!"); // TODO improve this message 20 + throw new PolemyRuntimeException("+ takes two arguments!! ["~to!string(pos)~"]"); 19 21 if( auto x = cast(IntValue)args[0] ) 20 22 if( auto y = cast(IntValue)args[1] ) 21 23 return new IntValue(x.data+y.data); 22 - throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 24 + throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 23 25 })); 24 - ctx.add("-", new PrimitiveFunction(delegate Value(Value[] args){ 26 + ctx.add("-", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 25 27 if( args.length != 2 ) 26 - throw new PolemyRuntimeException("- takes two arguments!!"); // TODO improve this message 28 + throw new PolemyRuntimeException("- takes two arguments!! ["~to!string(pos)~"]"); 27 29 if( auto x = cast(IntValue)args[0] ) 28 30 if( auto y = cast(IntValue)args[1] ) 29 31 return new IntValue(x.data-y.data); 30 - throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 32 + throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 31 33 })); 32 - ctx.add("*", new PrimitiveFunction(delegate Value(Value[] args){ 34 + ctx.add("*", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 33 35 if( args.length != 2 ) 34 - throw new PolemyRuntimeException("* takes two arguments!!"); // TODO improve this message 36 + throw new PolemyRuntimeException("* takes two arguments!! ["~to!string(pos)~"]"); 35 37 if( auto x = cast(IntValue)args[0] ) 36 38 if( auto y = cast(IntValue)args[1] ) 37 39 return new IntValue(x.data*y.data); 38 - throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 40 + throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 39 41 })); 40 - ctx.add("/", new PrimitiveFunction(delegate Value(Value[] args){ 42 + ctx.add("/", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 41 43 if( args.length != 2 ) 42 - throw new PolemyRuntimeException("/ takes two arguments!!"); // TODO improve this message 44 + throw new PolemyRuntimeException("/ takes two arguments!! ["~to!string(pos)~"]"); 43 45 if( auto x = cast(IntValue)args[0] ) 44 46 if( auto y = cast(IntValue)args[1] ) 45 47 return new IntValue(x.data/y.data); 46 - throw new PolemyRuntimeException("cannot add non-integers"); // TODO improve this message 48 + throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 47 49 })); 48 50 return ctx; 49 51 } 50 52 51 -Context evalString(T...)(T params) 53 +Tuple!(Value,"val",Context,"ctx") evalString(T...)(T params) 52 54 { 53 55 return eval( parserFromString(params).parseProgram() ); 54 56 } 55 57 56 -Context evalFile(T...)(T params) 58 +Tuple!(Value,"val",Context,"ctx") evalFile(T...)(T params) 57 59 { 58 60 return eval( parserFromFile(params).parseProgram() ); 59 61 } 60 62 61 -Context eval(Program prog) 63 +Tuple!(Value,"val",Context,"ctx") eval(Program prog) 62 64 { 63 - return eval(prog, createGlobalContext()); 65 + Context ctx = createGlobalContext(); 66 + return typeof(return)(eval(prog, ctx), ctx); 64 67 } 65 68 66 -Context eval(Program prog, Context ctx) 69 +Value eval(Program prog, Context ctx) 67 70 { 71 + Value v = new UndefinedValue; 68 72 foreach(s; prog) 69 - ctx = eval(s, ctx); 70 - return ctx; 73 + v = eval(s, ctx); 74 + return v; 71 75 } 72 76 73 -Context eval(Statement _s, Context ctx) 77 +Value eval(Statement _s, Context ctx) 74 78 { 75 79 if( auto s = cast(DeclStatement)_s ) 76 80 { 77 81 auto v = eval(s.expr, ctx); 78 82 ctx.add(s.var, v); 79 - return ctx; 83 + return v; 80 84 } 81 85 else 82 86 if( auto s = cast(ExprStatement)_s ) 83 87 { 84 - eval(s.expr, ctx); 85 - return ctx; 88 + return eval(s.expr, ctx); 86 89 } 87 90 throw new PolemyRuntimeException(sprintf!"Unknown Kind of Statement %s at [%s]"(typeid(_s), _s.pos)); 88 91 } 89 92 90 93 Value eval(Expression _e, Context ctx) 91 94 { 92 95 if( auto e = cast(StrLiteralExpression)_e ) ................................................................................ 118 121 if( auto e = cast(FuncallExpression)_e ) 119 122 { 120 123 Value _f = eval(e.fun, ctx); 121 124 if( auto f = cast(FunValue)_f ) { 122 125 Value[] args; 123 126 foreach(a; e.args) 124 127 args ~= eval(a, ctx); 125 - return f.call(args); 128 + return f.call(e.pos, args); 126 129 } else 127 130 throw new PolemyRuntimeException(sprintf!"Non-funcion is applied at [%s]"(e.pos)); 131 + } 132 + else 133 + if( auto e = cast(FunLiteralExpression)_e ) 134 + { 135 + return new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 136 + if( e.params.length != args.length ) 137 + throw new PolemyRuntimeException(sprintf!"Argument Number Mismatch (%d required but %d given) at [%s]" 138 + (e.params.length, args.length, e.pos)); 139 + Context ctxNeo = new Context(ctx); 140 + foreach(i,p; e.params) 141 + ctxNeo.add(p, args[i]); 142 + return eval(e.funbody, ctxNeo); 143 + }); 128 144 } 129 145 throw new PolemyRuntimeException(sprintf!"Unknown Kind of Expression %s at [%s]"(typeid(_e), _e.pos)); 130 146 } 131 147 132 - 133 -version(unittest) import polemy.parse; 134 -version(unittest) import std.stdio; 135 -version(unittest) import std.exception; 148 +import std.stdio; 136 149 unittest 137 150 { 138 - auto ctx = evalString(`var x = 21; x = x + x*x;`); 139 - assert( ctx["x"] == new IntValue(BigInt(21+21*21)) ); 140 - assert( !collectException(ctx["x"]) ); 141 - assert( collectException(ctx["y"]) ); 151 + auto r = evalString(`var x = 21; x = x + x*x;`); 152 + assert( r.val == new IntValue(BigInt(21+21*21)) ); 153 + assert( r.ctx["x"] == new IntValue(BigInt(21+21*21)) ); 154 + assert( !collectException(r.ctx["x"]) ); 155 + assert( collectException(r.ctx["y"]) ); 142 156 } 143 157 unittest 144 158 { 145 159 assert( collectException(evalString(`var x = 21; x = x + x*y;`)) ); 160 + assert( collectException(evalString(`x=1;`)) ); 161 +} 162 +unittest 163 +{ 164 + auto r = evalString(`var x = fun(a){1+a;}(2);`); 165 + assert( r.ctx["x"] == new IntValue(BigInt(3)) ); 166 + assert( r.val == new IntValue(BigInt(3)) ); 146 167 } 147 168 unittest 148 169 { 149 - assert( collectException(evalString(`var x = 21; y = x + x*x;`)) ); 170 + auto r = evalString(`var x = 1; var f = fun(){x=x+1;}; f(); f(); f();`); 171 + assert( r.ctx["x"] == new IntValue(BigInt(4)) ); 172 + assert( r.val == new IntValue(BigInt(4)) ); 150 173 }

Modified polemy/parse.d from [4856c979362ef435] to [1d6de9cb69bbf7d4].

188 188 return e; 189 189 } 190 190 191 191 if( tryEat("fun") ) 192 192 { 193 193 eat("(", "after fun"); 194 194 string[] params; 195 - for(;;) 195 + while(!tryEat(")")) 196 196 { 197 197 if( lex.empty ) { 198 198 auto e = ParserException.create(lex,"Unexpected EOF"); 199 199 throw e; 200 200 } 201 201 if( lex.front.kind != Token.Kind.identifier ) { 202 202 auto e = ParserException.create(lex,"Identifier Expected for parameters"); ................................................................................ 306 306 new IntLiteralExpression(null, BigInt(1)), 307 307 new FuncallExpression(null, 308 308 new FunLiteralExpression(null, ["abc"], [ 309 309 ]), 310 310 new IntLiteralExpression(null, BigInt(4)) 311 311 )))); 312 312 } 313 +unittest 314 +{ 315 + auto p = parserFromString(`var x = 1; var f = fun(){x=x+1;}; f(); f(); x;`); 316 + Program prog = p.parseProgram(); 317 +}

Modified polemy/runtime.d from [c94ffd3733368117] to [eb7f695558db6c0f].

2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Runtime data structures for Polemy programming language. 6 6 */ 7 7 module polemy.runtime; 8 8 import polemy._common; 9 +import polemy.lex : LexPosition; 10 +import std.stdio; 9 11 10 12 class PolemyRuntimeException : Exception 11 13 { 12 14 this(string msg) { super(msg); } 13 15 } 14 16 15 17 abstract class Value 16 18 { 17 19 } 20 + 21 +class UndefinedValue : Value 22 +{ 23 + mixin SimpleConstructor; 24 + mixin SimpleCompare; 25 +} 18 26 19 27 class IntValue : Value 20 28 { 21 29 BigInt data; 22 30 mixin SimpleConstructor; 23 31 mixin SimpleCompare; 24 32 } ................................................................................ 26 34 class StrValue : Value 27 35 { 28 36 string data; 29 37 mixin SimpleConstructor; 30 38 mixin SimpleCompare; 31 39 } 32 40 33 -abstract class FunValue : Value 41 +class FunValue : Value 34 42 { 35 - Value call(Value[] args); 43 + Value delegate(immutable LexPosition pos, Value[]) data; 44 + mixin SimpleConstructor; 45 + Value call(immutable LexPosition pos, Value[] args) { return data(pos,args); } 36 46 } 37 - 38 -class PrimitiveFunction : FunValue 39 -{ 40 - Value delegate(Value[]) data; 41 - mixin SimpleConstructor; 42 - override Value call(Value[] args) { return data(args); } 43 -} 44 - 47 +import std.stdio; 45 48 class Context 46 49 { 47 50 Context parent; 48 51 Value[string] table; 49 52 this(Context parent = null) { this.parent = parent; } 50 53 51 54 void add(string i, Value v)

Modified polemy/tricks.d from [193cf29f54393c6e] to [16f826d18ff480be].

26 26 /// Mixing-in the bean constructor for a class 27 27 28 28 /*mixin*/ template SimpleConstructor() 29 29 { 30 30 static if( is(typeof(super) == Object) || super.tupleof.length==0 ) 31 31 this( typeof(this.tupleof) params ) 32 32 { 33 - this.tupleof = params; 33 + static if(this.tupleof.length>0) 34 + this.tupleof = params; 34 35 } 35 36 else 36 37 // this parameter list is not always desirable but should work for many cases 37 38 this( typeof(super.tupleof) ps, typeof(this.tupleof) params ) 38 39 { 39 40 super(ps); 40 - this.tupleof = params; 41 + static if(this.tupleof.length>0) 42 + this.tupleof = params; 41 43 } 42 44 } 43 45 44 46 /// Mixing-in the (MOST-DERIVED) member-wise comparator for a class 45 47 46 48 /*mixin*/ template SimpleCompare() 47 49 {