Mercurial > projects > ddmd
diff dmd/CatExp.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/CatExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,255 @@ +module dmd.CatExp; + +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.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) + { + super(loc, TOK.TOKcat, CatExp.sizeof, e1, e2); + } + + 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(); +} + if ((tb1.ty == Tsarray || tb1.ty == Tarray) && + e2.type.implicitConvTo(tb1.nextOf()) >= MATCHconst) + { + type = tb1.nextOf().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.type.implicitConvTo(tb2.nextOf()) >= MATCHconst) + { + type = tb2.nextOf().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) && + (tb1.nextOf().mod || tb2.nextOf().mod) && + (tb1.nextOf().mod != tb2.nextOf().mod) + ) + { + Type t1 = tb1.nextOf().mutableOf().constOf().arrayOf(); + Type t2 = tb2.nextOf().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 && tb1.nextOf() && tb2.nextOf() && + tb1.nextOf().mod != tb2.nextOf().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()); + type = Type.tint32; + e = this; + } + e.type = e.type.semantic(loc, sc); + return e; + } + return this; + } + + 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; + } + + Expression interpret(InterState* istate) + { + assert(false); + } + + Identifier opId() + { + return Id.cat; + } + + Identifier opId_r() + { + return Id.cat_r; + } + + 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; + } +} +