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:
parent
37c5ae6f58
commit
92aacff71a
41 changed files with 654 additions and 130 deletions
122
src/parser.c
122
src/parser.c
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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 ===
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue