aboutsummaryrefslogtreecommitdiff
path: root/repl.c
diff options
context:
space:
mode:
Diffstat (limited to 'repl.c')
-rw-r--r--repl.c78
1 files changed, 47 insertions, 31 deletions
diff --git a/repl.c b/repl.c
index 9b92146f..d17d5699 100644
--- a/repl.c
+++ b/repl.c
@@ -17,6 +17,7 @@ typedef union {
int16_t i16;
int32_t i32;
int64_t i64;
+ Int_t integer;
double n64;
float n32;
} number_t;
@@ -156,7 +157,7 @@ static void *get_address(env_t *env, ast_t *ast)
}
}
-static int64_t ast_to_int(env_t *env, ast_t *ast)
+static Int_t ast_to_int(env_t *env, ast_t *ast)
{
type_t *t = get_type(env, ast);
switch (t->tag) {
@@ -164,10 +165,11 @@ static int64_t ast_to_int(env_t *env, ast_t *ast)
number_t num;
eval(env, ast, &num);
switch (Match(t, IntType)->bits) {
- case 0: case 64: return (int64_t)num.i64;
- case 32: return (int64_t)num.i32;
- case 16: return (int64_t)num.i16;
- case 8: return (int64_t)num.i8;
+ case 0: return num.integer;
+ case 64: return Int$from_i64((int64_t)num.i64);
+ case 32: return Int$from_i64((int64_t)num.i32);
+ case 16: return Int$from_i64((int64_t)num.i16);
+ case 8: return Int$from_i64((int64_t)num.i8);
default: errx(1, "Invalid int bits");
}
}
@@ -183,7 +185,8 @@ static double ast_to_num(env_t *env, ast_t *ast)
number_t num;
eval(env, ast, &num);
switch (Match(t, IntType)->bits) {
- case 0: case 64: return (double)num.i64;
+ case 0: return Int$as_num(num.integer);
+ case 64: return (double)num.i64;
case 32: return (double)num.i32;
case 16: return (double)num.i16;
case 8: return (double)num.i8;
@@ -383,33 +386,46 @@ void eval(env_t *env, ast_t *ast, void *dest)
if (dest) *(CORD*)dest = ret;
break;
}
-#define CASE_OP(OP_NAME, C_OP) case BINOP_##OP_NAME: {\
- if (t->tag == IntType) { \
- int64_t lhs = ast_to_int(env, binop->lhs); \
- int64_t rhs = ast_to_int(env, binop->rhs); \
- switch (Match(t, IntType)->bits) { \
- case 64: *(int64_t*)dest = lhs C_OP rhs; break; \
- case 32: *(int32_t*)dest = (int32_t)(lhs C_OP rhs); break; \
- case 16: *(int16_t*)dest = (int16_t)(lhs C_OP rhs); break; \
- case 8: *(int8_t*)dest = (int8_t)(lhs C_OP rhs); break; \
- default: errx(1, "Invalid int bits"); \
- } \
- } else if (t->tag == NumType) { \
- double lhs = ast_to_num(env, binop->lhs); \
- double rhs = ast_to_num(env, binop->rhs); \
- if (Match(t, NumType)->bits == 64) \
- *(double*)dest = (double)(lhs C_OP rhs); \
- else \
- *(float*)dest = (float)(lhs C_OP rhs); \
- } else { \
- errx(1, "Binary ops are not yet supported for %W", ast); \
+ case BinaryOp: {
+ auto binop = Match(ast, BinaryOp);
+ if (t->tag == IntType) {
+#define CASE_OP(OP_NAME, method_name) case BINOP_##OP_NAME: {\
+ Int_t lhs = ast_to_int(env, binop->lhs); \
+ Int_t rhs = ast_to_int(env, binop->rhs); \
+ Int_t result = Int$ ## method_name (lhs, rhs); \
+ switch (Match(t, IntType)->bits) { \
+ case 0: *(Int_t*)dest = result; return; \
+ case 64: *(int64_t*)dest = (int64_t)Int$as_i64(result); return; \
+ case 32: *(int32_t*)dest = (int32_t)Int$as_i64(result); return; \
+ case 16: *(int16_t*)dest = (int16_t)Int$as_i64(result); return; \
+ case 8: *(int8_t*)dest = (int8_t)Int$as_i64(result); return; \
+ default: errx(1, "Invalid int bits"); \
} \
break; \
}
- case BinaryOp: {
- auto binop = Match(ast, BinaryOp);
+ switch (binop->op) {
+ CASE_OP(MULT, times) CASE_OP(DIVIDE, divided_by) CASE_OP(PLUS, plus) CASE_OP(MINUS, minus)
+ CASE_OP(RSHIFT, right_shifted) CASE_OP(LSHIFT, left_shifted)
+ default: break;
+ }
+#undef CASE_OP
+ } else if (t->tag == NumType) {
+#define CASE_OP(OP_NAME, C_OP) case BINOP_##OP_NAME: {\
+ double lhs = ast_to_num(env, binop->lhs); \
+ double rhs = ast_to_num(env, binop->rhs); \
+ if (Match(t, NumType)->bits == 64) \
+ *(double*)dest = (double)(lhs C_OP rhs); \
+ else \
+ *(float*)dest = (float)(lhs C_OP rhs); \
+ return; \
+ }
+ switch (binop->op) {
+ CASE_OP(MULT, *) CASE_OP(DIVIDE, /) CASE_OP(PLUS, +) CASE_OP(MINUS, -)
+ default: break;
+ }
+#undef CASE_OP
+ }
switch (binop->op) {
- CASE_OP(MULT, *) CASE_OP(DIVIDE, /) CASE_OP(PLUS, +) CASE_OP(MINUS, -)
case BINOP_EQ: case BINOP_NE: case BINOP_LT: case BINOP_LE: case BINOP_GT: case BINOP_GE: {
type_t *t_lhs = get_type(env, binop->lhs);
if (!type_eq(t_lhs, get_type(env, binop->rhs)))
@@ -431,7 +447,7 @@ void eval(env_t *env, ast_t *ast, void *dest)
}
break;
}
- default: errx(1, "Binary op not implemented: %W");
+ default: errx(1, "Binary op not implemented for %T: %W", t, ast);
}
break;
}
@@ -443,7 +459,7 @@ void eval(env_t *env, ast_t *ast, void *dest)
case ArrayType: {
array_t arr;
eval(env, index->indexed, &arr);
- int64_t raw_index = ast_to_int(env, index->index);
+ int64_t raw_index = Int$as_i64(ast_to_int(env, index->index));
int64_t index_int = raw_index;
if (index_int < 1) index_int = arr.length + index_int + 1;
if (index_int < 1 || index_int > arr.length)