80 lines
4.8 KiB
Markdown
80 lines
4.8 KiB
Markdown
# 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.
|
|
```c
|
|
#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_a(MS_WNDCLASSA const* lpWndClass) asm("RegisterClassA");`
|
|
* *Incorrect:* `WinAPI U2 RegisterClassA(...);`
|
|
|
|
## 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:
|
|
```c
|
|
typedef struct MS_WNDCLASSA {
|
|
U4 style;
|
|
S8 (*lpfnWndProc)(void*, U4, U8, S8);
|
|
S4 cbClsExtra;
|
|
// ...
|
|
char const* lpszClassName;
|
|
} MS_WNDCLASSA;
|
|
```
|
|
* **Multi-line Argument Alignment:** For long function signatures, place one argument per line with a single 4-space indent.
|
|
* Example:
|
|
```c
|
|
WinAPI B4 ms_read_console(
|
|
MS_Handle handle,
|
|
UTF8*r buffer,
|
|
U4 to_read,
|
|
U4*r num_read,
|
|
U8 reserved_input_control
|
|
) asm("ReadConsoleA");
|
|
```
|
|
* **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:** Always place `else if` and `else` statements on a new line, un-nested from the previous closing brace.
|
|
|
|
## 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 `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.
|
|
|
|
## 6. Type Qualifiers
|
|
* **`const` Placement:** The `const` keyword 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;`
|
|
|
|
## 7. Metadata Coupling (X-Macros)
|
|
* **Metadata Enums:** Use X-Macros to define Enums that are tightly coupled with static metadata (colors, prefixes, names).
|
|
* Example:
|
|
```c
|
|
#define Tag_Entries() \
|
|
X(Define, "Define", 0x0018AEFF, ":") \
|
|
X(Call, "Call", 0x00D6A454, "~")
|
|
```
|
|
* **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`).
|