diff dmd/NullExp.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/NullExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,154 @@
+module dmd.NullExp;
+
+import dmd.Expression;
+import dmd.backend.elem;
+import dmd.InterState;
+import dmd.MATCH;
+import dmd.Type;
+import dmd.TY;
+import dmd.TypeTypedef;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.IRState;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.backend.dt_t;
+import dmd.backend.Util;
+
+class NullExp : Expression
+{
+	ubyte committed;
+
+	this(Loc loc)
+	{
+		super(loc, TOK.TOKnull, NullExp.sizeof);
+	}
+
+	Expression semantic(Scope sc)
+	{
+version (LOGSEMANTIC) {
+		printf("NullExp.semantic('%s')\n", toChars());
+}
+		// null is the same as (void*)0
+		if (!type)
+			type = Type.tvoid.pointerTo();
+
+		return this;
+	}
+
+	bool isBool(bool result)
+	{
+		assert(false);
+	}
+
+	int isConst()
+	{
+		assert(false);
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring("null");
+	}
+
+	void toMangleBuffer(OutBuffer buf)
+	{
+		assert(false);
+	}
+
+	MATCH implicitConvTo(Type t)
+	{
+static if (false) {
+		printf("NullExp.implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n",
+		toChars(), type.toChars(), t.toChars(), committed);
+}
+		if (this.type.equals(t))
+			return MATCH.MATCHexact;
+
+		/* Allow implicit conversions from invariant to mutable|const,
+		 * and mutable to invariant. It works because, after all, a null
+		 * doesn't actually point to anything.
+		 */
+		if (t.invariantOf().equals(type.invariantOf()))
+			return MATCH.MATCHconst;
+
+		// null implicitly converts to any pointer type or dynamic array
+		if (type.ty == TY.Tpointer && type.nextOf().ty == TY.Tvoid)
+		{
+			if (t.ty == TY.Ttypedef)
+				t = (cast(TypeTypedef)t).sym.basetype;
+			if (t.ty == TY.Tpointer || t.ty == TY.Tarray ||
+				t.ty == TY.Taarray  || t.ty == TY.Tclass ||
+				t.ty == TY.Tdelegate)
+			{
+				return committed ? MATCH.MATCHconvert : MATCH.MATCHexact;
+			}
+		}
+
+		return Expression.implicitConvTo(t);
+	}
+
+	Expression castTo(Scope sc, Type t)
+	{
+		NullExp e;
+		Type tb;
+
+		//printf("NullExp::castTo(t = %p)\n", t);
+		if (type is t)
+		{
+			committed = 1;
+			return this;
+		}
+
+		e = cast(NullExp)copy();
+		e.committed = 1;
+		tb = t.toBasetype();
+		e.type = type.toBasetype();
+
+		if (tb !is e.type)
+		{
+			// null implicitly converts to any pointer type or dynamic array
+			if (e.type.ty == TY.Tpointer && e.type.nextOf().ty == TY.Tvoid &&
+				(tb.ty == TY.Tpointer || tb.ty == TY.Tarray || tb.ty == TY.Taarray ||
+				 tb.ty == TY.Tdelegate))
+			{
+static if (false) {
+				if (tb.ty == TY.Tdelegate)
+				{   
+					TypeDelegate td = cast(TypeDelegate)tb;
+					TypeFunction tf = cast(TypeFunction)td.nextOf();
+
+					if (!tf.varargs && !(tf.arguments && tf.arguments.dim))
+					{
+						return Expression.castTo(sc, t);
+					}
+				}
+}
+			}
+			else
+			{
+				return e.Expression.castTo(sc, t);
+			}
+		}
+		e.type = t;
+		return e;
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	elem* toElem(IRState* irs)
+	{
+		return el_long(type.totym(), 0);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		assert(type);
+		return dtnzeros(pdt, cast(uint)type.size());
+	}
+}
+