This commit is contained in:
Lobo 2026-01-23 18:43:16 -03:00
parent f40fd7eaa1
commit 30ff72b3ae
10 changed files with 103 additions and 43 deletions

2
README
View file

@ -12,5 +12,5 @@
TODO: TODO:
- [o] "#load" pragma - [o] "#load" pragma
- [o better dip/keep (avoid using the retain stack for them) - [o] better dip/keep (avoid using the retain stack for them)
- [ ] hand-rolled parser - [ ] hand-rolled parser

View file

@ -1,11 +1,4 @@
#load("std.grr") #load("std.grr")
def while {
swap dup bury >r >r
if: call dup
[r> dup >r call r> r> swap while]
[drop r> drop r> drop];
}
while: [stdin fgetline] while: [stdin fgetline]
[print]; [print];

View file

@ -32,8 +32,9 @@ V chunk_release(Bc *chunk) {
#if CHUNK_DEBUG #if CHUNK_DEBUG
fprintf(stderr, "DEBUG: freeing chunk %s at %p\n", chunk->name, (V *)chunk); fprintf(stderr, "DEBUG: freeing chunk %s at %p\n", chunk->name, (V *)chunk);
#endif #endif
yar_free(&chunk->lines);
yar_free(&chunk->constants); yar_free(&chunk->constants);
yar_free(&chunk->lines);
yar_free(&chunk->symbols);
yar_free(chunk); yar_free(chunk);
free(chunk); free(chunk);
} }

View file

@ -23,12 +23,17 @@ struct {
{"dup", {OP_DUP, 0}}, {"dup", {OP_DUP, 0}},
{"drop", {OP_DROP, 0}}, {"drop", {OP_DROP, 0}},
{"swap", {OP_SWAP, 0}}, {"swap", {OP_SWAP, 0}},
{"2dup", {OP_2DUP, 0}},
{"2drop", {OP_2DROP, 0}},
{"2swap", {OP_2SWAP, 0}},
{"over", {OP_OVER, 0}}, {"over", {OP_OVER, 0}},
{"nip", {OP_NIP, 0}}, {"nip", {OP_NIP, 0}},
{"bury", {OP_BURY, 0}}, {"bury", {OP_BURY, 0}},
{"dig", {OP_DIG, 0}}, {"dig", {OP_DIG, 0}},
{">r", {OP_TOR, 0}}, {">r", {OP_TOR, 0}},
{"r>", {OP_FROMR, 0}}, {"r>", {OP_FROMR, 0}},
{"2>r", {OP_2TOR, 0}},
{"2r>", {OP_2FROMR, 0}},
{"if", {OP_CHOOSE, OP_CALL, 0}}, {"if", {OP_CHOOSE, OP_CALL, 0}},
{"call", {OP_CALL, 0}}, {"call", {OP_CALL, 0}},
{"compose", {OP_COMPOSE, 0}}, {"compose", {OP_COMPOSE, 0}},
@ -395,6 +400,8 @@ static I compile_ast(Cm *cm, mpc_ast_t *curr, mpc_ast_trav_t **next) {
} }
Bc *compile_program(Cm *cm, mpc_ast_t *ast) { Bc *compile_program(Cm *cm, mpc_ast_t *ast) {
mpc_ast_print_to(ast, stderr);
mpc_ast_trav_t *next = mpc_ast_traverse_start(ast, mpc_ast_trav_order_pre); mpc_ast_trav_t *next = mpc_ast_traverse_start(ast, mpc_ast_trav_order_pre);
mpc_ast_t *curr = mpc_ast_traverse_next(&next); // Begin traversal mpc_ast_t *curr = mpc_ast_traverse_next(&next); // Begin traversal

View file

@ -7,7 +7,7 @@
#include "vendor/mpc.h" #include "vendor/mpc.h"
#define COMPILER_DEBUG 0 #define COMPILER_DEBUG 1
/** Compiler context */ /** Compiler context */
typedef struct Cm { typedef struct Cm {

View file

@ -60,7 +60,7 @@ static V printstats(Gc *gc, const char *label) {
} }
#endif #endif
V gc_collect(Vm *vm) { V gc_collect(Vm *vm, I final) {
Gc *gc = &vm->gc; Gc *gc = &vm->gc;
uint8_t *scan = gc->to.free; uint8_t *scan = gc->to.free;
@ -68,29 +68,32 @@ V gc_collect(Vm *vm) {
printstats(gc, "before GC"); printstats(gc, "before GC");
#endif #endif
for (Z i = 0; i < gc->roots.count; i++) { if (!final) {
O *o = gc->roots.items[i]; // Final GC ignores roots.
*o = forward(gc, *o); for (Z i = 0; i < gc->roots.count; i++) {
} O *o = gc->roots.items[i];
*o = forward(gc, *o);
Dt *dstack[256];
Dt **dsp = dstack;
*dsp++ = vm->dictionary;
// Forward constants referenced by dictionary entries
while (dsp > dstack) {
Dt *node = *--dsp;
if (!node)
continue;
if (node->chunk != NULL) {
for (Z i = 0; i < node->chunk->constants.count; i++) {
node->chunk->constants.items[i] =
forward(gc, node->chunk->constants.items[i]);
}
} }
for (I i = 0; i < 4; i++) {
if (node->child[i] != NULL) Dt *dstack[256];
*dsp++ = node->child[i]; Dt **dsp = dstack;
*dsp++ = vm->dictionary;
// Forward constants referenced by dictionary entries
while (dsp > dstack) {
Dt *node = *--dsp;
if (!node)
continue;
if (node->chunk != NULL) {
for (Z i = 0; i < node->chunk->constants.count; i++) {
node->chunk->constants.items[i] =
forward(gc, node->chunk->constants.items[i]);
}
}
for (I i = 0; i < 4; i++) {
if (node->child[i] != NULL)
*dsp++ = node->child[i];
}
} }
} }
@ -170,7 +173,7 @@ Hd *gc_alloc(Vm *vm, Z sz) {
Gc *gc = &vm->gc; Gc *gc = &vm->gc;
sz = ALIGN(sz); sz = ALIGN(sz);
if (gc->from.free + sz > gc->from.end) { if (gc->from.free + sz > gc->from.end) {
gc_collect(vm); gc_collect(vm, 0);
if (gc->from.free + sz > gc->from.end) { if (gc->from.free + sz > gc->from.end) {
fprintf(stderr, "out of memory (requested %" PRIdPTR "bytes\n", sz); fprintf(stderr, "out of memory (requested %" PRIdPTR "bytes\n", sz);
abort(); abort();

View file

@ -32,7 +32,7 @@ V gc_deinit(Gc *);
typedef struct Vm Vm; typedef struct Vm Vm;
V gc_collect(Vm *); V gc_collect(Vm *, I);
Hd *gc_alloc(Vm *, Z); Hd *gc_alloc(Vm *, Z);
#endif #endif

View file

@ -90,7 +90,7 @@ V vm_deinit(Vm *vm) {
vm->dictionary = NULL; vm->dictionary = NULL;
// Run final GC pass // Run final GC pass
gc_collect(vm); gc_collect(vm, 1);
gc_deinit(&vm->gc); gc_deinit(&vm->gc);
} }
@ -191,12 +191,26 @@ I vm_run(Vm *vm, Bc *chunk, I offset) {
(void)vm_pop(vm); (void)vm_pop(vm);
break; break;
} }
case OP_2DROP: {
(void)vm_pop(vm);
(void)vm_pop(vm);
break;
}
case OP_DUP: { case OP_DUP: {
O obj = vm_pop(vm); O obj = vm_pop(vm);
vm_push(vm, obj); vm_push(vm, obj);
vm_push(vm, obj); vm_push(vm, obj);
break; break;
} }
case OP_2DUP: {
O obj2 = vm_pop(vm);
O obj1 = vm_pop(vm);
vm_push(vm, obj1);
vm_push(vm, obj1);
vm_push(vm, obj2);
vm_push(vm, obj2);
break;
}
case OP_SWAP: { case OP_SWAP: {
O b = vm_pop(vm); O b = vm_pop(vm);
O a = vm_pop(vm); O a = vm_pop(vm);
@ -204,6 +218,17 @@ I vm_run(Vm *vm, Bc *chunk, I offset) {
vm_push(vm, a); vm_push(vm, a);
break; break;
} }
case OP_2SWAP: {
O d = vm_pop(vm);
O c = vm_pop(vm);
O b = vm_pop(vm);
O a = vm_pop(vm);
vm_push(vm, d);
vm_push(vm, c);
vm_push(vm, b);
vm_push(vm, a);
break;
}
case OP_NIP: { case OP_NIP: {
/* a b -> b */ /* a b -> b */
O b = vm_pop(vm); O b = vm_pop(vm);
@ -244,10 +269,24 @@ I vm_run(Vm *vm, Bc *chunk, I offset) {
vm_tpush(vm, vm_pop(vm)); vm_tpush(vm, vm_pop(vm));
break; break;
} }
case OP_2TOR: {
O obj2 = vm_pop(vm);
O obj1 = vm_pop(vm);
vm_tpush(vm, obj1);
vm_tpush(vm, obj2);
break;
}
case OP_FROMR: { case OP_FROMR: {
vm_push(vm, vm_tpop(vm)); vm_push(vm, vm_tpop(vm));
break; break;
} }
case OP_2FROMR: {
O obj2 = vm_tpop(vm);
O obj1 = vm_tpop(vm);
vm_push(vm, obj1);
vm_push(vm, obj2);
break;
}
case OP_DOWORD: { case OP_DOWORD: {
I idx = decode_sleb128(&vm->ip); I idx = decode_sleb128(&vm->ip);
Dt *word = vm->chunk->symbols.items[idx].resolved; Dt *word = vm->chunk->symbols.items[idx].resolved;

View file

@ -13,21 +13,26 @@
enum { enum {
OP_NOP = 0, OP_NOP = 0,
OP_CONST, // Push constant to stack OP_CONST,
OP_NIL, // Push constant to stack OP_NIL,
OP_DROP, OP_DROP,
OP_2DROP,
OP_DUP, OP_DUP,
OP_2DUP,
OP_SWAP, OP_SWAP,
OP_2SWAP,
OP_NIP, OP_NIP,
OP_OVER, OP_OVER,
OP_BURY, OP_BURY,
OP_DIG, OP_DIG,
OP_TOR, // Push from stack to retain stack OP_TOR,
OP_FROMR, // Push from retain stack to stack OP_2TOR,
OP_DOWORD, // Call word from dictionary by name hash OP_FROMR,
OP_2FROMR,
OP_DOWORD,
OP_CALL, OP_CALL,
OP_TAIL_DOWORD, // Tail call to dictionary word (reuses current frame) OP_TAIL_DOWORD,
OP_TAIL_CALL, // Tail call to quotation (reuses current frame) OP_TAIL_CALL,
OP_PRIM, OP_PRIM,
OP_COMPOSE, OP_COMPOSE,
OP_CURRY, OP_CURRY,

12
std.grr
View file

@ -9,7 +9,12 @@ def when { [] if }
def unless { swap when } def unless { swap when }
def dip { swap [] curry compose call } def dip { swap [] curry compose call }
def 2dip { swap [dip] dip }
def 3dip { swap [2dip] dip }
def keep { over [call] dip } def keep { over [call] dip }
def 2keep { [2dup] dip 2dip }
def bi { [keep] dip call } def bi { [keep] dip call }
def tri { [[keep] dip keep] dip call } def tri { [[keep] dip keep] dip call }
@ -18,3 +23,10 @@ def times {
[drop drop] [drop drop]
[swap over >r >r call r> 1 - r> times]; [swap over >r >r call r> 1 - r> times];
} }
def while {
swap dup bury >r >r
if: call dup
[r> dup >r call r> r> swap while]
[drop r> drop r> drop];
}