view dmd/DotIdExp.d @ 178:e3afd1303184

Many small bugs fixed Made all classes derive from TObject to detect memory leaks (functionality is disabled for now) Began work on overriding backend memory allocations (to avoid memory leaks)
author korDen
date Sun, 17 Oct 2010 07:42:00 +0400
parents 9d194c848e3a
children b0d41ff5e0df
line wrap: on
line source

module dmd.DotIdExp;

import dmd.common;
import dmd.Expression;
import dmd.Identifier;
import dmd.IntegerExp;
import dmd.Type;
import dmd.TY;
import dmd.ScopeExp;
import dmd.StringExp;
import dmd.PtrExp;
import dmd.TypePointer;
import dmd.Dsymbol;
import dmd.EnumMember;
import dmd.VarDeclaration;
import dmd.ThisExp;
import dmd.DotVarExp;
import dmd.VarExp;
import dmd.CommaExp;
import dmd.FuncDeclaration;
import dmd.OverloadSet;
import dmd.OverExp;
import dmd.TypeExp;
import dmd.TupleDeclaration;
import dmd.ScopeDsymbol;
import dmd.Import;
import dmd.Id;
import dmd.TupleExp;
import dmd.ArrayTypes;
import dmd.UnaExp;
import dmd.OutBuffer;
import dmd.Loc;
import dmd.Scope;
import dmd.TOK;
import dmd.HdrGenState;
import dmd.ClassDeclaration;
import dmd.StructDeclaration;
import dmd.AggregateDeclaration;
import dmd.DotExp;
import dmd.Global;
import dmd.IdentifierExp;
import dmd.CallExp;
import dmd.PREC;

import dmd.expression.Util;

class DotIdExp : UnaExp
{
	Identifier ident;

	this(Loc loc, Expression e, Identifier ident)
	{
		register();
		super(loc, TOK.TOKdot, DotIdExp.sizeof, e);
		this.ident = ident;
	}

	override Expression semantic(Scope sc)
	{
		// Indicate we didn't come from CallExp::semantic()
		return semantic(sc, 0);
	}

	Expression semantic(Scope sc, int flag)
	{
		Expression e;
		Expression eleft;
		Expression eright;

version (LOGSEMANTIC) {
		printf("DotIdExp.semantic(this = %p, '%s')\n", this, toChars());
		//printf("e1.op = %d, '%s'\n", e1.op, Token.toChars(e1.op));
}

	//{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }

static if (false) {
		/* Don't do semantic analysis if we'll be converting
		 * it to a string.
		 */
		if (ident == Id.stringof)
		{	
			char *s = e1.toChars();
			e = new StringExp(loc, s, strlen(s), 'c');
			e = e.semantic(sc);
			return e;
		}
}

		/* Special case: rewrite this.id and super.id
		 * to be classtype.id and baseclasstype.id
		 * if we have no this pointer.
		 */
		if ((e1.op == TOK.TOKthis || e1.op == TOK.TOKsuper) && !hasThis(sc))
		{
			ClassDeclaration cd;
			StructDeclaration sd;
			AggregateDeclaration ad;

			ad = sc.getStructClassScope();
			if (ad)
			{
				cd = ad.isClassDeclaration();
				if (cd)
				{
					if (e1.op == TOK.TOKthis)
					{
						e = typeDotIdExp(loc, cd.type, ident);
						return e.semantic(sc);
					}
					else if (cd.baseClass && e1.op == TOK.TOKsuper)
					{
						e = typeDotIdExp(loc, cd.baseClass.type, ident);
						return e.semantic(sc);
					}
				}
				else
				{
					sd = ad.isStructDeclaration();
					if (sd)
					{
						if (e1.op == TOK.TOKthis)
						{
						e = typeDotIdExp(loc, sd.type, ident);
						return e.semantic(sc);
						}
					}
				}
			}
		}

		UnaExp.semantic(sc);

		if (e1.op == TOK.TOKdotexp)
		{
			DotExp de = cast(DotExp)e1;
			eleft = de.e1;
			eright = de.e2;
		}
		else
		{
			e1 = resolveProperties(sc, e1);
			eleft = null;
			eright = e1;
		}
		
version (DMDV2) {
		if (e1.op == TOK.TOKtuple && ident == Id.offsetof)
		{
			/* 'distribute' the .offsetof to each of the tuple elements.
			*/
			TupleExp te = cast(TupleExp)e1;
			Expressions exps = new Expressions();
			exps.setDim(te.exps.dim);
			for (int i = 0; i < exps.dim; i++)
			{   
				auto ee = te.exps[i];
				ee = ee.semantic(sc);
				ee = new DotIdExp(ee.loc, ee, Id.offsetof);
				exps[i] = ee;
			}
			e = new TupleExp(loc, exps);
			e = e.semantic(sc);
			return e;
		}
}

		if (e1.op == TOK.TOKtuple && ident == Id.length)
		{
			TupleExp te = cast(TupleExp)e1;
			e = new IntegerExp(loc, te.exps.dim, Type.tsize_t);
			return e;
		}

		if (e1.op == TOK.TOKdottd)
		{
			error("template %s does not have property %s", e1.toChars(), ident.toChars());
			return e1;
		}

		if (!e1.type)
		{
			error("expression %s does not have property %s", e1.toChars(), ident.toChars());
			return e1;
		}

		Type t1b = e1.type.toBasetype();

		if (eright.op == TOK.TOKimport)	// also used for template alias's
		{
			ScopeExp ie = cast(ScopeExp)eright;

			/* Disable access to another module's private imports.
			 * The check for 'is sds our current module' is because
			 * the current module should have access to its own imports.
			 */
			Dsymbol s = ie.sds.search(loc, ident, //0);
				(ie.sds.isModule() && ie.sds != sc.module_) ? 1 : 0);
			if (s)
			{
				s = s.toAlias();
				checkDeprecated(sc, s);

				EnumMember em = s.isEnumMember();
				if (em)
				{
				e = em.value;
				e = e.semantic(sc);
				return e;
				}

				VarDeclaration v = s.isVarDeclaration();
				if (v)
				{
				//printf("DotIdExp. Identifier '%s' is a variable, type '%s'\n", toChars(), v.type.toChars());
				if (v.inuse)
				{
					error("circular reference to '%s'", v.toChars());
					type = Type.tint32;
					return this;
				}
				type = v.type;
				if (v.needThis())
				{
					if (!eleft)
					eleft = new ThisExp(loc);
					e = new DotVarExp(loc, eleft, v);
					e = e.semantic(sc);
				}
				else
				{
					e = new VarExp(loc, v);
					if (eleft)
					{	
						e = new CommaExp(loc, eleft, e);
						e.type = v.type;
					}
				}
				return e.deref();
				}

				FuncDeclaration f = s.isFuncDeclaration();
				if (f)
				{
					//printf("it's a function\n");
					if (f.needThis())
					{
						if (!eleft)
						eleft = new ThisExp(loc);
						e = new DotVarExp(loc, eleft, f);
						e = e.semantic(sc);
					}
					else
					{
						e = new VarExp(loc, f, 1);
						if (eleft)
						{	e = new CommaExp(loc, eleft, e);
						e.type = f.type;
						}
					}
					return e;
				}
version (DMDV2) {
				OverloadSet o = s.isOverloadSet();
				if (o)
				{   
					//printf("'%s' is an overload set\n", o.toChars());
					return new OverExp(o);
				}
}

				Type t = s.getType();
				if (t)
				{
					return new TypeExp(loc, t);
				}

				TupleDeclaration tup = s.isTupleDeclaration();
				if (tup)
				{
					if (eleft)
						error("cannot have e.tuple");
					e = new TupleExp(loc, tup);
					e = e.semantic(sc);
					return e;
				}

				ScopeDsymbol sds = s.isScopeDsymbol();
				if (sds)
				{
					//printf("it's a ScopeDsymbol\n");
					e = new ScopeExp(loc, sds);
					e = e.semantic(sc);
					if (eleft)
						e = new DotExp(loc, eleft, e);
					return e;
				}

				Import imp = s.isImport();
				if (imp)
				{
					ScopeExp iee = new ScopeExp(loc, imp.pkg);
					return iee.semantic(sc);
				}

				// BUG: handle other cases like in IdentifierExp.semantic()
version (DEBUG) {
				printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
}
				assert(0);
			}
			else if (ident is Id.stringof_)
			{  
				string ss = ie.toChars();
				e = new StringExp(loc, ss, 'c');
				e = e.semantic(sc);
				return e;
			}
			error("undefined identifier %s", toChars());
			type = Type.tvoid;
			return this;
		}
		else if (t1b.ty == TY.Tpointer &&
			 ident !is Id.init_ && ident !is Id.__sizeof &&
			 ident !is Id.alignof_ && ident !is Id.offsetof &&
			 ident !is Id.mangleof_ && ident !is Id.stringof_)
		{	/* Rewrite:
			 *   p.ident
			 * as:
			 *   (*p).ident
			 */
		e = new PtrExp(loc, e1);
		e.type = (cast(TypePointer)t1b).next;
		return e.type.dotExp(sc, e, ident);
		}
///version (DMDV2) {
		else if (t1b.ty == TY.Tarray ||
				 t1b.ty == TY.Tsarray ||
			 t1b.ty == TY.Taarray)
		{	
			/* If ident is not a valid property, rewrite:
			 *   e1.ident
			 * as:
			 *   .ident(e1)
			 */
			uint errors = global.errors;
			global.gag++;
			Type t1 = e1.type;
			e = e1.type.dotExp(sc, e1, ident);
			global.gag--;
			if (errors != global.errors)	// if failed to find the property
			{
				global.errors = errors;
				e1.type = t1;		// kludge to restore type
				e = new DotIdExp(loc, new IdentifierExp(loc, Id.empty), ident);
				e = new CallExp(loc, e, e1);
			}
			e = e.semantic(sc);
			return e;
		}
///}
		else
		{
			e = e1.type.dotExp(sc, e1, ident);
			if (!(flag && e.op == TOK.TOKdotti))	// let CallExp::semantic() handle this
				e = e.semantic(sc);
			return e;
		}
	}

	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		//printf("DotIdExp.toCBuffer()\n");
		expToCBuffer(buf, hgs, e1, PREC.PREC_primary);
		buf.writeByte('.');
		buf.writestring(ident.toChars());
	}

	override void dump(int i)
	{
		assert(false);
	}
}