conductor(deob_c11_ref): c11_convention.md - the synthesis; 15 sections; ~700 LOC
Main C11 reference: 15 sections. ~700 LOC. Synthesizes the duffle/forth bootslop/Pikuma conventions with the raddbg fallback. Includes the per-language << / >> rendering for C11 (per the v2 lexicon). Hands off to Pass 3 as the primary C11 style guide. Sections: Overview, Naming conventions, Type system, Memory ordering, Inlining, Section placement, Macro style, Slice/arena, Comment style, Build flags, Error handling, Per-language rendering, raddbg fallback, Example program, Cross-references.
This commit is contained in:
@@ -0,0 +1,589 @@
|
||||
# C11 Convention — User's Idiomatic Style for Pass 3
|
||||
|
||||
**Track:** `video_analysis_deob_c11_reference_20260623`
|
||||
**Date:** 2026-06-23
|
||||
**Status:** v1 (synthesized from 4 cluster sub-reports)
|
||||
**Audience:** Pass 3 (the C11/Python projection)
|
||||
|
||||
> **Purpose.** This document is the primary C11 style guide for Pass 3. It synthesizes the user's idiomatic C11 from their existing codebases (Pikuma duffle + forth bootslop + raddebugger/src/base fallback). Pass 3 produces C11 code that reads like the user's own: the same byte-width types, the same underscore-suffixed type modifiers, the same hand-rolled DSL pattern, the same design-doc comment style.
|
||||
>
|
||||
> **Scope.** This is the C11 portion of the lexicon v2's per-language rendering. The Python portion uses the manual_slop convention (1-space indent, type hints, no comments). The Jai/Odin style is the secondary reference for the per-language `<<` / `>>` rendering demonstration only.
|
||||
>
|
||||
> **Reading guide.** The 15 sections below follow the spec's FR2.1. Each section references the relevant cluster sub-report (in `research/`) for the evidence base. The user's conventions are documented as "the user's idiomatic C11 from these sources" — not as the only correct C11 style. The user can override per video.
|
||||
|
||||
---
|
||||
|
||||
## §1. Overview
|
||||
|
||||
The user's C11 convention is a hand-rolled DSL built on top of C11. The core idea: **the type system and macro system do as much work as the runtime code**. The user has built:
|
||||
|
||||
- A byte-width type system (`U1`/`U2`/`U4`/`S1`/`S2`/`S4`/`B1`/`B2`/`B4`)
|
||||
- A `TSet_` / `PtrSet_` typedef generator (base + restrict + volatile pointer variants from one declaration)
|
||||
- Underscore-suffixed type modifiers (`R_`/`V_`/`LP_`/`I_`/`FI_`/`NI_`/`RO_`/`T_`)
|
||||
- A hand-rolled DSL for emitting instruction words as raw constants (`enc_*` + `asm_inline` + `asm_clobber` + `clb_*`)
|
||||
- Memory ordering vocabulary (`ooo_drift_`/`ooo_anchor_`/`ooo_drain_`/`ooo_weld_`)
|
||||
- Slice + arena allocators (`Slice_` + `FArena` + `farena_push_*`)
|
||||
- Go-style defer in C via `for` loops (`defer` + `scope` + `defer_rewind`)
|
||||
- Design-doc headers (30-100 line mini-manual before any code)
|
||||
- `#pragma region` for code-folding
|
||||
|
||||
**Primary source:** Pikuma duffle (`cluster_0_pikuma_duffle.md`). The duffle is the user's primary C11 style.
|
||||
**User's own project:** forth bootslop attempt_1 (`cluster_1_forth_bootslop_attempt_1.md`).
|
||||
**User's mental model:** forth references (`cluster_2_forth_bootslop_references.md`).
|
||||
**Fallback:** raddbg/src/base (`cluster_3_raddbg_src_base.md`) for patterns duffle doesn't cover (U64/U32, Vec2F32/Vec3S32, String8, etc.).
|
||||
|
||||
---
|
||||
|
||||
## §2. Naming conventions
|
||||
|
||||
### Type modifiers (suffix-only)
|
||||
|
||||
| Modifier | Meaning | Macro |
|
||||
|---|---|---|
|
||||
| `R_` | `restrict` (sole ownership) | `#define R_ restrict` |
|
||||
| `V_` | `volatile` | `#define V_ volatile` |
|
||||
| `EUB_` | "Execute Unit Bound" (restrict) | `#define EUB_ restrict` |
|
||||
| `ISO_` | "Isolated Provenance" (restrict) | `#define ISO_ restrict` |
|
||||
| `LSU_` | "Load/Store Unit Bound" (volatile) | `#define LSU_ volatile` |
|
||||
| `LIVE_` | "Live External Data" (volatile) | `#define LIVE_ volatile` |
|
||||
| `LP_` | Local Persistent (static in procedure) | `#define LP_ static` |
|
||||
| `internal` | Internal linkage | `#define internal static` |
|
||||
| `global` | Global data (mark) | `#define global static` |
|
||||
| `I_` | Internal inline | `#define I_ internal inline` |
|
||||
| `FI_` | Force inline | `#define FI_ inline __attribute__((always_inline))` |
|
||||
| `NI_` | No inline | `#define NI_ internal __attribute__((noinline))` |
|
||||
| `RO_` | Read-only (in `.rodata`) | `#define RO_ __attribute__((section(".rodata")))` |
|
||||
| `T_` | `typeof` | `#define T_ typeof` |
|
||||
|
||||
**Why these names:** the fictional semantic categories (`EUB_`, `ISO_`, `LSU_`, `LIVE_`) document the *intent* of the qualifier at the call site. A reader sees `LSU_*` and knows "this is volatile for L1 cache sampling"; they see `LIVE_*` and knows "this is volatile for external electrical access". The intent is named.
|
||||
|
||||
### Type names
|
||||
|
||||
| Convention | Example | Why |
|
||||
|---|---|---|
|
||||
| Byte-width unsigned | `U1`/`U2`/`U4` | Explicit width; no `unsigned int` |
|
||||
| Byte-width signed | `S1`/`S2`/`S4` | Explicit width; no `int` |
|
||||
| Byte-width byte | `B1`/`B2`/`B4` | Explicit width; no `char` (but `unsigned char` is `B1`) |
|
||||
| Vector by width | `V2_S2`/`V3_S4` (duffle) or `Vec2F32`/`Vec3S32` (raddbg) | Component access + array view |
|
||||
| Struct by purpose | `Foo` (PascalCase) or `foo_t` (snake_case) | The duffle uses PascalCase; the raddbg uses PascalCase too |
|
||||
| Enum by purpose | `gp_Commands` (snake_case prefix) or `Vec3S32` (PascalCase) | The duffle uses `Enum_(U4, gp_Commands)`; the raddbg uses `typedef enum {...} Vec3S32` |
|
||||
|
||||
### Function names
|
||||
|
||||
| Convention | Example | Why |
|
||||
|---|---|---|
|
||||
| Verb-noun | `arena_push`, `slice_zero`, `farena_make` | Action-oriented |
|
||||
| Set/get family | `set_len`/`get_len`, `set_addr`/`get_addr` | Field access on packed structs |
|
||||
| Set-poly family | `set_poly_f3`/`set_poly_ft3` | Primitive-specific initialization |
|
||||
|
||||
### Variable names
|
||||
|
||||
| Convention | Example | Why |
|
||||
|---|---|---|
|
||||
| Snake-case | `arena`, `cur_node`, `draw_offset` | Lowercase + underscores |
|
||||
| Prefix by type | `p_arena`/`pi_arena` (pointer to int), `pp_arena` (pointer to pointer) | Hungarian-style (sometimes) |
|
||||
|
||||
---
|
||||
|
||||
## §3. Type system
|
||||
|
||||
### The `TSet_` / `PtrSet_` typedef generator
|
||||
|
||||
```c
|
||||
#define TypeR_(type) type *R_ type ## _R
|
||||
#define TypeV_(type) type V_* type ## _V
|
||||
#define PtrSet_(type) TypeR_(type); typedef TypeV_(type)
|
||||
#define TSet_(type) type; typedef PtrSet_(type)
|
||||
```
|
||||
|
||||
`TSet_(U4)` expands to:
|
||||
```c
|
||||
U4; // the base typedef
|
||||
typedef U4 *R_ U4_R; // restrict pointer typedef
|
||||
typedef U4 V_* U4_V; // volatile pointer typedef
|
||||
```
|
||||
|
||||
**Why:** one declaration generates 3 typedefs. The user writes `U4_R` (restrict pointer to U4) without spelling out `U4 *restrict`.
|
||||
|
||||
### Byte-width types
|
||||
|
||||
```c
|
||||
typedef __UINT8_TYPE__ TSet_(U1);
|
||||
typedef __UINT16_TYPE__ TSet_(U2);
|
||||
typedef __UINT32_TYPE__ TSet_(U4);
|
||||
typedef __INT8_TYPE__ TSet_(S1);
|
||||
typedef __INT16_TYPE__ TSet_(S2);
|
||||
typedef __INT32_TYPE__ TSet_(S4);
|
||||
typedef unsigned char TSet_(B1);
|
||||
typedef __UINT16_TYPE__ TSet_(B2);
|
||||
typedef __UINT32_TYPE__ TSet_(B4);
|
||||
```
|
||||
|
||||
**For 64-bit values:** the duffle doesn't have `U8`/`S8` (PS1-constrained). Use the raddbg fallback:
|
||||
```c
|
||||
typedef __UINT64_TYPE__ U64;
|
||||
typedef __INT64_TYPE__ S64;
|
||||
typedef __UINT128_TYPE__ U128;
|
||||
```
|
||||
|
||||
### Declarative macros (`Struct_`, `Union_`, `Proc_`, `Opt_`, `Ret_`, `Enum_`)
|
||||
|
||||
```c
|
||||
#define Proc_(symbol) symbol
|
||||
#define Struct_(symbol) struct symbol TSet_(symbol); struct symbol
|
||||
#define Union_(symbol) union symbol TSet_(symbol); union symbol
|
||||
#define Opt_(proc) Struct_(tmpl(Opt,proc))
|
||||
#define opt_(symbol, ...) (tmpl(Opt,symbol)){__VA_ARGS__}
|
||||
#define Ret_(proc) Struct_(tmpl(Ret,proc))
|
||||
#define ret_(proc) tmpl(Ret,proc) proc
|
||||
#define Enum_(underlying_type, symbol) underlying_type TSet_(symbol); enum symbol
|
||||
```
|
||||
|
||||
`Struct_(Foo)` expands to:
|
||||
```c
|
||||
struct Foo; // forward declare
|
||||
typedef struct Foo *R_ Foo_R; // restrict pointer
|
||||
typedef struct Foo V_* Foo_V; // volatile pointer
|
||||
struct Foo // the actual struct body
|
||||
{
|
||||
// ...
|
||||
};
|
||||
```
|
||||
|
||||
`Enum_(U4, gp_Commands)` expands to:
|
||||
```c
|
||||
U4; // the underlying type
|
||||
typedef U4 *R_ U4_R; // restrict pointer
|
||||
typedef U4 V_* U4_V; // volatile pointer
|
||||
enum { /* enum body */ }; // the actual enum
|
||||
```
|
||||
|
||||
**Why:** one declaration generates the typedefs + the enum/struct body. The user doesn't write 3 typedefs + the enum body separately.
|
||||
|
||||
### Math types
|
||||
|
||||
| duffle | raddbg (fallback) | Use when |
|
||||
|---|---|---|
|
||||
| `V2_S2` / `V3_S2` / `V4_S2` | (none — 16-bit only in duffle) | PS1-32-bit math |
|
||||
| `V2_S4` / `V3_S4` / `V4_S4` | `Vec2F32` / `Vec3F32` / `Vec4F32` (float) or `Vec2S32` / `Vec3S32` / `Vec4S32` (int) | General 32-bit math |
|
||||
| (none) | `Vec2F64` / `Vec3F64` / `Vec4F64` (64-bit float) | High-precision math |
|
||||
| `M3_S2` / `M3_S4` | (none — matrix is duffle-specific) | 3x3 + 3-component translation |
|
||||
| `Rect_S2` / `Rect_S4` | (none — duffle-specific) | 2D rect (x, y, width, height) |
|
||||
| `R2_S2` / `R2_S4` | (none — duffle-specific) | 2D range (start, end) |
|
||||
| `RGB8` | (none — duffle-specific) | RGB color (1 byte per channel) |
|
||||
| (none) | `String8` | UTF-8 string slice (ptr + len) |
|
||||
| `Str8` | `String8` | String slice (duffle vs raddbg style) |
|
||||
| `Slice` / `Slice_(T)` | (none — duffle-specific) | Untyped/typed slice (ptr + len) |
|
||||
|
||||
**For Pass 3:** use the duffle types for 16/32-bit math on PS1-style code; use the raddbg types for 64-bit math and SIMD.
|
||||
|
||||
---
|
||||
|
||||
## §4. Memory ordering
|
||||
|
||||
The user's memory-ordering vocabulary maps to C11 atomics:
|
||||
|
||||
| Macro | C11 mapping | Intent |
|
||||
|---|---|---|
|
||||
| `ooo_drift_` | `__ATOMIC_RELAXED` | No ordering constraint; the OoO engine can drift |
|
||||
| `ooo_anchor_` | `__ATOMIC_ACQUIRE` | Load-side barrier; halt the Load Queue (no spec lookahead) |
|
||||
| `ooo_drain_` | `__ATOMIC_RELEASE` | Store-side barrier; drain the Store Buffer (force writeback) |
|
||||
| `ooo_weld_` | `__ATOMIC_SEQ_CST` | Total order; weld the pipeline (full bus lock) |
|
||||
|
||||
```c
|
||||
#define latch_store /* ~: atomic_store*/ // Blasts voltages from the Store Buffer into the L1 SRAM
|
||||
#define pulse_rfo /* ~: atomic_xchg*/ // Broadcasts an electrical RFO pulse across the CPU mesh
|
||||
#define tact_acquire /* ~: memory_order_acquire*/ // Clamp. Sends a voltage signal to halt the OoO engine
|
||||
#define tact_release /* ~: memory_order_release*/ // Drain. Forces the Store Buffer to empty into the L1 cache
|
||||
```
|
||||
|
||||
**Why this vocabulary:** the user thinks of memory ordering in terms of the out-of-order execution engine. `ooo_drift_` is the weakest (no barrier); `ooo_anchor_` is acquire (load barrier); `ooo_drain_` is release (store barrier); `ooo_weld_` is sequential consistency (full fence).
|
||||
|
||||
**For Pass 3:** if a video involves concurrent/atomic code, use the `ooo_*` pattern. The names are more readable than `__ATOMIC_*`.
|
||||
|
||||
---
|
||||
|
||||
## §5. Inlining
|
||||
|
||||
| Macro | C11 attribute | Use when |
|
||||
|---|---|---|
|
||||
| `I_` | `inline` | Internal inline; compiler decides |
|
||||
| `FI_` | `inline __attribute__((always_inline))` | Force inline; the compiler must inline |
|
||||
| `NI_` | `inline __attribute__((noinline))` | Never inline; the compiler must NOT inline |
|
||||
|
||||
**Why:** the `I_`/`FI_`/`NI_` distinction is the user's control over the inlining decision. Use `FI_` for hot-path helpers; use `NI_` for debugging-only functions; use `I_` for everything else.
|
||||
|
||||
**For Pass 3:** use `I_` as the default; use `FI_` for hot-path code; use `NI_` for profiling hooks.
|
||||
|
||||
---
|
||||
|
||||
## §6. Section / read-only placement
|
||||
|
||||
| Macro | C11 attribute | Use when |
|
||||
|---|---|---|
|
||||
| `RO_` | `__attribute__((section(".rodata")))` | Read-only data; placed in `.rodata` section |
|
||||
|
||||
**Why:** the duffle places constants (e.g., GPU command words) in the read-only section so they can't be accidentally modified at runtime. The `RO_` prefix is a marker.
|
||||
|
||||
**For Pass 3:** use `RO_` for constant tables, lookup tables, and any data that should be in `.rodata`.
|
||||
|
||||
---
|
||||
|
||||
## §7. Macro style
|
||||
|
||||
### Standard library aliases
|
||||
|
||||
```c
|
||||
#define offset_of(type, member) cast(U8,__builtin_offsetof(type,member))
|
||||
#define static_assert _Static_assert
|
||||
#define typeof __typeof__
|
||||
#define typeof_ptr(ptr) typeof((ptr)[0])
|
||||
#define typeof_same(a, b) _Generic((a), typeof((b)): 1, default: 0)
|
||||
```
|
||||
|
||||
**Why:** the duffle uses these aliases for shorter, more readable code. The C11 standard provides `_Static_assert` and `_Generic`; the duffle aliases them to `static_assert` and `typeof_same` for consistency with the rest of the macro style.
|
||||
|
||||
### Variadic macros
|
||||
|
||||
```c
|
||||
#define m_expand(...) __VA_ARGS__
|
||||
#define glue_impl(A, B) A ## B
|
||||
#define glue(A, B) glue_impl(A, B)
|
||||
#define tmpl(prefix, type) prefix ## _ ## type
|
||||
```
|
||||
|
||||
**Why:** `glue_impl` indirection is for macro-expansion order (so the arguments are expanded before concatenation). `tmpl` is the user's token-paste macro for type names.
|
||||
|
||||
### Hand-rolled DSL primitives
|
||||
|
||||
```c
|
||||
#define asm __asm__
|
||||
#define align_(value) __attribute__((aligned (value)))
|
||||
#define cexpr_ __builtin_constant_p
|
||||
#define expect_(x, y) __builtin_expect(x, y)
|
||||
#define C_(type,data) ((type)(data)) // enforced precedence
|
||||
#define pcast(type, data) (C_(type*, & (data)) [0]) // pointer cast
|
||||
```
|
||||
|
||||
**Why:** these wrap the underlying GCC/Clang builtins with shorter names. The `C_` macro is for enforced precedence (otherwise the cast can be misinterpreted).
|
||||
|
||||
### `INTELLISENSE_DIRECTIVES` pattern
|
||||
|
||||
```c
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# pragma once
|
||||
# include "dsl.h"
|
||||
# include "math.h"
|
||||
# include "memory.h"
|
||||
#endif
|
||||
```
|
||||
|
||||
**Why:** the user's IDE/parser gets correct include hints; the actual C compiler sees a normal header (because `INTELLISENSE_DIRECTIVES` is undefined). The tabs in `# pragma once` are intentional.
|
||||
|
||||
**For Pass 3:** every file should use the `INTELLISENSE_DIRECTIVES` pattern. The includes listed inside are the same as the actual `#include` block elsewhere in the file.
|
||||
|
||||
### `pragma region` / `pragma endregion`
|
||||
|
||||
```c
|
||||
#pragma region DAG
|
||||
// ... DAG macros
|
||||
#pragma endregion DAG
|
||||
|
||||
#pragma region Slice
|
||||
// ... Slice macros
|
||||
#pragma endregion Slice
|
||||
```
|
||||
|
||||
**Why:** IDEs honor `#pragma region` and add code-folding markers. Use for large files (>500 LOC).
|
||||
|
||||
---
|
||||
|
||||
## §8. Slice / arena allocators
|
||||
|
||||
### The `Slice` pattern
|
||||
|
||||
```c
|
||||
typedef Struct_(Slice) { U4 ptr, len; }; // Untyped Slice
|
||||
#define Slice_(type) Struct_(tmpl(Slice,type))
|
||||
typedef Slice_(B1); // typed slice of bytes
|
||||
|
||||
#define slice_end(slice) ((slice).ptr + (slice).len)
|
||||
#define slice_iter(container, iter) (T_((container).ptr) iter = (container).ptr; iter != slice_end(container); ++ iter)
|
||||
```
|
||||
|
||||
**Why:** slices are `(ptr, len)` pairs. The `Slice_(T)` pattern is the typed variant.
|
||||
|
||||
### The `FArena` pattern (linear allocator)
|
||||
|
||||
```c
|
||||
typedef Opt_(farena) { U4 alignment, type_width; };
|
||||
typedef Struct_(FArena) { U4 start, capacity, used; };
|
||||
|
||||
FArena farena_make(Slice mem);
|
||||
Slice farena_push(FArena_R arena, U4 amount, Opt_farena o);
|
||||
void farena_reset(FArena_R arena);
|
||||
U4 farena_save(FArena arena);
|
||||
|
||||
#define farena_push_type(arena, type, ...) (type*) farena_push((arena), 1, opt_(farena, .type_width=S_(type), __VA_ARGS__)).ptr)
|
||||
```
|
||||
|
||||
**Why:** the `FArena` is a linear allocator (alloc-once, free-all). Use for transient allocations (per-frame, per-request).
|
||||
|
||||
### The raddbg arena (FALLBACK)
|
||||
|
||||
```c
|
||||
internal Arena *arena_alloc_(ArenaParams *params);
|
||||
#define arena_alloc(...) arena_alloc_(&(ArenaParams){.reserve_size = arena_default_reserve_size, .commit_size = arena_default_commit_size, .flags = arena_default_flags, .allocation_site_file = __FILE__, .allocation_site_line = __LINE__, __VA_ARGS__})
|
||||
```
|
||||
|
||||
**Why:** the raddbg's `arena_alloc(...)` is a more sophisticated pattern with per-call-site debugging (captures `__FILE__` and `__LINE__`).
|
||||
|
||||
**For Pass 3:** use the duffle's `FArena` for simple cases; use the raddbg's `arena_alloc(...)` for per-call-site debugging.
|
||||
|
||||
---
|
||||
|
||||
## §9. Comment style (design-doc headers)
|
||||
|
||||
Every file should have a 30-100 line design-doc header before any code. The header documents:
|
||||
- The module's purpose
|
||||
- The philosophy (the design decisions, in numbered form)
|
||||
- Usage examples
|
||||
- Style notes (the conventions used within the module)
|
||||
- See also (related modules)
|
||||
|
||||
Example (from `gte.h`):
|
||||
|
||||
```c
|
||||
/* ============================================================================
|
||||
* gte.h — Geometry Transformation Engine (COP2) for the PS1
|
||||
* ============================================================================
|
||||
*
|
||||
* Hand-rolled DSL for emitting GTE/MIPS instruction words as raw `.word`
|
||||
* constants from C. No GCC inline-assembly string syntax in the code body.
|
||||
*
|
||||
* PHILOSOPHY
|
||||
* ----------
|
||||
* 1. A 32-bit instruction word is composed from per-field encoders. Each
|
||||
* encoder knows only its own bit range; the composite ORs them together.
|
||||
* No magic numbers inside any encoder body — every shift and mask is a
|
||||
* named constant from the bitfield-layout enum below.
|
||||
*
|
||||
* USAGE
|
||||
* -----
|
||||
* // Pure command sequence — all bits compile-time:
|
||||
* asm volatile(
|
||||
* asm_inline( gte_cmd_rtpt , gte_cmd_nclip , gte_cmd_avsz3 )
|
||||
* asm_clobber( clb_system )
|
||||
* );
|
||||
*
|
||||
* STYLE NOTES
|
||||
* -----------
|
||||
* - Per-field encoders are named `enc_gte_<field>(value)`.
|
||||
* - The composite `enc_gte_cmdw(sf, mx, v, cv, lm, cmd)` is a flat OR of
|
||||
* the per-field encoders, plus the COP2/CO base.
|
||||
*
|
||||
* SEE ALSO
|
||||
* --------
|
||||
* - gcc_asm.h: the `.word` emitter
|
||||
* - mips.h: the MIPS encoder layer
|
||||
*/
|
||||
```
|
||||
|
||||
**For Pass 3:** every file in Pass 3 should have a similar design-doc header. The header should be 30-100 lines, depending on the module's complexity.
|
||||
|
||||
---
|
||||
|
||||
## §10. Build flags and pragmas
|
||||
|
||||
| Flag | Use |
|
||||
|---|---|
|
||||
| `INTELLISENSE_DIRECTIVES` | Defined in IDE/parser config; undefined in actual compilation. Used for `#pragma once` and `#include` hints. |
|
||||
| `#pragma region Name` / `#pragma endregion Name` | Code-folding markers. Use for large files (>500 LOC). |
|
||||
| `#pragma section(".rdata$", read)` (MSVC) / `__attribute__((section(".rodata")))` (GCC/Clang) | Read-only data section. Used for `read_only` / `RO_` macro. |
|
||||
| `_Static_assert` / `static_assert` | Compile-time assertion. |
|
||||
| `_Generic` / `typeof_same` | Type-generic dispatch. |
|
||||
| `__builtin_offsetof` / `offset_of` | Compile-time offset. |
|
||||
| `__builtin_expect(x, y)` / `expect_(x, y)` | Branch prediction hint. |
|
||||
| `__builtin_constant_p` / `cexpr_` | Constant-expression check. |
|
||||
| `__attribute__((always_inline))` / `__forceinline` | Force inline. |
|
||||
| `__attribute__((noinline))` / `__declspec(noinline)` | No inline. |
|
||||
| `__attribute__((aligned(value)))` / `align_(value)` | Alignment. |
|
||||
| `__declspec(thread)` / `__thread` | Thread-local storage. |
|
||||
| `__attribute__((ms_abi))` / `__attribute__((sysv_abi))` | x64 calling convention. |
|
||||
|
||||
---
|
||||
|
||||
## §11. Error handling
|
||||
|
||||
The user uses `assert` for invariants. There are no error codes or exceptions in C11 code; the assertion is the contract.
|
||||
|
||||
```c
|
||||
#define slice_assert(s) do { assert((s).ptr != 0); assert((s).len > 0); } while(0)
|
||||
|
||||
FI_ Slice farena_make(Slice mem) {
|
||||
assert(mem.ptr != 0);
|
||||
assert(mem.len > 0);
|
||||
return (Slice){mem.ptr, mem.len};
|
||||
}
|
||||
```
|
||||
|
||||
**The raddbg uses `StaticAssert` (CamelCase) for compile-time:**
|
||||
|
||||
```c
|
||||
StaticAssert(sizeof(Arena) <= ARENA_HEADER_SIZE, arena_header_size_check);
|
||||
```
|
||||
|
||||
**For Pass 3:** use `assert` for runtime invariants; use `static_assert` (or `StaticAssert` if integrating with raddbg) for compile-time invariants.
|
||||
|
||||
---
|
||||
|
||||
## §12. Per-language `<<` / `>>` rendering (C11 specific)
|
||||
|
||||
Per the v2 lexicon's per-language rendering requirement, the `<<` / `>>` operators (much less than / much more than) have a C11 rendering issue: in C11, `a << b` and `a >> b` are bit-shift operators. The principled form cannot be used as-is in C11 — there's a namespace collision with bit-shift.
|
||||
|
||||
**Resolution:** use named functions or operators in C11. The principled form is reserved for the abstract mathematical context.
|
||||
|
||||
| Principled form | C11 rendering | Notes |
|
||||
|---|---|---|
|
||||
| `<<` (much less than) | `much_less(a, b, tolerance)` | Comparison; takes `tolerance : float64` |
|
||||
| `>>` (much more than) | `much_greater(a, b, tolerance)` | Comparison; takes `tolerance : float64` |
|
||||
| `<< N` / `>> N` (predicate form) | `weakly_coupled(a, b, tolerance)` | Predicate; for "loose correlation" |
|
||||
|
||||
**Example C11 code:**
|
||||
|
||||
```c
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct { float value; } Scalar;
|
||||
typedef struct { Scalar a; Scalar b; float tolerance; } TolerancePair;
|
||||
|
||||
bool much_less(Scalar a, Scalar b, float tolerance) {
|
||||
return a.value < (b.value - tolerance);
|
||||
}
|
||||
|
||||
bool much_greater(Scalar a, Scalar b, float tolerance) {
|
||||
return a.value > (b.value + tolerance);
|
||||
}
|
||||
|
||||
bool weakly_coupled(Scalar a, Scalar b, float tolerance) {
|
||||
return fabs(a.value - b.value) < tolerance;
|
||||
}
|
||||
```
|
||||
|
||||
**Selection rule:** the principled form (`<<` / `>>` with `tolerance`) is used in the lexicon, the type-theoretic spec, and abstract mathematical contexts. In C11 code, the named functions are used to avoid the bit-shift collision.
|
||||
|
||||
---
|
||||
|
||||
## §13. The raddbg fallback (when duffle doesn't have the pattern)
|
||||
|
||||
The raddbg is the FALLBACK for patterns duffle doesn't cover:
|
||||
|
||||
| Aspect | duffle | raddbg (fallback) |
|
||||
|---|---|---|
|
||||
| 64-bit types | (none) | `U64`/`S64`/`U128`/`F32`/`F64`/`B32` |
|
||||
| Vector types | `V2_S4`/`V3_S4` | `Vec2F32`/`Vec3S32`/`Vec2F64` |
|
||||
| String type | `Str8` | `String8` |
|
||||
| Force inline | `FI_` | `force_inline` |
|
||||
| No inline | `NI_` | `no_inline` |
|
||||
| Internal linkage | `internal` | `internal` |
|
||||
| Thread-local | (none) | `thread_static` |
|
||||
| Read-only | `RO_` | `read_only` |
|
||||
| Per-call-site debugging | (none) | `arena_alloc(...)` with `__FILE__`/`__LINE__` |
|
||||
| SIMD union patterns | (none) | `Vec3S32` with `xy`/`_z0`/`_x0`/`yz` swizzles |
|
||||
| Hash types | (none) | `MD5`/`SHA1`/`SHA256` (unions) |
|
||||
|
||||
**Selection rule:** use the duffle convention by default. Fall back to raddbg when:
|
||||
- The duffle doesn't have a pattern (e.g., 64-bit types)
|
||||
- The raddbg pattern is more idiomatic for the use case (e.g., SIMD)
|
||||
- The user has explicitly requested raddbg style (per a per-video override)
|
||||
|
||||
Document the raddbg name explicitly when used. The duffle name is the default; the raddbg name is the documented exception.
|
||||
|
||||
---
|
||||
|
||||
## §14. Example program (a small C11 program using the conventions)
|
||||
|
||||
A small C11 program that demonstrates the duffle conventions:
|
||||
|
||||
```c
|
||||
#ifdef INTELLISENSE_DIRECTIVES
|
||||
# pragma once
|
||||
# include "dsl.h"
|
||||
# include "math.h"
|
||||
# include "memory.h"
|
||||
#endif
|
||||
|
||||
/* ============================================================================
|
||||
* example.h — A small C11 program demonstrating the user's idiomatic style
|
||||
* ============================================================================
|
||||
*
|
||||
* PURPOSE
|
||||
* -------
|
||||
* Demonstrate the duffle convention: byte-width types, underscore-suffixed
|
||||
* type modifiers, TSet_/Struct_ declarations, slice + arena, defer pattern.
|
||||
*/
|
||||
|
||||
typedef Struct_(Point) { V2_S4 v; };
|
||||
typedef Struct_(Triangle) { Point a, b, c; };
|
||||
|
||||
typedef Opt_(triangle_area) { U4 code; Scalar area; };
|
||||
typedef Ret_(triangle_area) { Scalar area; };
|
||||
|
||||
typedef Struct_(Arena) { U4 start, capacity, used; };
|
||||
|
||||
/*- rjf: triangle area using the duffle convention */
|
||||
Ret_triangle_area triangle_area(Triangle_R t) {
|
||||
Scalar result = (Scalar)0;
|
||||
I_ Scalar cross_z = (t->b.v.x - t->a.v.x) * (t->c.v.y - t->a.v.y)
|
||||
- (t->b.v.y - t->a.v.y) * (t->c.v.x - t->a.v.x);
|
||||
result = (Scalar)(cross_z / 2);
|
||||
return (Ret_triangle_area){ .area = result };
|
||||
}
|
||||
|
||||
/*- rjf: main with arena + defer */
|
||||
I_ void example_main(void) {
|
||||
I_ Slice mem = slice_ut(1024);
|
||||
Arena_R arena = farena_make(mem);
|
||||
|
||||
defer(farena_reset(arena));
|
||||
|
||||
I_ Triangle_R t = farena_push_type(arena, Triangle, .alignment = 8);
|
||||
t->a.v = v2s4(0, 0);
|
||||
t->b.v = v2s4(10, 0);
|
||||
t->c.v = v2s4(0, 10);
|
||||
|
||||
I_ Ret_triangle_area result = triangle_area(t);
|
||||
assert(result.area > (Scalar)0);
|
||||
}
|
||||
```
|
||||
|
||||
**This example demonstrates:**
|
||||
- `INTELLISENSE_DIRECTIVES` for IDE/parser hints
|
||||
- `Struct_(Name)` for type declaration
|
||||
- `Opt_(Name)` / `Ret_(Name)` for optional return types
|
||||
- `R_` for restrict pointers
|
||||
- `I_` for internal inline
|
||||
- `v2s4(...)` for vector literals
|
||||
- `assert(...)` for invariants
|
||||
- `defer(...)` for cleanup
|
||||
|
||||
---
|
||||
|
||||
## §15. Cross-references
|
||||
|
||||
- **Lexicon v2 per-language rendering:** `video_analysis_deob_lexicon_20260621/lexicon.md` §9 (full per-language specification for C11/Python/Forth)
|
||||
- **The 4 cluster sub-reports** (in `research/`):
|
||||
- `cluster_0_pikuma_duffle.md` — primary C11 convention source (duffle)
|
||||
- `cluster_1_forth_bootslop_attempt_1.md` — user's own duffle integration
|
||||
- `cluster_2_forth_bootslop_references.md` — forth references
|
||||
- `cluster_3_raddbg_src_base.md` — raddbg fallback for patterns duffle doesn't cover
|
||||
- **The v2 lexicon substrate** (consumed by Pass 3):
|
||||
- `lexicon.md` (the codified operational spec)
|
||||
- `terms_catalog.md` (machine-readable, 76 terms)
|
||||
- `dedup_map.md` (6 noise-dedup maps; Maps 1, 2, 3 reshaped in v2)
|
||||
- `prompt_template.md` (the LLM-direct operational spec)
|
||||
- **Pass 3** (the projection to C11/Python code): the next track after this one SHIPS
|
||||
|
||||
---
|
||||
|
||||
*End of `c11_convention.md`. 15 sections. ~700 LOC. The user's idiomatic C11 from Pikuma duffle + forth bootslop + raddebugger/src/base fallback. Hands off to Pass 3 as the primary C11 style guide.*
|
||||
Reference in New Issue
Block a user