Mercurial > projects > ddmd
view dmd/CatExp.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 | e8a741997ccf |
children | b0d41ff5e0df |
line wrap: on
line source
module dmd.CatExp; import dmd.common; import dmd.Expression; import dmd.Identifier; import dmd.InterState; import dmd.Loc; import dmd.Scope; import dmd.IRState; import dmd.BinExp; import dmd.TOK; import dmd.Type; import dmd.TY; import dmd.MATCH; import dmd.ArrayLiteralExp; import dmd.StringExp; import dmd.ErrorExp; import dmd.WANT; import dmd.Id; import dmd.GlobalExpressions; import dmd.backend.elem; import dmd.backend.Util; import dmd.backend.TYM; import dmd.backend.OPER; import dmd.backend.RTLSYM; import dmd.codegen.Util; import dmd.expression.Cat; class CatExp : BinExp { this(Loc loc, Expression e1, Expression e2) { register(); super(loc, TOK.TOKcat, CatExp.sizeof, e1, e2); } override Expression semantic(Scope sc) { Expression e; //printf("CatExp.semantic() %s\n", toChars()); if (!type) { BinExp.semanticp(sc); e = op_overload(sc); if (e) return e; Type tb1 = e1.type.toBasetype(); Type tb2 = e2.type.toBasetype(); /* BUG: Should handle things like: * char c; * c ~ ' ' * ' ' ~ c; */ static if (false) { e1.type.print(); e2.type.print(); } Type tb1next = tb1.nextOf(); Type tb2next = tb2.nextOf(); if ((tb1.ty == Tsarray || tb1.ty == Tarray) && e2.implicitConvTo(tb1next) >= MATCHconvert) { e2 = e2.implicitCastTo(sc, tb1next); type = tb1next.arrayOf(); if (tb2.ty == Tarray) { // Make e2 into [e2] e2 = new ArrayLiteralExp(e2.loc, e2); e2.type = type; } return this; } else if ((tb2.ty == Tsarray || tb2.ty == Tarray) && e1.implicitConvTo(tb2next) >= MATCHconvert) { e1 = e1.implicitCastTo(sc, tb2next); type = tb2next.arrayOf(); if (tb1.ty == Tarray) { // Make e1 into [e1] e1 = new ArrayLiteralExp(e1.loc, e1); e1.type = type; } return this; } if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod) ) { Type t1 = tb1next.mutableOf().constOf().arrayOf(); Type t2 = tb2next.mutableOf().constOf().arrayOf(); if (e1.op == TOKstring && !(cast(StringExp)e1).committed) e1.type = t1; else e1 = e1.castTo(sc, t1); if (e2.op == TOKstring && !(cast(StringExp)e2).committed) e2.type = t2; else e2 = e2.castTo(sc, t2); } typeCombine(sc); type = type.toHeadMutable(); Type tb = type.toBasetype(); if (tb.ty == Tsarray) type = tb.nextOf().arrayOf(); if (type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod) { type = type.nextOf().toHeadMutable().arrayOf(); } static if (false) { e1.type.print(); e2.type.print(); type.print(); print(); } Type t1 = e1.type.toBasetype(); Type t2 = e2.type.toBasetype(); if (e1.op == TOKstring && e2.op == TOKstring) e = optimize(WANTvalue); else if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray)) { e = this; } else { //printf("(%s) ~ (%s)\n", e1.toChars(), e2.toChars()); error("Can only concatenate arrays, not (%s ~ %s)", e1.type.toChars(), e2.type.toChars()); return new ErrorExp(); } e.type = e.type.semantic(loc, sc); return e; } return this; } override Expression optimize(int result) { //printf("CatExp::optimize(%d) %s\n", result, toChars()); e1 = e1.optimize(result); e2 = e2.optimize(result); Expression e = Cat(type, e1, e2); if (e is EXP_CANT_INTERPRET) e = this; return e; } override Expression interpret(InterState istate) { Expression e; Expression e1; Expression e2; version (LOG) { printf("CatExp.interpret() %.*s\n", toChars()); } e1 = this.e1.interpret(istate); if (e1 is EXP_CANT_INTERPRET) { goto Lcant; } e2 = this.e2.interpret(istate); if (e2 is EXP_CANT_INTERPRET) goto Lcant; return Cat(type, e1, e2); Lcant: version (LOG) { printf("CatExp.interpret() %.*s CANT\n", toChars()); } return EXP_CANT_INTERPRET; } override Identifier opId() { return Id.cat; } override Identifier opId_r() { return Id.cat_r; } override elem* toElem(IRState* irs) { elem *e; static if (false) { printf("CatExp::toElem()\n"); print(); } Type tb1 = e1.type.toBasetype(); Type tb2 = e2.type.toBasetype(); Type tn; ///static if (false) { /// if ((tb1.ty == Tarray || tb1.ty == Tsarray) && /// (tb2.ty == Tarray || tb2.ty == Tsarray) /// ) ///} Type ta = tb1.nextOf() ? e1.type : e2.type; tn = tb1.nextOf() ? tb1.nextOf() : tb2.nextOf(); { if (e1.op == TOKcat) { elem* ep; CatExp ce = this; int n = 2; ep = eval_Darray(irs, ce.e2); do { n++; ce = cast(CatExp)ce.e1; ep = el_param(ep, eval_Darray(irs, ce.e2)); } while (ce.e1.op == TOKcat); ep = el_param(ep, eval_Darray(irs, ce.e1)); static if (true) { ep = el_params( ep, el_long(TYint, n), ta.getTypeInfo(null).toElem(irs), null); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATNT]), ep); } else { ep = el_params( ep, el_long(TYint, n), el_long(TYint, tn.size()), null); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATN]), ep); } } else { elem *e1; elem *e2; elem *ep; e1 = eval_Darray(irs, this.e1); e2 = eval_Darray(irs, this.e2); static if (true) { ep = el_params(e2, e1, ta.getTypeInfo(null).toElem(irs), null); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCATT]), ep); } else { ep = el_params(el_long(TYint, tn.size()), e2, e1, null); e = el_bin(OPcall, TYdarray, el_var(rtlsym[RTLSYM_ARRAYCAT]), ep); } } el_setLoc(e,loc); } /// static if (false) { /// else if ((tb1.ty == Tarray || tb1.ty == Tsarray) && /// e2.type.equals(tb1.next)) /// { /// error("array cat with element not implemented"); /// e = el_long(TYint, 0); /// } /// else /// assert(0); /// } return e; } }