Files
forth_bootslop/CLAUDE.md
2026-02-21 10:06:50 -05:00

4.4 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

bootslop is an experimental x86-64 Windows application: a sourceless, zero-overhead ColorForth-inspired programming environment. There is no human-readable source — the "source of truth" is a binary token array (the "tape"). It features a modal visual editor (GDI-based), real-time JIT compilation to x86-64 machine code, and cartridge-based persistence.

The canonical reference for architecture is references/Architectural_Consolidation.md. The coding conventions are in CONVENTIONS.md.

Build

Two-stage build via PowerShell: compile with clang, link with lld-link.

pwsh scripts/build.attempt_1.c.ps1

Output goes to build/attempt_1.exe. Run the exe manually — it opens a GUI window.

Toolchain requirements: clang and lld-link.exe on PATH. Targets amd64 Windows 11. Standard: C23. Flags: -O0 -g -Wall -DBUILD_DEBUG=1.

No automated tests exist. Verification is interactive via the running GUI.

Code Architecture

All active source is in attempt_1/:

  • main.c — The entire application (~850 lines). Contains: semantic tag definitions (X-macro), global VM state, the JIT compiler (compile_action, compile_and_run), the GDI renderer, keyboard input handling, and cartridge save/load (F1/F2).
  • duffle.amd64.win32.h — The C DSL header. Defines all base types (U1U8, S1S8, F4, F8, B1B8, Str8, UTF8), macros (global, internal, LP_, I_, N_), arena allocator (FArena, farena_push, farena_reset), string formatting, and raw WinAPI bindings.

Token / Tape Model

  • Tokens are U4 (32-bit): top 4 bits = semantic tag, lower 28 bits = value or annotation index.
  • Tags are defined via X-macro Tag_Entries(): Define, Call, Data, Imm, Comment, Format.
  • Two arenas: tape_arena (array of U4 tokens) and anno_arena (array of U8 — 8-char name slots for each token).
  • Helper macros: pack_token(tag, val), unpack_tag(token), unpack_val(token).

JIT Compiler

  • compile_action() — incremental: emits x86-64 machine code into code_arena up to the cursor position. Runs on every keystroke for live feedback.
  • compile_and_run() — full tape compilation + execution. Toggled by F5.
  • The VM uses two global registers (vm_rax, vm_rdx) and 16 global memory cells (vm_globals[16]).
  • 13 primitive operations: SWAP, MULT, ADD, FETCH, STORE, DUP, DROP, SUB, DEC, PRINT, RET, RET_IF_Z, RET_IF_S.
  • Name resolution: resolve_name_to_index() matches 8-char space-padded annotations against primitives or prior Define tokens. After edits, relink_tape() re-resolves all Call/Imm references.

Editor

  • Two modes: MODE_NAV (navigate) / MODE_EDIT (insert tokens). Toggled with i / Escape.
  • Tape renders as colored token boxes, 8 per row (TOKENS_PER_ROW), each showing a prefix character (from tag_prefixes) and a 6-char hex value or 8-char name.
  • GDI double-buffered rendering. Scroll via arrow keys in NAV mode.

C DSL Conventions (from CONVENTIONS.md — strictly enforced)

Types: Never use int, long, unsigned, etc. Always use U1/U2/U4/U8 (unsigned), S1/S2/S4/S8 (signed), F4/F8 (float), B1B8 (bool). Use cast macros (u8_(val), u4_(val)) not C-style casts.

Naming: lower_snake_case for functions/variables. PascalCase for types. WinAPI bindings prefixed with ms_ using asm("SymbolName") — never declare raw WinAPI names.

const placement: Always to the right: char const*, not const char*.

Structs/Enums: Use typedef Struct_(Name) { ... }; and typedef Enum_(UnderlyingType, Name) { ... };.

X-Macros: Use for enums coupled with metadata (colors, prefixes, names). Entry names PascalCase, enum symbols use tmpl(TypeName, Entry)TypeName_Entry.

Memory: Use FArena / farena_push / farena_reset — no raw malloc. Use mem_fill/mem_copy not memset/memcpy. Do not #include <stdlib.h> or <string.h>.

Formatting: Allman braces for complex blocks. Vertical alignment for struct fields and related declarations. Space between & and operand: & my_var. else if / else on new lines.

Storage class keywords: global (= static at file scope), internal (= static for functions), LP_ (= static inside a function), I_ (inline), N_ (noinline).