view dmd/TypeAArray.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 2cc604139636
line wrap: on
line source

module dmd.TypeAArray;

import dmd.TypeArray;
import dmd.MOD;
import dmd.ArrayTypes;
import dmd.TypeInfoDeclaration;
import dmd.Expression;
import dmd.Scope;
import dmd.Loc;
import dmd.Dsymbol;
import dmd.Type;
import dmd.TypeSArray;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.Identifier;
import dmd.MATCH;
import dmd.TY;
import dmd.Id;
import dmd.CallExp;
import dmd.IntegerExp;
import dmd.FuncDeclaration;
import dmd.VarExp;
import dmd.TypeFunction;
import dmd.NullExp;
import dmd.Array;

import dmd.backend.Symbol;
import dmd.backend.TYPE;
import dmd.backend.Util;
import dmd.backend.SC;
import dmd.backend.LIST;
import dmd.backend.TYM;
import dmd.backend.TF;
import dmd.backend.mTYman;

import core.stdc.stdio;
import core.stdc.stdlib;

class TypeAArray : TypeArray
{
    Type index;		// key type

    this(Type t, Type index)
	{
		super(Taarray, t);
		this.index = index;
	}
	
    Type syntaxCopy()
	{
		assert(false);
	}

version (DumbClone) {
} else {
	Type clone()
	{
		assert(false);
	}
}
    ulong size(Loc loc)
	{
		return PTRSIZE /* * 2*/;
	}
	
    Type semantic(Loc loc, Scope sc)
	{
		//printf("TypeAArray::semantic() %s index.ty = %d\n", toChars(), index.ty);

		// Deal with the case where we thought the index was a type, but
		// in reality it was an expression.
		if (index.ty == Tident || index.ty == Tinstance || index.ty == Tsarray)
		{
			Expression e;
			Type t;
			Dsymbol s;

			index.resolve(loc, sc, &e, &t, &s);
			if (e)
			{   // It was an expression -
				// Rewrite as a static array
				TypeSArray tsa = new TypeSArray(next, e);
				return tsa.semantic(loc,sc);
			}
			else if (t)
				index = t;
			else
				index.error(loc, "index is not a type or an expression");
		}
		else
			index = index.semantic(loc,sc);

		if (index.nextOf() && !index.nextOf().isInvariant())
		{
			index = index.constOf().mutableOf();
static if (false) {
			printf("index is %p %s\n", index, index.toChars());
			index.check();
			printf("index.mod = x%x\n", index.mod);
			printf("index.ito = x%x\n", index.ito);
			if (index.ito) {
				printf("index.ito.mod = x%x\n", index.ito.mod);
				printf("index.ito.ito = x%x\n", index.ito.ito);
			}
}
		}

		switch (index.toBasetype().ty)
		{
			case Tbool:
			case Tfunction:
			case Tvoid:
			case Tnone:
				error(loc, "can't have associative array key of %s", index.toBasetype().toChars());
				break;
			default:
				break;	///
		}
		next = next.semantic(loc,sc);
		transitive();

		switch (next.toBasetype().ty)
		{
			case Tfunction:
			case Tnone:
				error(loc, "can't have associative array of %s", next.toChars());
				break;
			default:
				break;	///
		}
		if (next.isauto())
			error(loc, "cannot have array of auto %s", next.toChars());

		return merge();
	}
	
    void resolve(Loc loc, Scope sc, Expression* pe, Type* pt, Dsymbol* ps)
	{
		assert(false);
	}
	
    void toDecoBuffer(OutBuffer buf, int flag)
	{
		Type.toDecoBuffer(buf, flag);
		index.toDecoBuffer(buf);
		next.toDecoBuffer(buf, (flag & 0x100) ? MOD.MODundefined : mod);
	}
	
    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
	{
		assert(false);
	}
	
    Expression dotExp(Scope sc, Expression e, Identifier ident)
	{
	version (LOGDOTEXP) {
		printf("TypeAArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
	}
		if (ident == Id.length)
		{
			Expression ec;
			FuncDeclaration fd;
			Expressions arguments;

			fd = FuncDeclaration.genCfunc(Type.tsize_t, Id.aaLen);
			ec = new VarExp(Loc(0), fd);
			arguments = new Expressions();
			arguments.push(cast(void*)e);
			e = new CallExp(e.loc, ec, arguments);
			e.type = (cast(TypeFunction)fd.type).next;
		}
		else if (ident == Id.keys)
		{
			Expression ec;
			FuncDeclaration fd;
			Expressions arguments;
			int size = cast(int)index.size(e.loc);

			assert(size);
			fd = FuncDeclaration.genCfunc(Type.tindex, Id.aaKeys);
			ec = new VarExp(Loc(0), fd);
			arguments = new Expressions();
			arguments.push(cast(void*)e);
			arguments.push(cast(void*)new IntegerExp(Loc(0), size, Type.tsize_t));
			e = new CallExp(e.loc, ec, arguments);
			e.type = index.arrayOf();
		}
		else if (ident == Id.values)
		{
			Expression ec;
			FuncDeclaration fd;
			Expressions arguments;

			fd = FuncDeclaration.genCfunc(Type.tindex, Id.aaValues);
			ec = new VarExp(Loc(0), fd);
			arguments = new Expressions();
			arguments.push(cast(void*)e);
			size_t keysize = cast(size_t)index.size(e.loc);
			keysize = (keysize + PTRSIZE - 1) & ~(PTRSIZE - 1);
			arguments.push(cast(void*)new IntegerExp(Loc(0), keysize, Type.tsize_t));
			arguments.push(cast(void*)new IntegerExp(Loc(0), next.size(e.loc), Type.tsize_t));
			e = new CallExp(e.loc, ec, arguments);
			e.type = next.arrayOf();
		}
		else if (ident == Id.rehash)
		{
			Expression ec;
			FuncDeclaration fd;
			Expressions arguments;

			fd = FuncDeclaration.genCfunc(Type.tint64, Id.aaRehash);
			ec = new VarExp(Loc(0), fd);
			arguments = new Expressions();
			arguments.push(cast(void*)e.addressOf(sc));
			arguments.push(cast(void*)index.getInternalTypeInfo(sc));
			e = new CallExp(e.loc, ec, arguments);
			e.type = this;
		}
		else
		{
			e = Type.dotExp(sc, e, ident);
		}
		return e;
	}
	
    Expression defaultInit(Loc loc)
	{
	version (LOGDEFAULTINIT) {
		printf("TypeAArray.defaultInit() '%s'\n", toChars());
	}
		Expression e = new NullExp(loc);
		e.type = this;
		return e;
	}
	
    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
	{
		assert(false);
	}
	
    bool isZeroInit(Loc loc)
	{
		assert(false);
	}
	
    bool checkBoolean()
	{
		assert(false);
	}
	
    TypeInfoDeclaration getTypeInfoDeclaration()
	{
		assert(false);
	}
	
    bool hasPointers()
	{
		return true;
	}
	
    MATCH implicitConvTo(Type to)
	{
		assert(false);
	}
	
    MATCH constConv(Type to)
	{
		assert(false);
	}
	
version (CPP_MANGLE) {
    void toCppMangle(OutBuffer buf, CppMangleState* cms)
	{
		assert(false);
	}
}

    // Back end
	/********************************************
	 * Determine the right symbol to look up
	 * an associative array element.
	 * Input:
	 *	flags	0	don't add value signature
	 *		1	add value signature
	 */
    Symbol* aaGetSymbol(const(char)* func, int flags)
    in
    {
		assert(func);
		assert((flags & ~1) == 0);
    }
    out (result)
    {
		assert(result);
    }
    body
    {
		int sz;
		char* id;
		type* t;
		Symbol* s;
		int i;

		// Dumb linear symbol table - should use associative array!
		static Array sarray = null;

		//printf("aaGetSymbol(func = '%s', flags = %d, key = %p)\n", func, flags, key);
	static if (false) {
		scope OutBuffer buf = new OutBuffer();
		key.toKeyBuffer(buf);

		sz = next.size();		// it's just data, so we only care about the size
		sz = (sz + 3) & ~3;		// reduce proliferation of library routines
		id = cast(char*)alloca(3 + strlen(func) + buf.offset + sizeof(sz) * 3 + 1);
		buf.writeByte(0);
		if (flags & 1)
			sprintf(id, "_aa%s%s%d", func, buf.data, sz);
		else
			sprintf(id, "_aa%s%s", func, buf.data);
	} else {
		id = cast(char*)alloca(3 + strlen(func) + 1);
		sprintf(id, "_aa%s", func);
	}
		if (!sarray)
			sarray = new Array();

		// See if symbol is already in sarray
		for (i = 0; i < sarray.dim; i++)
		{   
			s = cast(Symbol*)sarray.data[i];
			if (strcmp(id, s.Sident.ptr) == 0)
				return s;			// use existing Symbol
		}

		// Create new Symbol

		s = symbol_calloc(id);
		slist_add(s);
		s.Sclass = SCextern;
		s.Ssymnum = -1;
		symbol_func(s);

		t = type_alloc(TYnfunc);
		t.Tflags = TFprototype | TFfixed;
		t.Tmangle = mTYman_c;
		t.Tparamtypes = null;
		t.Tnext = next.toCtype();
		t.Tnext.Tcount++;
		t.Tcount++;
		s.Stype = t;

		sarray.push(s);			// remember it
		return s;
    }

    type* toCtype()
	{
		assert(false);
	}
}