Files
forth_bootslop/attempt_1/main.c
2026-02-19 17:33:34 -05:00

337 lines
11 KiB
C

// Fundamental Boolean and Null types for no-std environment
#define true 1
#define false 0
#define NULL ((void*)0)
#include "duffle.amd64.win32.h"
// --- WinAPI Minimal Definitions ---
typedef int MS_BOOL;
typedef unsigned long MS_DWORD;
typedef void* MS_HANDLE;
typedef MS_HANDLE MS_HWND;
typedef MS_HANDLE MS_HMENU;
typedef MS_HANDLE MS_HINSTANCE;
typedef MS_HANDLE MS_HICON;
typedef MS_HANDLE MS_HCURSOR;
typedef MS_HANDLE MS_HBRUSH;
typedef MS_HANDLE MS_HDC;
typedef MS_HANDLE MS_HFONT;
typedef long MS_LONG;
typedef char const* MS_LPCSTR;
typedef void* MS_LPVOID;
typedef S8 MS_LRESULT;
typedef U8 MS_WPARAM;
typedef S8 MS_LPARAM;
typedef U4 MS_UINT;
typedef struct MS_WNDCLASSA {
MS_UINT style;
MS_LRESULT (*lpfnWndProc)(MS_HWND, MS_UINT, MS_WPARAM, MS_LPARAM);
int cbClsExtra;
int cbWndExtra;
MS_HINSTANCE hInstance;
MS_HICON hIcon;
MS_HCURSOR hCursor;
MS_HBRUSH hbrBackground;
MS_LPCSTR lpszMenuName;
MS_LPCSTR lpszClassName;
} MS_WNDCLASSA;
typedef struct MS_POINT {
MS_LONG x, y;
} MS_POINT;
typedef struct MS_MSG {
MS_HWND hwnd;
MS_UINT message;
MS_WPARAM wParam;
MS_LPARAM lParam;
MS_DWORD time;
MS_POINT pt;
} MS_MSG;
typedef struct MS_RECT {
MS_LONG left, top, right, bottom;
} MS_RECT;
typedef struct MS_PAINTSTRUCT {
MS_HDC hdc;
MS_BOOL fErase;
MS_RECT rcPaint;
MS_BOOL fRestore;
MS_BOOL fIncUpdate;
U1 rgbReserved[32];
} MS_PAINTSTRUCT;
// Win32 API declarations
WinAPI MS_LPVOID VirtualAlloc(MS_LPVOID lpAddress, U8 dwSize, MS_DWORD flAllocationType, MS_DWORD flProtect);
WinAPI void ExitProcess(MS_UINT uExitCode);
WinAPI U2 RegisterClassA(const MS_WNDCLASSA* lpWndClass);
WinAPI MS_HWND CreateWindowExA(MS_DWORD dwExStyle, MS_LPCSTR lpClassName, MS_LPCSTR lpWindowName, MS_DWORD dwStyle, int X, int Y, int nWidth, int nHeight, MS_HWND hWndParent, MS_HMENU hMenu, MS_HINSTANCE hInstance, MS_LPVOID lpParam);
WinAPI MS_BOOL ShowWindow(MS_HWND hWnd, int nCmdShow);
WinAPI MS_BOOL GetMessageA(MS_MSG* lpMsg, MS_HWND hWnd, MS_UINT wMsgFilterMin, MS_UINT wMsgFilterMax);
WinAPI MS_BOOL TranslateMessage(const MS_MSG* lpMsg);
WinAPI MS_LRESULT DispatchMessageA(const MS_MSG* lpMsg);
WinAPI MS_LRESULT DefWindowProcA(MS_HWND hWnd, MS_UINT Msg, MS_WPARAM wParam, MS_LPARAM lParam);
WinAPI void PostQuitMessage(int nExitCode);
WinAPI MS_BOOL InvalidateRect(MS_HWND hWnd, const MS_RECT* lpRect, MS_BOOL bErase);
WinAPI MS_HDC BeginPaint(MS_HWND hWnd, MS_PAINTSTRUCT* lpPaint);
WinAPI MS_BOOL EndPaint(MS_HWND hWnd, const MS_PAINTSTRUCT* lpPaint);
WinAPI MS_DWORD SetTextColor(MS_HDC hdc, MS_DWORD color);
WinAPI MS_DWORD SetBkColor(MS_HDC hdc, MS_DWORD color);
WinAPI MS_BOOL TextOutA(MS_HDC hdc, int x, int y, MS_LPCSTR lpString, int c);
WinAPI MS_HANDLE GetStockObject(int i);
WinAPI MS_HFONT CreateFontA(int cHeight, int cWidth, int cEscapement, int cOrientation, int cWeight, MS_DWORD bItalic, MS_DWORD bUnderline, MS_DWORD bStrikeOut, MS_DWORD iCharSet, MS_DWORD iOutPrecision, MS_DWORD iClipPrecision, MS_DWORD iQuality, MS_DWORD iPitchAndFamily, MS_LPCSTR pszFaceName);
WinAPI MS_HANDLE SelectObject(MS_HDC hdc, MS_HANDLE h);
#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_PRIOR 0x21 // Page Up
#define MS_VK_NEXT 0x22 // Page Down
// --- Semantic Tags (The "Colors" of ColorForth) ---
#define TAG_DEFINE 0x0 // RED: New word definition
#define TAG_CALL 0x1 // GREEN: Call/Compile word
#define TAG_DATA 0x2 // CYAN: Variable or Literal Address
#define TAG_IMM 0x3 // YELLOW: Immediate value/Execute
#define TAG_COMMENT 0x4 // WHITE: Ignored by compiler
// 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)
// The Tape Drive (Memory Arena)
global U4* tape;
global U8 tape_pos = 0;
global U8 view_block = 0; // Current block being viewed
#define TOKENS_PER_BLOCK 256
// Virtual Machine State (Onat's 2-item stack)
global U8 vm_rax = 0;
global U8 vm_rdx = 0;
internal void scatter(U4 token) {
tape[tape_pos++] = token;
}
// Minimal u64 to hex string helper
internal void u64_to_hex(U8 val, char* buf, int chars) {
static const char hex_chars[] = "0123456789ABCDEF";
for(S1 i = chars - 1; i >= 0; --i) {
buf[i] = hex_chars[val & 0xF];
val >>= 4;
}
}
// Provide memset for the compiler's implicit struct zeroing (-nostdlib)
void* memset(void* dest, int c, U8 count) {
U1* bytes = (U1*)dest;
while (count--) {
*bytes++ = (U1)c;
}
return dest;
}
// --- The Tiny Interpreter ---
internal void vm_execute(U4 val) {
// Very rudimentary simulated execution.
// 0x1 = DUP
// 0x2 = MULT
// Normally this would look up the address in the dictionary.
if (val == 0x1) {
// DUP (push rax into rdx, simulating a 2-reg stack)
vm_rdx = vm_rax;
} else if (val == 0x2) {
// MULT (rax = rax * rdx)
vm_rax = vm_rax * vm_rdx;
} else if (val == 0x51415245) {
// Call "SQUARE". For this tiny mock, we just execute its body directly: DUP *
vm_execute(0x1); // DUP
vm_execute(0x2); // MULT
}
}
internal void vm_eval_tape() {
for (U8 i = 0; i < tape_pos; ++i) {
U4 t = tape[i];
U4 tag = UNPACK_TAG(t);
U4 val = UNPACK_VAL(t);
if (tag == TAG_DATA) {
// Push data onto the 2-register stack (simulate the xchg setup)
vm_rdx = vm_rax;
vm_rax = val;
} else if (tag == TAG_IMM) {
// Execute immediately
vm_execute(val);
}
}
}
// --- Window Procedure (Event Loop) ---
MS_LRESULT win_proc(MS_HWND hwnd, MS_UINT msg, MS_WPARAM wparam, MS_LPARAM lparam) {
switch (msg) {
case MS_WM_KEYDOWN: {
if (wparam == MS_VK_NEXT) { // Page Down
if ((view_block + 1) * TOKENS_PER_BLOCK < tape_pos) view_block++;
InvalidateRect(hwnd, NULL, true);
} else if (wparam == MS_VK_PRIOR) { // Page Up
if (view_block > 0) view_block--;
InvalidateRect(hwnd, NULL, true);
}
return 0;
}
case MS_WM_PAINT: {
MS_PAINTSTRUCT ps;
MS_HDC hdc = BeginPaint(hwnd, &ps);
// Modern Monospace Font (Consolas)
MS_HFONT hFont = CreateFontA(22, 0, 0, 0, 400, 0, 0, 0, 0, 0, 0, 0, 0, "Consolas");
MS_HANDLE hOldFont = SelectObject(hdc, hFont);
// Dark background
U4 bg_color = 0x001E1E1E;
SetBkColor(hdc, bg_color);
int x = 20;
int y = 20;
int line_height = 24;
// Render Block Header
SetTextColor(hdc, 0x00AAAAAA);
char header_str[32] = "Block 0x000";
u64_to_hex(view_block, header_str + 8, 3);
TextOutA(hdc, x, y, header_str, 11);
y += line_height * 2;
// Render Tokens for current block
U8 start_idx = view_block * TOKENS_PER_BLOCK;
U8 end_idx = start_idx + TOKENS_PER_BLOCK;
if (end_idx > tape_pos) end_idx = tape_pos;
for (U8 i = start_idx; i < end_idx; i++) {
U4 t = tape[i];
U4 tag = UNPACK_TAG(t);
U4 val = UNPACK_VAL(t);
U4 color = 0x00FFFFFF;
const char* prefix = "";
switch (tag) {
case TAG_DEFINE: color = 0x003333FF; prefix = ": "; break; // RED
case TAG_CALL: color = 0x0033FF33; prefix = "~ "; break; // GREEN
case TAG_DATA: color = 0x00FFFF33; prefix = "$ "; break; // CYAN
case TAG_IMM: color = 0x0033FFFF; prefix = "^ "; break; // YELLOW
case TAG_COMMENT: color = 0x00AAAAAA; prefix = ". "; break; // DIM
}
SetTextColor(hdc, color);
TextOutA(hdc, x, y, prefix, 2);
char val_str[8];
u64_to_hex(val, val_str, 7);
val_str[7] = '\0';
TextOutA(hdc, x + 24, y, val_str, 7);
y += line_height;
// Simple column wrapping inside the block
if (y > 500) {
y = 20 + line_height * 2;
x += 160;
}
}
// Render VM State at the bottom right
y = 480;
x = 600;
SetTextColor(hdc, 0x00FFFFFF);
TextOutA(hdc, x, y, "VM State (2-Reg Stack)", 22);
y += line_height;
char rax_str[16] = "RAX: 0x00000000";
char rdx_str[16] = "RDX: 0x00000000";
u64_to_hex(vm_rax, rax_str + 7, 8);
u64_to_hex(vm_rdx, rdx_str + 7, 8);
SetTextColor(hdc, 0x0033FF33);
TextOutA(hdc, x, y, rax_str, 15);
y += line_height;
SetTextColor(hdc, 0x00FFFF33);
TextOutA(hdc, x, y, rdx_str, 15);
SelectObject(hdc, hOldFont);
EndPaint(hwnd, &ps);
return 0;
}
case MS_WM_DESTROY: {
PostQuitMessage(0);
return 0;
}
}
return DefWindowProcA(hwnd, msg, wparam, lparam);
}
void main() {
tape = (U4*)VirtualAlloc(NULL, 64 * 1024, MS_MEM_COMMIT | MS_MEM_RESERVE, MS_PAGE_READWRITE);
if (!tape) ExitProcess(1);
// Bootstrap Block 0
scatter(PACK_TOKEN(TAG_DEFINE, 0x51415245)); // ":SQUARE"
scatter(PACK_TOKEN(TAG_CALL, 0x00000001)); // DUP
scatter(PACK_TOKEN(TAG_CALL, 0x00000002)); // MULT
scatter(PACK_TOKEN(TAG_CALL, 0x00000003)); // RET
scatter(PACK_TOKEN(TAG_COMMENT, 0x4E4F5445)); // ".NOTE"
scatter(PACK_TOKEN(TAG_DATA, 5)); // $5
scatter(PACK_TOKEN(TAG_IMM, 0x51415245)); // ^SQUARE
// Fill some padding so we can test pagination (Page Down)
for(int i=0; i < 300; i++) {
scatter(PACK_TOKEN(TAG_COMMENT, 0x0));
}
// Block 1 content
scatter(PACK_TOKEN(TAG_DATA, 10)); // $10
scatter(PACK_TOKEN(TAG_IMM, 0x51415245)); // ^SQUARE
// Run Interpreter
vm_eval_tape();
// Window Setup
MS_WNDCLASSA wc;
memset(&wc, 0, sizeof(wc));
wc.lpfnWndProc = win_proc;
wc.hInstance = (MS_HINSTANCE)GetStockObject(0);
wc.lpszClassName = "ColorForthWindow";
wc.hbrBackground = (MS_HBRUSH)GetStockObject(4);
if (!RegisterClassA(&wc)) ExitProcess(1);
MS_HWND hwnd = CreateWindowExA(
0, wc.lpszClassName, "Sourceless Tape Drive Editor",
MS_WS_OVERLAPPEDWINDOW | MS_WS_VISIBLE,
100, 100, 800, 600, NULL, NULL, wc.hInstance, NULL
);
if (!hwnd) ExitProcess(1);
MS_MSG msg;
while (GetMessageA(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessageA(&msg);
}
ExitProcess(0);
}