commit 89b803775add158835e56f6194850eec6d58b437
parent 1e1c5bd379f93b673372f60c168c492db12f3cd4
Author: Eyal Sawady <ecs@d2evs.net>
Date: Sun, 2 May 2021 15:02:55 -0400
eval: implement floats
Signed-off-by: Eyal Sawady <ecs@d2evs.net>
Diffstat:
2 files changed, 114 insertions(+), 50 deletions(-)
diff --git a/src/eval.c b/src/eval.c
@@ -106,6 +106,17 @@ itrunc(const struct type *type, uintmax_t val)
assert(0);
}
+static double
+ftrunc(const struct type *type, double val)
+{
+ if (type->storage == STORAGE_F32) {
+ return (float)val;
+ } else if (type->storage == STORAGE_F64) {
+ return val;
+ }
+ assert(0);
+}
+
enum eval_result
eval_binarithm(struct context *ctx, struct expression *in, struct expression *out)
{
@@ -120,90 +131,107 @@ eval_binarithm(struct context *ctx, struct expression *in, struct expression *ou
}
bool blval = lvalue.constant.bval, brval = rvalue.constant.bval, bval;
- intmax_t ilval = itrunc(lvalue.result, lvalue.constant.ival),
- irval = itrunc(rvalue.result, rvalue.constant.ival), ival;
- uintmax_t ulval = itrunc(lvalue.result, lvalue.constant.uval),
- urval = itrunc(rvalue.result, rvalue.constant.uval), uval;
+ intmax_t ilval = lvalue.constant.ival, irval = rvalue.constant.ival, ival;
+ uintmax_t ulval = lvalue.constant.uval, urval = rvalue.constant.uval, uval;
+ double flval = lvalue.constant.fval, frval = rvalue.constant.fval, fval;
// Type promotion is lowered in check
assert(lvalue.result->storage == rvalue.result->storage);
switch (in->binarithm.op) {
case BIN_BAND:
+ assert(!type_is_float(lvalue.result));
if (type_is_signed(lvalue.result)) {
- ival = ilval & irval;
+ ival = itrunc(lvalue.result, ilval) & itrunc(rvalue.result, irval);
} else {
- uval = ulval & urval;
+ uval = itrunc(lvalue.result, ulval) & itrunc(rvalue.result, urval);
}
break;
case BIN_BOR:
+ assert(!type_is_float(lvalue.result));
if (type_is_signed(lvalue.result)) {
- ival = ilval | irval;
+ ival = itrunc(lvalue.result, ilval) | itrunc(rvalue.result, irval);
} else {
- uval = ulval | urval;
+ uval = itrunc(lvalue.result, ulval) | itrunc(rvalue.result, urval);
}
break;
case BIN_DIV:
- if (type_is_signed(lvalue.result)) {
- ival = ilval / irval;
+ if (type_is_float(lvalue.result)) {
+ fval = ftrunc(lvalue.result, flval) / ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ ival = itrunc(lvalue.result, ilval) / itrunc(rvalue.result, irval);
} else {
- uval = ulval / urval;
+ uval = itrunc(lvalue.result, ulval) / itrunc(rvalue.result, urval);
}
break;
case BIN_LSHIFT:
assert(!type_is_signed(rvalue.result));
- uval = ulval << urval;
+ assert(!type_is_float(lvalue.result));
+ uval = itrunc(lvalue.result, ulval) << itrunc(rvalue.result, urval);
break;
case BIN_MINUS:
- if (type_is_signed(lvalue.result)) {
- ival = ilval - irval;
+ if (type_is_float(lvalue.result)) {
+ fval = ftrunc(lvalue.result, flval) - ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ ival = itrunc(lvalue.result, ilval) - itrunc(rvalue.result, irval);
} else {
- uval = ulval - urval;
+ uval = itrunc(lvalue.result, ulval) - itrunc(rvalue.result, urval);
}
break;
case BIN_MODULO:
+ assert(!type_is_float(lvalue.result));
if (type_is_signed(lvalue.result)) {
- ival = ilval % irval;
+ ival = itrunc(lvalue.result, ilval) % itrunc(rvalue.result, irval);
} else {
- uval = ulval % urval;
+ uval = itrunc(lvalue.result, ulval) % itrunc(rvalue.result, urval);
}
break;
case BIN_PLUS:
- if (type_is_signed(lvalue.result)) {
- ival = ilval + irval;
+ if (type_is_float(lvalue.result)) {
+ fval = ftrunc(lvalue.result, flval) + ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ ival = itrunc(lvalue.result, ilval) + itrunc(rvalue.result, irval);
} else {
- uval = ulval + urval;
+ uval = itrunc(lvalue.result, ulval) + itrunc(rvalue.result, urval);
}
break;
case BIN_RSHIFT:
assert(!type_is_signed(rvalue.result));
- uval = ulval >> urval;
+ assert(!type_is_float(lvalue.result));
+ uval = itrunc(lvalue.result, ulval) >> itrunc(rvalue.result, urval);
break;
case BIN_TIMES:
- if (type_is_signed(lvalue.result)) {
- ival = ilval * irval;
+ if (type_is_float(lvalue.result)) {
+ fval = ftrunc(lvalue.result, flval) * ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ ival = itrunc(lvalue.result, ilval) * itrunc(rvalue.result, irval);
} else {
- uval = ulval * urval;
+ uval = itrunc(lvalue.result, ulval) * itrunc(rvalue.result, urval);
}
break;
case BIN_BXOR:
+ assert(!type_is_float(lvalue.result));
if (type_is_signed(lvalue.result)) {
- ival = ilval ^ irval;
+ ival = itrunc(lvalue.result, ilval) ^ itrunc(rvalue.result, irval);
} else {
- uval = ulval ^ urval;
+ uval = itrunc(lvalue.result, ulval) ^ itrunc(rvalue.result, urval);
}
break;
// Logical arithmetic
case BIN_GREATER:
- if (type_is_signed(lvalue.result)) {
- bval = ilval > irval;
+ if (type_is_float(lvalue.result)) {
+ bval = ftrunc(lvalue.result, flval) > ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ bval = itrunc(lvalue.result, ilval) > itrunc(rvalue.result, irval);
} else {
- bval = ulval > urval;
+ bval = itrunc(lvalue.result, ulval) > itrunc(rvalue.result, urval);
}
break;
case BIN_GREATEREQ:
- if (type_is_signed(lvalue.result)) {
- bval = ilval >= irval;
+ if (type_is_float(lvalue.result)) {
+ bval = ftrunc(lvalue.result, flval) >= ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ bval = itrunc(lvalue.result, ilval) >= itrunc(rvalue.result, irval);
} else {
- bval = ulval >= urval;
+ bval = itrunc(lvalue.result, ulval) >= itrunc(rvalue.result, urval);
}
break;
case BIN_LAND:
@@ -212,24 +240,30 @@ eval_binarithm(struct context *ctx, struct expression *in, struct expression *ou
bval = blval && brval;
break;
case BIN_LEQUAL:
- if (type_is_signed(lvalue.result)) {
- bval = ilval == irval;
+ if (type_is_float(lvalue.result)) {
+ bval = ftrunc(lvalue.result, flval) == ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ bval = itrunc(lvalue.result, ilval) == itrunc(rvalue.result, irval);
} else {
- bval = ulval == urval;
+ bval = itrunc(lvalue.result, ulval) == itrunc(rvalue.result, urval);
}
break;
case BIN_LESS:
- if (type_is_signed(lvalue.result)) {
- bval = ilval < irval;
+ if (type_is_float(lvalue.result)) {
+ bval = ftrunc(lvalue.result, flval) < ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ bval = itrunc(lvalue.result, ilval) < itrunc(rvalue.result, irval);
} else {
- bval = ulval < urval;
+ bval = itrunc(lvalue.result, ulval) < itrunc(rvalue.result, urval);
}
break;
case BIN_LESSEQ:
- if (type_is_signed(lvalue.result)) {
- bval = ilval <= irval;
+ if (type_is_float(lvalue.result)) {
+ bval = ftrunc(lvalue.result, flval) <= ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ bval = itrunc(lvalue.result, ilval) <= itrunc(rvalue.result, irval);
} else {
- bval = ulval <= urval;
+ bval = itrunc(lvalue.result, ulval) <= itrunc(rvalue.result, urval);
}
break;
case BIN_LOR:
@@ -243,23 +277,25 @@ eval_binarithm(struct context *ctx, struct expression *in, struct expression *ou
bval = blval != brval;
break;
case BIN_NEQUAL:
- if (type_is_signed(lvalue.result)) {
- bval = ilval != irval;
+ if (type_is_float(lvalue.result)) {
+ bval = ftrunc(lvalue.result, flval) != ftrunc(rvalue.result, frval);
+ } else if (type_is_signed(lvalue.result)) {
+ bval = itrunc(lvalue.result, ilval) != itrunc(rvalue.result, irval);
} else {
- bval = ulval != urval;
+ bval = itrunc(lvalue.result, ulval) != itrunc(rvalue.result, urval);
}
break;
}
- uval = itrunc(in->result, uval);
- ival = itrunc(in->result, ival);
out->type = EXPR_CONSTANT;
out->result = in->result;
- if (type_is_signed(in->result)) {
- out->constant.ival = ival;
+ if (type_is_float(in->result)) {
+ out->constant.fval = ftrunc(in->result, fval);
+ } else if (type_is_signed(in->result)) {
+ out->constant.ival = itrunc(in->result, ival);
} else if (type_dealias(in->result)->storage == STORAGE_BOOL) {
out->constant.bval = bval;
} else {
- out->constant.uval = uval;
+ out->constant.uval = itrunc(in->result, uval);
}
return EVAL_OK;
}
@@ -378,7 +414,14 @@ eval_cast(struct context *ctx, struct expression *in, struct expression *out)
case STORAGE_UINTPTR:
case STORAGE_SIZE:
case STORAGE_RUNE:
- out->constant.uval = itrunc(to, val.constant.uval);
+ if (type_is_float(val.result)) {
+ out->constant.ival =
+ itrunc(to, (intmax_t)val.constant.fval);
+ } else if (type_is_signed(val.result)) {
+ out->constant.ival = itrunc(to, val.constant.ival);
+ } else {
+ out->constant.ival = itrunc(to, val.constant.uval);
+ }
return EVAL_OK;
case STORAGE_ARRAY:
case STORAGE_SLICE:
@@ -388,6 +431,16 @@ eval_cast(struct context *ctx, struct expression *in, struct expression *out)
case STORAGE_F32:
case STORAGE_F64:
case STORAGE_FCONST:
+ if (type_is_float(val.result)) {
+ out->constant.fval = ftrunc(to, val.constant.fval);
+ } else if (type_is_signed(val.result)) {
+ out->constant.fval =
+ ftrunc(to, (double)val.constant.ival);
+ } else {
+ out->constant.fval =
+ ftrunc(to, (double)val.constant.uval);
+ }
+ return EVAL_OK;
case STORAGE_CHAR:
case STORAGE_ENUM:
case STORAGE_NULL:
diff --git a/tests/10-binarithms.ha b/tests/10-binarithms.ha
@@ -89,8 +89,19 @@ fn sar_shr() void = {
assert(h1 == -189203912);
};
+def FLOAT: f64 = 6.0 * 7.0;
+def I8: i8 = 127 * 2;
+def U8: u8 = 128 * 2;
+
+fn eval() void = {
+ assert(FLOAT == 42.0);
+ assert(I8 == 126);
+ assert(U8 == 0);
+};
+
export fn main() void = {
// TODO: other binarithms
andorxor();
sar_shr();
+ eval();
};