feat: add modular Forth interpreter implementation
Co-authored-by: aider (openrouter/tencent/hy3-preview:free) <aider@aider.chat>
This commit is contained in:
+296
@@ -0,0 +1,296 @@
|
||||
#include "forth.h"
|
||||
|
||||
// Stack operations
|
||||
void do_dup(Word* w) {
|
||||
if (sp < 0) return;
|
||||
int32_t v = data_stack[sp];
|
||||
data_push(v);
|
||||
}
|
||||
|
||||
void do_drop(Word* w) {
|
||||
data_pop();
|
||||
}
|
||||
|
||||
void do_swap(Word* 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;
|
||||
}
|
||||
|
||||
void do_over(Word* w) {
|
||||
if (sp < 1) return;
|
||||
data_push(data_stack[sp-1]);
|
||||
}
|
||||
|
||||
void do_rot(Word* 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;
|
||||
}
|
||||
|
||||
void do_minus_rot(Word* 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;
|
||||
}
|
||||
|
||||
void do_nip(Word* w) {
|
||||
if (sp < 1) return;
|
||||
data_stack[sp-1] = data_stack[sp];
|
||||
sp--;
|
||||
}
|
||||
|
||||
void do_tuck(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t a = data_stack[sp-1];
|
||||
int32_t b = data_stack[sp];
|
||||
data_push(a);
|
||||
data_stack[sp-2] = b;
|
||||
}
|
||||
|
||||
// Arithmetic operations
|
||||
void do_add(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a + b);
|
||||
}
|
||||
|
||||
void do_sub(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a - b);
|
||||
}
|
||||
|
||||
void do_mul(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a * b);
|
||||
}
|
||||
|
||||
void do_div(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
if (b == 0) {
|
||||
printf("Division by zero\n");
|
||||
data_push(a);
|
||||
data_push(b);
|
||||
return;
|
||||
}
|
||||
data_push(a / b);
|
||||
}
|
||||
|
||||
void do_mod(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
if (b == 0) {
|
||||
printf("Modulo by zero\n");
|
||||
data_push(a);
|
||||
data_push(b);
|
||||
return;
|
||||
}
|
||||
data_push(a % b);
|
||||
}
|
||||
|
||||
void do_slash_mod(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
if (b == 0) {
|
||||
printf("Modulo by zero\n");
|
||||
data_push(a);
|
||||
data_push(b);
|
||||
return;
|
||||
}
|
||||
data_push(a / b);
|
||||
data_push(a % b);
|
||||
}
|
||||
|
||||
void do_one_plus(Word* w) {
|
||||
if (sp < 0) return;
|
||||
data_stack[sp]++;
|
||||
}
|
||||
|
||||
void do_one_minus(Word* w) {
|
||||
if (sp < 0) return;
|
||||
data_stack[sp]--;
|
||||
}
|
||||
|
||||
void do_two_plus(Word* w) {
|
||||
if (sp < 0) return;
|
||||
data_stack[sp] += 2;
|
||||
}
|
||||
|
||||
void do_two_minus(Word* w) {
|
||||
if (sp < 0) return;
|
||||
data_stack[sp] -= 2;
|
||||
}
|
||||
|
||||
void do_negate(Word* w) {
|
||||
if (sp < 0) return;
|
||||
data_stack[sp] = -data_stack[sp];
|
||||
}
|
||||
|
||||
void do_abs(Word* w) {
|
||||
if (sp < 0) return;
|
||||
int32_t v = data_pop();
|
||||
data_push(v < 0 ? -v : v);
|
||||
}
|
||||
|
||||
void do_min(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a < b ? a : b);
|
||||
}
|
||||
|
||||
void do_max(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a > b ? a : b);
|
||||
}
|
||||
|
||||
// Logic operations
|
||||
void do_and(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a & b);
|
||||
}
|
||||
|
||||
void do_or(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a | b);
|
||||
}
|
||||
|
||||
void do_xor(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a ^ b);
|
||||
}
|
||||
|
||||
void do_invert(Word* w) {
|
||||
if (sp < 0) return;
|
||||
data_stack[sp] = ~data_stack[sp];
|
||||
}
|
||||
|
||||
void do_lshift(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a << b);
|
||||
}
|
||||
|
||||
void do_rshift(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push((int32_t)((uint32_t)a >> b));
|
||||
}
|
||||
|
||||
// Comparison operations
|
||||
void do_eq(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a == b ? -1 : 0); // Forth uses -1 for true, 0 for false
|
||||
}
|
||||
|
||||
void do_neq(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a != b ? -1 : 0);
|
||||
}
|
||||
|
||||
void do_lt(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a < b ? -1 : 0);
|
||||
}
|
||||
|
||||
void do_gt(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a > b ? -1 : 0);
|
||||
}
|
||||
|
||||
void do_lte(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a <= b ? -1 : 0);
|
||||
}
|
||||
|
||||
void do_gte(Word* w) {
|
||||
if (sp < 1) return;
|
||||
int32_t b = data_pop();
|
||||
int32_t a = data_pop();
|
||||
data_push(a >= b ? -1 : 0);
|
||||
}
|
||||
|
||||
void do_zero_eq(Word* w) {
|
||||
if (sp < 0) return;
|
||||
int32_t a = data_pop();
|
||||
data_push(a == 0 ? -1 : 0);
|
||||
}
|
||||
|
||||
void do_zero_lt(Word* w) {
|
||||
if (sp < 0) return;
|
||||
int32_t a = data_pop();
|
||||
data_push(a < 0 ? -1 : 0);
|
||||
}
|
||||
|
||||
void do_zero_gt(Word* w) {
|
||||
if (sp < 0) return;
|
||||
int32_t a = data_pop();
|
||||
data_push(a > 0 ? -1 : 0);
|
||||
}
|
||||
|
||||
// I/O operations
|
||||
void do_dot(Word* w) {
|
||||
if (sp < 0) return;
|
||||
printf("%d ", data_pop());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void do_cr(Word* w) {
|
||||
printf("\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void do_emit(Word* w) {
|
||||
if (sp < 0) return;
|
||||
putchar((char)data_pop());
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void do_key(Word* w) {
|
||||
int c = getchar();
|
||||
data_push(c == EOF ? -1 : c);
|
||||
}
|
||||
|
||||
void do_dot_quote(Word* w) {
|
||||
// Immediate word: parse string until " and print/compile
|
||||
if (state == 0) { // Interpret mode: print immediately
|
||||
//
|
||||
Reference in New Issue
Block a user