#ifndef FORTH_H #define FORTH_H #include #include #include // Configuration (all hard limits removed) #define MAX_NAME_LEN 31 #define FORTH_EOF (-1) /* Platform interface -- must be provided by the target platform layer. */ void forth_putchar(char c); int forth_getchar(void); void forth_printf(const char* fmt, ...); void forth_fflush(void); void forth_panic(void); /* Platform string-to-number (base 10 is required). */ int64_t forth_strtoll(const char* str, char** endptr, int base); /* Portable character classification. */ static inline int forth_isspace(int c) { return c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' || c == '\v'; } /* Portable string operations. */ static inline size_t forth_strlen(const char* s) { size_t n = 0; while (s[n]) n++; return n; } static inline void forth_memcpy(void* dst, const void* src, size_t n) { char* d = dst; const char* s = src; while (n--) *d++ = *s++; } static inline int forth_strcmp(const char* a, const char* b) { while (*a && *a == *b) { a++; b++; } return (unsigned char)*a - (unsigned char)*b; } /* Static memory sizes (override before including forth.h) */ #ifndef FORTH_DATA_STACK_SIZE #define FORTH_DATA_STACK_SIZE 128 #endif #ifndef FORTH_RET_STACK_SIZE #define FORTH_RET_STACK_SIZE 128 #endif #ifndef FORTH_COMPILE_STACK_SIZE #define FORTH_COMPILE_STACK_SIZE 64 #endif #ifndef FORTH_COMPILE_BUF_SIZE #define FORTH_COMPILE_BUF_SIZE 256 #endif #ifndef FORTH_USER_MEM_CELLS #define FORTH_USER_MEM_CELLS (1024 * 1024) #endif #ifndef FORTH_MAX_WORDS #define FORTH_MAX_WORDS 256 #endif #ifndef FORTH_MAX_WORD_BODY_CELLS #define FORTH_MAX_WORD_BODY_CELLS 4096 #endif #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; // Entry point void forth_run(void); // 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); void do_comma(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