Index: d2stacktrace/stacktrace.d
==================================================================
--- d2stacktrace/stacktrace.d
+++ d2stacktrace/stacktrace.d
@@ -355,17 +355,17 @@
 
 					DWORD zeichen = 0;
 					if(Dbghelp.SymGetLineFromAddr64(hProcess,stackframe.AddrPC.Offset,&zeichen,&Line) == TRUE){
 						char[] fileName = new char[strlen(Line.FileName)];
 						fileName = std.path.basename( Line.FileName[0..fileName.length] );
-						lineStr = to!string(fileName ~ "::" ~ to!string(Line.LineNumber) ~ "(" ~ to!string(zeichen) ~ ") " ~ lineStr);
+						lineStr = text(fileName ~ "::" ~ text(Line.LineNumber) ~ "(" ~ text(zeichen) ~ ") " ~ lineStr);
 					}
 				}
 				else {
-					lineStr = to!string(cast(ulong)stackframe.AddrPC.Offset);
+					lineStr = text(cast(ulong)stackframe.AddrPC.Offset);
 				}
-				lineStr = to!string(frameNum-2) ~ " " ~ lineStr;
+				lineStr = text(frameNum-2) ~ " " ~ lineStr;
 				if(frameNum-2 < 10)
 					lineStr = "0" ~ lineStr;
 				if(frameNum >= 2)
 					stack.append(lineStr);
 			}

Index: polemy/_common.d
==================================================================
--- polemy/_common.d
+++ polemy/_common.d
@@ -1,16 +1,16 @@
 /**
  * Authors: k.inaba
  * License: NYSL 0.9982 http://www.kmonos.net/nysl/
  *
- * "Always-opend" modules inside Polemy.
+ * These modules are globaly used inside Polemy.
  */
 module polemy._common;
-public import std.array;
-public import std.range;
+public import tricks.test;
+public import tricks.tricks;
 public import std.algorithm;
-public import std.conv : to;
+public import std.array;
 public import std.bigint;
+public import std.conv : text;
 public import std.exception;
-public import tricks.tricks;
-public import tricks.test;
+public import std.range;
 public import std.stdio : writeln; // for debugging...

Index: polemy/eval.d
==================================================================
--- polemy/eval.d
+++ polemy/eval.d
@@ -11,39 +11,10 @@
 import polemy.parse;
 import polemy.value;
 import std.typecons;
 import std.stdio;
 
-// [todo] move to value.d
-
-FunValue nativef(Value delegate(immutable LexPosition pos, Layer lay, Value[] args) dg)
-{
-	return new FunValue(dg);
-}
-
-FunValue native(R,T...)(R delegate (T) dg)
-{
-	return nativef( delegate Value(immutable LexPosition pos, Layer lay, Value[] args) {
-		if( lay != "@v" )
-			throw genex!RuntimeException(pos, "only @v layer can call native function");
-		if( T.length != args.length )
-			throw genex!RuntimeException(pos, "argument number mismatch!");
-		T typed_args;
-		foreach(i, Ti; T)
-		{
-			typed_args[i] = cast(Ti) args[i];
-			if( typed_args[i] is null )
-				throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1));
-		}
-		try {
-			return dg(typed_args);
-		} catch( RuntimeException e ) {
-			throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e;
-		}
-	});
-}
-
 ///
 Table createGlobalContext()
 {
 	auto ctx = new Table;
 	ctx.set("+", "@v", native( (IntValue lhs, IntValue rhs){return new IntValue(lhs.data + rhs.data);} ));
@@ -76,10 +47,25 @@
 	}));
 	ctx.set("_isint", "@v", native( (Value v){return new IntValue(BigInt(cast(IntValue)v is null ? 0 : 1));} ));
 	ctx.set("_isstr", "@v", native( (Value v){return new IntValue(BigInt(cast(StrValue)v is null ? 0 : 1));} ));
 	ctx.set("_isfun", "@v", native( (Value v){return new IntValue(BigInt(cast(FunValue)v is null ? 0 : 1));} ));
 	ctx.set("_isundefined", "@v", native( (Value v){return new IntValue(BigInt(cast(UndValue)v is null ? 0 : 1));} ));
+	ctx.set("_istable", "@v", native( (Value v){return new IntValue(BigInt(cast(Table)v is null ? 0 : 1));} ));
+	ctx.set(".", "@v", native( (Table t, StrValue s){
+		return (t.has(s.data, "@v") ? t.get(s.data, "@v") : new UndValue);
+	}) );
+	ctx.set(".?", "@v", native( (Table t, StrValue s){
+		return new IntValue(BigInt(t.has(s.data, "@v") ? 1 : 0));
+	}) );
+	ctx.set(".=", "@v", native( (Table t, StrValue s, Value v){
+		auto t2 = new Table(t, Table.Kind.NotPropagateSet);
+		t2.set(s.data, "@v", v);
+		return t2;
+	}) );
+	ctx.set("{}", "@v", native( (){
+		return new Table;
+	}) );
 	return ctx;
 }
 
 /// Entry point of this module
 
@@ -259,6 +245,6 @@
 }
 
 unittest
 {
 	assert_eq( evalString(`@@t = fun(x){x+1}; @t(123)`).val, new IntValue(BigInt(124)) );
-}
+}

Index: polemy/lex.d
==================================================================
--- polemy/lex.d
+++ polemy/lex.d
@@ -52,11 +52,11 @@
 	auto p = new LexPosition("hello.cpp", 123, 45);
 
 	assert_eq( p.filename, "hello.cpp" );
 	assert_eq( p.lineno, 123 );
 	assert_eq( p.column, 45 );
-	assert_eq( to!string(p), "hello.cpp:123:45" );
+	assert_eq( text(p), "hello.cpp:123:45" );
 
 	assert( !__traits(compiles, new LexPosition) );
 	assert( !__traits(compiles, p.filename="foo") );
 	assert( !__traits(compiles, p.lineno  =789) );
 	assert( !__traits(compiles, p.column  =222) );
@@ -413,11 +413,11 @@
 				buffer.popFront;
 			c = '\n';
 		}
 		if( c=='\n' )
 		{
-			lineno ++;
+			lineno ++;	
 			column = 1;
 		}
 		else
 			column ++;
 	}

Index: polemy/parse.d
==================================================================
--- polemy/parse.d
+++ polemy/parse.d
@@ -165,11 +165,12 @@
 		["&"],
 		["<<", ">>"],
 		["+","-"],
 		["~"],
 		["*","/","%"],
-		["^^","**"]
+		["^^","**"],
+		[".",".?"]
 	];
 
 	AST E(size_t level)
 	{
 		/// Expression ::= (Binary left-associative operators over) Funcall
@@ -180,10 +181,14 @@
 				return lhs;
 
 			auto pos = currentPosition();
 			foreach(op; operator_perferences[level])
 				if( tryEat(op) )
+					if( op[0]=='.' )
+						return rec(
+							new FuncallExpression(lhs.pos, new VarExpression(pos, op), lhs, parseId()));
+					else
 					return rec(
 						new FuncallExpression(lhs.pos, new VarExpression(pos, op), lhs, E(level+1)));
 			return lhs;
 		}
 
@@ -243,10 +248,30 @@
 		if( tryEat("(") )
 		{
 			auto e = Body();
 			eat(")", "after parenthesized expression");
 			return e;
+		}
+		if( tryEat("{") )
+		{
+			AST e = new FuncallExpression(pos, new VarExpression(pos,"{}"));
+			if( tryEat("}") )
+				return e;
+			for(;;)
+			{
+				string key = eatId("for table key", AllowQuoted);
+				eat(":", "after table key");
+				AST val = E(0);
+				e = new FuncallExpression(pos, new VarExpression(pos,".="),
+						e, new StrLiteral(pos,key), val);
+				if( !tryEat(",") )
+				{
+					eat("}", "for the end of table literal");
+					break;
+				}
+			}
+			return e;
 		}
 		if( tryEat("if") )
 		{
 			eat("(", "after if");
 			auto cond = E(0);
@@ -275,10 +300,16 @@
 			return parseLambdaAfterOpenParen(pos);
 		}
 		scope(exit) lex.popFront;
 		return new VarExpression(pos, lex.front.str);
 	}
+
+	AST parseId()
+	{
+		scope(exit) lex.popFront;
+		return new StrLiteral(currentPosition(), lex.front.str);
+	}
 
 	AST parseLambdaAfterOpenParen(immutable LexPosition pos)
 	{
 		Parameter[] params;
 		while( !tryEat(")") )
@@ -436,6 +467,12 @@
 			var("foo"))
 	);
 
 	assert_eq(parseString(`@@type ( x ) { x }`),
 		let("@type", "(system)", fun(["x"], var("x")), var("@type")) );
+
+	assert_eq(parseString(`{}`), call(var("{}")));
+	assert_eq(parseString(`{foo:1,"bar":2}`),
+		call(var(".="), call(var(".="), call(var("{}")), strl("foo"), intl(1)), strl("bar"), intl(2)));
+	assert_eq(parseString(`{}.foo`), call(var("."),call(var("{}")),strl("foo")));
+	assert_eq(parseString(`{}.?foo`), call(var(".?"),call(var("{}")),strl("foo")));
 }

Index: polemy/value.d
==================================================================
--- polemy/value.d
+++ polemy/value.d
@@ -19,40 +19,75 @@
 
 abstract class Value
 {
 }
 
+///
 class IntValue : Value
 {
 	BigInt data;
 
 	mixin SimpleClass;
 	override string toString() const { return std.bigint.toDecimalString(cast(BigInt)data); }
 }
 
+///
 class StrValue : Value
 {
 	string data;
 
 	mixin SimpleClass;
 	override string toString() const { return data; }
 }
 
+///
 class FunValue : Value
 {
 	Value delegate(immutable LexPosition pos, string lay, Value[]) data;
 
 	mixin SimpleConstructor;
 	alias data call;
 	override string toString() const { return sprintf!"(function:%s:%s)"(data.ptr,data.funcptr); }
 }
 
+///
 class UndValue : Value
 {
 	mixin SimpleClass;
 	override string toString() const { return "<undefined>"; }
 }
+
+/// Named Constructor for FunValue
+
+FunValue nativef(Value delegate(immutable LexPosition pos, Layer lay, Value[] args) dg)
+{
+	return new FunValue(dg);
+}
+
+/// Named Constructor for FunValue
+
+FunValue native(R,T...)(R delegate (T) dg)
+{
+	return nativef( delegate Value(immutable LexPosition pos, Layer lay, Value[] args) {
+		if( lay != "@v" )
+			throw genex!RuntimeException(pos, "only @v layer can call native function");
+		if( T.length != args.length )
+			throw genex!RuntimeException(pos, "argument number mismatch!");
+		T typed_args;
+		foreach(i, Ti; T)
+		{
+			typed_args[i] = cast(Ti) args[i];
+			if( typed_args[i] is null )
+				throw genex!RuntimeException(pos, sprintf!"type mismatch on the argument %d"(i+1));
+		}
+		try {
+			return dg(typed_args);
+		} catch( RuntimeException e ) {
+			throw e.pos is null ? new RuntimeException(pos, e.msg, e.file, e.line) : e;
+		}
+	});
+}
 
 /// Layer ID
 
 alias string Layer;
 
@@ -72,13 +107,26 @@
 		if( setIfExist(i, lay, v) )
 			return;
 		data[i][lay] = v;
 	}
 
+	bool has(string i, Layer lay, in LexPosition pos=null)
+	{
+		if( i in data ) {
+			if( lay !in data[i] )
+				return false;
+			return true;
+		}
+		if( prototype is null )
+			return false;
+		return prototype.has(i, lay, pos);
+	}
+	
 	Value get(string i, Layer lay, in LexPosition pos=null)
 	{
 		if( i in data ) {
+			// [TODO] consider forwarding to proto also in this case
 			if( lay !in data[i] )
 				throw genex!RuntimeException(pos, sprintf!"variable %s is not set in layer %s"(i,lay));
 			return data[i][lay];
 		}
 		if( prototype is null )

Index: readme.txt
==================================================================
--- readme.txt
+++ readme.txt
@@ -1,18 +1,18 @@
 -----------------------------------------------------------------------------
   Polemy 0.1.0
                                                  by k.inaba (www.kmonos.net)
-                                                                Nov 8, 2010
+                                                               Nov 20, 2010
 -----------------------------------------------------------------------------
 
 
 
 <<How to Build>>
 
   - Install DMD
       http://www.digitalmars.com/d/2.0/changelog.html
-    Version 2.050 is recommended. Older and/or newer version may not work.
+    Version 2.050 is recommended. Older or newer version may not work.
 
   - Build
       (for Windows) Run build.bat
       (for Unix) Run build.sh
       or use your favorite build tools upon main.d and polemy/*.d.
@@ -42,35 +42,90 @@
 <<How to Use>>
 
   > polemy
       starts REPL
 
-  > polemy foo.pmy
-      executes foo.pmy
-
+  > polemy foo.pmy
+      executes foo.pmy
+
+  > polemy -l foo.pmy
+      after executing foo.pmy, starts REPL
+
 
 
-<<Memo of Language Spec>>
-
-syntax
-
- E ::= ("var"|"let"|"def"|LAYER) ID "=" E ; E
-     | "fun" "(" PARAMS ")" "{" E "}"
-     | E "(" ARGS ")"
+<<Syntax>>
+
+ Comment is "# ... \n"
 
-     | LAYER "(" E ")"
-
-     | "(" E ")"
-     | E BINOP E
-     | "if" "(" E ")" "{" E "}"
-     | "if" "(" E ")" "{" E "}" "else "{" E "}"
-     | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}"
-
-ARGS ::= ","-separated E's
-PARAMS ::= ","-separated VAR's
-LAYER ::= "@" ID
-
-if-then-else is a syntax sugar for a function call: if( E, fun(){E}, fun(){E} )
-binary ops (e.g., E + E) is a syntax sugar: +(E, E)
-
-comment is "# ... \n"
-
+ E ::=
+   // declaration
+     | ("var"|"let"|"def"|LAYER) ID "=" E (";"|"in") E
+     | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}" (";"|"in") E
+     | ("var"|"let"|"def"|LAYER) ID "=" E
+     | ("var"|"let"|"def"|LAYER) ID "(" PARAMS ")" "{" E "}"
+   // literal
+     | INTEGER
+	 | STRING
+	 | "{" ENTRYS "}"
+     | "fun" "(" PARAMS ")" "{" E "}"
+   // function call
+     | E "(" ARGS")"
+	     where ARGS ::= E "," ... "," E
+	         PARAMS ::= ID LAYER* "," ... "," ID LAYER*
+			 ENTRYS ::= ID ":" E  "," ... "," ID ":" E
+                 ID ::= 'a-zA-Z0-9_...'+
+              LAYER ::= "@" ID
+   // operators
+     | "(" E ")"
+	 | E "." ID
+	 | E ".?" ID
+     | E BINOP E
+     | "if" "(" E ")" "{" E "}"
+     | "if" "(" E ")" "{" E "}" "else "{" E "}"
+   // layered exec
+     | LAYER "(" E ")"
+
+The following are actually rewritten to function calls:
+
+  - if (E) then{E} else{E} ==> if( E, fun(){E}, fun(){E} )
+  - E BINOP E              ==> BINOP(E, E)
+  - E.ID                   ==> . (E, ID)
+  - E.?ID                  ==> .?(E, ID)
+  - {}                     ==> {}()
+  - {ID:E, ...}            ==> .=({...}, ID, E)
+
+Several styles of variable declaration can be used:
+
+  - fun(x){ fun(y){x} }               # K-combinator
+  - fun(x){ let f = fun(y){x} in f }  # let-in style
+  - fun(x){ var f = fun(y){x}; f }    # var-;  style
+  - fun(x){ def f = fun(y){x} in f }  # you can use any combination of (let|var|def)-(;|in)
+  - fun(x){ def f(y){x} in f } # syntax sugar for function declaration
+  - fun(x){ let f(y){x}; f }   # this is also ok
+  - fun(x){ var f(y){x} }      # omitting (;|in) returns the last declared object directly
+  - fun(x,y){x} #< this is not equal to the above ones. functions are no curried.
+
+NOTE: Theres no "let rec" syntax, but still recursive definition works
+    def f(x) { if(x==0){1}else{x*f(x-1)} } in f(10)  #=> 3628800
+  yet still the code below also works
+    def x=21 in def x=x+x in x  #=> 42.
+  The internal scoping mechanism is a little tricky (this is for coping with
+  the "layer" feature explained below), but I hope that it works as everyone
+  expects in most cases, as long as you don't use the same-name-variables heavily :).
+
+
+
+<<Basic Features>>
+
+  Polemy is an untyped functional programming language that has
+   - integers:   0, 123, 456666666666666666666666666666666666666789, ...
+   - strings:    "hello, world!\n", ...
+   - tables:     {car: 1, cdr: {car: 2, cdr: {}}}
+   - functions:  fun(x){x+1}
+  as primitive datatypes. Functions capture lexical closures.
+  It is almost 'pure' (except the primitve function "print" and some
+  trick inside scoping mechanisms).
+
+
+<<Layer>>
+
+ to be written

Index: tricks/test.d
==================================================================
--- tricks/test.d
+++ tricks/test.d
@@ -1,50 +1,59 @@
 /**
  * Authors: k.inaba
  * License: NYSL 0.9982 http://www.kmonos.net/nysl/
  *
- * Unittest helpers.
- * TODO: use stderr instead of stdout. the problem is that std.cstream is xxxx....
- * TODO: is there any way to clearnly implement "assert_compiles" and "assert_not_compile"?
+ * Hepler routines for unittesting.
+ * TODO: Is there any clean way to implement "assert_compiles" and "assert_not_compile"?
  */
 module tricks.test;
-import std.conv : to;
+import std.conv : text;
 import core.exception;
 
 version(unittest)
 {
-	import std.stdio;
+	import std.cstream;
 	import core.runtime;
 
-	// Install custom test runner
 	static this()
 	{
+		installCustomTestRunner();
+	}
+
+	private void installCustomTestRunner()
+	{
 		Runtime.moduleUnitTester = function()
 		{
-			Throwable ee = null;
-			size_t failed=0;
-			foreach(m; ModuleInfo) if(m) if(auto fp=m.unitTest)
+			Throwable firstError = null;
+
+			void logError(Throwable e)
+			{
+				if(firstError is null)
+					firstError = e;
+				derr.writefln("  !! %s(%d): %s", e.file, e.line, e.msg);
+			}
+
+			void testModule(ModuleInfo* m, void function() test)
 			{
-				writeln("[TEST] ", m.name);
-				try {
-					fp();
-				} catch( Throwable e ) {
-					if(ee is null)
-						ee = e;
-					failed++;
-					writeln("  !! ",e.file,"(",e.line,"): ",e.msg);
-				}
+				derr.writefln("[TEST] %s", m.name);
+				try { test(); } catch( Throwable e ) { logError(e); }
 			}
-			if(ee !is null)
+
+			bool report()
 			{
-				writeln("[TEST] ",failed," modules failed. The first error was:");
-				writeln(ee);
-				write("[TEST] press enter to exit.");
-				readln();
+				if(firstError is null)
+					return true;
+				derr.writefln("[TEST] The first error was:\n%s", firstError);
+				derr.writeString("[TEST] press enter to exit.");
+				din.readLine();
 				return false;
 			}
-			return true;
+
+			foreach(m; ModuleInfo)
+				if(m && m.unitTest)
+					testModule(m, m.unitTest);
+			return report();
 		};
 	}
 }
 
 /// Unittest helper that asserts an expression must throw something
@@ -99,11 +108,11 @@
 	{
 		try
 			{ if( mixin("a"~op~"b") ) return; }
 		catch(Throwable e)
 			{ onAssertErrorMsg(fn, ln, msg.length ? msg : "bad exception \n  >> "~e.toString()); }
-		onAssertErrorMsg(fn, ln, msg.length ? msg : to!string(a)~" !"~op~" "~to!string(b));
+		onAssertErrorMsg(fn, ln, msg.length ? msg : text(a, " !", op, " ", b));
 	}
 }
 
 alias assertOp!(`==`) assert_eq; /// asserts two operands are ==
 alias assertOp!(`!=`) assert_ne; /// asserts two operands are !=

Index: tricks/tricks.d
==================================================================
--- tricks/tricks.d
+++ tricks/tricks.d
@@ -4,13 +4,13 @@
  *
  * Common tricks and utilities for programming in D.
  */
 module tricks.tricks;
 import tricks.test;
-import std.array      : appender;
-import std.format     : formattedWrite;
-import core.exception;
+import core.exception;
+import std.array  : appender;
+import std.format : formattedWrite;
 import std.traits;
 import std.typetuple;
 
 /// Simple Wrapper for std.format.doFormat
 
@@ -108,11 +108,11 @@
 	override bool opEquals(Object rhs_) const /// member-by-member equality
 	{
 		if( auto rhs = cast(typeof(this))rhs_ )
 		{
 			foreach(i,_; this.tupleof)
-				if( this.tupleof[i] != rhs.tupleof[i] )
+				if( this.tupleof[i] != (cast(const)rhs).tupleof[i] )
 					return false;
 			return true;
 		}
 		assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_)));
 	}
@@ -128,15 +128,16 @@
 	override int opCmp(Object rhs_) const /// member-by-member compare
 	{
 		if( auto rhs = cast(typeof(this))rhs_ )
 		{
 			foreach(i,_; this.tupleof)
-				if( this.tupleof[i] != rhs.tupleof[i] ) {
-					auto a = this.tupleof[i];
+				if( this.tupleof[i] != (cast(const)rhs).tupleof[i] ) {
+					auto a = (cast(SC_Unqual!(typeof(this)))this).tupleof[i];
 					auto b =  rhs.tupleof[i];
-					return cast(SC_Unqual!(typeof(a)))a < b ? -1 : +1;
-				}
+					return a < b ? -1 : +1;
+				}
+// not work well for structures???????
 //				if(auto c = typeid(_).compare(&this.tupleof[i],&rhs.tupleof[i]))
 //					return c;
 			return 0;
 		}
 		assert(false, sprintf!"Cannot compare %s with %s"(typeid(this), typeid(rhs_)));
@@ -321,11 +322,11 @@
 	class D2 : Base {
 		string s;
 		mixin SimpleConstructor;
 	}
 	class D3 : Base {
-		int[int]m;
+		int[int] m;
 		mixin SimpleConstructor;
 	}
 
 	Base d1 = new D1(1, 2.3);
 	Base d2 = new D2("foobar");
@@ -332,62 +333,62 @@
 	Base d3 = new D3(null); (cast(D3)d3).m[1]=10;
 
 	// normal dispatch
 	assert_eq( d1.match(
 		(D1 x){return 1;},
-		(D2 x){return 2;},
+		(D2 x){return 2;}
 	), 1);
 	assert_eq( d2.match(
 		(D1 x){return 1;},
-		(D2 x){return 2;},
+		(D2 x){return 2;}
 	), 2);
 	assert_throw!AssertError( d3.match(
 		(D1 x){return 1;},
-		(D2 x){return 2;},
+		(D2 x){return 2;}
 	));
 	assert_eq( d3.match(
 		(D1 x){return 1;},
 		(D2 x){return 2;},
-		(Base x){return 3;},
+		(Base x){return 3;}
 	), 3);
 	assert_eq( d2.match(
 		(D1 x){return 1;},
 		(D2 x){return 2;},
-		(Base x){return 3;},
+		(Base x){return 3;}
 	), 2);
 	assert_eq( d2.match(
 		(D1 x){return 1;},
 		(Base x){return 3;},
-		(D2 x){return 2;},
+		(D2 x){return 2;}
 	), 3);
 
 	// member decomposing match
 	assert_eq( d1.match(
 		when!(D1, (x, y){return x + cast(int)y;}),
 		when!(D2, (x){return x.length;}),
-		when!(D3, (x){return x[1];}),
+		when!(D3, (x){return x[1];})
 	), 3);
 	assert_eq( d2.match(
 		when!(D1, (x, y){return x + cast(int)y;}),
 		when!(D2, (x){return x.length;}),
-		when!(D3, (x){return x[1];}),
+		when!(D3, (x){return x[1];})
 	), 6);
 	assert_eq( d3.match(
 		when!(D1, (x, y){return x + cast(int)y;}),
 		when!(D2, (x){return x.length;}),
-		when!(D3, (x){return x[1];}),
+		when!(D3, (x){return x[1];})
 	), 10);
 	assert_throw!AssertError( d3.match(
 		when!(D1, (x, y){return x + cast(int)y;}),
-		when!(D2, (x){return x.length;}),
+		when!(D2, (x){return x.length;})
 	));
 	assert_eq( d2.match(
 		when!(D1, (x, y){return x + cast(int)y;}),
 		when!(D2, (x){return x.length;}),
-		otherwise!({return 999;}),
+		otherwise!({return 999;})
 	), 6);
 	assert_eq( d2.match(
 		when!(D1, (x, y){return x + cast(int)y;}),
 		otherwise!({return 999;}),
-		when!(D2, (x){return x.length;}),
+		when!(D2, (x){return x.length;})
 	), 999);
 }