adjustments

This commit is contained in:
2026-02-20 20:33:39 -05:00
parent bc30206e65
commit 9db1748249
6 changed files with 734 additions and 641 deletions

50
.editorconfig Normal file
View File

@@ -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

View File

@@ -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. * **Case:** Strictly use `lower_snake_case` for all functions and variables.
* **Types:** Use `PascalCase` for type names (`FArena`, `SWord_Tag`). * **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. * **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(...);` * *Incorrect:* `WinAPI U2 RegisterClassA(...);`
## 4. Formatting & Layout ## 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. * **Conditionals:** Always place `else if` and `else` statements on a new line, un-nested from the previous closing brace.
## 5. Memory Management ## 5. Memory Management
* **No Standard Library:** The environment is built with `-nostdlib` and `-ffreestanding`. Never include `<stdlib.h>`, `<string.h>`, etc. * **Standard Library:** The C standard library is linked, but headers like `<stdlib.h>` or `<string.h>` 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. * **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. * **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;`

View File

@@ -1,7 +1,7 @@
# Technical Outline: Attempt 1 # Technical Outline: Attempt 1
## Overview ## 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. 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.

View File

@@ -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 endregion Thread Coherence
#pragma region Debug #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() #define debug_trap() __builtin_debugtrap()
#if BUILD_DEBUG #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 #else
#define assert(cond) #define assert(cond)
#endif #endif
@@ -242,6 +243,13 @@ IA_ Slice mem_bump(U8 start, U8 cap, U8*r used, U8 amount) {
} }
#pragma endregion Memory #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 #pragma region Math
#define u8_max 0xffffffffffffffffull #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_INPUT u4_(-10)
#define MS_STD_OUTPUT u4_(-11) #define MS_STD_OUTPUT u4_(-11)
typedef Struct_(MS_Handle){U8 id;}; 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 endregion IO
#pragma region Key Table Linear (KTL) #pragma region Key Table Linear (KTL)
@@ -599,37 +604,83 @@ typedef struct MS_WNDCLASSA {
char const* lpszMenuName; char const* lpszMenuName;
char const* lpszClassName; char const* lpszClassName;
} MS_WNDCLASSA; } MS_WNDCLASSA;
typedef struct MS_POINT { S4 x, y; } MS_POINT; 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_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_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; 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_virtual_alloc(void* lpAddress, U8 dwSize, U4 flAllocationType, U4 flProtect) asm("VirtualAlloc");
WinAPI void ms_exit_process(U4 uExitCode) asm("ExitProcess"); WinAPI void ms_exit_process(U4 uExitCode) asm("ExitProcess");
WinAPI U2 ms_register_class_a(const MS_WNDCLASSA* lpWndClass) asm("RegisterClassA"); WinAPI MS_Handle ms_get_std_handle(U4 handle_type) asm("GetStdHandle");
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 void* ms_virtual_alloc(void* lpAddress, U8 dwSize, U4 flAllocationType, U4 flProtect) asm("VirtualAlloc");
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");
// --- 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_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_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 S4 ms_translate_message(MS_MSG const* lpMsg) asm("TranslateMessage");
WinAPI S8 ms_dispatch_message_a(const MS_MSG* lpMsg) asm("DispatchMessageA"); 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 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 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 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 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 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_text_color(void* hdc, U4 color) asm("SetTextColor");
WinAPI U4 ms_set_bk_color(void* hdc, U4 color) asm("SetBkColor"); 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 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_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_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 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_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 S4 ms_set_bk_mode(void* hdc, S4 mode) asm("SetBkMode");
WinAPI void* ms_create_solid_brush(U4 color) asm("CreateSolidBrush"); WinAPI void* ms_create_solid_brush(U4 color) asm("CreateSolidBrush");
WinAPI S4 ms_delete_object(void* ho) asm("DeleteObject"); WinAPI S4 ms_delete_object(void* ho) asm("DeleteObject");
WinAPI S2 ms_get_async_key_state(S4 vKey) asm("GetAsyncKeyState");
#define MS_MEM_COMMIT 0x00001000 #define MS_MEM_COMMIT 0x00001000
#define MS_MEM_RESERVE 0x00002000 #define MS_MEM_RESERVE 0x00002000

View File

@@ -1,14 +1,9 @@
// Fundamental Boolean and Null types for no-std environment
#define true 1
#define false 0
#define NULL ((void*)0)
#include "duffle.amd64.win32.h" #include "duffle.amd64.win32.h"
// --- Semantic Tags (Using X-Macros & Enum_) --- // --- Semantic Tags (Using X-Macros & Enum_) ---
// Colors translated from Cozy-and-WIndy: // Colors translated from Cozy-and-WIndy:
// 0x00bbggrr Win32 format // 0x00bbggrr Win32 format
typedef Enum_(U4, STag) {
#define Tag_Entries() \ #define Tag_Entries() \
X(Define, "Define", 0x0018AEFF, ":") /* Orange-ish (Language.Type) */ \ X(Define, "Define", 0x0018AEFF, ":") /* Orange-ish (Language.Type) */ \
X(Call, "Call", 0x00D6A454, "~") /* Soft Blue (Language.Class) */ \ X(Call, "Call", 0x00D6A454, "~") /* Soft Blue (Language.Class) */ \
@@ -17,27 +12,22 @@ typedef Enum_(U4, STag) {
X(Comment, "Comment", 0x00AAAAAA, ".") /* Grey (Language.Comment) */ \ X(Comment, "Comment", 0x00AAAAAA, ".") /* Grey (Language.Comment) */ \
X(Format, "Format", 0x003A2F3B, " ") /* Current Line BG for invisibles */ X(Format, "Format", 0x003A2F3B, " ") /* Current Line BG for invisibles */
typedef Enum_(U4, STag) {
#define X(n, s, c, p) tmpl(STag, n), #define X(n, s, c, p) tmpl(STag, n),
Tag_Entries() Tag_Entries()
#undef X #undef X
STag_Count, STag_Count,
}; };
// Helper array to fetch Hex colors for UI rendering based on STag
global U4 tag_colors[] = { global U4 tag_colors[] = {
#define X(n, s, c, p) c, #define X(n, s, c, p) c,
Tag_Entries() Tag_Entries()
#undef X #undef X
}; };
// Helper array to fetch the text prefix based on STag
global const char* tag_prefixes[] = { global const char* tag_prefixes[] = {
#define X(n, s, c, p) p, #define X(n, s, c, p) p,
Tag_Entries() Tag_Entries()
#undef X #undef X
}; };
// Helper array to fetch the full name of the STag
global const char* tag_names[] = { global const char* tag_names[] = {
#define X(n, s, c, p) s, #define X(n, s, c, p) s,
Tag_Entries() Tag_Entries()
@@ -45,12 +35,12 @@ global const char* tag_names[] = {
}; };
// Token Packing: 28 bits payload | 4 bits tag // Token Packing: 28 bits payload | 4 bits tag
#define PACK_TOKEN(tag, val) (((U4)(tag) << 28) | ((U4)(val) & 0x0FFFFFFF)) #define pack_token(tag, val) ((u4_(tag) << 28) | (u4_(val) & 0x0FFFFFFF))
#define UNPACK_TAG(token) (((token) >> 28) & 0x0F) #define unpack_tag(token) ( ((token) >> 28) & 0x0F)
#define UNPACK_VAL(token) ((token) & 0x0FFFFFFF) #define unpack_val(token) ( (token) & 0x0FFFFFFF)
// 2-Character Mapped Dictionary Helper // 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 #define TOKENS_PER_ROW 8
@@ -95,11 +85,10 @@ global U8 dict_count = 0;
IA_ void scatter(U4 token, const char* anno_str) { 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) { 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); U4*r ptr = u4_r(tape_arena.start + tape_arena.used);
ptr[0] = token; ptr[0] = token;
tape_arena.used += sizeof(U4); tape_arena.used += sizeof(U4);
U8*r aptr = u8_r(anno_arena.start + anno_arena.used);
U8*r aptr = C_(U8*r, anno_arena.start + anno_arena.used);
aptr[0] = 0; aptr[0] = 0;
if (anno_str) { if (anno_str) {
char* dest = (char*)aptr; char* dest = (char*)aptr;
@@ -113,85 +102,80 @@ IA_ void scatter(U4 token, const char* anno_str) {
} }
} }
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; }
}
// --- Minimal x86-64 Emitter --- // --- Minimal x86-64 Emitter ---
internal void emit8(U1 b) { internal void emit8(U1 b) {
if (code_arena.used + 1 <= code_arena.capacity) { if (code_arena.used + 1 <= code_arena.capacity) {
U1* ptr = (U1*)(code_arena.start + code_arena.used); U1*r ptr = u1_r(code_arena.start + code_arena.used);
*ptr = b; ptr[0] = b;
code_arena.used += 1; code_arena.used += 1;
} }
} }
internal void emit32(U4 val) { internal void emit32(U4 val) {
if (code_arena.used + 4 <= code_arena.capacity) { if (code_arena.used + 4 <= code_arena.capacity) {
U4* ptr = (U4*)(code_arena.start + code_arena.used); U4*r ptr = u4_r(code_arena.start + code_arena.used);
*ptr = val; ptr[0] = val;
code_arena.used += 4; code_arena.used += 4;
} }
} }
internal void compile_action(U4 val) { internal void compile_action(U4 val)
if (val == ID2('S','W')) { // SWAP: xchg rax, rdx {
if (val == id2('S','W')) { // SWAP: xchg rax, rdx
emit8(0x48); emit8(0x87); emit8(0xC2); emit8(0x48); emit8(0x87); emit8(0xC2);
return; return;
} else if (val == ID2('M','*')) { // MULT: imul rax, rdx } else if (val == id2('M','*')) { // MULT: imul rax, rdx
emit8(0x48); emit8(0x0F); emit8(0xAF); emit8(0xC2); emit8(0x48); emit8(0x0F); emit8(0xAF); emit8(0xC2);
return; return;
} else if (val == ID2('+',' ')) { // ADD: add rax, rdx } else if (val == id2('+',' ')) { // ADD: add rax, rdx
emit8(0x48); emit8(0x01); emit8(0xD0); emit8(0x48); emit8(0x01); emit8(0xD0);
return; return;
} else if (val == ID2('@',' ')) { // FETCH: mov rax, QWORD PTR [rcx + rax*8] } else if (val == id2('@',' ')) { // FETCH: mov rax, QWORD PTR [rcx + rax*8]
emit8(0x48); emit8(0x8B); emit8(0x04); emit8(0xC1); emit8(0x48); emit8(0x8B); emit8(0x04); emit8(0xC1);
return; return;
} else if (val == ID2('-','1')) { // DEC: dec rax } else if (val == id2('-','1')) { // DEC: dec rax
emit8(0x48); emit8(0xFF); emit8(0xC8); emit8(0x48); emit8(0xFF); emit8(0xC8);
return; return;
} else if (val == ID2('!',' ')) { // STORE: mov QWORD PTR [rcx + rax*8], rdx } else if (val == id2('!',' ')) { // STORE: mov QWORD PTR [rcx + rax*8], rdx
emit8(0x48); emit8(0x89); emit8(0x14); emit8(0xC1); emit8(0x48); emit8(0x89); emit8(0x14); emit8(0xC1);
return; return;
} else if (val == ID2('R','0')) { // RET_IF_ZERO: test rax, rax; jnz +1; ret } 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(0x48); emit8(0x85); emit8(0xC0); // test rax, rax
emit8(0x75); emit8(0x01); // jnz skip_ret (+1 byte) emit8(0x75); emit8(0x01); // jnz skip_ret (+1 byte)
emit8(0xC3); // ret emit8(0xC3); // ret
return; return;
} else if (val == ID2('R','E')) { // RET } else if (val == id2('R','E')) { // RET
emit8(0xC3); emit8(0xC3);
return; return;
} else if (val == ID2('P','R')) { // PRINT: call ms_builtin_print } else if (val == id2('P','R')) { // PRINT: call ms_builtin_print
emit8(0x51); // push rcx emit8(0x51); // push rcx
emit8(0x52); // push rdx emit8(0x52); // push rdx
emit8(0x48); emit8(0x83); emit8(0xEC); emit8(0x20); // sub rsp, 32 emit8(0x48); emit8(0x83); emit8(0xEC); emit8(0x20); // sub rsp, 32
emit8(0x48); emit8(0x89); emit8(0xC1); // mov rcx, rax emit8(0x48); emit8(0x89); emit8(0xC1); // mov rcx, rax
emit8(0x49); emit8(0xB8); // mov r8, imm64 emit8(0x49); emit8(0xB8); // mov r8, imm64
U8 addr = (U8)&ms_builtin_print; U8 addr = u8_(& ms_builtin_print);
emit32((U4)(addr & 0xFFFFFFFF)); emit32(u4_(addr & 0xFFFFFFFF));
emit32((U4)(addr >> 32)); emit32(u4_(addr >> 32));
emit8(0x41); emit8(0xFF); emit8(0xD0); // call r8 emit8(0x41); emit8(0xFF); emit8(0xD0); // call r8
emit8(0x48); emit8(0x83); emit8(0xC4); emit8(0x20); // add rsp, 32 emit8(0x48); emit8(0x83); emit8(0xC4); emit8(0x20); // add rsp, 32
emit8(0x5A); // pop rdx emit8(0x5A); // pop rdx
emit8(0x59); // pop rcx emit8(0x59); // pop rcx
return; return;
} }
// Dictionary Resolver (Call User Word) // Dictionary Resolver (Call User Word)
for (U8 i = 0; i < dict_count; i++) { for (U8 entry = 0; entry < dict_count; entry++) {
if (dict[i].val == val) { if (dict[entry].val == val) {
U4 target = dict[i].offset; U4 target = dict[entry].offset;
U4 current = code_arena.used; U4 current = code_arena.used;
S4 rel32 = (S4)target - (S4)(current + 5); S4 rel32 = s4_(target) - s4_(current + 5);
emit8(0xE8); // CALL rel32 emit8(0xE8); // CALL rel32
emit32((U4)rel32); emit32(u4_(rel32));
return; return;
} }
} }
} }
IA_ void compile_and_run_tape(void) { IA_ void compile_and_run_tape(void)
{
farena_reset(& code_arena); farena_reset(& code_arena);
dict_count = 0; dict_count = 0;
log_count = 0; log_count = 0;
@@ -200,18 +184,17 @@ IA_ void compile_and_run_tape(void) {
emit8(0x48); emit8(0x8B); emit8(0x41); emit8(0x70); // mov rax, [rcx+112] emit8(0x48); emit8(0x8B); emit8(0x41); emit8(0x70); // mov rax, [rcx+112]
emit8(0x48); emit8(0x8B); emit8(0x51); emit8(0x78); // mov rdx, [rcx+120] emit8(0x48); emit8(0x8B); emit8(0x51); emit8(0x78); // mov rdx, [rcx+120]
U4*r tape_ptr = C_(U4*r, tape_arena.start); U4*r tape_ptr = u4_r(tape_arena.start);
B4 in_def = false; B4 in_def = false;
U4 def_jmp_offset = 0; U4 def_jmp_offset = 0;
U8 end_idx = run_full ? (tape_arena.used / sizeof(U4)) : (cursor_idx + 1); U8 end_idx = run_full ? (tape_arena.used / sizeof(U4)) : (cursor_idx + 1);
for (U8 i = 0; i < end_idx; i++)
for (U8 i = 0; i < end_idx; i++) { {
U4 tag = UNPACK_TAG(tape_ptr[i]); U4 tag = unpack_tag(tape_ptr[i]);
U4 val = UNPACK_VAL(tape_ptr[i]); U4 val = unpack_val(tape_ptr[i]);
if (tag == STag_Define)
if (tag == tmpl(STag, Define)) { {
if (!in_def) { if (in_def == false) {
emit8(0xE9); // JMP rel32 (Skip over definition body) emit8(0xE9); // JMP rel32 (Skip over definition body)
def_jmp_offset = code_arena.used; def_jmp_offset = code_arena.used;
emit32(0); emit32(0);
@@ -222,22 +205,27 @@ IA_ void compile_and_run_tape(void) {
dict[dict_count].offset = code_arena.used; dict[dict_count].offset = code_arena.used;
dict_count++; dict_count++;
} }
} else if (tag == tmpl(STag, Call)) { }
else if (tag == STag_Call)
{
compile_action(val); compile_action(val);
if (val == ID2('R','E') && in_def) { if (val == id2('R','E') && in_def) {
// End of definition block, patch the jump // End of definition block, patch the jump
U4 current = code_arena.used; U4 current = code_arena.used;
*(U4*)(code_arena.start + def_jmp_offset) = current - (def_jmp_offset + 4); u4_r(code_arena.start + def_jmp_offset)[0] = current - (def_jmp_offset + 4);
in_def = false; in_def = false;
} }
} else if (tag == tmpl(STag, Data)) { }
else if (tag == tmpl(STag, Data)) {
emit8(0x48); emit8(0x89); emit8(0xC2); // mov rdx, rax emit8(0x48); emit8(0x89); emit8(0xC2); // mov rdx, rax
emit8(0x48); emit8(0xC7); emit8(0xC0); emit32(val); // mov rax, imm32 emit8(0x48); emit8(0xC7); emit8(0xC0); emit32(val); // mov rax, imm32
} else if (tag == tmpl(STag, Imm)) { }
else if (tag == tmpl(STag, Imm))
{
if (in_def) { if (in_def) {
// If we execute something, we jump out of def block first // If we execute something, we jump out of def block first
U4 current = code_arena.used; U4 current = code_arena.used;
*(U4*)(code_arena.start + def_jmp_offset) = current - (def_jmp_offset + 4); u4_r(code_arena.start + def_jmp_offset)[0] = current - (def_jmp_offset + 4);
in_def = false; in_def = false;
} }
compile_action(val); compile_action(val);
@@ -247,7 +235,7 @@ IA_ void compile_and_run_tape(void) {
if (in_def) { if (in_def) {
// If we hit cursor inside a definition, patch jump so it doesn't crash on execution // If we hit cursor inside a definition, patch jump so it doesn't crash on execution
U4 current = code_arena.used; U4 current = code_arena.used;
*(U4*)(code_arena.start + def_jmp_offset) = current - (def_jmp_offset + 4); u4_r(code_arena.start + def_jmp_offset)[0] = current - (def_jmp_offset + 4);
} }
// Epilogue: Save VM state back to globals // Epilogue: Save VM state back to globals
@@ -256,8 +244,8 @@ IA_ void compile_and_run_tape(void) {
emit8(0xC3); // ret emit8(0xC3); // ret
// Cast code arena to function pointer and CALL it! // Cast code arena to function pointer and CALL it!
typedef void (*JIT_Func)(U8* globals_ptr); typedef void JIT_Func(U8* globals_ptr);
JIT_Func func = (JIT_Func)code_arena.start; JIT_Func* func = (JIT_Func*)code_arena.start;
func(vm_globals); func(vm_globals);
// Read state for UI // Read state for UI
@@ -277,18 +265,18 @@ IA_ void compile_and_run_tape(void) {
#define MS_VK_SHIFT 0x10 #define MS_VK_SHIFT 0x10
// --- Window Procedure --- // --- Window Procedure ---
S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) { S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
{
U8 tape_count = tape_arena.used / sizeof(U4); U8 tape_count = tape_arena.used / sizeof(U4);
U4*r tape_ptr = C_(U4*r, tape_arena.start); U4*r tape_ptr = C_(U4*r, tape_arena.start);
switch (msg) { switch (msg) {
case MS_WM_CHAR: { case MS_WM_CHAR: {
if (editor_mode != MODE_EDIT) return 0; if (editor_mode != MODE_EDIT) return 0;
U4 t = tape_ptr[cursor_idx]; U4 t = tape_ptr[cursor_idx];
U4 tag = UNPACK_TAG(t); U4 tag = unpack_tag(t);
U4 val = UNPACK_VAL(t); U4 val = unpack_val(t);
U1 c = (U1)wparam; U1 c = u1_(wparam);
// Skip control characters and the 'E' that triggered the mode // Skip control characters and the 'E' that triggered the mode
if (c < 32) break; if (c < 32) break;
@@ -301,53 +289,50 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
if (c >= 'A' && c <= 'F') digit = c - 'A' + 10; if (c >= 'A' && c <= 'F') digit = c - 'A' + 10;
if (digit < 16) { if (digit < 16) {
val = ((val << 4) | digit) & 0x0FFFFFFF; val = ((val << 4) | digit) & 0x0FFFFFFF;
tape_ptr[cursor_idx] = PACK_TOKEN(tag, val); tape_ptr[cursor_idx] = pack_token(tag, val);
} }
} else if (tag != STag_Format) { }
U8*r anno_ptr = C_(U8*r, anno_arena.start); else if (tag != STag_Format) {
U8*r anno_ptr = u8_r(anno_arena.start);
char* anno_str = (char*) & anno_ptr[cursor_idx]; char* anno_str = (char*) & anno_ptr[cursor_idx];
int len = 0; int len = 0;
while (len < 8 && anno_str[len] != '\0' && anno_str[len] != ' ') len ++; while (len < 8 && anno_str[len] != '\0' && anno_str[len] != ' ') len ++;
if (len < 8) { if (len < 8) {
anno_str[len] = (char)c; anno_str[len] = (char)c;
for (int i = len + 1; i < 8; i++) anno_str[i] = '\0'; for (int i = len + 1; i < 8; i++) anno_str[i] = '\0';
// Update the 2-char token ID from the first 2 chars // Update the 2-char token ID from the first 2 chars
char c1 = anno_str[0] ? anno_str[0] : ' '; char c1 = anno_str[0] ? anno_str[0] : ' ';
char c2 = anno_str[1] ? anno_str[1] : ' '; char c2 = anno_str[1] ? anno_str[1] : ' ';
val = ID2(c1, c2); val = id2(c1, c2);
tape_ptr[cursor_idx] = PACK_TOKEN(tag, val); tape_ptr[cursor_idx] = pack_token(tag, val);
} }
} }
vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals)); vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals));
compile_and_run_tape(); compile_and_run_tape();
ms_invalidate_rect(hwnd, NULL, true); ms_invalidate_rect(hwnd, nullptr, true);
return 0; return 0;
} }
case MS_WM_KEYDOWN: { case MS_WM_KEYDOWN: {
if (wparam == 0x45 && editor_mode == MODE_NAV) { // 'E' if (wparam == 0x45 && editor_mode == MODE_NAV) { // 'E'
editor_mode = MODE_EDIT; editor_mode = MODE_EDIT;
ms_invalidate_rect(hwnd, NULL, true); ms_invalidate_rect(hwnd, nullptr, true);
return 0; // Consume the keypress so it doesn't trigger WM_CHAR return 0; // Consume the keypress so it doesn't trigger WM_CHAR
} }
if (wparam == 0x1B && editor_mode == MODE_EDIT) { // ESC if (wparam == 0x1B && editor_mode == MODE_EDIT) { // ESC
editor_mode = MODE_NAV; editor_mode = MODE_NAV;
ms_invalidate_rect(hwnd, NULL, true); ms_invalidate_rect(hwnd, nullptr, true);
return 0; return 0;
} }
if (editor_mode == MODE_EDIT) { if (editor_mode == MODE_EDIT) {
if (wparam == MS_VK_BACK) { if (wparam == MS_VK_BACK) {
U4 t = tape_ptr[cursor_idx]; U4 t = tape_ptr[cursor_idx];
U4 tag = UNPACK_TAG(t); U4 tag = unpack_tag(t);
U4 val = UNPACK_VAL(t); U4 val = unpack_val(t);
if (tag == STag_Data) { if (tag == STag_Data) {
val = val >> 4; val = val >> 4;
tape_ptr[cursor_idx] = PACK_TOKEN(tag, val); tape_ptr[cursor_idx] = pack_token(tag, val);
} else if (tag != STag_Format) { }
else if (tag != STag_Format) {
U8*r anno_ptr = C_(U8*r, anno_arena.start); U8*r anno_ptr = C_(U8*r, anno_arena.start);
char* anno_str = (char*)&anno_ptr[cursor_idx]; char* anno_str = (char*)&anno_ptr[cursor_idx];
int len = 0; int len = 0;
@@ -356,12 +341,12 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
anno_str[len - 1] = '\0'; anno_str[len - 1] = '\0';
char c1 = anno_str[0] ? anno_str[0] : ' '; char c1 = anno_str[0] ? anno_str[0] : ' ';
char c2 = anno_str[1] ? anno_str[1] : ' '; char c2 = anno_str[1] ? anno_str[1] : ' ';
tape_ptr[cursor_idx] = PACK_TOKEN(tag, ID2(c1, c2)); tape_ptr[cursor_idx] = pack_token(tag, id2(c1, c2));
} }
} }
vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals)); vm_rax = 0; vm_rdx = 0; mem_zero(u8_(vm_globals), sizeof(vm_globals));
compile_and_run_tape(); compile_and_run_tape();
ms_invalidate_rect(hwnd, NULL, true); ms_invalidate_rect(hwnd, nullptr, true);
} }
return 0; // Block navigation keys in Edit Mode return 0; // Block navigation keys in Edit Mode
} }
@@ -371,26 +356,26 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
if (wparam == MS_VK_UP) { if (wparam == MS_VK_UP) {
U8 line_start = cursor_idx; U8 line_start = cursor_idx;
while (line_start > 0 && UNPACK_TAG(tape_ptr[line_start - 1]) != STag_Format) line_start--; while (line_start > 0 && unpack_tag(tape_ptr[line_start - 1]) != STag_Format) line_start--;
if (line_start > 0) { if (line_start > 0) {
U8 col = cursor_idx - line_start; U8 col = cursor_idx - line_start;
U8 prev_line_start = line_start - 1; 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--; 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; U8 prev_line_len = (line_start - 1) - prev_line_start;
cursor_idx = prev_line_start + (col < prev_line_len ? col : prev_line_len); cursor_idx = prev_line_start + (col < prev_line_len ? col : prev_line_len);
} }
} }
if (wparam == MS_VK_DOWN) { if (wparam == MS_VK_DOWN) {
U8 line_start = cursor_idx; U8 line_start = cursor_idx;
while (line_start > 0 && UNPACK_TAG(tape_ptr[line_start - 1]) != STag_Format) line_start--; while (line_start > 0 && unpack_tag(tape_ptr[line_start - 1]) != STag_Format) line_start--;
U8 col = cursor_idx - line_start; U8 col = cursor_idx - line_start;
U8 next_line_start = cursor_idx; U8 next_line_start = cursor_idx;
while (next_line_start < tape_count && UNPACK_TAG(tape_ptr[next_line_start]) != STag_Format) next_line_start++; while (next_line_start < tape_count && unpack_tag(tape_ptr[next_line_start]) != STag_Format) next_line_start++;
if (next_line_start < tape_count) { if (next_line_start < tape_count) {
next_line_start++; // Skip the newline next_line_start++; // Skip the newline
U8 next_line_end = next_line_start; 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++; 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; U8 next_line_len = next_line_end - next_line_start;
cursor_idx = next_line_start + (col < next_line_len ? col : next_line_len); cursor_idx = next_line_start + (col < next_line_len ? col : next_line_len);
} }
@@ -403,23 +388,25 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
if (wparam == MS_VK_TAB) { if (wparam == MS_VK_TAB) {
// Cycle Color Tag // Cycle Color Tag
U4 t = tape_ptr[cursor_idx]; U4 t = tape_ptr[cursor_idx];
U4 tag = (UNPACK_TAG(t) + 1) % STag_Count; U4 tag = (unpack_tag(t) + 1) % STag_Count;
tape_ptr[cursor_idx] = PACK_TOKEN(tag, UNPACK_VAL(t)); tape_ptr[cursor_idx] = pack_token(tag, unpack_val(t));
} else if (wparam == MS_VK_BACK) { }
else if (wparam == MS_VK_BACK)
{
// Delete Token // Delete Token
// Shift: delete AT cursor | Regular: delete TO THE LEFT // Shift: delete AT cursor | Regular: delete TO THE LEFT
U8 delete_idx = cursor_idx; U8 delete_idx = cursor_idx;
B4 is_shift = (ms_get_async_key_state(MS_VK_SHIFT) & 0x8000) != 0; B4 is_shift = (ms_get_async_key_state(MS_VK_SHIFT) & 0x8000) != 0;
if (is_shift == false) {
if (!is_shift) {
if (cursor_idx > 0) { if (cursor_idx > 0) {
delete_idx = cursor_idx - 1; delete_idx = cursor_idx - 1;
cursor_idx--; cursor_idx--;
} else return 0; }
else return 0;
} }
if (tape_count > 0) { if (tape_count > 0) {
U8*r anno_ptr = C_(U8*r, anno_arena.start); U8*r anno_ptr = u8_r(anno_arena.start);
for (U8 i = delete_idx; i < tape_count - 1; i ++) { for (U8 i = delete_idx; i < tape_count - 1; i ++) {
tape_ptr[i] = tape_ptr[i + 1]; tape_ptr[i] = tape_ptr[i + 1];
anno_ptr[i] = anno_ptr[i + 1]; anno_ptr[i] = anno_ptr[i + 1];
@@ -441,10 +428,10 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
anno_ptr[i] = anno_ptr[i-1]; anno_ptr[i] = anno_ptr[i-1];
} }
if (wparam == MS_VK_RETURN) { if (wparam == MS_VK_RETURN) {
tape_ptr[insert_idx] = PACK_TOKEN(STag_Format, 0xA); tape_ptr[insert_idx] = pack_token(STag_Format, 0xA);
anno_ptr[insert_idx] = 0; anno_ptr[insert_idx] = 0;
} else { } else {
tape_ptr[insert_idx] = PACK_TOKEN(STag_Comment, ID2(' ',' ')); tape_ptr[insert_idx] = pack_token(STag_Comment, id2(' ',' '));
anno_ptr[insert_idx] = 0; anno_ptr[insert_idx] = 0;
} }
if (is_shift) cursor_idx++; if (is_shift) cursor_idx++;
@@ -459,7 +446,7 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
compile_and_run_tape(); compile_and_run_tape();
ms_invalidate_rect(hwnd, NULL, true); ms_invalidate_rect(hwnd, nullptr, true);
return 0; return 0;
} }
case MS_WM_PAINT: { case MS_WM_PAINT: {
@@ -498,8 +485,8 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
if (render_y >= 30 && render_y < 500) { if (render_y >= 30 && render_y < 500) {
U4 t = tape_ptr[i]; U4 t = tape_ptr[i];
U4 tag = UNPACK_TAG(t); U4 tag = unpack_tag(t);
U4 val = UNPACK_VAL(t); U4 val = unpack_val(t);
U8 anno = anno_ptr[i]; U8 anno = anno_ptr[i];
if (tag == STag_Format && val == 0xA) { if (tag == STag_Format && val == 0xA) {
@@ -544,7 +531,7 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
ms_text_out_a(hdc, x, render_y, out_buf, 10); ms_text_out_a(hdc, x, render_y, out_buf, 10);
x += spacing_x; x += spacing_x;
} }
} else if (UNPACK_TAG(tape_ptr[i]) == STag_Format && UNPACK_VAL(tape_ptr[i]) == 0xA) { } else if (unpack_tag(tape_ptr[i]) == STag_Format && unpack_val(tape_ptr[i]) == 0xA) {
x = start_x; x = start_x;
y += spacing_y; y += spacing_y;
} else { } else {
@@ -576,7 +563,7 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
// HUD: Display Current Token Meaning // HUD: Display Current Token Meaning
if (tape_count > 0 && cursor_idx < tape_count) { if (tape_count > 0 && cursor_idx < tape_count) {
U4 cur_tag = UNPACK_TAG(tape_ptr[cursor_idx]); U4 cur_tag = unpack_tag(tape_ptr[cursor_idx]);
const char* tag_name = tag_names[cur_tag]; const char* tag_name = tag_names[cur_tag];
U4 cur_color = tag_colors[cur_tag]; U4 cur_color = tag_colors[cur_tag];
@@ -626,9 +613,9 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam) {
int main(void) { int main(void) {
// 1. Initialize Memory Arenas using WinAPI + FArena // 1. Initialize Memory Arenas using WinAPI + FArena
Slice tape_mem = slice_ut_(u8_(ms_virtual_alloc(NULL, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE)), 64 * 1024); Slice tape_mem = slice_ut_(u8_(ms_virtual_alloc(nullptr, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE)), 64 * 1024);
Slice anno_mem = slice_ut_(u8_(ms_virtual_alloc(NULL, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE)), 64 * 1024); Slice anno_mem = slice_ut_(u8_(ms_virtual_alloc(nullptr, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE)), 64 * 1024);
Slice code_mem = slice_ut_(u8_(ms_virtual_alloc(NULL, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_EXECUTE_READWRITE)), 64 * 1024); Slice code_mem = slice_ut_(u8_(ms_virtual_alloc(nullptr, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_EXECUTE_READWRITE)), 64 * 1024);
if (!tape_mem.ptr || !anno_mem.ptr || !code_mem.ptr) ms_exit_process(1); if (!tape_mem.ptr || !anno_mem.ptr || !code_mem.ptr) ms_exit_process(1);
farena_init(&tape_arena, tape_mem); farena_init(&tape_arena, tape_mem);
@@ -636,53 +623,53 @@ int main(void) {
farena_init(&code_arena, code_mem); farena_init(&code_arena, code_mem);
// Bootstrap Robust Sample: Factorial State Machine // Bootstrap Robust Sample: Factorial State Machine
scatter(PACK_TOKEN(STag_Comment, ID2('I','N')), "INIT "); // .IN scatter(pack_token(STag_Comment, id2('I','N')), "INIT "); // .IN
scatter(PACK_TOKEN(STag_Data, 5), 0); // $5 scatter(pack_token(STag_Data, 5), 0); // $5
scatter(PACK_TOKEN(STag_Data, 0), 0); // $0 (Addr) scatter(pack_token(STag_Data, 0), 0); // $0 (Addr)
scatter(PACK_TOKEN(STag_Imm, ID2('!',' ')), "STORE "); // ^! scatter(pack_token(STag_Imm, id2('!',' ')), "STORE "); // ^!
scatter(PACK_TOKEN(STag_Data, 1), 0); // $1 scatter(pack_token(STag_Data, 1), 0); // $1
scatter(PACK_TOKEN(STag_Data, 1), 0); // $1 (Addr) scatter(pack_token(STag_Data, 1), 0); // $1 (Addr)
scatter(PACK_TOKEN(STag_Imm, ID2('!',' ')), "STORE "); // ^! scatter(pack_token(STag_Imm, id2('!',' ')), "STORE "); // ^!
scatter(PACK_TOKEN(STag_Format, 0xA), 0); // Newline scatter(pack_token(STag_Format, 0xA), 0); // Newline
// Define the FS (Factorial Step) word in memory // Define the FS (Factorial Step) word in memory
scatter(PACK_TOKEN(STag_Define, ID2('F','S')), "F_STEP "); scatter(pack_token(STag_Define, id2('F','S')), "F_STEP ");
scatter(PACK_TOKEN(STag_Data, 0), 0); scatter(pack_token(STag_Data, 0), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH "); scatter(pack_token(STag_Call, id2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Call, ID2('R','0')), "RET_IF_Z"); scatter(pack_token(STag_Call, id2('R','0')), "RET_IF_Z");
scatter(PACK_TOKEN(STag_Format, 0xA), 0); // Newline scatter(pack_token(STag_Format, 0xA), 0); // Newline
scatter(PACK_TOKEN(STag_Data, 1), 0); scatter(pack_token(STag_Data, 1), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH "); scatter(pack_token(STag_Call, id2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Data, 0), 0); scatter(pack_token(STag_Data, 0), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH "); scatter(pack_token(STag_Call, id2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Call, ID2('M','*')), "MULT "); scatter(pack_token(STag_Call, id2('M','*')), "MULT ");
scatter(PACK_TOKEN(STag_Data, 1), 0); scatter(pack_token(STag_Data, 1), 0);
scatter(PACK_TOKEN(STag_Call, ID2('!',' ')), "STORE "); scatter(pack_token(STag_Call, id2('!',' ')), "STORE ");
scatter(PACK_TOKEN(STag_Format, 0xA), 0); // Newline scatter(pack_token(STag_Format, 0xA), 0); // Newline
scatter(PACK_TOKEN(STag_Data, 0), 0); scatter(pack_token(STag_Data, 0), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH "); scatter(pack_token(STag_Call, id2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Call, ID2('-','1')), "DEC "); scatter(pack_token(STag_Call, id2('-','1')), "DEC ");
scatter(PACK_TOKEN(STag_Data, 0), 0); scatter(pack_token(STag_Data, 0), 0);
scatter(PACK_TOKEN(STag_Call, ID2('!',' ')), "STORE "); scatter(pack_token(STag_Call, id2('!',' ')), "STORE ");
scatter(PACK_TOKEN(STag_Data, 1), 0); scatter(pack_token(STag_Data, 1), 0);
scatter(PACK_TOKEN(STag_Call, ID2('@',' ')), "FETCH "); scatter(pack_token(STag_Call, id2('@',' ')), "FETCH ");
scatter(PACK_TOKEN(STag_Call, ID2('P','R')), "PRINT "); // Print Accumulator! scatter(pack_token(STag_Call, id2('P','R')), "PRINT "); // Print Accumulator!
scatter(PACK_TOKEN(STag_Call, ID2('R','E')), "RETURN "); // Return! scatter(pack_token(STag_Call, id2('R','E')), "RETURN "); // Return!
scatter(PACK_TOKEN(STag_Format, 0xA), 0); // Newline scatter(pack_token(STag_Format, 0xA), 0); // Newline
// Call it // Call it
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP "); // ^FS scatter(pack_token(STag_Imm, id2('F','S')), "F_STEP "); // ^FS
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP "); scatter(pack_token(STag_Imm, id2('F','S')), "F_STEP ");
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP "); scatter(pack_token(STag_Imm, id2('F','S')), "F_STEP ");
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP "); scatter(pack_token(STag_Imm, id2('F','S')), "F_STEP ");
scatter(PACK_TOKEN(STag_Imm, ID2('F','S')), "F_STEP "); scatter(pack_token(STag_Imm, id2('F','S')), "F_STEP ");
MS_WNDCLASSA wc; MS_WNDCLASSA wc;
mem_fill(u8_(& wc), 0, sizeof(wc)); mem_fill(u8_(& wc), 0, sizeof(wc));
@@ -692,9 +679,9 @@ int main(void) {
wc.hbrBackground = ms_get_stock_object(4); wc.hbrBackground = ms_get_stock_object(4);
ms_register_class_a(&wc); ms_register_class_a(&wc);
void* hwnd = ms_create_window_ex_a(0, wc.lpszClassName, "Sourceless Global Memory Explorer", MS_WS_OVERLAPPEDWINDOW | MS_WS_VISIBLE, 100, 100, 1100, 750, NULL, NULL, wc.hInstance, NULL); void* hwnd = ms_create_window_ex_a(0, wc.lpszClassName, "Sourceless Global Memory Explorer", MS_WS_OVERLAPPEDWINDOW | MS_WS_VISIBLE, 100, 100, 1100, 750, nullptr, nullptr, wc.hInstance, nullptr);
MS_MSG msg; MS_MSG msg;
while (ms_get_message_a(&msg, NULL, 0, 0)) { ms_translate_message(&msg); ms_dispatch_message_a(&msg); } while (ms_get_message_a(&msg, nullptr, 0, 0)) { ms_translate_message(&msg); ms_dispatch_message_a(&msg); }
ms_exit_process(0); ms_exit_process(0);
return 0; return 0;
} }

View File

@@ -77,7 +77,6 @@ $linker_args += $flag_link_win_subsystem_console
$linker_args += "kernel32.lib" $linker_args += "kernel32.lib"
$linker_args += "user32.lib" $linker_args += "user32.lib"
$linker_args += "gdi32.lib" $linker_args += "gdi32.lib"
$linker_args += "/entry:main"
$linker_args += $object $linker_args += $object
$linker_args | ForEach-Object { Write-Host $_ } $linker_args | ForEach-Object { Write-Host $_ }