🐐 Compiler fixes
This commit is contained in:
@@ -129,7 +129,7 @@ def emit_expr(node, ctx):
|
||||
if isinstance(node, UnaryMinus):
|
||||
inner_lines, inner_var = emit_expr(node.expr, ctx)
|
||||
tmp = ctx.fresh_tmp()
|
||||
return inner_lines + [f"CentValue {tmp} = cent_int(-{inner_var}.ival);"], tmp
|
||||
return inner_lines + [f"CentValue {tmp} = cent_neg({inner_var});"], tmp
|
||||
|
||||
if isinstance(node, UnaryNot):
|
||||
inner_lines, inner_var = emit_expr(node.expr, ctx)
|
||||
|
||||
@@ -92,6 +92,8 @@ def compile_program(program):
|
||||
lines.append(" cent_init();")
|
||||
if "MAGNVM" in ctx.modules:
|
||||
lines.append(" cent_magnvm = 1;")
|
||||
if "SVBNVLLA" in ctx.modules:
|
||||
lines.append(" cent_svbnvlla = 1;")
|
||||
lines.append(" CentScope _scope = {0};")
|
||||
lines.append(" CentValue _return_val = cent_null();")
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
CentArena *cent_arena;
|
||||
int cent_magnvm = 0;
|
||||
int cent_svbnvlla = 0;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Portable xorshift32 RNG (matches Python _CentRng) */
|
||||
@@ -181,7 +182,15 @@ void cent_int_to_roman(long n, char *buf, size_t bufsz) {
|
||||
if (bufsz > 6) { memcpy(buf, "NVLLVS", 6); buf[6] = '\0'; }
|
||||
return;
|
||||
}
|
||||
if (n < 0 || (n > 3999 && !cent_magnvm))
|
||||
if (n < 0) {
|
||||
if (!cent_svbnvlla)
|
||||
cent_runtime_error("number out of range for Roman numerals");
|
||||
if (bufsz < 2) cent_runtime_error("Roman numeral buffer overflow");
|
||||
buf[0] = '-';
|
||||
cent_int_to_roman(-n, buf + 1, bufsz - 1);
|
||||
return;
|
||||
}
|
||||
if (n > 3999 && !cent_magnvm)
|
||||
cent_runtime_error("number out of range for Roman numerals");
|
||||
size_t pos = 0;
|
||||
if (n > 3999) {
|
||||
@@ -271,8 +280,13 @@ static int write_val(CentValue v, char *buf, int bufsz) {
|
||||
case CENT_FRAC: {
|
||||
long num = v.fval.num, den = v.fval.den;
|
||||
if (den < 0) { num = -num; den = -den; }
|
||||
if (num < 0)
|
||||
cent_runtime_error("cannot display negative numbers without SVBNVLLA");
|
||||
int negative = 0;
|
||||
if (num < 0) {
|
||||
if (!cent_svbnvlla)
|
||||
cent_runtime_error("cannot display negative numbers without SVBNVLLA");
|
||||
negative = 1;
|
||||
num = -num;
|
||||
}
|
||||
long int_part = num / den;
|
||||
long rem_num = num % den;
|
||||
|
||||
@@ -297,11 +311,13 @@ static int write_val(CentValue v, char *buf, int bufsz) {
|
||||
for (int i = 0; i < (int)((level_int % 6) % 2); i++) frac_buf[frac_pos++] = '.';
|
||||
}
|
||||
|
||||
n = int_len + frac_pos;
|
||||
n = int_len + frac_pos + (negative ? 1 : 0);
|
||||
if (buf && n < bufsz) {
|
||||
memcpy(buf, int_buf, int_len);
|
||||
memcpy(buf + int_len, frac_buf, frac_pos);
|
||||
buf[n] = '\0';
|
||||
int pos = 0;
|
||||
if (negative) buf[pos++] = '-';
|
||||
memcpy(buf + pos, int_buf, int_len); pos += int_len;
|
||||
memcpy(buf + pos, frac_buf, frac_pos); pos += frac_pos;
|
||||
buf[pos] = '\0';
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -391,6 +407,13 @@ static void to_frac(CentValue v, long *num, long *den) {
|
||||
else { *num = v.fval.num; *den = v.fval.den; }
|
||||
}
|
||||
|
||||
CentValue cent_neg(CentValue v) {
|
||||
if (v.type == CENT_INT) return cent_int(-v.ival);
|
||||
if (v.type == CENT_FRAC) return frac_reduce(-v.fval.num, v.fval.den);
|
||||
cent_type_error("Unary minus requires a number");
|
||||
return cent_null();
|
||||
}
|
||||
|
||||
CentValue cent_add(CentValue a, CentValue b) {
|
||||
if (a.type == CENT_INT && b.type == CENT_INT)
|
||||
return cent_int(a.ival + b.ival);
|
||||
|
||||
@@ -97,6 +97,9 @@ extern CentArena *cent_arena;
|
||||
/* Set to 1 when CVM MAGNVM is active; enables extended numeral display */
|
||||
extern int cent_magnvm;
|
||||
|
||||
/* Set to 1 when CVM SVBNVLLA is active; enables negative number display */
|
||||
extern int cent_svbnvlla;
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Value constructors */
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -197,6 +200,7 @@ char *cent_make_string(CentValue v);
|
||||
/* Arithmetic and comparison operators */
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
CentValue cent_neg(CentValue v); /* unary minus: INT or FRAC */
|
||||
CentValue cent_add(CentValue a, CentValue b); /* INT+INT or FRAC+FRAC/INT */
|
||||
CentValue cent_array_concat(CentValue a, CentValue b); /* @ operator: concatenate two arrays */
|
||||
CentValue cent_concat(CentValue a, CentValue b); /* & operator: coerce all types to str */
|
||||
|
||||
Reference in New Issue
Block a user