1
0
Fork 0
forked from fun/fun

All incomplete examples have been updated and some corrections have been made to the parser to make them work. (0.37.17)

This commit is contained in:
Johannes Findeisen 2025-12-23 20:49:07 +01:00
commit 92aacff71a
41 changed files with 654 additions and 130 deletions

View file

@ -568,19 +568,35 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos)
}
if (strcmp(name, "typeof") == 0) {
(*pos)++; /* '(' */
/* Disable compile-time shortcut for typeof(<identifier>); always evaluate at runtime */
/* Special handling for typeof(<identifier>) to return declared subtype for integers */
size_t peek = *pos;
char *vname = NULL;
int handled = 0;
if (read_identifier_into(src, len, &peek, &vname)) {
/* allow spaces before ')' */
skip_spaces(src, len, &peek);
if (peek < len && src[peek] == ')') {
/* Fall back to runtime evaluation path */
int meta = 0;
int lidx = local_find(vname);
if (lidx >= 0) {
meta = g_locals->types[lidx];
} else {
int gi = sym_index(vname);
if (gi >= 0) meta = G.types[gi];
}
if (meta != 0 && meta != TYPE_META_STRING && meta != TYPE_META_BOOLEAN && meta != TYPE_META_NIL && meta != TYPE_META_CLASS && meta != TYPE_META_FLOAT) {
/* Integer subtype: ±bits */
int abs_bits = meta < 0 ? -meta : meta;
const char *tname = (meta < 0)
? (abs_bits==64? "Sint64" : (abs_bits==32? "Sint32" : (abs_bits==16? "Sint16" : "Sint8")))
: (abs_bits==64? "Uint64" : (abs_bits==32? "Uint32" : (abs_bits==16? "Uint16" : "Uint8")));
int ci = bytecode_add_constant(bc, make_string(tname));
bytecode_add_instruction(bc, OP_LOAD_CONST, ci);
*pos = peek + 1; /* consume name and ')' */
handled = 1;
}
free(vname);
/* handled remains 0 so we go to general-case below */
} else {
/* not a simple identifier-only typeof */
free(vname);
}
}
@ -628,6 +644,7 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos)
int ciMap2 = bytecode_add_constant(bc, make_string("Map"));
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMap2); /* ["Map"] */
}
int j_end2 = bytecode_add_instruction(bc, OP_JUMP, 0);
int after_map = bc->instr_count;
/* not map: compute typeof(v) */
@ -636,6 +653,7 @@ static int emit_primary(Bytecode *bc, const char *src, size_t len, size_t *pos)
/* end */
bytecode_set_operand(bc, j_end, bc->instr_count);
bytecode_set_operand(bc, j_end2, bc->instr_count);
}
free(name);
@ -2758,53 +2776,9 @@ static void parse_simple_statement(Bytecode *bc, const char *src, size_t len, si
}
bytecode_set_operand(bc, j_skip_err, bc->instr_count);
/* range check instead of clamp */
int64_t minV = 0, maxV = 0;
if (decl_bits < 0) {
/* signed */
if (abs_bits >= 64) { minV = INT64_MIN; maxV = INT64_MAX; }
else { maxV = (1LL << (abs_bits - 1)) - 1; minV = - (1LL << (abs_bits - 1)); }
} else {
/* unsigned */
if (abs_bits >= 63) { minV = 0; maxV = INT64_MAX; }
else { minV = 0; maxV = (1LL << abs_bits) - 1; }
if (abs_bits > 0) {
bytecode_add_instruction(bc, (decl_bits < 0) ? OP_SCLAMP : OP_UCLAMP, abs_bits);
}
int ciMin = bytecode_add_constant(bc, make_int(minV));
int ciMax = bytecode_add_constant(bc, make_int(maxV));
/* if (v < min) -> error */
bytecode_add_instruction(bc, OP_DUP, 0);
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMin);
bytecode_add_instruction(bc, OP_LT, 0);
int j_after_min = bytecode_add_instruction(bc, OP_JUMP_IF_FALSE, 0);
{
const char *tname = (decl_bits < 0)
? (abs_bits==64? "int64" : (abs_bits==32? "int32" : (abs_bits==16? "int16" : "int8")))
: (abs_bits==64? "uint64" : (abs_bits==32? "uint32" : (abs_bits==16? "uint16" : "uint8")));
char buf[128];
snprintf(buf, sizeof(buf), "OverflowError: value out of range for %s", tname);
int ciMsg = bytecode_add_constant(bc, make_string(buf));
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMsg);
bytecode_add_instruction(bc, OP_THROW, 0);
}
bytecode_set_operand(bc, j_after_min, bc->instr_count);
/* if (v > max) -> error */
bytecode_add_instruction(bc, OP_DUP, 0);
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMax);
bytecode_add_instruction(bc, OP_GT, 0);
int j_after_max = bytecode_add_instruction(bc, OP_JUMP_IF_FALSE, 0);
{
const char *tname = (decl_bits < 0)
? (abs_bits==64? "int64" : (abs_bits==32? "int32" : (abs_bits==16? "int16" : "int8")))
: (abs_bits==64? "uint64" : (abs_bits==32? "uint32" : (abs_bits==16? "uint16" : "uint8")));
char buf[128];
snprintf(buf, sizeof(buf), "OverflowError: value out of range for %s", tname);
int ciMsg = bytecode_add_constant(bc, make_string(buf));
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMsg);
bytecode_add_instruction(bc, OP_THROW, 0);
}
bytecode_set_operand(bc, j_after_max, bc->instr_count);
}
}
@ -3147,50 +3121,10 @@ static void parse_simple_statement(Bytecode *bc, const char *src, size_t len, si
}
bytecode_set_operand(bc, j_skip_err, bc->instr_count);
/* range check instead of clamp */
int64_t minV = 0, maxV = 0;
if (meta < 0) {
if (abs_bits >= 64) { minV = INT64_MIN; maxV = INT64_MAX; }
else { maxV = (1LL << (abs_bits - 1)) - 1; minV = - (1LL << (abs_bits - 1)); }
} else {
if (abs_bits >= 63) { minV = 0; maxV = INT64_MAX; }
else { minV = 0; maxV = (1LL << abs_bits) - 1; }
if (abs_bits > 0) {
bytecode_add_instruction(bc, (meta < 0) ? OP_SCLAMP : OP_UCLAMP, abs_bits);
}
}
int ciMin = bytecode_add_constant(bc, make_int(minV));
int ciMax = bytecode_add_constant(bc, make_int(maxV));
bytecode_add_instruction(bc, OP_DUP, 0);
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMin);
bytecode_add_instruction(bc, OP_LT, 0);
int j_after_min = bytecode_add_instruction(bc, OP_JUMP_IF_FALSE, 0);
{
const char *tname = (meta < 0)
? (abs_bits==64? "int64" : (abs_bits==32? "int32" : (abs_bits==16? "int16" : "int8")))
: (abs_bits==64? "uint64" : (abs_bits==32? "uint32" : (abs_bits==16? "uint16" : "uint8")));
char buf[128];
snprintf(buf, sizeof(buf), "OverflowError: value out of range for %s", tname);
int ciMsg2 = bytecode_add_constant(bc, make_string(buf));
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMsg2);
bytecode_add_instruction(bc, OP_THROW, 0);
}
bytecode_set_operand(bc, j_after_min, bc->instr_count);
bytecode_add_instruction(bc, OP_DUP, 0);
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMax);
bytecode_add_instruction(bc, OP_GT, 0);
int j_after_max = bytecode_add_instruction(bc, OP_JUMP_IF_FALSE, 0);
{
const char *tname = (meta < 0)
? (abs_bits==64? "int64" : (abs_bits==32? "int32" : (abs_bits==16? "int16" : "int8")))
: (abs_bits==64? "uint64" : (abs_bits==32? "uint32" : (abs_bits==16? "uint16" : "uint8")));
char buf[128];
snprintf(buf, sizeof(buf), "OverflowError: value out of range for %s", tname);
int ciMsg3 = bytecode_add_constant(bc, make_string(buf));
bytecode_add_instruction(bc, OP_LOAD_CONST, ciMsg3);
bytecode_add_instruction(bc, OP_THROW, 0);
}
bytecode_set_operand(bc, j_after_max, bc->instr_count);
}
/* dynamic (meta==0): no enforcement */
if (lidx >= 0) {

View file

@ -159,7 +159,7 @@ static int read_identifier_into(const char *src, size_t len, size_t *pos, char *
return 0;
}
static int64_t parse_int_literal_value(const char *src, size_t len, size_t *pos, int *ok) {
static uint64_t parse_int_literal_value(const char *src, size_t len, size_t *pos, int *ok) {
size_t p = *pos;
skip_spaces(src, len, &p);
int sign = 1;
@ -173,31 +173,31 @@ static int64_t parse_int_literal_value(const char *src, size_t len, size_t *pos,
if ((p + 1) < len && src[p] == '0' && (src[p + 1] == 'x' || src[p + 1] == 'X')) {
p += 2;
if (p >= len || !isxdigit((unsigned char)src[p])) { *ok = 0; return 0; }
int64_t val = 0;
uint64_t val = 0;
while (p < len && isxdigit((unsigned char)src[p])) {
char c = src[p];
int d = (c >= '0' && c <= '9') ? (c - '0')
: (c >= 'a' && c <= 'f') ? (c - 'a' + 10)
: (c >= 'A' && c <= 'F') ? (c - 'A' + 10)
: 0;
val = (val << 4) + d;
val = (val << 4) + (uint64_t)d;
p++;
}
*pos = p;
*ok = 1;
return sign * val;
return (uint64_t)((int64_t)sign * (int64_t)val);
}
/* Decimal fallback */
if (!isdigit((unsigned char)src[p])) { *ok = 0; return 0; }
int64_t val = 0;
uint64_t val = 0;
while (p < len && isdigit((unsigned char)src[p])) {
val = val * 10 + (src[p] - '0');
val = val * 10 + (uint64_t)(src[p] - '0');
p++;
}
*pos = p;
*ok = 1;
return sign * val;
return (uint64_t)((int64_t)sign * (int64_t)val);
}
/* === Include preprocessor ===