This commit is contained in:
2026-02-21 12:11:39 -05:00
parent b5e038f909
commit fcc4d4a515
7 changed files with 2648 additions and 136 deletions

View File

@@ -465,13 +465,76 @@ IA_ void compile_and_run_tape(void)
debug_log(str8("JIT finished. RAX: <rax>, RDX: <rdx>"), ktl_str8_from_arr(post_jit_log_table));
}
#undef r
#undef v
#undef expect
#include "microui.c"
#undef expect
#define expect(x,y) __builtin_expect(x, y) // so compiler knows the common path
#define r restrict
#define v volatile
global mu_Context mu_ctx;
internal int text_width_cb(mu_Font font, const char *str, int len) {
if (len == -1) { len = 0; while (str[len]) len++; }
return len * 11; // Approx 11px per char for Consolas 20
}
internal int text_height_cb(mu_Font font) {
return 20; // Consolas 20 height
}
internal void gdi_draw_rect(void* hdc, mu_Rect rect, mu_Color color) {
U1 red = ((U1*)&color)[0];
U1 green = ((U1*)&color)[1];
U1 blue = ((U1*)&color)[2];
void* hBrush = ms_create_solid_brush((red) | (green << 8) | (blue << 16));
void* hOldBrush = ms_select_object(hdc, hBrush);
ms_rectangle(hdc, rect.x - 1, rect.y - 1, rect.x + rect.w + 1, rect.y + rect.h + 1);
ms_select_object(hdc, hOldBrush);
ms_delete_object(hBrush);
}
internal void render_microui(void* hdc) {
mu_Command *cmd = NULL;
while (mu_next_command(&mu_ctx, &cmd)) {
switch (cmd->type) {
case MU_COMMAND_TEXT: {
U1 red = ((U1*)&cmd->text.color)[0];
U1 green = ((U1*)&cmd->text.color)[1];
U1 blue = ((U1*)&cmd->text.color)[2];
ms_set_text_color(hdc, (red) | (green << 8) | (blue << 16));
int len = 0; while (cmd->text.str[len]) len++;
ms_text_out_a(hdc, cmd->text.pos.x, cmd->text.pos.y, cmd->text.str, len);
break;
}
case MU_COMMAND_RECT: {
gdi_draw_rect(hdc, cmd->rect.rect, cmd->rect.color);
break;
}
case MU_COMMAND_ICON: {
gdi_draw_rect(hdc, cmd->icon.rect, cmd->icon.color);
break;
}
case MU_COMMAND_CLIP: {
break;
}
}
}
}
S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
{
U8 tape_count = tape_arena.used / sizeof(U4);
U4*r tape_ptr = u4_r(tape_arena.start);
switch (msg) {
case MS_WM_CHAR: {
if (editor_mode != MODE_EDIT) return 0;
char buf[2] = { (char)wparam, 0 };
mu_input_text(&mu_ctx, buf);
if (editor_mode != MODE_EDIT) { ms_invalidate_rect(hwnd, nullptr, true); return 0; }
U4 t = tape_ptr[cursor_idx];
U4 tag = unpack_tag(t);
@@ -479,7 +542,7 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
U1 c = u1_(wparam);
B4 should_skip = c < 32 || (c == 'e' && mode_switch_now);
if (should_skip) { mode_switch_now = false; return 0; }
if (should_skip) { mode_switch_now = false; ms_invalidate_rect(hwnd, nullptr, true); return 0; }
if (tag == STag_Data) {
U4 digit = 16;
@@ -512,7 +575,34 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
ms_invalidate_rect(hwnd, nullptr, true);
return 0;
}
case MS_WM_MOUSEMOVE: {
mu_input_mousemove(&mu_ctx, lparam & 0xFFFF, (lparam >> 16) & 0xFFFF);
ms_invalidate_rect(hwnd, nullptr, true);
return 0;
}
case MS_WM_LBUTTONDOWN: {
mu_input_mousedown(&mu_ctx, lparam & 0xFFFF, (lparam >> 16) & 0xFFFF, MU_MOUSE_LEFT);
ms_invalidate_rect(hwnd, nullptr, true);
return 0;
}
case MS_WM_LBUTTONUP: {
mu_input_mouseup(&mu_ctx, lparam & 0xFFFF, (lparam >> 16) & 0xFFFF, MU_MOUSE_LEFT);
ms_invalidate_rect(hwnd, nullptr, true);
return 0;
}
case MS_WM_MOUSEWHEEL: {
mu_input_scroll(&mu_ctx, 0, ((S4)(wparam >> 16)) / -30);
ms_invalidate_rect(hwnd, nullptr, true);
return 0;
}
case MS_WM_KEYDOWN: {
int key = 0;
if (wparam == MS_VK_BACK) key = MU_KEY_BACKSPACE;
if (wparam == MS_VK_RETURN) key = MU_KEY_RETURN;
if (wparam == 0x10) key = MU_KEY_SHIFT;
if (wparam == 0x11) key = MU_KEY_CTRL;
if (wparam == 0x12) key = MU_KEY_ALT;
if (key) mu_input_keydown(&mu_ctx, key);
if (wparam == 0x45 && editor_mode == MODE_NAV) {
editor_mode = MODE_EDIT;
@@ -650,115 +740,122 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
ms_invalidate_rect(hwnd, nullptr, true);
return 0;
}
case MS_WM_KEYUP: {
int key = 0;
if (wparam == MS_VK_BACK) key = MU_KEY_BACKSPACE;
if (wparam == MS_VK_RETURN) key = MU_KEY_RETURN;
if (wparam == 0x10) key = MU_KEY_SHIFT;
if (wparam == 0x11) key = MU_KEY_CTRL;
if (wparam == 0x12) key = MU_KEY_ALT;
if (key) mu_input_keyup(&mu_ctx, key);
ms_invalidate_rect(hwnd, nullptr, true);
return 0;
}
case MS_WM_SIZE: {
ms_invalidate_rect(hwnd, nullptr, true);
return 0;
}
case MS_WM_ERASEBKGND: {
return 1;
}
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);
mu_begin(&mu_ctx);
ms_set_bk_mode(hdc, 1);
if (mu_begin_window(&mu_ctx, "ColorForth Source Tape", mu_rect(10, 10, 900, 480))) {
U4*r tape_ptr = u4_r(tape_arena.start);
U8*r anno_ptr = u8_r(anno_arena.start);
void* hBgBrush = ms_create_solid_brush(0x00222222);
ms_select_object(hdc, hBgBrush);
ms_rectangle(hdc, -1, -1, 3000, 3000);
S4 start_x = 5, start_y = 5, spacing_x = 6, spacing_y = 26;
S4 x = start_x, y = start_y;
void* hBrushEdit = ms_create_solid_brush(0x008E563B);
void* hBrushNav = ms_create_solid_brush(0x00262F3B);
for (U8 i = 0; i < tape_count; i++) {
U4 t = tape_ptr[i];
U4 tag = unpack_tag(t);
U4 val = unpack_val(t);
U8 anno = anno_ptr[i];
S4 start_x = 40, start_y = 60, spacing_x = 110, spacing_y = 35;
S4 x = start_x, y = start_y;
if (tag == STag_Format && val == 0xA) {
x = start_x;
y += spacing_y;
continue;
}
U4*r tape_ptr = u4_r(tape_arena.start);
U8*r anno_ptr = u8_r(anno_arena.start);
U4 color_u32 = tag_colors[tag];
const char* prefix = tag_prefixes[tag];
char val_str[9];
if (tag == STag_Data) {
u64_to_hex(val, val_str, 6);
val_str[6] = '\0';
}
else
{
char* a_str = (char*) & anno;
for(int c=0; c<8; c++) {
val_str[c] = a_str[c] ? a_str[c] : ' ';
}
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';
for (U8 i = 0; i < tape_count; i++)
{
if (x >= start_x + (TOKENS_PER_ROW * spacing_x)) {
x = start_x; y += spacing_y;
}
S4 render_y = y - scroll_y_offset;
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 (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 (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) {
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
{
char* a_str = (char*) & anno;
for(int c=0; c<8; c++) {
val_str[c] = a_str[c] ? a_str[c] : ' ';
}
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;
}
}
int btn_w = 20 + text_width_cb(NULL, out_buf, 10);
// auto-wrap
mu_Container* current_window = mu_get_current_container(&mu_ctx);
if (x + btn_w > current_window->body.w - 15) {
x = start_x;
y += spacing_y;
}
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);
mu_ctx.style->colors[MU_COLOR_BUTTON] = mu_color(color_u32 & 0xFF, (color_u32 >> 8) & 0xFF, (color_u32 >> 16) & 0xFF, 255);
if (i == cursor_idx && editor_mode == MODE_EDIT) {
mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(0,0,0,255);
mu_ctx.style->colors[MU_COLOR_BUTTON] = mu_color(0x8E, 0x56, 0x3B, 255);
} else if (i == cursor_idx && editor_mode == MODE_NAV) {
mu_ctx.style->colors[MU_COLOR_BUTTON] = mu_color(0x26, 0x2F, 0x3B, 255);
}
mu_layout_set_next(&mu_ctx, mu_rect(x, y, btn_w, 22), 1);
if (mu_button(&mu_ctx, out_buf)) {
cursor_idx = i;
editor_mode = MODE_NAV;
}
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);
ms_set_text_color(hdc, 0x00FFFFFF);
char jit_str[64] = "Mode: Incremental | JIT Size: 0x000 bytes";
x += btn_w + spacing_x;
mu_ctx.style->colors[MU_COLOR_BUTTON] = mu_color(75, 75, 75, 255);
mu_ctx.style->colors[MU_COLOR_TEXT] = mu_color(230, 230, 230, 255);
}
// Dummy element to ensure scrolling bounds are correct
mu_layout_set_next(&mu_ctx, mu_rect(start_x, y + spacing_y, 10, 10), 1);
mu_draw_rect(&mu_ctx, mu_layout_next(&mu_ctx), mu_color(0,0,0,0));
mu_end_window(&mu_ctx);
}
if (mu_begin_window(&mu_ctx, "HUD / Memory", mu_rect(10, 500, 900, 200))) {
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";
mu_layout_row(&mu_ctx, 1, (int[]){-1}, 0);
mu_text(&mu_ctx, "x86-64 Machine Code Emitter | 2-Reg Stack | [F5] Toggle Run Mode | [PgUp/PgDn] Scroll");
mu_text(&mu_ctx, jit_str);
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);
ms_text_out_a(hdc, 40, 550, state_str, 29);
if (tape_count > 0 && cursor_idx < tape_count) {
mu_text(&mu_ctx, state_str);
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]) {
@@ -766,47 +863,48 @@ S8 win_proc(void* hwnd, U4 msg, U8 wparam, S8 lparam)
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, 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);
ms_text_out_a(hdc, 400, 550 + (i * 25), glob_str, 13);
}
ms_set_text_color(hdc, 0x00C8C8C8);
ms_text_out_a(hdc, 750, 520, "Print Log:", 10);
for (int i = 0; i<log_count && i < 4; i ++) {
char log_str[32] = "00000000";
u64_to_hex(log_buffer[i], log_str, 8);
ms_set_text_color(hdc, 0x0094BAA1);
ms_text_out_a(hdc, 750, 550 + (i * 25), log_str, 8);
}
ms_set_text_color(hdc, 0x00C8C8C8);
ms_text_out_a(hdc, 40, 650, "Debug Log:", 10);
for (U4 i = 0; i < gdi_log_count; i++) {
U4 len = 0;
while(gdi_log_buffer[i][len] != '\0' && len < GDI_LOG_MAX_LINE_LEN) {
len++;
}
ms_set_text_color(hdc, 0x00AAAAAA);
ms_text_out_a(hdc, 40, 670 + (i * 20), gdi_log_buffer[i], len);
mu_text(&mu_ctx, semantics_str);
}
mu_end_window(&mu_ctx);
}
mu_end(&mu_ctx);
ms_select_object(hdc, hOldFont);
ms_delete_object(hBgBrush);
ms_delete_object(hBrushEdit);
ms_delete_object(hBrushNav);
ms_delete_object(hHudBrush);
ms_end_paint(hwnd, & ps);
return 0;
MS_PAINTSTRUCT ps;
void* hdc = ms_begin_paint(hwnd, & ps);
MS_RECT rect;
ms_get_client_rect(hwnd, &rect);
S4 width = rect.right - rect.left;
S4 height = rect.bottom - rect.top;
void* memDC = ms_create_compatible_dc(hdc);
void* memBitmap = ms_create_compatible_bitmap(hdc, width, height);
void* oldBitmap = ms_select_object(memDC, memBitmap);
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(memDC, hFont);
ms_set_bk_mode(memDC, 1);
void* hBgBrush = ms_create_solid_brush(0x00222222);
ms_select_object(memDC, hBgBrush);
ms_rectangle(memDC, -1, -1, width + 2, height + 2);
render_microui(memDC);
ms_bit_blt(hdc, 0, 0, width, height, memDC, 0, 0, MS_SRCCOPY);
ms_select_object(memDC, hOldFont);
ms_delete_object(hBgBrush);
ms_delete_object(hFont);
ms_select_object(memDC, oldBitmap);
ms_delete_object(memBitmap);
ms_delete_dc(memDC);
ms_end_paint(hwnd, & ps);
return 0;
}
case MS_WM_DESTROY: { ms_post_quit_message(0); return 0; }
}
@@ -822,6 +920,10 @@ int main(void) {
farena_init(& tape_arena, tape_mem);
farena_init(& anno_arena, anno_mem);
farena_init(& code_arena, code_mem);
mu_init(&mu_ctx);
mu_ctx.text_width = text_width_cb;
mu_ctx.text_height = text_height_cb;
scatter(pack_token(STag_Comment, 0), "INIT ");
scatter(pack_token(STag_Data, 5), 0);