view dmd/StructInitializer.d @ 51:b7d29f613539

StaticAssertStatement.syntaxCopy IfStatement.syntaxCopy CompoundDeclarationStatement.syntaxCopy VoidInitializer.syntaxCopy TypeAArray.syntaxCopy TypeTypeof.syntaxCopy TypeAArray.resolve TypeSArray.deduceType TypeAArray.deduceType TypeAArray.implicitConvTo TemplateDeclaration.leastAsSpecialized TemplateTypeParameter.dummyArg TypeIdentifier.deduceType TemplateTypeParameter.syntaxCopy Lexer.hexStringConstant Lexer.delimitedStringConstant GotoDefaultStatement.ctor CaseRangeStatement.ctor Type.castMod StorageClassDeclaration.syntaxCopy TemplateDeclaration.syntaxCopy
author korDen
date Sat, 21 Aug 2010 11:17:42 +0400
parents 7427ded8caf7
children 51605de93870
line wrap: on
line source

module dmd.StructInitializer;

import dmd.Initializer;
import dmd.TOK;
import dmd.FuncLiteralDeclaration;
import dmd.TypeFunction;
import dmd.ArrayTypes;
import dmd.Array;
import dmd.Loc;
import dmd.Type;
import dmd.Scope;
import dmd.Identifier;
import dmd.CompoundStatement;
import dmd.AggregateDeclaration;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.Expression;
import dmd.TypeStruct;
import dmd.TY;
import dmd.VarDeclaration;
import dmd.Dsymbol;
import dmd.Util;
import dmd.ExpInitializer;
import dmd.FuncExp;
import dmd.LINK;

import dmd.backend.dt_t;

class StructInitializer : Initializer
{
    Identifiers field;	// of Identifier *'s
    Initializers value;	// parallel array of Initializer *'s

    Array vars;		// parallel array of VarDeclaration *'s
    AggregateDeclaration ad;	// which aggregate this is for

    this(Loc loc)
	{
		super(loc);
		ad = null;
		
		field = new Identifiers();
		value = new Initializers();
		
		vars = new Array();
	}
	
    Initializer syntaxCopy()
	{
		StructInitializer ai = new StructInitializer(loc);

		assert(field.dim == value.dim);
		ai.field.setDim(field.dim);
		ai.value.setDim(value.dim);
		for (int i = 0; i < field.dim; i++)
		{    
			ai.field.data[i] = field.data[i];

			Initializer init = cast(Initializer)value.data[i];
			init = init.syntaxCopy();
			ai.value.data[i] = cast(void*)init;
		}

		return ai;
	}
	
    void addInit(Identifier field, Initializer value)
	{
		//printf("StructInitializer.addInit(field = %p, value = %p)\n", field, value);
		this.field.push(cast(void*)field);
		this.value.push(cast(void*)value);
	}
	
    Initializer semantic(Scope sc, Type t)
	{
		TypeStruct ts;
		int errors = 0;

		//printf("StructInitializer.semantic(t = %s) %s\n", t.toChars(), toChars());
		vars.setDim(field.dim);
		t = t.toBasetype();
		if (t.ty == Tstruct)
		{	
			uint i;
			uint fieldi = 0;

			ts = cast(TypeStruct)t;
			ad = ts.sym;
			for (i = 0; i < field.dim; i++)
			{
				Identifier id = cast(Identifier)field.data[i];
				Initializer val = cast(Initializer)value.data[i];
				Dsymbol s;
				VarDeclaration v;

				if (id is null)
				{
					if (fieldi >= ad.fields.dim)
					{   
						error(loc, "too many initializers for %s", ad.toChars());
						field.remove(i);
						i--;
						continue;
					}
					else
					{
						s = cast(Dsymbol)ad.fields.data[fieldi];
					}
				}
				else
				{
					//s = ad.symtab.lookup(id);
					s = ad.search(loc, id, 0);
					if (!s)
					{
						error(loc, "'%s' is not a member of '%s'", id.toChars(), t.toChars());
						continue;
					}

					// Find out which field index it is
					for (fieldi = 0; 1; fieldi++)
					{
						if (fieldi >= ad.fields.dim)
						{
							s.error("is not a per-instance initializable field");
							break;
						}
						if (s == cast(Dsymbol)ad.fields.data[fieldi])
							break;
					}
				}
				if (s && (v = s.isVarDeclaration()) !is null)
				{
					val = val.semantic(sc, v.type);
					value.data[i] = cast(void*)val;
					vars.data[i] = cast(void*)v;
				}
				else
				{
					error(loc, "%s is not a field of %s", id ? id.toChars() : s.toChars(), ad.toChars());
					errors = 1;
				}
				fieldi++;
			}
		}
		else if (t.ty == Tdelegate && value.dim == 0)
		{	
			/* Rewrite as empty delegate literal { }
			 */
			Arguments arguments = new Arguments;
			Type tf = new TypeFunction(arguments, null, 0, LINK.LINKd);
			FuncLiteralDeclaration fd = new FuncLiteralDeclaration(loc, Loc(0), tf, TOK.TOKdelegate, null);
			fd.fbody = new CompoundStatement(loc, new Statements());
			fd.endloc = loc;
			Expression e = new FuncExp(loc, fd);
			ExpInitializer ie = new ExpInitializer(loc, e);
			return ie.semantic(sc, t);
		}
		else
		{
			error(loc, "a struct is not a valid initializer for a %s", t.toChars());
			errors = 1;
		}
		if (errors)
		{
			field.setDim(0);
			value.setDim(0);
			vars.setDim(0);
		}
		return this;
	}
	
    Expression toExpression()
	{
		assert(false);
	}
	
    void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		assert(false);
	}

    dt_t* toDt()
	{
		assert(false);
	}

    StructInitializer isStructInitializer() { return this; }
}