From 9db17482490557cb14e8eabb20c3a0c2f027966c Mon Sep 17 00:00:00 2001 From: Ed_ Date: Fri, 20 Feb 2026 20:33:39 -0500 Subject: [PATCH] adjustments --- .editorconfig | 50 ++ CONVENTIONS.md | 10 +- attempt_1/attempt_1.md | 2 +- attempt_1/duffle.amd64.win32.h | 147 ++-- attempt_1/main.c | 1165 ++++++++++++++++---------------- scripts/build.attempt_1.c.ps1 | 1 - 6 files changed, 734 insertions(+), 641 deletions(-) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..6d1ff5e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,50 @@ +root = true + +[*.s] +indent_style = tab +indent_size = 2 + +[*.asm] +indent_style = tab +indent_size = 2 + +[*.refactor] +indent_style = space +indent_size = 4 + +[*.md] +indent_style = space +indent_size = 4 + +[*.c] +indent_style = tab +indent_size = 2 +charset = utf-8 + +[*.cpp] +indent_style = tab +indent_size = 2 +charset = utf-8 + +[*.h] +indent_style = tab +indent_size = 2 +charset = utf-8 + +[*.hpp] +indent_style = tab +indent_size = 2 +charset = utf-8 + +[*.{ps1, psm1}] +indent_style = tab +indent_size = 4 + +[*.odin] +indent_style = tab +indent_size = 2 +charset = utf-8 + +[*.{natvis, natstepfilter}] +indent_style = tab +indent_size = 4 diff --git a/CONVENTIONS.md b/CONVENTIONS.md index 3cbb4ca..ed298ef 100644 --- a/CONVENTIONS.md +++ b/CONVENTIONS.md @@ -27,7 +27,7 @@ This document outlines the strict C style and architectural conventions expected * **Case:** Strictly use `lower_snake_case` for all functions and variables. * **Types:** Use `PascalCase` for type names (`FArena`, `SWord_Tag`). * **WinAPI Symbols:** When declaring foreign Win32 symbols, prefix the C function name with `ms_` (using `lower_snake_case`) and use the `asm("SymbolName")` attribute to link it to the actual DLL export. - * *Correct:* `WinAPI U2 ms_register_class_a(const MS_WNDCLASSA* lpWndClass) asm("RegisterClassA");` + * *Correct:* `WinAPI U2 ms_register_class_a(MS_WNDCLASSA const* lpWndClass) asm("RegisterClassA");` * *Incorrect:* `WinAPI U2 RegisterClassA(...);` ## 4. Formatting & Layout @@ -36,6 +36,12 @@ This document outlines the strict C style and architectural conventions expected * **Conditionals:** Always place `else if` and `else` statements on a new line, un-nested from the previous closing brace. ## 5. Memory Management -* **No Standard Library:** The environment is built with `-nostdlib` and `-ffreestanding`. Never include ``, ``, etc. +* **Standard Library:** The C standard library is linked, but headers like `` or `` should not be included directly. Required functions should be declared manually if needed, or accessed via compiler builtins. * **Arenas over Malloc:** Use `FArena` and its associated macros (`farena_push`, `farena_push_type`, `farena_reset`) for all dynamic memory allocations. Do not use raw pointers with manual arithmetic when an arena can handle it. * **Memory Ops:** Use `mem_fill` and `mem_copy` instead of standard `memset`/`memcpy` within the application logic. + +## 6. Type Qualifiers +* **`const` Placement:** The `const` keyword must always be placed to the right of the type it modifies. This maintains a consistent right-to-left reading of type declarations. + * **Correct:** `char const* my_ptr;` (Pointer to a constant character) + * **Correct:** `U4 const* const my_ptr;` (Constant pointer to a constant U4) + * **Incorrect:** `const char* my_ptr;` diff --git a/attempt_1/attempt_1.md b/attempt_1/attempt_1.md index 27cef8e..9673646 100644 --- a/attempt_1/attempt_1.md +++ b/attempt_1/attempt_1.md @@ -1,7 +1,7 @@ # Technical Outline: Attempt 1 ## Overview -`attempt_1` is a minimal, `-nostdlib` C program that serves as a proof-of-concept for the "Lottes/Onat" sourceless ColorForth paradigm. It successfully integrates a visual editor, a live JIT compiler, and an execution environment into a single, cohesive Win32 application that runs without any external dependencies or the C runtime. +`attempt_1` is a minimal C program that serves as a proof-of-concept for the "Lottes/Onat" sourceless ColorForth paradigm. It successfully integrates a visual editor, a live JIT compiler, and an execution environment into a single, cohesive Win32 application that links against the C runtime but avoids direct includes of standard headers, using manually declared functions instead. The application presents a visual grid of 32-bit tokens and allows the user to navigate and edit them directly. On every keypress, the token array is re-compiled into x86-64 machine code and executed, with the results (register states and global memory) displayed instantly in the HUD. diff --git a/attempt_1/duffle.amd64.win32.h b/attempt_1/duffle.amd64.win32.h index 7814d93..9a13c9e 100644 --- a/attempt_1/duffle.amd64.win32.h +++ b/attempt_1/duffle.amd64.win32.h @@ -159,10 +159,11 @@ IA_ U8 atm_swap_u8(U8*r addr, U8 value){asm volatile("lock xchgq %0,%1":"=r"(val #pragma endregion Thread Coherence #pragma region Debug -WinAPI void process_exit(U4 status) asm("ExitProcess"); +WinAPI void ms_exit_process(U4 uExitCode) asm("ExitProcess"); // Kernel 32 + #define debug_trap() __builtin_debugtrap() #if BUILD_DEBUG -IA_ void assert(U8 cond) { if(cond){return;} else{debug_trap(); process_exit(1);} } +IA_ void assert(U8 cond) { if(cond){return;} else{debug_trap(); ms_exit_process(1);} } #else #define assert(cond) #endif @@ -242,6 +243,13 @@ IA_ Slice mem_bump(U8 start, U8 cap, U8*r used, U8 amount) { } #pragma endregion Memory +#pragma region Encoding +IA_ void u64_to_hex(U8 val, char* buf, S4 chars) { + static const char hex_chars[] = "0123456789ABCDEF"; + for(S1 i = chars - 1; i >= 0; --i) { buf[i] = hex_chars[val & 0xF]; val >>= 4; } +} +#pragma endregion Encoding + #pragma region Math #define u8_max 0xffffffffffffffffull @@ -350,9 +358,6 @@ IA_ U8 hash64_fnv1a_ret(Slice data, U8 seed) { U8 h = 0; hash64_fnv1a(& h, data, #define MS_STD_INPUT u4_(-10) #define MS_STD_OUTPUT u4_(-11) typedef Struct_(MS_Handle){U8 id;}; -WinAPI MS_Handle ms_get_std_handle(U4 handle_type) asm("GetStdHandle"); -WinAPI B4 ms_read_console(MS_Handle handle, UTF8*r buffer, U4 to_read, U4*r num_read, U8 reserved_input_control) asm("ReadConsoleA"); -WinAPI B4 ms_write_console(MS_Handle handle, UTF8 const*r buffer, U4 chars_to_write, U4*v chars_written, U8 reserved) asm("WriteConsoleA"); #pragma endregion IO #pragma region Key Table Linear (KTL) @@ -588,10 +593,10 @@ IA_ void str8gen_append_fmt(Str8Gen*r gen, Str8 fmt, KTL_Str8 tbl) { #pragma region OS_GDI_And_Minimal // --- WinAPI Minimal Definitions --- typedef struct MS_WNDCLASSA { - U4 style; - S8 (*lpfnWndProc)(void*, U4, U8, S8); - S4 cbClsExtra; - S4 cbWndExtra; + U4 style; + S8 (*lpfnWndProc)(void*, U4, U8, S8); + S4 cbClsExtra; + S4 cbWndExtra; void* hInstance; void* hIcon; void* hCursor; @@ -599,50 +604,96 @@ typedef struct MS_WNDCLASSA { char const* lpszMenuName; char const* lpszClassName; } MS_WNDCLASSA; - -typedef struct MS_POINT { S4 x, y; } MS_POINT; -typedef struct MS_MSG { void* hwnd; U4 message; U8 wParam; S8 lParam; U4 time; MS_POINT pt; } MS_MSG; -typedef struct MS_RECT { S4 left, top, right, bottom; } MS_RECT; +typedef struct MS_POINT { S4 x, y; } MS_POINT; +typedef struct MS_MSG { void* hwnd; U4 message; U8 wParam; S8 lParam; U4 time; MS_POINT pt; } MS_MSG; +typedef struct MS_RECT { S4 left, top, right, bottom; } MS_RECT; typedef struct MS_PAINTSTRUCT { void* hdc; S4 fErase; MS_RECT rcPaint; S4 fRestore; S4 fIncUpdate; U1 rgbReserved[32]; } MS_PAINTSTRUCT; -// Win32 API declarations +// --- Kernel32 --- +WinAPI void ms_exit_process(U4 uExitCode) asm("ExitProcess"); +WinAPI MS_Handle ms_get_std_handle(U4 handle_type) asm("GetStdHandle"); WinAPI void* ms_virtual_alloc(void* lpAddress, U8 dwSize, U4 flAllocationType, U4 flProtect) asm("VirtualAlloc"); -WinAPI void ms_exit_process(U4 uExitCode) asm("ExitProcess"); -WinAPI U2 ms_register_class_a(const MS_WNDCLASSA* lpWndClass) asm("RegisterClassA"); -WinAPI void* ms_create_window_ex_a(U4 dwExStyle, char const* lpClassName, char const* lpWindowName, U4 dwStyle, S4 X, S4 Y, S4 nWidth, S4 nHeight, void* hWndParent, void* hMenu, void* hInstance, void* lpParam) asm("CreateWindowExA"); -WinAPI S4 ms_show_window(void* hWnd, S4 nCmdShow) asm("ShowWindow"); -WinAPI S4 ms_get_message_a(MS_MSG* lpMsg, void* hWnd, U4 wMsgFilterMin, U4 wMsgFilterMax) asm("GetMessageA"); -WinAPI S4 ms_translate_message(const MS_MSG* lpMsg) asm("TranslateMessage"); -WinAPI S8 ms_dispatch_message_a(const MS_MSG* lpMsg) asm("DispatchMessageA"); -WinAPI S8 ms_def_window_proc_a(void* hWnd, U4 Msg, U8 wParam, S8 lParam) asm("DefWindowProcA"); -WinAPI void ms_post_quit_message(S4 nExitCode) asm("PostQuitMessage"); -WinAPI S4 ms_invalidate_rect(void* hWnd, const MS_RECT* lpRect, S4 bErase) asm("InvalidateRect"); -WinAPI void* ms_begin_paint(void* hWnd, MS_PAINTSTRUCT* lpPaint) asm("BeginPaint"); -WinAPI S4 ms_end_paint(void* hWnd, const MS_PAINTSTRUCT* lpPaint) asm("EndPaint"); -WinAPI U4 ms_set_text_color(void* hdc, U4 color) asm("SetTextColor"); -WinAPI U4 ms_set_bk_color(void* hdc, U4 color) asm("SetBkColor"); -WinAPI S4 ms_text_out_a(void* hdc, S4 x, S4 y, char const* lpString, S4 c) asm("TextOutA"); -WinAPI void* ms_get_stock_object(S4 i) asm("GetStockObject"); -WinAPI void* ms_create_font_a(S4 cHeight, S4 cWidth, S4 cEscapement, S4 cOrientation, S4 cWeight, U4 bItalic, U4 bUnderline, U4 bStrikeOut, U4 iCharSet, U4 iOutPrecision, U4 iClipPrecision, U4 iQuality, U4 iPitchAndFamily, char const* pszFaceName) asm("CreateFontA"); -WinAPI void* ms_select_object(void* hdc, void* h) asm("SelectObject"); -WinAPI S4 ms_rectangle(void* hdc, S4 left, S4 top, S4 right, S4 bottom) asm("Rectangle"); -WinAPI S4 ms_set_bk_mode(void* hdc, S4 mode) asm("SetBkMode"); -WinAPI void* ms_create_solid_brush(U4 color) asm("CreateSolidBrush"); -WinAPI S4 ms_delete_object(void* ho) asm("DeleteObject"); -WinAPI S2 ms_get_async_key_state(S4 vKey) asm("GetAsyncKeyState"); +WinAPI B4 ms_read_console( + MS_Handle handle, + UTF8*r buffer, + U4 to_read, + U4*r num_read, + U8 reserved_input_control +) asm("ReadConsoleA"); +WinAPI B4 ms_write_console( + MS_Handle handle, + UTF8 const*r buffer, + U4 chars_to_write, + U4*v chars_written, + U8 reserved +) asm("WriteConsoleA"); -#define MS_MEM_COMMIT 0x00001000 -#define MS_MEM_RESERVE 0x00002000 -#define MS_PAGE_READWRITE 0x04 -#define MS_WM_DESTROY 0x0002 -#define MS_WM_PAINT 0x000F -#define MS_WM_KEYDOWN 0x0100 +// --- User32 --- +WinAPI U2 ms_register_class_a(MS_WNDCLASSA const* lpWndClass) asm("RegisterClassA"); +WinAPI void* ms_create_window_ex_a( + U4 dwExStyle, + char const* lpClassName, + char const* lpWindowName, + U4 dwStyle, + S4 X, + S4 Y, + S4 nWidth, + S4 nHeight, + void* hWndParent, + void* hMenu, + void* hInstance, + void* lpParam +) asm("CreateWindowExA"); +WinAPI S4 ms_show_window(void* hWnd, S4 nCmdShow) asm("ShowWindow"); +WinAPI S4 ms_get_message_a(MS_MSG* lpMsg, void* hWnd, U4 wMsgFilterMin, U4 wMsgFilterMax) asm("GetMessageA"); +WinAPI S4 ms_translate_message(MS_MSG const* lpMsg) asm("TranslateMessage"); +WinAPI S8 ms_dispatch_message_a(MS_MSG const* lpMsg) asm("DispatchMessageA"); +WinAPI S8 ms_def_window_proc_a(void* hWnd, U4 Msg, U8 wParam, S8 lParam) asm("DefWindowProcA"); +WinAPI void ms_post_quit_message(S4 nExitCode) asm("PostQuitMessage"); +WinAPI S4 ms_invalidate_rect(void* hWnd, MS_RECT const* lpRect, S4 bErase) asm("InvalidateRect"); +WinAPI S2 ms_get_async_key_state(S4 vKey) asm("GetAsyncKeyState"); + +// --- GDI32 --- +WinAPI void* ms_begin_paint(void* hWnd, MS_PAINTSTRUCT* lpPaint) asm("BeginPaint"); +WinAPI S4 ms_end_paint(void* hWnd, MS_PAINTSTRUCT const* lpPaint) asm("EndPaint"); +WinAPI U4 ms_set_text_color(void* hdc, U4 color) asm("SetTextColor"); +WinAPI U4 ms_set_bk_color(void* hdc, U4 color) asm("SetBkColor"); +WinAPI S4 ms_text_out_a(void* hdc, S4 x, S4 y, char const* lpString, S4 c) asm("TextOutA"); +WinAPI void* ms_get_stock_object(S4 i) asm("GetStockObject"); +WinAPI void* ms_create_font_a( + S4 cHeight, + S4 cWidth, + S4 cEscapement, + S4 cOrientation, + S4 cWeight, + U4 bItalic, + U4 bUnderline, + U4 bStrikeOut, + U4 iCharSet, + U4 iOutPrecision, + U4 iClipPrecision, + U4 iQuality, + U4 iPitchAndFamily, + char const* pszFaceName +) asm("CreateFontA"); +WinAPI void* ms_select_object(void* hdc, void* h) asm("SelectObject"); +WinAPI S4 ms_rectangle(void* hdc, S4 left, S4 top, S4 right, S4 bottom) asm("Rectangle"); +WinAPI S4 ms_set_bk_mode(void* hdc, S4 mode) asm("SetBkMode"); +WinAPI void* ms_create_solid_brush(U4 color) asm("CreateSolidBrush"); +WinAPI S4 ms_delete_object(void* ho) asm("DeleteObject"); + +#define MS_MEM_COMMIT 0x00001000 +#define MS_MEM_RESERVE 0x00002000 +#define MS_PAGE_READWRITE 0x04 +#define MS_WM_DESTROY 0x0002 +#define MS_WM_PAINT 0x000F +#define MS_WM_KEYDOWN 0x0100 #define MS_WS_OVERLAPPEDWINDOW 0x00CF0000 -#define MS_WS_VISIBLE 0x10000000 -#define MS_VK_LEFT 0x25 -#define MS_VK_UP 0x26 -#define MS_VK_RIGHT 0x27 -#define MS_VK_DOWN 0x28 +#define MS_WS_VISIBLE 0x10000000 +#define MS_VK_LEFT 0x25 +#define MS_VK_UP 0x26 +#define MS_VK_RIGHT 0x27 +#define MS_VK_DOWN 0x28 #define MS_PAGE_EXECUTE_READWRITE 0x40 #pragma endregion OS_GDI_And_Minimal diff --git a/attempt_1/main.c b/attempt_1/main.c index 20a46ba..1b0b0b5 100644 --- a/attempt_1/main.c +++ b/attempt_1/main.c @@ -1,56 +1,46 @@ -// Fundamental Boolean and Null types for no-std environment -#define true 1 -#define false 0 -#define NULL ((void*)0) - #include "duffle.amd64.win32.h" // --- Semantic Tags (Using X-Macros & Enum_) --- // Colors translated from Cozy-and-WIndy: // 0x00bbggrr Win32 format -typedef Enum_(U4, STag) { + #define Tag_Entries() \ - X(Define, "Define", 0x0018AEFF, ":") /* Orange-ish (Language.Type) */ \ - X(Call, "Call", 0x00D6A454, "~") /* Soft Blue (Language.Class) */ \ - X(Data, "Data", 0x0094BAA1, "$") /* Muted Green (Language.Number) */ \ - X(Imm, "Imm", 0x004AA4C2, "^") /* Sand/Yellow (Language.Keyword) */ \ - X(Comment, "Comment", 0x00AAAAAA, ".") /* Grey (Language.Comment) */ \ - X(Format, "Format", 0x003A2F3B, " ") /* Current Line BG for invisibles */ + X(Define, "Define", 0x0018AEFF, ":") /* Orange-ish (Language.Type) */ \ + X(Call, "Call", 0x00D6A454, "~") /* Soft Blue (Language.Class) */ \ + X(Data, "Data", 0x0094BAA1, "$") /* Muted Green (Language.Number) */ \ + X(Imm, "Imm", 0x004AA4C2, "^") /* Sand/Yellow (Language.Keyword) */ \ + X(Comment, "Comment", 0x00AAAAAA, ".") /* Grey (Language.Comment) */ \ + X(Format, "Format", 0x003A2F3B, " ") /* Current Line BG for invisibles */ +typedef Enum_(U4, STag) { #define X(n, s, c, p) tmpl(STag, n), - Tag_Entries() + Tag_Entries() #undef X - STag_Count, + STag_Count, }; - -// Helper array to fetch Hex colors for UI rendering based on STag global U4 tag_colors[] = { #define X(n, s, c, p) c, - Tag_Entries() + Tag_Entries() #undef X }; - -// Helper array to fetch the text prefix based on STag global const char* tag_prefixes[] = { #define X(n, s, c, p) p, - Tag_Entries() + Tag_Entries() #undef X }; - -// Helper array to fetch the full name of the STag global const char* tag_names[] = { #define X(n, s, c, p) s, - Tag_Entries() + Tag_Entries() #undef X }; // Token Packing: 28 bits payload | 4 bits tag -#define PACK_TOKEN(tag, val) (((U4)(tag) << 28) | ((U4)(val) & 0x0FFFFFFF)) -#define UNPACK_TAG(token) (((token) >> 28) & 0x0F) -#define UNPACK_VAL(token) ((token) & 0x0FFFFFFF) +#define pack_token(tag, val) ((u4_(tag) << 28) | (u4_(val) & 0x0FFFFFFF)) +#define unpack_tag(token) ( ((token) >> 28) & 0x0F) +#define unpack_val(token) ( (token) & 0x0FFFFFFF) // 2-Character Mapped Dictionary Helper -#define ID2(a, b) (((U4)(a) << 8) | (U4)(b)) +#define id2(a, b) ((u4_(a) << 8) | u4_(b)) #define TOKENS_PER_ROW 8 @@ -60,209 +50,207 @@ global const char* tag_names[] = { // The Tape Drive (Using FArena from duffle) global FArena tape_arena; global FArena anno_arena; -global U8 cursor_idx = 0; +global U8 cursor_idx = 0; global U4 editor_mode = MODE_NAV; // Executable Code Arena (The JIT) global FArena code_arena; // VM State: 2-Reg Stack + Global Memory -global U8 vm_rax = 0; // Top -global U8 vm_rdx = 0; // Next +global U8 vm_rax = 0; // Top +global U8 vm_rdx = 0; // Next global U8 vm_globals[16] = {0}; // Execution Mode & Logging -global B4 run_full = false; +global B4 run_full = false; global U8 log_buffer[16] = {0}; -global U4 log_count = 0; +global U4 log_count = 0; // UI State global S4 scroll_y_offset = 0; void ms_builtin_print(U8 val) { - if (log_count < 16) { - log_buffer[log_count++] = val; - } + if (log_count < 16) { + log_buffer[log_count++] = val; + } } // Dictionary typedef struct { - U4 val; - U4 offset; + U4 val; + U4 offset; } DictEntry; global DictEntry dict[256]; -global U8 dict_count = 0; +global U8 dict_count = 0; IA_ void scatter(U4 token, const char* anno_str) { - if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) { - U4*r ptr = C_(U4*r, tape_arena.start + tape_arena.used); - ptr[0] = token; - tape_arena.used += sizeof(U4); - - U8*r aptr = C_(U8*r, anno_arena.start + anno_arena.used); - aptr[0] = 0; - if (anno_str) { - char* dest = (char*)aptr; - int i = 0; - while(i < 8 && anno_str[i]) { - dest[i] = anno_str[i]; - i++; - } - } - anno_arena.used += sizeof(U8); - } -} - -IA_ void u64_to_hex(U8 val, char* buf, S4 chars) { - static const char hex_chars[] = "0123456789ABCDEF"; - for(S1 i = chars - 1; i >= 0; --i) { buf[i] = hex_chars[val & 0xF]; val >>= 4; } + if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) { + U4*r ptr = u4_r(tape_arena.start + tape_arena.used); + ptr[0] = token; + tape_arena.used += sizeof(U4); + U8*r aptr = u8_r(anno_arena.start + anno_arena.used); + aptr[0] = 0; + if (anno_str) { + char* dest = (char*)aptr; + int i = 0; + while(i < 8 && anno_str[i]) { + dest[i] = anno_str[i]; + i++; + } + } + anno_arena.used += sizeof(U8); + } } // --- Minimal x86-64 Emitter --- internal void emit8(U1 b) { - if (code_arena.used + 1 <= code_arena.capacity) { - U1* ptr = (U1*)(code_arena.start + code_arena.used); - *ptr = b; - code_arena.used += 1; - } + if (code_arena.used + 1 <= code_arena.capacity) { + U1*r ptr = u1_r(code_arena.start + code_arena.used); + ptr[0] = b; + code_arena.used += 1; + } } - internal void emit32(U4 val) { - if (code_arena.used + 4 <= code_arena.capacity) { - U4* ptr = (U4*)(code_arena.start + code_arena.used); - *ptr = val; - code_arena.used += 4; - } + if (code_arena.used + 4 <= code_arena.capacity) { + U4*r ptr = u4_r(code_arena.start + code_arena.used); + ptr[0] = val; + code_arena.used += 4; + } } -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; - } else if (val == ID2('P','R')) { // PRINT: call ms_builtin_print - emit8(0x51); // push rcx - emit8(0x52); // push rdx - emit8(0x48); emit8(0x83); emit8(0xEC); emit8(0x20); // sub rsp, 32 - emit8(0x48); emit8(0x89); emit8(0xC1); // mov rcx, rax - emit8(0x49); emit8(0xB8); // mov r8, imm64 - U8 addr = (U8)&ms_builtin_print; - emit32((U4)(addr & 0xFFFFFFFF)); - emit32((U4)(addr >> 32)); - emit8(0x41); emit8(0xFF); emit8(0xD0); // call r8 - emit8(0x48); emit8(0x83); emit8(0xC4); emit8(0x20); // add rsp, 32 - emit8(0x5A); // pop rdx - emit8(0x59); // pop rcx - 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_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; + } else if (val == id2('P','R')) { // PRINT: call ms_builtin_print + emit8(0x51); // push rcx + emit8(0x52); // push rdx + emit8(0x48); emit8(0x83); emit8(0xEC); emit8(0x20); // sub rsp, 32 + emit8(0x48); emit8(0x89); emit8(0xC1); // mov rcx, rax + emit8(0x49); emit8(0xB8); // mov r8, imm64 + U8 addr = u8_(& ms_builtin_print); + emit32(u4_(addr & 0xFFFFFFFF)); + emit32(u4_(addr >> 32)); + emit8(0x41); emit8(0xFF); emit8(0xD0); // call r8 + emit8(0x48); emit8(0x83); emit8(0xC4); emit8(0x20); // add rsp, 32 + emit8(0x5A); // pop rdx + emit8(0x59); // pop rcx + return; + } + // Dictionary Resolver (Call User Word) + for (U8 entry = 0; entry < dict_count; entry++) { + if (dict[entry].val == val) { + U4 target = dict[entry].offset; + U4 current = code_arena.used; + S4 rel32 = s4_(target) - s4_(current + 5); + emit8(0xE8); // CALL rel32 + emit32(u4_(rel32)); + return; + } + } } -IA_ void compile_and_run_tape(void) { - farena_reset(&code_arena); - dict_count = 0; - log_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] +IA_ void compile_and_run_tape(void) +{ + farena_reset(& code_arena); + dict_count = 0; + log_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] - U4*r tape_ptr = C_(U4*r, tape_arena.start); - B4 in_def = false; - U4 def_jmp_offset = 0; + U4*r tape_ptr = u4_r(tape_arena.start); + B4 in_def = false; + U4 def_jmp_offset = 0; + U8 end_idx = run_full ? (tape_arena.used / sizeof(U4)) : (cursor_idx + 1); + for (U8 i = 0; i < end_idx; i++) + { + U4 tag = unpack_tag(tape_ptr[i]); + U4 val = unpack_val(tape_ptr[i]); + if (tag == STag_Define) + { + if (in_def == false) { + 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 == 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_r(code_arena.start + def_jmp_offset)[0] = 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_r(code_arena.start + def_jmp_offset)[0] = current - (def_jmp_offset + 4); + in_def = false; + } + compile_action(val); + } + } - U8 end_idx = run_full ? (tape_arena.used / sizeof(U4)) : (cursor_idx + 1); + 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_r(code_arena.start + def_jmp_offset)[0] = current - (def_jmp_offset + 4); + } - for (U8 i = 0; i < end_idx; i++) { - U4 tag = UNPACK_TAG(tape_ptr[i]); - U4 val = UNPACK_VAL(tape_ptr[i]); + // Epilogue: Save VM state back to globals + 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 - 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 - 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 - - // Cast code arena to function pointer and CALL it! - typedef void (*JIT_Func)(U8* globals_ptr); - JIT_Func func = (JIT_Func)code_arena.start; - func(vm_globals); - - // Read state for UI - vm_rax = vm_globals[14]; - vm_rdx = vm_globals[15]; + // Cast code arena to function pointer and CALL it! + typedef void JIT_Func(U8* globals_ptr); + JIT_Func* func = (JIT_Func*)code_arena.start; + func(vm_globals); + + // Read state for UI + vm_rax = vm_globals[14]; + vm_rdx = vm_globals[15]; } #define MS_WM_CHAR 0x0102 @@ -277,424 +265,423 @@ IA_ void compile_and_run_tape(void) { #define MS_VK_SHIFT 0x10 // --- Window Procedure --- -S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) { - U8 tape_count = tape_arena.used / sizeof(U4); - U4*r tape_ptr = C_(U4*r, tape_arena.start); +S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) +{ + U8 tape_count = tape_arena.used / sizeof(U4); + U4*r tape_ptr = C_(U4*r, tape_arena.start); + switch (msg) { + case MS_WM_CHAR: { + if (editor_mode != MODE_EDIT) return 0; + + U4 t = tape_ptr[cursor_idx]; + U4 tag = unpack_tag(t); + U4 val = unpack_val(t); + U1 c = u1_(wparam); + + // Skip control characters and the 'E' that triggered the mode + if (c < 32) break; - switch (msg) { - case MS_WM_CHAR: { - if (editor_mode != MODE_EDIT) return 0; - - U4 t = tape_ptr[cursor_idx]; - U4 tag = UNPACK_TAG(t); - U4 val = UNPACK_VAL(t); - U1 c = (U1)wparam; - - // Skip control characters and the 'E' that triggered the mode - if (c < 32) break; + if (tag == STag_Data) { + // Hex input + U4 digit = 16; + if (c >= '0' && c <= '9') digit = c - '0'; + if (c >= 'a' && c <= 'f') digit = c - 'a' + 10; + if (c >= 'A' && c <= 'F') digit = c - 'A' + 10; + if (digit < 16) { + val = ((val << 4) | digit) & 0x0FFFFFFF; + tape_ptr[cursor_idx] = pack_token(tag, val); + } + } + else if (tag != STag_Format) { + U8*r anno_ptr = u8_r(anno_arena.start); + char* anno_str = (char*) & anno_ptr[cursor_idx]; + int len = 0; + while (len < 8 && anno_str[len] != '\0' && anno_str[len] != ' ') len ++; + if (len < 8) { + anno_str[len] = (char)c; + for (int i = len + 1; i < 8; i++) anno_str[i] = '\0'; + // Update the 2-char token ID from the first 2 chars + char c1 = anno_str[0] ? anno_str[0] : ' '; + char c2 = anno_str[1] ? anno_str[1] : ' '; + val = id2(c1, c2); + tape_ptr[cursor_idx] = pack_token(tag, val); + } + } + vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals)); + compile_and_run_tape(); + ms_invalidate_rect(hwnd, nullptr, true); + return 0; + } + case MS_WM_KEYDOWN: { + if (wparam == 0x45 && editor_mode == MODE_NAV) { // 'E' + editor_mode = MODE_EDIT; + ms_invalidate_rect(hwnd, nullptr, true); + return 0; // Consume the keypress so it doesn't trigger WM_CHAR + } + if (wparam == 0x1B && editor_mode == MODE_EDIT) { // ESC + editor_mode = MODE_NAV; + ms_invalidate_rect(hwnd, nullptr, true); + return 0; + } + if (editor_mode == MODE_EDIT) { + if (wparam == MS_VK_BACK) { + U4 t = tape_ptr[cursor_idx]; + U4 tag = unpack_tag(t); + U4 val = unpack_val(t); + if (tag == STag_Data) { + val = val >> 4; + tape_ptr[cursor_idx] = pack_token(tag, val); + } + else if (tag != STag_Format) { + U8*r anno_ptr = C_(U8*r, anno_arena.start); + char* anno_str = (char*)&anno_ptr[cursor_idx]; + int len = 0; + while (len < 8 && anno_str[len] != '\0' && anno_str[len] != ' ') len++; + if (len > 0) { + anno_str[len - 1] = '\0'; + char c1 = anno_str[0] ? anno_str[0] : ' '; + char c2 = anno_str[1] ? anno_str[1] : ' '; + tape_ptr[cursor_idx] = pack_token(tag, id2(c1, c2)); + } + } + vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals)); + compile_and_run_tape(); + ms_invalidate_rect(hwnd, nullptr, true); + } + return 0; // Block navigation keys in Edit Mode + } + + if (wparam == MS_VK_RIGHT && cursor_idx < tape_count - 1) cursor_idx ++; + if (wparam == MS_VK_LEFT && cursor_idx > 0) cursor_idx --; + + if (wparam == MS_VK_UP) { + U8 line_start = cursor_idx; + while (line_start > 0 && unpack_tag(tape_ptr[line_start - 1]) != STag_Format) line_start--; + if (line_start > 0) { + U8 col = cursor_idx - line_start; + U8 prev_line_start = line_start - 1; + while (prev_line_start > 0 && unpack_tag(tape_ptr[prev_line_start - 1]) != STag_Format) prev_line_start--; + U8 prev_line_len = (line_start - 1) - prev_line_start; + cursor_idx = prev_line_start + (col < prev_line_len ? col : prev_line_len); + } + } + if (wparam == MS_VK_DOWN) { + U8 line_start = cursor_idx; + while (line_start > 0 && unpack_tag(tape_ptr[line_start - 1]) != STag_Format) line_start--; + U8 col = cursor_idx - line_start; + + U8 next_line_start = cursor_idx; + while (next_line_start < tape_count && unpack_tag(tape_ptr[next_line_start]) != STag_Format) next_line_start++; + if (next_line_start < tape_count) { + next_line_start++; // Skip the newline + U8 next_line_end = next_line_start; + while (next_line_end < tape_count && unpack_tag(tape_ptr[next_line_end]) != STag_Format) next_line_end++; + U8 next_line_len = next_line_end - next_line_start; + cursor_idx = next_line_start + (col < next_line_len ? col : next_line_len); + } + } + + if (wparam == MS_VK_PRIOR) { scroll_y_offset -= 100; if (scroll_y_offset < 0) scroll_y_offset = 0; } + if (wparam == MS_VK_NEXT) { scroll_y_offset += 100; } + if (wparam == MS_VK_F5) { run_full = !run_full; } - if (tag == STag_Data) { - // Hex input - U4 digit = 16; - if (c >= '0' && c <= '9') digit = c - '0'; - if (c >= 'a' && c <= 'f') digit = c - 'a' + 10; - if (c >= 'A' && c <= 'F') digit = c - 'A' + 10; - if (digit < 16) { - val = ((val << 4) | digit) & 0x0FFFFFFF; - tape_ptr[cursor_idx] = PACK_TOKEN(tag, val); - } - } else if (tag != STag_Format) { - U8*r anno_ptr = C_(U8*r, anno_arena.start); - char* anno_str = (char*)&anno_ptr[cursor_idx]; - - int len = 0; - while (len < 8 && anno_str[len] != '\0' && anno_str[len] != ' ') len++; - - if (len < 8) { - anno_str[len] = (char)c; - for (int i = len + 1; i < 8; i++) anno_str[i] = '\0'; - - // Update the 2-char token ID from the first 2 chars - char c1 = anno_str[0] ? anno_str[0] : ' '; - char c2 = anno_str[1] ? anno_str[1] : ' '; - val = ID2(c1, c2); - tape_ptr[cursor_idx] = PACK_TOKEN(tag, val); - } - } - - vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals)); - compile_and_run_tape(); - ms_invalidate_rect(hwnd, NULL, true); - return 0; - } - case MS_WM_KEYDOWN: { - if (wparam == 0x45 && editor_mode == MODE_NAV) { // 'E' - editor_mode = MODE_EDIT; - ms_invalidate_rect(hwnd, NULL, true); - return 0; // Consume the keypress so it doesn't trigger WM_CHAR - } - if (wparam == 0x1B && editor_mode == MODE_EDIT) { // ESC - editor_mode = MODE_NAV; - ms_invalidate_rect(hwnd, NULL, true); - return 0; - } + if (wparam == MS_VK_TAB) { + // Cycle Color Tag + U4 t = tape_ptr[cursor_idx]; + U4 tag = (unpack_tag(t) + 1) % STag_Count; + tape_ptr[cursor_idx] = pack_token(tag, unpack_val(t)); + } + else if (wparam == MS_VK_BACK) + { + // Delete Token + // Shift: delete AT cursor | Regular: delete TO THE LEFT + U8 delete_idx = cursor_idx; + B4 is_shift = (ms_get_async_key_state(MS_VK_SHIFT) & 0x8000) != 0; + if (is_shift == false) { + if (cursor_idx > 0) { + delete_idx = cursor_idx - 1; + cursor_idx--; + } + else return 0; + } - if (editor_mode == MODE_EDIT) { - if (wparam == MS_VK_BACK) { - U4 t = tape_ptr[cursor_idx]; - U4 tag = UNPACK_TAG(t); - U4 val = UNPACK_VAL(t); - if (tag == STag_Data) { - val = val >> 4; - tape_ptr[cursor_idx] = PACK_TOKEN(tag, val); - } else if (tag != STag_Format) { - U8*r anno_ptr = C_(U8*r, anno_arena.start); - char* anno_str = (char*)&anno_ptr[cursor_idx]; - int len = 0; - while(len < 8 && anno_str[len] != '\0' && anno_str[len] != ' ') len++; - if (len > 0) { - anno_str[len-1] = '\0'; - char c1 = anno_str[0] ? anno_str[0] : ' '; - char c2 = anno_str[1] ? anno_str[1] : ' '; - tape_ptr[cursor_idx] = PACK_TOKEN(tag, ID2(c1, c2)); - } - } - vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals)); - compile_and_run_tape(); - ms_invalidate_rect(hwnd, NULL, true); - } - return 0; // Block navigation keys in Edit Mode - } - - if (wparam == MS_VK_RIGHT && cursor_idx < tape_count - 1) cursor_idx++; - if (wparam == MS_VK_LEFT && cursor_idx > 0) cursor_idx--; - - if (wparam == MS_VK_UP) { - U8 line_start = cursor_idx; - while (line_start > 0 && UNPACK_TAG(tape_ptr[line_start - 1]) != STag_Format) line_start--; - if (line_start > 0) { - U8 col = cursor_idx - line_start; - U8 prev_line_start = line_start - 1; - while (prev_line_start > 0 && UNPACK_TAG(tape_ptr[prev_line_start - 1]) != STag_Format) prev_line_start--; - U8 prev_line_len = (line_start - 1) - prev_line_start; - cursor_idx = prev_line_start + (col < prev_line_len ? col : prev_line_len); - } - } - if (wparam == MS_VK_DOWN) { - U8 line_start = cursor_idx; - while (line_start > 0 && UNPACK_TAG(tape_ptr[line_start - 1]) != STag_Format) line_start--; - U8 col = cursor_idx - line_start; - - U8 next_line_start = cursor_idx; - while (next_line_start < tape_count && UNPACK_TAG(tape_ptr[next_line_start]) != STag_Format) next_line_start++; - if (next_line_start < tape_count) { - next_line_start++; // Skip the newline - U8 next_line_end = next_line_start; - while (next_line_end < tape_count && UNPACK_TAG(tape_ptr[next_line_end]) != STag_Format) next_line_end++; - U8 next_line_len = next_line_end - next_line_start; - cursor_idx = next_line_start + (col < next_line_len ? col : next_line_len); - } - } - - if (wparam == MS_VK_PRIOR) { scroll_y_offset -= 100; if (scroll_y_offset < 0) scroll_y_offset = 0; } - if (wparam == MS_VK_NEXT) { scroll_y_offset += 100; } - if (wparam == MS_VK_F5) { run_full = !run_full; } + if (tape_count > 0) { + U8*r anno_ptr = u8_r(anno_arena.start); + for (U8 i = delete_idx; i < tape_count - 1; i ++) { + tape_ptr[i] = tape_ptr[i + 1]; + anno_ptr[i] = anno_ptr[i + 1]; + } + tape_arena.used -= sizeof(U4); + anno_arena.used -= sizeof(U8); + } + } else if (wparam == MS_VK_SPACE || wparam == MS_VK_RETURN) { + // Insert New Token + // Shift: insert AFTER cursor | Regular: insert BEFORE cursor + B4 is_shift = (ms_get_async_key_state(MS_VK_SHIFT) & 0x8000) != 0; + U8 insert_idx = cursor_idx; + if (is_shift) insert_idx ++; - if (wparam == MS_VK_TAB) { - // Cycle Color Tag - U4 t = tape_ptr[cursor_idx]; - U4 tag = (UNPACK_TAG(t) + 1) % STag_Count; - tape_ptr[cursor_idx] = PACK_TOKEN(tag, UNPACK_VAL(t)); - } else if (wparam == MS_VK_BACK) { - // Delete Token - // Shift: delete AT cursor | Regular: delete TO THE LEFT - U8 delete_idx = cursor_idx; - B4 is_shift = (ms_get_async_key_state(MS_VK_SHIFT) & 0x8000) != 0; - - if (!is_shift) { - if (cursor_idx > 0) { - delete_idx = cursor_idx - 1; - cursor_idx--; - } else return 0; - } + if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) { + U8*r anno_ptr = C_(U8*r, anno_arena.start); + for (U8 i = tape_count; i > insert_idx; i--) { + tape_ptr[i] = tape_ptr[i-1]; + anno_ptr[i] = anno_ptr[i-1]; + } + if (wparam == MS_VK_RETURN) { + tape_ptr[insert_idx] = pack_token(STag_Format, 0xA); + anno_ptr[insert_idx] = 0; + } else { + tape_ptr[insert_idx] = pack_token(STag_Comment, id2(' ',' ')); + anno_ptr[insert_idx] = 0; + } + if (is_shift) cursor_idx++; + tape_arena.used += sizeof(U4); + anno_arena.used += sizeof(U8); + } + } + + // Interaction: Reset VM and compile + vm_rax = 0; vm_rdx = 0; + mem_zero(u8_(vm_globals), sizeof(vm_globals)); + + compile_and_run_tape(); + + ms_invalidate_rect(hwnd, nullptr, true); + return 0; + } + case MS_WM_PAINT: { + MS_PAINTSTRUCT ps; + void* hdc = ms_begin_paint(hwnd, &ps); + void* hFont = ms_create_font_a(20, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, "Consolas"); + void* hOldFont = ms_select_object(hdc, hFont); - if (tape_count > 0) { - U8*r anno_ptr = C_(U8*r, anno_arena.start); - for (U8 i = delete_idx; i < tape_count - 1; i++) { - tape_ptr[i] = tape_ptr[i+1]; - anno_ptr[i] = anno_ptr[i+1]; - } - tape_arena.used -= sizeof(U4); - anno_arena.used -= sizeof(U8); - } - } else if (wparam == MS_VK_SPACE || wparam == MS_VK_RETURN) { - // Insert New Token - // Shift: insert AFTER cursor | Regular: insert BEFORE cursor - B4 is_shift = (ms_get_async_key_state(MS_VK_SHIFT) & 0x8000) != 0; - U8 insert_idx = cursor_idx; - if (is_shift) insert_idx++; + ms_set_bk_mode(hdc, 1); // TRANSPARENT text background - if (tape_arena.used + sizeof(U4) <= tape_arena.capacity && anno_arena.used + sizeof(U8) <= anno_arena.capacity) { - U8*r anno_ptr = C_(U8*r, anno_arena.start); - for (U8 i = tape_count; i > insert_idx; i--) { - tape_ptr[i] = tape_ptr[i-1]; - anno_ptr[i] = anno_ptr[i-1]; - } - if (wparam == MS_VK_RETURN) { - tape_ptr[insert_idx] = PACK_TOKEN(STag_Format, 0xA); - anno_ptr[insert_idx] = 0; - } else { - tape_ptr[insert_idx] = PACK_TOKEN(STag_Comment, ID2(' ',' ')); - anno_ptr[insert_idx] = 0; - } - if (is_shift) cursor_idx++; - tape_arena.used += sizeof(U4); - anno_arena.used += sizeof(U8); - } - } - - // Interaction: Reset VM and compile - vm_rax = 0; vm_rdx = 0; - mem_zero(u8_(vm_globals), sizeof(vm_globals)); - - compile_and_run_tape(); - - ms_invalidate_rect(hwnd, NULL, true); - return 0; - } - case MS_WM_PAINT: { - MS_PAINTSTRUCT ps; - void* hdc = ms_begin_paint(hwnd, &ps); - void* hFont = ms_create_font_a(20, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, "Consolas"); - void* hOldFont = ms_select_object(hdc, hFont); + void* hBgBrush = ms_create_solid_brush(0x00222222); + ms_select_object(hdc, hBgBrush); + ms_rectangle(hdc, -1, -1, 3000, 3000); - ms_set_bk_mode(hdc, 1); // TRANSPARENT text background + void* hBrushEdit = ms_create_solid_brush(0x008E563B); + void* hBrushNav = ms_create_solid_brush(0x00262F3B); - void* hBgBrush = ms_create_solid_brush(0x00222222); - ms_select_object(hdc, hBgBrush); - ms_rectangle(hdc, -1, -1, 3000, 3000); + S4 start_x = 40, start_y = 60, spacing_x = 110, spacing_y = 35; + S4 x = start_x, y = start_y; - void* hBrushEdit = ms_create_solid_brush(0x008E563B); - void* hBrushNav = ms_create_solid_brush(0x00262F3B); + U4*r tape_ptr = C_(U4*r, tape_arena.start); + U8*r anno_ptr = C_(U8*r, anno_arena.start); - S4 start_x = 40, start_y = 60, spacing_x = 110, spacing_y = 35; - S4 x = start_x, y = start_y; + // Render Tokens + for (U8 i = 0; i < tape_count; i++) { + if (x >= start_x + (TOKENS_PER_ROW * spacing_x)) { + x = start_x; y += spacing_y; + } - U4*r tape_ptr = C_(U4*r, tape_arena.start); - U8*r anno_ptr = C_(U8*r, anno_arena.start); + S4 render_y = y - scroll_y_offset; - // Render Tokens - for (U8 i = 0; i < tape_count; i++) { - if (x >= start_x + (TOKENS_PER_ROW * spacing_x)) { - x = start_x; y += spacing_y; - } + if (i == cursor_idx && render_y >= 30 && render_y < 500) { + ms_select_object(hdc, editor_mode == MODE_EDIT ? hBrushEdit : hBrushNav); + ms_rectangle(hdc, x - 5, render_y - 2, x + 95, render_y + 22); + } - S4 render_y = y - scroll_y_offset; + if (render_y >= 30 && render_y < 500) { + U4 t = tape_ptr[i]; + U4 tag = unpack_tag(t); + U4 val = unpack_val(t); + U8 anno = anno_ptr[i]; - if (i == cursor_idx && render_y >= 30 && render_y < 500) { - ms_select_object(hdc, editor_mode == MODE_EDIT ? hBrushEdit : hBrushNav); - ms_rectangle(hdc, x - 5, render_y - 2, x + 95, render_y + 22); - } + if (tag == STag_Format && val == 0xA) { + ms_set_text_color(hdc, 0x00444444); + ms_text_out_a(hdc, x, render_y, " \\n ", 6); + x = start_x; + y += spacing_y; + } else { + U4 color = tag_colors[tag]; + const char* prefix = tag_prefixes[tag]; + + ms_set_text_color(hdc, color); + if (editor_mode == MODE_EDIT && i == cursor_idx) { + // Better visibility in Edit Mode: White text on White-ish cursor + ms_set_text_color(hdc, 0x001E1E1E); + } + + char val_str[9]; if (tag == STag_Data) { + u64_to_hex(val, val_str, 6); + val_str[6] = '\0'; + } else { + // Extract annotation string + char* a_str = (char*)&anno; + if (a_str[0] == '\0') { + // Fallback to 2-character ID + val_str[0] = (char)((val >> 8) & 0xFF); + val_str[1] = (char)(val & 0xFF); + val_str[2] = ' '; val_str[3] = ' '; val_str[4] = ' '; val_str[5] = ' '; + val_str[6] = '\0'; + } else { + mem_copy(u8_(val_str), u8_(a_str), 8); + val_str[8] = '\0'; + } + } - if (render_y >= 30 && render_y < 500) { - U4 t = tape_ptr[i]; - U4 tag = UNPACK_TAG(t); - U4 val = UNPACK_VAL(t); - U8 anno = anno_ptr[i]; + char out_buf[12]; + out_buf[0] = prefix[0]; + out_buf[1] = ' '; + mem_copy(u8_(out_buf + 2), u8_(val_str), 8); + out_buf[10] = '\0'; + + ms_text_out_a(hdc, x, render_y, out_buf, 10); + x += spacing_x; + } + } else if (unpack_tag(tape_ptr[i]) == STag_Format && unpack_val(tape_ptr[i]) == 0xA) { + x = start_x; + y += spacing_y; + } else { + x += spacing_x; + } + } - if (tag == STag_Format && val == 0xA) { - ms_set_text_color(hdc, 0x00444444); - ms_text_out_a(hdc, x, render_y, " \\n ", 6); - x = start_x; - y += spacing_y; - } else { - U4 color = tag_colors[tag]; - const char* prefix = tag_prefixes[tag]; - - ms_set_text_color(hdc, color); - if (editor_mode == MODE_EDIT && i == cursor_idx) { - // Better visibility in Edit Mode: White text on White-ish cursor - ms_set_text_color(hdc, 0x001E1E1E); - } - - char val_str[9]; if (tag == STag_Data) { - u64_to_hex(val, val_str, 6); - val_str[6] = '\0'; - } else { - // Extract annotation string - char* a_str = (char*)&anno; - if (a_str[0] == '\0') { - // Fallback to 2-character ID - val_str[0] = (char)((val >> 8) & 0xFF); - val_str[1] = (char)(val & 0xFF); - val_str[2] = ' '; val_str[3] = ' '; val_str[4] = ' '; val_str[5] = ' '; - val_str[6] = '\0'; - } else { - mem_copy(u8_(val_str), u8_(a_str), 8); - val_str[8] = '\0'; - } - } - - char out_buf[12]; - out_buf[0] = prefix[0]; - out_buf[1] = ' '; - mem_copy(u8_(out_buf + 2), u8_(val_str), 8); - out_buf[10] = '\0'; - - ms_text_out_a(hdc, x, render_y, out_buf, 10); - x += spacing_x; - } - } else if (UNPACK_TAG(tape_ptr[i]) == STag_Format && UNPACK_VAL(tape_ptr[i]) == 0xA) { - x = start_x; - y += spacing_y; - } else { - x += spacing_x; - } - } - - // Draw a solid background behind the HUD to cover scrolling text - void* hHudBrush = ms_create_solid_brush(0x00141E23); - ms_select_object(hdc, hHudBrush); - ms_rectangle(hdc, -1, 500, 3000, 3000); - ms_rectangle(hdc, -1, -1, 3000, 40); - - ms_set_text_color(hdc, 0x00AAAAAA); - ms_text_out_a(hdc, 40, 10, "x86-64 Machine Code Emitter | 2-Reg Stack | [F5] Toggle Run Mode | [PgUp/PgDn] Scroll", 85); - - // Render VM State - ms_set_text_color(hdc, 0x00FFFFFF); - char jit_str[64] = "Mode: Incremental | JIT Size: 0x000 bytes"; - if (run_full) mem_copy(u8_(jit_str + 6), u8_("Full "), 11); - u64_to_hex(code_arena.used, jit_str + 32, 3); - ms_text_out_a(hdc, 40, 520, jit_str, 41); - - char state_str[64] = "RAX: 00000000 | RDX: 00000000"; - u64_to_hex(vm_rax, state_str + 5, 8); - u64_to_hex(vm_rdx, state_str + 21, 8); - ms_set_text_color(hdc, 0x0094BAA1); // Number green - ms_text_out_a(hdc, 40, 550, state_str, 29); + // Draw a solid background behind the HUD to cover scrolling text + void* hHudBrush = ms_create_solid_brush(0x00141E23); + ms_select_object(hdc, hHudBrush); + ms_rectangle(hdc, -1, 500, 3000, 3000); + ms_rectangle(hdc, -1, -1, 3000, 40); - // HUD: Display Current Token Meaning - if (tape_count > 0 && cursor_idx < tape_count) { - U4 cur_tag = UNPACK_TAG(tape_ptr[cursor_idx]); - const char* tag_name = tag_names[cur_tag]; - U4 cur_color = tag_colors[cur_tag]; - - char semantics_str[64] = "Current Tag: "; - U4 name_len = 0; - while (tag_name[name_len]) { - semantics_str[13 + name_len] = tag_name[name_len]; - name_len++; - } - semantics_str[13 + name_len] = '\0'; - - ms_set_text_color(hdc, cur_color); - ms_text_out_a(hdc, 40, 580, semantics_str, 13 + name_len); - } + ms_set_text_color(hdc, 0x00AAAAAA); + ms_text_out_a(hdc, 40, 10, "x86-64 Machine Code Emitter | 2-Reg Stack | [F5] Toggle Run Mode | [PgUp/PgDn] Scroll", 85); + + // Render VM State + ms_set_text_color(hdc, 0x00FFFFFF); + char jit_str[64] = "Mode: Incremental | JIT Size: 0x000 bytes"; + if (run_full) mem_copy(u8_(jit_str + 6), u8_("Full "), 11); + u64_to_hex(code_arena.used, jit_str + 32, 3); + ms_text_out_a(hdc, 40, 520, jit_str, 41); + + char state_str[64] = "RAX: 00000000 | RDX: 00000000"; + u64_to_hex(vm_rax, state_str + 5, 8); + u64_to_hex(vm_rdx, state_str + 21, 8); + ms_set_text_color(hdc, 0x0094BAA1); // Number green + ms_text_out_a(hdc, 40, 550, state_str, 29); - ms_set_text_color(hdc, 0x00C8C8C8); - ms_text_out_a(hdc, 400, 520, "Global Memory (Contiguous Array):", 33); - for (int i=0; i<4; i++) { - char glob_str[32] = "[0]: 00000000"; - glob_str[1] = '0' + i; - u64_to_hex(vm_globals[i], glob_str + 5, 8); - ms_set_text_color(hdc, 0x00D6A454); // Soft blue - ms_text_out_a(hdc, 400, 550 + (i * 25), glob_str, 13); - } + // HUD: Display Current Token Meaning + if (tape_count > 0 && cursor_idx < tape_count) { + U4 cur_tag = unpack_tag(tape_ptr[cursor_idx]); + const char* tag_name = tag_names[cur_tag]; + U4 cur_color = tag_colors[cur_tag]; + + char semantics_str[64] = "Current Tag: "; + U4 name_len = 0; + while (tag_name[name_len]) { + semantics_str[13 + name_len] = tag_name[name_len]; + name_len++; + } + semantics_str[13 + name_len] = '\0'; + + ms_set_text_color(hdc, cur_color); + ms_text_out_a(hdc, 40, 580, semantics_str, 13 + name_len); + } - // Print Log - ms_set_text_color(hdc, 0x00C8C8C8); - ms_text_out_a(hdc, 750, 520, "Print Log:", 10); - for (int i=0; i