view dmd/TemplateValueParameter.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 96c0fff6897d
children b0d41ff5e0df
line wrap: on
line source

module dmd.TemplateValueParameter;

import dmd.common;
import dmd.TemplateParameter;
import dmd.Scope;
import dmd.Declaration;
import dmd.ArrayTypes;
import dmd.Type;
import dmd.Expression;
import dmd.Loc;
import dmd.Identifier;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.MATCH;
import dmd.VarDeclaration;
import dmd.Initializer;
import dmd.ExpInitializer;
import dmd.Global;
import dmd.DefaultInitExp;
import dmd.STC;
import dmd.Util;
import dmd.TY;
import dmd.WANT;
import dmd.TOK;

import dmd.Dsymbol : isExpression;

class TemplateValueParameter : TemplateParameter
{
    /* Syntax:
     *	valType ident : specValue = defaultValue
     */

    Type valType;
    Expression specValue;
    Expression defaultValue;

    this(Loc loc, Identifier ident, Type valType, Expression specValue, Expression defaultValue)
	{
		register();
		super(loc, ident);

		this.valType = valType;
		this.specValue = specValue;
		this.defaultValue = defaultValue;
	}

    override TemplateValueParameter isTemplateValueParameter()
	{
		return this;
	}

    override TemplateParameter syntaxCopy()
	{
		TemplateValueParameter tp = new TemplateValueParameter(loc, ident, valType, specValue, defaultValue);
		tp.valType = valType.syntaxCopy();
		if (specValue)
			tp.specValue = specValue.syntaxCopy();
		if (defaultValue)
			tp.defaultValue = defaultValue.syntaxCopy();
		return tp;
	}

    override void declareParameter(Scope sc)
	{
		VarDeclaration v = new VarDeclaration(loc, valType, ident, null);
		v.storage_class = STC.STCtemplateparameter;
		if (!sc.insert(v))
			error(loc, "parameter '%s' multiply defined", ident.toChars());
		sparam = v;
	}

    override void semantic(Scope sc)
	{
		sparam.semantic(sc);
		valType = valType.semantic(loc, sc);
		if (!(valType.isintegral() || valType.isfloating() || valType.isString()) && valType.ty != TY.Tident)
			error(loc, "arithmetic/string type expected for value-parameter, not %s", valType.toChars());

		if (specValue)
		{
			Expression e = specValue;

			e = e.semantic(sc);
			e = e.implicitCastTo(sc, valType);
			e = e.optimize(WANTvalue | WANTinterpret);
			if (e.op == TOKint64 || e.op == TOKfloat64 ||
				e.op == TOKcomplex80 || e.op == TOKnull || e.op == TOKstring)
				specValue = e;
			//e.toInteger();
		}

static if (false) {	// defer semantic analysis to arg match
		if (defaultValue)
		{
			Expression e = defaultValue;

			e = e.semantic(sc);
			e = e.implicitCastTo(sc, valType);
			e = e.optimize(WANTvalue | WANTinterpret);
			if (e.op == TOKint64)
				defaultValue = e;
			//e.toInteger();
		}
}
	}

    override void print(Object oarg, Object oded)
	{
		assert(false);
	}

    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		valType.toCBuffer(buf, ident, hgs);
		if (specValue)
		{
			buf.writestring(" : ");
			specValue.toCBuffer(buf, hgs);
		}
		if (defaultValue)
		{
			buf.writestring(" = ");
			defaultValue.toCBuffer(buf, hgs);
		}
	}

    override Object specialization()
	{
		return specValue;
	}

    override Object defaultArg(Loc loc, Scope sc)
	{
		Expression e = defaultValue;
		if (e)
		{
			e = e.syntaxCopy();
			e = e.semantic(sc);
version (DMDV2) {
            e = e.resolveLoc(loc, sc);
}
		}
		return e;
	}

    override bool overloadMatch(TemplateParameter tp)
	{
		TemplateValueParameter tvp = tp.isTemplateValueParameter();

		if (tvp)
		{
			if (valType != tvp.valType)
				return false;

			if (valType && !valType.equals(tvp.valType))
				return false;

			if (specValue != tvp.specValue)
				return false;

			return true;			// match
		}

		return false;
	}

    override MATCH matchArg(Scope sc, Objects tiargs, int i, TemplateParameters parameters, Objects dedtypes, Declaration* psparam, int flags)
	{
		//printf("TemplateValueParameter.matchArg()\n");

		Initializer init;
		Declaration sparam;
		MATCH m = MATCHexact;
		Expression ei;
		Object oarg;

		if (i < tiargs.dim)
			oarg = tiargs[i];
		else
		{
			// Get default argument instead
			oarg = defaultArg(loc, sc);
			if (!oarg)
			{
				assert(i < dedtypes.dim);
				// It might have already been deduced
				oarg = dedtypes[i];
				if (!oarg)
					goto Lnomatch;
			}
		}

		ei = isExpression(oarg);
		Type vt;

		if (!ei && oarg)
			goto Lnomatch;

		if (ei && ei.op == TOKvar)
		{
			// Resolve const variables that we had skipped earlier
			ei = ei.optimize(WANTvalue | WANTinterpret);
		}

		if (specValue)
		{
			if (!ei || ei is global.edummy)
				goto Lnomatch;

			Expression e = specValue;

			e = e.semantic(sc);
			e = e.implicitCastTo(sc, valType);
			e = e.optimize(WANTvalue | WANTinterpret);
			//e.type = e.type.toHeadMutable();

			ei = ei.syntaxCopy();
			ei = ei.semantic(sc);
			ei = ei.optimize(WANTvalue | WANTinterpret);
			//ei.type = ei.type.toHeadMutable();
			//printf("\tei: %s, %s\n", ei.toChars(), ei.type.toChars());
			//printf("\te : %s, %s\n", e.toChars(), e.type.toChars());
			if (!ei.equals(e))
				goto Lnomatch;
		}
		else if (dedtypes[i])
		{   // Must match already deduced value
			auto e = cast(Expression)dedtypes[i];

			if (!ei || !ei.equals(e))
				goto Lnomatch;
		}
	Lmatch:
		//printf("\tvalType: %s, ty = %d\n", valType.toChars(), valType.ty);
		vt = valType.semantic(Loc(0), sc);
		//printf("ei: %s, ei.type: %s\n", ei.toChars(), ei.type.toChars());
		//printf("vt = %s\n", vt.toChars());
		if (ei.type)
		{
			m = cast(MATCH)ei.implicitConvTo(vt);
			//printf("m: %d\n", m);
			if (!m)
				goto Lnomatch;
		}
		dedtypes[i] = ei;

		init = new ExpInitializer(loc, ei);
		sparam = new VarDeclaration(loc, vt, ident, init);
		sparam.storage_class = STCmanifest;
		*psparam = sparam;
		return m;

	Lnomatch:
		//printf("\tno match\n");
		*psparam = null;
		return MATCHnomatch;
	}

    override Object dummyArg()
	{
		if (!specValue)
		{
			return global.edummy;
		}

		return specValue;
	}
}