Files
forth_bootslop/CONVENTIONS.md
2026-02-20 14:11:59 -05:00

2.8 KiB

C DSL Conventions (duffle)

This document outlines the strict C style and architectural conventions expected in this workspace. It is based on the duffle.amd64.win32.h header, the user's fortish-study samples, and iterative feedback.

1. Type Conventions (Byte-Width Fundamentals)

  • Never use standard C types (e.g., int, long, unsigned, short, float, double) directly in application code.
  • Always use the byte-width typedefs:
    • Unsigned: U1, U2, U4, U8
    • Signed: S1, S2, S4, S8
    • Float: F4, F8
    • Boolean: B1, B2, B4, B8 (use true/false primitives)
    • Strings/Chars: UTF8 (for characters), Str8 (for string slices)
  • WinAPI Structs: Only use MS_ prefixed fundamental types (e.g., MS_LONG, MS_DWORD) inside WinAPI struct definitions (MS_WNDCLASSA, etc.) to maintain FFI compatibility. Do not use them in general application logic.

2. Declaration Wrappers & X-Macros

  • Structs and Enums: Always use the macro wrappers for defining compound types to enforce clean namespacing.
    • typedef Struct_(Name) { ... };
    • typedef Enum_(UnderlyingType, Name) { ... };
  • X-Macros: Use X-Macros to tightly couple Enums with their corresponding string representations or metadata.
    #define My_Tag_Entries() 
            X(Define, "Define") 
            X(Call,   "Call")
    

3. Function & Symbol Naming

  • 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(const MS_WNDCLASSA* lpWndClass) asm("RegisterClassA");
    • Incorrect: WinAPI U2 RegisterClassA(...);

4. Memory Management

  • No Standard Library: The environment is built with -nostdlib and -ffreestanding. Never include <stdlib.h>, <string.h>, etc.
  • 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. (A minimal memset/memcpy shim is only provided to satisfy compiler intrinsic struct zeroing under -nostdlib).

5. Modifiers

  • internal: Static functions.
  • global: Global state variables.
  • IA_: Internal Always Inline.
  • I_: Internal Inline.
  • Pointers use *r (restrict) or *v (volatile) macros where applicable.