Mercurial > projects > ddmd
diff dmd/ArrayInitializer.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | 51605de93870 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/ArrayInitializer.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,373 @@ +module dmd.ArrayInitializer; + +import dmd.ArrayTypes; +import dmd.Type; +import dmd.TypeNext; +import dmd.Array; +import dmd.Loc; +import dmd.Initializer; +import dmd.WANT; +import dmd.Util; +import dmd.TY; +import dmd.TypeSArray; +import dmd.IntegerExp; +import dmd.Expression; +import dmd.ArrayLiteralExp; +import dmd.Scope; +import dmd.ErrorExp; +import dmd.OutBuffer; +import dmd.HdrGenState; + +import dmd.backend.dt_t; +import dmd.backend.Util; +import dmd.codegen.Util; +import dmd.backend.TYM; +import dmd.backend.Symbol; + +class ArrayInitializer : Initializer +{ + Expressions index; // indices + Initializers value; // of Initializer *'s + uint dim = 0; // length of array being initialized + Type type = null; // type that array will be used to initialize + int sem = 0; // !=0 if semantic() is run + + this(Loc loc) + { + super(loc); + index = new Expressions(); + value = new Initializers(); + } + + Initializer syntaxCopy() + { + //printf("ArrayInitializer.syntaxCopy()\n"); + + ArrayInitializer ai = new ArrayInitializer(loc); + + assert(index.dim == value.dim); + ai.index.setDim(index.dim); + ai.value.setDim(value.dim); + for (int i = 0; i < ai.value.dim; i++) + { + Expression e = cast(Expression)index.data[i]; + if (e) + e = e.syntaxCopy(); + ai.index.data[i] = cast(void*)e; + + Initializer init = cast(Initializer)value.data[i]; + init = init.syntaxCopy(); + ai.value.data[i] = cast(void*)init; + } + return ai; + } + + void addInit(Expression index, Initializer value) + { + this.index.push(cast(void*)index); + this.value.push(cast(void*)value); + dim = 0; + type = null; + } + + Initializer semantic(Scope sc, Type t) + { + uint i; + uint length; + + //printf("ArrayInitializer.semantic(%s)\n", t.toChars()); + if (sem) // if semantic() already run + return this; + + sem = 1; + type = t; + t = t.toBasetype(); + switch (t.ty) + { + case Tpointer: + case Tsarray: + case Tarray: + break; + + default: + error(loc, "cannot use array to initialize %s", type.toChars()); + return this; + } + + length = 0; + for (i = 0; i < index.dim; i++) + { + Expression idx; + Initializer val; + + idx = cast(Expression)index.data[i]; + if (idx) + { + idx = idx.semantic(sc); + idx = idx.optimize(WANTvalue | WANTinterpret); + index.data[i] = cast(void*)idx; + length = cast(uint)idx.toInteger(); + } + + val = cast(Initializer)value.data[i]; + val = val.semantic(sc, t.nextOf()); + value.data[i] = cast(void*)val; + length++; + if (length == 0) + error(loc, "array dimension overflow"); + if (length > dim) + dim = length; + } + uint amax = 0x80000000; + if (cast(uint) (dim * t.nextOf().size()) >= amax) + error(loc, "array dimension %u exceeds max of %ju", dim, amax / t.nextOf().size()); + + return this; + } + + Type inferType(Scope sc) + { + //printf("ArrayInitializer.inferType() %s\n", toChars()); + type = Type.terror; + for (size_t i = 0; i < value.dim; i++) + { + if (index.data[i]) + goto Lno; + } + + for (size_t i = 0; i < value.dim; i++) + { + Initializer iz = cast(Initializer)value.data[i]; + if (iz) + { + Type t = iz.inferType(sc); + if (i == 0) + { + t = new TypeSArray(t, new IntegerExp(value.dim)); + t = t.semantic(loc, sc); + type = t; + } + } + } + return type; + + Lno: + error(loc, "cannot infer type from this array initializer"); + return Type.terror; + } + + /******************************** + * If possible, convert array initializer to array literal. + */ + Expression toExpression() + { + Expression e; + + //printf("ArrayInitializer.toExpression(), dim = %d\n", dim); + //static int i; if (++i == 2) halt(); + + size_t edim; + Type t = null; + if (type) + { + t = type.toBasetype(); + switch (t.ty) + { + case Tsarray: + edim = cast(uint)(cast(TypeSArray)t).dim.toInteger(); + break; + + case Tpointer: + case Tarray: + edim = dim; + break; + + default: + assert(0); + } + } + else + { + edim = value.dim; + for (size_t i = 0, j = 0; i < value.dim; i++, j++) + { + if (index.data[i]) + j = cast(uint)(cast(Expression)index.data[i]).toInteger(); + if (j >= edim) + edim = j + 1; + } + } + + Expressions elements = new Expressions(); + elements.setDim(edim); + for (size_t i = 0, j = 0; i < value.dim; i++, j++) + { + if (index.data[i]) + j = cast(uint)(cast(Expression)index.data[i]).toInteger(); + assert(j < edim); + Initializer iz = cast(Initializer)value.data[i]; + if (!iz) + goto Lno; + Expression ex = iz.toExpression(); + if (!ex) + { + goto Lno; + } + elements.data[j] = cast(void*)ex; + } + + /* Fill in any missing elements with the default initializer + */ + { + Expression init = null; + for (size_t i = 0; i < edim; i++) + { + if (!elements.data[i]) + { + if (!type) + goto Lno; + if (!init) + init = (cast(TypeNext)t).next.defaultInit(Loc(0)); + elements.data[i] = cast(void*)init; + } + } + + Expression e2 = new ArrayLiteralExp(loc, elements); + e2.type = type; + return e2; + } + + Lno: + delete elements; + error(loc, "array initializers as expressions are not allowed"); + return new ErrorExp(); + } + + Initializer toAssocArrayInitializer() + { + assert(false); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + assert(false); + } + + dt_t* toDt() + { + //printf("ArrayInitializer.toDt('%s')\n", toChars()); + Type tb = type.toBasetype(); + Type tn = tb.nextOf().toBasetype(); + + scope Array dts = new Array(); + uint size; + uint length; + uint i; + dt_t* dt; + dt_t* d; + dt_t** pdtend; + + //printf("\tdim = %d\n", dim); + dts.setDim(dim); + dts.zero(); + + size = cast(uint)tn.size(); + + length = 0; + for (i = 0; i < index.dim; i++) + { + Expression idx; + Initializer val; + + idx = cast(Expression)index.data[i]; + if (idx) + length = cast(uint)idx.toInteger(); + //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim); + + assert(length < dim); + val = cast(Initializer)value.data[i]; + dt = val.toDt(); + if (dts.data[length]) + error(loc, "duplicate initializations for index %d", length); + dts.data[length] = cast(void*)dt; + length++; + } + + Expression edefault = tb.nextOf().defaultInit(Loc(0)); + + uint n = 1; + for (Type tbn = tn; tbn.ty == Tsarray; tbn = tbn.nextOf().toBasetype()) + { + TypeSArray tsa = cast(TypeSArray)tbn; + n *= tsa.dim.toInteger(); + } + + d = null; + pdtend = &d; + for (i = 0; i < dim; i++) + { + dt = cast(dt_t*)dts.data[i]; + if (dt) + pdtend = dtcat(pdtend, dt); + else + { + for (int j = 0; j < n; j++) + pdtend = edefault.toDt(pdtend); + } + } + switch (tb.ty) + { + case Tsarray: + { + uint tadim; + TypeSArray ta = cast(TypeSArray)tb; + + tadim = cast(uint)ta.dim.toInteger(); + if (dim < tadim) + { + if (edefault.isBool(false)) + // pad out end of array + pdtend = dtnzeros(pdtend, size * (tadim - dim)); + else + { + for (i = dim; i < tadim; i++) + { + for (int j = 0; j < n; j++) + pdtend = edefault.toDt(pdtend); + } + } + } + else if (dim > tadim) + { + debug writef("1: "); + error(loc, "too many initializers, %d, for array[%d]", dim, tadim); + } + break; + } + + case Tpointer: + case Tarray: + // Create symbol, and then refer to it + Symbol* s = static_sym(); + s.Sdt = d; + outdata(s); + + d = null; + if (tb.ty == Tarray) + dtdword(&d, dim); + dtxoff(&d, s, 0, TYnptr); + break; + + default: + assert(0); + } + return d; + } + + dt_t* toDtBit() // for bit arrays + { + assert(false); + } + + ArrayInitializer isArrayInitializer() { return this; } +} \ No newline at end of file