~sircmpwn/harec unlisted

89b803775add158835e56f6194850eec6d58b437 — Eyal Sawady a month ago 1e1c5bd
eval: implement floats

Signed-off-by: Eyal Sawady <ecs@d2evs.net>
2 files changed, 114 insertions(+), 50 deletions(-)

M src/eval.c
M tests/10-binarithms.ha
M src/eval.c => src/eval.c +103 -50
@@ 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:

M tests/10-binarithms.ha => tests/10-binarithms.ha +11 -0
@@ 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();
};