harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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:
Msrc/eval.c | 153+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
Mtests/10-binarithms.ha | 11+++++++++++
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(); };