f033187c6c
Co-authored-by: aider (openrouter/moonshotai/kimi-k2.6) <aider@aider.chat>
194 lines
4.4 KiB
C
194 lines
4.4 KiB
C
#ifndef FORTH_H
|
||
#define FORTH_H
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <ctype.h>
|
||
#include <stdint.h>
|
||
#include <inttypes.h>
|
||
|
||
// Configuration (all hard limits removed)
|
||
#define MAX_NAME_LEN 31
|
||
|
||
#define F_IMMEDIATE (1 << 7)
|
||
#define F_HIDDEN (1 << 6)
|
||
|
||
// Core types
|
||
typedef struct Word Word;
|
||
typedef union Cell {
|
||
Word* word;
|
||
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
|
||
char name[MAX_NAME_LEN + 1];
|
||
void (*code)(Word*);
|
||
Cell* body; // points to the word’s body (allocated dynamically)
|
||
};
|
||
|
||
// 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_head;
|
||
|
||
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; // line buffer (dynamic, managed by getline)
|
||
extern size_t input_buf_cap;
|
||
extern char* input_ptr;
|
||
|
||
extern int64_t *compile_stack; // holds indices into compile_buf
|
||
extern int32_t compile_sp;
|
||
extern int32_t compile_stack_cap;
|
||
|
||
extern Cell *user_mem;
|
||
extern int64_t user_mem_size; // in cells
|
||
extern Cell* here;
|
||
|
||
// Pointers to critical hidden/primitive words (set during init)
|
||
extern Word* w_exit;
|
||
extern Word* w_docolon;
|
||
extern Word* w_lit;
|
||
extern Word* w_branch;
|
||
extern Word* w_zbranch;
|
||
extern Word* w_dot_quote_inner;
|
||
|
||
// Core function prototypes
|
||
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(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);
|
||
|
||
// Ensure compile_buf has at least 'needed' free cells (returns 0 on overflow)
|
||
int ensure_compile_cap(int32_t needed);
|
||
|
||
Word* forth_alloc_word(void);
|
||
Cell* forth_alloc_body(int32_t cells);
|
||
|
||
// Stack ops
|
||
void do_dup(Word* w);
|
||
void do_drop(Word* w);
|
||
void do_swap(Word* w);
|
||
void do_over(Word* w);
|
||
void do_rot(Word* w);
|
||
void do_minus_rot(Word* w);
|
||
void do_nip(Word* w);
|
||
void do_tuck(Word* w);
|
||
|
||
// Arithmetic
|
||
void do_add(Word* w);
|
||
void do_sub(Word* w);
|
||
void do_mul(Word* w);
|
||
void do_div(Word* w);
|
||
void do_mod(Word* w);
|
||
void do_slash_mod(Word* w);
|
||
void do_one_plus(Word* w);
|
||
void do_one_minus(Word* w);
|
||
void do_two_plus(Word* w);
|
||
void do_two_minus(Word* w);
|
||
void do_negate(Word* w);
|
||
void do_abs(Word* w);
|
||
void do_min(Word* w);
|
||
void do_max(Word* w);
|
||
|
||
// Logic
|
||
void do_and(Word* w);
|
||
void do_or(Word* w);
|
||
void do_xor(Word* w);
|
||
void do_invert(Word* w);
|
||
void do_lshift(Word* w);
|
||
void do_rshift(Word* w);
|
||
|
||
// Comparison
|
||
void do_eq(Word* w);
|
||
void do_neq(Word* w);
|
||
void do_lt(Word* w);
|
||
void do_gt(Word* w);
|
||
void do_lte(Word* w);
|
||
void do_gte(Word* w);
|
||
void do_zero_eq(Word* w);
|
||
void do_zero_lt(Word* w);
|
||
void do_zero_gt(Word* w);
|
||
|
||
// I/O
|
||
void do_dot(Word* w);
|
||
void do_cr(Word* w);
|
||
void do_emit(Word* w);
|
||
void do_key(Word* w);
|
||
void do_dot_quote(Word* w);
|
||
void do_dot_quote_inner(Word* w);
|
||
void do_words(Word* w);
|
||
|
||
// Memory
|
||
void do_fetch(Word* w);
|
||
void do_store(Word* w);
|
||
void do_plus_store(Word* w);
|
||
void do_cfetch(Word* w);
|
||
void do_cstore(Word* w);
|
||
void do_variable(Word* w);
|
||
void do_constant(Word* w);
|
||
void do_do_var(Word* w);
|
||
void do_do_const(Word* w);
|
||
void do_here(Word* w);
|
||
void do_allot(Word* w);
|
||
|
||
// Return stack
|
||
void do_to_r(Word* w);
|
||
void do_r_from(Word* w);
|
||
void do_r_fetch(Word* w);
|
||
|
||
// Control flow
|
||
void do_exit(Word* w);
|
||
void do_docolon(Word* w);
|
||
void do_lit(Word* w);
|
||
void do_colon(Word* w);
|
||
void do_semicolon(Word* w);
|
||
void do_branch(Word* w);
|
||
void do_zero_branch(Word* w);
|
||
void do_if(Word* w);
|
||
void do_else(Word* w);
|
||
void do_then(Word* w);
|
||
void do_begin(Word* w);
|
||
void do_until(Word* w);
|
||
void do_while(Word* w);
|
||
void do_repeat(Word* w);
|
||
|
||
/* Additional stack words */
|
||
void do_depth(Word* w);
|
||
void do_pick(Word* w);
|
||
void do_roll(Word* w);
|
||
void do_qdup(Word* w);
|
||
void do_2dup(Word* w);
|
||
void do_2drop(Word* w);
|
||
void do_2swap(Word* w);
|
||
|
||
#endif
|