view dmd/interpret/Util.d @ 74:7e0d548de9e6

Switch Arrays of Dsymbols to the new templated Vector type
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Sun, 29 Aug 2010 09:43:40 +0100
parents cab4c37afb89
children 43073c7c7769
line wrap: on
line source

module dmd.interpret.Util;

import dmd.StructDeclaration;
import dmd.Expression;
import dmd.InterState;
import dmd.ArrayTypes;
import dmd.GlobalExpressions;
import dmd.TOK;
import dmd.AssocArrayLiteralExp;
import dmd.IntegerExp;
import dmd.Type;
import dmd.Declaration;
import dmd.Loc;
import dmd.ArrayLiteralExp;
import dmd.TypeAArray;
import dmd.TypeSArray;
import dmd.STC;
import dmd.SymbolDeclaration;
import dmd.StructLiteralExp;
import dmd.VarDeclaration;
import dmd.Util;

Expression interpret_aaLen(InterState istate, Expressions arguments)
{
    if (!arguments || arguments.dim != 1)
		return null;
    Expression earg = cast(Expression)arguments.data[0];
    earg = earg.interpret(istate);
    if (earg is EXP_CANT_INTERPRET)
		return null;
    if (earg.op != TOKassocarrayliteral)
		return null;
    AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg;
    Expression e = new IntegerExp(aae.loc, aae.keys.dim, Type.tsize_t);
    return e;
}

Expression interpret_aaKeys(InterState istate, Expressions arguments)
{
version (LOG) {
    printf("interpret_aaKeys()\n");
}
    if (!arguments || arguments.dim != 2)
		return null;
    Expression earg = cast(Expression)arguments.data[0];
    earg = earg.interpret(istate);
    if (earg is EXP_CANT_INTERPRET)
		return null;
    if (earg.op != TOKassocarrayliteral)
		return null;
    AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg;
    Expression e = new ArrayLiteralExp(aae.loc, aae.keys);
    Type elemType = (cast(TypeAArray)aae.type).index;
    e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0));
    return e;
}

Expression interpret_aaValues(InterState istate, Expressions arguments)
{
    //printf("interpret_aaValues()\n");
    if (!arguments || arguments.dim != 3)
		return null;
    Expression earg = cast(Expression)arguments.data[0];
    earg = earg.interpret(istate);
    if (earg is EXP_CANT_INTERPRET)
		return null;
    if (earg.op != TOKassocarrayliteral)
		return null;
    AssocArrayLiteralExp aae = cast(AssocArrayLiteralExp)earg;
    Expression e = new ArrayLiteralExp(aae.loc, aae.values);
    Type elemType = (cast(TypeAArray)aae.type).next;
    e.type = new TypeSArray(elemType, new IntegerExp(arguments ? arguments.dim : 0));
    //printf("result is %s\n", e.toChars());
    return e;
}

Expression getVarExp(Loc loc, InterState istate, Declaration d)
{
    Expression e = EXP_CANT_INTERPRET;
    VarDeclaration v = d.isVarDeclaration();
    SymbolDeclaration s = d.isSymbolDeclaration();
    if (v)
    {
///version (DMDV2) {
		if ((v.isConst() || v.isInvariant() || v.storage_class & STCmanifest) && v.init && !v.value)
///} else {
///	if (v.isConst() && v.init)
///}
		{   
			e = v.init.toExpression();
			if (e && !e.type)
				e.type = v.type;
		}
		else
		{   
			e = v.value;
			if (v.isDataseg())
			{	
				error(loc, "static variable %s cannot be read at compile time", v.toChars());
				e = EXP_CANT_INTERPRET;
			}
			else if (!e)
				error(loc, "variable %s is used before initialization", v.toChars());
			else if (e !is EXP_CANT_INTERPRET)
				e = e.interpret(istate);
		}
		if (!e)
			e = EXP_CANT_INTERPRET;
    }
    else if (s)
    {
		if (s.dsym.toInitializer() == s.sym)
		{   
			Expressions exps = new Expressions();
			e = new StructLiteralExp(Loc(0), s.dsym, exps);
			e = e.semantic(null);
		}
    }
    return e;
}

/* Helper functions for BinExp.interpretAssignCommon
 */

/***************************************
 * Duplicate the elements array, then set field 'indexToChange' = newelem.
 */
Expressions changeOneElement(Expressions oldelems, size_t indexToChange, void* newelem)
{
    Expressions expsx = new Expressions();
    expsx.setDim(oldelems.dim);
    for (size_t j = 0; j < expsx.dim; j++)
    {
		if (j == indexToChange)
			expsx.data[j] = newelem;
		else
			expsx.data[j] = oldelems.data[j];
    }
    return expsx;
}

/***************************************
 * Returns oldelems[0..insertpoint] ~ newelems ~ oldelems[insertpoint..$]
 */
Expressions spliceElements(Expressions oldelems, Expressions newelems, size_t insertpoint)
{
    Expressions expsx = new Expressions();
    expsx.setDim(oldelems.dim);
    for (size_t j = 0; j < expsx.dim; j++)
    {
		if (j >= insertpoint && j < insertpoint + newelems.dim)
			expsx.data[j] = newelems.data[j - insertpoint];
		else
			expsx.data[j] = oldelems.data[j];
    }
    return expsx;
}

/******************************
 * Create an array literal consisting of 'elem' duplicated 'dim' times.
 */
ArrayLiteralExp createBlockDuplicatedArrayLiteral(Type type, Expression elem, size_t dim)
{
    Expressions elements = new Expressions();
    elements.setDim(dim);
    for (size_t i = 0; i < dim; i++) {
		elements.data[i] = cast(void*)elem;
	}
	
    ArrayLiteralExp ae = new ArrayLiteralExp(Loc(0), elements);
    ae.type = type;
    return ae;
}


/********************************
 * Necessary because defaultInit() for a struct is a VarExp, not a StructLiteralExp.
 */
StructLiteralExp createDefaultInitStructLiteral(Loc loc, StructDeclaration sym)
{
    Expressions structelems = new Expressions();
    structelems.setDim(sym.fields.dim);
    for (size_t j = 0; j < structelems.dim; j++)
    {
		structelems.data[j] = cast(void*)(cast(VarDeclaration)(sym.fields.data[j])).type.defaultInit(Loc(0));
    }
    StructLiteralExp structinit = new StructLiteralExp(loc, sym, structelems);
    // Why doesn't the StructLiteralExp constructor do this, when
    // sym.type != null ?
    structinit.type = sym.type;
    return structinit;
}

/********************************
 *  Add v to the istate list, unless it already exists there.
 */
void addVarToInterstate(InterState istate, VarDeclaration v)
{
    if (!v.isParameter())
    {
		for (size_t i = 0; 1; i++)
		{
			if (i == istate.vars.dim)
			{   
				istate.vars.push(v);
				//printf("\tadding %s to istate\n", v.toChars());
				break;
			}
			if (v == cast(VarDeclaration)istate.vars[i])
				break;
		}
    }
}