Mercurial > projects > ddmd
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