From 7cbd20062472012caee73f6a438978be97d2ace2 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Sat, 17 Feb 2024 20:21:01 -0500 Subject: [PATCH] Clean up some binops to use generic ops --- builtins/bool.c | 2 +- compile.c | 73 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 11 deletions(-) diff --git a/builtins/bool.c b/builtins/bool.c index 9af2ed2..4efb268 100644 --- a/builtins/bool.c +++ b/builtins/bool.c @@ -26,7 +26,7 @@ public CORD Bool__as_str(const bool *b, bool colorize, const TypeInfo *type) return *b ? "yes" : "no"; } -Bool_namespace_t Bool_type = { +public Bool_namespace_t Bool_type = { .type={ .size=sizeof(bool), .align=alignof(bool), diff --git a/compile.c b/compile.c index baebede..e7617e3 100644 --- a/compile.c +++ b/compile.c @@ -56,6 +56,17 @@ CORD compile(env_t *env, ast_t *ast) auto binop = Match(ast, BinaryOp); CORD lhs = compile(env, binop->lhs); CORD rhs = compile(env, binop->rhs); + + type_t *lhs_t = get_type(env, binop->lhs); + type_t *rhs_t = get_type(env, binop->rhs); + type_t *operand_t; + if (can_promote(rhs_t, lhs_t)) + operand_t = lhs_t; + else if (can_promote(lhs_t, rhs_t)) + operand_t = rhs_t; + else + code_err(ast, "I can't do binary operations between %T and %T", lhs_t, rhs_t); + switch (binop->op) { case BINOP_MULT: return CORD_asprintf("(%r * %r)", lhs, rhs); case BINOP_DIVIDE: return CORD_asprintf("(%r / %r)", lhs, rhs); @@ -65,12 +76,54 @@ CORD compile(env_t *env, ast_t *ast) case BINOP_MINUS: return CORD_asprintf("(%r - %r)", lhs, rhs); case BINOP_LSHIFT: return CORD_asprintf("(%r << %r)", lhs, rhs); case BINOP_RSHIFT: return CORD_asprintf("(%r >> %r)", lhs, rhs); - case BINOP_EQ: return CORD_asprintf("$eq(%r, %r)", lhs, rhs); - case BINOP_NE: return CORD_asprintf("$ne(%r, %r)", lhs, rhs); - case BINOP_LT: return CORD_asprintf("$lt(%r, %r)", lhs, rhs); - case BINOP_LE: return CORD_asprintf("$le(%r, %r)", lhs, rhs); - case BINOP_GT: return CORD_asprintf("$gt(%r, %r)", lhs, rhs); - case BINOP_GE: return CORD_asprintf("$ge(%r, %r)", lhs, rhs); + case BINOP_EQ: { + switch (operand_t->tag) { + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: + return CORD_asprintf("(%r == %r)", lhs, rhs); + default: + return CORD_asprintf("generic_equal($stack(%r), $stack(%r), %r)", lhs, rhs, compile_type_info(env, operand_t)); + } + } + case BINOP_NE: { + switch (operand_t->tag) { + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: + return CORD_asprintf("(%r != %r)", lhs, rhs); + default: + return CORD_asprintf("!generic_equal($stack(%r), $stack(%r), %r)", lhs, rhs, compile_type_info(env, operand_t)); + } + } + case BINOP_LT: { + switch (operand_t->tag) { + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: + return CORD_asprintf("(%r < %r)", lhs, rhs); + default: + return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) < 0)", lhs, rhs, compile_type_info(env, operand_t)); + } + } + case BINOP_LE: { + switch (operand_t->tag) { + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: + return CORD_asprintf("(%r <= %r)", lhs, rhs); + default: + return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) <= 0)", lhs, rhs, compile_type_info(env, operand_t)); + } + } + case BINOP_GT: { + switch (operand_t->tag) { + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: + return CORD_asprintf("(%r > %r)", lhs, rhs); + default: + return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) > 0)", lhs, rhs, compile_type_info(env, operand_t)); + } + } + case BINOP_GE: { + switch (operand_t->tag) { + case BoolType: case IntType: case NumType: case PointerType: case FunctionType: + return CORD_asprintf("(%r >= %r)", lhs, rhs); + default: + return CORD_asprintf("(generic_compare($stack(%r), $stack(%r), %r) >= 0)", lhs, rhs, compile_type_info(env, operand_t)); + } + } case BINOP_AND: return CORD_asprintf("and(%r, %r)", lhs, rhs); case BINOP_OR: return CORD_asprintf("or(%r, %r)", lhs, rhs); case BINOP_XOR: return CORD_asprintf("xor(%r, %r)", lhs, rhs); @@ -432,12 +485,12 @@ CORD compile(env_t *env, ast_t *ast) CORD compile_type_info(env_t *env, type_t *t) { switch (t->tag) { - case BoolType: return "&Bool_type"; + case BoolType: return "&Bool_type.type"; case IntType: return CORD_asprintf("&Int%ld_type.type", Match(t, IntType)->bits); case NumType: return CORD_asprintf("&Num%ld_type.type", Match(t, NumType)->bits); - case StringType: return CORD_all("&", Match(t, StringType)->dsl ? Match(t, StringType)->dsl : "Str", "_type"); - case StructType: return CORD_all("&", Match(t, StructType)->name, "_type"); - case EnumType: return CORD_all("&", Match(t, EnumType)->name, "_type"); + case StringType: return CORD_all("&", Match(t, StringType)->dsl ? Match(t, StringType)->dsl : "Str", "_type.type"); + case StructType: return CORD_all("&", Match(t, StructType)->name, "_type.type"); + case EnumType: return CORD_all("&", Match(t, EnumType)->name, "_type.type"); case ArrayType: { type_t *item_t = Match(t, ArrayType)->item_type; return CORD_asprintf(