Mercurial > projects > ddmd
diff dmd/ArrayLiteralExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | cab4c37afb89 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/ArrayLiteralExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,363 @@ +module dmd.ArrayLiteralExp; + +import dmd.Expression; +import dmd.backend.elem; +import dmd.InterState; +import dmd.MATCH; +import dmd.Type; +import dmd.OutBuffer; +import dmd.Loc; +import dmd.WANT; +import dmd.Scope; +import dmd.InlineCostState; +import dmd.IRState; +import dmd.InlineDoState; +import dmd.HdrGenState; +import dmd.backend.dt_t; +import dmd.InlineScanState; +import dmd.ArrayTypes; +import dmd.TOK; +import dmd.IntegerExp; +import dmd.TypeSArray; +import dmd.TY; +import dmd.StringExp; + +import dmd.expression.Util; +import dmd.backend.Util; +import dmd.backend.RTLSYM; +import dmd.backend.OPER; +import dmd.backend.TYM; +import dmd.backend.mTY; + +class ArrayLiteralExp : Expression +{ + Expressions elements; + + this(Loc loc, Expressions elements) + { + super(loc, TOK.TOKarrayliteral, ArrayLiteralExp.sizeof); + this.elements = elements; + } + + this(Loc loc, Expression e) + { + super(loc, TOK.TOKarrayliteral, ArrayLiteralExp.sizeof); + elements = new Expressions(); + elements.push(cast(void*)e); + } + + Expression syntaxCopy() + { + return new ArrayLiteralExp(loc, arraySyntaxCopy(elements)); + } + + Expression semantic(Scope sc) + { + Expression e; + Type t0 = null; + + version (LOGSEMANTIC) { + printf("ArrayLiteralExp.semantic('%s')\n", toChars()); + } + if (type) + return this; + + // Run semantic() on each element + for (int i = 0; i < elements.dim; i++) + { + e = cast(Expression)elements.data[i]; + e = e.semantic(sc); + assert(e.type); + elements.data[i] = cast(void*)e; + } + + expandTuples(elements); + + for (int i = 0; i < elements.dim; i++) + { + e = cast(Expression)elements.data[i]; + + if (!e.type) + error("%s has no value", e.toChars()); + + e = resolveProperties(sc, e); + + ubyte committed = 1; + if (e.op == TOKstring) + committed = (cast(StringExp)e).committed; + + if (!t0) + { + t0 = e.type; + // Convert any static arrays to dynamic arrays + if (t0.ty == Tsarray) + { + t0 = (cast(TypeSArray)t0).next.arrayOf(); + e = e.implicitCastTo(sc, t0); + } + } + else + e = e.implicitCastTo(sc, t0); + + if (!committed && e.op == TOKstring) + { + StringExp se = cast(StringExp)e; + se.committed = 0; + } + elements.data[i] = cast(void*)e; + } + + if (!t0) + t0 = Type.tvoid; + type = new TypeSArray(t0, new IntegerExp(elements.dim)); + type = type.semantic(loc, sc); + return this; + } + + bool isBool(bool result) + { + size_t dim = elements ? elements.dim : 0; + return result ? (dim != 0) : (dim == 0); + } + + elem* toElem(IRState* irs) + { + elem* e; + size_t dim; + + //printf("ArrayLiteralExp.toElem() %s\n", toChars()); + if (elements) + { + scope Expressions args = new Expressions(); + dim = elements.dim; + args.setDim(dim + 1); // +1 for number of args parameter + e = el_long(TYint, dim); + args.data[dim] = cast(void*)e; + for (size_t i = 0; i < dim; i++) + { + Expression el = cast(Expression)elements.data[i]; + elem* ep = el.toElem(irs); + + if (tybasic(ep.Ety) == TYstruct || tybasic(ep.Ety) == TYarray) + { + ep = el_una(OPstrpar, TYstruct, ep); + ep.Enumbytes = cast(uint)el.type.size(); + } + args.data[dim - (i + 1)] = cast(void *)ep; + } + + /* Because the number of parameters can get very large, produce + * a balanced binary tree so we don't blow up the stack in + * the subsequent tree walking code. + */ + e = el_params(args.data, dim + 1); + } + else + { + dim = 0; + e = el_long(TYint, 0); + } + Type tb = type.toBasetype(); + static if (true) { + e = el_param(e, type.getTypeInfo(null).toElem(irs)); + + // call _d_arrayliteralT(ti, dim, ...) + e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERALT]),e); + } else { + e = el_param(e, el_long(TYint, tb.next.size())); + + // call _d_arrayliteral(size, dim, ...) + e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ARRAYLITERAL]),e); + } + if (tb.ty == Tarray) + { + e = el_pair(TYullong, el_long(TYint, dim), e); + } + else if (tb.ty == Tpointer) + { + } + else + { + e = el_una(OPind,TYstruct,e); + e.Enumbytes = cast(uint)type.size(); + } + + el_setLoc(e,loc); + return e; + } + + bool checkSideEffect(int flag) + { + bool f = false; + + for (size_t i = 0; i < elements.dim; i++) + { + Expression e = cast(Expression)elements.data[i]; + f |= e.checkSideEffect(2); + } + if (flag == 0 && f == false) + Expression.checkSideEffect(0); + + return f; + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + buf.writeByte('['); + argsToCBuffer(buf, elements, hgs); + buf.writeByte(']'); + } + + void toMangleBuffer(OutBuffer buf) + { + size_t dim = elements ? elements.dim : 0; + buf.printf("A%u", dim); + for (size_t i = 0; i < dim; i++) + { + Expression e = cast(Expression)elements.data[i]; + e.toMangleBuffer(buf); + } + } + + void scanForNestedRef(Scope sc) + { + assert(false); + } + + Expression optimize(int result) + { + if (elements) + { + for (size_t i = 0; i < elements.dim; i++) + { + Expression e = cast(Expression)elements.data[i]; + + e = e.optimize(WANTvalue | (result & WANTinterpret)); + elements.data[i] = cast(void*)e; + } + } + + return this; + } + + Expression interpret(InterState* istate) + { + assert(false); + } + + MATCH implicitConvTo(Type t) + { + MATCH result = MATCHexact; + + static if (false) { + printf("ArrayLiteralExp.implicitConvTo(this=%s, type=%s, t=%s)\n", + toChars(), type.toChars(), t.toChars()); + } + Type typeb = type.toBasetype(); + Type tb = t.toBasetype(); + if ((tb.ty == Tarray || tb.ty == Tsarray) && + (typeb.ty == Tarray || typeb.ty == Tsarray)) + { + if (tb.ty == Tsarray) + { + TypeSArray tsa = cast(TypeSArray)tb; + if (elements.dim != tsa.dim.toInteger()) + result = MATCHnomatch; + } + + for (int i = 0; i < elements.dim; i++) + { + Expression e = cast(Expression)elements.data[i]; + MATCH m = cast(MATCH)e.implicitConvTo(tb.nextOf()); + if (m < result) + result = m; // remember worst match + if (result == MATCHnomatch) + break; // no need to check for worse + } + return result; + } + else + return Expression.implicitConvTo(t); + } + + Expression castTo(Scope sc, Type t) + { + static if (false) { + printf("ArrayLiteralExp.castTo(this=%s, type=%s, => %s)\n", + toChars(), type.toChars(), t.toChars()); + } + if (type == t) + return this; + ArrayLiteralExp e = this; + Type typeb = type.toBasetype(); + Type tb = t.toBasetype(); + if ((tb.ty == Tarray || tb.ty == Tsarray) && + (typeb.ty == Tarray || typeb.ty == Tsarray) && + // Not trying to convert non-void[] to void[] + !(tb.nextOf().toBasetype().ty == Tvoid && typeb.nextOf().toBasetype().ty != Tvoid)) + { + if (tb.ty == Tsarray) + { + TypeSArray tsa = cast(TypeSArray)tb; + if (elements.dim != tsa.dim.toInteger()) + goto L1; + } + + e = cast(ArrayLiteralExp)copy(); + e.elements = cast(Expressions)elements.copy(); + for (int i = 0; i < elements.dim; i++) + { + Expression ex = cast(Expression)elements.data[i]; + ex = ex.castTo(sc, tb.nextOf()); + e.elements.data[i] = cast(void*)ex; + } + e.type = t; + return e; + } + if (tb.ty == Tpointer && typeb.ty == Tsarray) + { + Type tp = typeb.nextOf().pointerTo(); + if (!tp.equals(e.type)) + { + e = cast(ArrayLiteralExp)copy(); + e.type = tp; + } + } + L1: + return e.Expression.castTo(sc, t); + } + + dt_t** toDt(dt_t** pdt) + { + assert(false); + } + +version (DMDV2) { + bool canThrow() + { + return 1; // because it can fail allocating memory + } +} + int inlineCost(InlineCostState* ics) + { + return 1 + arrayInlineCost(ics, elements); + } + + Expression doInline(InlineDoState ids) + { + ArrayLiteralExp ce = cast(ArrayLiteralExp)copy(); + ce.elements = arrayExpressiondoInline(elements, ids); + return ce; + } + + Expression inlineScan(InlineScanState* iss) + { + Expression e = this; + + //printf("ArrayLiteralExp.inlineScan()\n"); + arrayInlineScan(iss, elements); + + return e; + } +} +