diff dmd/VarExp.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children ccbc1e0bb3f0
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/VarExp.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,258 @@
+module dmd.VarExp;
+
+import dmd.Expression;
+import dmd.Declaration;
+import dmd.InterState;
+import dmd.OutBuffer;
+import dmd.Loc;
+import dmd.Scope;
+import dmd.InlineCostState;
+import dmd.FuncLiteralDeclaration;
+import dmd.VarDeclaration;
+import dmd.Dsymbol;
+import dmd.FuncDeclaration;
+import dmd.InlineDoState;
+import dmd.HdrGenState;
+import dmd.TOK;
+import dmd.TY;
+import dmd.STC;
+import dmd.SymbolExp;
+import dmd.Type;
+import dmd.backend.dt_t;
+import dmd.expression.Util;
+
+// Variable
+
+class VarExp : SymbolExp
+{
+	this(Loc loc, Declaration var, int hasOverloads = 0)
+	{
+		super(loc, TOK.TOKvar, VarExp.sizeof, var, hasOverloads);
+		
+		//printf("VarExp(this = %p, '%s', loc = %s)\n", this, var.toChars(), loc.toChars());
+		//if (strcmp(var.ident.toChars(), "func") == 0) halt();
+		this.type = var.type;
+	}
+
+	int equals(Object o)
+	{
+		assert(false);
+	}
+
+	Expression semantic(Scope sc)
+	{
+		FuncLiteralDeclaration fd;
+
+	version (LOGSEMANTIC) {
+		printf("VarExp.semantic(%s)\n", toChars());
+	}
+		if (!type)
+		{
+			type = var.type;
+static if (false) {
+			if (var.storage_class & STC.STClazy)
+			{
+				TypeFunction tf = new TypeFunction(null, type, 0, LINK.LINKd);
+				type = new TypeDelegate(tf);
+				type = type.semantic(loc, sc);
+			}
+}
+		}
+
+		/* Fix for 1161 doesn't work because it causes protection
+		 * problems when instantiating imported templates passing private
+		 * variables as alias template parameters.
+		 */
+		//accessCheck(loc, sc, null, var);
+
+		VarDeclaration v = var.isVarDeclaration();
+		if (v)
+		{
+static if (false) {
+			if ((v.isConst() || v.isInvariant()) && type.toBasetype().ty != TY.Tsarray && v.init)
+			{
+				ExpInitializer ei = v.init.isExpInitializer();
+				if (ei)
+				{
+					//ei.exp.implicitCastTo(sc, type).print();
+					return ei.exp.implicitCastTo(sc, type);
+				}
+			}
+}
+			v.checkNestedReference(sc, loc);
+version (DMDV2) {
+	static if (true) {
+			if (sc.func)
+			{
+				/* Determine if sc.func is pure or if any function that
+				 * encloses it is also pure.
+				 */
+				bool hasPureParent = false;
+				for (FuncDeclaration outerfunc = sc.func; outerfunc;)
+				{
+					if (outerfunc.isPure())
+					{
+						hasPureParent = true;
+						break;
+					}
+					Dsymbol parent = outerfunc.toParent2();
+					if (!parent)
+						break;
+					outerfunc = parent.isFuncDeclaration();
+				}
+
+				/* If ANY of its enclosing functions are pure,
+				 * it cannot do anything impure.
+				 * If it is pure, it cannot access any mutable variables other
+				 * than those inside itself
+				 */
+				if (hasPureParent && !sc.intypeof && v.isDataseg() && !v.isInvariant())
+				{
+					error("pure function '%s' cannot access mutable static data '%s'",
+						sc.func.toChars(), v.toChars());
+				}
+				else if (sc.func.isPure() && sc.parent != v.parent && !sc.intypeof && !v.isInvariant() && !(v.storage_class & STC.STCmanifest))
+				{
+					error("pure nested function '%s' cannot access mutable data '%s'", sc.func.toChars(), v.toChars());
+					if (v.isEnumDeclaration())
+						error("enum");
+				}	
+			}
+	} else {
+			if (sc.func && sc.func.isPure() && !sc.intypeof)
+			{
+				if (v.isDataseg() && !v.isInvariant())
+					error("pure function '%s' cannot access mutable static data '%s'", sc.func.toChars(), v.toChars());
+			}
+	}
+}
+		}
+		else
+		{
+static if (false) {
+			if ((fd = var.isFuncLiteralDeclaration()) !is null)
+			{	
+				Expression e = new FuncExp(loc, fd);
+				e.type = type;
+				return e;
+			}
+}
+		}
+
+		return this;
+	}
+
+	Expression optimize(int result)
+	{
+		return fromConstInitializer(result, this);
+	}
+
+	Expression interpret(InterState* istate)
+	{
+		assert(false);
+	}
+
+	void dump(int indent)
+	{
+		assert(false);
+	}
+
+	string toChars()
+	{
+		return var.toChars();
+	}
+
+	void toCBuffer(OutBuffer buf, HdrGenState* hgs)
+	{
+		buf.writestring(var.toChars());
+	}
+
+	void checkEscape()
+	{
+		VarDeclaration v = var.isVarDeclaration();
+		if (v)
+		{	
+			Type tb = v.type.toBasetype();
+			// if reference type
+			if (tb.ty == TY.Tarray || tb.ty == TY.Tsarray || tb.ty == TY.Tclass)
+			{
+				if ((v.isAuto() || v.isScope()) && !v.noauto)
+					error("escaping reference to scope local %s", v.toChars());
+				else if (v.storage_class & STC.STCvariadic)
+					error("escaping reference to variadic parameter %s", v.toChars());
+			}
+		}
+	}
+
+version (DMDV2) {
+	int isLvalue()
+	{
+		if (var.storage_class & STClazy)
+			return 0;
+		return 1;
+	}
+}
+	Expression toLvalue(Scope sc, Expression e)
+	{
+static if (false) {
+		tym = tybasic(e1.ET.Tty);
+		if (!(tyscalar(tym) ||
+		  tym == TYM.TYstruct ||
+		  tym == TYM.TYarray && e.Eoper == TOK.TOKaddr))
+		{
+			synerr(EM_lvalue);	// lvalue expected
+		}
+}
+		if (var.storage_class & STC.STClazy)
+			error("lazy variables cannot be lvalues");
+
+		return this;
+	}
+
+	Expression modifiableLvalue(Scope sc, Expression e)
+	{
+		//printf("VarExp::modifiableLvalue('%s')\n", var.toChars());
+		if (type && type.toBasetype().ty == TY.Tsarray)
+			error("cannot change reference to static array '%s'", var.toChars());
+
+		var.checkModify(loc, sc, type);
+
+		// See if this expression is a modifiable lvalue (i.e. not const)
+		return toLvalue(sc, e);
+	}
+
+	dt_t** toDt(dt_t** pdt)
+	{
+		assert(false);
+	}
+
+	void scanForNestedRef(Scope sc)
+	{
+		assert(false);
+	}
+
+	int inlineCost(InlineCostState* ics)
+	{
+		//printf("VarExp.inlineCost() %s\n", toChars());
+		return 1;
+	}
+
+	Expression doInline(InlineDoState ids)
+	{
+		int i;
+
+		//printf("VarExp.doInline(%s)\n", toChars());
+		for (i = 0; i < ids.from.dim; i++)
+		{
+			if (var == cast(Declaration)ids.from.data[i])
+			{
+				VarExp ve = cast(VarExp)copy();
+
+				ve.var = cast(Declaration)ids.to.data[i];
+				return ve;
+			}
+		}
+		return this;
+	}
+}
+