view dmd/DotTemplateInstanceExp.d @ 114:e28b18c23469

added a module dmd.common for commonly used stuff it currently holds code for consistency checking of predefined versions also added a VisualD project file
author Trass3r
date Wed, 01 Sep 2010 18:21:58 +0200
parents 2e2a5c3f943a
children 60bb0fe4563e
line wrap: on
line source

module dmd.DotTemplateInstanceExp;

import dmd.common;
import dmd.Expression;
import dmd.UnaExp;
import dmd.OutBuffer;
import dmd.Loc;
import dmd.Scope;
import dmd.TemplateInstance;
import dmd.HdrGenState;
import dmd.TOK;
import dmd.PREC;
import dmd.Declaration;
import dmd.Global;
import dmd.TypePointer;
import dmd.TypeStruct;
import dmd.TY;
import dmd.ScopeExp;
import dmd.DotExp;
import dmd.Type;
import dmd.Identifier;
import dmd.ErrorExp;
import dmd.DotVarExp;
import dmd.TemplateDeclaration;
import dmd.Dsymbol;

import dmd.expression.Util;

/* Things like:
 *	foo.bar!(args)
 */
class DotTemplateInstanceExp : UnaExp
{
	TemplateInstance ti;

	this(Loc loc, Expression e, TemplateInstance ti)
	{
		super(loc, TOK.TOKdotti, DotTemplateInstanceExp.sizeof, e);
		//printf("DotTemplateInstanceExp()\n");
		this.ti = ti;
	}

	override Expression syntaxCopy()
	{
		DotTemplateInstanceExp de = new DotTemplateInstanceExp(loc, e1.syntaxCopy(), cast(TemplateInstance)ti.syntaxCopy(null));
		return de;
	}

	override Expression semantic(Scope sc)
	{
		Dsymbol s;
		Dsymbol s2;
		TemplateDeclaration td;
		Expression e;
		Identifier id;
		Type t1;
		Expression eleft = null;
		Expression eright;

	version (LOGSEMANTIC) {
		printf("DotTemplateInstanceExp.semantic('%s')\n", toChars());
	}
		//e1.print();
		//print();
		e1 = e1.semantic(sc);
		t1 = e1.type;
		if (t1)
			t1 = t1.toBasetype();
		//t1.print();

		/* Extract the following from e1:
		 *	s: the symbol which ti should be a member of
		 *	eleft: if not null, it is the 'this' pointer for ti
		 */

		if (e1.op == TOKdotexp)
		{	
			DotExp de = cast(DotExp)e1;
			eleft = de.e1;
			eright = de.e2;
		}
		else
		{	
			eleft = null;
			eright = e1;
		}
		if (eright.op == TOKimport)
		{
			s = (cast(ScopeExp)eright).sds;
		}
		else if (e1.op == TOKtype)
		{
			s = t1.isClassHandle();
			if (!s)
			{
				if (t1.ty == Tstruct)
					s = (cast(TypeStruct)t1).sym;
				else
					goto L1;
			}
		}
		else if (t1 && (t1.ty == Tstruct || t1.ty == Tclass))
		{
			s = t1.toDsymbol(sc);
			eleft = e1;
		}
		else if (t1 && t1.ty == Tpointer)
		{
			t1 = (cast(TypePointer)t1).next.toBasetype();
			if (t1.ty != Tstruct)
				goto L1;
			s = t1.toDsymbol(sc);
			eleft = e1;
		}
		else
		{
		  L1:
			error("template %s is not a member of %s", ti.toChars(), e1.toChars());
			goto Lerr;
		}

		assert(s);
		id = ti.name;
		s2 = s.search(loc, id, 0);
		if (!s2)
		{
			if (!s.ident)
				error("template identifier %s is not a member of undefined %s", id.toChars(), s.kind());
			else
				error("template identifier %s is not a member of %s %s", id.toChars(), s.kind(), s.ident.toChars());
			goto Lerr;
		}
		s = s2;
		s.semantic(sc);
		s = s.toAlias();
		td = s.isTemplateDeclaration();
		if (!td)
		{
			error("%s is not a template", id.toChars());
			goto Lerr;
		}
		if (global.errors)
			goto Lerr;

		ti.tempdecl = td;

		if (eleft)
		{	
			Declaration v;

			ti.semantic(sc);
			s = ti.inst.toAlias();
			v = s.isDeclaration();
			if (v)
			{   
				e = new DotVarExp(loc, eleft, v);
				e = e.semantic(sc);
				return e;
			}
		}

		e = new ScopeExp(loc, ti);
		if (eleft)
		{
			e = new DotExp(loc, eleft, e);
		}
		e = e.semantic(sc);
		return e;

	Lerr:
		return new ErrorExp();
	}

	override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		expToCBuffer(buf, hgs, e1, PREC.PREC_primary);
		buf.writeByte('.');
		ti.toCBuffer(buf, hgs);
	}

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