🐐 Compiler fix
This commit is contained in:
@@ -380,7 +380,9 @@ static long gcd(long a, long b) {
|
|||||||
static CentValue frac_reduce(long num, long den) {
|
static CentValue frac_reduce(long num, long den) {
|
||||||
if (den < 0) { num = -num; den = -den; }
|
if (den < 0) { num = -num; den = -den; }
|
||||||
long g = gcd(num < 0 ? -num : num, den);
|
long g = gcd(num < 0 ? -num : num, den);
|
||||||
return cent_frac(num / g, den / g);
|
num /= g; den /= g;
|
||||||
|
if (den == 1) return cent_int(num);
|
||||||
|
return cent_frac(num, den);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void to_frac(CentValue v, long *num, long *den) {
|
static void to_frac(CentValue v, long *num, long *den) {
|
||||||
@@ -445,11 +447,16 @@ CentValue cent_mul(CentValue a, CentValue b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CentValue cent_div(CentValue a, CentValue b) {
|
CentValue cent_div(CentValue a, CentValue b) {
|
||||||
|
if (a.type == CENT_NULL) a = cent_int(0);
|
||||||
|
if (b.type == CENT_NULL) b = cent_int(0);
|
||||||
if (a.type != CENT_INT || b.type != CENT_INT)
|
if (a.type != CENT_INT || b.type != CENT_INT)
|
||||||
cent_type_error("'/' requires two integers");
|
cent_type_error("'/' requires two integers");
|
||||||
if (b.ival == 0)
|
if (b.ival == 0)
|
||||||
cent_runtime_error("division by zero");
|
cent_runtime_error("division by zero");
|
||||||
return cent_int(a.ival / b.ival);
|
/* floored division (Python // semantics) */
|
||||||
|
long q = a.ival / b.ival;
|
||||||
|
if ((a.ival % b.ival != 0) && ((a.ival < 0) != (b.ival < 0))) q -= 1;
|
||||||
|
return cent_int(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
CentValue cent_div_frac(CentValue a, CentValue b) {
|
CentValue cent_div_frac(CentValue a, CentValue b) {
|
||||||
@@ -460,11 +467,16 @@ CentValue cent_div_frac(CentValue a, CentValue b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
CentValue cent_mod(CentValue a, CentValue b) {
|
CentValue cent_mod(CentValue a, CentValue b) {
|
||||||
|
if (a.type == CENT_NULL) a = cent_int(0);
|
||||||
|
if (b.type == CENT_NULL) b = cent_int(0);
|
||||||
if (a.type != CENT_INT || b.type != CENT_INT)
|
if (a.type != CENT_INT || b.type != CENT_INT)
|
||||||
cent_type_error("'RELIQVVM' requires two integers");
|
cent_type_error("'RELIQVVM' requires two integers");
|
||||||
if (b.ival == 0)
|
if (b.ival == 0)
|
||||||
cent_runtime_error("modulo by zero");
|
cent_runtime_error("modulo by zero");
|
||||||
return cent_int(a.ival % b.ival);
|
/* floored modulo (Python % semantics) */
|
||||||
|
long r = a.ival % b.ival;
|
||||||
|
if (r != 0 && ((a.ival < 0) != (b.ival < 0))) r += b.ival;
|
||||||
|
return cent_int(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
CentValue cent_mod_frac(CentValue a, CentValue b) {
|
CentValue cent_mod_frac(CentValue a, CentValue b) {
|
||||||
|
|||||||
13
tests.py
13
tests.py
@@ -689,6 +689,8 @@ error_tests = [
|
|||||||
("CVM SVBNVLLA\n[I, II][-I]", CentvrionError), # negative index
|
("CVM SVBNVLLA\n[I, II][-I]", CentvrionError), # negative index
|
||||||
("[I, II][-I]", CentvrionError), # negative value
|
("[I, II][-I]", CentvrionError), # negative value
|
||||||
("I / NVLLVS", CentvrionError), # division by zero (NVLLVS coerces to 0)
|
("I / NVLLVS", CentvrionError), # division by zero (NVLLVS coerces to 0)
|
||||||
|
("V RELIQVVM NVLLVS", CentvrionError), # modulo by zero (NVLLVS coerces to 0)
|
||||||
|
("NVLLVS RELIQVVM NVLLVS", CentvrionError), # modulo by zero (both NVLLVS)
|
||||||
("I / [I, II]", CentvrionError), # division with array operand
|
("I / [I, II]", CentvrionError), # division with array operand
|
||||||
("I - \"hello\"", CentvrionError), # subtraction with string
|
("I - \"hello\"", CentvrionError), # subtraction with string
|
||||||
("I * \"hello\"", CentvrionError), # multiplication with string
|
("I * \"hello\"", CentvrionError), # multiplication with string
|
||||||
@@ -990,6 +992,17 @@ arithmetic_edge_tests = [
|
|||||||
("NVLLVS + NVLLVS", Program([], [ExpressionStatement(BinOp(Nullus(), Nullus(), "SYMBOL_PLUS"))]), ValNul()),
|
("NVLLVS + NVLLVS", Program([], [ExpressionStatement(BinOp(Nullus(), Nullus(), "SYMBOL_PLUS"))]), ValNul()),
|
||||||
("NVLLVS - V", Program([], [ExpressionStatement(BinOp(Nullus(), Numeral("V"), "SYMBOL_MINUS"))]), ValInt(-5)),
|
("NVLLVS - V", Program([], [ExpressionStatement(BinOp(Nullus(), Numeral("V"), "SYMBOL_MINUS"))]), ValInt(-5)),
|
||||||
("V - NVLLVS", Program([], [ExpressionStatement(BinOp(Numeral("V"), Nullus(), "SYMBOL_MINUS"))]), ValInt(5)),
|
("V - NVLLVS", Program([], [ExpressionStatement(BinOp(Numeral("V"), Nullus(), "SYMBOL_MINUS"))]), ValInt(5)),
|
||||||
|
# NVLLVS coerces to 0 in modulo and division
|
||||||
|
("NVLLVS RELIQVVM V", Program([], [ExpressionStatement(BinOp(Nullus(), Numeral("V"), "KEYWORD_RELIQVVM"))]), ValInt(0)),
|
||||||
|
("NVLLVS / V", Program([], [ExpressionStatement(BinOp(Nullus(), Numeral("V"), "SYMBOL_DIVIDE"))]), ValInt(0)),
|
||||||
|
# floored division and modulo with negative operands (Python semantics)
|
||||||
|
("CVM SVBNVLLA\n- VII RELIQVVM III", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BinOp(UnaryMinus(Numeral("VII")), Numeral("III"), "KEYWORD_RELIQVVM"))]), ValInt(2)),
|
||||||
|
("CVM SVBNVLLA\nVII RELIQVVM - III", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BinOp(Numeral("VII"), UnaryMinus(Numeral("III")), "KEYWORD_RELIQVVM"))]), ValInt(-2)),
|
||||||
|
("CVM SVBNVLLA\n- VII RELIQVVM - III", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BinOp(UnaryMinus(Numeral("VII")), UnaryMinus(Numeral("III")), "KEYWORD_RELIQVVM"))]), ValInt(-1)),
|
||||||
|
("CVM SVBNVLLA\n- VII / III", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BinOp(UnaryMinus(Numeral("VII")), Numeral("III"), "SYMBOL_DIVIDE"))]), ValInt(-3)),
|
||||||
|
("CVM SVBNVLLA\nVII / - III", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BinOp(Numeral("VII"), UnaryMinus(Numeral("III")), "SYMBOL_DIVIDE"))]), ValInt(-3)),
|
||||||
|
("CVM SVBNVLLA\n- VII / - III", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BinOp(UnaryMinus(Numeral("VII")), UnaryMinus(Numeral("III")), "SYMBOL_DIVIDE"))]), ValInt(2)),
|
||||||
|
("CVM SVBNVLLA\n- L RELIQVVM C", Program([ModuleCall("SVBNVLLA")], [ExpressionStatement(BinOp(UnaryMinus(Numeral("L")), Numeral("C"), "KEYWORD_RELIQVVM"))]), ValInt(50)),
|
||||||
]
|
]
|
||||||
|
|
||||||
class TestArithmeticEdge(unittest.TestCase):
|
class TestArithmeticEdge(unittest.TestCase):
|
||||||
|
|||||||
Reference in New Issue
Block a user