Files
ai-forth-experiment/forth_interp.c
T
haxala1r b115744991 fix: qdup/tuck/2swap bugs, getline, and cached word pointers
Co-authored-by: aider (openrouter/moonshotai/kimi-k2.6) <aider@aider.chat>
2026-05-03 21:39:52 +03:00

109 lines
3.0 KiB
C

#include "forth.h"
// Input tokenizer (unchanged)
char* next_token(void) {
if (input_ptr == NULL) return NULL;
while (*input_ptr != '\0' && isspace((unsigned char)*input_ptr)) {
input_ptr++;
}
if (*input_ptr == '\0') return NULL;
char* start = input_ptr;
while (*input_ptr != '\0' && !isspace((unsigned char)*input_ptr)) {
input_ptr++;
}
if (*input_ptr != '\0') {
*input_ptr = '\0';
input_ptr++;
}
return start;
}
// Ensure compile_buf has room for at least 'needed' more cells
void ensure_compile_cap(int32_t needed) {
while (compile_idx + needed > compile_cap) {
int32_t new_cap = compile_cap ? compile_cap * 2 : 256;
Cell *tmp = realloc(compile_buf, new_cap * sizeof(Cell));
if (!tmp) {
fprintf(stderr, "Out of memory\n");
exit(1);
}
compile_buf = tmp;
compile_cap = new_cap;
}
}
// Inner interpreter (unchanged)
void inner_interpreter(void) {
while (ip != NULL) {
Cell current = *ip;
ip++;
current.word->code(current.word);
}
}
void process_token(const char* token) {
Word* w = lookup_word(token);
if (w != NULL) {
if (state == 0) { // Interpret mode
if (w->code == do_docolon) {
ret_push_ip(NULL);
ip = w->body;
inner_interpreter();
} else {
w->code(w);
}
} else { // Compile mode
if (w->flags & (1 << 7)) { // Immediate word
if (w->code == do_docolon) {
ret_push_ip(NULL);
ip = w->body;
inner_interpreter();
} else {
w->code(w);
}
} else { // Compile normal word
ensure_compile_cap(1);
compile_buf[compile_idx++] = (Cell){.word = w};
}
}
} else { // Try to parse as number
char* end;
long long v = strtoll(token, &end, 10);
if (end != token && *end == '\0') {
if (state == 0) {
data_push((int64_t)v);
} else { // Compile lit + number
if (!w_lit) {
fprintf(stderr, "Fatal: lit word not found\n");
return;
}
ensure_compile_cap(2);
compile_buf[compile_idx++] = (Cell){.word = w_lit};
compile_buf[compile_idx++] = (Cell){.num = (int64_t)v};
}
} else {
printf("Unknown word: '%s'\n", token);
}
}
}
void outer_interpreter(void) {
while (1) {
printf("ok ");
fflush(stdout);
ssize_t n = getline(&input_buf, &input_buf_cap, stdin);
if (n < 0) {
break;
}
if (n > 0 && input_buf[n - 1] == '\n') {
input_buf[n - 1] = '\0';
}
input_ptr = input_buf;
char* tok;
while ((tok = next_token()) != NULL) {
process_token(tok);
}
}
printf("\n");
}