Check-in [8de5b49cdf]
Not logged in
Overview
SHA1 Hash:8de5b49cdf478ae4727df1eaddd3ad369c707e5e
Date: 2010-11-09 14:19:20
User: kinaba
Comment:split tricks module into a separate package.
Timelines: family | ancestors | descendants | both | trunk
Downloads: Tarball | ZIP archive
Other Links: files | file ages | manifest
Tags And Properties
Changes

Modified .poseidon from [2bab91be5bee6d2e] to [374d8a7e60e3002a].

29 29 <projectFiles> 30 30 <source> 31 31 <name>d2stacktrace\dbghelp.d</name> 32 32 <name>d2stacktrace\stacktrace.d</name> 33 33 <name>main.d</name> 34 34 <name>polemy\_common.d</name> 35 35 <name>polemy\ast.d</name> 36 + <name>polemy\eval.d</name> 36 37 <name>polemy\lex.d</name> 37 38 <name>polemy\parse.d</name> 38 - <name>polemy\tricks.d</name> 39 39 <name>polemy\value.d</name> 40 + <name>tricks\test.d</name> 41 + <name>tricks\tricks.d</name> 40 42 </source> 41 43 <interface /> 42 44 <resource /> 43 45 <othersDMD /> 44 46 <others> 45 47 <name>build.bat</name> 46 48 <name>build.sh</name>

Modified build.bat from [a3b137d66c9ae5c5] to [4a978e9aa8f5388f].

1 1 @setlocal ENABLEDELAYEDEXPANSION 2 2 @set ARGS= 3 -@for %%I in (main.d polemy\*.d) do @set ARGS=!ARGS! %%I 3 +@for %%I in (main.d polemy\*.d tricks\*.d) do @set ARGS=!ARGS! %%I 4 4 @if not exist bin mkdir bin 5 5 @echo dmd -ofbin\polemy.exe -O -release -inline %ARGS% 6 6 @dmd -ofbin\polemy.exe -O -release -inline %ARGS%

Modified d2stacktrace/stacktrace.d from [059fc11fc8a1312c] to [1456272a3238466c].

Modified polemy/_common.d from [935cc3e03ebe462f] to [5141868f3bc27248].

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 13 public import std.exception; 14 -public import polemy.tricks; 14 +public import tricks.tricks; 15 +public import tricks.test;

Modified polemy/ast.d from [35d37c6aa0a6531e] to [c08643c4271f8f35].

1 -/** 1 +/** 2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Syntax tree for Polemy programming language. 6 6 */ 7 7 module polemy.ast; 8 8 import polemy._common;

Modified polemy/eval.d from [003971cb94b55966] to [1a40d715cf0caee4].

1 -/** 1 +/** 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 9 import polemy.lex : LexPosition; 10 10 import polemy.ast; 11 11 import polemy.parse; 12 12 import polemy.value; 13 13 import std.typecons; 14 14 import std.stdio; 15 15 16 -Context createGlobalContext() 16 +Table createGlobalContext() 17 17 { 18 - auto ctx = new Context; 19 - ctx.add("+", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 18 + auto ctx = new Table; 19 + // [TODO] autogenerate these typechecks 20 + ctx.set("+", "@val", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 20 21 if( args.length != 2 ) 21 - throw new PolemyRuntimeException("+ takes two arguments!! ["~to!string(pos)~"]"); 22 + throw new RuntimeException(pos, "+ takes two arguments!!"); 22 23 if( auto x = cast(IntValue)args[0] ) 23 24 if( auto y = cast(IntValue)args[1] ) 24 25 return new IntValue(x.data+y.data); 25 - throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 26 + throw new RuntimeException(pos, "cannot add non-integers"); 26 27 })); 27 - ctx.add("-", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 28 + ctx.set("-", "@val", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 28 29 if( args.length != 2 ) 29 - throw new PolemyRuntimeException("- takes two arguments!! ["~to!string(pos)~"]"); 30 + throw new RuntimeException(pos, "- takes two arguments!!"); 30 31 if( auto x = cast(IntValue)args[0] ) 31 32 if( auto y = cast(IntValue)args[1] ) 32 33 return new IntValue(x.data-y.data); 33 - throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 34 + throw new RuntimeException(pos, "cannot subtract non-integers"); 34 35 })); 35 - ctx.add("*", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 36 + ctx.set("*", "@val", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 36 37 if( args.length != 2 ) 37 - throw new PolemyRuntimeException("* takes two arguments!! ["~to!string(pos)~"]"); 38 + throw new RuntimeException(pos, "* takes two arguments!!"); 38 39 if( auto x = cast(IntValue)args[0] ) 39 40 if( auto y = cast(IntValue)args[1] ) 40 41 return new IntValue(x.data*y.data); 41 - throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 42 + throw new RuntimeException(pos, "cannot multiply non-integers"); 42 43 })); 43 - ctx.add("/", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 44 + ctx.set("/", "@val", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 44 45 if( args.length != 2 ) 45 - throw new PolemyRuntimeException("/ takes two arguments!! ["~to!string(pos)~"]"); 46 + throw new RuntimeException(pos, "/ takes two arguments!!"); 46 47 if( auto x = cast(IntValue)args[0] ) 47 48 if( auto y = cast(IntValue)args[1] ) 48 49 return new IntValue(x.data/y.data); 49 - throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 50 + throw new RuntimeException(pos, "cannot divide non-integers"); 50 51 })); 51 - ctx.add("<", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 52 + ctx.set("<", "@val", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 52 53 if( args.length != 2 ) 53 - throw new PolemyRuntimeException("< takes two arguments!! ["~to!string(pos)~"]"); 54 + throw new RuntimeException(pos, "< takes two arguments!!"); 54 55 if( auto x = cast(IntValue)args[0] ) 55 56 if( auto y = cast(IntValue)args[1] ) 56 57 return new IntValue(BigInt(to!int(x.data < y.data))); 57 - throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 58 + throw new RuntimeException(pos, "cannot compare non-integers"); 58 59 })); 59 - ctx.add(">", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 60 + ctx.set(">", "@val", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 60 61 if( args.length != 2 ) 61 - throw new PolemyRuntimeException("> takes two arguments!! ["~to!string(pos)~"]"); 62 + throw new RuntimeException(pos, "> takes two arguments!!"); 62 63 if( auto x = cast(IntValue)args[0] ) 63 64 if( auto y = cast(IntValue)args[1] ) 64 65 return new IntValue(BigInt(to!int(x.data>y.data))); 65 - throw new PolemyRuntimeException("cannot add non-integers ["~to!string(pos)~"]"); 66 + throw new RuntimeException(pos, "cannot compare non-integers"); 66 67 })); 67 - ctx.add("print", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 68 + ctx.set("print", "@val", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 68 69 foreach(a; args) 69 70 write(a); 70 71 writeln(""); 71 - return new UndefinedValue; 72 + return new IntValue(BigInt(178)); 72 73 })); 73 - ctx.add("if", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 74 + ctx.set("if", "@val", new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 74 75 if( args.length != 3 ) 75 - throw new PolemyRuntimeException("if takes three arguments!! ["~to!string(pos)~"]"); 76 + throw new RuntimeException(pos, "if takes three arguments!!"); 76 77 if( auto x = cast(IntValue)args[0] ) 77 78 if( auto ft = cast(FunValue)args[1] ) 78 79 if( auto fe = cast(FunValue)args[2] ) 79 80 return (x.data == 0 ? fe : ft).call(pos,[]); 80 - throw new PolemyRuntimeException("type mismatch in if ["~to!string(pos)~"]"); 81 + throw new RuntimeException(pos, "type mismatch in if"); 81 82 })); 82 83 return ctx; 83 84 } 84 85 85 -Tuple!(Value,"val",Context,"ctx") evalString(T...)(T params) 86 +/// Entry point of this module 87 + 88 +Tuple!(Value,"val",Table,"ctx") evalString(S,T...)(S str, T fn_ln_cn) 86 89 { 87 - return eval( parserFromString(params).parseProgram() ); 90 + return eval( polemy.parse.parseString(str, fn_ln_cn) ); 88 91 } 89 92 90 -Tuple!(Value,"val",Context,"ctx") evalFile(T...)(T params) 93 +Tuple!(Value,"val",Table,"ctx") evalFile(S, T...)(S filenae, T ln_cn) 91 94 { 92 - return eval( parserFromFile(params).parseProgram() ); 95 + return eval( polemy.parse.parseFile(filename, ln_cn) ); 93 96 } 94 97 95 -Tuple!(Value,"val",Context,"ctx") eval(Program prog) 98 +Tuple!(Value,"val",Table,"ctx") eval(AST e) 96 99 { 97 - Context ctx = createGlobalContext(); 98 - return typeof(return)(eval(prog, ctx), ctx); 100 + Table ctx = createGlobalContext(); 101 + return typeof(return)(eval(e, ctx), ctx); 99 102 } 100 103 101 -Value eval(Program prog, Context ctx) 102 -{ 103 - Value v = new UndefinedValue; 104 - foreach(s; prog) 105 - v = eval(s, ctx); 106 - return v; 107 -} 108 - 109 -Value eval(Statement _s, Context ctx) 104 +Value eval(AST _e, Table ctx, bool splitCtx = true) 110 105 { 111 - if( auto s = cast(DeclStatement)_s ) 112 - { 113 - auto v = eval(s.expr, ctx); 114 - ctx.add(s.var, v); 115 - return v; 116 - } 117 - else 118 - if( auto s = cast(ExprStatement)_s ) 119 - { 120 - return eval(s.expr, ctx); 121 - } 122 - throw new PolemyRuntimeException(sprintf!"Unknown Kind of Statement %s at [%s]"(typeid(_s), _s.pos)); 123 -} 124 - 125 -Value eval(Expression _e, Context ctx) 126 -{ 127 - if( auto e = cast(StrLiteralExpression)_e ) 106 + if( auto e = cast(StrLiteral)_e ) 128 107 { 129 108 return new StrValue(e.data); 130 109 } 131 110 else 132 - if( auto e = cast(IntLiteralExpression)_e ) 111 + if( auto e = cast(IntLiteral)_e ) 133 112 { 134 113 return new IntValue(e.data); 135 114 } 136 115 else 137 116 if( auto e = cast(VarExpression)_e ) 138 117 { 139 - return ctx[e.var]; 118 + return ctx.get(e.var, "@val", e.pos); 140 119 } 141 120 else 142 - if( auto e = cast(AssignExpression)_e ) 121 + if( auto e = cast(LetExpression)_e ) 143 122 { 144 - if( auto ev = cast(VarExpression)e.lhs ) 145 - { 146 - Value r = eval(e.rhs, ctx); 147 - ctx[ev.var] = r; 148 - return r; 149 - } 150 - throw new PolemyRuntimeException(sprintf!"Lhs of assignment must be a variable: %s"(e.pos)); 123 + // for letrec, we need this, but should avoid overwriting???? 124 + // ctx.set(e.var, "@val", new UndefinedValue, e.pos); 125 + Value v = eval(e.init, ctx, true); 126 + ctx.set(e.var, "@val", v, e.pos); 127 + return eval(e.expr, ctx); 151 128 } 152 129 else 153 130 if( auto e = cast(FuncallExpression)_e ) 154 131 { 155 132 Value _f = eval(e.fun, ctx); 156 133 if( auto f = cast(FunValue)_f ) { 157 134 Value[] args; 158 135 foreach(a; e.args) 159 136 args ~= eval(a, ctx); 160 137 return f.call(e.pos, args); 161 138 } else 162 - throw new PolemyRuntimeException(sprintf!"Non-funcion is applied at [%s]"(e.pos)); 139 + throw new RuntimeException(e.pos, "Non-funcion is applied"); 163 140 } 164 141 else 165 - if( auto e = cast(FunLiteralExpression)_e ) 142 + if( auto e = cast(FunLiteral)_e ) 166 143 { 167 144 return new FunValue(delegate Value(immutable LexPosition pos, Value[] args){ 168 145 if( e.params.length != args.length ) 169 - throw new PolemyRuntimeException(sprintf!"Argument Number Mismatch (%d required but %d given) at [%s]" 170 - (e.params.length, args.length, e.pos)); 171 - Context ctxNeo = new Context(ctx); 146 + throw new RuntimeException(e.pos, sprintf!"Argument Number Mismatch (%d required but %d given)" 147 + (e.params.length, args.length)); 148 + Table ctxNeo = new Table(ctx, Table.Kind.NotPropagateSet); 172 149 foreach(i,p; e.params) 173 - ctxNeo.add(p, args[i]); 150 + ctxNeo.set(p, "@val", args[i]); 174 151 return eval(e.funbody, ctxNeo); 175 152 }); 176 153 } 177 - throw new PolemyRuntimeException(sprintf!"Unknown Kind of Expression %s at [%s]"(typeid(_e), _e.pos)); 154 + throw new RuntimeException(_e.pos, sprintf!"Unknown Kind of Expression %s"(typeid(_e))); 178 155 } 179 156 180 157 unittest 181 158 { 182 - auto r = evalString(`var x = 21; x = x + x*x;`); 183 - assert( r.val == new IntValue(BigInt(21+21*21)) ); 184 - assert( r.ctx["x"] == new IntValue(BigInt(21+21*21)) ); 185 - assert( !collectException(r.ctx["x"]) ); 186 - assert( collectException(r.ctx["y"]) ); 159 + auto r = assert_nothrow( evalString(`var x = 21; x + x*x;`) ); 160 + assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 161 + assert_eq( r.ctx.get("x","@val"), new IntValue(BigInt(21)) ); 162 + assert_nothrow( r.ctx.get("x","@val") ); 163 + assert_throw!RuntimeException( r.ctx.get("y","@val") ); 187 164 } 188 165 unittest 189 166 { 190 - assert( collectException(evalString(`var x = 21; x = x + x*y;`)) ); 191 - assert( collectException(evalString(`x=1;`)) ); 167 + auto r = assert_nothrow( evalString(`var x = 21; var x = x + x*x;`) ); 168 + assert_eq( r.val, new IntValue(BigInt(21+21*21)) ); 169 + assert_eq( r.ctx.get("x","@val"), new IntValue(BigInt(21+21*21)) ); 170 + assert_nothrow( r.ctx.get("x","@val") ); 171 + assert_throw!RuntimeException( r.ctx.get("y","@val") ); 192 172 } 193 173 unittest 194 174 { 195 - auto r = evalString(`var x = fun(a){1+a;}(2);`); 196 - assert( r.ctx["x"] == new IntValue(BigInt(3)) ); 197 - assert( r.val == new IntValue(BigInt(3)) ); 175 + assert_nothrow( evalString(`print("Hello, world!");`) ); 176 + assert_nothrow( evalString(`print(fun(){});`) ); 198 177 } 199 178 unittest 200 179 { 201 - auto r = evalString(`var x = 1; var f = fun(){x=x+1;}; f(); f(); f();`); 202 - assert( r.ctx["x"] == new IntValue(BigInt(4)) ); 203 - assert( r.val == new IntValue(BigInt(4)) ); 204 -} 205 -unittest 206 -{ 207 - evalString(`print("Hello, world!");`); 208 - evalString(`print(fun(){});`); 209 -} 210 -unittest 211 -{ 212 - evalString(`var fac = fun(x){ 180 + assert_nothrow( evalString(`var fac = fun(x){ 213 181 1; 214 182 }; 215 - print(fac(3));`); 216 - evalString(`var fac = fun(x){ 183 + print(fac(3));`)); 184 + assert_nothrow( evalString(`var fac = fun(x){ 217 185 if(x) 218 186 { x*fac(x-1); } 219 187 else 220 188 { 1; }; 221 189 }; 222 - print(fac(10));`); 223 - evalString(`var fib = fun(x){ 190 + print(fac(10));`)); 191 + assert_nothrow( evalString(`var fib = fun(x){ 224 192 if(x<2) 225 193 { 1; } 226 194 else 227 195 { fib(x-1) + fib(x-2); }; 228 196 }; 229 - print(fib(10));`); 197 + print(fib(10));`)); 230 198 }

Modified polemy/lex.d from [cc80329bc2ab2034] to [df057f5d35e6bc8a].

11 11 12 12 /// Exception from this module 13 13 14 14 class LexException : Exception 15 15 { 16 16 const LexPosition pos; 17 17 18 - private this( const LexPosition pos, string msg ) 19 - { super(sprintf!"%s [%s]"(msg, pos)); this.pos = pos; } 18 + this( const LexPosition pos, string msg, string file="", int line=0 ) 19 + { super(sprintf!"[%s] %s"(pos, msg), file, line); this.pos = pos; } 20 20 }; 21 21 22 22 /// Represents a position in a source code 23 23 24 24 class LexPosition 25 25 { 26 26 immutable string filename; /// name of the source file 27 27 immutable int lineno; /// 1-origin 28 28 immutable int column; /// 1-origin 29 29 30 + mixin SimpleClass; 30 31 override string toString() const 31 32 { return sprintf!"%s:%d:%d"(filename, lineno, column); } 32 33 33 - mixin SimpleConstructor; 34 - mixin SimpleCompare; 35 - 36 34 static immutable LexPosition dummy; 37 35 static this(){ dummy = new immutable(LexPosition)("<unnamed>",0,0); } 38 36 } 39 37 40 38 unittest 41 39 { 42 40 auto p = new LexPosition("hello.cpp", 123, 45); ................................................................................ 59 57 60 58 class Token 61 59 { 62 60 immutable LexPosition pos; /// Position where the token occurred in the source 63 61 immutable string str; /// The token string itself 64 62 immutable bool quoted; /// Was it a "quoted" token or unquoted? 65 63 66 - mixin SimpleConstructor; 67 - mixin SimpleCompare; 68 - mixin SimpleToString; 64 + mixin SimpleClass; 69 65 } 70 66 71 67 unittest 72 68 { 73 69 auto p = new immutable(LexPosition)("hello.cpp", 123, 45); 74 70 auto t = new Token(p, "class", false); 75 71 auto u = new Token(p, "class", true);

Modified polemy/parse.d from [d47e2b014f260d66] to [fe5c9fee07b98701].

18 18 private this( const LexPosition pos, string msg ) 19 19 { super(sprintf!"%s [%s]"(msg, pos)); this.pos = pos; } 20 20 } 21 21 22 22 private auto createException(Lexer)(Lexer lex, string msg) 23 23 { return new ParseException(lex.empty?null:lex.front.pos, msg); } 24 24 25 -/// Entry point of this module 25 +/// Entry points of this module 26 26 27 27 auto parseString(S, T...)(S str, T fn_ln_cn) 28 28 { return parserFromString(str, fn_ln_cn).parse(); } 29 29 30 30 auto parseFile(S, T...)(S filename,T ln_cn) 31 31 { return parserFromString(filename, ln_cn).parse(); } 32 32

Deleted polemy/tricks.d version [73906cba073bce6c]

1 -/** 2 - * Authors: k.inaba 3 - * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 - * 5 - * Common tricks and utilities for programming in D. 6 - */ 7 -module polemy.tricks; 8 -import std.array : appender; 9 -import std.format : formattedWrite; 10 -import core.exception : onAssertErrorMsg, AssertError; 11 - 12 -/// Simple Wrapper for std.format.doFormat 13 - 14 -string sprintf(string fmt, T...)(T params) 15 -{ 16 - auto writer = appender!string(); 17 - formattedWrite(writer, fmt, params); 18 - return writer.data; 19 -} 20 - 21 -unittest 22 -{ 23 - assert( sprintf!"%s == %d"("1+2", 3) == "1+2 == 3" ); 24 - assert( sprintf!"%s == %04d"("1+2", 3) == "1+2 == 0003" ); 25 -} 26 - 27 -/// Unittest helper that asserts an expression must throw something 28 - 29 -void assert_throw(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="") 30 -{ 31 - try { 32 - t(); 33 - } catch(ExceptionType) { 34 - return; 35 - } catch(Throwable e) { 36 - onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e)); 37 - } 38 - onAssertErrorMsg(fn, ln, msg.length ? msg : "no execption"); 39 -} 40 - 41 -/// Unittest helper that asserts an expression must not throw anything 42 - 43 -void assert_nothrow(T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="") 44 -{ 45 - try { 46 - t(); 47 - } catch(Throwable e) { 48 - onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e)); 49 - } 50 -} 51 - 52 -unittest 53 -{ 54 - auto error = {throw new Error("hello");}; 55 - auto nothing = (){}; 56 - auto assertError = {assert(0);}; 57 - 58 - assert_nothrow ( assert_nothrow(nothing()) ); 59 - assert_throw!AssertError( assert_nothrow(error()) ); 60 - assert_throw!AssertError( assert_nothrow(assertError()) ); 61 - 62 - assert_nothrow ( assert_throw!Error(error()) ); 63 - assert_throw!AssertError( assert_throw!Error(nothing()) ); 64 - assert_nothrow ( assert_throw!Error(assertError()) ); 65 - assert_throw!AssertError( assert_throw!AssertError(error()) ); 66 -} 67 - 68 -/// Unittest helpers asserting two values are in some relation ==, !=, <, <=, >, >= 69 - 70 -template assertOp(string op) 71 -{ 72 - void assertOp(A, B, string fn=__FILE__, int ln=__LINE__)(A a, B b, string msg="") 73 - { 74 - try { 75 - if( mixin("a"~op~"b") ) return; 76 - } catch(Throwable e) { 77 - onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e)); 78 - } 79 - onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"%s !%s %s"(a,op,b)); 80 - } 81 -} 82 - 83 -alias assertOp!(`==`) assert_eq; 84 -alias assertOp!(`!=`) assert_ne; 85 -alias assertOp!(`<`) assert_lt; 86 -alias assertOp!(`<=`) assert_le; 87 -alias assertOp!(`>`) assert_gt; 88 -alias assertOp!(`>=`) assert_ge; 89 - 90 -unittest 91 -{ 92 - assert_nothrow( assert_eq(1, 1) ); 93 - assert_nothrow( assert_ne(1, 0) ); 94 - assert_nothrow( assert_lt(0, 1) ); 95 - assert_nothrow( assert_le(0, 1) ); 96 - assert_nothrow( assert_le(0, 0) ); 97 - assert_nothrow( assert_gt(1, 0) ); 98 - assert_nothrow( assert_ge(1, 0) ); 99 - assert_nothrow( assert_ge(0, 0) ); 100 - 101 - assert_throw!AssertError( assert_eq(1, 0) ); 102 - assert_throw!AssertError( assert_ne(1, 1) ); 103 - assert_throw!AssertError( assert_lt(1, 1) ); 104 - assert_throw!AssertError( assert_lt(1, 0) ); 105 - assert_throw!AssertError( assert_le(1, 0) ); 106 - assert_throw!AssertError( assert_gt(0, 0) ); 107 - assert_throw!AssertError( assert_gt(0, 1) ); 108 - assert_throw!AssertError( assert_ge(0, 1) ); 109 - 110 - class Temp { bool opEquals(int x){return x/x==x;} } 111 - assert_throw!AssertError( assert_eq(new Temp, 0) ); 112 - assert_nothrow ( assert_eq(new Temp, 1) ); 113 - assert_throw!AssertError( assert_eq(new Temp, 2) ); 114 -} 115 - 116 -/* [Todo] is there any way to clearnly implement "assert_compiles" and "assert_not_compile"? */ 117 - 118 -/// Mixing-in the bean constructor for a class 119 - 120 -/*mixin*/ 121 -template SimpleConstructor() 122 -{ 123 - static if( is(typeof(super) == Object) || super.tupleof.length==0 ) 124 - this( typeof(this.tupleof) params ) 125 - { 126 - static if(this.tupleof.length>0) 127 - this.tupleof = params; 128 - } 129 - else 130 - this( typeof(super.tupleof) ps, typeof(this.tupleof) params ) 131 - { 132 - // including (only) the direct super class members 133 - // may not always be a desirable choice, but should work for many cases 134 - super(ps); 135 - static if(this.tupleof.length>0) 136 - this.tupleof = params; 137 - } 138 -} 139 - 140 -unittest 141 -{ 142 - class Temp 143 - { 144 - int x; 145 - string y; 146 - mixin SimpleConstructor; 147 - } 148 - assert_eq( (new Temp(1,"foo")).x, 1 ); 149 - assert_eq( (new Temp(1,"foo")).y, "foo" ); 150 - assert( !__traits(compiles, new Temp) ); 151 - assert( !__traits(compiles, new Temp(1)) ); 152 - assert( !__traits(compiles, new Temp("foo",1)) ); 153 - 154 - class Tomp : Temp 155 - { 156 - real z; 157 - mixin SimpleConstructor; 158 - } 159 - assert_eq( (new Tomp(1,"foo",2.5)).x, 1 ); 160 - assert_eq( (new Tomp(1,"foo",2.5)).y, "foo" ); 161 - assert_eq( (new Tomp(1,"foo",2.5)).z, 2.5 ); 162 - assert( !__traits(compiles, new Tomp(3.14)) ); 163 - 164 - // shiyo- desu. Don't use in this way. 165 - // Tamp tries to call new Tomp(real) (because it only sees Tomp's members), 166 - // but it fails because Tomp takes (int,string,real). 167 - assert( !__traits(compiles, { 168 - class Tamp : Tomp 169 - { 170 - mixin SimpleConstructor; 171 - } 172 - }) ); 173 -} 174 - 175 -/// Mixing-in the MOST-DERIVED-member-wise comparator for a class 176 - 177 -/*mixin*/ 178 -template SimpleCompare() 179 -{ 180 - override bool opEquals(Object rhs_) const 181 - { 182 - if( auto rhs = cast(typeof(this))rhs_ ) 183 - { 184 - foreach(i,_; this.tupleof) 185 - if( this.tupleof[i] != rhs.tupleof[i] ) 186 - return false; 187 - return true; 188 - } 189 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 190 - } 191 - 192 - override hash_t toHash() const 193 - { 194 - hash_t h = 0; 195 - foreach(mem; this.tupleof) 196 - h += typeid(mem).getHash(&mem); 197 - return h; 198 - } 199 - 200 - override int opCmp(Object rhs_) const 201 - { 202 - if( auto rhs = cast(typeof(this))rhs_ ) 203 - { 204 - foreach(i,_; this.tupleof) 205 - if(auto c = typeid(_).compare(&this.tupleof[i],&rhs.tupleof[i])) 206 - return c; 207 - return 0; 208 - } 209 - assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_))); 210 - } 211 -} 212 - 213 -unittest 214 -{ 215 - class Temp 216 - { 217 - int x; 218 - string y; 219 - mixin SimpleConstructor; 220 - mixin SimpleCompare; 221 - } 222 - assert_eq( new Temp(1,"foo"), new Temp(1,"foo") ); 223 - assert_eq( (new Temp(1,"foo")).toHash, (new Temp(1,"foo")).toHash ); 224 - assert_ne( new Temp(1,"foo"), new Temp(2,"foo") ); 225 - assert_ne( new Temp(1,"foo"), new Temp(1,"bar") ); 226 - assert_gt( new Temp(1,"foo"), new Temp(1,"bar") ); 227 - assert_lt( new Temp(1,"foo"), new Temp(2,"bar") ); 228 - assert_ge( new Temp(1,"foo"), new Temp(1,"foo") ); 229 - 230 - class TempDummy 231 - { 232 - int x; 233 - string y; 234 - mixin SimpleConstructor; 235 - mixin SimpleCompare; 236 - } 237 - assert_throw!AssertError( new Temp(1,"foo") == new TempDummy(1,"foo") ); 238 - assert_throw!AssertError( new Temp(1,"foo") <= new TempDummy(1,"foo") ); 239 -} 240 - 241 -/// Mixing-in a simple toString method 242 - 243 -/*mixin*/ 244 -template SimpleToString() 245 -{ 246 - override string toString() 247 - { 248 - string str = sprintf!"%s("(typeof(this).stringof); 249 - foreach(i,mem; this.tupleof) 250 - { 251 - if(i) str ~= ","; 252 - static if( is(typeof(mem) == std.bigint.BigInt) ) 253 - str ~= std.bigint.toDecimalString(mem); 254 - else 255 - str ~= sprintf!"%s"(mem); 256 - } 257 - return str ~ ")"; 258 - } 259 -} 260 - 261 -version(unittest) import std.bigint; 262 -unittest 263 -{ 264 - class Temp 265 - { 266 - int x; 267 - string y; 268 - BigInt z; 269 - mixin SimpleConstructor; 270 - mixin SimpleToString; 271 - } 272 - assert_eq( (new Temp(1,"foo",BigInt(42))).toString(), "Temp(1,foo,42)" ); 273 -} 274 - 275 -/// Everything is in 276 - 277 -/*mixin*/ 278 -template SimpleClass() 279 -{ 280 - mixin SimpleConstructor; 281 - mixin SimpleCompare; 282 - mixin SimpleToString; 283 -}

Modified polemy/value.d from [b8f99f303d4d3a98] to [38155bcc400d812f].

1 -/** 1 +/** 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.value; 8 8 import polemy._common; ................................................................................ 11 11 /// Raised when something went wrong in runtime 12 12 13 13 class RuntimeException : Exception 14 14 { 15 15 const LexPosition pos; 16 16 17 17 this( const LexPosition pos, string msg ) 18 - { super(sprintf!"%s [%s]"(msg, pos)); this.pos = pos; } 19 - this( string msg ) { super(msg); this.pos = null; } 18 + { super(sprintf!"%s at [%s]"(msg, pos)); this.pos = pos; } 20 19 } 21 20 22 21 /// Runtime values of Polemy 23 22 24 23 abstract class Value 25 24 { 26 25 } ................................................................................ 63 62 class Table : Value 64 63 { 65 64 enum Kind {PropagateSet, NotPropagateSet}; 66 65 67 66 this( Table proto=null, Kind k = Kind.PropagateSet ) 68 67 { this.prototype = proto; this.kind = k; } 69 68 70 - void set(string i, Layer lay, Value v) 69 + void set(string i, Layer lay, Value v, in LexPosition pos=null) 71 70 { 72 - if( !setIfExist(i, lay, v) ) 73 - data[i][lay] = v; 71 + if( setIfExist(i, lay, v) ) 72 + return; 73 + data[i][lay] = v; 74 74 } 75 75 76 - Value get(string i, Layer lay) 76 + Value get(string i, Layer lay, in LexPosition pos=null) 77 77 { 78 78 if( i in data ) 79 79 return data[i][lay]; 80 80 if( prototype is null ) 81 - throw new RuntimeException(sprintf!"variable %s not found"(i)); 81 + throw new RuntimeException(pos, sprintf!"variable %s not found"(i)); 82 82 return prototype.get(i, lay); 83 83 } 84 84 85 85 private: 86 86 Table prototype; 87 87 Kind kind; 88 88 Value[Layer][string] data;

Added tricks/test.d version [bb5afea9b7b1423d]

1 +/** 2 + * Authors: k.inaba 3 + * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 + * 5 + * Unittest helpers. 6 + */ 7 +module tricks.test; 8 +import std.conv : to; 9 +import core.exception; 10 + 11 +/// Unittest helper that asserts an expression must throw something 12 + 13 +void assert_throw(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="") 14 +{ 15 + try 16 + { t(); } 17 + catch(ExceptionType) 18 + { return; } 19 + catch(Throwable e) 20 + { onAssertErrorMsg(fn, ln, msg.length ? msg : "exception ["~e.toString()~"]"); } 21 + onAssertErrorMsg(fn, ln, msg.length ? msg : "no execption"); 22 +} 23 + 24 +/// Unittest helper that asserts an expression must not throw anything 25 + 26 +auto assert_nothrow(T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="") 27 +{ 28 + try 29 + { return t(); } 30 + catch(Throwable e) 31 + { onAssertErrorMsg(fn, ln, msg.length ? msg : "exception ["~e.toString()~"]"); } 32 + assert(false); 33 +} 34 + 35 +unittest 36 +{ 37 + auto error = {throw new Error("hello");}; 38 + auto nothing = (){}; 39 + auto assertError = {assert(0);}; 40 + 41 + assert_nothrow ( assert_nothrow(nothing()) ); 42 + assert_throw!AssertError( assert_nothrow(error()) ); 43 + assert_throw!AssertError( assert_nothrow(assertError()) ); 44 + 45 + assert_nothrow ( assert_throw!Error(error()) ); 46 + assert_throw!AssertError( assert_throw!Error(nothing()) ); 47 + assert_nothrow ( assert_throw!Error(assertError()) ); 48 + assert_throw!AssertError( assert_throw!AssertError(error()) ); 49 +} 50 + 51 +/// Unittest helpers asserting two values are in some relation ==, !=, <, <=, >, >= 52 + 53 +template assertOp(string op) 54 +{ 55 + void assertOp(A, B, string fn=__FILE__, int ln=__LINE__)(A a, B b, string msg="") 56 + { 57 + try 58 + { if( mixin("a"~op~"b") ) return; } 59 + catch(Throwable e) 60 + { onAssertErrorMsg(fn, ln, msg.length ? msg : "exception ["~e.toString()~"]"); } 61 + onAssertErrorMsg(fn, ln, msg.length ? msg : to!string(a)~" !"~op~to!string(b)); 62 + } 63 +} 64 + 65 +alias assertOp!(`==`) assert_eq; 66 +alias assertOp!(`!=`) assert_ne; 67 +alias assertOp!(`<`) assert_lt; 68 +alias assertOp!(`<=`) assert_le; 69 +alias assertOp!(`>`) assert_gt; 70 +alias assertOp!(`>=`) assert_ge; 71 + 72 +unittest 73 +{ 74 + assert_nothrow( assert_eq(1, 1) ); 75 + assert_nothrow( assert_ne(1, 0) ); 76 + assert_nothrow( assert_lt(0, 1) ); 77 + assert_nothrow( assert_le(0, 1) ); 78 + assert_nothrow( assert_le(0, 0) ); 79 + assert_nothrow( assert_gt(1, 0) ); 80 + assert_nothrow( assert_ge(1, 0) ); 81 + assert_nothrow( assert_ge(0, 0) ); 82 + 83 + assert_throw!AssertError( assert_eq(1, 0) ); 84 + assert_throw!AssertError( assert_ne(1, 1) ); 85 + assert_throw!AssertError( assert_lt(1, 1) ); 86 + assert_throw!AssertError( assert_lt(1, 0) ); 87 + assert_throw!AssertError( assert_le(1, 0) ); 88 + assert_throw!AssertError( assert_gt(0, 0) ); 89 + assert_throw!AssertError( assert_gt(0, 1) ); 90 + assert_throw!AssertError( assert_ge(0, 1) ); 91 + 92 + class Temp { bool opEquals(int x){return x/x==x;} } 93 + assert_throw!AssertError( assert_eq(new Temp, 0) ); 94 + assert_nothrow ( assert_eq(new Temp, 1) ); 95 + assert_throw!AssertError( assert_eq(new Temp, 2) ); 96 +} 97 + 98 +/* [Todo] is there any way to clearnly implement "assert_compiles" and "assert_not_compile"? */

Modified tricks/tricks.d from [73906cba073bce6c] to [3f689d3451f8c1cc].

1 -/** 1 +/** 2 2 * Authors: k.inaba 3 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 4 * 5 5 * Common tricks and utilities for programming in D. 6 6 */ 7 -module polemy.tricks; 7 +module tricks.tricks; 8 +import tricks.test; 8 9 import std.array : appender; 9 10 import std.format : formattedWrite; 10 -import core.exception : onAssertErrorMsg, AssertError; 11 +import core.exception : AssertError; 11 12 12 13 /// Simple Wrapper for std.format.doFormat 13 14 14 15 string sprintf(string fmt, T...)(T params) 15 16 { 16 17 auto writer = appender!string(); 17 18 formattedWrite(writer, fmt, params); ................................................................................ 20 21 21 22 unittest 22 23 { 23 24 assert( sprintf!"%s == %d"("1+2", 3) == "1+2 == 3" ); 24 25 assert( sprintf!"%s == %04d"("1+2", 3) == "1+2 == 0003" ); 25 26 } 26 27 27 -/// Unittest helper that asserts an expression must throw something 28 +/// Create an exception with automatically completed filename and lineno information 28 29 29 -void assert_throw(ExceptionType, T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="") 30 +auto genex(ExceptionType, string fn=__FILE__, int ln=__LINE__, T...)(T params) 30 31 { 31 - try { 32 - t(); 33 - } catch(ExceptionType) { 34 - return; 35 - } catch(Throwable e) { 36 - onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e)); 37 - } 38 - onAssertErrorMsg(fn, ln, msg.length ? msg : "no execption"); 39 -} 40 - 41 -/// Unittest helper that asserts an expression must not throw anything 42 - 43 -void assert_nothrow(T, string fn=__FILE__, int ln=__LINE__)(lazy T t, string msg="") 44 -{ 45 - try { 46 - t(); 47 - } catch(Throwable e) { 48 - onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e)); 49 - } 32 + static if( T.length > 0 && is(T[$-1] : Throwable) ) 33 + return new ExceptionType(params[0..$-1], fn, ln, params[$-1]); 34 + else 35 + return new ExceptionType(params, fn, ln); 50 36 } 51 37 52 38 unittest 53 39 { 54 - auto error = {throw new Error("hello");}; 55 - auto nothing = (){}; 56 - auto assertError = {assert(0);}; 57 - 58 - assert_nothrow ( assert_nothrow(nothing()) ); 59 - assert_throw!AssertError( assert_nothrow(error()) ); 60 - assert_throw!AssertError( assert_nothrow(assertError()) ); 61 - 62 - assert_nothrow ( assert_throw!Error(error()) ); 63 - assert_throw!AssertError( assert_throw!Error(nothing()) ); 64 - assert_nothrow ( assert_throw!Error(assertError()) ); 65 - assert_throw!AssertError( assert_throw!AssertError(error()) ); 40 + assert_ne( genex!Exception("msg").file, "" ); 41 + assert_ne( genex!Exception("msg").line, 0 ); 42 + assert_ne( genex!Exception("msg",new Exception("bar")).next, Exception.init ); 66 43 } 67 44 68 -/// Unittest helpers asserting two values are in some relation ==, !=, <, <=, >, >= 69 - 70 -template assertOp(string op) 71 -{ 72 - void assertOp(A, B, string fn=__FILE__, int ln=__LINE__)(A a, B b, string msg="") 73 - { 74 - try { 75 - if( mixin("a"~op~"b") ) return; 76 - } catch(Throwable e) { 77 - onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"exception [%s]"(e)); 78 - } 79 - onAssertErrorMsg(fn, ln, msg.length ? msg : sprintf!"%s !%s %s"(a,op,b)); 80 - } 81 -} 82 - 83 -alias assertOp!(`==`) assert_eq; 84 -alias assertOp!(`!=`) assert_ne; 85 -alias assertOp!(`<`) assert_lt; 86 -alias assertOp!(`<=`) assert_le; 87 -alias assertOp!(`>`) assert_gt; 88 -alias assertOp!(`>=`) assert_ge; 89 - 90 -unittest 91 -{ 92 - assert_nothrow( assert_eq(1, 1) ); 93 - assert_nothrow( assert_ne(1, 0) ); 94 - assert_nothrow( assert_lt(0, 1) ); 95 - assert_nothrow( assert_le(0, 1) ); 96 - assert_nothrow( assert_le(0, 0) ); 97 - assert_nothrow( assert_gt(1, 0) ); 98 - assert_nothrow( assert_ge(1, 0) ); 99 - assert_nothrow( assert_ge(0, 0) ); 100 - 101 - assert_throw!AssertError( assert_eq(1, 0) ); 102 - assert_throw!AssertError( assert_ne(1, 1) ); 103 - assert_throw!AssertError( assert_lt(1, 1) ); 104 - assert_throw!AssertError( assert_lt(1, 0) ); 105 - assert_throw!AssertError( assert_le(1, 0) ); 106 - assert_throw!AssertError( assert_gt(0, 0) ); 107 - assert_throw!AssertError( assert_gt(0, 1) ); 108 - assert_throw!AssertError( assert_ge(0, 1) ); 109 - 110 - class Temp { bool opEquals(int x){return x/x==x;} } 111 - assert_throw!AssertError( assert_eq(new Temp, 0) ); 112 - assert_nothrow ( assert_eq(new Temp, 1) ); 113 - assert_throw!AssertError( assert_eq(new Temp, 2) ); 114 -} 115 - 116 -/* [Todo] is there any way to clearnly implement "assert_compiles" and "assert_not_compile"? */ 117 - 118 45 /// Mixing-in the bean constructor for a class 119 46 120 47 /*mixin*/ 121 48 template SimpleConstructor() 122 49 { 123 50 static if( is(typeof(super) == Object) || super.tupleof.length==0 ) 124 51 this( typeof(this.tupleof) params )