diff dmd/TypeSArray.d @ 0:10317f0c89a5

Initial commit
author korDen
date Sat, 24 Oct 2009 08:42:06 +0400
parents
children 832f71e6f96c
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dmd/TypeSArray.d	Sat Oct 24 08:42:06 2009 +0400
@@ -0,0 +1,455 @@
+module dmd.TypeSArray;
+
+import dmd.TypeArray;
+import dmd.MOD;
+import dmd.Argument;
+import dmd.TypeStruct;
+import dmd.TypeTuple;
+import dmd.VarExp;
+import dmd.IntegerExp;
+import dmd.Expression;
+import dmd.Type;
+import dmd.TupleDeclaration;
+import dmd.TOK;
+import dmd.Loc;
+import dmd.STC;
+import dmd.Scope;
+import dmd.Dsymbol;
+import dmd.OutBuffer;
+import dmd.HdrGenState;
+import dmd.Identifier;
+import dmd.MATCH;
+import dmd.TypeDArray;
+import dmd.TypePointer;
+import dmd.ArrayTypes;
+import dmd.WANT;
+import dmd.TypeInfoDeclaration;
+import dmd.TY;
+import dmd.Util;
+import dmd.Id;
+
+import dmd.type.Util;
+
+import dmd.backend.dt_t;
+import dmd.backend.TYPE;
+import dmd.backend.Util;
+import dmd.backend.TYM;
+import dmd.backend.DT;
+
+// Static array, one with a fixed dimension
+class TypeSArray : TypeArray
+{
+    Expression dim;
+
+    this(Type t, Expression dim)
+	{
+		super(TY.Tsarray, t);
+		//printf("TypeSArray(%s)\n", dim.toChars());
+		this.dim = dim;
+	}
+	
+version (DumbClone) {
+} else {
+	Type clone()
+	{
+		assert(false);
+	}
+}
+
+    Type syntaxCopy()
+	{
+		assert(false);
+	}
+
+    ulong size(Loc loc)
+	{
+		if (!dim)
+			return Type.size(loc);
+
+		long sz = dim.toInteger();
+
+		{	
+			long n, n2;
+			n = next.size();
+			n2 = n * sz;
+			if (n && (n2 / n) != sz)
+				goto Loverflow;
+
+			sz = n2;
+		}
+		return sz;
+
+	Loverflow:
+		error(loc, "index %jd overflow for static array", sz);
+		return 1;
+	}
+	
+    uint alignsize()
+	{
+		return next.alignsize();
+	}
+
+    Type semantic(Loc loc, Scope sc)
+	{
+		//printf("TypeSArray.semantic() %s\n", toChars());
+
+		Type t;
+		Expression e;
+		Dsymbol s;
+		next.resolve(loc, sc, &e, &t, &s);
+		if (dim && s && s.isTupleDeclaration())
+		{	
+			TupleDeclaration sd = s.isTupleDeclaration();
+
+			dim = semanticLength(sc, sd, dim);
+			dim = dim.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+			ulong d = dim.toUInteger();
+
+			if (d >= sd.objects.dim)
+			{   error(loc, "tuple index %ju exceeds %u", d, sd.objects.dim);
+				return Type.terror;
+			}
+			///Object o = cast(Object)sd.objects.data[(size_t)d];
+			///if (o.dyncast() != DYNCAST_TYPE)
+			///{   
+			///	error(loc, "%s is not a type", toChars());
+			///	return Type.terror;
+			///}
+			///t = cast(Type)o;
+			
+			t = cast(Type)sd.objects.data[cast(size_t)d];
+			if (t is null) {
+				error(loc, "%s is not a type", toChars());
+				return Type.terror;
+			}
+			return t;
+		}
+
+		next = next.semantic(loc,sc);
+		transitive();
+
+		Type tbn = next.toBasetype();
+
+		if (dim)
+		{	
+			long n, n2;
+
+		dim = semanticLength(sc, tbn, dim);
+
+		dim = dim.optimize(WANT.WANTvalue | WANT.WANTinterpret);
+		if (sc && sc.parameterSpecialization && dim.op == TOK.TOKvar &&
+			(cast(VarExp)dim).var.storage_class & STC.STCtemplateparameter)
+		{
+			/* It could be a template parameter N which has no value yet:
+			 *   template Foo(T : T[N], size_t N);
+			 */
+			return this;
+		}
+		long d1 = dim.toInteger();
+		dim = dim.castTo(sc, tsize_t);
+		dim = dim.optimize(WANT.WANTvalue);
+		long d2 = dim.toInteger();
+
+		if (d1 != d2)
+			goto Loverflow;
+
+		if (tbn.isintegral() ||
+			 tbn.isfloating() ||
+			 tbn.ty == TY.Tpointer ||
+			 tbn.ty == TY.Tarray ||
+			 tbn.ty == TY.Tsarray ||
+			 tbn.ty == TY.Taarray ||
+			 tbn.ty == TY.Tclass)
+		{
+			/* Only do this for types that don't need to have semantic()
+			 * run on them for the size, since they may be forward referenced.
+			 */
+			n = tbn.size(loc);
+			n2 = n * d2;
+			if (cast(int)n2 < 0)
+			goto Loverflow;
+			if (n2 >= 0x1000000)	// put a 'reasonable' limit on it
+			goto Loverflow;
+			if (n && n2 / n != d2)
+			{
+			  Loverflow:
+			error(loc, "index %jd overflow for static array", d1);
+			dim = new IntegerExp(Loc(0), 1, tsize_t);
+			}
+		}
+		}
+		switch (tbn.ty)
+		{
+			case TY.Ttuple:
+			{   // Index the tuple to get the type
+				assert(dim);
+				TypeTuple tt = cast(TypeTuple)tbn;
+				ulong d = dim.toUInteger();
+
+				if (d >= tt.arguments.dim)
+				{	
+					error(loc, "tuple index %ju exceeds %u", d, tt.arguments.dim);
+					return Type.terror;
+				}
+				Argument arg = cast(Argument)tt.arguments.data[cast(size_t)d];
+				return arg.type;
+			}
+			case TY.Tstruct:
+			{   TypeStruct ts = cast(TypeStruct)tbn;
+				if (ts.sym.isnested)
+				error(loc, "cannot have array of inner structs %s", ts.toChars());
+				break;
+			}
+			case TY.Tfunction:
+			case TY.Tnone:
+				error(loc, "can't have array of %s", tbn.toChars());
+				tbn = next = tint32;
+				break;
+			default:		///
+				break;
+		}
+		if (tbn.isauto())
+			error(loc, "cannot have array of auto %s", tbn.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);
+		if (dim)
+			//buf.printf("%ju", dim.toInteger());	///
+			buf.printf("%s", dim.toInteger());
+		if (next)
+			/* Note that static arrays are value types, so
+			 * for a parameter, propagate the 0x100 to the next
+			 * level, since for T[4][3], any const should apply to the T,
+			 * not the [4].
+			 */
+			next.toDecoBuffer(buf,  (flag & 0x100) ? flag : mod);
+	}
+	
+    void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
+	{
+		assert(false);
+	}
+	
+    Expression dotExp(Scope sc, Expression e, Identifier ident)
+	{
+	version (LOGDOTEXP) {
+		printf("TypeSArray.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars());
+	}
+		if (ident == Id.length)
+		{
+			e = dim;
+		}
+		else if (ident == Id.ptr)
+		{
+			e = e.castTo(sc, next.pointerTo());
+		}
+		else
+		{
+			e = TypeArray.dotExp(sc, e, ident);
+		}
+		return e;
+	}
+	
+    int isString()
+	{
+		assert(false);
+	}
+	
+    bool isZeroInit(Loc loc)
+	{
+		return next.isZeroInit(loc);
+	}
+	
+    uint memalign(uint salign)
+	{
+		return next.memalign(salign);
+	}
+	
+    MATCH constConv(Type to)
+	{
+		assert(false);
+	}
+	
+    MATCH implicitConvTo(Type to)
+	{
+		//printf("TypeSArray.implicitConvTo(to = %s) this = %s\n", to.toChars(), toChars());
+
+		// Allow implicit conversion of static array to pointer or dynamic array
+		if (IMPLICIT_ARRAY_TO_PTR && to.ty == Tpointer)
+		{
+			TypePointer tp = cast(TypePointer)to;
+
+			if (next.mod != tp.next.mod && tp.next.mod != MODconst)
+				return MATCHnomatch;
+
+			if (tp.next.ty == Tvoid || next.constConv(tp.next) != MATCHnomatch)
+			{
+				return MATCHconvert;
+			}
+			return MATCHnomatch;
+		}
+		if (to.ty == Tarray)
+		{
+			int offset = 0;
+			TypeDArray ta = cast(TypeDArray)to;
+
+			if (next.mod != ta.next.mod && ta.next.mod != MODconst)
+				return MATCHnomatch;
+
+			if (next.equals(ta.next) ||
+				next.implicitConvTo(ta.next) >= MATCHconst ||
+				(ta.next.isBaseOf(next, &offset) && offset == 0) ||
+				ta.next.ty == Tvoid
+			)
+				return MATCHconvert;
+
+			return MATCHnomatch;
+		}
+		if (to.ty == Tsarray)
+		{
+			if (this == to)
+				return MATCHexact;
+
+			TypeSArray tsa = cast(TypeSArray)to;
+
+			if (dim.equals(tsa.dim))
+			{
+				/* Since static arrays are value types, allow
+				 * conversions from const elements to non-const
+				 * ones, just like we allow conversion from const int
+				 * to int.
+				 */
+				MATCH m = next.implicitConvTo(tsa.next);
+				if (m >= MATCHconst)
+				{
+					if (mod != to.mod)
+						m = MATCHconst;
+					return m;
+				}
+			}
+		}
+		return MATCHnomatch;
+	}
+	
+    Expression defaultInit(Loc loc)
+	{
+	version (LOGDEFAULTINIT) {
+		printf("TypeSArray.defaultInit() '%s'\n", toChars());
+	}
+		return next.defaultInit(loc);
+	}
+	
+    dt_t** toDt(dt_t** pdt)
+	{
+		return toDtElem(pdt, null);
+	}
+	
+    dt_t** toDtElem(dt_t** pdt, Expression e)
+	{
+		int i;
+
+		//printf("TypeSArray::toDtElem()\n");
+		uint len = cast(uint)dim.toInteger();
+		if (len)
+		{
+			while (*pdt)
+				pdt = &((*pdt).DTnext);
+			Type tnext = next;
+			Type tbn = tnext.toBasetype();
+			while (tbn.ty == Tsarray)
+			{   
+				TypeSArray tsa = cast(TypeSArray)tbn;
+
+				len *= tsa.dim.toInteger();
+				tnext = tbn.nextOf();
+				tbn = tnext.toBasetype();
+			}
+			if (!e)				// if not already supplied
+				e = tnext.defaultInit(Loc(0));	// use default initializer
+			if (tbn.ty == Tstruct)
+				tnext.toDt(pdt);
+			else
+				e.toDt(pdt);
+			dt_optimize(*pdt);
+			if ((*pdt).dt == DT_azeros && !(*pdt).DTnext)
+			{
+				(*pdt).DTazeros *= len;
+				pdt = &((*pdt).DTnext);
+			}
+			else if ((*pdt).dt == DT_1byte && (*pdt).DTonebyte == 0 && !(*pdt).DTnext)
+			{
+				(*pdt).dt = DT_azeros;
+				(*pdt).DTazeros = len;
+				pdt = &((*pdt).DTnext);
+			}
+			else if (e.op != TOKstring)
+			{
+				for (i = 1; i < len; i++)
+				{
+					if (tbn.ty == Tstruct)
+					{   
+						pdt = tnext.toDt(pdt);
+						while (*pdt)
+							pdt = &((*pdt).DTnext);
+					}
+					else
+						pdt = e.toDt(pdt);
+				}
+			}
+		}
+		return pdt;
+	}
+	
+    MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes)
+	{
+		assert(false);
+	}
+	
+    TypeInfoDeclaration getTypeInfoDeclaration()
+	{
+		assert(false);
+	}
+	
+    Expression toExpression()
+	{
+		assert(false);
+	}
+	
+    bool hasPointers()
+	{
+		return next.hasPointers();
+	}
+	
+version (CPP_MANGLE) {
+    void toCppMangle(OutBuffer buf, CppMangleState* cms)
+	{
+		assert(false);
+	}
+}
+
+    type* toCtype()
+	{
+		if (!ctype)
+		{
+			type* tn = next.toCtype();
+			ctype = type_allocn(TYarray, tn);
+			ctype.Tdim = cast(uint)dim.toInteger();
+		}
+
+		return ctype;
+	}
+	
+    type* toCParamtype()
+	{
+		// arrays are passed as pointers
+		return next.pointerTo().toCtype();
+	}
+}
\ No newline at end of file