Mercurial > projects > ddmd
view dmd/AssocArrayLiteralExp.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | 60bb0fe4563e |
children | b0d41ff5e0df |
line wrap: on
line source
module dmd.AssocArrayLiteralExp; import dmd.common; import dmd.Expression; import dmd.GlobalExpressions; import dmd.WANT; import dmd.expression.Equal; import dmd.backend.elem; import dmd.InterState; import dmd.MATCH; import dmd.Type; import dmd.TypeAArray; import dmd.OutBuffer; import dmd.Loc; import dmd.Scope; import dmd.InlineCostState; import dmd.IRState; import dmd.TY; import dmd.InlineDoState; import dmd.HdrGenState; import dmd.InlineScanState; import dmd.ArrayTypes; import dmd.TOK; import dmd.PREC; import dmd.expression.Util; import dmd.backend.Util; import dmd.backend.TYM; import dmd.backend.mTY; import dmd.backend.OPER; import dmd.backend.RTLSYM; class AssocArrayLiteralExp : Expression { Expressions keys; Expressions values; this(Loc loc, Expressions keys, Expressions values) { register(); super(loc, TOK.TOKassocarrayliteral, this.sizeof); assert(keys.dim == values.dim); this.keys = keys; this.values = values; } override Expression syntaxCopy() { return new AssocArrayLiteralExp(loc, arraySyntaxCopy(keys), arraySyntaxCopy(values)); } override Expression semantic(Scope sc) { Expression e; version (LOGSEMANTIC) { printf("AssocArrayLiteralExp.semantic('%s')\n", toChars()); } if (type) return this; // Run semantic() on each element arrayExpressionSemantic(keys, sc); arrayExpressionSemantic(values, sc); expandTuples(keys); expandTuples(values); if (keys.dim != values.dim) { error("number of keys is %u, must match number of values %u", keys.dim, values.dim); keys.setDim(0); values.setDim(0); } Type tkey; Type tvalue; keys = arrayExpressionToCommonType(sc, keys, &tkey); values = arrayExpressionToCommonType(sc, values, &tvalue); type = new TypeAArray(tvalue, tkey); type = type.semantic(loc, sc); return this; } override bool isBool(bool result) { size_t dim = keys.dim; return result ? (dim != 0) : (dim == 0); } override elem* toElem(IRState* irs) { elem* e; size_t dim; //printf("AssocArrayLiteralExp.toElem() %s\n", toChars()); dim = keys.dim; e = el_long(TYint, dim); for (size_t i = 0; i < dim; i++) { auto el = keys[i]; for (int j = 0; j < 2; j++) { 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(); } //printf("[%d] %s\n", i, el.toChars()); //elem_print(ep); e = el_param(ep, e); el = values[i]; } } Type t = type.toBasetype().mutableOf(); assert(t.ty == Taarray); auto ta = cast(TypeAArray)t; static if(false) { /* Unfortunately, the hash function for Aa (array of chars) is custom and * different from Axa and Aya, which get the generic hash function. * So, rewrite the type of the AArray so that if it's key type * is an array of const or invariant, make it an array of mutable. */ Type tkey = ta.index.toBasetype(); if (tkey.ty == Tarray) { tkey = tkey.nextOf().mutableOf().arrayOf(); tkey = tkey.semantic(Loc(0), null); ta = new TypeAArray(ta.nextOf(), tkey); ta = cast(TypeAArray)ta.merge(); } } e = el_param(e, ta.getTypeInfo(null).toElem(irs)); // call _d_assocarrayliteralT(ti, dim, ...) e = el_bin(OPcall,TYnptr,el_var(rtlsym[RTLSYM_ASSOCARRAYLITERALT]),e); el_setLoc(e,loc); return e; } override bool checkSideEffect(int flag) { bool f = false; for (size_t i = 0; i < keys.dim; i++) { auto key = keys[i]; auto value = values[i]; f |= key.checkSideEffect(2); f |= value.checkSideEffect(2); } if (flag == 0 && f == 0) Expression.checkSideEffect(0); return f; } override void toCBuffer(OutBuffer buf, HdrGenState* hgs) { buf.writeByte('['); for (size_t i = 0; i < keys.dim; i++) { auto key = keys[i]; auto value = values[i]; if (i) buf.writeByte(','); expToCBuffer(buf, hgs, key, PREC.PREC_assign); buf.writeByte(':'); expToCBuffer(buf, hgs, value, PREC.PREC_assign); } buf.writeByte(']'); } override void toMangleBuffer(OutBuffer buf) { size_t dim = keys.dim; buf.printf("A%u", dim); for (size_t i = 0; i < dim; i++) { auto key = keys[i]; auto value = values[i]; key.toMangleBuffer(buf); value.toMangleBuffer(buf); } } override void scanForNestedRef(Scope sc) { assert(false); } override Expression optimize(int result) { assert(keys.dim == values.dim); foreach (size_t i, Expression e; keys) { e = e.optimize(WANTvalue | (result & WANTinterpret)); keys[i] = e; e = values[i]; e = e.optimize(WANTvalue | (result & WANTinterpret)); values[i] = e; } return this; } override Expression interpret(InterState istate) { Expressions keysx = keys; Expressions valuesx = values; version (LOG) { printf("AssocArrayLiteralExp.interpret() %s\n", toChars()); } for (size_t i = 0; i < keys.dim; i++) { auto ekey = keys[i]; auto evalue = values[i]; Expression ex; ex = ekey.interpret(istate); if (ex is EXP_CANT_INTERPRET) goto Lerr; /* If any changes, do Copy On Write */ if (ex != ekey) { if (keysx == keys) keysx = cast(Expressions)keys.copy(); keysx[i] = ex; } ex = evalue.interpret(istate); if (ex is EXP_CANT_INTERPRET) goto Lerr; /* If any changes, do Copy On Write */ if (ex != evalue) { if (valuesx == values) valuesx = values.copy(); valuesx[i] = ex; } } if (keysx != keys) expandTuples(keysx); if (valuesx != values) expandTuples(valuesx); if (keysx.dim != valuesx.dim) goto Lerr; /* Remove duplicate keys */ for (size_t i = 1; i < keysx.dim; i++) { auto ekey = keysx[i - 1]; for (size_t j = i; j < keysx.dim; j++) { auto ekey2 = keysx[j]; Expression ex = Equal(TOKequal, Type.tbool, ekey, ekey2); if (ex is EXP_CANT_INTERPRET) goto Lerr; if (ex.isBool(true)) // if a match { // Remove ekey if (keysx == keys) keysx = cast(Expressions)keys.copy(); if (valuesx == values) valuesx = cast(Expressions)values.copy(); keysx.remove(i - 1); valuesx.remove(i - 1); i -= 1; // redo the i'th iteration break; } } } if (keysx != keys || valuesx != values) { AssocArrayLiteralExp ae; ae = new AssocArrayLiteralExp(loc, keysx, valuesx); ae.type = type; return ae; } return this; Lerr: if (keysx != keys) delete keysx; if (valuesx != values) delete values; return EXP_CANT_INTERPRET; } override MATCH implicitConvTo(Type t) { MATCH result = MATCHexact; Type typeb = type.toBasetype(); Type tb = t.toBasetype(); if (tb.ty == Taarray && typeb.ty == Taarray) { for (size_t i = 0; i < keys.dim; i++) { auto e = keys[i]; auto m = cast(MATCH)e.implicitConvTo((cast(TypeAArray)tb).index); if (m < result) result = m; // remember worst match if (result == MATCHnomatch) break; // no need to check for worse e = values[i]; 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); } override Expression castTo(Scope sc, Type t) { if (type == t) return this; AssocArrayLiteralExp e = this; Type typeb = type.toBasetype(); Type tb = t.toBasetype(); if (tb.ty == Taarray && typeb.ty == Taarray && tb.nextOf().toBasetype().ty != Tvoid) { e = cast(AssocArrayLiteralExp)copy(); e.keys = cast(Expressions)keys.copy(); e.values = cast(Expressions)values.copy(); assert(keys.dim == values.dim); for (size_t i = 0; i < keys.dim; i++) { auto ex = values[i]; ex = ex.castTo(sc, tb.nextOf()); e.values[i] = ex; ex = keys[i]; ex = ex.castTo(sc, (cast(TypeAArray)tb).index); e.keys[i] = ex; } e.type = t; return e; } L1: return e.Expression.castTo(sc, t); } override bool canThrow() { return true; } override int inlineCost(InlineCostState* ics) { assert(false); } override Expression doInline(InlineDoState ids) { assert(false); } override Expression inlineScan(InlineScanState* iss) { assert(false); } }