view dmd/TypeDArray.d @ 135:af1bebfd96a4 dmd2037

dmd 2.038
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Mon, 13 Sep 2010 22:19:42 +0100
parents e28b18c23469
children fa9a71a9f5a8
line wrap: on
line source

module dmd.TypeDArray;

import dmd.common;
import dmd.TypeArray;
import dmd.MOD;
import dmd.Id;
import dmd.TOK;
import dmd.StringExp;
import dmd.IntegerExp;
import dmd.ArrayLengthExp;
import dmd.Type;
import dmd.Loc;
import dmd.Scope;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.Expression;
import dmd.Identifier;
import dmd.MATCH;
import dmd.ArrayTypes;
import dmd.TypeInfoDeclaration;
import dmd.TypeInfoArrayDeclaration;
import dmd.NullExp;
import dmd.TY;
import dmd.TypeStruct;
import dmd.Util;
import dmd.TypePointer;
import dmd.Global;

import dmd.backend.TYPE;
import dmd.backend.Symbol;
import dmd.backend.Classsym;
import dmd.backend.Util;
import dmd.backend.SC;
import dmd.backend.TYM;
import dmd.backend.LIST;

import core.stdc.stdlib;
import core.stdc.stdio;
version (Bug4054) import core.memory;

// Dynamic array, no dimension
class TypeDArray : TypeArray
{
    this(Type t)
	{
		super(TY.Tarray, t);
		//printf("TypeDArray(t = %p)\n", t);
	}
	
version (DumbClone) {
} else {
	Type clone()
	{
		assert(false);
	}
}
    override Type syntaxCopy()
	{
		Type t = next.syntaxCopy();
		if (t == next)
			t = this;
		else
		{	
			t = new TypeDArray(t);
			t.mod = mod;
		}
		return t;
	}
	
    override ulong size(Loc loc)
	{
		//printf("TypeDArray.size()\n");
		return PTRSIZE * 2;
	}
	
    override uint alignsize()
	{
		// A DArray consists of two ptr-sized values, so align it on pointer size
		// boundary
		return PTRSIZE;
	}
	
    override Type semantic(Loc loc, Scope sc)
	{
		Type tn = next;

		tn = next.semantic(loc,sc);
		Type tbn = tn.toBasetype();
		switch (tbn.ty)
		{
			case TY.Tfunction:
			case TY.Tnone:
			case TY.Ttuple:
				error(loc, "can't have array of %s", tbn.toChars());
				tn = next = tint32;
				break;
			case TY.Tstruct:
			{   
				TypeStruct ts = cast(TypeStruct)tbn;
				if (ts.sym.isnested)
					error(loc, "cannot have array of inner structs %s", ts.toChars());
				break;
			}
			
			default:
				break;	///
		}
		if (tn.isauto())
			error(loc, "cannot have array of auto %s", tn.toChars());

		next = tn;
		transitive();
		return merge();
	}
	
    override void toDecoBuffer(OutBuffer buf, int flag)
	{
		Type.toDecoBuffer(buf, flag);
		if (next)
			next.toDecoBuffer(buf, (flag & 0x100) ? 0 : mod);
	}
	
	override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
	{
		if (mod != this.mod)
		{
			toCBuffer3(buf, hgs, mod);
			return;
		}
		if (equals(tstring))
			buf.writestring("string");
		else
		{
			next.toCBuffer2(buf, hgs, this.mod);
			buf.writestring("[]");
		}
	}
	
    override Expression dotExp(Scope sc, Expression e, Identifier ident)
	{
version (LOGDOTEXP) {
		printf("TypeDArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
}
		if (ident is Id.length)
		{
			if (e.op == TOK.TOKstring)
			{   
				StringExp se = cast(StringExp)e;

				return new IntegerExp(se.loc, se.len, Type.tindex);
			}
			e = new ArrayLengthExp(e.loc, e);
			e.type = Type.tsize_t;
			return e;
		}
		else if (ident is Id.ptr)
		{
			e = e.castTo(sc, next.pointerTo());
			return e;
		}
		else
		{
			e = TypeArray.dotExp(sc, e, ident);
		}
		return e;
	}
	
    override bool isString()
	{
		TY nty = next.toBasetype().ty;
		return nty == Tchar || nty == Twchar || nty == Tdchar;
	}
	
    override bool isZeroInit(Loc loc)
	{
		return true;
	}
	
    override bool checkBoolean()
	{
		return true;
	}
	
    override MATCH implicitConvTo(Type to)
	{
		//printf("TypeDArray.implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
		if (equals(to))
			return MATCHexact;

		// Allow implicit conversion of array to pointer
		if (IMPLICIT_ARRAY_TO_PTR && to.ty == Tpointer)
		{
			TypePointer tp = cast(TypePointer)to;

			/* Allow conversion to void*
			 */
			if (tp.next.ty == Tvoid &&
				MODimplicitConv(next.mod, tp.next.mod))
			{
				return MATCHconvert;
			}

			return next.constConv(to);
		}

		if (to.ty == Tarray)
		{	
			int offset = 0;
			TypeDArray ta = cast(TypeDArray)to;

			if (!MODimplicitConv(next.mod, ta.next.mod))
				return MATCHnomatch;	// not const-compatible

			/* Allow conversion to void[]
			 */
			if (next.ty != Tvoid && ta.next.ty == Tvoid)
			{
				return MATCHconvert;
			}

			MATCH m = next.constConv(ta.next);
			if (m != MATCHnomatch)
			{
				if (m == MATCHexact && mod != to.mod)
				m = MATCHconst;
				return m;
			}

static if(false) {
			/* Allow conversions of T[][] to const(T)[][]
			 */
			if (mod == ta.mod && next.ty == Tarray && ta.next.ty == Tarray)
			{
				m = next.implicitConvTo(ta.next);
				if (m == MATCHconst)
				return m;
			}
}
			/* Conversion of array of derived to array of base
			 */
			if (ta.next.isBaseOf(next, &offset) && offset == 0)
				return MATCHconvert;
		}
		return Type.implicitConvTo(to);
	}
	
    override Expression defaultInit(Loc loc)
	{
	version (LOGDEFAULTINIT) {
		printf("TypeDArray.defaultInit() '%s'\n", toChars());
	}
		return new NullExp(loc, this);
	}
	
    override bool builtinTypeInfo()
	{
	version (DMDV2) {
		return !mod && (next.isTypeBasic() !is null && !next.mod ||
			// strings are so common, make them builtin
			next.ty == Tchar && next.mod == MODimmutable);
	} else {
		return next.isTypeBasic() !is null;
	}
	}
version (DMDV2) {
    override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
	{
	static if (false) {
		printf("TypeDArray.deduceType()\n");
		printf("\tthis   = %d, ", ty); print();
		printf("\ttparam = %d, ", tparam.ty); tparam.print();
	}
		return Type.deduceType(sc, tparam, parameters, dedtypes);

	  Lnomatch:
		return MATCHnomatch;
	}
}
    override TypeInfoDeclaration getTypeInfoDeclaration()
	{
		return new TypeInfoArrayDeclaration(this);
	}

    override bool hasPointers()
	{
		return true;
	}

version (CPP_MANGLE) {
    void toCppMangle(OutBuffer buf, CppMangleState* cms);
}

    override type* toCtype()
	{
		type *t;

		if (ctype)
			return ctype;

		if (0 && global.params.symdebug)
		{
			/* Create a C type out of:
			 *	struct _Array_T { size_t length; T* data; }
			 */
			Symbol* s;
			char *id;

			assert(next.deco);
			version (Bug4054)
			id = cast(char*) GC.malloc(7 + next.deco.length + 1);
			else
			id = cast(char*) alloca(7 + next.deco.length + 1);
			sprintf(id, "_Array_%.*s", next.deco);
			s = symbol_calloc(id);
			s.Sclass = SC.SCstruct;
			s.Sstruct = struct_calloc();
			s.Sstruct.Sflags |= 0;
			s.Sstruct.Salignsize = alignsize();
			s.Sstruct.Sstructalign = cast(ubyte)global.structalign;
			s.Sstruct.Sstructsize = cast(uint)size(Loc(0));
			slist_add(s);

			Symbol* s1 = symbol_name("length", SC.SCmember, Type.tsize_t.toCtype());
			list_append(&s.Sstruct.Sfldlst, s1);

			Symbol* s2 = symbol_name("data", SC.SCmember, next.pointerTo().toCtype());
			s2.Smemoff = cast(uint)Type.tsize_t.size();
			list_append(&s.Sstruct.Sfldlst, s2);

			t = type_alloc(TYM.TYstruct);
			t.Ttag = cast(Classsym*)s;		// structure tag name
			t.Tcount++;
			s.Stype = t;
		}
		else
		{
			if (global.params.symdebug == 1)
			{
				// Generate D symbolic debug info, rather than C
				t = type_allocn(TYM.TYdarray, next.toCtype());
			}
			else
				t = type_fake(TYM.TYdarray);
		}
		t.Tcount++;
		ctype = t;
		return t;
	}
}