5.1 KiB
5.1 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(usetrue/falseprimitives) - Strings/Chars:
UTF8(for characters),Str8(for string slices)
- Unsigned:
- Fundamental Type Casts: Strictly use the provided casting macros (e.g.,
u8_(val),u4_r(ptr),s4_(val)) instead of standard C-style cast syntax like(U8)val. Standard casts should only be used for complex types or when an appropriate macro isn't available. - 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_casefor all functions and variables. - Types: Use
PascalCasefor type names (FArena,SWord_Tag). - WinAPI Symbols: When declaring foreign Win32 symbols, prefix the C function name with
ms_(usinglower_snake_case) and use theasm("SymbolName")attribute to link it to the actual DLL export.- Correct:
WinAPI U2 ms_register_class_a(MS_WNDCLASSA const* lpWndClass) asm("RegisterClassA"); - Incorrect:
WinAPI U2 RegisterClassA(...);
- Correct:
4. Formatting & Layout
- Vertical Alignment: Align related variable declarations, struct fields, and function prototypes into columns to create a "sheet-like" layout. This improves visual parsing.
- Example Struct:
typedef struct MS_WNDCLASSA { U4 style; S8 (*lpfnWndProc)(void*, U4, U8, S8); S4 cbClsExtra; // ... char const* lpszClassName; } MS_WNDCLASSA;
- Example Struct:
- Multi-line Argument Alignment: For long function signatures, place one argument per line with a single 4-space indent.
- WinAPI Grouping: Group foreign procedure declarations by their originating OS library (e.g., Kernel32, User32, GDI32) using comment headers.
- Brace Style: Use Allman style (braces on a new line) for function bodies or control blocks (
if,for,switch, etc.) that are large or complex. Smaller blocks may use K&R style. - Conditionals & Control Flow: Always place
else ifandelsestatements on a new line. Align control flow parentheses (e.g., between consecutivewhileandifblocks) vertically when possible for aesthetic uniformity:while (len < 8) len ++; if (len > 0) { ... } - Address-Of Operator: Do insert a space between the address-of operator (
&) and the variable name.- Correct:
& my_var - Incorrect:
&my_var
- Correct:
5. Memory Management
- 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
FArenaand 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_fillandmem_copyinstead of standardmemset/memcpywithin the application logic.
6. Type Qualifiers
constPlacement: Theconstkeyword 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;
- Correct:
7. Metadata Coupling (X-Macros)
- Metadata Enums: Use X-Macros to define Enums that are tightly coupled with static metadata (colors, prefixes, names).
- Example:
#define Tag_Entries() \ X(Define, "Define", 0x0018AEFF, ":") \ X(Call, "Call", 0x00D6A454, "~")
- Example:
- Naming Conventions: When using X-Macros for Tags, entry names should be PascalCase, and the Enum symbols should be prefixed with the Enum type name (e.g.,
tmpl(STag, Define)->STag_Define).