Compiler: READ arrays, PRINT USING colon fix, array assign fix — 41/72

READ into array elements: parse subscripts after variable name in READ
handler, call gwrt_array_elem + gwrt_data_read. Unlocks matrix_mult,
roman_numerals (partial).

PRINT USING colon-in-string: scan past quoted strings when finding
statement-end colon for token embedding. Fixes truncated format strings
like "Pi estimate: #.####".

Array element assignment: don't zero element before RHS evaluation.
Previous code did `*_elem = {.type=4}` which zeroed fval before
reading C(I,J) in `C(I,J) = C(I,J) + A(I,K)*B(K,J)`, making
self-referencing assignments always read 0.

DEF FN call fix: skip past TOK_FN byte before calling gw_eval_fn_call.

DEFINT pre-scan: analysis pass processes DEFINT/DEFSNG/DEFDBL/DEFSTR
before variable type resolution.

Integer assignment rounding: use gw_cint() (rint) instead of (int16_t)
C truncation.

41/72 tests pass. 0 compile errors.
New: hundred_doors, matrix_mult, pascal_triangle, stats_calc.
This commit is contained in:
Eremey Valetov
2026-03-29 14:53:02 -04:00
parent e6a6bddb26
commit 1dcc39f45b

View File

@@ -1019,9 +1019,9 @@ static void emit_assignment(void)
emit_str_expr();
EMIT(";\n _elem->type = VT_STR;\n");
} else {
EMIT(" *_elem = (gw_value_t){.type=%d};\n", type);
EMIT(" _elem->type = %d;\n", type);
switch (type) {
case VT_INT: EMIT(" _elem->ival = (int16_t)("); break;
case VT_INT: EMIT(" _elem->ival = gw_cint((double)("); break;
case VT_SNG: EMIT(" _elem->fval = (float)("); break;
case VT_DBL: EMIT(" _elem->dval = (double)("); break;
default: EMIT(" _elem->fval = (float)("); break;
@@ -1086,7 +1086,12 @@ static void emit_stmt(void)
/* Skip past USING token, then embed remaining bytes */
advance(); /* skip TOK_USING */
uint8_t *start = tp;
while (*tp && *tp != ':') tp++;
/* Scan to end of statement, skipping string literals */
while (*tp) {
if (*tp == '"') { tp++; while (*tp && *tp != '"') tp++; if (*tp) tp++; continue; }
if (*tp == ':') break;
tp++;
}
int len = (int)(tp - start);
/* Sync compiled variables to interpreter table so gw_eval works */
EMIT(" {\n");
@@ -1760,7 +1765,38 @@ static void emit_stmt(void)
if (is_letter(cur())) {
char name[2];
gw_valtype_t type = parse_var(name);
if (type == VT_STR) {
skip_spaces();
if (cur() == '(') {
/* READ into array element */
advance();
char *sbufs[8]; int nd = 0;
do {
if (nd > 0 && cur() == ',') advance();
sbufs[nd++] = emit_to_buf(emit_prec_wrapper, 0);
} while (cur() == ',' && nd < 8);
if (cur() == ')') advance();
EMIT(" { gw_value_t *_re = gwrt_array_elem(");
emit_name_str(name);
EMIT(", %d, %d, (int[]){", type, nd);
for (int d = 0; d < nd; d++) {
if (d > 0) EMIT(",");
EMIT("(int)(%s)", sbufs[d]);
free(sbufs[d]);
}
EMIT("});\n");
if (type == VT_STR) {
EMIT(" gw_str_free(&_re->sval);\n");
EMIT(" _re->sval = gw_str_from_cstr(gwrt_data_read());\n");
EMIT(" _re->type = VT_STR; }\n");
} else {
EMIT(" _re->type = %d;\n", type);
switch (type) {
case VT_INT: EMIT(" _re->ival = (int16_t)atof(gwrt_data_read()); }\n"); break;
case VT_DBL: EMIT(" _re->dval = atof(gwrt_data_read()); }\n"); break;
default: EMIT(" _re->fval = (float)atof(gwrt_data_read()); }\n"); break;
}
}
} else if (type == VT_STR) {
EMIT(" gw_str_free(&");
emit_varname(name, type);
EMIT(");\n");
@@ -1770,7 +1806,10 @@ static void emit_stmt(void)
} else {
EMIT(" ");
emit_varname(name, type);
EMIT(" = (%s)atof(gwrt_data_read());\n", c_type(type));
if (type == VT_INT)
EMIT(" = (int16_t)atof(gwrt_data_read());\n");
else
EMIT(" = (%s)atof(gwrt_data_read());\n", c_type(type));
}
}
skip_spaces();