changeset 1577:e4f7b5d9c68a

DMD 2.032 Merge.
author Robert Clipsham <robert@octarineparrot.com>
date Tue, 08 Sep 2009 10:07:56 +0100
parents 4551475bc6b6
children 1dee66f6ec0b
files dmd2/arrayop.c dmd2/attrib.c dmd2/attrib.h dmd2/cast.c dmd2/class.c dmd2/constfold.c dmd2/cppmangle.c dmd2/declaration.c dmd2/declaration.h dmd2/doc.c dmd2/dsymbol.c dmd2/dsymbol.h dmd2/expression.c dmd2/expression.h dmd2/func.c dmd2/id.c dmd2/id.h dmd2/idgen.c dmd2/impcnvtab.c dmd2/init.c dmd2/inline.c dmd2/interpret.c dmd2/lexer.c dmd2/lexer.h dmd2/mangle.c dmd2/mars.c dmd2/mars.h dmd2/mtype.c dmd2/mtype.h dmd2/optimize.c dmd2/parse.c dmd2/root/response.c dmd2/root/root.c dmd2/statement.c dmd2/statement.h dmd2/template.c gen/classes.cpp gen/tollvm.cpp
diffstat 38 files changed, 1736 insertions(+), 590 deletions(-) [+]
line wrap: on
line diff
--- a/dmd2/arrayop.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/arrayop.c	Tue Sep 08 10:07:56 2009 +0100
@@ -333,6 +333,17 @@
     arguments->shift(this);
 }
 
+void CastExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
+{
+    Type *tb = type->toBasetype();
+    if (tb->ty == Tarray || tb->ty == Tsarray)
+    {
+	e1->buildArrayIdent(buf, arguments);
+    }
+    else
+	Expression::buildArrayIdent(buf, arguments);
+}
+
 void SliceExp::buildArrayIdent(OutBuffer *buf, Expressions *arguments)
 {
     buf->writestring("Slice");
@@ -417,6 +428,17 @@
     return e;
 }
 
+Expression *CastExp::buildArrayLoop(Arguments *fparams)
+{
+    Type *tb = type->toBasetype();
+    if (tb->ty == Tarray || tb->ty == Tsarray)
+    {
+	return e1->buildArrayLoop(fparams);
+    }
+    else
+	Expression::buildArrayLoop(fparams);
+}
+
 Expression *SliceExp::buildArrayLoop(Arguments *fparams)
 {
     Identifier *id = Identifier::generateId("p", fparams->dim);
@@ -435,12 +457,14 @@
     /* Evaluate assign expressions right to left
      */
     Expression *ex2 = e2->buildArrayLoop(fparams);
+#if DMDV2
     /* Need the cast because:
      *   b = c + p[i];
      * where b is a byte fails because (c + p[i]) is an int
      * which cannot be implicitly cast to byte.
      */
     ex2 = new CastExp(0, ex2, e1->type->nextOf());
+#endif
     Expression *ex1 = e1->buildArrayLoop(fparams);
     Argument *param = (Argument *)fparams->data[0];
     param->storageClass = 0;
--- a/dmd2/attrib.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/attrib.c	Tue Sep 08 10:07:56 2009 +0100
@@ -77,6 +77,41 @@
     return m;
 }
 
+void AttribDeclaration::setScopeNewSc(Scope *sc,
+	unsigned stc, enum LINK linkage, enum PROT protection, int explicitProtection,
+	unsigned structalign)
+{
+    if (decl)
+    {
+	Scope *newsc = sc;
+	if (stc != sc->stc ||
+	    linkage != sc->linkage ||
+	    protection != sc->protection ||
+	    explicitProtection != sc->explicitProtection ||
+	    structalign != sc->structalign)
+	{
+	    // create new one for changes
+	    newsc = new Scope(*sc);
+	    newsc->flags &= ~SCOPEfree;
+	    newsc->stc = stc;
+	    newsc->linkage = linkage;
+	    newsc->protection = protection;
+	    newsc->explicitProtection = explicitProtection;
+	    newsc->structalign = structalign;
+	}
+	for (unsigned i = 0; i < decl->dim; i++)
+	{   Dsymbol *s = (Dsymbol *)decl->data[i];
+
+	    s->setScope(newsc);	// yes, the only difference from semanticNewSc()
+	}
+	if (newsc != sc)
+	{
+	    sc->offset = newsc->offset;
+	    newsc->pop();
+	}
+    }
+}
+
 void AttribDeclaration::semanticNewSc(Scope *sc,
 	unsigned stc, enum LINK linkage, enum PROT protection, int explicitProtection,
 	unsigned structalign)
@@ -340,11 +375,33 @@
     return scd;
 }
 
+void StorageClassDeclaration::setScope(Scope *sc)
+{
+    if (decl)
+    {
+	unsigned scstc = sc->stc;
+
+	/* These sets of storage classes are mutually exclusive,
+	 * so choose the innermost or most recent one.
+	 */
+	if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
+	    scstc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
+	if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
+	    scstc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
+	if (stc & (STCconst | STCimmutable | STCmanifest))
+	    scstc &= ~(STCconst | STCimmutable | STCmanifest);
+	if (stc & (STCgshared | STCshared | STCtls))
+	    scstc &= ~(STCgshared | STCshared | STCtls);
+	scstc |= stc;
+
+	setScopeNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
+    }
+}
+
 void StorageClassDeclaration::semantic(Scope *sc)
 {
     if (decl)
     {
-#if 1
 	unsigned scstc = sc->stc;
 
 	/* These sets of storage classes are mutually exclusive,
@@ -361,29 +418,6 @@
 	scstc |= stc;
 
 	semanticNewSc(sc, scstc, sc->linkage, sc->protection, sc->explicitProtection, sc->structalign);
-#else
-	unsigned stc_save = sc->stc;
-
-	/* These sets of storage classes are mutually exclusive,
-	 * so choose the innermost or most recent one.
-	 */
-	if (stc & (STCauto | STCscope | STCstatic | STCextern | STCmanifest))
-	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCextern | STCmanifest);
-	if (stc & (STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared))
-	    sc->stc &= ~(STCauto | STCscope | STCstatic | STCtls | STCmanifest | STCgshared);
-	if (stc & (STCconst | STCimmutable | STCmanifest))
-	    sc->stc &= ~(STCconst | STCimmutable | STCmanifest);
-	if (stc & (STCgshared | STCshared | STCtls))
-	    sc->stc &= ~(STCgshared | STCshared | STCtls);
-	sc->stc |= stc;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->stc = stc_save;
-#endif
     }
 }
 
@@ -402,22 +436,24 @@
 	{ STCstatic,       TOKstatic },
 	{ STCextern,       TOKextern },
 	{ STCconst,        TOKconst },
-	{ STCimmutable,    TOKimmutable },
-	{ STCshared,       TOKshared },
 	{ STCfinal,        TOKfinal },
 	{ STCabstract,     TOKabstract },
 	{ STCsynchronized, TOKsynchronized },
 	{ STCdeprecated,   TOKdeprecated },
 	{ STCoverride,     TOKoverride },
+	{ STClazy,         TOKlazy },
+	{ STCalias,        TOKalias },
+	{ STCout,          TOKout },
+	{ STCin,           TOKin },
+#if DMDV2
+	{ STCimmutable,    TOKimmutable },
+	{ STCshared,       TOKshared },
 	{ STCnothrow,      TOKnothrow },
 	{ STCpure,         TOKpure },
 	{ STCref,          TOKref },
 	{ STCtls,          TOKtls },
 	{ STCgshared,      TOKgshared },
-	{ STClazy,         TOKlazy },
-	{ STCalias,        TOKalias },
-	{ STCout,          TOKout },
-	{ STCin,           TOKin },
+#endif
     };
 
     for (int i = 0; i < sizeof(table)/sizeof(table[0]); i++)
@@ -454,25 +490,21 @@
     return ld;
 }
 
+void LinkDeclaration::setScope(Scope *sc)
+{
+    //printf("LinkDeclaration::setScope(linkage = %d, decl = %p)\n", linkage, decl);
+    if (decl)
+    {
+	setScopeNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
+    }
+}
+
 void LinkDeclaration::semantic(Scope *sc)
 {
     //printf("LinkDeclaration::semantic(linkage = %d, decl = %p)\n", linkage, decl);
     if (decl)
     {
-#if 1
 	semanticNewSc(sc, sc->stc, linkage, sc->protection, sc->explicitProtection, sc->structalign);
-#else
-	enum LINK linkage_save = sc->linkage;
-
-	sc->linkage = linkage;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->linkage = linkage_save;
-#endif
     }
 }
 
@@ -544,27 +576,19 @@
     return pd;
 }
 
+void ProtDeclaration::setScope(Scope *sc)
+{
+    if (decl)
+    {
+	setScopeNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
+    }
+}
+
 void ProtDeclaration::semantic(Scope *sc)
 {
     if (decl)
     {
-#if 1
 	semanticNewSc(sc, sc->stc, sc->linkage, protection, 1, sc->structalign);
-#else
-	enum PROT protection_save = sc->protection;
-	int explicitProtection_save = sc->explicitProtection;
-
-	sc->protection = protection;
-	sc->explicitProtection = 1;
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-	    s->semantic(sc);
-	}
-	sc->protection = protection_save;
-	sc->explicitProtection = explicitProtection_save;
-#endif
     }
 }
 
@@ -611,44 +635,21 @@
     return ad;
 }
 
+void AlignDeclaration::setScope(Scope *sc)
+{
+    //printf("\tAlignDeclaration::setScope '%s'\n",toChars());
+    if (decl)
+    {
+	setScopeNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
+    }
+}
+
 void AlignDeclaration::semantic(Scope *sc)
 {
-// LDC
-// we only support packed structs, as from the spec: align(1) struct Packed { ... }
-// other alignments are simply ignored. my tests show this is what llvm-gcc does too ...
-
     //printf("\tAlignDeclaration::semantic '%s'\n",toChars());
     if (decl)
     {
-#if 1
 	semanticNewSc(sc, sc->stc, sc->linkage, sc->protection, sc->explicitProtection, salign);
-#else
-	unsigned salign_save = sc->structalign;
-
-#if IN_DMD
-	sc->structalign = salign;
-#endif
-	for (unsigned i = 0; i < decl->dim; i++)
-	{
-	    Dsymbol *s = (Dsymbol *)decl->data[i];
-
-#if IN_LLVM
-        if (s->isStructDeclaration() && salign == 1)
-        {
-            sc->structalign = salign;
-            s->semantic(sc);
-            sc->structalign = salign_save;
-        }
-        else
-        {
-#endif
-            s->semantic(sc);
-#if IN_LLVM
-        }
-#endif
-	}
-	sc->structalign = salign_save;
-#endif
     }
     else
     assert(0 && "what kind of align use triggers this?");
@@ -870,6 +871,39 @@
     return pd;
 }
 
+void PragmaDeclaration::setScope(Scope *sc)
+{
+#if TARGET_NET
+    if (ident == Lexer::idPool("assembly"))
+    {
+        if (!args || args->dim != 1)
+        {
+            error("pragma has invalid number of arguments");
+        }
+        else
+        {
+            Expression *e = (Expression *)args->data[0];
+            e = e->semantic(sc);
+            e = e->optimize(WANTvalue | WANTinterpret);
+            args->data[0] = (void *)e;
+            if (e->op != TOKstring)
+            {
+                error("string expected, not '%s'", e->toChars());
+            }
+            PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast<StringExp*>(e));
+
+            assert(sc);
+            pragma->setScope(sc);
+
+            //add to module members
+            assert(sc->module);
+            assert(sc->module->members);
+            sc->module->members->push(pragma);
+        }
+    }
+#endif // TARGET_NET
+}
+
 void PragmaDeclaration::semantic(Scope *sc)
 {   // Should be merged with PragmaStatement
 
@@ -892,7 +926,7 @@
 		if (e->op == TOKstring)
 		{
 		    StringExp *se = (StringExp *)e;
-		    fprintf(stdmsg, "%.*s", (int)se->len, (char*)se->string);
+		    fprintf(stdmsg, "%.*s", (int)se->len, (char *)se->string);
 		}
 		else
 		    error("string expected for message, not '%s'", e->toChars());
@@ -981,22 +1015,6 @@
 #if TARGET_NET
     else if (ident == Lexer::idPool("assembly"))
     {
-        if (!args || args->dim != 1)
-	        error("pragma has invalid number of arguments");
-	    else
-	    {
-	        Expression *e = (Expression *)args->data[0];
-	        e = e->semantic(sc);
-	        e = e->optimize(WANTvalue | WANTinterpret);
-	        args->data[0] = (void *)e;
-	        if (e->op != TOKstring)
-		    {
-		        error("string expected, not '%s'", e->toChars());
-	        }
-            PragmaScope* pragma = new PragmaScope(this, sc->parent, static_cast<StringExp*>(e));
-            decl = new Array;
-            decl->push(pragma);
-        }
     }
 #endif // TARGET_NET
 // LDC
--- a/dmd2/attrib.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/attrib.h	Tue Sep 08 10:07:56 2009 +0100
@@ -36,6 +36,9 @@
     AttribDeclaration(Array *decl);
     virtual Array *include(Scope *sc, ScopeDsymbol *s);
     int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
+    void setScopeNewSc(Scope *sc,
+	unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection,
+	unsigned structalign);
     void semanticNewSc(Scope *sc,
 	unsigned newstc, enum LINK linkage, enum PROT protection, int explictProtection,
 	unsigned structalign);
@@ -69,6 +72,7 @@
 
     StorageClassDeclaration(unsigned stc, Array *decl);
     Dsymbol *syntaxCopy(Dsymbol *s);
+    void setScope(Scope *sc);
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
@@ -81,6 +85,7 @@
 
     LinkDeclaration(enum LINK p, Array *decl);
     Dsymbol *syntaxCopy(Dsymbol *s);
+    void setScope(Scope *sc);
     void semantic(Scope *sc);
     void semantic3(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
@@ -93,6 +98,7 @@
 
     ProtDeclaration(enum PROT p, Array *decl);
     Dsymbol *syntaxCopy(Dsymbol *s);
+    void setScope(Scope *sc);
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 
@@ -105,6 +111,7 @@
 
     AlignDeclaration(Loc loc, unsigned sa, Array *decl);
     Dsymbol *syntaxCopy(Dsymbol *s);
+    void setScope(Scope *sc);
     void semantic(Scope *sc);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
 };
@@ -128,6 +135,7 @@
     PragmaDeclaration(Loc loc, Identifier *ident, Expressions *args, Array *decl);
     Dsymbol *syntaxCopy(Dsymbol *s);
     void semantic(Scope *sc);
+    void setScope(Scope *sc);
     int oneMember(Dsymbol **ps);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     const char *kind();
--- a/dmd2/cast.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/cast.c	Tue Sep 08 10:07:56 2009 +0100
@@ -1796,8 +1796,17 @@
 
     if (op == TOKmin || op == TOKadd)
     {
-	if (t1 == t2 && (t1->ty == Tstruct || t1->ty == Tclass))
-	    goto Lerror;
+	if (t1->ty == Tstruct)
+	{
+	    if (t2->ty == Tstruct &&
+		((TypeStruct *)t1)->sym == ((TypeStruct *)t2)->sym)
+		goto Lerror;
+	}
+	else if (t1->ty == Tclass)
+	{
+	    if (t2->ty == Tclass)
+		goto Lerror;
+	}
     }
 
     if (!typeMerge(sc, this, &type, &e1, &e2))
@@ -1941,6 +1950,9 @@
     IntRange ir1 = e1->getIntRange();
     IntRange ir2 = e2->getIntRange();
 
+    if (ir2.imax == 0 || ir2.imin == 0)
+	return Expression::getIntRange();
+
     ir.imin = ir1.imin / ir2.imax;
     ir.imax = ir1.imax / ir2.imin;
 
--- a/dmd2/class.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/class.c	Tue Sep 08 10:07:56 2009 +0100
@@ -349,6 +349,8 @@
 		    //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
 		    scope = scx ? scx : new Scope(*sc);
 		    scope->setNoFree();
+		    if (tc->sym->scope)
+		        tc->sym->scope->module->addDeferredSemantic(tc->sym);
 		    scope->module->addDeferredSemantic(this);
 		    return;
 		}
@@ -402,6 +404,12 @@
 		    error("inherits from duplicate interface %s", b2->base->toChars());
 	    }
 
+	    if (!tc->sym->symtab)
+	    {   // Try to resolve forward reference
+		if (sc->mustsemantic && tc->sym->scope)
+		    tc->sym->semantic(NULL);
+	    }
+
 	    b->base = tc->sym;
 	    if (!b->base->symtab || b->base->scope)
 	    {
@@ -410,6 +418,8 @@
 		//printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
 		scope = scx ? scx : new Scope(*sc);
 		scope->setNoFree();
+		if (tc->sym->scope)
+		    tc->sym->scope->module->addDeferredSemantic(tc->sym);
 		scope->module->addDeferredSemantic(this);
 		return;
 	    }
@@ -798,8 +808,8 @@
 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
 {
     Dsymbol *s;
+    //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
 
-    //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
     if (scope)
     {	Scope *sc = scope;
 	sc->mustsemantic++;
@@ -962,10 +972,12 @@
     return 0;
 }
 
+#if DMDV2
 int ClassDeclaration::isCPPinterface()
 {
     return 0;
 }
+#endif
 
 
 /****************************************
@@ -1142,6 +1154,11 @@
 		baseclasses.remove(i);
 		continue;
 	    }
+	    if (!b->base->symtab)
+	    {   // Try to resolve forward reference
+		if (sc->mustsemantic && b->base->scope)
+		    b->base->semantic(NULL);
+	    }
 	    if (!b->base->symtab || b->base->scope || b->base->inuse)
 	    {
 		//error("forward reference of base class %s", baseClass->toChars());
@@ -1326,10 +1343,12 @@
     return com;
 }
 
+#if DMDV2
 int InterfaceDeclaration::isCPPinterface()
 {
     return cpp;
 }
+#endif
 
 /*******************************************
  */
--- a/dmd2/constfold.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/constfold.c	Tue Sep 08 10:07:56 2009 +0100
@@ -65,6 +65,11 @@
     return 1;
 }
 
+int NullExp::isConst()
+{
+    return 0;
+}
+
 int SymOffExp::isConst()
 {
     return 2;
@@ -1084,6 +1089,8 @@
     Type *tb = to->toBasetype();
     Type *typeb = type->toBasetype();
 
+    /* Allow casting from one string type to another
+     */
     if (e1->op == TOKstring)
     {
 	if (tb->ty == Tarray && typeb->ty == Tarray &&
--- a/dmd2/cppmangle.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/cppmangle.c	Tue Sep 08 10:07:56 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2007 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -25,7 +25,7 @@
 #include "import.h"
 #include "aggregate.h"
 
-#if DMDV2
+#if CPP_MANGLE
 
 /* Do mangling for C++ linkage.
  * Follows Itanium C++ ABI 1.86
--- a/dmd2/declaration.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/declaration.c	Tue Sep 08 10:07:56 2009 +0100
@@ -141,7 +141,7 @@
 	    if (isConst())
 		p = "const";
 	    else if (isInvariant())
-		p = "mutable";
+		p = "immutable";
 	    else if (storage_class & STCmanifest)
 		p = "enum";
 	    else if (!t->isAssignable())
@@ -639,6 +639,7 @@
     onstack = 0;
     canassign = 0;
     value = NULL;
+    rundtor = NULL;
 #if IN_LLVM
     aggrIndex = 0;
 
@@ -956,9 +957,7 @@
 	    Expression *e1;
 	    e1 = new VarExp(loc, this);
 	    e = new AssignExp(loc, e1, e);
-#if DMDV2
 	    e->op = TOKconstruct;
-#endif
 	    e->type = e1->type;		// don't type check this, it would fail
 	    init = new ExpInitializer(loc, e);
 	    return;
@@ -979,10 +978,8 @@
 	{
 	    init = getExpInitializer();
 	}
-#if DMDV2
 	// Default initializer is always a blit
 	op = TOKblit;
-#endif
     }
 
     if (init)
@@ -1039,7 +1036,7 @@
 		Expression *e1 = new VarExp(loc, this);
 
 		Type *t = type->toBasetype();
-		if (t->ty == Tsarray)
+		if (t->ty == Tsarray && !(storage_class & (STCref | STCout)))
 		{
 		    ei->exp = ei->exp->semantic(sc);
 		    if (!ei->exp->implicitConvTo(type))
@@ -1167,7 +1164,7 @@
 			e = e->optimize(WANTvalue | WANTinterpret);
 		    else
 			e = e->optimize(WANTvalue);
-		    if (e->op == TOKint64 || e->op == TOKstring)
+		    if (e->op == TOKint64 || e->op == TOKstring || e->op == TOKfloat64)
 		    {
 			ei->exp = e;		// no errors, keep result
 		    }
--- a/dmd2/declaration.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/declaration.h	Tue Sep 08 10:07:56 2009 +0100
@@ -261,7 +261,11 @@
     Initializer *init;
     unsigned offset;
     int noauto;			// no auto semantics
+#if DMDV2
     FuncDeclarations nestedrefs; // referenced by these lexically nested functions
+#else
+    int nestedref;		// referenced by a lexically nested function
+#endif
     int ctorinit;		// it has been initialized in a ctor
     int onstack;		// 1: it has been allocated on the stack
 				// 2: on stack, run destructor anyway
@@ -269,6 +273,11 @@
     Dsymbol *aliassym;		// if redone as alias to another symbol
     Expression *value;		// when interpreting, this is the value
 				// (NULL if value not determinable)
+#if DMDV2
+    VarDeclaration *rundtor;	// if !NULL, rundtor is tested at runtime to see
+				// if the destructor should be run. Used to prevent
+				// dtor calls on postblitted vars
+#endif
 
     VarDeclaration(Loc loc, Type *t, Identifier *id, Initializer *init);
     Dsymbol *syntaxCopy(Dsymbol *);
@@ -285,8 +294,10 @@
     int isDataseg();
     int isThreadlocal();
     int hasPointers();
+#if DMDV2
     int canTakeAddressOf();
     int needsAutoDtor();
+#endif
     Expression *callAutoDtor(Scope *sc);
     ExpInitializer *getExpInitializer();
     Expression *getConstInitializer();
@@ -625,6 +636,8 @@
 
 Expression *eval_builtin(enum BUILTIN builtin, Expressions *arguments);
 
+#else
+enum BUILTIN { };
 #endif
 
 struct FuncDeclaration : Declaration
@@ -718,6 +731,7 @@
     void appendExp(Expression *e);
     void appendState(Statement *s);
     char *mangle();
+    const char *toPrettyChars();
     int isMain();
     int isWinMain();
     int isDllMain();
@@ -734,7 +748,7 @@
     virtual int isFinal();
     virtual int addPreInvariant();
     virtual int addPostInvariant();
-    Expression *interpret(InterState *istate, Expressions *arguments);
+    Expression *interpret(InterState *istate, Expressions *arguments, Expression *thisexp = NULL);
     void inlineScan();
     int canInline(int hasthis, int hdrscan = 0);
     Expression *doInline(InlineScanState *iss, Expression *ethis, Array *arguments);
@@ -788,12 +802,13 @@
 #endif
 };
 
+#if DMDV2
 FuncDeclaration *resolveFuncCall(Scope *sc, Loc loc, Dsymbol *s,
 	Objects *tiargs,
 	Expression *ethis,
 	Expressions *arguments,
 	int flags);
-
+#endif
 
 struct FuncAliasDeclaration : FuncDeclaration
 {
--- a/dmd2/doc.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/doc.c	Tue Sep 08 10:07:56 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -238,7 +238,7 @@
     // Generate predefined macros
 
     // Set the title to be the name of the module
-    {	char *p = toPrettyChars();
+    {	const char *p = toPrettyChars();
 	Macro::define(&macrotable, (unsigned char *)"TITLE", 5, (unsigned char *)p, strlen(p));
     }
 
--- a/dmd2/dsymbol.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/dsymbol.c	Tue Sep 08 10:07:56 2009 +0100
@@ -169,7 +169,7 @@
     return ident ? ident->toChars() : (char *)"__anonymous";
 }
 
-char *Dsymbol::toPrettyChars()
+const char *Dsymbol::toPrettyChars()
 {   Dsymbol *p;
     char *s;
     char *q;
@@ -452,10 +452,12 @@
     return FALSE;
 }
 
+#if DMDV2
 int Dsymbol::isOverloadable()
 {
     return 0;
 }
+#endif
 
 LabelDsymbol *Dsymbol::isLabel()		// is this a LabelDsymbol()?
 {
@@ -695,6 +697,7 @@
 
 /********************************* OverloadSet ****************************/
 
+#if DMDV2
 OverloadSet::OverloadSet()
     : Dsymbol()
 {
@@ -709,6 +712,7 @@
 {
     return "overloadset";
 }
+#endif
 
 
 /********************************* ScopeDsymbol ****************************/
--- a/dmd2/dsymbol.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/dsymbol.h	Tue Sep 08 10:07:56 2009 +0100
@@ -62,6 +62,7 @@
 struct TypeTuple;
 struct WithStatement;
 struct LabelDsymbol;
+struct ScopeDsymbol;
 struct TemplateDeclaration;
 struct TemplateInstance;
 struct TemplateMixin;
@@ -130,7 +131,6 @@
     Dsymbol();
     Dsymbol(Identifier *);
     char *toChars();
-    char *toPrettyChars();
     char *locToChars();
     int equals(Object *o);
     int isAnonymous();
@@ -148,6 +148,7 @@
 
     static Array *arraySyntaxCopy(Array *a);
 
+    virtual const char *toPrettyChars();
     virtual const char *kind();
     virtual Dsymbol *toAlias();			// resolve real symbol
     virtual int addMember(Scope *sc, ScopeDsymbol *s, int memnum);
@@ -173,7 +174,9 @@
     virtual int isExport();			// is Dsymbol exported?
     virtual int isImportedSymbol();		// is Dsymbol imported?
     virtual int isDeprecated();			// is Dsymbol deprecated?
+#if DMDV2
     virtual int isOverloadable();
+#endif
     virtual LabelDsymbol *isLabel();		// is this a LabelDsymbol?
     virtual AggregateDeclaration *isMember();	// is this symbol a member of an AggregateDeclaration?
     virtual Type *getType();			// is this a type?
@@ -322,6 +325,7 @@
 
 // Overload Sets
 
+#if DMDV2
 struct OverloadSet : Dsymbol
 {
     Dsymbols a;		// array of Dsymbols
@@ -331,6 +335,7 @@
     OverloadSet *isOverloadSet() { return this; }
     const char *kind();
 };
+#endif
 
 // Table of Dsymbol's
 
--- a/dmd2/expression.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/expression.c	Tue Sep 08 10:07:56 2009 +0100
@@ -3235,7 +3235,7 @@
 	e = resolveProperties(sc, e);
 	if (i >= nfields)
 	{   error("more initializers than fields of %s", sd->toChars());
-	    break;
+	    return new ErrorExp();
 	}
 	Dsymbol *s = (Dsymbol *)sd->fields.data[i];
 	VarDeclaration *v = s->isVarDeclaration();
@@ -4429,7 +4429,9 @@
 	else
 	{
 	    fd->semantic2(sc);
-	    if (!global.errors)
+	    if (!global.errors ||
+		// need to infer return type
+		(fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()))
 	    {
 		fd->semantic3(sc);
 
@@ -4438,6 +4440,10 @@
 	    }
 	}
 
+	// need to infer return type
+	if (global.errors && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())
+	    ((TypeFunction *)fd->type)->next = Type::terror;
+
 	// Type is a "delegate to" or "pointer to" the function literal
 	if (fd->isNested())
 	{
@@ -4788,6 +4794,12 @@
 		    goto Lno;
 		tded = targ;
 		break;
+
+	    case TOKshared:
+		if (!targ->isShared())
+		    goto Lno;
+		tded = targ;
+		break;
 #endif
 
 	    case TOKsuper:
@@ -5293,7 +5305,7 @@
     }
 
     if (global.params.verbose)
-	printf("file      %s\t(%s)\n", (char*)se->string, name);
+	printf("file      %s\t(%s)\n", (char *)se->string, name);
 
     {	File f(name);
 	if (f.read())
@@ -6219,7 +6231,7 @@
 	}
     }
 
-#if DMDV2
+#if 1
     /* This recognizes:
      *	foo!(tiargs)(funcargs)
      */
@@ -6346,7 +6358,7 @@
 	if (t1->ty == Tstruct)
 	{
 	    ad = ((TypeStruct *)t1)->sym;
-
+#if DMDV2
 	    // First look for constructor
 	    if (ad->ctor && arguments && arguments->dim)
 	    {
@@ -6374,7 +6386,7 @@
 		e = e->semantic(sc);
 		return e;
 	    }
-
+#endif
 	    // No constructor, look for overload of opCall
 	    if (search_function(ad, Id::call))
 		goto L1;	// overload of opCall, therefore it's a call
@@ -6449,7 +6461,7 @@
 	    f->addPostInvariant()
 	   )
 	{
-	    error("cannot call public/export function %s from immutable", f->toChars());
+	    error("cannot call public/export function %s from invariant", f->toChars());
 	}
 
 	checkDeprecated(sc, f);
@@ -6484,19 +6496,27 @@
 		Type *tthis = ue->e1->type->toBasetype();
 		if (tthis->ty == Tpointer)
 		    tthis = tthis->nextOf()->toBasetype();
+#if 0	// this checking should have been already done
 		if (f->type->isInvariant())
 		{
 		    if (tthis->mod != MODinvariant)
-			error("%s can only be called on an invariant object", e1->toChars());
+			error("%s can only be called with an immutable object", e1->toChars());
+		}
+		else if (f->type->isShared())
+		{
+		    if (tthis->mod != MODinvariant &&
+			tthis->mod != MODshared &&
+			tthis->mod != (MODshared | MODconst))
+			error("shared %s can only be called with a shared or immutable object", e1->toChars());
 		}
 		else
 		{
 		    if (tthis->mod != 0)
 		    {	//printf("mod = %x\n", tthis->mod);
-			error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars());
+			error("%s can only be called with a mutable object, not %s", e1->toChars(), tthis->toChars());
 		    }
 		}
-
+#endif
 		/* Cannot call mutable method on a final struct
 		 */
 		if (tthis->ty == Tstruct &&
@@ -7586,27 +7606,30 @@
     else
 	goto Lerror;
 
+    {
+    Scope *sc2 = sc;
     if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
     {
 	sym = new ArrayScopeSymbol(sc, this);
 	sym->loc = loc;
 	sym->parent = sc->scopesym;
-	sc = sc->push(sym);
+	sc2 = sc->push(sym);
     }
 
     if (lwr)
-    {	lwr = lwr->semantic(sc);
-	lwr = resolveProperties(sc, lwr);
-	lwr = lwr->implicitCastTo(sc, Type::tsize_t);
+    {	lwr = lwr->semantic(sc2);
+	lwr = resolveProperties(sc2, lwr);
+	lwr = lwr->implicitCastTo(sc2, Type::tsize_t);
     }
     if (upr)
-    {	upr = upr->semantic(sc);
-	upr = resolveProperties(sc, upr);
-	upr = upr->implicitCastTo(sc, Type::tsize_t);
-    }
-
-    if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
-	sc->pop();
+    {	upr = upr->semantic(sc2);
+	upr = resolveProperties(sc2, upr);
+	upr = upr->implicitCastTo(sc2, Type::tsize_t);
+    }
+
+    if (sc2 != sc)
+	sc2->pop();
+    }
 
     if (t->ty == Ttuple)
     {
@@ -8292,6 +8315,15 @@
 	}
     }
 
+    // Determine if this is an initialization of a reference
+    int refinit = 0;
+    if (op == TOKconstruct && e1->op == TOKvar)
+    {	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (v->storage_class & (STCout | STCref))
+	    refinit = 1;
+    }
+
     Type *t1 = e1->type->toBasetype();
 
     if (t1->ty == Tfunction)
@@ -8313,22 +8345,14 @@
 	    if (e)
 		return e;
 	}
-	else if (op == TOKconstruct)
+	else if (op == TOKconstruct && !refinit)
 	{   Type *t2 = e2->type->toBasetype();
 	    if (t2->ty == Tstruct &&
 		sd == ((TypeStruct *)t2)->sym &&
 		sd->cpctor)
 	    {	/* We have a copy constructor for this
 		 */
-		if (e2->op == TOKvar || e2->op == TOKstar)
-		{   /* Write as:
-		     *	e1.cpctor(e2);
-		     */
-		    Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
-		    e = new CallExp(loc, e, e2);
-		    return e->semantic(sc);
-		}
-		else if (e2->op == TOKquestion)
+		if (e2->op == TOKquestion)
 		{   /* Write as:
 		     *	a ? e1 = b : e1 = c;
 		     */
@@ -8340,6 +8364,17 @@
 		    Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
 		    return e->semantic(sc);
 		}
+		else if (e2->op == TOKvar ||
+			 e2->op == TOKdotvar ||
+			 e2->op == TOKstar ||
+			 e2->op == TOKindex)
+		{   /* Write as:
+		     *	e1.cpctor(e2);
+		     */
+		    Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
+		    e = new CallExp(loc, e, e2);
+		    return e->semantic(sc);
+		}
 	    }
 	}
     }
@@ -8353,7 +8388,7 @@
 	}
     }
 
-    if (t1->ty == Tsarray)
+    if (t1->ty == Tsarray && !refinit)
     {	// Convert e1 to e1[]
 	Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
 	e1 = e->semantic(sc);
@@ -8398,7 +8433,7 @@
     {
 	/* Should have already converted e1 => e1[]
 	 */
-	assert(0);
+	assert(op == TOKconstruct);
 	//error("cannot assign to static array %s", e1->toChars());
     }
     else if (e1->op == TOKslice)
--- a/dmd2/expression.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/expression.h	Tue Sep 08 10:07:56 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -323,6 +323,7 @@
 
     ThisExp(Loc loc);
     Expression *semantic(Scope *sc);
+    Expression *interpret(InterState *istate);
     int isBool(int result);
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     int isLvalue();
@@ -361,6 +362,7 @@
     NullExp(Loc loc);
     Expression *semantic(Scope *sc);
     int isBool(int result);
+    int isConst();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
     void toMangleBuffer(OutBuffer *buf);
     MATCH implicitConvTo(Type *t);
@@ -620,6 +622,7 @@
 	Type *newtype, Expressions *arguments);
     Expression *syntaxCopy();
     Expression *semantic(Scope *sc);
+    Expression *optimize(int result);
 #if IN_DMD
     elem *toElem(IRState *irs);
 #endif
@@ -1245,6 +1248,8 @@
     int checkSideEffect(int flag);
     void checkEscape();
     void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
+    void buildArrayIdent(OutBuffer *buf, Expressions *arguments);
+    Expression *buildArrayLoop(Arguments *fparams);
 #if IN_DMD
     elem *toElem(IRState *irs);
 #endif
--- a/dmd2/func.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/func.c	Tue Sep 08 10:07:56 2009 +0100
@@ -180,7 +180,7 @@
 	    stc |= STCimmutable;
 	if (type->isConst())
 	    stc |= STCconst;
-	if (type->isShared())
+	if (type->isShared() || storage_class & STCsynchronized)
 	    stc |= STCshared;
 	switch (stc & STC_TYPECTOR)
 	{
@@ -1199,12 +1199,13 @@
 		error("expected to return a value of type %s", type->nextOf()->toChars());
 	    else if (!inlineAsm)
 	    {
+#if DMDV2
 		int blockexit = fbody ? fbody->blockExit() : BEfallthru;
 		if (f->isnothrow && blockexit & BEthrow)
 		    error("'%s' is nothrow yet may throw", toChars());
 
 		int offend = blockexit & BEfallthru;
-
+#endif
 		if (type->nextOf()->ty == Tvoid)
 		{
 		    if (offend && isMain())
@@ -1217,10 +1218,11 @@
 		{
 		    if (offend)
 		    {   Expression *e;
-
-			//warning(loc, "no return exp; or assert(0); at end of function");
+#if DMDV1
+			warning(loc, "no return exp; or assert(0); at end of function");
+#else
 			error("no return exp; or assert(0); at end of function");
-
+#endif
 			if (global.params.useAssert &&
 			    !global.params.useInline)
 			{   /* Add an assert(0, msg); where the missing return
@@ -1412,7 +1414,7 @@
 
 	    fbody = new CompoundStatement(0, a);
 
-#if IN_LLVM
+#if 0 // This seems to have been added in with dmd 2.032, see below
 	    // wrap body of synchronized functions in a synchronized statement
 	    if (isSynchronized())
 	    {
@@ -1450,7 +1452,7 @@
 		fbody = new CompoundStatement(0, a);
 	    }
 #endif
-
+#if DMDV2
 	    /* Append destructor calls for parameters as finally blocks.
 	     */
 	    if (parameters)
@@ -1479,6 +1481,46 @@
 		    }
 		}
 	    }
+#endif
+
+#if 1
+	    if (isSynchronized())
+	    {	/* Wrap the entire function body in a synchronized statement
+		 */
+		ClassDeclaration *cd = parent->isClassDeclaration();
+		if (cd)
+		{
+#if TARGET_WINDOS
+		    if (/*config.flags2 & CFG2seh &&*/	// always on for WINDOS
+			!isStatic() && !fbody->usesEH())
+		    {
+			/* The back end uses the "jmonitor" hack for syncing;
+			 * no need to do the sync at this level.
+			 */
+		    }
+		    else
+#endif
+		    {
+			Expression *vsync;
+			if (isStatic())
+			{   // The monitor is in the ClassInfo
+			    vsync = new DotIdExp(loc, new DsymbolExp(loc, cd), Id::classinfo);
+			}
+			else
+			{   // 'this' is the monitor
+			    vsync = new VarExp(loc, vthis);
+			}
+			fbody = new PeelStatement(fbody);	// don't redo semantic()
+			fbody = new SynchronizedStatement(loc, vsync, fbody);
+			fbody = fbody->semantic(sc2);
+		    }
+		}
+		else
+		{
+		    error("synchronized function %s must be a member of a class", toChars());
+		}
+	    }
+#endif
 	}
 
 	sc2->callSuper = 0;
@@ -1914,12 +1956,18 @@
     {
 	OutBuffer buf;
 
+	buf.writeByte('(');
 	if (arguments)
 	{
 	    HdrGenState hgs;
 
 	    argExpTypesToCBuffer(&buf, arguments, &hgs);
+	    buf.writeByte(')');
+	    if (ethis)
+		ethis->type->modToBuffer(&buf);
 	}
+	else
+	    buf.writeByte(')');
 
 	if (m.last == MATCHnomatch)
 	{
@@ -1928,9 +1976,13 @@
 
 	    tf = (TypeFunction *)type;
 
+	    OutBuffer buf2;
+	    tf->modToBuffer(&buf2);
+
 	    //printf("tf = %s, args = %s\n", tf->deco, ((Expression *)arguments->data[0])->type->deco);
-	    error(loc, "%s does not match parameter types (%s)",
+	    error(loc, "%s%s is not callable using argument types %s",
 		Argument::argsTypesToChars(tf->parameters, tf->varargs),
+		buf2.toChars(),
 		buf.toChars());
 	    return m.anyf;		// as long as it's not a FuncAliasDeclaration
 	}
@@ -2202,6 +2254,13 @@
     }
 }
 
+const char *FuncDeclaration::toPrettyChars()
+{
+    if (isMain())
+	return "D main";
+    else
+	return Dsymbol::toPrettyChars();
+}
 
 int FuncDeclaration::isMain()
 {
--- a/dmd2/id.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/id.c	Tue Sep 08 10:07:56 2009 +0100
@@ -103,6 +103,7 @@
 Identifier *Id::reverse;
 Identifier *Id::dup;
 Identifier *Id::idup;
+Identifier *Id::property;
 Identifier *Id::___out;
 Identifier *Id::___in;
 Identifier *Id::__int;
@@ -180,6 +181,10 @@
 Identifier *Id::aaKeys;
 Identifier *Id::aaValues;
 Identifier *Id::aaRehash;
+Identifier *Id::monitorenter;
+Identifier *Id::monitorexit;
+Identifier *Id::criticalenter;
+Identifier *Id::criticalexit;
 Identifier *Id::GNU_asm;
 Identifier *Id::lib;
 Identifier *Id::msg;
@@ -333,6 +338,7 @@
     reverse = Lexer::idPool("reverse");
     dup = Lexer::idPool("dup");
     idup = Lexer::idPool("idup");
+    property = Lexer::idPool("property");
     ___out = Lexer::idPool("out");
     ___in = Lexer::idPool("in");
     __int = Lexer::idPool("int");
@@ -410,6 +416,10 @@
     aaKeys = Lexer::idPool("_aaKeys");
     aaValues = Lexer::idPool("_aaValues");
     aaRehash = Lexer::idPool("_aaRehash");
+    monitorenter = Lexer::idPool("_d_monitorenter");
+    monitorexit = Lexer::idPool("_d_monitorexit");
+    criticalenter = Lexer::idPool("_d_criticalenter");
+    criticalexit = Lexer::idPool("_d_criticalexit");
     GNU_asm = Lexer::idPool("GNU_asm");
     lib = Lexer::idPool("lib");
     msg = Lexer::idPool("msg");
--- a/dmd2/id.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/id.h	Tue Sep 08 10:07:56 2009 +0100
@@ -105,6 +105,7 @@
     static Identifier *reverse;
     static Identifier *dup;
     static Identifier *idup;
+    static Identifier *property;
     static Identifier *___out;
     static Identifier *___in;
     static Identifier *__int;
@@ -182,6 +183,10 @@
     static Identifier *aaKeys;
     static Identifier *aaValues;
     static Identifier *aaRehash;
+    static Identifier *monitorenter;
+    static Identifier *monitorexit;
+    static Identifier *criticalenter;
+    static Identifier *criticalexit;
     static Identifier *GNU_asm;
     static Identifier *lib;
     static Identifier *msg;
--- a/dmd2/idgen.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/idgen.c	Tue Sep 08 10:07:56 2009 +0100
@@ -137,6 +137,8 @@
     { "dup" },
     { "idup" },
 
+    { "property" },
+
     // For inline assembler
     { "___out", "out" },
     { "___in", "in" },
@@ -232,6 +234,10 @@
     { "aaKeys", "_aaKeys" },
     { "aaValues", "_aaValues" },
     { "aaRehash", "_aaRehash" },
+    { "monitorenter", "_d_monitorenter" },
+    { "monitorexit", "_d_monitorexit" },
+    { "criticalenter", "_d_criticalenter" },
+    { "criticalexit", "_d_criticalexit" },
 
     // For pragma's
     { "GNU_asm" },
--- a/dmd2/impcnvtab.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/impcnvtab.c	Tue Sep 08 10:07:56 2009 +0100
@@ -2,181 +2,185 @@
 #include "mtype.h"
 unsigned char Type::impcnvResult[TMAX][TMAX] =
 {
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,23,24,25,29,30,31,37,20,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,23,24,25,29,30,31,37,21,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,23,24,25,29,30,31,37,22,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,23,24,25,29,30,31,37,23,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,24,24,25,30,30,31,37,24,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,25,25,25,31,31,31,37,25,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,29,29,29,29,29,29,29,29,29,30,31,29,30,31,29,30,31,37,29,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,30,30,30,30,30,30,30,30,30,30,31,30,30,31,30,30,31,37,30,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,37,31,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,29,30,31,37,33,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
 };
 unsigned char Type::impcnvType1[TMAX][TMAX] =
 {
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,22,23,24,22,23,24,36,19,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,22,23,24,22,23,24,36,20,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,22,23,24,22,23,24,36,21,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,22,23,24,22,23,24,36,22,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,23,23,24,23,23,24,36,23,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,24,36,24,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,25,25,25,25,25,25,25,25,25,26,27,25,26,27,25,26,27,36,25,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,26,26,26,26,26,26,26,26,26,26,27,26,26,27,26,26,27,36,26,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,27,36,27,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,28,28,28,28,28,28,28,28,28,29,30,28,29,30,28,29,30,36,28,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,29,29,29,29,29,29,29,29,29,29,30,29,29,30,29,29,30,36,29,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,36,30,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,22,23,24,22,23,24,36,32,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,23,24,25,23,24,25,37,20,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,23,24,25,23,24,25,37,21,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,23,24,25,23,24,25,37,22,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,23,24,25,23,24,25,37,23,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,24,24,25,24,24,25,37,24,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,37,25,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,26,26,26,26,26,26,26,26,26,27,28,26,27,28,26,27,28,37,26,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,27,27,27,27,27,27,27,27,27,27,28,27,27,28,27,27,28,37,27,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,28,37,28,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,29,29,29,29,29,29,29,29,29,30,31,29,30,31,29,30,31,37,29,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,30,30,30,30,30,30,30,30,30,30,31,30,30,31,30,30,31,37,30,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,37,31,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,23,24,25,23,24,25,37,33,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
 };
 unsigned char Type::impcnvType2[TMAX][TMAX] =
 {
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,18,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,19,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,36,19,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,20,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,36,20,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,21,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,36,21,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,22,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,36,22,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,23,23,23,23,23,23,23,23,23,23,24,26,26,27,29,29,30,36,23,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,24,24,24,24,24,24,24,24,24,24,24,27,27,27,30,30,30,36,24,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,18,18,18,18,18,19,20,21,22,23,24,25,26,27,28,29,30,36,32,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
-36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,36,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,19,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,20,20,20,20,20,20,21,22,23,24,25,26,27,28,29,30,31,37,20,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,21,21,21,21,21,21,21,22,23,24,25,26,27,28,29,30,31,37,21,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,22,22,22,22,22,22,22,22,23,24,25,26,27,28,29,30,31,37,22,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,23,23,23,23,23,23,23,23,23,24,25,26,27,28,29,30,31,37,23,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,24,24,24,24,24,24,24,24,24,24,25,27,27,28,30,30,31,37,24,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,25,25,25,25,25,25,25,25,25,25,25,28,28,28,31,31,31,37,25,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,19,19,19,19,19,20,21,22,23,24,25,26,27,28,29,30,31,37,33,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
+37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
 };
 unsigned char Type::impcnvWarn[TMAX][TMAX] =
 {
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 };
--- a/dmd2/init.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/init.c	Tue Sep 08 10:07:56 2009 +0100
@@ -412,15 +412,24 @@
 
 	   case Tpointer:
 	   case Tarray:
-	       edim = dim;
-	       break;
+		edim = dim;
+		break;
 
 	   default:
 	       assert(0);
 	}
     }
     else
+    {
 	edim = value.dim;
+	for (size_t i = 0, j = 0; i < value.dim; i++, j++)
+	{
+	    if (index.data[i])
+		j = ((Expression *)index.data[i])->toInteger();
+	    if (j >= edim)
+		edim = j + 1;
+	}
+    }
 
     elements = new Expressions();
     elements->setDim(edim);
@@ -464,7 +473,7 @@
 Lno:
     delete elements;
     error(loc, "array initializers as expressions are not allowed");
-    return NULL;
+    return new ErrorExp();
 }
 
 
--- a/dmd2/inline.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/inline.c	Tue Sep 08 10:07:56 2009 +0100
@@ -1,5 +1,5 @@
 
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -870,7 +870,8 @@
 	condition = condition->inlineScan(iss);
     if (increment)
 	increment = increment->inlineScan(iss);
-    body = body->inlineScan(iss);
+    if (body)
+	body = body->inlineScan(iss);
     return this;
 }
 
@@ -1072,6 +1073,31 @@
 
 		if (ie)
 		{
+#if DMDV2
+		    if (vd->type)
+		    {	Type *tb = vd->type->toBasetype();
+			if (tb->ty == Tstruct)
+			{   StructDeclaration *sd = ((TypeStruct *)tb)->sym;
+			    if (sd->cpctor)
+			    {   /* The problem here is that if the initializer is a
+				 * function call that returns a struct S with a cpctor:
+				 *   S s = foo();
+				 * the postblit is done by the return statement in foo()
+				 * in s2ir.c, the intermediate code generator.
+				 * But, if foo() is inlined and now the code looks like:
+				 *   S s = x;
+				 * the postblit is not there, because such assignments
+				 * are rewritten as s.cpctor(&x) by the front end.
+				 * So, the inlining won't get the postblit called.
+				 * Work around by not inlining these cases.
+				 * A proper fix would be to move all the postblit
+				 * additions to the front end.
+				 */
+				return;
+			    }
+			}
+		    }
+#endif
 		    ie->exp = ie->exp->inlineScan(iss);
 		}
 	    }
@@ -1499,6 +1525,9 @@
     inlineNest++;
     Expression *eb = fbody->doInline(&ids);
     inlineNest--;
+//eb->type->print();
+//eb->print();
+//eb->dump(0);
     return Expression::combine(e, eb);
 }
 
--- a/dmd2/interpret.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/interpret.c	Tue Sep 08 10:07:56 2009 +0100
@@ -1,6 +1,6 @@
 
 // Compiler implementation of the D programming language
-// Copyright (c) 1999-2008 by Digital Mars
+// Copyright (c) 1999-2009 by Digital Mars
 // All Rights Reserved
 // written by Walter Bright
 // http://www.digitalmars.com
@@ -34,6 +34,7 @@
     Dsymbols vars;		// variables used in this function
     Statement *start;		// if !=NULL, start execution at this statement
     Statement *gotoTarget;	// target of EXP_GOTO_INTERPRET result
+    Expression *localThis;	// value of 'this', or NULL if none
 
     InterState();
 };
@@ -50,11 +51,14 @@
 /*************************************
  * Attempt to interpret a function given the arguments.
  * Input:
- *	istate	state for calling function (NULL if none)
+ *	istate     state for calling function (NULL if none)
+ *      arguments  function arguments
+ *      thisarg    'this', if a needThis() function, NULL if not.	
+ *
  * Return result expression if successful, NULL if not.
  */
 
-Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments)
+Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments, Expression *thisarg)
 {
 #if LOG
     printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars());
@@ -72,7 +76,7 @@
     if (cantInterpret || semanticRun == 3)
 	return NULL;
 
-    if (needThis() || isNested() || !fbody)
+    if (!fbody)
     {	cantInterpret = 1;
 	return NULL;
     }
@@ -90,11 +94,13 @@
     assert(tb->ty == Tfunction);
     TypeFunction *tf = (TypeFunction *)tb;
     Type *tret = tf->next->toBasetype();
-    if (tf->varargs /*|| tret->ty == Tvoid*/)
+    if (tf->varargs)
     {	cantInterpret = 1;
+	error("Variadic functions are not yet implemented in CTFE");
 	return NULL;
     }
-
+    
+    // Ensure there are no lazy parameters
     if (tf->parameters)
     {	size_t dim = Argument::dim(tf->parameters);
 	for (size_t i = 0; i < dim; i++)
@@ -109,13 +115,20 @@
     InterState istatex;
     istatex.caller = istate;
     istatex.fd = this;
+    istatex.localThis = thisarg;
 
     Expressions vsave;		// place to save previous parameter values
     size_t dim = 0;
+    if (needThis() && !thisarg)
+    {	cantInterpret = 1;
+	// error, no this. Prevent segfault.
+	error("need 'this' to access member %s", toChars());
+	return NULL;
+    }
     if (arguments)
     {
 	dim = arguments->dim;
-	assert(!dim || parameters->dim == dim);
+	assert(!dim || (parameters && (parameters->dim == dim)));
 	vsave.setDim(dim);
 
 	/* Evaluate all the arguments to the function,
@@ -144,7 +157,9 @@
 		}
 		earg = earg->interpret(istate ? istate : &istatex);
 		if (earg == EXP_CANT_INTERPRET)
+		{   cantInterpret = 1;
 		    return NULL;
+		}
 	    }
 	    eargs.data[i] = earg;
 	}
@@ -157,23 +172,36 @@
 #if LOG
 	    printf("arg[%d] = %s\n", i, earg->toChars());
 #endif
-	    if (arg->storageClass & (STCout | STCref))
+	    if (arg->storageClass & (STCout | STCref) && earg->op==TOKvar)
 	    {
 		/* Bind out or ref parameter to the corresponding
 		 * variable v2
 		 */
-		if (!istate || earg->op != TOKvar)
+		if (!istate)
+		{   cantInterpret = 1;
+		    error("%s cannot be by passed by reference at compile time", earg->toChars());
 		    return NULL;	// can't bind to non-interpreted vars
-
+		}		
+		// We need to chase down all of the the passed parameters until
+		// we find something that isn't a TOKvar, then create a variable
+		// containg that expression.
 		VarDeclaration *v2;
 		while (1)
 		{
 		    VarExp *ve = (VarExp *)earg;
 		    v2 = ve->var->isVarDeclaration();
 		    if (!v2)
+		    {   cantInterpret = 1;
 			return NULL;
+		    }
 		    if (!v2->value || v2->value->op != TOKvar)
 			break;
+		    if (((VarExp *)v2->value)->var->isStaticStructInitDeclaration())		   
+		    {	// This can happen if v is a struct initialized to
+			// 0 using an __initZ StaticStructInitDeclaration from
+			// TypeStruct::defaultInit()
+			break; // eg default-initialized variable
+		    }
 		    earg = v2->value;
 		}
 
@@ -191,8 +219,7 @@
 		}
 	    }
 	    else
-	    {	/* Value parameters
-		 */
+	    {	// Value parameters and non-trivial references
 		v->value = earg;
 	    }
 #if LOG
@@ -200,11 +227,22 @@
 #endif
 	}
     }
+    // Don't restore the value of 'this' upon function return
+    if (needThis() && thisarg->op==TOKvar) {
+	VarDeclaration *thisvar = ((VarExp *)(thisarg))->var->isVarDeclaration();
+    	for (size_t i = 0; i < istate->vars.dim; i++)
+	{   VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
+	    if (v == thisvar)
+	    {	istate->vars.data[i] = NULL;
+		break;
+	    }
+	}
+    }
 
     /* Save the values of the local variables used
      */
     Expressions valueSaves;
-    if (istate)
+    if (istate && !isNested())
     {
 	//printf("saving local variables...\n");
 	valueSaves.setDim(istate->vars.dim);
@@ -220,7 +258,6 @@
     }
 
     Expression *e = NULL;
-
     while (1)
     {
 	e = fbody->interpret(&istatex);
@@ -246,7 +283,6 @@
 	else
 	    break;
     }
-
     /* Restore the parameter values
      */
     for (size_t i = 0; i < dim; i++)
@@ -255,7 +291,7 @@
 	v->value = (Expression *)vsave.data[i];
     }
 
-    if (istate)
+    if (istate && !isNested())
     {
 	/* Restore the variable values
 	 */
@@ -268,7 +304,6 @@
 	    }
 	}
     }
-
     return e;
 }
 
@@ -478,7 +513,7 @@
 	    return e;
 	if (e == EXP_BREAK_INTERPRET)
 	    return NULL;
-	if (e != EXP_CONTINUE_INTERPRET)
+	if (e && e != EXP_CONTINUE_INTERPRET)
 	    return e;
     }
 
@@ -758,7 +793,7 @@
 
 	while (1)
 	{
-	    e = Cmp(TOKlt, key->value->type, key->value, upr);
+	    e = Cmp(TOKlt, key->value->type, key->value, eupr);
 	    if (e == EXP_CANT_INTERPRET)
 		break;
 	    if (e->isBool(TRUE) == FALSE)
@@ -773,19 +808,23 @@
 	    {   e = NULL;
 		break;
 	    }
-	    e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type));
-	    if (e == EXP_CANT_INTERPRET)
+	    if (e == NULL || e == EXP_CONTINUE_INTERPRET)
+	    {	e = Add(key->value->type, key->value, new IntegerExp(loc, 1, key->value->type));
+		if (e == EXP_CANT_INTERPRET)
+		    break;
+		key->value = e;
+	    }
+	    else
 		break;
-	    key->value = e;
 	}
     }
     else // TOKforeach_reverse
     {
 	key->value = eupr;
 
-	while (1)
+	do
 	{
-	    e = Cmp(TOKgt, key->value->type, key->value, lwr);
+	    e = Cmp(TOKgt, key->value->type, key->value, elwr);
 	    if (e == EXP_CANT_INTERPRET)
 		break;
 	    if (e->isBool(TRUE) == FALSE)
@@ -805,7 +844,7 @@
 	    {   e = NULL;
 		break;
 	    }
-	}
+	} while (e == NULL || e == EXP_CONTINUE_INTERPRET);
     }
     key->value = keysave;
     return e;
@@ -946,6 +985,14 @@
     printf("type = %s\n", type->toChars());
     dump(0);
 #endif
+    error("Cannot interpret %s at compile time", toChars());
+    return EXP_CANT_INTERPRET;
+}
+
+Expression *ThisExp::interpret(InterState *istate)
+{
+    if (istate->localThis)
+        return istate->localThis->interpret(istate);
     return EXP_CANT_INTERPRET;
 }
 
@@ -995,7 +1042,7 @@
     if (v)
     {
 #if DMDV2
-	if ((v->isConst() || v->isInvariant()) && v->init && !v->value)
+	if ((v->isConst() || v->isInvariant() || v->storage_class & STCmanifest) && v->init && !v->value)
 #else
 	if (v->isConst() && v->init)
 #endif
@@ -1005,7 +1052,11 @@
 	}
 	else
 	{   e = v->value;
-	    if (!e)
+	    if (v->isDataseg())
+	    {	error(loc, "static variable %s cannot be read at compile time", v->toChars());
+		e = EXP_CANT_INTERPRET;
+	    }
+	    else if (!e)
 		error(loc, "variable %s is used before initialization", v->toChars());
 	    else if (e != EXP_CANT_INTERPRET)
 		e = e->interpret(istate);
@@ -1064,6 +1115,8 @@
 	     declaration->isTemplateMixin() ||
 	     declaration->isTupleDeclaration())
     {	// These can be made to work, too lazy now
+    error("Declaration %s is not yet implemented in CTFE", toChars());
+
 	e = EXP_CANT_INTERPRET;
     }
     else
@@ -1071,7 +1124,7 @@
 	e = NULL;
     }
 #if LOG
-    printf("-DeclarationExp::interpret(): %p\n", e);
+    printf("-DeclarationExp::interpret(%s): %p\n", toChars(), e);
 #endif
     return e;
 }
@@ -1261,7 +1314,9 @@
     /* We don't know how to deal with overlapping fields
      */
     if (sd->hasUnions)
-	return EXP_CANT_INTERPRET;
+	{   error("Unions with overlapping fields are not yet supported in CTFE");
+		return EXP_CANT_INTERPRET;
+    }
 
     if (elements)
     {
@@ -1433,6 +1488,98 @@
 BIN_INTERPRET2(Identity)
 BIN_INTERPRET2(Cmp)
 
+/* Helper functions for BinExp::interpretAssignCommon
+ */
+
+/***************************************
+ * Duplicate the elements array, then set field 'indexToChange' = newelem.
+ */
+Expressions *changeOneElement(Expressions *oldelems, size_t indexToChange, void *newelem)
+{
+    Expressions *expsx = new Expressions();
+    expsx->setDim(oldelems->dim);
+    for (size_t j = 0; j < expsx->dim; j++)
+    {
+	if (j == indexToChange)
+	    expsx->data[j] = newelem;
+	else
+	    expsx->data[j] = oldelems->data[j];
+    }
+    return expsx;
+}
+
+/***************************************
+ * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$]
+ */
+Expressions *spliceElements(Expressions *oldelems,
+	Expressions *newelems, size_t insertpoint)
+{
+    Expressions *expsx = new Expressions();
+    expsx->setDim(oldelems->dim);
+    for (size_t j = 0; j < expsx->dim; j++)
+    {
+	if (j >= insertpoint && j < insertpoint + newelems->dim)
+	    expsx->data[j] = newelems->data[j - insertpoint];
+	else
+	    expsx->data[j] = oldelems->data[j];
+    }
+    return expsx;
+}
+
+/******************************
+ * Create an array literal consisting of 'elem' duplicated 'dim' times.
+ */
+ArrayLiteralExp *createBlockDuplicatedArrayLiteral(Type *type,
+	Expression *elem, size_t dim)
+{
+    Expressions *elements = new Expressions();
+    elements->setDim(dim);
+    for (size_t i = 0; i < dim; i++)
+	 elements->data[i] = elem;	
+    ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements);
+    ae->type = type;
+    return ae;
+}
+
+
+/********************************
+ * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp.
+ */
+StructLiteralExp *createDefaultInitStructLiteral(Loc loc, StructDeclaration *sym)
+{
+    Expressions *structelems = new Expressions();
+    structelems->setDim(sym->fields.dim);
+    for (size_t j = 0; j < structelems->dim; j++)
+    {
+	structelems->data[j] = ((VarDeclaration *)(sym->fields.data[j]))->type->defaultInit();
+    }
+    StructLiteralExp *structinit = new StructLiteralExp(loc, sym, structelems);
+    // Why doesn't the StructLiteralExp constructor do this, when
+    // sym->type != NULL ?
+    structinit->type = sym->type;
+    return structinit;
+}
+
+/********************************
+ *  Add v to the istate list, unless it already exists there.
+ */
+void addVarToInterstate(InterState *istate, VarDeclaration *v)
+{
+    if (!v->isParameter())
+    {
+	for (size_t i = 0; 1; i++)
+	{
+	    if (i == istate->vars.dim)
+	    {   istate->vars.push(v);
+		//printf("\tadding %s to istate\n", v->toChars());
+		break;
+	    }
+	    if (v == (VarDeclaration *)istate->vars.data[i])
+		break;
+	}
+    }
+}
+
 Expression *BinExp::interpretAssignCommon(InterState *istate, fp_t fp, int post)
 {
 #if LOG
@@ -1453,7 +1600,40 @@
     Expression *e2 = this->e2->interpret(istate);
     if (e2 == EXP_CANT_INTERPRET)
 	return e2;
+	
+    // Chase down rebinding of out and ref.
+    if (e1->op == TOKvar)
+    {
+	VarExp *ve = (VarExp *)e1;
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (v && v->value && v->value->op == TOKvar)
+	{
+	    VarExp *ve2 = (VarExp *)v->value;
+	    if (ve2->var->isStaticStructInitDeclaration())
+	    {	// This can happen if v is a struct initialized to
+		// 0 using an __initZ StaticStructInitDeclaration from
+		// TypeStruct::defaultInit()
+	    }
+	    else
+		e1 = v->value;
+	}
+	else if (v && v->value && (v->value->op==TOKindex || v->value->op == TOKdotvar))
+	{
+            // It is no longer be a TOKvar, eg when a[4] is passed by ref.
+	    e1 = v->value;	    
+	}
+    }
 
+    // To reduce code complexity of handling dotvar expressions,
+    // extract the aggregate now.
+    Expression *aggregate;
+    if (e1->op == TOKdotvar) {
+        aggregate = ((DotVarExp *)e1)->e1;
+	// Get rid of 'this'.
+        if (aggregate->op == TOKthis && istate->localThis)
+            aggregate = istate->localThis;	
+    }
+    
     /* Assignment to variable of the form:
      *	v = e2
      */
@@ -1461,25 +1641,14 @@
     {
 	VarExp *ve = (VarExp *)e1;
 	VarDeclaration *v = ve->var->isVarDeclaration();
+	assert(v);
+   	if (v && v->isDataseg())
+	{   // Can't modify global or static data
+	    error("%s cannot be modified at compile time", v->toChars());
+	    return EXP_CANT_INTERPRET;
+	}
 	if (v && !v->isDataseg())
 	{
-	    /* Chase down rebinding of out and ref
-	     */
-	    if (v->value && v->value->op == TOKvar)
-	    {
-		VarExp *ve2 = (VarExp *)v->value;
-		if (ve2->var->isStaticStructInitDeclaration())
-		{
-		    /* This can happen if v is a struct initialized to
-		     * 0 using an StaticStructInitDeclaration from
-		     * TypeStruct::defaultInit()
-		     */
-		}
-		else
-		    v = ve2->var->isVarDeclaration();
-		assert(v);
-	    }
-
 	    Expression *ev = v->value;
 	    if (fp && !ev)
 	    {	error("variable %s is used before initialization", v->toChars());
@@ -1496,35 +1665,43 @@
 		}
 		e2 = Cast(v->type, v->type, e2);
 	    }
-	    if (e2 != EXP_CANT_INTERPRET)
-	    {
-		if (!v->isParameter())
-		{
-		    for (size_t i = 0; 1; i++)
-		    {
-			if (i == istate->vars.dim)
-			{   istate->vars.push(v);
-			    //printf("\tadding %s to istate\n", v->toChars());
-			    break;
-			}
-			if (v == (VarDeclaration *)istate->vars.data[i])
-			    break;
-		    }
-		}
-		v->value = e2;
-		e = Cast(type, type, post ? ev : e2);
-	    }
+	    if (e2 == EXP_CANT_INTERPRET)
+		return e2;
+
+	    addVarToInterstate(istate, v);
+	    v->value = e2;
+	    e = Cast(type, type, post ? ev : e2);
 	}
     }
+    else if (e1->op == TOKdotvar && aggregate->op == TOKdotvar)
+    {	// eg  v.u.var = e2,  v[3].u.var = e2, etc.
+	error("Nested struct assignment %s is not yet supported in CTFE", toChars());
+    }
     /* Assignment to struct member of the form:
      *   v.var = e2
      */
-    else if (e1->op == TOKdotvar && ((DotVarExp *)e1)->e1->op == TOKvar)
-    {	VarExp *ve = (VarExp *)((DotVarExp *)e1)->e1;
-	VarDeclaration *v = ve->var->isVarDeclaration();
+    else if (e1->op == TOKdotvar && aggregate->op == TOKvar)
+    {	VarDeclaration *v = ((VarExp *)aggregate)->var->isVarDeclaration();
 
 	if (v->isDataseg())
+	{   // Can't modify global or static data
+	    error("%s cannot be modified at compile time", v->toChars());
 	    return EXP_CANT_INTERPRET;
+	} else {
+	    // Chase down rebinding of out and ref
+	    if (v->value && v->value->op == TOKvar)
+	    {
+		VarExp *ve2 = (VarExp *)v->value;
+		if (ve2->var->isStaticStructInitDeclaration())
+		{	// This can happen if v is a struct initialized to
+			// 0 using an __initZ StaticStructInitDeclaration from
+			// TypeStruct::defaultInit()
+		}
+		else
+		    v = ve2->var->isVarDeclaration();
+		assert(v);
+	    }
+	}
 	if (fp && !v->value)
 	{   error("variable %s is used before initialization", v->toChars());
 	    return e;
@@ -1561,30 +1738,11 @@
 	if (e2 == EXP_CANT_INTERPRET)
 	    return e2;
 
-	if (!v->isParameter())
-	{
-	    for (size_t i = 0; 1; i++)
-	    {
-		if (i == istate->vars.dim)
-		{   istate->vars.push(v);
-		    break;
-		}
-		if (v == (VarDeclaration *)istate->vars.data[i])
-		    break;
-	    }
-	}
+	addVarToInterstate(istate, v);
 
 	/* Create new struct literal reflecting updated fieldi
 	 */
-	Expressions *expsx = new Expressions();
-	expsx->setDim(se->elements->dim);
-	for (size_t j = 0; j < expsx->dim; j++)
-	{
-	    if (j == fieldi)
-		expsx->data[j] = (void *)e2;
-	    else
-		expsx->data[j] = se->elements->data[j];
-	}
+	Expressions *expsx = changeOneElement(se->elements, fieldi, e2);
 	v->value = new StructLiteralExp(se->loc, se->sd, expsx);
 	v->value->type = se->type;
 
@@ -1598,7 +1756,10 @@
 	VarDeclaration *v = soe->var->isVarDeclaration();
 
 	if (v->isDataseg())
+	{
+	    error("%s cannot be modified at compile time", v->toChars());
 	    return EXP_CANT_INTERPRET;
+	}
 	if (fp && !v->value)
 	{   error("variable %s is used before initialization", v->toChars());
 	    return e;
@@ -1623,30 +1784,11 @@
 	if (e2 == EXP_CANT_INTERPRET)
 	    return e2;
 
-	if (!v->isParameter())
-	{
-	    for (size_t i = 0; 1; i++)
-	    {
-		if (i == istate->vars.dim)
-		{   istate->vars.push(v);
-		    break;
-		}
-		if (v == (VarDeclaration *)istate->vars.data[i])
-		    break;
-	    }
-	}
+   	addVarToInterstate(istate, v);
 
 	/* Create new struct literal reflecting updated fieldi
 	 */
-	Expressions *expsx = new Expressions();
-	expsx->setDim(se->elements->dim);
-	for (size_t j = 0; j < expsx->dim; j++)
-	{
-	    if (j == fieldi)
-		expsx->data[j] = (void *)e2;
-	    else
-		expsx->data[j] = se->elements->data[j];
-	}
+	Expressions *expsx = changeOneElement(se->elements, fieldi, e2);
 	v->value = new StructLiteralExp(se->loc, se->sd, expsx);
 	v->value->type = se->type;
 
@@ -1659,9 +1801,23 @@
     {	IndexExp *ie = (IndexExp *)e1;
 	VarExp *ve = (VarExp *)ie->e1;
 	VarDeclaration *v = ve->var->isVarDeclaration();
-
 	if (!v || v->isDataseg())
+	{
+	    error("%s cannot be modified at compile time", v ? v->toChars(): "void");
 	    return EXP_CANT_INTERPRET;
+	}
+	    if (v->value && v->value->op == TOKvar)
+	    {
+		VarExp *ve2 = (VarExp *)v->value;
+		if (ve2->var->isStaticStructInitDeclaration())
+		{	// This can happen if v is a struct initialized to
+			// 0 using an __initZ StaticStructInitDeclaration from
+			// TypeStruct::defaultInit()
+		}
+		else
+		    v = ve2->var->isVarDeclaration();
+		assert(v);
+	    }
 	if (!v->value)
 	{
 	    if (fp)
@@ -1679,15 +1835,10 @@
 		 * But we're too lazy at the moment to do it, as that
 		 * involves redoing Index() and whoever calls it.
 		 */
-		Expression *ev = v->type->defaultInit();
+
 		size_t dim = ((TypeSArray *)t)->dim->toInteger();
-		Expressions *elements = new Expressions();
-		elements->setDim(dim);
-		for (size_t i = 0; i < dim; i++)
-		    elements->data[i] = (void *)ev;
-		ArrayLiteralExp *ae = new ArrayLiteralExp(0, elements);
-		ae->type = v->type;
-		v->value = ae;
+	        v->value = createBlockDuplicatedArrayLiteral(v->type,
+			v->type->defaultInit(), dim);
 	    }
 	    else
 		return EXP_CANT_INTERPRET;
@@ -1702,9 +1853,20 @@
 	    aae = (AssocArrayLiteralExp *)v->value;
 	else if (v->value->op == TOKstring)
 	    se = (StringExp *)v->value;
+	else if (v->value->op == TOKnull)
+	{
+	    // This would be a runtime segfault
+	    error("Cannot index null array %s", v->toChars());
+	    return EXP_CANT_INTERPRET;
+	}
 	else
 	    return EXP_CANT_INTERPRET;
 
+	/* Set the $ variable
+	 */
+	Expression *ee = ArrayLength(Type::tsize_t, v->value);
+	if (ee != EXP_CANT_INTERPRET && ie->lengthVar)
+	    ie->lengthVar->value = ee;
 	Expression *index = ie->e2->interpret(istate);
 	if (index == EXP_CANT_INTERPRET)
 	    return EXP_CANT_INTERPRET;
@@ -1722,34 +1884,14 @@
 	    e2 = Cast(type, type, e2);
 	if (e2 == EXP_CANT_INTERPRET)
 	    return e2;
-
-	if (!v->isParameter())
-	{
-	    for (size_t i = 0; 1; i++)
-	    {
-		if (i == istate->vars.dim)
-		{   istate->vars.push(v);
-		    break;
-		}
-		if (v == (VarDeclaration *)istate->vars.data[i])
-		    break;
-	    }
-	}
-
+	
+	addVarToInterstate(istate, v);
 	if (ae)
 	{
 	    /* Create new array literal reflecting updated elem
 	     */
 	    int elemi = index->toInteger();
-	    Expressions *expsx = new Expressions();
-	    expsx->setDim(ae->elements->dim);
-	    for (size_t j = 0; j < expsx->dim; j++)
-	    {
-		if (j == elemi)
-		    expsx->data[j] = (void *)e2;
-		else
-		    expsx->data[j] = ae->elements->data[j];
-	    }
+	    Expressions *expsx = changeOneElement(ae->elements, elemi, e2);
 	    v->value = new ArrayLiteralExp(ae->loc, expsx);
 	    v->value->type = ae->type;
 	}
@@ -1812,8 +1954,245 @@
 
 	e = Cast(type, type, post ? ev : e2);
     }
+    
+    /* Assignment to struct element in array, of the form:
+     *  a[i].var = e2
+     */
+    else if (e1->op == TOKdotvar && aggregate->op == TOKindex &&
+	     ((IndexExp *)aggregate)->e1->op == TOKvar)
+    {
+        IndexExp * ie = (IndexExp *)aggregate;
+	VarExp *ve = (VarExp *)(ie->e1);
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (!v || v->isDataseg())
+	{
+	    error("%s cannot be modified at compile time", v ? v->toChars(): "void");
+	    return EXP_CANT_INTERPRET;
+	}
+	Type *t = ve->type->toBasetype();
+	ArrayLiteralExp *ae = (ArrayLiteralExp *)v->value;
+	if (!ae)
+	{
+	    // assignment to one element in an uninitialized (static) array.
+	    // This is quite difficult, because defaultInit() for a struct is a VarExp,
+	    // not a StructLiteralExp.
+	    Type *t = v->type->toBasetype();
+	    if (t->ty != Tsarray)
+	    {
+		error("Cannot index an uninitialized variable");
+		return EXP_CANT_INTERPRET;
+	    }
+
+	    Type *telem = ((TypeSArray *)t)->nextOf()->toBasetype();
+	    if (telem->ty != Tstruct) { return EXP_CANT_INTERPRET; }
+
+	    // Create a default struct literal...
+	    StructDeclaration *sym = ((TypeStruct *)telem)->sym;
+	    StructLiteralExp *structinit = createDefaultInitStructLiteral(v->loc, sym);
+
+	    // ... and use to create a blank array literal
+	    size_t dim = ((TypeSArray *)t)->dim->toInteger();
+	    ae = createBlockDuplicatedArrayLiteral(v->type, structinit, dim);
+	    v->value = ae;
+	}
+	if ((Expression *)(ae->elements) == EXP_CANT_INTERPRET)
+	{
+	    // Note that this would be a runtime segfault
+	    error("Cannot index null array %s", v->toChars());
+	    return EXP_CANT_INTERPRET;
+	}
+	// Set the $ variable
+	Expression *ee = ArrayLength(Type::tsize_t, v->value);
+	if (ee != EXP_CANT_INTERPRET && ie->lengthVar)
+	    ie->lengthVar->value = ee;
+	// Determine the index, and check that it's OK.
+	Expression *index = ie->e2->interpret(istate);
+	if (index == EXP_CANT_INTERPRET)
+	    return EXP_CANT_INTERPRET;
+
+	int elemi = index->toInteger();
+	if (elemi >= ae->elements->dim)
+	{
+	    error("array index %d is out of bounds %s[0..%d]", elemi,
+		v->toChars(), ae->elements->dim);
+	    return EXP_CANT_INTERPRET;
+	}
+	// Get old element
+	Expression *vie = (Expression *)(ae->elements->data[elemi]);
+	if (vie->op != TOKstructliteral)
+	    return EXP_CANT_INTERPRET;
+
+	// Work out which field needs to be changed
+	StructLiteralExp *se = (StructLiteralExp *)vie;
+	VarDeclaration *vf = ((DotVarExp *)e1)->var->isVarDeclaration();
+	if (!vf)
+	    return EXP_CANT_INTERPRET;
+
+	int fieldi = se->getFieldIndex(type, vf->offset);
+	if (fieldi == -1)
+	    return EXP_CANT_INTERPRET;
+		
+	Expression *ev = se->getField(type, vf->offset);
+	if (fp)
+	    e2 = (*fp)(type, ev, e2);
+	else
+	    e2 = Cast(type, type, e2);
+	if (e2 == EXP_CANT_INTERPRET)
+	    return e2;
+
+	// Create new struct literal reflecting updated field
+	Expressions *expsx = changeOneElement(se->elements, fieldi, e2);
+	Expression * newstruct = new StructLiteralExp(se->loc, se->sd, expsx);
+
+	// Create new array literal reflecting updated struct elem
+	ae->elements = changeOneElement(ae->elements, elemi, newstruct);
+	return ae;
+    }
+    /* Slice assignment, initialization of static arrays
+     *   a[] = e
+     */
+    else if (e1->op == TOKslice && ((SliceExp *)e1)->e1->op==TOKvar)
+    {
+        SliceExp * sexp = (SliceExp *)e1;
+	VarExp *ve = (VarExp *)(sexp->e1);
+	VarDeclaration *v = ve->var->isVarDeclaration();
+	if (!v || v->isDataseg())
+	{
+	    error("%s cannot be modified at compile time", v->toChars());
+	    return EXP_CANT_INTERPRET;
+	}
+	    // Chase down rebinding of out and ref
+	    if (v->value && v->value->op == TOKvar)
+	    {
+		VarExp *ve2 = (VarExp *)v->value;
+		if (ve2->var->isStaticStructInitDeclaration())
+		{	// This can happen if v is a struct initialized to
+			// 0 using an __initZ StaticStructInitDeclaration from
+			// TypeStruct::defaultInit()
+		}
+		else
+		    v = ve2->var->isVarDeclaration();
+		assert(v);
+	    }
+	/* Set the $ variable
+	 */
+	Expression *ee = v->value ? ArrayLength(Type::tsize_t, v->value)
+				  : EXP_CANT_INTERPRET;
+	if (ee != EXP_CANT_INTERPRET && sexp->lengthVar)
+	    sexp->lengthVar->value = ee;
+	Expression *upper = NULL;
+	Expression *lower = NULL;
+	if (sexp->upr)
+	{
+	    upper = sexp->upr->interpret(istate);
+	    if (upper == EXP_CANT_INTERPRET)
+		return EXP_CANT_INTERPRET;
+	}
+	if (sexp->lwr)
+	{
+	    lower = sexp->lwr->interpret(istate);
+	    if (lower == EXP_CANT_INTERPRET)
+		return EXP_CANT_INTERPRET;
+	}
+	Type *t = v->type->toBasetype();
+	size_t dim;
+	if (t->ty == Tsarray)			
+	    dim = ((TypeSArray *)t)->dim->toInteger();
+	else if (t->ty == Tarray)
+	{
+	    if (!v->value || v->value->op == TOKnull)
+	    {
+		error("cannot assign to null array %s", v->toChars());
+		return EXP_CANT_INTERPRET;
+	    }
+	    if (v->value->op == TOKarrayliteral)
+		dim = ((ArrayLiteralExp *)v->value)->elements->dim;
+	    else if (v->value->op ==TOKstring)
+	    {
+		error("String slice assignment is not yet supported in CTFE");
+		return EXP_CANT_INTERPRET;
+	    }
+	}
+	else
+	{
+	    error("%s cannot be evaluated at compile time", toChars());
+	    return EXP_CANT_INTERPRET;
+	}
+	int upperbound = upper ? upper->toInteger() : dim;
+	int lowerbound = lower ? lower->toInteger() : 0;
+
+	ArrayLiteralExp *existing;
+	if (((int)lowerbound < 0) || (upperbound > dim))
+	{
+	    error("Array bounds [0..%d] exceeded in slice [%d..%d]", dim, lowerbound, upperbound);
+	    return EXP_CANT_INTERPRET;
+	}
+	if (upperbound-lowerbound != dim)
+	{
+	    // Only modifying part of the array. Must create a new array literal.
+	    // If the existing array is uninitialized (this can only happen
+	    // with static arrays), create it.
+	    if (v->value && v->value->op == TOKarrayliteral)
+		    existing = (ArrayLiteralExp *)v->value;
+	    else
+	    {
+		// this can only happen with static arrays
+		existing = createBlockDuplicatedArrayLiteral(v->type, v->type->defaultInit(), dim);
+	    }
+	}
+
+	if (e2->op == TOKarrayliteral)
+	{
+	    // Static array assignment from literal
+	    ArrayLiteralExp *ae = (ArrayLiteralExp *)e2;				
+	    if (ae->elements->dim != (upperbound - lowerbound))
+	    {
+		error("Array length mismatch assigning [0..%d] to [%d..%d]", ae->elements->dim, lowerbound, upperbound);
+		return e;
+	    }
+	    if (upperbound - lowerbound == dim)
+		v->value = ae;
+	    else
+	    {
+		// value[] = value[0..lower] ~ ae ~ value[upper..$]
+		existing->elements = spliceElements(existing->elements, ae->elements, lowerbound);
+		v->value = existing;
+	    }
+	    return e2;
+	}
+	else if (t->nextOf()->ty == e2->type->ty)
+	{
+	     // Static array block assignment
+	    if (upperbound-lowerbound ==dim)
+		v->value = createBlockDuplicatedArrayLiteral(v->type, e2, dim);
+	    else
+	    {
+		// value[] = value[0..lower] ~ ae ~ value[upper..$]
+		existing->elements = spliceElements(existing->elements, createBlockDuplicatedArrayLiteral(v->type, e2, upperbound-lowerbound)->elements, lowerbound);
+		v->value = existing;
+	    }				
+	    return e2;
+	}
+	else if (e2->op == TOKstring)
+	{
+	    StringExp *se = (StringExp *)e2;
+	    // This is problematic. char[8] should be storing
+	    // values as a string literal, not
+	    // as an array literal. Then, for static arrays, we
+	    // could do modifications
+	    // in-place, with a dramatic memory and speed improvement.
+	    error("String slice assignment is not yet supported in CTFE");
+	    return e2;
+	}
+	else
+	{
+	    error("Slice operation %s cannot be evaluated at compile time", toChars());
+	    return e;
+	}
+    }
     else
     {
+	error("%s cannot be evaluated at compile time", toChars());
 #ifdef DEBUG
 	dump(0);
 #endif
@@ -1927,6 +2306,27 @@
 #if LOG
     printf("CallExp::interpret() %s\n", toChars());
 #endif
+    if (e1->op == TOKdotvar)
+    {
+        Expression * pthis = ((DotVarExp*)e1)->e1;
+	FuncDeclaration *fd = ((DotVarExp*)e1)->var->isFuncDeclaration();
+	TypeFunction *tf = fd ? (TypeFunction *)(fd->type) : NULL;
+	if (tf)
+	{   // Member function call
+	    if(pthis->op == TOKthis)
+		pthis = istate->localThis;	    
+	    Expression *eresult = fd->interpret(istate, arguments, pthis);
+	    if (eresult)
+		e = eresult;
+	    else if (fd->type->toBasetype()->nextOf()->ty == Tvoid && !global.errors)
+		e = EXP_VOID_INTERPRET;
+	    else
+		error("cannot evaluate %s at compile time", toChars());
+	    return e;
+	} 
+	error("cannot evaluate %s at compile time", toChars());
+        return EXP_CANT_INTERPRET;
+    }
     if (e1->op == TOKvar)
     {
 	FuncDeclaration *fd = ((VarExp *)e1)->var->isFuncDeclaration();
@@ -2159,6 +2559,17 @@
 #if LOG
     printf("AssertExp::interpret() %s\n", toChars());
 #endif
+    if( this->e1->op == TOKaddress)
+    {   // Special case: deal with compiler-inserted assert(&this, "null this") 
+	AddrExp *ade = (AddrExp *)this->e1;
+	if(ade->e1->op == TOKthis && istate->localThis)   	
+	return istate->localThis->interpret(istate);
+    }
+if (this->e1->op == TOKthis)
+{
+	if(istate->localThis)   	
+	return istate->localThis->interpret(istate);
+}    
     e1 = this->e1->interpret(istate);
     if (e1 == EXP_CANT_INTERPRET)
 	goto Lcant;
@@ -2227,6 +2638,14 @@
 	    }
 	}
     }
+#if DMDV2
+#else // this is required for D1, where structs return *this instead of 'this'.    
+    else if (e1->op == TOKthis)
+    {
+    	if(istate->localThis)   	
+	    return istate->localThis->interpret(istate);
+    }
+#endif    
 #if LOG
     if (e == EXP_CANT_INTERPRET)
 	printf("PtrExp::interpret() %s = EXP_CANT_INTERPRET\n", toChars());
@@ -2253,7 +2672,7 @@
 		    e = EXP_CANT_INTERPRET;
 		return e;
 	    }
-	}
+	} else error("%s.%s is not yet implemented at compile time", ex->toChars(), var->toChars());
     }
 
 #if LOG
@@ -2282,7 +2701,9 @@
 
 Expression *interpret_aaKeys(InterState *istate, Expressions *arguments)
 {
-    //printf("interpret_aaKeys()\n");
+#if LOG
+    printf("interpret_aaKeys()\n");
+#endif
     if (!arguments || arguments->dim != 2)
 	return NULL;
     Expression *earg = (Expression *)arguments->data[0];
--- a/dmd2/lexer.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/lexer.c	Tue Sep 08 10:07:56 2009 +0100
@@ -1160,6 +1160,7 @@
 	    SINGLE(';', TOKsemicolon)
 	    SINGLE(':', TOKcolon)
 	    SINGLE('$', TOKdollar)
+	    SINGLE('@', TOKat)
 
 #undef SINGLE
 
@@ -3088,6 +3089,7 @@
 
     Token::tochars[TOKorass]		= "|=";
     Token::tochars[TOKidentifier]	= "identifier";
+    Token::tochars[TOKat]		= "@";
 
      // For debugging
     Token::tochars[TOKdotexp]		= "dotexp";
--- a/dmd2/lexer.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/lexer.h	Tue Sep 08 10:07:56 2009 +0100
@@ -31,7 +31,7 @@
 	+	-	+=	-=
 	*	/	%	*=	/=	%=
 	&	| 	^	&=	|=	^=
-	=	!	~
+	=	!	~	@
 	++	--
 	.	->	:	,
 	?	&&	||
@@ -159,7 +159,8 @@
 	TOKgshared,
 	TOKline,
 	TOKfile,
-    TOKshared,
+	TOKshared,
+	TOKat,
 #endif
 
 // LDC specific
--- a/dmd2/mangle.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/mangle.c	Tue Sep 08 10:07:56 2009 +0100
@@ -122,7 +122,7 @@
 		    return ident->toChars();
 
 		case LINKcpp:
-#if DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS)
+#if CPP_MANGLE
 		    return cpp_mangle(this);
 #else
 		    // Windows C++ mangling is done by C++ back end
--- a/dmd2/mars.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/mars.c	Tue Sep 08 10:07:56 2009 +0100
@@ -98,7 +98,7 @@
     "\nMSIL back-end (alpha release) by Cristian L. Vlasceanu and associates.";
 #endif
     ;
-    version = "v2.031";
+    version = "v2.032";
 #if IN_LLVM
     ldc_version = LDC_REV;
     llvm_version = LLVM_REV_STR;
--- a/dmd2/mars.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/mars.h	Tue Sep 08 10:07:56 2009 +0100
@@ -95,6 +95,9 @@
 #define STRUCTTHISREF DMDV2	// if 'this' for struct is a reference, not a pointer
 #define SNAN_DEFAULT_INIT DMDV2	// if floats are default initialized to signalling NaN
 
+// Set if C++ mangling is done by the front end
+#define CPP_MANGLE (DMDV2 && (TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS))
+
 /* Other targets are TARGET_LINUX, TARGET_OSX, TARGET_FREEBSD and
  * TARGET_SOLARIS, which are
  * set on the command line via the compiler makefile.
--- a/dmd2/mtype.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/mtype.c	Tue Sep 08 10:07:56 2009 +0100
@@ -198,6 +198,7 @@
 	sizeTy[i] = sizeof(TypeBasic);
     sizeTy[Tsarray] = sizeof(TypeSArray);
     sizeTy[Tarray] = sizeof(TypeDArray);
+    //sizeTy[Tnarray] = sizeof(TypeNArray);
     sizeTy[Taarray] = sizeof(TypeAArray);
     sizeTy[Tpointer] = sizeof(TypePointer);
     sizeTy[Treference] = sizeof(TypeReference);
@@ -216,6 +217,7 @@
 
     mangleChar[Tarray] = 'A';
     mangleChar[Tsarray] = 'G';
+    mangleChar[Tnarray] = '@';
     mangleChar[Taarray] = 'H';
     mangleChar[Tpointer] = 'P';
     mangleChar[Treference] = 'R';
@@ -1151,6 +1153,16 @@
     }
 }
 
+void Type::modToBuffer(OutBuffer *buf)
+{
+    if (mod & MODshared)
+        buf->writestring(" shared");
+    if (mod & MODconst)
+        buf->writestring(" const");
+    if (mod & MODinvariant)
+        buf->writestring(" immutable");
+}
+
 /************************************
  */
 
@@ -1651,6 +1663,12 @@
     return next->reliesOnTident();
 }
 
+/*******************************
+ * For TypeFunction, nextOf() can return NULL if the function return
+ * type is meant to be inferred, and semantic() hasn't yet ben run
+ * on the function. After semantic(), it must no longer be NULL.
+ */
+
 Type *TypeNext::nextOf()
 {
     return next;
@@ -3251,6 +3269,88 @@
     return TRUE;
 }
 
+
+/***************************** TypeNewArray *****************************/
+
+#if 0
+
+TypeNewArray::TypeNewArray(Type *telement)
+	: TypeArray(Tnewarray, telement)
+{
+    sym = NULL;
+}
+
+Type *TypeNewArray::syntaxCopy()
+{
+    Type *t = next->syntaxCopy();
+    if (t == next)
+	t = this;
+    else
+    {	t = new TypeNewArray(t);
+	t->mod = mod;
+    }
+    return t;
+}
+
+d_uns64 TypeNewArray::size(Loc loc)
+{
+    //printf("TypeNewArray::size()\n");
+    return PTRSIZE;
+}
+
+unsigned TypeNewArray::alignsize()
+{
+    return PTRSIZE;
+}
+
+Type *TypeNewArray::semantic(Loc loc, Scope *sc)
+{   Type *tn = next;
+
+    tn = next->semantic(loc,sc);
+    Type *tbn = tn->toBasetype();
+    switch (tbn->ty)
+    {
+	case Tfunction:
+	case Tnone:
+	case Ttuple:
+	    error(loc, "can't have array of %s", tbn->toChars());
+	    tn = next = tint32;
+	    break;
+	case Tstruct:
+	{   TypeStruct *ts = (TypeStruct *)tbn;
+	    if (ts->sym->isnested)
+		error(loc, "cannot have array of inner structs %s", ts->toChars());
+	    break;
+	}
+    }
+    if (tn->isauto())
+	error(loc, "cannot have array of auto %s", tn->toChars());
+
+    next = tn;
+    transitive();
+    return merge();
+}
+
+void TypeNewArray::toDecoBuffer(OutBuffer *buf, int flag)
+{
+    Type::toDecoBuffer(buf, flag);
+    buf->writeByte('e');
+    if (next)
+	next->toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
+}
+
+void TypeNewArray::toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod)
+{
+    if (mod != this->mod)
+    {	toCBuffer3(buf, hgs, mod);
+	return;
+    }
+    next->toCBuffer2(buf, hgs, this->mod);
+    buf->writestring("[new]");
+}
+
+#endif
+
 /***************************** TypeAArray *****************************/
 
 TypeAArray::TypeAArray(Type *t, Type *index)
@@ -3774,6 +3874,7 @@
     this->inuse = 0;
     this->isnothrow = false;
     this->ispure = false;
+    this->isproperty = false;
     this->isref = false;
 
 #if IN_LLVM
@@ -3789,6 +3890,7 @@
     t->mod = mod;
     t->isnothrow = isnothrow;
     t->ispure = ispure;
+    t->isproperty = isproperty;
     t->isref = isref;
     return t;
 }
@@ -3958,8 +4060,7 @@
 	    assert(0);
     }
     buf->writeByte(mc);
-
-    if (ispure || isnothrow || isref)
+    if (ispure || isnothrow || isproperty || isref)
     {
 	if (ispure)
 	    buf->writestring("Na");
@@ -3967,6 +4068,8 @@
 	    buf->writestring("Nb");
 	if (isref)
 	    buf->writestring("Nc");
+	if (isproperty)
+	    buf->writestring("Nd");
     }
 
     // LDC: if we're not producing a mangle string, add the this
@@ -4026,6 +4129,8 @@
 	buf->writestring("pure ");
     if (isnothrow)
 	buf->writestring("nothrow ");
+    if (isproperty)
+	buf->writestring("@property ");
     if (isref)
 	buf->writestring("ref ");
 
@@ -4098,17 +4203,14 @@
      */
     if (mod != this->mod)
     {
-	if (mod & MODconst)
-	    buf->writestring(" const");
-	if (mod & MODinvariant)
-	    buf->writestring(" immutable");
-	if (mod & MODshared)
-	    buf->writestring(" shared");
+	modToBuffer(buf);
     }
     if (ispure)
 	buf->writestring(" pure");
     if (isnothrow)
 	buf->writestring(" nothrow");
+    if (isproperty)
+	buf->writestring(" @property");
     if (isref)
 	buf->writestring(" ref");
 
@@ -6170,7 +6272,7 @@
 {
     if (mod)
 	return Type::toChars();
-    return sym->toPrettyChars();
+    return (char *)sym->toPrettyChars();
 }
 
 Type *TypeClass::syntaxCopy()
--- a/dmd2/mtype.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/mtype.h	Tue Sep 08 10:07:56 2009 +0100
@@ -60,9 +60,10 @@
 
 enum ENUMTY
 {
-    Tarray,		// dynamic array
-    Tsarray,		// static array
-    Taarray,		// associative array
+    Tarray,		// slice array, aka T[]
+    Tsarray,		// static array, aka T[dimension]
+    Tnarray,		// resizable array, aka T[new]
+    Taarray,		// associative array, aka T[type]
     Tpointer,
     Treference,
     Tfunction,
@@ -128,7 +129,10 @@
 	#define MODshared    2	// type is shared
     char *deco;
 
-    /* Note that there is no "shared immutable", because that is just immutable
+    /* These are cached values that are lazily evaluated by constOf(), invariantOf(), etc.
+     * They should not be referenced by anybody but mtype.c.
+     * They can be NULL if not lazily evaluated yet.
+     * Note that there is no "shared immutable", because that is just immutable
      */
 
     Type *cto;		// MODconst ? mutable version of this type : const version
@@ -242,7 +246,8 @@
     virtual void toCBuffer(OutBuffer *buf, Identifier *ident, HdrGenState *hgs);
     virtual void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
     void toCBuffer3(OutBuffer *buf, HdrGenState *hgs, int mod);
-#if POSIX
+    void modToBuffer(OutBuffer *buf);
+#if CPP_MANGLE
     virtual void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
     virtual int isintegral();
@@ -359,7 +364,7 @@
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     char *toChars();
     void toCBuffer2(OutBuffer *buf, HdrGenState *hgs, int mod);
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
     int isintegral();
@@ -413,7 +418,7 @@
     TypeInfoDeclaration *getTypeInfoDeclaration();
     Expression *toExpression();
     int hasPointers();
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 
@@ -443,7 +448,7 @@
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 
@@ -472,7 +477,7 @@
     int hasPointers();
     MATCH implicitConvTo(Type *to);
     MATCH constConv(Type *to);
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 
@@ -500,7 +505,7 @@
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
 
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 
@@ -519,7 +524,7 @@
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     Expression *defaultInit(Loc loc);
     int isZeroInit(Loc loc);
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 };
@@ -539,6 +544,7 @@
 			// 2: T t ...) style for variable number of arguments
     bool isnothrow;	// true: nothrow
     bool ispure;	// true: pure
+    bool isproperty;	// can be called without parentheses
     bool isref;		// true: returns a reference
     enum LINK linkage;	// calling convention
 
@@ -553,7 +559,7 @@
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     TypeInfoDeclaration *getTypeInfoDeclaration();
     Type *reliesOnTident();
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
     bool parameterEscapes(Argument *p);
@@ -591,7 +597,7 @@
     TypeInfoDeclaration *getTypeInfoDeclaration();
     Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
     int hasPointers();
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 
@@ -697,7 +703,7 @@
     MATCH implicitConvTo(Type *to);
     MATCH constConv(Type *to);
     Type *toHeadMutable();
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 
@@ -738,7 +744,7 @@
     MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 
@@ -784,7 +790,7 @@
     TypeInfoDeclaration *getTypeInfoDeclaration();
     int hasPointers();
     Type *toHeadMutable();
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 
@@ -821,7 +827,7 @@
 #if DMDV2
     Type *toHeadMutable();
     MATCH constConv(Type *to);
-#if POSIX
+#if CPP_MANGLE
     void toCppMangle(OutBuffer *buf, CppMangleState *cms);
 #endif
 #endif
--- a/dmd2/optimize.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/optimize.c	Tue Sep 08 10:07:56 2009 +0100
@@ -86,6 +86,8 @@
 		    e = ei->syntaxCopy();
 		    e = e->semantic(v->scope);
 		    e = e->implicitCastTo(v->scope, v->type);
+		    // enabling this line causes test22 in test suite to fail
+		    //ei->type = e->type;
 		    v->scope = NULL;
 		    v->inuse--;
 		}
@@ -426,11 +428,50 @@
     return this;
 }
 
+Expression *NewExp::optimize(int result)
+{
+    if (thisexp)
+	thisexp = thisexp->optimize(WANTvalue);
+
+    // Optimize parameters
+    if (newargs)
+    {
+	for (size_t i = 0; i < newargs->dim; i++)
+	{   Expression *e = (Expression *)newargs->data[i];
+
+	    e = e->optimize(WANTvalue);
+	    newargs->data[i] = (void *)e;
+	}
+    }
+
+    if (arguments)
+    {
+	for (size_t i = 0; i < arguments->dim; i++)
+	{   Expression *e = (Expression *)arguments->data[i];
+
+	    e = e->optimize(WANTvalue);
+	    arguments->data[i] = (void *)e;
+	}
+    }
+    return this;
+}
+
 Expression *CallExp::optimize(int result)
 {
     //printf("CallExp::optimize(result = %d) %s\n", result, toChars());
     Expression *e = this;
 
+    // Optimize parameters
+    if (arguments)
+    {
+	for (size_t i = 0; i < arguments->dim; i++)
+	{   Expression *e = (Expression *)arguments->data[i];
+
+	    e = e->optimize(WANTvalue);
+	    arguments->data[i] = (void *)e;
+	}
+    }
+
     e1 = e1->optimize(result);
     if (e1->op == TOKvar)
     {
@@ -792,7 +833,8 @@
     e2 = e2->optimize(WANTvalue | (result & WANTinterpret));
     e = this;
 
-    if (this->e1->isConst() && this->e2->isConst())
+    if ((this->e1->isConst()     && this->e2->isConst()) ||
+	(this->e1->op == TOKnull && this->e2->op == TOKnull))
     {
 	e = Identity(op, type, this->e1, this->e2);
     }
--- a/dmd2/parse.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/parse.c	Tue Sep 08 10:07:56 2009 +0100
@@ -2266,7 +2266,7 @@
 		nextToken();
 		arguments = parseParameters(&varargs);
 		while (1)
-		{   // Postfixes of 'pure' or 'nothrow'
+		{   // Postfixes
 		    if (token.value == TOKpure)
 			ispure = true;
 		    else if (token.value == TOKnothrow)
@@ -2433,6 +2433,22 @@
 			    ((TypeFunction *)tf)->ispure = 1;
 			    nextToken();
 			    continue;
+
+			case TOKat:
+			    nextToken();
+			    if (token.value != TOKidentifier)
+			    {   error("attribute identifier expected");
+				nextToken();
+				continue;
+			    }
+			    Identifier *id = token.ident;
+			    if (id == Id::property)
+				((TypeFunction *)tf)->ispure = 1;
+			    else
+				error("valid attribute identifiers are property, not %s", id->toChars());
+			    nextToken();
+			    continue;
+
 		    }
 		    break;
 		}
@@ -4361,6 +4377,10 @@
 			case TOKnothrow:
 			    t = peek(t);
 			    continue;
+			case TOKat:
+			    t = peek(t);	// skip '@'
+			    t = peek(t);	// skip identifier
+			    continue;
 			default:
 			    break;
 		    }
--- a/dmd2/root/response.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/root/response.c	Tue Sep 08 10:07:56 2009 +0100
@@ -14,16 +14,13 @@
 #include <stdlib.h>
 #include <string.h>
 
-#if !__DMC__
-#include <sys/stat.h>
-#endif
-
 #if _WIN32
 #include <tchar.h>
 #include <io.h>
 #endif
 
 #if linux || __APPLE__ || __FreeBSD__ || __sun&&__SVR4
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <fcntl.h>
 #include <errno.h>
--- a/dmd2/root/root.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/root/root.c	Tue Sep 08 10:07:56 2009 +0100
@@ -409,10 +409,12 @@
 			continue;
 #endif
 
+#if 0
 		    case ' ':
 		    case '\t':		// tabs in filenames?
 			if (!instring)	// if not in string
 			    break;	// treat as end of path
+#endif
 		    default:
 			buf.writeByte(c);
 			continue;
--- a/dmd2/statement.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/statement.c	Tue Sep 08 10:07:56 2009 +0100
@@ -29,6 +29,12 @@
 #include "template.h"
 #include "attrib.h"
 
+#if IN_LLVM
+#include "gen/tollvm.h"
+#elif IN_DMD
+extern int os_critsecsize();
+#endif
+
 /******************************** Statement ***************************/
 
 Statement::Statement(Loc loc)
@@ -182,6 +188,22 @@
 }
 
 
+/******************************** PeelStatement ***************************/
+
+PeelStatement::PeelStatement(Statement *s)
+    : Statement(s->loc)
+{
+    this->s = s;
+}
+
+Statement *PeelStatement::semantic(Scope *sc)
+{
+    /* "peel" off this wrapper, and don't run semantic()
+     * on the result.
+     */
+    return s;
+}
+
 /******************************** ExpStatement ***************************/
 
 ExpStatement::ExpStatement(Loc loc, Expression *exp)
@@ -344,6 +366,25 @@
 		if (e)
 		{
 		    //printf("dtor is: "); e->print();
+#if 0
+		    if (v->type->toBasetype()->ty == Tstruct)
+		    {	/* Need a 'gate' to turn on/off destruction,
+			 * in case v gets moved elsewhere.
+			 */
+			Identifier *id = Lexer::uniqueId("__runDtor");
+			ExpInitializer *ie = new ExpInitializer(loc, new IntegerExp(1));
+			VarDeclaration *rd = new VarDeclaration(loc, Type::tint32, id, ie);
+			*sentry = new DeclarationStatement(loc, rd);
+			v->rundtor = rd;
+
+			/* Rewrite e as:
+			 *  rundtor && e
+			 */
+			Expression *ve = new VarExp(loc, v->rundtor);
+			e = new AndAndExp(loc, ve, e);
+			e->type = Type::tbool;
+		    }
+#endif
 		    *sfinally = new ExpStatement(loc, e);
 		}
 	    }
@@ -418,7 +459,12 @@
 		if (sentry)
 		{
 		    sentry = sentry->semantic(sc);
-		    statements->data[i] = sentry;
+		    if (s->isDeclarationStatement())
+		    {	statements->insert(i, sentry);
+			i++;
+		    }
+		    else
+			statements->data[i] = sentry;
 		}
 		if (sexception)
 		{
@@ -562,7 +608,8 @@
 //printf("%s\n", s->toChars());
 	    if (!(result & BEfallthru) && !s->comeFrom())
 	    {
-		s->warning("statement is not reachable");
+		if (s->blockExit() != BEhalt)
+		    s->warning("statement is not reachable");
 	    }
 
 	    result &= ~BEfallthru;
@@ -909,46 +956,12 @@
 
 Statement *WhileStatement::semantic(Scope *sc)
 {
-#if 0
-    if (condition->op == TOKmatch)
-    {
-	/* Rewrite while (condition) body as:
-	 *   if (condition)
-	 *     do
-	 *       body
-	 *     while ((_match = _match.opNext), _match);
-	 */
-
-	Expression *ew = new IdentifierExp(0, Id::_match);
-	ew = new DotIdExp(0, ew, Id::next);
-	ew = new AssignExp(0, new IdentifierExp(0, Id::_match), ew);
-	////ew = new EqualExp(TOKnotequal, 0, ew, new NullExp(0));
-	Expression *ev = new IdentifierExp(0, Id::_match);
-	//ev = new CastExp(0, ev, Type::tvoidptr);
-	ew = new CommaExp(0, ew, ev);
-	Statement *sw = new DoStatement(loc, body, ew);
-	Statement *si = new IfStatement(loc, condition, sw, NULL);
-	return si->semantic(sc);
-    }
-#endif
-
-    condition = condition->semantic(sc);
-    condition = resolveProperties(sc, condition);
-    condition = condition->optimize(WANTvalue);
-    condition = condition->checkToBoolean();
-
-    sc->noctor++;
-
-    Scope *scd = sc->push();
-    scd->sbreak = this;
-    scd->scontinue = this;
-    if (body)
-	body = body->semantic(scd);
-    scd->pop();
-
-    sc->noctor--;
-
-    return this;
+    /* Rewrite as a for(;condition;) loop
+     */
+
+    Statement *s = new ForStatement(loc, NULL, condition, NULL, body);
+    s = s->semantic(sc);
+    return s;
 }
 
 int WhileStatement::hasBreak()
@@ -963,11 +976,13 @@
 
 int WhileStatement::usesEH()
 {
+    assert(0);
     return body ? body->usesEH() : 0;
 }
 
 int WhileStatement::blockExit()
 {
+    assert(0);
     //printf("WhileStatement::blockExit(%p)\n", this);
 
     int result = BEnone;
@@ -998,6 +1013,7 @@
 
 int WhileStatement::comeFrom()
 {
+    assert(0);
     if (body)
 	return body->comeFrom();
     return FALSE;
@@ -1193,6 +1209,10 @@
     if (condition)
     {	if (condition->canThrow())
 	    result |= BEthrow;
+	if (condition->isBool(TRUE))
+	    result &= ~BEfallthru;
+	else if (condition->isBool(FALSE))
+	    return result;
     }
     else
 	result &= ~BEfallthru;	// the body must do the exiting
@@ -1452,11 +1472,14 @@
 	    for (size_t i = 0; i < dim; i++)
 	    {	// Declare args
 		Argument *arg = (Argument *)arguments->data[i];
+		Type *argtype = arg->type->semantic(loc, sc);
 		VarDeclaration *var;
 
-		var = new VarDeclaration(loc, arg->type, arg->ident, NULL);
+		var = new VarDeclaration(loc, argtype, arg->ident, NULL);
 		var->storage_class |= STCforeach;
 		var->storage_class |= arg->storageClass & (STCin | STCout | STCref | STC_TYPECTOR);
+		if (var->storage_class & (STCref | STCout))
+		    var->storage_class |= STCnodtor;
 		if (dim == 2 && i == 0)
 		{   key = var;
 		    //var->storage_class |= STCfinal;
@@ -1471,20 +1494,68 @@
 			var->storage_class |= STCconst;
 		    }
 		}
-#if 1
+#if 0
 		DeclarationExp *de = new DeclarationExp(loc, var);
 		de->semantic(sc);
-#else
-		var->semantic(sc);
-		if (!sc->insert(var))
-		    error("%s already defined", var->ident->toChars());
 #endif
 	    }
 
-	    sc->sbreak = this;
-	    sc->scontinue = this;
-	    body = body->semantic(sc);
-
+#if 1
+	{
+	     /* Convert to a ForStatement
+	      *   foreach (key, value; a) body =>
+	      *   for (T[] tmp = a[], size_t key; key < tmp.length; ++key)
+	      *   { T value = tmp[k]; body }
+	      *
+	      *   foreach_reverse (key, value; a) body =>
+	      *   for (T[] tmp = a[], size_t key = tmp.length; key--; )
+	      *   { T value = tmp[k]; body }
+	      */
+	    Identifier *id = Lexer::uniqueId("__aggr");
+	    ExpInitializer *ie = new ExpInitializer(loc, new SliceExp(loc, aggr, NULL, NULL));
+	    VarDeclaration *tmp = new VarDeclaration(loc, aggr->type->nextOf()->arrayOf(), id, ie);
+
+	    Expression *tmp_length = new DotIdExp(loc, new VarExp(loc, tmp), Id::length);
+
+	    if (!key)
+	    {
+		Identifier *id = Lexer::uniqueId("__key");
+		key = new VarDeclaration(loc, Type::tsize_t, id, NULL);
+	    }
+	    if (op == TOKforeach_reverse)
+		key->init = new ExpInitializer(loc, tmp_length);
+	    else
+		key->init = new ExpInitializer(loc, new IntegerExp(0));
+
+	    Statements *cs = new Statements();
+	    cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+	    cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+	    Statement *forinit = new CompoundDeclarationStatement(loc, cs);
+
+	    Expression *cond;
+	    if (op == TOKforeach_reverse)
+		// key--
+		cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
+	    else
+		// key < tmp.length
+		cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), tmp_length);
+
+	    Expression *increment = NULL;
+	    if (op == TOKforeach)
+		// key += 1
+		increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
+
+	    // T value = tmp[key];
+	    value->init = new ExpInitializer(loc, new IndexExp(loc, new VarExp(loc, tmp), new VarExp(loc, key)));
+	    Statement *ds = new DeclarationStatement(loc, new DeclarationExp(loc, value));
+
+	    body = new CompoundStatement(loc, ds, body);
+
+	    ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
+	    s = fs->semantic(sc);
+	    break;
+	}
+#else
 	    if (tab->nextOf()->implicitConvTo(value->type) < MATCHconst)
 	    {
 		if (aggr->op == TOKstring)
@@ -1494,20 +1565,23 @@
 			tab->toChars(), value->type->toChars());
 	    }
 
-	    if (key && key->type->ty != Tint32 && key->type->ty != Tuns32)
+	    if (key)
 	    {
 		if (global.params.is64bit)
 		{
 		    if (key->type->ty != Tint64 && key->type->ty != Tuns64)
 			error("foreach: key type must be int or uint, long or ulong, not %s", key->type->toChars());
 		}
-		else
-		    error("foreach: key type must be int or uint, not %s", key->type->toChars());
+
+		if (key->storage_class & (STCout | STCref))
+		    error("foreach: key cannot be out or ref");
 	    }
 
-	    if (key && key->storage_class & (STCout | STCref))
-		error("foreach: key cannot be out or ref");
+	    sc->sbreak = this;
+	    sc->scontinue = this;
+	    body = body->semantic(sc);
 	    break;
+#endif
 
 	case Taarray:
 	    if (!checkForArgTypes())
@@ -1745,12 +1819,14 @@
 		keysize = (keysize + (PTRSIZE-1)) & ~(PTRSIZE-1);
 		exps->push(new IntegerExp(0, keysize, Type::tsize_t));
 
+#if IN_LLVM
         // LDC paint delegate argument to the type runtime expects
         if (!fldeTy->equals(flde->type))
         {
             flde = new CastExp(loc, flde, flde->type);
             flde->type = fldeTy;
         }
+#endif
 		exps->push(flde);
 		e = new CallExp(loc, ec, exps);
 		e->type = Type::tindex;	// don't run semantic() on e
@@ -2055,6 +2131,55 @@
 	lwr = ea.e1;
 	upr = ea.e2;
     }
+#if 1
+    /* Convert to a for loop:
+     *	foreach (key; lwr .. upr) =>
+     *	for (auto key = lwr, auto tmp = upr; key < tmp; ++key)
+     *
+     *	foreach_reverse (key; lwr .. upr) =>
+     *	for (auto tmp = lwr, auto key = upr; key-- > tmp;)
+     */
+
+    ExpInitializer *ie = new ExpInitializer(loc, (op == TOKforeach) ? lwr : upr);
+    key = new VarDeclaration(loc, arg->type, arg->ident, ie);
+
+    Identifier *id = Lexer::uniqueId("__limit");
+    ie = new ExpInitializer(loc, (op == TOKforeach) ? upr : lwr);
+    VarDeclaration *tmp = new VarDeclaration(loc, arg->type, id, ie);
+
+    Statements *cs = new Statements();
+    // Keep order of evaluation as lwr, then upr
+    if (op == TOKforeach)
+    {
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+    }
+    else
+    {
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, key)));
+    }
+    Statement *forinit = new CompoundDeclarationStatement(loc, cs);
+
+    Expression *cond;
+    if (op == TOKforeach_reverse)
+    {	// key-- > tmp
+	cond = new PostExp(TOKminusminus, loc, new VarExp(loc, key));
+	cond = new CmpExp(TOKgt, loc, cond, new VarExp(loc, tmp));
+    }
+    else
+	// key < tmp
+	cond = new CmpExp(TOKlt, loc, new VarExp(loc, key), new VarExp(loc, tmp));
+
+    Expression *increment = NULL;
+    if (op == TOKforeach)
+	// key += 1
+	increment = new AddAssignExp(loc, new VarExp(loc, key), new IntegerExp(1));
+
+    ForStatement *fs = new ForStatement(loc, forinit, cond, increment, body);
+    s = fs->semantic(sc);
+    return s;
+#else
     if (!arg->type->isscalar())
 	error("%s is not a scalar type", arg->type->toChars());
 
@@ -2078,6 +2203,7 @@
     sc->noctor--;
     sc->pop();
     return s;
+#endif
 }
 
 int ForeachRangeStatement::hasBreak()
@@ -2092,11 +2218,14 @@
 
 int ForeachRangeStatement::usesEH()
 {
+    assert(0);
     return body->usesEH();
 }
 
 int ForeachRangeStatement::blockExit()
-{   int result = BEfallthru;
+{
+    assert(0);
+    int result = BEfallthru;
 
     if (lwr && lwr->canThrow())
 	result |= BEthrow;
@@ -2113,6 +2242,7 @@
 
 int ForeachRangeStatement::comeFrom()
 {
+    assert(0);
     if (body)
 	return body->comeFrom();
     return FALSE;
@@ -2462,7 +2592,7 @@
     {
         sc->func->allowInlining = true;
     }
-
+#if DMDV2
     else if (ident == Id::startaddress)
     {
 	if (!args || args->dim != 1)
@@ -2483,6 +2613,7 @@
 	    return this;
 	}
     }
+#endif
     else
         error("unrecognized pragma(%s)", ident->toChars());
 
@@ -2657,7 +2788,7 @@
 	;
     }
 
-    if (!sc->sw->sdefault)
+    if (!sc->sw->sdefault && !isFinal)
     {	hasNoDefault = 1;
 
 	warning("switch statement has no default");
@@ -3693,21 +3824,145 @@
 Statement *SynchronizedStatement::semantic(Scope *sc)
 {
     if (exp)
-    {	ClassDeclaration *cd;
-
+    {
 	exp = exp->semantic(sc);
 	exp = resolveProperties(sc, exp);
-	cd = exp->type->isClassHandle();
+	ClassDeclaration *cd = exp->type->isClassHandle();
 	if (!cd)
 	    error("can only synchronize on class objects, not '%s'", exp->type->toChars());
 	else if (cd->isInterfaceDeclaration())
-	{   Type *t = new TypeIdentifier(0, Id::Object);
+	{   /* Cast the interface to an object, as the object has the monitor,
+	     * not the interface.
+	     */
+	    Type *t = new TypeIdentifier(0, Id::Object);
 
 	    t = t->semantic(0, sc);
 	    exp = new CastExp(loc, exp, t);
 	    exp = exp->semantic(sc);
 	}
+
+#if 1
+	/* Rewrite as:
+	 *  auto tmp = exp;
+	 *  _d_monitorenter(tmp);
+	 *  try { body } finally { _d_monitorexit(tmp); }
+	 */
+	Identifier *id = Lexer::uniqueId("__sync");
+	ExpInitializer *ie = new ExpInitializer(loc, exp);
+	VarDeclaration *tmp = new VarDeclaration(loc, exp->type, id, ie);
+
+	Statements *cs = new Statements();
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+
+#if IN_LLVM
+	// LDC: Build args
+	Arguments* args = new Arguments;
+	args->push(new Argument(STCin, ClassDeclaration::object->type, NULL, NULL));
+	FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorenter);
+#else
+	FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::monitorenter);
+#endif
+	Expression *e = new CallExp(loc, new VarExp(loc, fdenter), new VarExp(loc, tmp));
+	e->type = Type::tvoid;			// do not run semantic on e
+	cs->push(new ExpStatement(loc, e));
+
+#if IN_LLVM
+	FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit);
+#else
+	FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::monitorexit);
+#endif
+	e = new CallExp(loc, new VarExp(loc, fdexit), new VarExp(loc, tmp));
+	e->type = Type::tvoid;			// do not run semantic on e
+	Statement *s = new ExpStatement(loc, e);
+	s = new TryFinallyStatement(loc, body, s);
+	cs->push(s);
+
+	s = new CompoundStatement(loc, cs);
+	return s->semantic(sc);
+#endif
     }
+#if 1
+    else
+    {	/* Generate our own critical section, then rewrite as:
+	 *  __gshared byte[CriticalSection.sizeof] critsec;
+	 *  _d_criticalenter(critsec.ptr);
+	 *  try { body } finally { _d_criticalexit(critsec.ptr); }
+	 */
+	Identifier *id = Lexer::uniqueId("__critsec");
+#if IN_LLVM	
+	Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + getTypePaddedSize(DtoMutexType())));
+#elif IN_DMD
+	Type *t = new TypeSArray(Type::tint8, new IntegerExp(PTRSIZE + os_critsecsize()));
+#endif
+	VarDeclaration *tmp = new VarDeclaration(loc, t, id, NULL);
+	tmp->storage_class |= STCgshared | STCstatic;
+
+	Statements *cs = new Statements();
+	cs->push(new DeclarationStatement(loc, new DeclarationExp(loc, tmp)));
+
+#if IN_LLVM
+	// LDC: Build args (based on the code from gen/tollvm.cpp:DtoMutexType()
+	Arguments* args = new Arguments;
+	StructDeclaration* dcs = new StructDeclaration(loc, id);
+	if (global.params.os == OSWindows)
+	{
+		dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
+	}
+	else if (global.params.os == OSFreeBSD)
+	{
+		dcs->addField(dcs->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL));
+	}
+	else
+	{
+		// pthread_fastlock
+		StructDeclaration* pfl = new StructDeclaration(loc, id);
+		pfl->scope->linkage = LINKc;
+		pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tsize_t, id, NULL));
+		pfl->addField(pfl->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
+
+		// pthread_mutex
+		StructDeclaration* pm = new StructDeclaration(loc, id);
+		pm->scope->linkage = LINKc;
+		pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
+		pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
+		pm->addField(pm->scope, new VarDeclaration(loc, Type::tvoidptr, id, NULL));
+		pm->addField(pm->scope, new VarDeclaration(loc, Type::tint32, id, NULL));
+		pm->addField(pm->scope, new VarDeclaration(loc, pfl->type, id, NULL));
+
+		// D_CRITICAL_SECTION
+		dcs->scope->linkage = LINKc;
+		dcs->addField(dcs->scope, new VarDeclaration(loc, dcs->type->pointerTo(), id, NULL));
+		dcs->addField(dcs->scope, new VarDeclaration(loc, pm->type, id, NULL));
+	}
+	args->push(new Argument(STCin, dcs->type->pointerTo(), NULL, NULL));
+
+	FuncDeclaration *fdenter = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalenter);
+#else
+	FuncDeclaration *fdenter = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalenter);
+#endif
+	Expression *e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
+	e = e->semantic(sc);
+	e = new CallExp(loc, new VarExp(loc, fdenter), e);
+	e->type = Type::tvoid;			// do not run semantic on e
+	cs->push(new ExpStatement(loc, e));
+
+#if IN_LLVM
+	FuncDeclaration *fdexit = FuncDeclaration::genCfunc(args, Type::tvoid, Id::criticalexit);
+#else
+	FuncDeclaration *fdexit = FuncDeclaration::genCfunc(Type::tvoid, Id::criticalexit);
+#endif
+	e = new DotIdExp(loc, new VarExp(loc, tmp), Id::ptr);
+	e = e->semantic(sc);
+	e = new CallExp(loc, new VarExp(loc, fdexit), e);
+	e->type = Type::tvoid;			// do not run semantic on e
+	Statement *s = new ExpStatement(loc, e);
+	s = new TryFinallyStatement(loc, body, s);
+	cs->push(s);
+
+	s = new CompoundStatement(loc, cs);
+	return s->semantic(sc);
+    }
+#endif
     if (body)
     {
 	Statement* oldScopeExit = sc->enclosingScopeExit;
--- a/dmd2/statement.h	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/statement.h	Tue Sep 08 10:07:56 2009 +0100
@@ -153,6 +153,14 @@
 #endif
 };
 
+struct PeelStatement : Statement
+{
+    Statement *s;
+
+    PeelStatement(Statement *s);
+    Statement *semantic(Scope *sc);
+};
+
 struct ExpStatement : Statement
 {
     Expression *exp;
--- a/dmd2/template.c	Tue Aug 25 21:35:43 2009 +0200
+++ b/dmd2/template.c	Tue Sep 08 10:07:56 2009 +0100
@@ -1972,14 +1972,21 @@
 
       L2:
 
-	for (int i = 0; i < tempinst->tiargs->dim; i++)
+	for (int i = 0; 1; i++)
 	{
 	    //printf("\ttest: tempinst->tiargs[%d]\n", i);
+	    Object *o1;
+	    if (i < tempinst->tiargs->dim)
+		o1 = (Object *)tempinst->tiargs->data[i];
+	    else if (i < tempinst->tdtypes.dim && i < tp->tempinst->tiargs->dim)
+		// Pick up default arg
+		o1 = (Object *)tempinst->tdtypes.data[i];
+	    else
+		break;
+
 	    if (i >= tp->tempinst->tiargs->dim)
 		goto Lnomatch;
 
-	    int j;
-	    Object *o1 = (Object *)tempinst->tiargs->data[i];
 	    Object *o2 = (Object *)tp->tempinst->tiargs->data[i];
 
 	    Type *t1 = isType(o1);
@@ -2005,6 +2012,7 @@
 #endif
 
 	    TemplateTupleParameter *ttp;
+	    int j;
 	    if (t2 &&
 		t2->ty == Tident &&
 		i == tp->tempinst->tiargs->dim - 1 &&
@@ -2119,6 +2127,7 @@
     return Type::deduceType(sc, tparam, parameters, dedtypes);
 
 Lnomatch:
+    //printf("no match\n");
     return MATCHnomatch;
 }
 
@@ -4143,7 +4152,7 @@
 	Expression *ea = isExpression(o);
 	Dsymbol *sa = isDsymbol(o);
 	Tuple *va = isTuple(o);
-	//printf("\to %p ta %p ea %p sa %p va %p\n", o, ta, ea, sa, va);
+	//printf("\to [%d] %p ta %p ea %p sa %p va %p\n", i, o, ta, ea, sa, va);
 	if (ta)
 	{
 	    buf.writeByte('T');
--- a/gen/classes.cpp	Tue Aug 25 21:35:43 2009 +0200
+++ b/gen/classes.cpp	Tue Sep 08 10:07:56 2009 +0100
@@ -732,7 +732,11 @@
 
     // class name
     // code from dmd
+#if DMDV2
+    const char *name = cd->ident->toChars();
+#else
     char *name = cd->ident->toChars();
+#endif
     size_t namelen = strlen(name);
     if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
     {
--- a/gen/tollvm.cpp	Tue Aug 25 21:35:43 2009 +0200
+++ b/gen/tollvm.cpp	Tue Sep 08 10:07:56 2009 +0100
@@ -874,8 +874,11 @@
     opaque->refineAbstractTypeTo(pa.get());
     pmutex = isaStruct(pa.get());
 
-    gIR->mutexType = pmutex;
-    gIR->module->addTypeName("D_CRITICAL_SECTION", pmutex);
+    if (gIR->module != NULL)
+    {
+    	gIR->mutexType = pmutex;
+    	gIR->module->addTypeName("D_CRITICAL_SECTION", pmutex);
+    }
     return pmutex;
 }