diff dmd/StructDeclaration.d @ 130:60bb0fe4563e

dmdfe 2.037 first main iteration
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Thu, 09 Sep 2010 22:51:44 +0100
parents 010eb8f0e18d
children 206db751bd4c
line wrap: on
line diff
--- a/dmd/StructDeclaration.d	Sun Sep 05 15:32:22 2010 +0400
+++ b/dmd/StructDeclaration.d	Thu Sep 09 22:51:44 2010 +0100
@@ -23,7 +23,7 @@
 import dmd.ThisExp;
 import dmd.ThisDeclaration;
 import dmd.TypeFunction;
-import dmd.Argument;
+import dmd.Parameter;
 import dmd.Id;
 import dmd.TY;
 import dmd.LINK;
@@ -70,6 +70,7 @@
 version (DMDV2) {
     int hasIdentityAssign;	// !=0 if has identity opAssign
     FuncDeclaration cpctor;	// generated copy-constructor, if any
+    FuncDeclaration eq;	// bool opEquals(ref const T), if any
 
     FuncDeclarations postblits;	// Array of postblit functions
     FuncDeclaration postblit;	// aggregate postblit
@@ -234,6 +235,10 @@
 			}
 		}
 
+version(DMDV1) {
+        /* This doesn't work for DMDV2 because (ref S) and (S) parameter
+         * lists will overload the same.
+         */
 		/* The TypeInfo_Struct is expecting an opEquals and opCmp with
 		 * a parameter that is a pointer to the struct. But if there
 		 * isn't one, but is an opEquals or opCmp with a value, write
@@ -243,8 +248,8 @@
 
 		TypeFunction tfeqptr;
 		{
-			Arguments arguments = new Arguments;
-			Argument arg = new Argument(STC.STCin, handle, Id.p, null);
+			auto arguments = new Parameters;
+			auto arg = new Parameter(STC.STCin, handle, Id.p, null);
 
 			arguments.push(arg);
 			tfeqptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd);
@@ -253,8 +258,8 @@
 
 		TypeFunction tfeq;
 		{
-			Arguments arguments = new Arguments;
-			Argument arg = new Argument(STC.STCin, type, null, null);
+			auto arguments = new Parameters;
+			auto arg = new Parameter(STC.STCin, type, null, null);
 
 			arguments.push(arg);
 			tfeq = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd);
@@ -291,7 +296,39 @@
 
 			id = Id.cmp;
 		}
+}
 version (DMDV2) {
+        /* Try to find the opEquals function. Build it if necessary.
+         */
+        TypeFunction *tfeqptr;
+        {   // bool opEquals(const T*) const;
+            auto parameters = new Parameters;
+version(STRUCTTHISREF) {
+            // bool opEquals(ref const T) const;
+            auto param = new Parameter(STC.STCref, type.constOf(), null, null);
+} else {
+            // bool opEquals(const T*) const;
+            auto param = new Parameter(STC.STCin, type.pointerTo(), null, null);
+}
+
+            parameters.push(param);
+            tfeqptr = new TypeFunction(parameters, Type.tbool, 0, LINK.LINKd);
+            tfeqptr.mod = MOD.MODconst;
+            tfeqptr = cast(TypeFunction)(tfeqptr.semantic(0, sc2));
+
+	        Dsymbol s = search_function(this, Id.eq);
+	        FuncDeclaration fdx = s ? s.isFuncDeclaration() : null;
+	        if (fdx)
+	        {
+	            eq = fdx.overloadExactMatch(tfeqptr);
+	            if (!eq)
+		            fdx.error("type signature should be %s not %s", tfeqptr.toChars(), fdx.type.toChars());
+	        }
+
+	        if (!eq)
+	            eq = buildOpEquals(sc2);
+        }
+
 		dtor = buildDtor(sc2);
 		postblit = buildPostBlit(sc2);
 		cpctor = buildCpCtor(sc2);
@@ -386,7 +423,17 @@
 	{
 		assert(false);
 	}
-	
+
+version(DMDV1)
+{
+    Expression cloneMembers()
+	{
+		assert(false);
+	}
+}
+
+version(DMDV2)
+{
 	/*******************************************
 	 * We need an opAssign for the struct if
 	 * it has a destructor or a postblit.
@@ -436,6 +483,46 @@
 		return true;
 	}
 	
+	/*******************************************
+	* We need an opEquals for the struct if
+	* any fields has an opEquals.
+	* Generate one if a user-specified one does not exist.
+	*/
+	bool needOpEquals()
+	{
+		enum X = 0;
+static if (X) printf("StructDeclaration::needOpEquals() %s\n", toChars());
+
+		/* If any of the fields has an opEquals, then we
+		 * need it too.
+		 */
+		foreach (s; fields)
+		{
+		VarDeclaration v = s.isVarDeclaration();
+		assert(v && v.storage_class & STC.STCfield);
+		if (v.storage_class & STC.STCref)
+			continue;
+		Type tv = v.type.toBasetype();
+		while (tv.ty == Tsarray)
+		{   auto ta = cast(TypeSArray)tv;
+			tv = tv.nextOf().toBasetype();
+		}
+		if (tv.ty == Tstruct)
+		{   auto ts = cast(TypeStruct)tv;
+			StructDeclaration sd = ts.sym;
+			if (sd.eq)
+			goto Lneed;
+		}
+		}
+	Ldontneed:
+static if (X) printf("\tdontneed\n");
+		return false;
+
+	Lneed:
+static if (X) printf("\tneed\n");
+		return true;
+	}
+	
 	/******************************************
 	 * Build opAssign for struct.
 	 *	S* opAssign(S s) { ... }
@@ -449,8 +536,8 @@
 
 		FuncDeclaration fop = null;
 
-		Argument param = new Argument(STC.STCnodtor, type, Id.p, null);
-		Arguments fparams = new Arguments;
+		auto param = new Parameter(STC.STCnodtor, type, Id.p, null);
+		auto fparams = new Parameters;
 		fparams.push(param);
 		Type ftype = new TypeFunction(fparams, handle, false, LINK.LINKd);
 version (STRUCTTHISREF) {
@@ -543,6 +630,72 @@
 		return fop;
 	}
 	
+	/******************************************
+	 * Build opEquals for struct.
+	 *	const bool opEquals(const ref S s) { ... }
+	 */
+	FuncDeclaration buildOpEquals(Scope sc)
+	{
+		if (!needOpEquals())
+		return null;
+		//printf("StructDeclaration::buildOpEquals() %s\n", toChars());
+		Loc loc = this.loc;
+
+		auto parameters = new Parameters;
+version (STRUCTTHISREF) {
+		// bool opEquals(ref const T) const;
+		auto param = new Parameter(STC.STCref, type.constOf(), Id.p, NULL);
+} else {
+		// bool opEquals(const T*) const;
+		auto param = new Parameter(STC.STCin, type.pointerTo(), Id.p, NULL);
+}
+
+		parameters.push(param);
+		auto ftype = new TypeFunction(parameters, Type.tbool, 0, LINKd);
+		ftype.mod = MOD.MODconst;
+		ftype = cast(TypeFunction)ftype.semantic(loc, sc);
+
+		auto fop = new FuncDeclaration(loc, 0, Id.eq, STD.STCundefined, ftype);
+
+		Expression *e = NULL;
+		/* Do memberwise compare
+		 */
+		//printf("\tmemberwise compare\n");
+		foreach (s; fields)
+		{
+		VarDeclaration v = s.isVarDeclaration();
+		assert(v && v.storage_class & STD.STCfield);
+		if (v.storage_class & STC.STCref)
+			assert(0);			// what should we do with this?
+		// this.v == s.v;
+		auto ec = new EqualExp(TOKequal, loc,
+			new DotVarExp(loc, new ThisExp(loc), v, 0),
+			new DotVarExp(loc, new IdentifierExp(loc, Id.p), v, 0));
+		if (e)
+			e = new AndAndExp(loc, e, ec);
+		else
+			e = ec;
+		}
+		if (!e)
+		e = new IntegerExp(loc, 1, Type.tbool);
+		fop.fbody = new ReturnStatement(loc, e);
+
+		members.push(fop);
+		fop.addMember(sc, this, 1);
+
+		sc = sc.push();
+		sc.stc = 0;
+		sc.linkage = LINK.LINKd;
+
+		fop.semantic(sc);
+
+		sc.pop();
+
+		//printf("-StructDeclaration::buildOpEquals() %s\n", toChars());
+
+		return fop;
+	}
+
 	/*****************************************
 	 * Create inclusive postblit for struct by aggregating
 	 * all the postblits in postblits[] with the postblits for
@@ -664,8 +817,8 @@
 		{
 			//printf("generating cpctor\n");
 
-			Argument param = new Argument(STC.STCref, type, Id.p, null);
-			Arguments fparams = new Arguments;
+		        auto param = new Parameter(STC.STCref, type, Id.p, null);
+		        auto fparams = new Parameters;
 			fparams.push(param);
 			Type ftype = new TypeFunction(fparams, Type.tvoid, false, LINK.LINKd);
 
@@ -701,7 +854,7 @@
 
 		return fcp;
 	}
-	
+}
     override void toDocBuffer(OutBuffer buf)
 	{
 		assert(false);