changeset 12:832f71e6f96c

*Exp and *AssignExp arrayOp implementation added (might be a bit incomplete) Some unittest-specific functions implemented
author korDen
date Mon, 12 Apr 2010 15:13:00 +0400
parents 3356c90e9aac
children 427f8aa74d28
files dmd/AddAssignExp.d dmd/AddExp.d dmd/AndAssignExp.d dmd/AndExp.d dmd/AssignExp.d dmd/BinExp.d dmd/CastExp.d dmd/DivAssignExp.d dmd/DivExp.d dmd/Expression.d dmd/ForeachStatement.d dmd/MinAssignExp.d dmd/MinExp.d dmd/ModExp.d dmd/MulAssignExp.d dmd/MulExp.d dmd/OutBuffer.d dmd/SliceExp.d dmd/Type.d dmd/TypeDArray.d dmd/TypeSArray.d dmd/UnitTestDeclaration.d dmd/VarDeclaration.d dmd/XorAssignExp.d dmd/XorExp.d
diffstat 25 files changed, 494 insertions(+), 42 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/AddAssignExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/AddAssignExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -5,6 +5,8 @@
 import dmd.Expression;
 import dmd.Scope;
 import dmd.InterState;
+import dmd.Argument;
+import dmd.STC;
 import dmd.OutBuffer;
 import dmd.ArrayTypes;
 import dmd.Identifier;
@@ -143,12 +145,19 @@
 	
     void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		AssignExp_buildArrayIdent(buf, arguments, "Add");
 	}
 	
     Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions right to left		
+		 */								
+		Expression ex2 = e2.buildArrayLoop(fparams);		
+		Expression ex1 = e1.buildArrayLoop(fparams);		
+		Argument param = cast(Argument)fparams.data[0];		
+		param.storageClass = STCundefined;					
+		Expression e = new AddAssignExp(Loc(0), ex1, ex2);		
+		return e;							
 	}
 
     Identifier opId()    /* For operator overloading */
--- a/dmd/AddExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/AddExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -118,12 +118,17 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		Exp_buildArrayIdent(buf, arguments, "Add");
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions left to right		
+		 */								
+		Expression ex1 = e1.buildArrayLoop(fparams);		
+		Expression ex2 = e2.buildArrayLoop(fparams);		
+		Expression e = new AddExp(Loc(0), ex1, ex2);			
+		return e;							
 	}
 
 	bool isCommutative()
--- a/dmd/AndAssignExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/AndAssignExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -34,7 +34,7 @@
 	
     void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		AssignExp_buildArrayIdent(buf, arguments, "And");
 	}
 	
     Expression buildArrayLoop(Arguments fparams)
--- a/dmd/AndExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/AndExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -80,12 +80,17 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		Exp_buildArrayIdent(buf, arguments, "And");
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions left to right		
+		 */								
+		Expression ex1 = e1.buildArrayLoop(fparams);		
+		Expression ex2 = e2.buildArrayLoop(fparams);		
+		Expression e = new AndExp(Loc(0), ex1, ex2);			
+		return e;							
 	}
 
 	IntRange getIntRange()
--- a/dmd/AssignExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/AssignExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -4,8 +4,10 @@
 import dmd.Identifier;
 import dmd.backend.elem;
 import dmd.InterState;
+import dmd.Argument;
 import dmd.IndexExp;
 import dmd.CallExp;
+import dmd.CastExp;
 import dmd.TypeSArray;
 import dmd.StructLiteralExp;
 import dmd.ArrayLengthExp;
@@ -379,12 +381,31 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		/* Evaluate assign expressions right to left
+		 */
+		e2.buildArrayIdent(buf, arguments);
+		e1.buildArrayIdent(buf, arguments);
+		buf.writestring("Assign");
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions right to left
+		 */
+		Expression ex2 = e2.buildArrayLoop(fparams);
+	version (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(Loc(0), ex2, e1.type.nextOf());
+	}
+		Expression ex1 = e1.buildArrayLoop(fparams);
+		Argument param = cast(Argument)fparams.data[0];
+		param.storageClass = STCundefined;
+		Expression e = new AssignExp(Loc(0), ex1, ex2);
+		return e;
 	}
 
 	elem* toElem(IRState* irs)
--- a/dmd/BinExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/BinExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -31,12 +31,32 @@
 import dmd.MulExp;
 import dmd.Token;
 import dmd.PREC;
+import dmd.StringValue;
+import dmd.StringTable;
+import dmd.Argument;
+import dmd.Statement;
+import dmd.ForeachRangeStatement;
+import dmd.ArrayLengthExp;
+import dmd.IdentifierExp;
+import dmd.ExpStatement;
+import dmd.CompoundStatement;
+import dmd.TypeFunction;
+import dmd.LINK;
+import dmd.Lexer;
+import dmd.ReturnStatement;
+import dmd.Id;
+import dmd.STC;
+import dmd.PROT;
+import dmd.VarExp;
+import dmd.CallExp;
 
 import dmd.expression.Util;
 
 import dmd.backend.elem;
 import dmd.backend.Util;
 
+import dmd.backend.iasm : binary;
+
 import std.stdio : writef;
 
 /**************************************
@@ -50,6 +70,12 @@
  *	0	failed
  */
 
+/**************************************
+ * Hash table of array op functions already generated or known about.
+ */
+
+__gshared StringTable arrayfuncs;
+
 int typeMerge(Scope sc, Expression e, Type* pt, Expression* pe1, Expression* pe2)
 {
     //printf("typeMerge() %s op %s\n", (*pe1).toChars(), (*pe2).toChars());
@@ -620,9 +646,283 @@
 		return e1.canThrow() || e2.canThrow();
 	}
 
+	/***********************************
+	 * Construct the array operation expression.
+	 */
     Expression arrayOp(Scope sc)
 	{
-		assert(false);
+		//printf("BinExp.arrayOp() %s\n", toChars());
+		Expressions arguments = new Expressions();
+
+		/* The expression to generate an array operation for is mangled
+		 * into a name to use as the array operation function name.
+		 * Mangle in the operands and operators in RPN order, and type.
+		 */
+		scope OutBuffer buf = new OutBuffer();
+		buf.writestring("_array");
+		buildArrayIdent(buf, arguments);
+		buf.writeByte('_');
+
+		/* Append deco of array element type
+		 */
+version (DMDV2) {
+		buf.writestring(type.toBasetype().nextOf().toBasetype().mutableOf().deco);
+} else {
+		buf.writestring(type.toBasetype().nextOf().toBasetype().deco);
+}
+
+		size_t namelen = buf.offset;
+		buf.writeByte(0);
+		immutable(char)* name = cast(immutable(char)*)buf.extractData();
+
+		/* Look up name in hash table
+		 */
+		if (arrayfuncs is null) arrayfuncs = new StringTable(); /// HACK!
+
+		StringValue* sv = arrayfuncs.update(name[0..namelen]);
+		FuncDeclaration fd = cast(FuncDeclaration)sv.ptrvalue;
+		if (!fd)
+		{
+			/* Some of the array op functions are written as library functions,
+			 * presumably to optimize them with special CPU vector instructions.
+			 * List those library functions here, in alpha order.
+			 */
+			static const(char)*[] libArrayopFuncs =
+			[
+				"_arrayExpSliceAddass_a",
+				"_arrayExpSliceAddass_d",		// T[]+=T
+				"_arrayExpSliceAddass_f",		// T[]+=T
+				"_arrayExpSliceAddass_g",
+				"_arrayExpSliceAddass_h",
+				"_arrayExpSliceAddass_i",
+				"_arrayExpSliceAddass_k",
+				"_arrayExpSliceAddass_s",
+				"_arrayExpSliceAddass_t",
+				"_arrayExpSliceAddass_u",
+				"_arrayExpSliceAddass_w",
+
+				"_arrayExpSliceDivass_d",		// T[]/=T
+				"_arrayExpSliceDivass_f",		// T[]/=T
+
+				"_arrayExpSliceMinSliceAssign_a",
+				"_arrayExpSliceMinSliceAssign_d",	// T[]=T-T[]
+				"_arrayExpSliceMinSliceAssign_f",	// T[]=T-T[]
+				"_arrayExpSliceMinSliceAssign_g",
+				"_arrayExpSliceMinSliceAssign_h",
+				"_arrayExpSliceMinSliceAssign_i",
+				"_arrayExpSliceMinSliceAssign_k",
+				"_arrayExpSliceMinSliceAssign_s",
+				"_arrayExpSliceMinSliceAssign_t",
+				"_arrayExpSliceMinSliceAssign_u",
+				"_arrayExpSliceMinSliceAssign_w",
+
+				"_arrayExpSliceMinass_a",
+				"_arrayExpSliceMinass_d",		// T[]-=T
+				"_arrayExpSliceMinass_f",		// T[]-=T
+				"_arrayExpSliceMinass_g",
+				"_arrayExpSliceMinass_h",
+				"_arrayExpSliceMinass_i",
+				"_arrayExpSliceMinass_k",
+				"_arrayExpSliceMinass_s",
+				"_arrayExpSliceMinass_t",
+				"_arrayExpSliceMinass_u",
+				"_arrayExpSliceMinass_w",
+
+				"_arrayExpSliceMulass_d",		// T[]*=T
+				"_arrayExpSliceMulass_f",		// T[]*=T
+				"_arrayExpSliceMulass_i",
+				"_arrayExpSliceMulass_k",
+				"_arrayExpSliceMulass_s",
+				"_arrayExpSliceMulass_t",
+				"_arrayExpSliceMulass_u",
+				"_arrayExpSliceMulass_w",
+
+				"_arraySliceExpAddSliceAssign_a",
+				"_arraySliceExpAddSliceAssign_d",	// T[]=T[]+T
+				"_arraySliceExpAddSliceAssign_f",	// T[]=T[]+T
+				"_arraySliceExpAddSliceAssign_g",
+				"_arraySliceExpAddSliceAssign_h",
+				"_arraySliceExpAddSliceAssign_i",
+				"_arraySliceExpAddSliceAssign_k",
+				"_arraySliceExpAddSliceAssign_s",
+				"_arraySliceExpAddSliceAssign_t",
+				"_arraySliceExpAddSliceAssign_u",
+				"_arraySliceExpAddSliceAssign_w",
+
+				"_arraySliceExpDivSliceAssign_d",	// T[]=T[]/T
+				"_arraySliceExpDivSliceAssign_f",	// T[]=T[]/T
+
+				"_arraySliceExpMinSliceAssign_a",
+				"_arraySliceExpMinSliceAssign_d",	// T[]=T[]-T
+				"_arraySliceExpMinSliceAssign_f",	// T[]=T[]-T
+				"_arraySliceExpMinSliceAssign_g",
+				"_arraySliceExpMinSliceAssign_h",
+				"_arraySliceExpMinSliceAssign_i",
+				"_arraySliceExpMinSliceAssign_k",
+				"_arraySliceExpMinSliceAssign_s",
+				"_arraySliceExpMinSliceAssign_t",
+				"_arraySliceExpMinSliceAssign_u",
+				"_arraySliceExpMinSliceAssign_w",
+
+				"_arraySliceExpMulSliceAddass_d",	// T[] += T[]*T
+				"_arraySliceExpMulSliceAddass_f",
+				"_arraySliceExpMulSliceAddass_r",
+
+				"_arraySliceExpMulSliceAssign_d",	// T[]=T[]*T
+				"_arraySliceExpMulSliceAssign_f",	// T[]=T[]*T
+				"_arraySliceExpMulSliceAssign_i",
+				"_arraySliceExpMulSliceAssign_k",
+				"_arraySliceExpMulSliceAssign_s",
+				"_arraySliceExpMulSliceAssign_t",
+				"_arraySliceExpMulSliceAssign_u",
+				"_arraySliceExpMulSliceAssign_w",
+
+				"_arraySliceExpMulSliceMinass_d",	// T[] -= T[]*T
+				"_arraySliceExpMulSliceMinass_f",
+				"_arraySliceExpMulSliceMinass_r",
+
+				"_arraySliceSliceAddSliceAssign_a",
+				"_arraySliceSliceAddSliceAssign_d",	// T[]=T[]+T[]
+				"_arraySliceSliceAddSliceAssign_f",	// T[]=T[]+T[]
+				"_arraySliceSliceAddSliceAssign_g",
+				"_arraySliceSliceAddSliceAssign_h",
+				"_arraySliceSliceAddSliceAssign_i",
+				"_arraySliceSliceAddSliceAssign_k",
+				"_arraySliceSliceAddSliceAssign_r",	// T[]=T[]+T[]
+				"_arraySliceSliceAddSliceAssign_s",
+				"_arraySliceSliceAddSliceAssign_t",
+				"_arraySliceSliceAddSliceAssign_u",
+				"_arraySliceSliceAddSliceAssign_w",
+
+				"_arraySliceSliceAddass_a",
+				"_arraySliceSliceAddass_d",		// T[]+=T[]
+				"_arraySliceSliceAddass_f",		// T[]+=T[]
+				"_arraySliceSliceAddass_g",
+				"_arraySliceSliceAddass_h",
+				"_arraySliceSliceAddass_i",
+				"_arraySliceSliceAddass_k",
+				"_arraySliceSliceAddass_s",
+				"_arraySliceSliceAddass_t",
+				"_arraySliceSliceAddass_u",
+				"_arraySliceSliceAddass_w",
+
+				"_arraySliceSliceMinSliceAssign_a",
+				"_arraySliceSliceMinSliceAssign_d",	// T[]=T[]-T[]
+				"_arraySliceSliceMinSliceAssign_f",	// T[]=T[]-T[]
+				"_arraySliceSliceMinSliceAssign_g",
+				"_arraySliceSliceMinSliceAssign_h",
+				"_arraySliceSliceMinSliceAssign_i",
+				"_arraySliceSliceMinSliceAssign_k",
+				"_arraySliceSliceMinSliceAssign_r",	// T[]=T[]-T[]
+				"_arraySliceSliceMinSliceAssign_s",
+				"_arraySliceSliceMinSliceAssign_t",
+				"_arraySliceSliceMinSliceAssign_u",
+				"_arraySliceSliceMinSliceAssign_w",
+
+				"_arraySliceSliceMinass_a",
+				"_arraySliceSliceMinass_d",		// T[]-=T[]
+				"_arraySliceSliceMinass_f",		// T[]-=T[]
+				"_arraySliceSliceMinass_g",
+				"_arraySliceSliceMinass_h",
+				"_arraySliceSliceMinass_i",
+				"_arraySliceSliceMinass_k",
+				"_arraySliceSliceMinass_s",
+				"_arraySliceSliceMinass_t",
+				"_arraySliceSliceMinass_u",
+				"_arraySliceSliceMinass_w",
+
+				"_arraySliceSliceMulSliceAssign_d",	// T[]=T[]*T[]
+				"_arraySliceSliceMulSliceAssign_f",	// T[]=T[]*T[]
+				"_arraySliceSliceMulSliceAssign_i",
+				"_arraySliceSliceMulSliceAssign_k",
+				"_arraySliceSliceMulSliceAssign_s",
+				"_arraySliceSliceMulSliceAssign_t",
+				"_arraySliceSliceMulSliceAssign_u",
+				"_arraySliceSliceMulSliceAssign_w",
+
+				"_arraySliceSliceMulass_d",		// T[]*=T[]
+				"_arraySliceSliceMulass_f",		// T[]*=T[]
+				"_arraySliceSliceMulass_i",
+				"_arraySliceSliceMulass_k",
+				"_arraySliceSliceMulass_s",
+				"_arraySliceSliceMulass_t",
+				"_arraySliceSliceMulass_u",
+				"_arraySliceSliceMulass_w",
+			];
+
+			int i = binary(name, libArrayopFuncs.ptr, libArrayopFuncs.length);
+			if (i == -1)
+			{
+debug {			// Make sure our array is alphabetized
+				for (i = 0; i < libArrayopFuncs.length; i++)
+				{
+					if (strcmp(name, libArrayopFuncs[i]) == 0)
+						assert(false);
+				}
+}
+				/* Not in library, so generate it.
+				 * Construct the function body:
+				 *	foreach (i; 0 .. p.length)    for (size_t i = 0; i < p.length; i++)
+				 *	    loopbody;
+				 *	return p;
+				 */
+
+				Arguments fparams = new Arguments();
+				Expression loopbody = buildArrayLoop(fparams);
+				Argument p = cast(Argument)fparams.data[0 /*fparams.dim - 1*/];
+version (DMDV1) {
+				// for (size_t i = 0; i < p.length; i++)
+				Initializer init = new ExpInitializer(0, new IntegerExp(0, 0, Type.tsize_t));
+				Dsymbol d = new VarDeclaration(0, Type.tsize_t, Id.p, init);
+				Statement s1 = new ForStatement(0,
+					new DeclarationStatement(0, d),
+					new CmpExp(TOKlt, 0, new IdentifierExp(0, Id.p), new ArrayLengthExp(0, new IdentifierExp(0, p.ident))),
+					new PostExp(TOKplusplus, 0, new IdentifierExp(0, Id.p)),
+					new ExpStatement(0, loopbody));
+} else {
+				// foreach (i; 0 .. p.length)
+				Statement s1 = new ForeachRangeStatement(Loc(0), TOKforeach,
+					new Argument(STC.STCundefined, null, Id.p, null),
+					new IntegerExp(Loc(0), 0, Type.tint32),
+					new ArrayLengthExp(Loc(0), new IdentifierExp(Loc(0), p.ident)),
+					new ExpStatement(Loc(0), loopbody));
+}
+				Statement s2 = new ReturnStatement(Loc(0), new IdentifierExp(Loc(0), p.ident));
+				//printf("s2: %s\n", s2.toChars());
+				Statement fbody = new CompoundStatement(Loc(0), s1, s2);
+
+				/* Construct the function
+				 */
+				TypeFunction ftype = new TypeFunction(fparams, type, 0, LINKc);
+				//printf("ftype: %s\n", ftype.toChars());
+				fd = new FuncDeclaration(Loc(0), Loc(0), Lexer.idPool(name[0..namelen]), STCundefined, ftype);
+				fd.fbody = fbody;
+				fd.protection = PROT.PROTpublic;
+				fd.linkage = LINKc;
+
+				sc.module_.importedFrom.members.push(cast(void*)fd);
+
+				sc = sc.push();
+				sc.parent = sc.module_.importedFrom;
+				sc.stc = STCundefined;
+				sc.linkage = LINKc;
+				fd.semantic(sc);
+				sc.pop();
+			}
+			else
+			{   /* In library, refer to it.
+				 */
+				fd = FuncDeclaration.genCfunc(type, name[0..namelen]);
+			}
+			sv.ptrvalue = cast(void*)fd;	// cache symbol in hash table
+		}
+
+		/* Call the function fd(arguments)
+		 */
+		Expression ec = new VarExp(Loc(0), fd);
+		Expression e = new CallExp(loc, ec, arguments);
+		e.type = type;
+		return e;
 	}
 
     int inlineCost(InlineCostState* ics)
@@ -917,4 +1217,23 @@
 
 		return e;
 	}
+	
+	final void Exp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str)
+	{									
+		/* Evaluate assign expressions left to right			
+		 */									
+		e1.buildArrayIdent(buf, arguments);				
+		e2.buildArrayIdent(buf, arguments);				
+		buf.writestring(Str);						
+	}
+	
+	final void AssignExp_buildArrayIdent(OutBuffer buf, Expressions arguments, string Str)
+	{							
+		/* Evaluate assign expressions right to left	
+		 */							
+		e2.buildArrayIdent(buf, arguments);		
+		e1.buildArrayIdent(buf, arguments);		
+		buf.writestring(Str);				
+		buf.writestring("ass");				
+	}
 }
\ No newline at end of file
--- a/dmd/CastExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/CastExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -378,12 +378,24 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		Type tb = type.toBasetype();
+		if (tb.ty == Tarray || tb.ty == Tsarray)
+		{
+			e1.buildArrayIdent(buf, arguments);
+		}
+		else
+			Expression.buildArrayIdent(buf, arguments);
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		Type tb = type.toBasetype();
+		if (tb.ty == Tarray || tb.ty == Tsarray)
+		{
+			return e1.buildArrayLoop(fparams);
+		}
+		else
+			return Expression.buildArrayLoop(fparams);
 	}
 	
 	static int X(int fty, int tty) {
--- a/dmd/DivAssignExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/DivAssignExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -98,7 +98,7 @@
 	
     void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		AssignExp_buildArrayIdent(buf, arguments, "Div");
 	}
 	
     Expression buildArrayLoop(Arguments fparams)
--- a/dmd/DivExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/DivExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -112,12 +112,17 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		Exp_buildArrayIdent(buf, arguments, "Div");
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions left to right		
+		 */								
+		Expression ex1 = e1.buildArrayLoop(fparams);		
+		Expression ex2 = e2.buildArrayLoop(fparams);		
+		Expression e = new DivExp(Loc(0), ex1, ex2);			
+		return e;							
 	}
 
 	IntRange getIntRange()
--- a/dmd/Expression.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/Expression.d	Mon Apr 12 15:13:00 2010 +0400
@@ -2,6 +2,8 @@
 
 import dmd.Loc;
 import dmd.TOK;
+import dmd.Argument;
+import dmd.IdentifierExp;
 import dmd.Type;
 import dmd.WANT;
 import dmd.Scope;
@@ -886,14 +888,23 @@
 	}
     
     // For array ops
+	/******************************************
+	 * Construct the identifier for the array operation function,
+	 * and build the argument list to pass to it.
+	 */
     void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		buf.writestring("Exp");
+		arguments.shift(cast(void*)this);
 	}
     
     Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		Identifier id = Identifier.generateId("c", fparams.dim);
+		Argument param = new Argument(STC.STCundefined, type, id, null);
+		fparams.shift(cast(void*)param);
+		Expression e = new IdentifierExp(Loc(0), id);
+		return e;
 	}
     
     // Back end
--- a/dmd/ForeachStatement.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/ForeachStatement.d	Mon Apr 12 15:13:00 2010 +0400
@@ -654,7 +654,7 @@
 						case TY.Tdchar:	flag += 2; break;
 					}
 					string r = (op == TOK.TOKforeach_reverse) ? "R" : "";
-					int j = sprintf(fdname.ptr, "_aApply%*.s%.*s%ld".ptr, r, 2, fntab[flag].ptr, dim);
+					int j = sprintf(fdname.ptr, "_aApply%.*s%.*s%ld".ptr, r, 2, fntab[flag].ptr, dim);
 					assert(j < fdname.sizeof);
 					fdapply = FuncDeclaration.genCfunc(Type.tindex, fdname[0..j].idup);
 
--- a/dmd/MinAssignExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/MinAssignExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -73,7 +73,7 @@
 	
     void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		AssignExp_buildArrayIdent(buf, arguments, "Min");
 	}
 	
     Expression buildArrayLoop(Arguments fparams)
--- a/dmd/MinExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/MinExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -144,12 +144,17 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		Exp_buildArrayIdent(buf, arguments, "Min");
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions left to right		
+		 */								
+		Expression ex1 = e1.buildArrayLoop(fparams);		
+		Expression ex2 = e2.buildArrayLoop(fparams);		
+		Expression e = new MinExp(Loc(0), ex1, ex2);			
+		return e;							
 	}
 
 	Identifier opId()
--- a/dmd/ModExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/ModExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -79,12 +79,17 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		Exp_buildArrayIdent(buf, arguments, "Mod");
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions left to right		
+		 */								
+		Expression ex1 = e1.buildArrayLoop(fparams);		
+		Expression ex2 = e2.buildArrayLoop(fparams);		
+		Expression e = new ModExp(Loc(0), ex1, ex2);			
+		return e;							
 	}
 
 	Identifier opId()
--- a/dmd/MulAssignExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/MulAssignExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -90,7 +90,7 @@
 	
     void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		AssignExp_buildArrayIdent(buf, arguments, "Mul");
 	}
 	
     Expression buildArrayLoop(Arguments fparams)
--- a/dmd/MulExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/MulExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -117,12 +117,17 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		Exp_buildArrayIdent(buf, arguments, "Mul");
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions left to right		
+		 */								
+		Expression ex1 = e1.buildArrayLoop(fparams);		
+		Expression ex2 = e2.buildArrayLoop(fparams);		
+		Expression e = new MulExp(Loc(0), ex1, ex2);			
+		return e;							
 	}
 
 	bool isCommutative()
--- a/dmd/OutBuffer.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/OutBuffer.d	Mon Apr 12 15:13:00 2010 +0400
@@ -195,7 +195,9 @@
 	
     final void write4(uint w)
 	{
-		assert(false);
+		reserve(4);
+		*cast(uint*)(this.data + offset) = w;
+		offset += 4;
 	}
 	
     final void write(OutBuffer buf)
--- a/dmd/SliceExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/SliceExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -3,6 +3,10 @@
 import dmd.Expression;
 import dmd.backend.elem;
 import dmd.UnaExp;
+import dmd.Identifier;
+import dmd.IdentifierExp;
+import dmd.ArrayExp;
+import dmd.STC;
 import dmd.InterState;
 import dmd.ScopeDsymbol;
 import dmd.WANT;
@@ -444,12 +448,21 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		buf.writestring("Slice");
+		arguments.shift(cast(void*)this);
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		Identifier id = Identifier.generateId("p", fparams.dim);
+		Argument param = new Argument(STCconst, type, id, null);
+		fparams.shift(cast(void*)param);
+		Expression e = new IdentifierExp(Loc(0), id);
+		Expressions arguments = new Expressions();
+		Expression index = new IdentifierExp(Loc(0), Id.p);
+		arguments.push(cast(void*)index);
+		e = new ArrayExp(Loc(0), e, arguments);
+		return e;
 	}
 
 	int inlineCost(InlineCostState* ics)
--- a/dmd/Type.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/Type.d	Mon Apr 12 15:13:00 2010 +0400
@@ -894,7 +894,7 @@
 		return false;
 	}
 	
-    int isString()
+    bool isString()
 	{
 		return false;
 	}
--- a/dmd/TypeDArray.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/TypeDArray.d	Mon Apr 12 15:13:00 2010 +0400
@@ -158,9 +158,10 @@
 		return e;
 	}
 	
-    int isString()
+    bool isString()
 	{
-		assert(false);
+		TY nty = next.toBasetype().ty;
+		return nty == Tchar || nty == Twchar || nty == Tdchar;
 	}
 	
     bool isZeroInit(Loc loc)
--- a/dmd/TypeSArray.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/TypeSArray.d	Mon Apr 12 15:13:00 2010 +0400
@@ -258,7 +258,7 @@
 		return e;
 	}
 	
-    int isString()
+    bool isString()
 	{
 		assert(false);
 	}
--- a/dmd/UnitTestDeclaration.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/UnitTestDeclaration.d	Mon Apr 12 15:13:00 2010 +0400
@@ -65,22 +65,22 @@
 
     AggregateDeclaration isThis()
 	{
-		assert(false);
+		return null;
 	}
 
     bool isVirtual()
 	{
-		assert(false);
+		return false;
 	}
 
     bool addPreInvariant()
 	{
-		assert(false);
+		return false;
 	}
 
     bool addPostInvariant()
 	{
-		assert(false);
+		return false;
 	}
 
     void toCBuffer(OutBuffer buf, HdrGenState* hgs)
--- a/dmd/VarDeclaration.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/VarDeclaration.d	Mon Apr 12 15:13:00 2010 +0400
@@ -757,9 +757,38 @@
 		return true;
 	}
 	
-    int needsAutoDtor()
+	/******************************************
+	 * Return TRUE if variable needs to call the destructor.
+	 */
+    bool needsAutoDtor()
 	{
-		assert(false);
+		//printf("VarDeclaration.needsAutoDtor() %s\n", toChars());
+
+		if (noauto || storage_class & STCnodtor)
+			return false;
+
+		// Destructors for structs and arrays of structs
+		Type tv = type.toBasetype();
+		while (tv.ty == Tsarray)
+		{   
+			TypeSArray ta = cast(TypeSArray)tv;
+			tv = tv.nextOf().toBasetype();
+		}
+		if (tv.ty == Tstruct)
+		{   
+			TypeStruct ts = cast(TypeStruct)tv;
+			StructDeclaration sd = ts.sym;
+			if (sd.dtor)
+				return true;
+		}
+
+		// Destructors for classes
+		if (storage_class & (STCauto | STCscope))
+		{
+			if (type.isClassHandle())
+				return true;
+		}
+		return false;
 	}
 }
 
--- a/dmd/XorAssignExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/XorAssignExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -33,7 +33,7 @@
 	
     void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		AssignExp_buildArrayIdent(buf, arguments, "Xor");
 	}
 	
     Expression buildArrayLoop(Arguments fparams)
--- a/dmd/XorExp.d	Wed Mar 31 16:29:36 2010 +0400
+++ b/dmd/XorExp.d	Mon Apr 12 15:13:00 2010 +0400
@@ -77,12 +77,17 @@
 
 	void buildArrayIdent(OutBuffer buf, Expressions arguments)
 	{
-		assert(false);
+		Exp_buildArrayIdent(buf, arguments, "Xor");
 	}
 
 	Expression buildArrayLoop(Arguments fparams)
 	{
-		assert(false);
+		/* Evaluate assign expressions left to right		
+		 */								
+		Expression ex1 = e1.buildArrayLoop(fparams);		
+		Expression ex2 = e2.buildArrayLoop(fparams);		
+		Expression e = new XorExp(Loc(0), ex1, ex2);			
+		return e;							
 	}
 
 	MATCH implicitConvTo(Type t)