aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/expr.zc10
1 files changed, 7 insertions, 3 deletions
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc
index ffb90a7..95ce67b 100644
--- a/src/compiler/expr.zc
+++ b/src/compiler/expr.zc
@@ -1727,7 +1727,7 @@ int storekeep(int t) {
// restored for the second side) and then joined, so a variable can't be given
// away on one side only. both sides are fresh objects, or neither is.
int ternary(int c) {
- int a, b, s0, sa, livea, live0 = live, n0 = nloc, ca, cb, ta, ba, bb; word temp_a, temp_b, mask_a, mask_b;
+ int a, b, s0, sa, livea, live0 = live, n0 = nloc, ca, cb, ta, ba, bb, conv, skip, back; word temp_a, temp_b, mask_a, mask_b;
rval(); plainuse(c);
ftest();
next();
@@ -1735,6 +1735,7 @@ int ternary(int c) {
s0 = snap_push();
ca = expr(); rval(); ta = xty; ba = xbor; temp_a = xaf; mask_a = effect_mask(ca);
if (ca != C_FRESH) plainuse(ca);
+ conv = -1; if (isnum(ta) && !isfl(ta) && ta != tword) { conv = hole(); op(O_JMP); back = here; setlit(conv, back); } // a jump to the next word, redirected below if the other side is a float (appendix b.2.5)
livea = live; sa = snap_push();
b = hole(); op(O_JMP);
expect(s_colon);
@@ -1742,11 +1743,14 @@ int ternary(int c) {
snap_restore(s0); live = live0;
cb = expr(); rval(); bb = xbor; temp_b = xaf; mask_b = effect_mask(cb);
if (cb != C_FRESH) plainuse(cb);
+ if (isfl(ta) && !isfl(xty)) { op(OP_I2F); xfloat = 1; xty = tfloat; } // on the second side's path only
join2(sa, livea, b, live, n0, "ends the two sides of ?: in different states");
snap_pop(s0);
- if (isfl(ta) && !isfl(xty)) { op(OP_I2F); xfloat = 1; xty = tfloat; }
+ if (conv >= 0 && isfl(xty)) { // the first side was an integer: convert it out of line
+ skip = hole(); op(O_JMP); setlit(conv, here); op(OP_I2F); lit(back); op(O_JMP); setlit(skip, here);
+ }
if (!compat(ta, xty) && !compat(xty, ta)) tcerr("the two sides of ?:", ta, xty);
- if (ta != tword && !isfl(ta)) xty = ta;
+ if (ta != tword && !isfl(ta) && !(conv >= 0 && isfl(xty))) xty = ta;
else if (isfl(ta) || isfl(xty)) { xty = tfloat; xfloat = 1; }
if_value = 0;
effect_value = mask_a | mask_b;