diff dmd/EqualExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children cab4c37afb89
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/EqualExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,237 @@
+module dmd.EqualExp;
+
+import dmd.Expression;
+import dmd.Id;
+import dmd.Identifier;
+import dmd.InterState;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.BinExp;
+import dmd.TOK;
+import dmd.Type;
+import dmd.AddrExp;
+import dmd.VarExp;
+import dmd.IntegerExp;
+import dmd.TY;
+import dmd.Token;
+import dmd.NotExp;
+import dmd.WANT;
+import dmd.GlobalExpressions;
+
+import dmd.backend.elem;
+import dmd.backend.OPER;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.RTLSYM;
+
+import dmd.codegen.Util;
+
+import dmd.expression.util.arrayTypeCompatible;
+import dmd.expression.Util;
+import dmd.expression.Equal;
+
+class EqualExp : BinExp
+{
+	this(TOK op, Loc loc, Expression e1, Expression e2)
+	{
+		super(loc, op, EqualExp.sizeof, e1, e2);
+		assert(op == TOK.TOKequal || op == TOK.TOKnotequal);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Expression e;
+		Type t1;
+		Type t2;
+
+		//printf("EqualExp.semantic('%s')\n", toChars());
+		if (type)
+			return this;
+
+		BinExp.semanticp(sc);
+
+		/* Before checking for operator overloading, check to see if we're
+		 * comparing the addresses of two statics. If so, we can just see
+		 * if they are the same symbol.
+		 */
+		if (e1.op == TOK.TOKaddress && e2.op == TOK.TOKaddress)
+		{	
+			AddrExp ae1 = cast(AddrExp)e1;
+			AddrExp ae2 = cast(AddrExp)e2;
+
+			if (ae1.e1.op == TOK.TOKvar && ae2.e1.op == TOK.TOKvar)
+			{   
+				VarExp ve1 = cast(VarExp)ae1.e1;
+				VarExp ve2 = cast(VarExp)ae2.e1;
+
+				if (ve1.var == ve2.var /*|| ve1.var.toSymbol() == ve2.var.toSymbol()*/)
+				{
+					// They are the same, result is 'true' for ==, 'false' for !=
+					e = new IntegerExp(loc, (op == TOK.TOKequal), Type.tboolean);
+					return e;
+				}
+			}
+		}
+
+		if (e1.type.toBasetype().ty == TY.Tclass && e2.op == TOK.TOKnull || e2.type.toBasetype().ty == TY.Tclass && e1.op == TOK.TOKnull)
+		{
+			error("use '%s' instead of '%s' when comparing with null",
+				Token.toChars(op == TOK.TOKequal ? TOK.TOKidentity : TOK.TOKnotidentity),
+				Token.toChars(op));
+		}
+
+		//if (e2.op != TOKnull)
+		{
+			e = op_overload(sc);
+			if (e)
+			{
+				if (op == TOK.TOKnotequal)
+				{
+					e = new NotExp(e.loc, e);
+					e = e.semantic(sc);
+				}
+
+				return e;
+			}
+		}
+
+		e = typeCombine(sc);
+		type = Type.tboolean;
+
+		// Special handling for array comparisons
+		if (!arrayTypeCompatible(loc, e1.type, e2.type))
+		{
+			if (e1.type != e2.type && e1.type.isfloating() && e2.type.isfloating())
+			{
+				// Cast both to complex
+				e1 = e1.castTo(sc, Type.tcomplex80);
+				e2 = e2.castTo(sc, Type.tcomplex80);
+			}
+		}
+
+		return e;
+	}
+
+	Expression optimize(int result)
+	{
+		Expression e;
+
+		//printf("EqualExp::optimize(result = %x) %s\n", result, toChars());
+		e1 = e1.optimize(WANTvalue | (result & WANTinterpret));
+		e2 = e2.optimize(WANTvalue | (result & WANTinterpret));
+		e = this;
+
+		Expression e1 = fromConstInitializer(result, this.e1);
+		Expression e2 = fromConstInitializer(result, this.e2);
+
+		e = Equal(op, type, e1, e2);
+		if (e is EXP_CANT_INTERPRET)
+			e = this;
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	int isBit()
+	{
+		assert(false);
+	}
+
+	bool isCommutative()
+	{
+		return true;
+	}
+
+	Identifier opId()
+	{
+		return Id.eq;
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		//printf("EqualExp::toElem() %s\n", toChars());
+		elem* e;
+		OPER eop;
+		Type t1 = e1.type.toBasetype();
+		Type t2 = e2.type.toBasetype();
+
+		switch (op)
+		{
+			case TOKequal:		eop = OPeqeq;	break;
+			case TOKnotequal:	eop = OPne;	break;
+			default:
+				dump(0);
+				assert(0);
+		}
+
+		//printf("EqualExp::toElem()\n");
+		if (t1.ty == Tstruct)
+		{	// Do bit compare of struct's
+			elem* es1;
+			elem* es2;
+			elem* ecount;
+
+			es1 = e1.toElem(irs);
+			es2 = e2.toElem(irs);
+		static if (true) {
+			es1 = addressElem(es1, t1);
+			es2 = addressElem(es2, t2);
+		} else {
+			es1 = el_una(OPaddr, TYnptr, es1);
+			es2 = el_una(OPaddr, TYnptr, es2);
+		}
+			e = el_param(es1, es2);
+			ecount = el_long(TYint, t1.size());
+			e = el_bin(OPmemcmp, TYint, e, ecount);
+			e = el_bin(eop, TYint, e, el_long(TYint, 0));
+			el_setLoc(e,loc);
+		}
+///	static if (false) {
+///		else if (t1.ty == Tclass && t2.ty == Tclass)
+///		{
+///			elem *ec1;
+///			elem *ec2;
+///
+///			ec1 = e1.toElem(irs);
+///			ec2 = e2.toElem(irs);
+///			e = el_bin(OPcall,TYint,el_var(rtlsym[RTLSYM_OBJ_EQ]),el_param(ec1, ec2));
+///		}
+///	}
+		else if ((t1.ty == Tarray || t1.ty == Tsarray) &&
+			 (t2.ty == Tarray || t2.ty == Tsarray))
+		{
+			elem* ea1;
+			elem* ea2;
+			elem* ep;
+			Type telement = t1.nextOf().toBasetype();
+			int rtlfunc;
+
+			ea1 = e1.toElem(irs);
+			ea1 = array_toDarray(t1, ea1);
+			ea2 = e2.toElem(irs);
+			ea2 = array_toDarray(t2, ea2);
+
+		version (DMDV2) {
+			ep = el_params(telement.arrayOf().getInternalTypeInfo(null).toElem(irs),
+				ea2, ea1, null);
+			rtlfunc = RTLSYM_ARRAYEQ2;
+		} else {
+			ep = el_params(telement.getInternalTypeInfo(null).toElem(irs), ea2, ea1, null);
+			rtlfunc = RTLSYM_ARRAYEQ;
+		}
+			e = el_bin(OPcall, TYint, el_var(rtlsym[rtlfunc]), ep);
+			if (op == TOKnotequal)
+				e = el_bin(OPxor, TYint, e, el_long(TYint, 1));
+			el_setLoc(e,loc);
+		}
+		else
+			e = toElemBin(irs, eop);
+
+		return e;
+	}
+}
+