Mercurial > projects > ddmd
diff dmd/CondExp.d @ 0:10317f0c89a5
Initial commit
author | korDen |
---|---|
date | Sat, 24 Oct 2009 08:42:06 +0400 |
parents | |
children | a509c8688fbd |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dmd/CondExp.d Sat Oct 24 08:42:06 2009 +0400 @@ -0,0 +1,281 @@ +module dmd.CondExp; + +import dmd.BinExp; +import dmd.Loc; +import dmd.MATCH; +import dmd.Expression; +import dmd.Scope; +import dmd.InterState; +import dmd.OutBuffer; +import dmd.HdrGenState; +import dmd.Type; +import dmd.InlineCostState; +import dmd.InlineDoState; +import dmd.InlineScanState; +import dmd.IRState; +import dmd.TOK; +import dmd.TY; +import dmd.WANT; +import dmd.Global; + +import dmd.backend.elem; +import dmd.backend.Util; +import dmd.backend.OPER; +import dmd.backend.mTY; +import dmd.backend.TYM; +import dmd.codegen.Util; + +class CondExp : BinExp +{ + Expression econd; + + this(Loc loc, Expression econd, Expression e1, Expression e2) + { + super(loc, TOK.TOKquestion, CondExp.sizeof, e1, e2); + this.econd = econd; + } + + Expression syntaxCopy() + { + assert(false); + } + + Expression semantic(Scope sc) + { + Type t1; + Type t2; + uint cs0; + uint cs1; + + version (LOGSEMANTIC) { + printf("CondExp.semantic('%s')\n", toChars()); + } + if (type) + return this; + + econd = econd.semantic(sc); + econd = resolveProperties(sc, econd); + econd = econd.checkToPointer(); + econd = econd.checkToBoolean(); + + static if (false) { + /* this cannot work right because the types of e1 and e2 + * both contribute to the type of the result. + */ + if (sc.flags & SCOPEstaticif) + { + /* If in static if, don't evaluate what we don't have to. + */ + econd = econd.optimize(WANTflags); + if (econd.isBool(TRUE)) + { + e1 = e1.semantic(sc); + e1 = resolveProperties(sc, e1); + return e1; + } + else if (econd.isBool(FALSE)) + { + e2 = e2.semantic(sc); + e2 = resolveProperties(sc, e2); + return e2; + } + } + } + + cs0 = sc.callSuper; + e1 = e1.semantic(sc); + e1 = resolveProperties(sc, e1); + cs1 = sc.callSuper; + sc.callSuper = cs0; + e2 = e2.semantic(sc); + e2 = resolveProperties(sc, e2); + sc.mergeCallSuper(loc, cs1); + + // If either operand is void, the result is void + t1 = e1.type; + t2 = e2.type; + if (t1.ty == Tvoid || t2.ty == Tvoid) + type = Type.tvoid; + else if (t1 == t2) + type = t1; + else + { + typeCombine(sc); + switch (e1.type.toBasetype().ty) + { + case Tcomplex32: + case Tcomplex64: + case Tcomplex80: + e2 = e2.castTo(sc, e1.type); + break; + default: + break; + } + switch (e2.type.toBasetype().ty) + { + case Tcomplex32: + case Tcomplex64: + case Tcomplex80: + e1 = e1.castTo(sc, e2.type); + break; + default: + break; + } + if (type.toBasetype().ty == Tarray) + { + e1 = e1.castTo(sc, type); + e2 = e2.castTo(sc, type); + } + } + static if (false) { + printf("res: %s\n", type.toChars()); + printf("e1 : %s\n", e1.type.toChars()); + printf("e2 : %s\n", e2.type.toChars()); + } + return this; + } + + Expression optimize(int result) + { + Expression e; + + econd = econd.optimize(WANTflags | (result & WANTinterpret)); + if (econd.isBool(true)) + e = e1.optimize(result); + else if (econd.isBool(false)) + e = e2.optimize(result); + else + { + e1 = e1.optimize(result); + e2 = e2.optimize(result); + e = this; + } + + return e; + } + + Expression interpret(InterState istate) + { + assert(false); + } + + void checkEscape() + { + e1.checkEscape(); + e2.checkEscape(); + } + + int isLvalue() + { + assert(false); + } + + Expression toLvalue(Scope sc, Expression e) + { + assert(false); + } + + Expression modifiableLvalue(Scope sc, Expression e) + { + assert(false); + } + + Expression checkToBoolean() + { + assert(false); + } + + bool checkSideEffect(int flag) + { + assert(false); + } + + void toCBuffer(OutBuffer buf, HdrGenState* hgs) + { + assert(false); + } + + MATCH implicitConvTo(Type t) + { + MATCH m1 = e1.implicitConvTo(t); + MATCH m2 = e2.implicitConvTo(t); + //printf("CondExp: m1 %d m2 %d\n", m1, m2); + + // Pick the worst match + return (m1 < m2) ? m1 : m2; + } + + Expression castTo(Scope sc, Type t) + { + Expression e = this; + + if (type !is t) + { + if (1 || e1.op == TOKstring || e2.op == TOKstring) + { + e = new CondExp(loc, econd, e1.castTo(sc, t), e2.castTo(sc, t)); + e.type = t; + } + else + e = Expression.castTo(sc, t); + } + return e; + } + + void scanForNestedRef(Scope sc) + { + assert(false); + } + + bool canThrow() + { + return econd.canThrow() || e1.canThrow() || e2.canThrow(); + } + + int inlineCost(InlineCostState* ics) + { + return 1 + e1.inlineCost(ics) + e2.inlineCost(ics) + econd.inlineCost(ics); + } + + Expression doInline(InlineDoState ids) + { + CondExp ce = cast(CondExp)copy(); + + ce.econd = econd.doInline(ids); + ce.e1 = e1.doInline(ids); + ce.e2 = e2.doInline(ids); + return ce; + } + + Expression inlineScan(InlineScanState* iss) + { + econd = econd.inlineScan(iss); + e1 = e1.inlineScan(iss); + e2 = e2.inlineScan(iss); + return this; + } + + elem* toElem(IRState* irs) + { + elem* eleft; + elem* eright; + + elem* ec = econd.toElem(irs); + + eleft = e1.toElem(irs); + tym_t ty = eleft.Ety; + if (global.params.cov && e1.loc.linnum) + eleft = el_combine(incUsageElem(irs, e1.loc), eleft); + + eright = e2.toElem(irs); + if (global.params.cov && e2.loc.linnum) + eright = el_combine(incUsageElem(irs, e2.loc), eright); + + elem* e = el_bin(OPcond, ty, ec, el_bin(OPcolon, ty, eleft, eright)); + if (tybasic(ty) == TYstruct) + e.Enumbytes = cast(uint)e1.type.size(); + + el_setLoc(e, loc); + return e; + } +} \ No newline at end of file