Check-in [515502e8d1]
Not logged in
Overview
SHA1 Hash:515502e8d1fa4b18993621b1ed16e936b4675d5e
Date: 2010-11-20 18:20:03
User: kinaba
Comment:table get, init, ask expressions addded
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 [2d470e3c95d4cfbd] to [9e66870b7d120c42].

353 if(isOK) 353 if(isOK) 354 lineStr ~= demangledName; 354 lineStr ~= demangledName; 355 355 356 DWORD zeichen = 0; 356 DWORD zeichen = 0; 357 if(Dbghelp.SymGetLineFromAddr64(hProcess 357 if(Dbghelp.SymGetLineFromAddr64(hProcess 358 char[] fileName = new char[strle 358 char[] fileName = new char[strle 359 fileName = std.path.basename( Li 359 fileName = std.path.basename( Li 360 lineStr = to!string(fileName ~ " | 360 lineStr = text(fileName ~ "::" ~ 361 } 361 } 362 } 362 } 363 else { 363 else { 364 lineStr = to!string(cast(ulong)stackfram | 364 lineStr = text(cast(ulong)stackframe.Add 365 } 365 } 366 lineStr = to!string(frameNum-2) ~ " " ~ lineStr; | 366 lineStr = text(frameNum-2) ~ " " ~ lineStr; 367 if(frameNum-2 < 10) 367 if(frameNum-2 < 10) 368 lineStr = "0" ~ lineStr; 368 lineStr = "0" ~ lineStr; 369 if(frameNum >= 2) 369 if(frameNum >= 2) 370 stack.append(lineStr); 370 stack.append(lineStr); 371 } 371 } 372 } 372 } 373 373 374 free(Symbol); 374 free(Symbol); 375 return stack; 375 return stack; 376 } 376 } 377 }; 377 }; 378 378

Modified polemy/_common.d from [7abcb8181e6c0ff0] to [ae51765dfb783149].

1 /** 1 /** 2 * Authors: k.inaba 2 * Authors: k.inaba 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 * 4 * 5 * "Always-opend" modules inside Polemy. | 5 * These modules are globaly used inside Polemy. 6 */ 6 */ 7 module polemy._common; 7 module polemy._common; 8 public import std.array; | 8 public import tricks.test; 9 public import std.range; | 9 public import tricks.tricks; 10 public import std.algorithm; 10 public import std.algorithm; 11 public import std.conv : to; | 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.exception; 14 public import std.exception; 14 public import tricks.tricks; < 15 public import tricks.test; | 15 public import std.range; 16 public import std.stdio : writeln; // for debugging... 16 public import std.stdio : writeln; // for debugging...

Modified polemy/eval.d from [5c2f449580dd9555] to [6db0ce492da06d00].

9 import polemy.lex : LexPosition; 9 import polemy.lex : LexPosition; 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 std.typecons; 13 import std.typecons; 14 import std.stdio; 14 import std.stdio; 15 15 16 // [todo] move to value.d < 17 < 18 FunValue nativef(Value delegate(immutable LexPosition pos, Layer lay, Value[] ar < 19 { < 20 return new FunValue(dg); < 21 } < 22 < 23 FunValue native(R,T...)(R delegate (T) dg) < 24 { < 25 return nativef( delegate Value(immutable LexPosition pos, Layer lay, Val < 26 if( lay != "@v" ) < 27 throw genex!RuntimeException(pos, "only @v layer can cal < 28 if( T.length != args.length ) < 29 throw genex!RuntimeException(pos, "argument number misma < 30 T typed_args; < 31 foreach(i, Ti; T) < 32 { < 33 typed_args[i] = cast(Ti) args[i]; < 34 if( typed_args[i] is null ) < 35 throw genex!RuntimeException(pos, sprintf!"type < 36 } < 37 try { < 38 return dg(typed_args); < 39 } catch( RuntimeException e ) { < 40 throw e.pos is null ? new RuntimeException(pos, e.msg, e < 41 } < 42 }); < 43 } < 44 < 45 /// 16 /// 46 Table createGlobalContext() 17 Table createGlobalContext() 47 { 18 { 48 auto ctx = new Table; 19 auto ctx = new Table; 49 ctx.set("+", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa 20 ctx.set("+", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa 50 ctx.set("-", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa 21 ctx.set("-", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa 51 ctx.set("*", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa 22 ctx.set("*", "@v", native( (IntValue lhs, IntValue rhs){return new IntVa ................................................................................................................................................................................ 74 return (x.data == 0 ? fe : ft).call(pos,lay,[]); 45 return (x.data == 0 ? fe : ft).call(pos,lay,[]); 75 throw genex!RuntimeException(pos, "type mismatch in if"); 46 throw genex!RuntimeException(pos, "type mismatch in if"); 76 })); 47 })); 77 ctx.set("_isint", "@v", native( (Value v){return new IntValue(BigInt(cas 48 ctx.set("_isint", "@v", native( (Value v){return new IntValue(BigInt(cas 78 ctx.set("_isstr", "@v", native( (Value v){return new IntValue(BigInt(cas 49 ctx.set("_isstr", "@v", native( (Value v){return new IntValue(BigInt(cas 79 ctx.set("_isfun", "@v", native( (Value v){return new IntValue(BigInt(cas 50 ctx.set("_isfun", "@v", native( (Value v){return new IntValue(BigInt(cas 80 ctx.set("_isundefined", "@v", native( (Value v){return new IntValue(BigI 51 ctx.set("_isundefined", "@v", native( (Value v){return new IntValue(BigI > 52 ctx.set("_istable", "@v", native( (Value v){return new IntValue(BigInt(c > 53 ctx.set(".", "@v", native( (Table t, StrValue s){ > 54 return (t.has(s.data, "@v") ? t.get(s.data, "@v") : new UndValue > 55 }) ); > 56 ctx.set(".?", "@v", native( (Table t, StrValue s){ > 57 return new IntValue(BigInt(t.has(s.data, "@v") ? 1 : 0)); > 58 }) ); > 59 ctx.set(".=", "@v", native( (Table t, StrValue s, Value v){ > 60 auto t2 = new Table(t, Table.Kind.NotPropagateSet); > 61 t2.set(s.data, "@v", v); > 62 return t2; > 63 }) ); > 64 ctx.set("{}", "@v", native( (){ > 65 return new Table; > 66 }) ); 81 return ctx; 67 return ctx; 82 } 68 } 83 69 84 /// Entry point of this module 70 /// Entry point of this module 85 71 86 Tuple!(Value,"val",Table,"ctx") evalString(S,T...)(S str, T fn_ln_cn) 72 Tuple!(Value,"val",Table,"ctx") evalString(S,T...)(S str, T fn_ln_cn) 87 { 73 {

Modified polemy/lex.d from [a4ea515a0f014c9c] to [f9cdaf211a0e9fb0].

50 unittest 50 unittest 51 { 51 { 52 auto p = new LexPosition("hello.cpp", 123, 45); 52 auto p = new LexPosition("hello.cpp", 123, 45); 53 53 54 assert_eq( p.filename, "hello.cpp" ); 54 assert_eq( p.filename, "hello.cpp" ); 55 assert_eq( p.lineno, 123 ); 55 assert_eq( p.lineno, 123 ); 56 assert_eq( p.column, 45 ); 56 assert_eq( p.column, 45 ); 57 assert_eq( to!string(p), "hello.cpp:123:45" ); | 57 assert_eq( text(p), "hello.cpp:123:45" ); 58 58 59 assert( !__traits(compiles, new LexPosition) ); 59 assert( !__traits(compiles, new LexPosition) ); 60 assert( !__traits(compiles, p.filename="foo") ); 60 assert( !__traits(compiles, p.filename="foo") ); 61 assert( !__traits(compiles, p.lineno =789) ); 61 assert( !__traits(compiles, p.lineno =789) ); 62 assert( !__traits(compiles, p.column =222) ); 62 assert( !__traits(compiles, p.column =222) ); 63 63 64 auto q = new LexPosition("hello.cpp", 123, 46); 64 auto q = new LexPosition("hello.cpp", 123, 46);

Modified polemy/parse.d from [7ed0053850ffa032] to [6bec0997c5764737].

163 ["|"], 163 ["|"], 164 ["^"], 164 ["^"], 165 ["&"], 165 ["&"], 166 ["<<", ">>"], 166 ["<<", ">>"], 167 ["+","-"], 167 ["+","-"], 168 ["~"], 168 ["~"], 169 ["*","/","%"], 169 ["*","/","%"], 170 ["^^","**"] | 170 ["^^","**"], > 171 [".",".?"] 171 ]; 172 ]; 172 173 173 AST E(size_t level) 174 AST E(size_t level) 174 { 175 { 175 /// Expression ::= (Binary left-associative operators over) Func 176 /// Expression ::= (Binary left-associative operators over) Func 176 177 177 AST rec(AST lhs) 178 AST rec(AST lhs) ................................................................................................................................................................................ 178 { 179 { 179 if( closingBracket() ) 180 if( closingBracket() ) 180 return lhs; 181 return lhs; 181 182 182 auto pos = currentPosition(); 183 auto pos = currentPosition(); 183 foreach(op; operator_perferences[level]) 184 foreach(op; operator_perferences[level]) 184 if( tryEat(op) ) 185 if( tryEat(op) ) > 186 if( op[0]=='.' ) > 187 return rec( > 188 new FuncallExpression(lh > 189 else 185 return rec( 190 return rec( 186 new FuncallExpression(lhs.pos, n 191 new FuncallExpression(lhs.pos, n 187 return lhs; 192 return lhs; 188 } 193 } 189 194 190 if( operator_perferences.length <= level ) 195 if( operator_perferences.length <= level ) 191 return Funcall(); 196 return Funcall(); ................................................................................................................................................................................ 241 return new LayeredExpression(pos, lay, e); 246 return new LayeredExpression(pos, lay, e); 242 } 247 } 243 if( tryEat("(") ) 248 if( tryEat("(") ) 244 { 249 { 245 auto e = Body(); 250 auto e = Body(); 246 eat(")", "after parenthesized expression"); 251 eat(")", "after parenthesized expression"); 247 return e; 252 return e; > 253 } > 254 if( tryEat("{") ) > 255 { > 256 AST e = new FuncallExpression(pos, new VarExpression(pos > 257 if( tryEat("}") ) > 258 return e; > 259 for(;;) > 260 { > 261 string key = eatId("for table key", AllowQuoted) > 262 eat(":", "after table key"); > 263 AST val = E(0); > 264 e = new FuncallExpression(pos, new VarExpression > 265 e, new StrLiteral(pos,key), val) > 266 if( !tryEat(",") ) > 267 { > 268 eat("}", "for the end of table literal") > 269 break; > 270 } > 271 } > 272 return e; 248 } 273 } 249 if( tryEat("if") ) 274 if( tryEat("if") ) 250 { 275 { 251 eat("(", "after if"); 276 eat("(", "after if"); 252 auto cond = E(0); 277 auto cond = E(0); 253 eat(")", "after if condition"); 278 eat(")", "after if condition"); 254 auto thenPos = lex.front.pos; 279 auto thenPos = lex.front.pos; ................................................................................................................................................................................ 273 { 298 { 274 eat("(", "after fun"); 299 eat("(", "after fun"); 275 return parseLambdaAfterOpenParen(pos); 300 return parseLambdaAfterOpenParen(pos); 276 } 301 } 277 scope(exit) lex.popFront; 302 scope(exit) lex.popFront; 278 return new VarExpression(pos, lex.front.str); 303 return new VarExpression(pos, lex.front.str); 279 } 304 } > 305 > 306 AST parseId() > 307 { > 308 scope(exit) lex.popFront; > 309 return new StrLiteral(currentPosition(), lex.front.str); > 310 } 280 311 281 AST parseLambdaAfterOpenParen(immutable LexPosition pos) 312 AST parseLambdaAfterOpenParen(immutable LexPosition pos) 282 { 313 { 283 Parameter[] params; 314 Parameter[] params; 284 while( !tryEat(")") ) 315 while( !tryEat(")") ) 285 { 316 { 286 params ~= parseParam(); 317 params ~= parseParam(); ................................................................................................................................................................................ 434 let("foo", "", 465 let("foo", "", 435 fun(["x"], call(var("+"), var("x"), intl(1))), 466 fun(["x"], call(var("+"), var("x"), intl(1))), 436 var("foo")) 467 var("foo")) 437 ); 468 ); 438 469 439 assert_eq(parseString(`@@type ( x ) { x }`), 470 assert_eq(parseString(`@@type ( x ) { x }`), 440 let("@type", "(system)", fun(["x"], var("x")), var("@type")) ); 471 let("@type", "(system)", fun(["x"], var("x")), var("@type")) ); > 472 > 473 assert_eq(parseString(`{}`), call(var("{}"))); > 474 assert_eq(parseString(`{foo:1,"bar":2}`), > 475 call(var(".="), call(var(".="), call(var("{}")), strl("foo"), in > 476 assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo > 477 assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("f 441 } 478 }

Modified polemy/value.d from [fe3f0c39a200a0bc] to [a4c75e644b34fb64].

17 17 18 /// Runtime values of Polemy 18 /// Runtime values of Polemy 19 19 20 abstract class Value 20 abstract class Value 21 { 21 { 22 } 22 } 23 23 > 24 /// 24 class IntValue : Value 25 class IntValue : Value 25 { 26 { 26 BigInt data; 27 BigInt data; 27 28 28 mixin SimpleClass; 29 mixin SimpleClass; 29 override string toString() const { return std.bigint.toDecimalString(cas 30 override string toString() const { return std.bigint.toDecimalString(cas 30 } 31 } 31 32 > 33 /// 32 class StrValue : Value 34 class StrValue : Value 33 { 35 { 34 string data; 36 string data; 35 37 36 mixin SimpleClass; 38 mixin SimpleClass; 37 override string toString() const { return data; } 39 override string toString() const { return data; } 38 } 40 } 39 41 > 42 /// 40 class FunValue : Value 43 class FunValue : Value 41 { 44 { 42 Value delegate(immutable LexPosition pos, string lay, Value[]) data; 45 Value delegate(immutable LexPosition pos, string lay, Value[]) data; 43 46 44 mixin SimpleConstructor; 47 mixin SimpleConstructor; 45 alias data call; 48 alias data call; 46 override string toString() const { return sprintf!"(function:%s:%s)"(dat 49 override string toString() const { return sprintf!"(function:%s:%s)"(dat 47 } 50 } 48 51 > 52 /// 49 class UndValue : Value 53 class UndValue : Value 50 { 54 { 51 mixin SimpleClass; 55 mixin SimpleClass; 52 override string toString() const { return "<undefined>"; } 56 override string toString() const { return "<undefined>"; } 53 } 57 } > 58 > 59 /// Named Constructor for FunValue > 60 > 61 FunValue nativef(Value delegate(immutable LexPosition pos, Layer lay, Value[] ar > 62 { > 63 return new FunValue(dg); > 64 } > 65 > 66 /// Named Constructor for FunValue > 67 > 68 FunValue native(R,T...)(R delegate (T) dg) > 69 { > 70 return nativef( delegate Value(immutable LexPosition pos, Layer lay, Val > 71 if( lay != "@v" ) > 72 throw genex!RuntimeException(pos, "only @v layer can cal > 73 if( T.length != args.length ) > 74 throw genex!RuntimeException(pos, "argument number misma > 75 T typed_args; > 76 foreach(i, Ti; T) > 77 { > 78 typed_args[i] = cast(Ti) args[i]; > 79 if( typed_args[i] is null ) > 80 throw genex!RuntimeException(pos, sprintf!"type > 81 } > 82 try { > 83 return dg(typed_args); > 84 } catch( RuntimeException e ) { > 85 throw e.pos is null ? new RuntimeException(pos, e.msg, e > 86 } > 87 }); > 88 } 54 89 55 /// Layer ID 90 /// Layer ID 56 91 57 alias string Layer; 92 alias string Layer; 58 93 59 /// Context (variable environment) 94 /// Context (variable environment) 60 /// Simlar to prototype chain of ECMAScript etc. 95 /// Simlar to prototype chain of ECMAScript etc. ................................................................................................................................................................................ 69 104 70 void set(string i, Layer lay, Value v, in LexPosition pos=null) 105 void set(string i, Layer lay, Value v, in LexPosition pos=null) 71 { 106 { 72 if( setIfExist(i, lay, v) ) 107 if( setIfExist(i, lay, v) ) 73 return; 108 return; 74 data[i][lay] = v; 109 data[i][lay] = v; 75 } 110 } > 111 > 112 bool has(string i, Layer lay, in LexPosition pos=null) > 113 { > 114 if( i in data ) { > 115 if( lay !in data[i] ) > 116 return false; > 117 return true; > 118 } > 119 if( prototype is null ) > 120 return false; > 121 return prototype.has(i, lay, pos); > 122 } 76 123 77 Value get(string i, Layer lay, in LexPosition pos=null) 124 Value get(string i, Layer lay, in LexPosition pos=null) 78 { 125 { 79 if( i in data ) { 126 if( i in data ) { > 127 // [TODO] consider forwarding to proto also in this case 80 if( lay !in data[i] ) 128 if( lay !in data[i] ) 81 throw genex!RuntimeException(pos, sprintf!"varia 129 throw genex!RuntimeException(pos, sprintf!"varia 82 return data[i][lay]; 130 return data[i][lay]; 83 } 131 } 84 if( prototype is null ) 132 if( prototype is null ) 85 throw new RuntimeException(pos, sprintf!"variable %s not 133 throw new RuntimeException(pos, sprintf!"variable %s not 86 return prototype.get(i, lay, pos); 134 return prototype.get(i, lay, pos);

Modified readme.txt from [7d7a59abebf26f18] to [b45d599d08f18ee0].

1 ----------------------------------------------------------------------------- 1 ----------------------------------------------------------------------------- 2 Polemy 0.1.0 2 Polemy 0.1.0 3 by k.inaba (www.kmonos.net) 3 by k.inaba (www.kmonos.net) 4 Nov 8, 2010 | 4 Nov 20, 2010 5 ----------------------------------------------------------------------------- 5 ----------------------------------------------------------------------------- 6 6 7 7 8 8 9 <<How to Build>> 9 <<How to Build>> 10 10 11 - Install DMD 11 - Install DMD 12 http://www.digitalmars.com/d/2.0/changelog.html 12 http://www.digitalmars.com/d/2.0/changelog.html 13 Version 2.050 is recommended. Older and/or newer version may not work. | 13 Version 2.050 is recommended. Older or newer version may not work. 14 14 15 - Build 15 - Build 16 (for Windows) Run build.bat 16 (for Windows) Run build.bat 17 (for Unix) Run build.sh 17 (for Unix) Run build.sh 18 or use your favorite build tools upon main.d and polemy/*.d. 18 or use your favorite build tools upon main.d and polemy/*.d. 19 19 20 Then you will get the executable "polemy" in the "bin" directory. 20 Then you will get the executable "polemy" in the "bin" directory. ................................................................................................................................................................................ 43 43 44 > polemy 44 > polemy 45 starts REPL 45 starts REPL 46 46 47 > polemy foo.pmy 47 > polemy foo.pmy 48 executes foo.pmy 48 executes foo.pmy 49 49 > 50 > polemy -l foo.pmy > 51 after executing foo.pmy, starts REPL 50 52 51 53 52 <<Memo of Language Spec>> < 53 54 54 syntax | 55 <<Syntax>> 55 56 > 57 Comment is "# ... \n" > 58 > 59 E ::= > 60 // declaration > 61 | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E > 62 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E 56 E ::= ("var"|"let"|"def"|LAYER) ID "=" E ; E | 63 | ("var"|"let"|"def"|LAYER) ID "=" E > 64 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" > 65 // literal > 66 | INTEGER > 67 | STRING > 68 | "{" ENTRYS "}" 57 | "fun" "(" PARAMS ")" "{" E "}" 69 | "fun" "(" PARAMS ")" "{" E "}" > 70 // function call 58 | E "(" ARGS ")" | 71 | E "(" ARGS")" 59 < > 72 where ARGS ::= E "," ... "," E > 73 PARAMS ::= ID LAYER* "," ... "," ID LAYER* > 74 ENTRYS ::= ID ":" E "," ... "," ID ":" E > 75 ID ::= 'a-zA-Z0-9_...'+ 60 | LAYER "(" E ")" | 76 LAYER ::= "@" ID 61 < > 77 // operators 62 | "(" E ")" 78 | "(" E ")" > 79 | E "." ID > 80 | E ".?" ID 63 | E BINOP E 81 | E BINOP E 64 | "if" "(" E ")" "{" E "}" 82 | "if" "(" E ")" "{" E "}" 65 | "if" "(" E ")" "{" E "}" "else "{" E "}" 83 | "if" "(" E ")" "{" E "}" "else "{" E "}" 66 | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" | 84 // layered exec > 85 | LAYER "(" E ")" > 86 > 87 The following are actually rewritten to function calls: > 88 > 89 - if (E) then{E} else{E} ==> if( E, fun(){E}, fun(){E} ) > 90 - E BINOP E ==> BINOP(E, E) > 91 - E.ID ==> . (E, ID) > 92 - E.?ID ==> .?(E, ID) > 93 - {} ==> {}() > 94 - {ID:E, ...} ==> .=({...}, ID, E) > 95 > 96 Several styles of variable declaration can be used: > 97 > 98 - fun(x){ fun(y){x} } # K-combinator > 99 - fun(x){ let f = fun(y){x} in f } # let-in style > 100 - fun(x){ var f = fun(y){x}; f } # var-; style > 101 - fun(x){ def f = fun(y){x} in f } # you can use any combination of (let|var| > 102 - fun(x){ def f(y){x} in f } # syntax sugar for function declaration > 103 - fun(x){ let f(y){x}; f } # this is also ok > 104 - fun(x){ var f(y){x} } # omitting (;|in) returns the last declared objec > 105 - fun(x,y){x} #< this is not equal to the above ones. functions are no curried > 106 > 107 NOTE: Theres no "let rec" syntax, but still recursive definition works > 108 def f(x) { if(x==0){1}else{x*f(x-1)} } in f(10) #=> 3628800 > 109 yet still the code below also works > 110 def x=21 in def x=x+x in x #=> 42. > 111 The internal scoping mechanism is a little tricky (this is for coping with > 112 the "layer" feature explained below), but I hope that it works as everyone > 113 expects in most cases, as long as you don't use the same-name-variables heavil > 114 > 115 67 116 68 ARGS ::= ","-separated E's | 117 <<Basic Features>> 69 PARAMS ::= ","-separated VAR's < 70 LAYER ::= "@" ID < 71 118 72 if-then-else is a syntax sugar for a function call: if( E, fun(){E}, fun(){E} ) | 119 Polemy is an untyped functional programming language that has 73 binary ops (e.g., E + E) is a syntax sugar: +(E, E) | 120 - integers: 0, 123, 456666666666666666666666666666666666666789, ... > 121 - strings: "hello, world!\n", ... > 122 - tables: {car: 1, cdr: {car: 2, cdr: {}}} > 123 - functions: fun(x){x+1} > 124 as primitive datatypes. Functions capture lexical closures. > 125 It is almost 'pure' (except the primitve function "print" and some > 126 trick inside scoping mechanisms). > 127 74 128 75 comment is "# ... \n" | 129 <<Layer>> 76 130 > 131 to be written

Modified tricks/test.d from [fc21831342965670] to [b9b84a35fccc5116].

1 /** 1 /** 2 * Authors: k.inaba 2 * Authors: k.inaba 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 * 4 * 5 * Unittest helpers. | 5 * Hepler routines for unittesting. 6 * TODO: use stderr instead of stdout. the problem is that std.cstream is xxxx.. < 7 * TODO: is there any way to clearnly implement "assert_compiles" and "assert_no | 6 * TODO: Is there any clean way to implement "assert_compiles" and "assert_not_c 8 */ 7 */ 9 module tricks.test; 8 module tricks.test; 10 import std.conv : to; | 9 import std.conv : text; 11 import core.exception; 10 import core.exception; 12 11 13 version(unittest) 12 version(unittest) 14 { 13 { 15 import std.stdio; | 14 import std.cstream; 16 import core.runtime; 15 import core.runtime; 17 16 18 // Install custom test runner < 19 static this() 17 static this() 20 { 18 { > 19 installCustomTestRunner(); > 20 } > 21 > 22 private void installCustomTestRunner() > 23 { 21 Runtime.moduleUnitTester = function() 24 Runtime.moduleUnitTester = function() 22 { 25 { > 26 Throwable firstError = null; > 27 23 Throwable ee = null; | 28 void logError(Throwable e) 24 size_t failed=0; < 25 foreach(m; ModuleInfo) if(m) if(auto fp=m.unitTest) < > 29 { > 30 if(firstError is null) > 31 firstError = e; > 32 derr.writefln(" !! %s(%d): %s", e.file, e.line, > 33 } > 34 > 35 void testModule(ModuleInfo* m, void function() test) 26 { 36 { 27 writeln("[TEST] ", m.name); | 37 derr.writefln("[TEST] %s", m.name); 28 try { < 29 fp(); < 30 } catch( Throwable e ) { | 38 try { test(); } catch( Throwable e ) { logError( 31 if(ee is null) < 32 ee = e; < 33 failed++; < 34 writeln(" !! ",e.file,"(",e.line,"): ", < 35 } < 36 } 39 } 37 if(ee !is null) < > 40 > 41 bool report() 38 { 42 { 39 writeln("[TEST] ",failed," modules failed. The f | 43 if(firstError is null) 40 writeln(ee); | 44 return true; > 45 derr.writefln("[TEST] The first error was:\n%s", 41 write("[TEST] press enter to exit."); | 46 derr.writeString("[TEST] press enter to exit."); 42 readln(); < > 47 din.readLine(); 43 return false; 48 return false; 44 } 49 } > 50 > 51 foreach(m; ModuleInfo) > 52 if(m && m.unitTest) > 53 testModule(m, m.unitTest); 45 return true; | 54 return report(); 46 }; 55 }; 47 } 56 } 48 } 57 } 49 58 50 /// Unittest helper that asserts an expression must throw something 59 /// Unittest helper that asserts an expression must throw something 51 60 52 void assert_throw(ExcT=Throwable, T, string fn=__FILE__, size_t ln=__LINE__)(laz 61 void assert_throw(ExcT=Throwable, T, string fn=__FILE__, size_t ln=__LINE__)(laz ................................................................................................................................................................................ 97 { 106 { 98 void assertOp(A, B, string fn=__FILE__, size_t ln=__LINE__)(A a, B b, st 107 void assertOp(A, B, string fn=__FILE__, size_t ln=__LINE__)(A a, B b, st 99 { 108 { 100 try 109 try 101 { if( mixin("a"~op~"b") ) return; } 110 { if( mixin("a"~op~"b") ) return; } 102 catch(Throwable e) 111 catch(Throwable e) 103 { onAssertErrorMsg(fn, ln, msg.length ? msg : "bad excep 112 { onAssertErrorMsg(fn, ln, msg.length ? msg : "bad excep 104 onAssertErrorMsg(fn, ln, msg.length ? msg : to!string(a)~" !"~op | 113 onAssertErrorMsg(fn, ln, msg.length ? msg : text(a, " !", op, " 105 } 114 } 106 } 115 } 107 116 108 alias assertOp!(`==`) assert_eq; /// asserts two operands are == 117 alias assertOp!(`==`) assert_eq; /// asserts two operands are == 109 alias assertOp!(`!=`) assert_ne; /// asserts two operands are != 118 alias assertOp!(`!=`) assert_ne; /// asserts two operands are != 110 alias assertOp!(`<`) assert_lt; /// asserts two operands are < 119 alias assertOp!(`<`) assert_lt; /// asserts two operands are < 111 alias assertOp!(`<=`) assert_le; /// asserts two operands are <= 120 alias assertOp!(`<=`) assert_le; /// asserts two operands are <=

Modified tricks/tricks.d from [d1500d1519df592c] to [0eae6cc37f045c97].

2 * Authors: k.inaba 2 * Authors: k.inaba 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 3 * License: NYSL 0.9982 http://www.kmonos.net/nysl/ 4 * 4 * 5 * Common tricks and utilities for programming in D. 5 * Common tricks and utilities for programming in D. 6 */ 6 */ 7 module tricks.tricks; 7 module tricks.tricks; 8 import tricks.test; 8 import tricks.test; 9 import std.array : appender; < 10 import std.format : formattedWrite; < 11 import core.exception; 9 import core.exception; > 10 import std.array : appender; > 11 import std.format : formattedWrite; 12 import std.traits; 12 import std.traits; 13 import std.typetuple; 13 import std.typetuple; 14 14 15 /// Simple Wrapper for std.format.doFormat 15 /// Simple Wrapper for std.format.doFormat 16 16 17 string sprintf(string fmt, T...)(T params) 17 string sprintf(string fmt, T...)(T params) 18 { 18 { ................................................................................................................................................................................ 106 template SimpleCompare() 106 template SimpleCompare() 107 { 107 { 108 override bool opEquals(Object rhs_) const /// member-by-member equality 108 override bool opEquals(Object rhs_) const /// member-by-member equality 109 { 109 { 110 if( auto rhs = cast(typeof(this))rhs_ ) 110 if( auto rhs = cast(typeof(this))rhs_ ) 111 { 111 { 112 foreach(i,_; this.tupleof) 112 foreach(i,_; this.tupleof) 113 if( this.tupleof[i] != rhs.tupleof[i] ) | 113 if( this.tupleof[i] != (cast(const)rhs).tupleof[ 114 return false; 114 return false; 115 return true; 115 return true; 116 } 116 } 117 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), 117 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), 118 } 118 } 119 119 120 override hash_t toHash() const /// member-by-member hash 120 override hash_t toHash() const /// member-by-member hash ................................................................................................................................................................................ 126 } 126 } 127 127 128 override int opCmp(Object rhs_) const /// member-by-member compare 128 override int opCmp(Object rhs_) const /// member-by-member compare 129 { 129 { 130 if( auto rhs = cast(typeof(this))rhs_ ) 130 if( auto rhs = cast(typeof(this))rhs_ ) 131 { 131 { 132 foreach(i,_; this.tupleof) 132 foreach(i,_; this.tupleof) 133 if( this.tupleof[i] != rhs.tupleof[i] ) { | 133 if( this.tupleof[i] != (cast(const)rhs).tupleof[ 134 auto a = this.tupleof[i]; | 134 auto a = (cast(SC_Unqual!(typeof(this))) 135 auto b = rhs.tupleof[i]; 135 auto b = rhs.tupleof[i]; 136 return cast(SC_Unqual!(typeof(a)))a < b | 136 return a < b ? -1 : +1; 137 } 137 } > 138 // not work well for structures??????? 138 // if(auto c = typeid(_).compare(&this.tupleof[i],& 139 // if(auto c = typeid(_).compare(&this.tupleof[i],& 139 // return c; 140 // return c; 140 return 0; 141 return 0; 141 } 142 } 142 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), 143 assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), 143 } 144 } 144 } 145 } ................................................................................................................................................................................ 319 mixin SimpleConstructor; 320 mixin SimpleConstructor; 320 } 321 } 321 class D2 : Base { 322 class D2 : Base { 322 string s; 323 string s; 323 mixin SimpleConstructor; 324 mixin SimpleConstructor; 324 } 325 } 325 class D3 : Base { 326 class D3 : Base { 326 int[int]m; | 327 int[int] m; 327 mixin SimpleConstructor; 328 mixin SimpleConstructor; 328 } 329 } 329 330 330 Base d1 = new D1(1, 2.3); 331 Base d1 = new D1(1, 2.3); 331 Base d2 = new D2("foobar"); 332 Base d2 = new D2("foobar"); 332 Base d3 = new D3(null); (cast(D3)d3).m[1]=10; 333 Base d3 = new D3(null); (cast(D3)d3).m[1]=10; 333 334 334 // normal dispatch 335 // normal dispatch 335 assert_eq( d1.match( 336 assert_eq( d1.match( 336 (D1 x){return 1;}, 337 (D1 x){return 1;}, 337 (D2 x){return 2;}, | 338 (D2 x){return 2;} 338 ), 1); 339 ), 1); 339 assert_eq( d2.match( 340 assert_eq( d2.match( 340 (D1 x){return 1;}, 341 (D1 x){return 1;}, 341 (D2 x){return 2;}, | 342 (D2 x){return 2;} 342 ), 2); 343 ), 2); 343 assert_throw!AssertError( d3.match( 344 assert_throw!AssertError( d3.match( 344 (D1 x){return 1;}, 345 (D1 x){return 1;}, 345 (D2 x){return 2;}, | 346 (D2 x){return 2;} 346 )); 347 )); 347 assert_eq( d3.match( 348 assert_eq( d3.match( 348 (D1 x){return 1;}, 349 (D1 x){return 1;}, 349 (D2 x){return 2;}, 350 (D2 x){return 2;}, 350 (Base x){return 3;}, | 351 (Base x){return 3;} 351 ), 3); 352 ), 3); 352 assert_eq( d2.match( 353 assert_eq( d2.match( 353 (D1 x){return 1;}, 354 (D1 x){return 1;}, 354 (D2 x){return 2;}, 355 (D2 x){return 2;}, 355 (Base x){return 3;}, | 356 (Base x){return 3;} 356 ), 2); 357 ), 2); 357 assert_eq( d2.match( 358 assert_eq( d2.match( 358 (D1 x){return 1;}, 359 (D1 x){return 1;}, 359 (Base x){return 3;}, 360 (Base x){return 3;}, 360 (D2 x){return 2;}, | 361 (D2 x){return 2;} 361 ), 3); 362 ), 3); 362 363 363 // member decomposing match 364 // member decomposing match 364 assert_eq( d1.match( 365 assert_eq( d1.match( 365 when!(D1, (x, y){return x + cast(int)y;}), 366 when!(D1, (x, y){return x + cast(int)y;}), 366 when!(D2, (x){return x.length;}), 367 when!(D2, (x){return x.length;}), 367 when!(D3, (x){return x[1];}), | 368 when!(D3, (x){return x[1];}) 368 ), 3); 369 ), 3); 369 assert_eq( d2.match( 370 assert_eq( d2.match( 370 when!(D1, (x, y){return x + cast(int)y;}), 371 when!(D1, (x, y){return x + cast(int)y;}), 371 when!(D2, (x){return x.length;}), 372 when!(D2, (x){return x.length;}), 372 when!(D3, (x){return x[1];}), | 373 when!(D3, (x){return x[1];}) 373 ), 6); 374 ), 6); 374 assert_eq( d3.match( 375 assert_eq( d3.match( 375 when!(D1, (x, y){return x + cast(int)y;}), 376 when!(D1, (x, y){return x + cast(int)y;}), 376 when!(D2, (x){return x.length;}), 377 when!(D2, (x){return x.length;}), 377 when!(D3, (x){return x[1];}), | 378 when!(D3, (x){return x[1];}) 378 ), 10); 379 ), 10); 379 assert_throw!AssertError( d3.match( 380 assert_throw!AssertError( d3.match( 380 when!(D1, (x, y){return x + cast(int)y;}), 381 when!(D1, (x, y){return x + cast(int)y;}), 381 when!(D2, (x){return x.length;}), | 382 when!(D2, (x){return x.length;}) 382 )); 383 )); 383 assert_eq( d2.match( 384 assert_eq( d2.match( 384 when!(D1, (x, y){return x + cast(int)y;}), 385 when!(D1, (x, y){return x + cast(int)y;}), 385 when!(D2, (x){return x.length;}), 386 when!(D2, (x){return x.length;}), 386 otherwise!({return 999;}), | 387 otherwise!({return 999;}) 387 ), 6); 388 ), 6); 388 assert_eq( d2.match( 389 assert_eq( d2.match( 389 when!(D1, (x, y){return x + cast(int)y;}), 390 when!(D1, (x, y){return x + cast(int)y;}), 390 otherwise!({return 999;}), 391 otherwise!({return 999;}), 391 when!(D2, (x){return x.length;}), | 392 when!(D2, (x){return x.length;}) 392 ), 999); 393 ), 999); 393 } 394 }