fix: correct Cell union and add interpreter, main, word implementations

Co-authored-by: aider (openrouter/tencent/hy3-preview:free) <aider@aider.chat>
This commit is contained in:
2026-05-03 16:59:53 +03:00
parent 0d9b7e3424
commit e5c6fdf9d0
4 changed files with 383 additions and 2 deletions
+211 -1
View File
@@ -293,4 +293,214 @@ void do_key(Word* w) {
void do_dot_quote(Word* w) {
// Immediate word: parse string until " and print/compile
if (state == 0) { // Interpret mode: print immediately
//
if (input_ptr == NULL) {
printf("Missing string\n");
return;
}
// Skip whitespace before opening "
while (*input_ptr != '\0' && isspace((unsigned char)*input_ptr)) {
input_ptr++;
}
if (*input_ptr != '"') {
printf("Expected \" to start string\n");
return;
}
input_ptr++; // Skip opening "
char* start = input_ptr;
// Find closing "
while (*input_ptr != '\0' && *input_ptr != '"') {
input_ptr++;
}
if (*input_ptr != '"') {
printf("Unterminated string\n");
return;
}
// Print the string
while (start < input_ptr) {
putchar(*start++);
}
input_ptr++; // Skip closing "
fflush(stdout);
} else { // Compile mode: compile string for runtime
if (input_ptr == NULL) {
printf("Missing string\n");
return;
}
// Skip whitespace before opening "
while (*input_ptr != '\0' && isspace((unsigned char)*input_ptr)) {
input_ptr++;
}
if (*input_ptr != '"') {
printf("Expected \" to start string\n");
return;
}
input_ptr++; // Skip opening "
char* start = input_ptr;
// Find closing "
while (*input_ptr != '\0' && *input_ptr != '"') {
input_ptr++;
}
if (*input_ptr != '"') {
printf("Unterminated string\n");
return;
}
size_t len = input_ptr - start;
// Compile do_dot_quote_inner
Word* inner_w = lookup_word("do_dot_quote_inner");
if (inner_w == NULL) {
printf("Fatal: do_dot_quote_inner not found\n");
return;
}
if (compile_idx + 2 + len > COMPILE_BUF_SIZE) {
printf("Compile buffer full\n");
return;
}
compile_buf[compile_idx++] = (Cell){.word = inner_w};
compile_buf[compile_idx++] = (Cell){.num = (int32_t)len};
// Store string characters in compile buffer (each as a num cell)
for (size_t i = 0; i < len; i++) {
compile_buf[compile_idx++] = (Cell){.num = (int32_t)start[i]};
}
input_ptr++; // Skip closing "
}
}
void do_dot_quote_inner(Word* w) {
// Runtime: ip points to length cell, followed by string characters
int32_t len = ip->num;
ip++;
for (int32_t i = 0; i < len; i++) {
putchar((char)ip->num);
ip++;
}
fflush(stdout);
}
void do_words(Word* w) {
printf("Dictionary words:\n");
for (Word* cur = dict_head; cur != NULL; cur = cur->prev) {
if (cur->flags & (1 << 6)) continue; // Skip hidden
printf("%s ", cur->name);
}
printf("\n");
fflush(stdout);
}
// Control flow operations
void do_exit(Word* w) {
Cell* ret_addr = ret_pop_ip();
ip = ret_addr;
}
void do_docolon(Word* w) {
// Push current ip (return address) onto return stack
ret_push_ip(ip);
// Set ip to this word's body
ip = w->body;
}
void do_lit(Word* w) {
// ip points to the number cell (inner interpreter already incremented past lit word)
data_push(ip->num);
ip++; // Move past number cell
}
void do_colon(Word* w) {
char* name = next_token();
if (name == NULL) {
printf("':' expects a name\n");
return;
}
strncpy(compiling_name, name, MAX_NAME_LEN);
compiling_name[MAX_NAME_LEN] = '\0';
state = 1; // Enter compile mode
compile_idx = 0; // Reset compile buffer
}
void do_semicolon(Word* w) {
if (state != 1) {
printf("';' is only valid in compile mode\n");
return;
}
Word* exit_w = lookup_word("exit");
if (exit_w == NULL) {
printf("Fatal: exit word not found\n");
return;
}
if (compile_idx >= COMPILE_BUF_SIZE) {
printf("Compile buffer overflow\n");
return;
}
compile_buf[compile_idx++] = (Cell){.word = exit_w};
// Copy compiled body to dictionary body storage
if (body_idx + compile_idx > BODY_SIZE) {
printf("Dictionary body storage full\n");
return;
}
memcpy(&dict_bodies[body_idx], compile_buf, compile_idx * sizeof(Cell));
// Create new word entry
if (dict_idx >= DICT_SIZE) {
printf("Dictionary full\n");
return;
}
Word* new_w = &dict[dict_idx++];
new_w->prev = dict_head;
dict_head = new_w;
size_t len = strlen(compiling_name);
if (len > MAX_NAME_LEN) len = MAX_NAME_LEN;
new_w->flags = (uint8_t)len; // No hidden, no immediate
strncpy(new_w->name, compiling_name, len);
new_w->name[len] = '\0';
new_w->code = do_docolon;
new_w->body = &dict_bodies[body_idx];
body_idx += compile_idx;
state = 0; // Back to interpret mode
}
void do_branch(Word* w) {
// Unconditional branch: ip points to offset cell
int32_t offset = ip->num;
ip += offset; // Jump offset cells (offset is relative to after the offset cell)
}
void do_zero_branch(Word* w) {
// Conditional branch: if top of stack is 0, branch
int32_t cond = data_pop();
if (cond == 0) {
int32_t offset = ip->num;
ip += offset;
} else {
ip++; // Skip offset cell
}
}
// Memory operations (stubs for now)
void do_fetch(Word* w) { /* TODO */ }
void do_store(Word* w) { /* TODO */ }
void do_plus_store(Word* w) { /* TODO */ }
void do_cfetch(Word* w) { /* TODO */ }
void do_cstore(Word* w) { /* TODO */ }
void do_variable(Word* w) { /* TODO */ }
void do_constant(Word* w) { /* TODO */ }
void do_do_var(Word* w) { /* TODO */ }
void do_do_const(Word* w) { /* TODO */ }
void do_here(Word* w) { /* TODO */ }
void do_allot(Word* w) { /* TODO */ }
// Return stack operations (stubs for now)
void do_to_r(Word* w) { /* TODO */ }
void do_r_from(Word* w) { /* TODO */ }
void do_r_fetch(Word* w) { /* TODO */ }
// Additional control flow stubs
void do_if(Word* w) { /* TODO */ }
void do_else(Word* w) { /* TODO */ }
void do_then(Word* w) { /* TODO */ }
void do_begin(Word* w) { /* TODO */ }
void do_until(Word* w) { /* TODO */ }
void do_while(Word* w) { /* TODO */ }
void do_repeat(Word* w) { /* TODO */ }