#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 Word* lit_w = lookup_word_internal("lit"); if (!lit_w) { fprintf(stderr, "Fatal: lit word not found\n"); return; } ensure_compile_cap(2); compile_buf[compile_idx++] = (Cell){.word = lit_w}; 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); if (fgets(input_buf, sizeof(input_buf), stdin) == NULL) { break; } input_ptr = input_buf; char* tok; while ((tok = next_token()) != NULL) { process_token(tok); } } printf("\n"); }