diff --git a/forth.h b/forth.h index c2a50c4..1e6f1f7 100644 --- a/forth.h +++ b/forth.h @@ -8,81 +8,76 @@ #include #include -// Configuration -#define DATA_STACK_SIZE 256 -#define RET_STACK_SIZE 256 -#define DICT_SIZE 256 -#define BODY_SIZE 1024 -#define COMPILE_BUF_SIZE 1024 -#define INPUT_BUF_SIZE 256 +// Configuration (all hard limits removed) #define MAX_NAME_LEN 31 -#define COMPILE_STACK_SIZE 256 -#define USER_MEMORY_SIZE 1024 // Core types typedef struct Word Word; typedef union Cell { Word* word; - int32_t num; - union Cell* cell_ptr; // Use union tag here, as typedef Cell is not available yet + int64_t num; + void* ptr; // used for return stack (holds Cell*) } Cell; struct Word { Word* prev; - uint8_t flags; // Bit7=immediate, Bit6=hidden, Bits0-5=name length + uint8_t flags; // Bit7=immediate, Bit6=hidden, Bits0-5=name length char name[MAX_NAME_LEN + 1]; void (*code)(Word*); - Cell* body; + Cell* body; // points to the word’s body (allocated dynamically) }; -// Globals -extern int32_t data_stack[DATA_STACK_SIZE]; -extern int sp; -extern Cell ret_stack[RET_STACK_SIZE]; -extern int rp; -extern Cell* ip; +// Globals (all dynamic) +extern int64_t *data_stack; +extern int32_t data_sp; // stack indices are small enough for int32_t +extern int32_t data_cap; + +extern Cell *ret_stack; +extern int32_t rp; +extern int32_t ret_cap; +extern Cell* ip; // instruction pointer -extern Word dict[DICT_SIZE]; -extern int dict_idx; extern Word* dict_head; -extern Cell dict_bodies[BODY_SIZE]; -extern int body_idx; -extern int state; // 0=interpret, 1=compile -extern Cell compile_buf[COMPILE_BUF_SIZE]; -extern int compile_idx; +extern int state; +extern Cell *compile_buf; +extern int32_t compile_idx; +extern int32_t compile_cap; extern char compiling_name[MAX_NAME_LEN + 1]; -extern char input_buf[INPUT_BUF_SIZE]; +extern char input_buf[1024]; // fixed for line input extern char* input_ptr; -extern Cell* compile_stack[COMPILE_STACK_SIZE]; -extern int compile_sp; +extern int64_t *compile_stack; // holds indices into compile_buf +extern int32_t compile_sp; +extern int32_t compile_stack_cap; -extern int32_t user_mem[USER_MEMORY_SIZE]; -extern int32_t* here; +extern Cell *user_mem; +extern int64_t user_mem_size; // in cells +extern Cell* here; // Core function prototypes -void data_push(int32_t val); -int32_t data_pop(void); +void data_push(int64_t val); +int64_t data_pop(void); void ret_push_ip(Cell* val); Cell* ret_pop_ip(void); -void ret_push_num(int32_t val); -int32_t ret_pop_num(void); -void compile_push(Cell* addr); -Cell* compile_pop(void); +void ret_push_num(int64_t val); +int64_t ret_pop_num(void); +void compile_push(int64_t idx); +int64_t compile_pop(void); Word* add_primitive(const char* name, void (*code)(Word*), uint8_t flags); Word* lookup_word(const char* name); Word* lookup_word_internal(const char* name); char* next_token(void); - void inner_interpreter(void); void process_token(const char* token); void outer_interpreter(void); -// Primitive word prototypes +// Ensure compile_buf has at least 'needed' free cells +void ensure_compile_cap(int32_t needed); + // Stack ops void do_dup(Word* w); void do_drop(Word* w); @@ -171,4 +166,4 @@ void do_until(Word* w); void do_while(Word* w); void do_repeat(Word* w); -#endif // FORTH_H +#endif diff --git a/forth_core.c b/forth_core.c index cbe373f..29f5fa1 100644 --- a/forth_core.c +++ b/forth_core.c @@ -1,103 +1,122 @@ #include "forth.h" -// Global variables -int32_t data_stack[DATA_STACK_SIZE]; -int sp = -1; -Cell ret_stack[RET_STACK_SIZE]; -int rp = -1; +// Dynamic storage +int64_t *data_stack = NULL; +int32_t data_sp = -1; +int32_t data_cap = 0; + +Cell *ret_stack = NULL; +int32_t rp = -1; +int32_t ret_cap = 0; Cell* ip = NULL; -Word dict[DICT_SIZE]; -int dict_idx = 0; Word* dict_head = NULL; -Cell dict_bodies[BODY_SIZE]; -int body_idx = 0; int state = 0; -Cell compile_buf[COMPILE_BUF_SIZE]; -int compile_idx = 0; -char compiling_name[MAX_NAME_LEN + 1]; +Cell *compile_buf = NULL; +int32_t compile_idx = 0; +int32_t compile_cap = 0; +char compiling_name[MAX_NAME_LEN + 1] = {0}; -char input_buf[INPUT_BUF_SIZE]; +char input_buf[1024] = {0}; char* input_ptr = NULL; -Cell* compile_stack[COMPILE_STACK_SIZE]; -int compile_sp = -1; +int64_t *compile_stack = NULL; +int32_t compile_sp = -1; +int32_t compile_stack_cap = 0; -int32_t user_mem[USER_MEMORY_SIZE]; -int32_t* here = &user_mem[0]; +Cell *user_mem = NULL; +int64_t user_mem_size = 0; +Cell* here = NULL; -// Stack helpers -void data_push(int32_t val) { - if (sp < DATA_STACK_SIZE - 1) { - data_stack[++sp] = val; - } else { - printf("Data stack overflow\n"); +// ---------- Data stack ---------- +void data_push(int64_t val) { + if (data_sp + 1 >= data_cap) { + int32_t new_cap = data_cap ? data_cap * 2 : 128; + int64_t *tmp = realloc(data_stack, new_cap * sizeof(int64_t)); + if (!tmp) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + data_stack = tmp; + data_cap = new_cap; } + data_stack[++data_sp] = val; } -int32_t data_pop(void) { - if (sp >= 0) { - return data_stack[sp--]; - } else { - printf("Data stack underflow\n"); +int64_t data_pop(void) { + if (data_sp < 0) { + fprintf(stderr, "Data stack underflow\n"); return 0; } + return data_stack[data_sp--]; +} + +// ---------- Return stack (holds Cell values) ---------- +static void ensure_ret_stack(void) { + if (rp + 1 >= ret_cap) { + int32_t new_cap = ret_cap ? ret_cap * 2 : 128; + Cell *tmp = realloc(ret_stack, new_cap * sizeof(Cell)); + if (!tmp) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + ret_stack = tmp; + ret_cap = new_cap; + } } void ret_push_ip(Cell* val) { - if (rp < RET_STACK_SIZE - 1) { - rp++; - ret_stack[rp].cell_ptr = val; - } else { - printf("Return stack overflow\n"); - } + ensure_ret_stack(); + rp++; + ret_stack[rp].ptr = val; // store pointer in the 'ptr' member } Cell* ret_pop_ip(void) { - if (rp >= 0) { - Cell* res = ret_stack[rp].cell_ptr; - rp--; - return res; - } else { - printf("Return stack underflow\n"); + if (rp < 0) { + fprintf(stderr, "Return stack underflow\n"); return NULL; } + return ret_stack[rp--].ptr; } -void ret_push_num(int32_t val) { - if (rp < RET_STACK_SIZE - 1) { - rp++; - ret_stack[rp].num = val; - } else { - printf("Return stack overflow\n"); - } +void ret_push_num(int64_t val) { + ensure_ret_stack(); + rp++; + ret_stack[rp].num = val; } -int32_t ret_pop_num(void) { - if (rp >= 0) { - int32_t res = ret_stack[rp].num; - rp--; - return res; - } else { - printf("Return stack underflow\n"); +int64_t ret_pop_num(void) { + if (rp < 0) { + fprintf(stderr, "Return stack underflow (num)\n"); return 0; } + return ret_stack[rp--].num; } -void compile_push(Cell* addr) { - if (compile_sp < COMPILE_STACK_SIZE - 1) { - compile_stack[++compile_sp] = addr; - } else { - printf("Compile stack overflow\n"); +// ---------- Compile stack (indices) ---------- +static void ensure_compile_stack(void) { + if (compile_sp + 1 >= compile_stack_cap) { + int32_t new_cap = compile_stack_cap ? compile_stack_cap * 2 : 64; + int64_t *tmp = realloc(compile_stack, new_cap * sizeof(int64_t)); + if (!tmp) { + fprintf(stderr, "Out of memory\n"); + exit(1); + } + compile_stack = tmp; + compile_stack_cap = new_cap; } } -Cell* compile_pop(void) { - if (compile_sp >= 0) { - return compile_stack[compile_sp--]; - } else { - printf("Compile stack underflow\n"); - return NULL; - } +void compile_push(int64_t idx) { + ensure_compile_stack(); + compile_stack[++compile_sp] = idx; +} + +int64_t compile_pop(void) { + if (compile_sp < 0) { + fprintf(stderr, "Compile stack underflow\n"); + return -1; + } + return compile_stack[compile_sp--]; } diff --git a/forth_dict.c b/forth_dict.c index eeeb6aa..bf70764 100644 --- a/forth_dict.c +++ b/forth_dict.c @@ -1,11 +1,11 @@ #include "forth.h" Word* add_primitive(const char* name, void (*code)(Word*), uint8_t flags) { - if (dict_idx >= DICT_SIZE) { - printf("Dictionary full\n"); - return NULL; + Word* w = malloc(sizeof(Word)); + if (!w) { + fprintf(stderr, "Out of memory\n"); + exit(1); } - Word* w = &dict[dict_idx++]; w->prev = dict_head; dict_head = w; @@ -21,7 +21,7 @@ Word* add_primitive(const char* name, void (*code)(Word*), uint8_t flags) { Word* lookup_word(const char* name) { for (Word* w = dict_head; w != NULL; w = w->prev) { - if (w->flags & (1 << 6)) continue; // Skip hidden words + if (w->flags & (1 << 6)) continue; if (strcmp(w->name, name) == 0) return w; } return NULL; diff --git a/forth_interp.c b/forth_interp.c index 7614c74..ee1ef63 100644 --- a/forth_interp.c +++ b/forth_interp.c @@ -1,6 +1,6 @@ #include "forth.h" -// Input tokenizer +// Input tokenizer (unchanged) char* next_token(void) { if (input_ptr == NULL) return NULL; while (*input_ptr != '\0' && isspace((unsigned char)*input_ptr)) { @@ -18,11 +18,25 @@ char* next_token(void) { return start; } -// Interpreter functions +// 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++; // Move to next cell + ip++; current.word->code(current.word); } } @@ -31,15 +45,15 @@ void process_token(const char* token) { Word* w = lookup_word(token); if (w != NULL) { if (state == 0) { // Interpret mode - if (w->code == do_docolon) { // Colon definition - ret_push_ip(NULL); // Return address to stop interpreter + if (w->code == do_docolon) { + ret_push_ip(NULL); ip = w->body; inner_interpreter(); - } else { // Primitive word + } else { w->code(w); } } else { // Compile mode - if (w->flags & (1 << 7)) { // Immediate word: execute now + if (w->flags & (1 << 7)) { // Immediate word if (w->code == do_docolon) { ret_push_ip(NULL); ip = w->body; @@ -47,32 +61,26 @@ void process_token(const char* token) { } else { w->code(w); } - } else { // Normal word: compile into current definition - if (compile_idx >= COMPILE_BUF_SIZE) { - printf("Compile buffer full\n"); - return; - } + } else { // Compile normal word + ensure_compile_cap(1); compile_buf[compile_idx++] = (Cell){.word = w}; } } - } else { // Not a known word: try to parse as number + } else { // Try to parse as number char* end; - long v = strtol(token, &end, 10); - if (end != token && *end == '\0') { // Valid integer - if (state == 0) { // Interpret mode: push number - data_push((int32_t)v); - } else { // Compile mode: compile lit + number + 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 == NULL) { - printf("Fatal: lit word not found\n"); - return; - } - if (compile_idx + 2 > COMPILE_BUF_SIZE) { - printf("Compile buffer full\n"); + 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 = (int32_t)v}; + compile_buf[compile_idx++] = (Cell){.num = (int64_t)v}; } } else { printf("Unknown word: '%s'\n", token); @@ -84,8 +92,8 @@ void outer_interpreter(void) { while (1) { printf("ok "); fflush(stdout); - if (fgets(input_buf, INPUT_BUF_SIZE, stdin) == NULL) { - break; // EOF + if (fgets(input_buf, sizeof(input_buf), stdin) == NULL) { + break; } input_ptr = input_buf; char* tok; diff --git a/forth_words.c b/forth_words.c index 2093b09..523e392 100644 --- a/forth_words.c +++ b/forth_words.c @@ -3,8 +3,8 @@ // Stack operations void do_dup(Word* w) { (void)w; - if (sp < 0) return; - int32_t v = data_stack[sp]; + if (data_sp < 0) return; + int64_t v = data_stack[data_sp]; data_push(v); } @@ -15,87 +15,87 @@ void do_drop(Word* w) { void do_swap(Word* w) { (void)w; - if (sp < 1) return; - int32_t a = data_stack[sp-1]; - int32_t b = data_stack[sp]; - data_stack[sp-1] = b; - data_stack[sp] = a; + if (data_sp < 1) return; + int64_t a = data_stack[data_sp-1]; + int64_t b = data_stack[data_sp]; + data_stack[data_sp-1] = b; + data_stack[data_sp] = a; } void do_over(Word* w) { (void)w; - if (sp < 1) return; - data_push(data_stack[sp-1]); + if (data_sp < 1) return; + data_push(data_stack[data_sp-1]); } void do_rot(Word* w) { (void)w; - if (sp < 2) return; - int32_t a = data_stack[sp-2]; - int32_t b = data_stack[sp-1]; - int32_t c = data_stack[sp]; - data_stack[sp-2] = c; - data_stack[sp-1] = a; - data_stack[sp] = b; + if (data_sp < 2) return; + int64_t a = data_stack[data_sp-2]; + int64_t b = data_stack[data_sp-1]; + int64_t c = data_stack[data_sp]; + data_stack[data_sp-2] = c; + data_stack[data_sp-1] = a; + data_stack[data_sp] = b; } void do_minus_rot(Word* w) { (void)w; - if (sp < 2) return; - int32_t a = data_stack[sp-2]; - int32_t b = data_stack[sp-1]; - int32_t c = data_stack[sp]; - data_stack[sp-2] = b; - data_stack[sp-1] = c; - data_stack[sp] = a; + if (data_sp < 2) return; + int64_t a = data_stack[data_sp-2]; + int64_t b = data_stack[data_sp-1]; + int64_t c = data_stack[data_sp]; + data_stack[data_sp-2] = b; + data_stack[data_sp-1] = c; + data_stack[data_sp] = a; } void do_nip(Word* w) { (void)w; - if (sp < 1) return; - data_stack[sp-1] = data_stack[sp]; - sp--; + if (data_sp < 1) return; + data_stack[data_sp-1] = data_stack[data_sp]; + data_sp--; } void do_tuck(Word* w) { (void)w; - if (sp < 1) return; - int32_t a = data_stack[sp-1]; - int32_t b = data_stack[sp]; + if (data_sp < 1) return; + int64_t a = data_stack[data_sp-1]; + int64_t b = data_stack[data_sp]; data_push(a); - data_stack[sp-2] = b; + data_stack[data_sp-2] = b; } -// Arithmetic operations +// Arithmetic void do_add(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a + b); } void do_sub(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a - b); } void do_mul(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a * b); } void do_div(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); if (b == 0) { printf("Division by zero\n"); data_push(a); @@ -107,9 +107,9 @@ void do_div(Word* w) { void do_mod(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); if (b == 0) { printf("Modulo by zero\n"); data_push(a); @@ -121,9 +121,9 @@ void do_mod(Word* w) { void do_slash_mod(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); if (b == 0) { printf("Modulo by zero\n"); data_push(a); @@ -136,179 +136,179 @@ void do_slash_mod(Word* w) { void do_one_plus(Word* w) { (void)w; - if (sp < 0) return; - data_stack[sp]++; + if (data_sp < 0) return; + data_stack[data_sp]++; } void do_one_minus(Word* w) { (void)w; - if (sp < 0) return; - data_stack[sp]--; + if (data_sp < 0) return; + data_stack[data_sp]--; } void do_two_plus(Word* w) { (void)w; - if (sp < 0) return; - data_stack[sp] += 2; + if (data_sp < 0) return; + data_stack[data_sp] += 2; } void do_two_minus(Word* w) { (void)w; - if (sp < 0) return; - data_stack[sp] -= 2; + if (data_sp < 0) return; + data_stack[data_sp] -= 2; } void do_negate(Word* w) { (void)w; - if (sp < 0) return; - data_stack[sp] = -data_stack[sp]; + if (data_sp < 0) return; + data_stack[data_sp] = -data_stack[data_sp]; } void do_abs(Word* w) { (void)w; - if (sp < 0) return; - int32_t v = data_pop(); + if (data_sp < 0) return; + int64_t v = data_pop(); data_push(v < 0 ? -v : v); } void do_min(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a < b ? a : b); } void do_max(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a > b ? a : b); } -// Logic operations +// Logic void do_and(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a & b); } void do_or(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a | b); } void do_xor(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a ^ b); } void do_invert(Word* w) { (void)w; - if (sp < 0) return; - data_stack[sp] = ~data_stack[sp]; + if (data_sp < 0) return; + data_stack[data_sp] = ~data_stack[data_sp]; } void do_lshift(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a << b); } void do_rshift(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); - data_push((int32_t)((uint32_t)a >> b)); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); + data_push((int64_t)((uint64_t)a >> b)); } -// Comparison operations +// Comparison void do_eq(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a == b ? -1 : 0); } void do_neq(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a != b ? -1 : 0); } void do_lt(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a < b ? -1 : 0); } void do_gt(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a > b ? -1 : 0); } void do_lte(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a <= b ? -1 : 0); } void do_gte(Word* w) { (void)w; - if (sp < 1) return; - int32_t b = data_pop(); - int32_t a = data_pop(); + if (data_sp < 1) return; + int64_t b = data_pop(); + int64_t a = data_pop(); data_push(a >= b ? -1 : 0); } void do_zero_eq(Word* w) { (void)w; - if (sp < 0) return; - int32_t a = data_pop(); + if (data_sp < 0) return; + int64_t a = data_pop(); data_push(a == 0 ? -1 : 0); } void do_zero_lt(Word* w) { (void)w; - if (sp < 0) return; - int32_t a = data_pop(); + if (data_sp < 0) return; + int64_t a = data_pop(); data_push(a < 0 ? -1 : 0); } void do_zero_gt(Word* w) { (void)w; - if (sp < 0) return; - int32_t a = data_pop(); + if (data_sp < 0) return; + int64_t a = data_pop(); data_push(a > 0 ? -1 : 0); } -// I/O operations +// I/O void do_dot(Word* w) { (void)w; - if (sp < 0) return; - printf("%d ", data_pop()); + if (data_sp < 0) return; + printf("%" PRId64 " ", data_pop()); fflush(stdout); } @@ -320,7 +320,7 @@ void do_cr(Word* w) { void do_emit(Word* w) { (void)w; - if (sp < 0) return; + if (data_sp < 0) return; putchar((char)data_pop()); fflush(stdout); } @@ -333,86 +333,45 @@ void do_key(Word* w) { void do_dot_quote(Word* w) { (void)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 " + if (state == 0) { + // Interpret mode: print immediately + if (input_ptr == NULL) { printf("Missing string\n"); return; } + while (*input_ptr && isspace((unsigned char)*input_ptr)) input_ptr++; + if (*input_ptr != '"') { printf("Expected \" to start string\n"); return; } + input_ptr++; 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 " + while (*input_ptr && *input_ptr != '"') input_ptr++; + if (*input_ptr != '"') { printf("Unterminated string\n"); return; } + while (start < input_ptr) putchar(*start++); + input_ptr++; 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 " + } else { + // Compile mode: compile string for runtime + if (input_ptr == NULL) { printf("Missing string\n"); return; } + while (*input_ptr && isspace((unsigned char)*input_ptr)) input_ptr++; + if (*input_ptr != '"') { printf("Expected \" to start string\n"); return; } + input_ptr++; char* start = input_ptr; - // Find closing " - while (*input_ptr != '\0' && *input_ptr != '"') { - input_ptr++; - } - if (*input_ptr != '"') { - printf("Unterminated string\n"); - return; - } + while (*input_ptr && *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_internal("do_dot_quote_inner"); - if (inner_w == NULL) { - printf("Fatal: do_dot_quote_inner not found\n"); - return; - } - if (compile_idx + 2 + (int32_t)len > COMPILE_BUF_SIZE) { - printf("Compile buffer full\n"); - return; - } + if (!inner_w) { printf("Fatal: do_dot_quote_inner not found\n"); return; } + ensure_compile_cap(2 + (int32_t)len); 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) + compile_buf[compile_idx++] = (Cell){.num = (int64_t)len}; for (size_t i = 0; i < len; i++) { - compile_buf[compile_idx++] = (Cell){.num = (int32_t)start[i]}; + compile_buf[compile_idx++] = (Cell){.num = (int64_t)start[i]}; } - input_ptr++; // Skip closing " + input_ptr++; } } void do_dot_quote_inner(Word* w) { (void)w; - // Runtime: ip points to length cell, followed by string characters - int32_t len = ip->num; + int64_t len = ip->num; ip++; - for (int32_t i = 0; i < len; i++) { + for (int64_t i = 0; i < len; i++) { putchar((char)ip->num); ip++; } @@ -423,202 +382,109 @@ void do_words(Word* w) { (void)w; printf("Dictionary words:\n"); for (Word* cur = dict_head; cur != NULL; cur = cur->prev) { - if (cur->flags & (1 << 6)) continue; // Skip hidden + if (cur->flags & (1 << 6)) continue; printf("%s ", cur->name); } printf("\n"); fflush(stdout); } -// Control flow operations -void do_exit(Word* w) { - (void)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) { - (void)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) { - (void)w; - char* name = next_token(); - if (name == NULL) { - printf("':' expects a name\n"); - return; - } - size_t len = strlen(name); - if (len > MAX_NAME_LEN) len = MAX_NAME_LEN; - memcpy(compiling_name, name, len); - compiling_name[len] = '\0'; - state = 1; // Enter compile mode - compile_idx = 0; // Reset compile buffer -} - -void do_semicolon(Word* w) { - (void)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 - memcpy(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) { - (void)w; - // Unconditional branch: ip points to offset cell - int32_t offset = ip->num; - ip += offset; // Jump offset cells (relative to offset cell itself) -} - -void do_zero_branch(Word* w) { - (void)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 void do_fetch(Word* w) { (void)w; - int32_t addr = data_pop(); - if (addr < 0 || addr >= USER_MEMORY_SIZE) { + int64_t addr = data_pop(); + if (addr < 0 || addr >= user_mem_size) { printf("Address out of bounds\n"); return; } - data_push(user_mem[addr]); + data_push(user_mem[addr].num); } void do_store(Word* w) { (void)w; - int32_t val = data_pop(); - int32_t addr = data_pop(); - if (addr < 0 || addr >= USER_MEMORY_SIZE) { + int64_t val = data_pop(); + int64_t addr = data_pop(); + if (addr < 0 || addr >= user_mem_size) { printf("Address out of bounds\n"); return; } - user_mem[addr] = val; + user_mem[addr].num = val; } void do_plus_store(Word* w) { (void)w; - int32_t val = data_pop(); - int32_t addr = data_pop(); - if (addr < 0 || addr >= USER_MEMORY_SIZE) { + int64_t val = data_pop(); + int64_t addr = data_pop(); + if (addr < 0 || addr >= user_mem_size) { printf("Address out of bounds\n"); return; } - user_mem[addr] += val; + user_mem[addr].num += val; } void do_cfetch(Word* w) { (void)w; - int32_t addr = data_pop(); - int32_t max_addr = USER_MEMORY_SIZE * (int32_t)sizeof(int32_t); - if (addr < 0 || addr >= max_addr) { + int64_t addr = data_pop(); // byte offset + int64_t max_byte = user_mem_size * (int64_t)sizeof(Cell); + if (addr < 0 || addr >= max_byte) { printf("Address out of bounds\n"); return; } - int32_t cell = addr / (int32_t)sizeof(int32_t); - int32_t byte = addr % (int32_t)sizeof(int32_t); - uint8_t* p = (uint8_t*)&user_mem[cell]; - data_push((int32_t)p[byte]); + uint8_t* base = (uint8_t*)user_mem; + data_push((int64_t)base[addr]); } void do_cstore(Word* w) { (void)w; - int32_t val = data_pop(); - int32_t addr = data_pop(); - int32_t max_addr = USER_MEMORY_SIZE * (int32_t)sizeof(int32_t); - if (addr < 0 || addr >= max_addr) { + int64_t val = data_pop(); + int64_t addr = data_pop(); + int64_t max_byte = user_mem_size * (int64_t)sizeof(Cell); + if (addr < 0 || addr >= max_byte) { printf("Address out of bounds\n"); return; } - int32_t cell = addr / (int32_t)sizeof(int32_t); - int32_t byte = addr % (int32_t)sizeof(int32_t); - uint8_t* p = (uint8_t*)&user_mem[cell]; - p[byte] = (uint8_t)val; + uint8_t* base = (uint8_t*)user_mem; + base[addr] = (uint8_t)val; } void do_here(Word* w) { (void)w; - data_push((int32_t)(here - user_mem)); + // push the cell offset index + data_push(here - user_mem); } void do_allot(Word* w) { (void)w; - int32_t n = data_pop(); + int64_t n = data_pop(); + if (here + n > user_mem + user_mem_size) { + printf("User memory overflow\n"); + return; + } here += n; } +// Variable and constant void do_variable(Word* w) { (void)w; char* name = next_token(); - if (name == NULL) { - printf("VARIABLE expects a name\n"); + if (!name) { printf("VARIABLE expects a name\n"); return; } + + // allocate a cell for the variable's address + Cell* body_cell = malloc(sizeof(Cell)); + if (!body_cell) { printf("Out of memory\n"); exit(1); } + body_cell->num = here - user_mem; // store the cell index + + // allocate one cell in user memory + if (here + 1 > user_mem + user_mem_size) { + printf("User memory overflow\n"); + free(body_cell); return; } - if (dict_idx >= DICT_SIZE) { - printf("Dictionary full\n"); - return; - } - if (body_idx >= BODY_SIZE) { - printf("Dictionary body storage full\n"); - return; - } - Word* new_w = &dict[dict_idx++]; + here++; + + // create dictionary entry + Word* new_w = malloc(sizeof(Word)); + if (!new_w) { printf("Out of memory\n"); free(body_cell); exit(1); } new_w->prev = dict_head; dict_head = new_w; @@ -628,34 +494,21 @@ void do_variable(Word* w) { memcpy(new_w->name, name, len); new_w->name[len] = '\0'; new_w->code = do_do_var; - - // Allocate body cell to hold the address (cell index in user_mem) - new_w->body = &dict_bodies[body_idx++]; - int32_t addr = (int32_t)(here - user_mem); - new_w->body->num = addr; - - // Allocate one cell in user_mem - here++; + new_w->body = body_cell; } void do_constant(Word* w) { (void)w; - int32_t val = data_pop(); + int64_t val = data_pop(); char* name = next_token(); - if (name == NULL) { - printf("CONSTANT expects a name\n"); - data_push(val); - return; - } - if (dict_idx >= DICT_SIZE) { - printf("Dictionary full\n"); - return; - } - if (body_idx >= BODY_SIZE) { - printf("Dictionary body storage full\n"); - return; - } - Word* new_w = &dict[dict_idx++]; + if (!name) { printf("CONSTANT expects a name\n"); data_push(val); return; } + + Cell* body_cell = malloc(sizeof(Cell)); + if (!body_cell) { printf("Out of memory\n"); exit(1); } + body_cell->num = val; + + Word* new_w = malloc(sizeof(Word)); + if (!new_w) { printf("Out of memory\n"); free(body_cell); exit(1); } new_w->prev = dict_head; dict_head = new_w; @@ -665,196 +518,204 @@ void do_constant(Word* w) { memcpy(new_w->name, name, len); new_w->name[len] = '\0'; new_w->code = do_do_const; - - // Allocate body cell to hold the constant value - new_w->body = &dict_bodies[body_idx++]; - new_w->body->num = val; + new_w->body = body_cell; } void do_do_var(Word* w) { - data_push(w->body->num); // Push the user_mem cell index + data_push(w->body->num); // push the address (cell index) } void do_do_const(Word* w) { - data_push(w->body->num); // Push the constant value + data_push(w->body->num); // push the constant value } -// Return stack operations +// Return stack ops void do_to_r(Word* w) { (void)w; - int32_t val = data_pop(); + int64_t val = data_pop(); ret_push_num(val); } void do_r_from(Word* w) { (void)w; - int32_t val = ret_pop_num(); + int64_t val = ret_pop_num(); data_push(val); } void do_r_fetch(Word* w) { (void)w; - if (rp < 0) { - printf("Return stack underflow\n"); - return; - } + if (rp < 0) { printf("Return stack underflow\n"); return; } data_push(ret_stack[rp].num); } -// Control flow: IF, ELSE, THEN, BEGIN, UNTIL, WHILE, REPEAT +// Control flow +void do_exit(Word* w) { + (void)w; + Cell* ret_addr = ret_pop_ip(); + ip = ret_addr; +} + +void do_docolon(Word* w) { + ret_push_ip(ip); + ip = w->body; +} + +void do_lit(Word* w) { + (void)w; + data_push(ip->num); + ip++; +} + +void do_colon(Word* w) { + (void)w; + char* name = next_token(); + if (!name) { printf("':' expects a name\n"); return; } + size_t len = strlen(name); + if (len > MAX_NAME_LEN) len = MAX_NAME_LEN; + memcpy(compiling_name, name, len); + compiling_name[len] = '\0'; + state = 1; + compile_idx = 0; + ensure_compile_cap(0); // make sure compile_buf exists +} + +void do_semicolon(Word* w) { + (void)w; + if (state != 1) { printf("';' only valid in compile mode\n"); return; } + Word* exit_w = lookup_word("exit"); + if (!exit_w) { printf("Fatal: exit word not found\n"); return; } + + ensure_compile_cap(1); + compile_buf[compile_idx++] = (Cell){.word = exit_w}; + + // Create body copy of compiled cells + Cell* body_copy = malloc(compile_idx * sizeof(Cell)); + if (!body_copy) { printf("Out of memory\n"); exit(1); } + memcpy(body_copy, compile_buf, compile_idx * sizeof(Cell)); + + // Create new word entry + Word* new_w = malloc(sizeof(Word)); + if (!new_w) { printf("Out of memory\n"); free(body_copy); exit(1); } + 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 + memcpy(new_w->name, compiling_name, len); + new_w->name[len] = '\0'; + new_w->code = do_docolon; + new_w->body = body_copy; + + state = 0; // back to interpret mode +} + +void do_branch(Word* w) { + (void)w; + int64_t offset = ip->num; + ip += offset; +} + +void do_zero_branch(Word* w) { + (void)w; + int64_t cond = data_pop(); + if (cond == 0) { + int64_t offset = ip->num; + ip += offset; + } else { + ip++; + } +} + +// Control flow using compile stack (indices) void do_if(Word* w) { (void)w; - if (state != 1) { - printf("IF only valid in compile mode\n"); - return; - } + if (state != 1) { printf("IF only valid in compile mode\n"); return; } Word* zbranch = lookup_word_internal("0branch"); - if (zbranch == NULL) { - printf("Fatal: 0branch not found\n"); - return; - } - if (compile_idx + 2 > COMPILE_BUF_SIZE) { - printf("Compile buffer full\n"); - return; - } + if (!zbranch) { printf("Fatal: 0branch not found\n"); return; } + ensure_compile_cap(2); compile_buf[compile_idx++] = (Cell){.word = zbranch}; - compile_push((Cell*)&compile_buf[compile_idx]); - compile_idx++; // Reserve offset cell + // compile_push current index (where the offset will be placed) + compile_push(compile_idx); + compile_idx++; // reserve offset cell } void do_then(Word* w) { (void)w; - if (state != 1) { - printf("THEN only valid in compile mode\n"); - return; - } - Cell* offset_addr = compile_pop(); - if (offset_addr == NULL) return; - int32_t offset_idx = (int32_t)(offset_addr - compile_buf); - int32_t target_idx = compile_idx; - offset_addr->num = target_idx - offset_idx; + if (state != 1) { printf("THEN only valid in compile mode\n"); return; } + int64_t offset_idx = compile_pop(); + if (offset_idx < 0) return; + compile_buf[offset_idx].num = compile_idx - offset_idx; } void do_else(Word* w) { (void)w; - if (state != 1) { - printf("ELSE only valid in compile mode\n"); - return; - } - Cell* if_offset = compile_pop(); - if (if_offset == NULL) return; - + if (state != 1) { printf("ELSE only valid in compile mode\n"); return; } + int64_t if_offset_idx = compile_pop(); + if (if_offset_idx < 0) return; + Word* branch_w = lookup_word_internal("branch"); - if (branch_w == NULL) { - printf("Fatal: branch not found\n"); - return; - } - if (compile_idx + 2 > COMPILE_BUF_SIZE) { - printf("Compile buffer full\n"); - return; - } - - // Resolve IF offset to jump to after this branch - int32_t if_offset_idx = (int32_t)(if_offset - compile_buf); - int32_t target_idx = compile_idx + 2; // after branch + its offset - if_offset->num = target_idx - if_offset_idx; - - // Compile unconditional branch for ELSE part + if (!branch_w) { printf("Fatal: branch not found\n"); return; } + ensure_compile_cap(2); + + // resolve IF offset to skip the ELSE branch + compile_buf[if_offset_idx].num = (compile_idx + 2) - if_offset_idx; + + // compile unconditional branch for ELSE part compile_buf[compile_idx++] = (Cell){.word = branch_w}; - compile_push((Cell*)&compile_buf[compile_idx]); - compile_idx++; // Reserve offset cell + compile_push(compile_idx); + compile_idx++; // reserve offset cell } void do_begin(Word* w) { (void)w; - if (state != 1) { - printf("BEGIN only valid in compile mode\n"); - return; - } - compile_push((Cell*)&compile_buf[compile_idx]); + if (state != 1) { printf("BEGIN only valid in compile mode\n"); return; } + compile_push(compile_idx); } void do_until(Word* w) { (void)w; - if (state != 1) { - printf("UNTIL only valid in compile mode\n"); - return; - } - Cell* begin_addr = compile_pop(); - if (begin_addr == NULL) return; - + if (state != 1) { printf("UNTIL only valid in compile mode\n"); return; } + int64_t begin_idx = compile_pop(); + if (begin_idx < 0) return; + Word* zbranch = lookup_word_internal("0branch"); - if (zbranch == NULL) { - printf("Fatal: 0branch not found\n"); - return; - } - if (compile_idx + 2 > COMPILE_BUF_SIZE) { - printf("Compile buffer full\n"); - return; - } - - int32_t begin_idx = (int32_t)(begin_addr - compile_buf); + if (!zbranch) { printf("Fatal: 0branch not found\n"); return; } + ensure_compile_cap(2); compile_buf[compile_idx++] = (Cell){.word = zbranch}; - int32_t offset_idx = compile_idx; - compile_buf[compile_idx++] = (Cell){.num = begin_idx - offset_idx}; + compile_buf[compile_idx++] = (Cell){.num = begin_idx - compile_idx}; } void do_while(Word* w) { (void)w; - if (state != 1) { - printf("WHILE only valid in compile mode\n"); - return; - } - Cell* begin_addr = compile_pop(); - if (begin_addr == NULL) return; - + if (state != 1) { printf("WHILE only valid in compile mode\n"); return; } + int64_t begin_idx = compile_pop(); + if (begin_idx < 0) return; + Word* zbranch = lookup_word_internal("0branch"); - if (zbranch == NULL) { - printf("Fatal: 0branch not found\n"); - return; - } - if (compile_idx + 2 > COMPILE_BUF_SIZE) { - printf("Compile buffer full\n"); - return; - } - + if (!zbranch) { printf("Fatal: 0branch not found\n"); return; } + ensure_compile_cap(2); compile_buf[compile_idx++] = (Cell){.word = zbranch}; - Cell* while_offset = (Cell*)&compile_buf[compile_idx]; - compile_idx++; // Reserve offset cell - - compile_push(while_offset); - compile_push(begin_addr); + int64_t while_offset_idx = compile_idx; + compile_idx++; // reserve offset + + compile_push(while_offset_idx); + compile_push(begin_idx); } void do_repeat(Word* w) { (void)w; - if (state != 1) { - printf("REPEAT only valid in compile mode\n"); - return; - } - Cell* begin_addr = compile_pop(); - if (begin_addr == NULL) return; - Cell* while_offset = compile_pop(); - if (while_offset == NULL) return; - + if (state != 1) { printf("REPEAT only valid in compile mode\n"); return; } + int64_t begin_idx = compile_pop(); + if (begin_idx < 0) return; + int64_t while_offset_idx = compile_pop(); + if (while_offset_idx < 0) return; + Word* branch_w = lookup_word_internal("branch"); - if (branch_w == NULL) { - printf("Fatal: branch not found\n"); - return; - } - if (compile_idx + 2 > COMPILE_BUF_SIZE) { - printf("Compile buffer full\n"); - return; - } - - // Compile backward branch to begin - int32_t begin_idx = (int32_t)(begin_addr - compile_buf); + if (!branch_w) { printf("Fatal: branch not found\n"); return; } + ensure_compile_cap(2); compile_buf[compile_idx++] = (Cell){.word = branch_w}; - int32_t offset_idx = compile_idx; - compile_buf[compile_idx++] = (Cell){.num = begin_idx - offset_idx}; - - // Resolve WHILE offset to point after this backward branch - int32_t while_offset_idx = (int32_t)(while_offset - compile_buf); - int32_t target_idx = compile_idx; - while_offset->num = target_idx - while_offset_idx; + compile_buf[compile_idx++] = (Cell){.num = begin_idx - compile_idx}; + + compile_buf[while_offset_idx].num = compile_idx - while_offset_idx; } diff --git a/main.c b/main.c index cc7635e..837140a 100644 --- a/main.c +++ b/main.c @@ -1,31 +1,39 @@ #include "forth.h" int main(void) { - // Register primitive words + // Allocate user memory + user_mem_size = 1024 * 1024; // 1 Mega cells + user_mem = calloc((size_t)user_mem_size, sizeof(Cell)); + if (!user_mem) { + fprintf(stderr, "Failed to allocate user memory\n"); + return 1; + } + here = user_mem; + // Hidden words first - add_primitive("exit", do_exit, 0); - add_primitive("docolon", do_docolon, 1 << 6); // Hidden - add_primitive("lit", do_lit, 1 << 6); // Hidden - add_primitive("do_dot_quote_inner", do_dot_quote_inner, 1 << 6); // Hidden - add_primitive("0branch", do_zero_branch, 1 << 6); // Hidden (for IF, UNTIL, WHILE) - add_primitive("branch", do_branch, 1 << 6); // Hidden (for ELSE, REPEAT) + add_primitive("exit", do_exit, 0); + add_primitive("docolon", do_docolon, 1 << 6); + add_primitive("lit", do_lit, 1 << 6); + add_primitive("do_dot_quote_inner", do_dot_quote_inner, 1 << 6); + add_primitive("0branch", do_zero_branch, 1 << 6); + add_primitive("branch", do_branch, 1 << 6); // Public primitives // Stack ops - add_primitive("dup", do_dup, 0); - add_primitive("drop", do_drop, 0); - add_primitive("swap", do_swap, 0); - add_primitive("over", do_over, 0); - add_primitive("rot", do_rot, 0); - add_primitive("minus-rot", do_minus_rot, 0); - add_primitive("nip", do_nip, 0); - add_primitive("tuck", do_tuck, 0); + add_primitive("dup", do_dup, 0); + add_primitive("drop", do_drop, 0); + add_primitive("swap", do_swap, 0); + add_primitive("over", do_over, 0); + add_primitive("rot", do_rot, 0); + add_primitive("-rot", do_minus_rot, 0); + add_primitive("nip", do_nip, 0); + add_primitive("tuck", do_tuck, 0); // Arithmetic - add_primitive("+", do_add, 0); - add_primitive("-", do_sub, 0); - add_primitive("*", do_mul, 0); - add_primitive("/", do_div, 0); + add_primitive("+", do_add, 0); + add_primitive("-", do_sub, 0); + add_primitive("*", do_mul, 0); + add_primitive("/", do_div, 0); add_primitive("mod", do_mod, 0); add_primitive("/mod", do_slash_mod, 0); add_primitive("1+", do_one_plus, 0); @@ -33,23 +41,23 @@ int main(void) { add_primitive("2+", do_two_plus, 0); add_primitive("2-", do_two_minus, 0); add_primitive("negate", do_negate, 0); - add_primitive("abs", do_abs, 0); - add_primitive("min", do_min, 0); - add_primitive("max", do_max, 0); + add_primitive("abs", do_abs, 0); + add_primitive("min", do_min, 0); + add_primitive("max", do_max, 0); // Logic - add_primitive("and", do_and, 0); - add_primitive("or", do_or, 0); - add_primitive("xor", do_xor, 0); + add_primitive("and", do_and, 0); + add_primitive("or", do_or, 0); + add_primitive("xor", do_xor, 0); add_primitive("invert", do_invert, 0); add_primitive("lshift", do_lshift, 0); add_primitive("rshift", do_rshift, 0); // Comparison - add_primitive("=", do_eq, 0); + add_primitive("=", do_eq, 0); add_primitive("<>", do_neq, 0); - add_primitive("<", do_lt, 0); - add_primitive(">", do_gt, 0); + add_primitive("<", do_lt, 0); + add_primitive(">", do_gt, 0); add_primitive("<=", do_lte, 0); add_primitive(">=", do_gte, 0); add_primitive("0=", do_zero_eq, 0); @@ -57,22 +65,22 @@ int main(void) { add_primitive("0>", do_zero_gt, 0); // I/O - add_primitive(".", do_dot, 0); - add_primitive("cr", do_cr, 0); - add_primitive("emit", do_emit, 0); - add_primitive("key", do_key, 0); - add_primitive(".\"", do_dot_quote, 1 << 7); // Immediate + add_primitive(".", do_dot, 0); + add_primitive("cr", do_cr, 0); + add_primitive("emit", do_emit, 0); + add_primitive("key", do_key, 0); + add_primitive(".\"", do_dot_quote, 1 << 7); // immediate add_primitive("words", do_words, 0); // Memory - add_primitive("@", do_fetch, 0); - add_primitive("!", do_store, 0); + add_primitive("@", do_fetch, 0); + add_primitive("!", do_store, 0); add_primitive("+!", do_plus_store, 0); add_primitive("c@", do_cfetch, 0); add_primitive("c!", do_cstore, 0); add_primitive("variable", do_variable, 0); add_primitive("constant", do_constant, 0); - add_primitive("here", do_here, 0); + add_primitive("here", do_here, 0); add_primitive("allot", do_allot, 0); // Return stack @@ -81,15 +89,15 @@ int main(void) { add_primitive("r@", do_r_fetch, 0); // Compilation / control flow - add_primitive(":", do_colon, 0); - add_primitive(";", do_semicolon, 1 << 7); // Immediate - add_primitive("if", do_if, 1 << 7); // Immediate - add_primitive("else", do_else, 1 << 7); // Immediate - add_primitive("then", do_then, 1 << 7); // Immediate - add_primitive("begin", do_begin, 1 << 7); // Immediate - add_primitive("until", do_until, 1 << 7); // Immediate - add_primitive("while", do_while, 1 << 7); // Immediate - add_primitive("repeat", do_repeat, 1 << 7); // Immediate + add_primitive(":", do_colon, 0); + add_primitive(";", do_semicolon, 1 << 7); + add_primitive("if", do_if, 1 << 7); + add_primitive("else", do_else, 1 << 7); + add_primitive("then", do_then, 1 << 7); + add_primitive("begin", do_begin, 1 << 7); + add_primitive("until", do_until, 1 << 7); + add_primitive("while", do_while, 1 << 7); + add_primitive("repeat", do_repeat, 1 << 7); // Start outer interpreter outer_interpreter();