aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruce Hill <bruce@bruce-hill.com>2024-11-03 15:15:03 -0500
committerBruce Hill <bruce@bruce-hill.com>2024-11-03 15:15:03 -0500
commitf656c9eb26154c206915f5f643d88f805315d3b0 (patch)
tree226dadba169435d74713905a972c0df6749978b1
parent87176ead2de2b0eb396d75555b3ed2bd5783ce8d (diff)
Better error messaging for binops and support for bit shifting by an
integer literal (without a bit size)
-rw-r--r--compile.c31
1 files changed, 22 insertions, 9 deletions
diff --git a/compile.c b/compile.c
index 91abbef8..e226668f 100644
--- a/compile.c
+++ b/compile.c
@@ -2049,8 +2049,21 @@ CORD compile(env_t *env, ast_t *ast)
}
CORD lhs = compile(env, binop->lhs);
+
+ // Special case for bit shifting by an integer literal:
+ if (binop->op == BINOP_LSHIFT || binop->op == BINOP_RSHIFT) {
+ if (lhs_t->tag == IntType && rhs_t->tag == BigIntType && binop->rhs->tag == Int) {
+ CORD shift_amount = compile_int_to_type(env, binop->rhs, lhs_t);
+ if (binop->op == BINOP_LSHIFT)
+ return CORD_all("(", lhs, " << ", shift_amount, ")");
+ else
+ return CORD_all("(", lhs, " >> ", shift_amount, ")");
+ }
+ }
+
CORD rhs = compile(env, binop->rhs);
type_t *operand_t;
+
if (promote(env, &rhs, rhs_t, lhs_t))
operand_t = lhs_t;
else if (promote(env, &lhs, lhs_t, rhs_t))
@@ -2061,7 +2074,7 @@ CORD compile(env_t *env, ast_t *ast)
switch (binop->op) {
case BINOP_POWER: {
if (operand_t->tag != NumType)
- code_err(ast, "Exponentiation is only supported for Num types");
+ code_err(ast, "Exponentiation is only supported for Num types, not %T", operand_t);
if (operand_t->tag == NumType && Match(operand_t, NumType)->bits == TYPE_NBITS32)
return CORD_all("powf(", lhs, ", ", rhs, ")");
else
@@ -2069,42 +2082,42 @@ CORD compile(env_t *env, ast_t *ast)
}
case BINOP_MULT: {
if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType)
- code_err(ast, "Math operations are only supported for numeric types");
+ code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t);
return CORD_all("(", lhs, " * ", rhs, ")");
}
case BINOP_DIVIDE: {
if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType)
- code_err(ast, "Math operations are only supported for numeric types");
+ code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t);
return CORD_all("(", lhs, " / ", rhs, ")");
}
case BINOP_MOD: {
if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType)
- code_err(ast, "Math operations are only supported for numeric types");
+ code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t);
return CORD_all("(", lhs, " % ", rhs, ")");
}
case BINOP_MOD1: {
if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType)
- code_err(ast, "Math operations are only supported for numeric types");
+ code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t);
return CORD_all("((((", lhs, ")-1) % (", rhs, ")) + 1)");
}
case BINOP_PLUS: {
if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType)
- code_err(ast, "Math operations are only supported for numeric types");
+ code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t);
return CORD_all("(", lhs, " + ", rhs, ")");
}
case BINOP_MINUS: {
if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType)
- code_err(ast, "Math operations are only supported for numeric types");
+ code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t);
return CORD_all("(", lhs, " - ", rhs, ")");
}
case BINOP_LSHIFT: {
if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType)
- code_err(ast, "Math operations are only supported for numeric types");
+ code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t);
return CORD_all("(", lhs, " << ", rhs, ")");
}
case BINOP_RSHIFT: {
if (operand_t->tag != IntType && operand_t->tag != NumType && operand_t->tag != ByteType)
- code_err(ast, "Math operations are only supported for numeric types");
+ code_err(ast, "Math operations are only supported for values of the same numeric type, not %T vs %T", lhs_t, rhs_t);
return CORD_all("(", lhs, " >> ", rhs, ")");
}
case BINOP_EQ: {