diff dmd/DeleteExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 2e2a5c3f943a
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/DeleteExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,273 @@
+module dmd.DeleteExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.UnaExp;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.Type;
+import dmd.IndexExp;
+import dmd.Global;
+import dmd.VarExp;
+import dmd.Identifier;
+import dmd.StructDeclaration;
+import dmd.Lexer;
+import dmd.FuncDeclaration;
+import dmd.TypeStruct;
+import dmd.CallExp;
+import dmd.DotVarExp;
+import dmd.DeclarationExp;
+import dmd.ExpInitializer;
+import dmd.VarDeclaration;
+import dmd.TypePointer;
+import dmd.ClassDeclaration;
+import dmd.TypeClass;
+import dmd.TY;
+import dmd.TOK;
+import dmd.TypeAArray;
+import dmd.TypeSArray;
+
+import dmd.codegen.Util;
+import dmd.backend.Util;
+import dmd.backend.OPER;
+import dmd.backend.RTLSYM;
+import dmd.backend.mTY;
+import dmd.backend.Symbol;
+import dmd.backend.TYM;
+
+class DeleteExp : UnaExp
+{
+	this(Loc loc, Expression e)
+	{
+		super(loc, TOK.TOKdelete, DeleteExp.sizeof, e);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		Type tb;
+
+		UnaExp.semantic(sc);
+		e1 = resolveProperties(sc, e1);
+		e1 = e1.toLvalue(sc, null);
+		type = Type.tvoid;
+
+		tb = e1.type.toBasetype();
+		switch (tb.ty)
+		{	
+			case Tclass:
+			{   
+				TypeClass tc = cast(TypeClass)tb;
+				ClassDeclaration cd = tc.sym;
+
+				if (cd.isCOMinterface())
+				{	/* Because COM classes are deleted by IUnknown.Release()
+					 */
+					error("cannot delete instance of COM interface %s", cd.toChars());
+				}
+				break;
+			}
+			case Tpointer:
+				tb = (cast(TypePointer)tb).next.toBasetype();
+				if (tb.ty == Tstruct)
+				{
+					TypeStruct ts = cast(TypeStruct)tb;
+					StructDeclaration sd = ts.sym;
+					FuncDeclaration f = sd.aggDelete;
+					FuncDeclaration fd = sd.dtor;
+
+					if (!f && !fd)
+						break;
+
+					/* Construct:
+					 *	ea = copy e1 to a tmp to do side effects only once
+					 *	eb = call destructor
+					 *	ec = call deallocator
+					 */
+					Expression ea = null;
+					Expression eb = null;
+					Expression ec = null;
+					VarDeclaration v;
+
+					if (fd && f)
+					{   
+						Identifier id = Lexer.idPool("__tmp");
+						v = new VarDeclaration(loc, e1.type, id, new ExpInitializer(loc, e1));
+						v.semantic(sc);
+						v.parent = sc.parent;
+						ea = new DeclarationExp(loc, v);
+						ea.type = v.type;
+					}
+
+					if (fd)
+					{   
+						Expression e = ea ? new VarExp(loc, v) : e1;
+						e = new DotVarExp(Loc(0), e, fd, 0);
+						eb = new CallExp(loc, e);
+						eb = eb.semantic(sc);
+					}
+
+					if (f)
+					{
+						Type tpv = Type.tvoid.pointerTo();
+						Expression e = ea ? new VarExp(loc, v) : e1.castTo(sc, tpv);
+						e = new CallExp(loc, new VarExp(loc, f), e);
+						ec = e.semantic(sc);
+					}
+					ea = combine(ea, eb);
+					ea = combine(ea, ec);
+					assert(ea);
+					return ea;
+				}
+				break;
+
+			case Tarray:
+				/* BUG: look for deleting arrays of structs with dtors.
+				 */
+				break;
+
+			default:
+				if (e1.op == TOKindex)
+				{
+					IndexExp ae = cast(IndexExp)e1;
+					Type tb1 = ae.e1.type.toBasetype();
+					if (tb1.ty == Taarray)
+						break;
+				}
+				error("cannot delete type %s", e1.type.toChars());
+				break;
+		}
+		
+		if (e1.op == TOKindex)
+		{
+			IndexExp ae = cast(IndexExp)e1;
+			Type tb1 = ae.e1.type.toBasetype();
+			if (tb1.ty == Taarray)
+			{   
+				if (!global.params.useDeprecated)
+					error("delete aa[key] deprecated, use aa.remove(key)");
+			}
+		}
+
+		return this;
+	}
+
+	Expression checkToBoolean()
+	{
+		assert(false);
+	}
+
+	bool checkSideEffect(int flag)
+	{
+		return true;
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		elem* e;
+		int rtl;
+		Type tb;
+
+		//printf("DeleteExp.toElem()\n");
+		if (e1.op == TOKindex)
+		{
+			IndexExp ae = cast(IndexExp)e1;
+			tb = ae.e1.type.toBasetype();
+			if (tb.ty == Taarray)
+			{
+				TypeAArray taa = cast(TypeAArray)tb;
+				elem* ea = ae.e1.toElem(irs);
+				elem* ekey = ae.e2.toElem(irs);
+				elem* ep;
+				elem* keyti;
+
+				if (tybasic(ekey.Ety) == TYstruct)
+				{
+					ekey = el_una(OPstrpar, TYstruct, ekey);
+					ekey.Enumbytes = ekey.E1.Enumbytes;
+					assert(ekey.Enumbytes);
+				}
+
+				Symbol *s = taa.aaGetSymbol("Del", 0);
+				keyti = taa.index.getInternalTypeInfo(null).toElem(irs);
+				ep = el_params(ekey, keyti, ea, null);
+				e = el_bin(OPcall, TYnptr, el_var(s), ep);
+				goto Lret;
+			}
+		}
+		//e1.type.print();
+		e = e1.toElem(irs);
+		tb = e1.type.toBasetype();
+		switch (tb.ty)
+		{
+			case Tarray:
+			{   
+				e = addressElem(e, e1.type);
+				rtl = RTLSYM_DELARRAYT;
+
+				/* See if we need to run destructors on the array contents
+				 */
+				elem *et = null;
+				Type tv = tb.nextOf().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)
+						et = tb.nextOf().getTypeInfo(null).toElem(irs);
+				}
+				if (!et)				// if no destructors needed
+					et = el_long(TYnptr, 0);	// pass null for TypeInfo
+				e = el_params(et, e, null);
+				// call _d_delarray_t(e, et);
+				e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
+				goto Lret;
+			}
+			case Tclass:
+				if (e1.op == TOKvar)
+				{	
+					VarExp ve = cast(VarExp)e1;
+					if (ve.var.isVarDeclaration() &&
+						ve.var.isVarDeclaration().onstack)
+					{
+						rtl = RTLSYM_CALLFINALIZER;
+						if (tb.isClassHandle().isInterfaceDeclaration())
+							rtl = RTLSYM_CALLINTERFACEFINALIZER;
+						break;
+					}
+				}
+				e = addressElem(e, e1.type);
+				rtl = RTLSYM_DELCLASS;
+				if (tb.isClassHandle().isInterfaceDeclaration())
+					rtl = RTLSYM_DELINTERFACE;
+				break;
+
+			case Tpointer:
+				e = addressElem(e, e1.type);
+				rtl = RTLSYM_DELMEMORY;
+				break;
+
+			default:
+				assert(0);
+				break;
+		}
+		e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), e);
+
+	  Lret:
+		el_setLoc(e,loc);
+		return e;
+	}
+}
+