From 7b738e037c3d8f541fbbe5bbb248700a4310a9f2 Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 20 Feb 2026 15:54:29 -0500 Subject: [PATCH] progress. --- attempt_1/main.c | 166 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 119 insertions(+), 47 deletions(-) diff --git a/attempt_1/main.c b/attempt_1/main.c index 7721719..c6bac6a 100644 --- a/attempt_1/main.c +++ b/attempt_1/main.c @@ -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));