progress.

This commit is contained in:
2026-02-20 15:54:29 -05:00
parent 13e1f09b60
commit 7b738e037c

View File

@@ -64,6 +64,14 @@ global U8 vm_rax = 0; // Top
global U8 vm_rdx = 0; // Next
global U8 vm_globals[16] = {0};
// Dictionary
typedef struct {
U4 val;
U4 offset;
} DictEntry;
global DictEntry dict[256];
global U8 dict_count = 0;
#pragma clang optimize off
void* memset(void* dest, int c, U8 count) {
U1* bytes = (U1*)dest;
@@ -109,64 +117,102 @@ internal void emit32(U4 val) {
}
}
internal void compile_word(U4 tag, U4 val) {
if (tag == tmpl(STag, Data)) {
// mov rdx, rax
emit8(0x48); emit8(0x89); emit8(0xC2);
// mov rax, imm32
emit8(0x48); emit8(0xC7); emit8(0xC0); emit32(val);
} else if (tag == tmpl(STag, Imm) || tag == tmpl(STag, Call)) {
if (val == ID2('S','W')) { // SWAP: xchg rax, rdx
emit8(0x48); emit8(0x87); emit8(0xC2);
} else if (val == ID2('M','*')) { // MULT: imul rax, rdx
emit8(0x48); emit8(0x0F); emit8(0xAF); emit8(0xC2);
} else if (val == ID2('+',' ')) { // ADD: add rax, rdx
emit8(0x48); emit8(0x01); emit8(0xD0);
} else if (val == ID2('@',' ')) { // FETCH: mov rax, QWORD PTR [rcx + rax*8]
emit8(0x48); emit8(0x8B); emit8(0x04); emit8(0xC1);
} else if (val == ID2('-','1')) { // DEC: dec rax
emit8(0x48); emit8(0xFF); emit8(0xC8);
} else if (val == ID2('!',' ')) { // STORE: mov QWORD PTR [rcx + rax*8], rdx
emit8(0x48); emit8(0x89); emit8(0x14); emit8(0xC1);
} else if (val == ID2('R','0')) { // RET_IF_ZERO: test rax, rax; jnz +9; epilogue; ret
emit8(0x48); emit8(0x85); emit8(0xC0); // test rax, rax
emit8(0x75); emit8(0x09); // jnz skip_ret (+9 bytes)
emit8(0x48); emit8(0x89); emit8(0x41); emit8(0x70); // mov [rcx+112], rax
emit8(0x48); emit8(0x89); emit8(0x51); emit8(0x78); // mov [rcx+120], rdx
emit8(0xC3); // ret
} else if (val == ID2('F','S')) { // F_STEP (Inlined Compiler Macro)
compile_word(tmpl(STag, Data), 0);
compile_word(tmpl(STag, Imm), ID2('@',' '));
compile_word(tmpl(STag, Imm), ID2('R','0'));
compile_word(tmpl(STag, Data), 1);
compile_word(tmpl(STag, Imm), ID2('@',' '));
compile_word(tmpl(STag, Data), 0);
compile_word(tmpl(STag, Imm), ID2('@',' '));
compile_word(tmpl(STag, Imm), ID2('M','*'));
compile_word(tmpl(STag, Data), 1);
compile_word(tmpl(STag, Imm), ID2('!',' '));
compile_word(tmpl(STag, Data), 0);
compile_word(tmpl(STag, Imm), ID2('@',' '));
compile_word(tmpl(STag, Imm), ID2('-','1'));
compile_word(tmpl(STag, Data), 0);
compile_word(tmpl(STag, Imm), ID2('!',' '));
internal void compile_action(U4 val) {
if (val == ID2('S','W')) { // SWAP: xchg rax, rdx
emit8(0x48); emit8(0x87); emit8(0xC2);
return;
} else if (val == ID2('M','*')) { // MULT: imul rax, rdx
emit8(0x48); emit8(0x0F); emit8(0xAF); emit8(0xC2);
return;
} else if (val == ID2('+',' ')) { // ADD: add rax, rdx
emit8(0x48); emit8(0x01); emit8(0xD0);
return;
} else if (val == ID2('@',' ')) { // FETCH: mov rax, QWORD PTR [rcx + rax*8]
emit8(0x48); emit8(0x8B); emit8(0x04); emit8(0xC1);
return;
} else if (val == ID2('-','1')) { // DEC: dec rax
emit8(0x48); emit8(0xFF); emit8(0xC8);
return;
} else if (val == ID2('!',' ')) { // STORE: mov QWORD PTR [rcx + rax*8], rdx
emit8(0x48); emit8(0x89); emit8(0x14); emit8(0xC1);
return;
} else if (val == ID2('R','0')) { // RET_IF_ZERO: test rax, rax; jnz +1; ret
emit8(0x48); emit8(0x85); emit8(0xC0); // test rax, rax
emit8(0x75); emit8(0x01); // jnz skip_ret (+1 byte)
emit8(0xC3); // ret
return;
} else if (val == ID2('R','E')) { // RET
emit8(0xC3);
return;
}
// Dictionary Resolver (Call User Word)
for (U8 i = 0; i < dict_count; i++) {
if (dict[i].val == val) {
U4 target = dict[i].offset;
U4 current = code_arena.used;
S4 rel32 = (S4)target - (S4)(current + 5);
emit8(0xE8); // CALL rel32
emit32((U4)rel32);
return;
}
}
}
internal void compile_and_run_tape(void) {
IA_ void compile_and_run_tape(void) {
farena_reset(&code_arena);
dict_count = 0;
// Prologue: Load VM state from globals[14] and [15]
emit8(0x48); emit8(0x8B); emit8(0x41); emit8(0x70); // mov rax, [rcx+112]
emit8(0x48); emit8(0x8B); emit8(0x51); emit8(0x78); // mov rdx, [rcx+120]
// Compile the selected tokens
U4*r tape_ptr = C_(U4*r, tape_arena.start);
B4 in_def = false;
U4 def_jmp_offset = 0;
for (U8 i = 0; i <= cursor_idx; i++) {
compile_word(UNPACK_TAG(tape_ptr[i]), UNPACK_VAL(tape_ptr[i]));
U4 tag = UNPACK_TAG(tape_ptr[i]);
U4 val = UNPACK_VAL(tape_ptr[i]);
if (tag == tmpl(STag, Define)) {
if (!in_def) {
emit8(0xE9); // JMP rel32 (Skip over definition body)
def_jmp_offset = code_arena.used;
emit32(0);
in_def = true;
}
if (dict_count < 256) {
dict[dict_count].val = val;
dict[dict_count].offset = code_arena.used;
dict_count++;
}
} else if (tag == tmpl(STag, Call)) {
compile_action(val);
if (val == ID2('R','E') && in_def) {
// End of definition block, patch the jump
U4 current = code_arena.used;
*(U4*)(code_arena.start + def_jmp_offset) = current - (def_jmp_offset + 4);
in_def = false;
}
} else if (tag == tmpl(STag, Data)) {
emit8(0x48); emit8(0x89); emit8(0xC2); // mov rdx, rax
emit8(0x48); emit8(0xC7); emit8(0xC0); emit32(val); // mov rax, imm32
} else if (tag == tmpl(STag, Imm)) {
if (in_def) {
// If we execute something, we jump out of def block first
U4 current = code_arena.used;
*(U4*)(code_arena.start + def_jmp_offset) = current - (def_jmp_offset + 4);
in_def = false;
}
compile_action(val);
}
}
if (in_def) {
// If we hit cursor inside a definition, patch jump so it doesn't crash on execution
U4 current = code_arena.used;
*(U4*)(code_arena.start + def_jmp_offset) = current - (def_jmp_offset + 4);
}
// Epilogue: Save VM state back to globals
@@ -432,11 +478,37 @@ int main(void) {
scatter(PACK_TOKEN(tmpl(STag, Format), 0xA)); // Newline
// Define the FS (Factorial Step) word in memory
scatter(PACK_TOKEN(tmpl(STag, Define), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Data), 0));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('@',' ')));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('R','0')));
scatter(PACK_TOKEN(tmpl(STag, Format), 0xA)); // Newline
scatter(PACK_TOKEN(tmpl(STag, Data), 1));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('@',' ')));
scatter(PACK_TOKEN(tmpl(STag, Data), 0));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('@',' ')));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('M','*')));
scatter(PACK_TOKEN(tmpl(STag, Data), 1));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('!',' ')));
scatter(PACK_TOKEN(tmpl(STag, Format), 0xA)); // Newline
scatter(PACK_TOKEN(tmpl(STag, Data), 0));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('@',' ')));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('-','1')));
scatter(PACK_TOKEN(tmpl(STag, Data), 0));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('!',' ')));
scatter(PACK_TOKEN(tmpl(STag, Call), ID2('R','E'))); // Return!
scatter(PACK_TOKEN(tmpl(STag, Format), 0xA)); // Newline
// Call it
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S'))); // ^FS
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
scatter(PACK_TOKEN(tmpl(STag, Imm), ID2('F','S')));
MS_WNDCLASSA wc;
mem_fill(u8_(& wc), 0, sizeof(wc));