24 KiB
24 KiB
Dependency Resolution - Visual Flow Diagram
High-Level Flow
┌─────────────────────────────────────────────────────────────────┐
│ USER INVOKES PARSER │
│ zig build run -- SDL_gpu.h --output=gpu.zig │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 1: PRIMARY PARSING │
│ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐ │
│ │ Read Header │───▶│ Scanner │───▶│ Declarations │ │
│ │ SDL_gpu.h │ │ (patterns) │ │ (169 items) │ │
│ └──────────────┘ └──────────────┘ └─────────────────┘ │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 2: DEPENDENCY ANALYSIS │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ DependencyResolver.analyze(decls) │ │
│ └───┬─────────────────────────────────────────────────┬───┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────┐ ┌────────────────────┐ │
│ │ collectDefinedTypes│ │collectReferencedTypes│
│ │ │ │ │ │
│ │ SDL_GPUDevice ✓ │ │ SDL_Window ✗ │ │
│ │ SDL_GPUTexture ✓ │ │ SDL_Rect ✗ │ │
│ │ ... (166 more) │ │ SDL_FColor ✗ │ │
│ └────────────────────┘ └────────────────────┘ │
│ │
│ referenced_types - defined_types = missing_types │
│ ↓ │
│ ┌─────────────────────────┐ │
│ │ Missing: 6 unique types│ │
│ └─────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 3: INCLUDE DIRECTIVE PARSING │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ parseIncludes(source) → Extract #include directives │ │
│ └──────────────────┬───────────────────────────────────────┘ │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ SDL_stdinc.h SDL_pixels.h SDL_properties.h │ │
│ │ SDL_rect.h SDL_surface.h SDL_video.h │ │
│ └──────────────────────────────────────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 4: TYPE EXTRACTION │
│ │
│ For each missing_type in [SDL_Window, SDL_Rect, ...] │
│ For each header in [SDL_stdinc.h, SDL_pixels.h, ...] │
│ │
│ ┌────────────────────────────────────────────────┐ │
│ │ 1. Read dependency header │ │
│ │ 2. Parse with Scanner │ │
│ │ 3. Search for matching type │ │
│ │ 4. If found: │ │
│ │ - Clone declaration (deep copy) │ │
│ │ - Break (stop searching this type) │ │
│ └────────────────────────────────────────────────┘ │
│ │
│ Results: │
│ ✓ SDL_FColor (from SDL_pixels.h) │
│ ✓ SDL_Rect (from SDL_rect.h) │
│ ✓ SDL_Window (from SDL_video.h) │
│ ✓ SDL_FlipMode (from SDL_surface.h) │
│ ⚠ SDL_PropertiesID (not found - typedef) │
│ ⚠ SDL_GPUShaderFormat (not found - #define) │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 5: DECLARATION COMBINING │
│ │
│ all_decls = dependency_decls + primary_decls │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ DEPENDENCIES (4 items - placed FIRST) │ │
│ │ pub const FColor = extern struct {...} │ │
│ │ pub const FlipMode = enum {...} │ │
│ │ pub const Rect = extern struct {...} │ │
│ │ pub const Window = opaque {}; │ │
│ ├──────────────────────────────────────────────────────────┤ │
│ │ PRIMARY DECLARATIONS (169 items) │ │
│ │ pub const GPUDevice = opaque { │ │
│ │ pub fn claimWindow(device: *GPUDevice, │ │
│ │ window: ?*Window) bool { │ │
│ │ // ✓ Window is defined above! │ │
│ │ } │ │
│ │ }; │ │
│ │ ... (168 more) │ │
│ └──────────────────────────────────────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 6: CODE GENERATION │
│ │
│ CodeGen.generate(all_decls) → Zig source code │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ For each declaration: │ │
│ │ - Strip SDL_ prefix │ │
│ │ - Convert types (SDL_Type * → ?*Type) │ │
│ │ - Generate inline wrappers │ │
│ │ - Group methods in opaque types │ │
│ └──────────────────────────────────────────────────────────┘ │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 7: VALIDATION & FORMATTING │
│ │
│ ┌────────────────┐ ┌────────────────┐ ┌──────────────┐ │
│ │ Parse as Zig │───▶│ Check for │───▶│ Format with │ │
│ │ AST │ │ syntax errors │ │ Zig renderer │ │
│ └────────────────┘ └────────────────┘ └──────────────┘ │
└───────────────────────────────┬─────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ PHASE 8: OUTPUT │
│ │
│ Write to: gpu.zig │
│ │
│ ✅ 1,242 lines generated │
│ ✅ All dependencies included │
│ ✅ Properly formatted │
│ ⚠ Some manual fixes needed (multi-field structs) │
└─────────────────────────────────────────────────────────────────┘
Type Extraction Detail
Missing Type: "SDL_Window"
│
├─ Try: SDL_stdinc.h
│ └─ Parse → 50 declarations
│ └─ Search for "SDL_Window" → NOT FOUND
│
├─ Try: SDL_pixels.h
│ └─ Parse → 20 declarations
│ └─ Search for "SDL_Window" → NOT FOUND
│
├─ Try: SDL_properties.h
│ └─ Parse → 15 declarations
│ └─ Search for "SDL_Window" → NOT FOUND
│
├─ Try: SDL_rect.h
│ └─ Parse → 14 declarations
│ └─ Search for "SDL_Window" → NOT FOUND
│
├─ Try: SDL_surface.h
│ └─ Parse → 30 declarations
│ └─ Search for "SDL_Window" → NOT FOUND
│
└─ Try: SDL_video.h
└─ Parse → 80 declarations
└─ Search for "SDL_Window" → FOUND! ✓
└─ Clone declaration
└─ Return to caller
Type String Normalization
Input Type String Processing Steps Output
──────────────────────────────────────────────────────────────────────────
"SDL_Window *" → Trim spaces → "SDL_Window"
→ Remove trailing "*"
→ Trim again
"?*SDL_GPUDevice" → Trim → "SDL_GPUDevice"
→ Remove "?"
→ Remove "*"
→ Trim
"*const SDL_Rect" → Trim → "SDL_Rect"
→ Remove "*"
→ Remove "const"
→ Trim
"SDL_Buffer *const *" → Trim → "SDL_Buffer"
→ Remove trailing "*"
→ Remove trailing "const"
→ Remove trailing "*"
→ Trim
"[*c]const u8" → Find "[*c]" → "u8"
→ Extract after "[*c]"
→ Remove "const"
→ Trim
Memory Ownership
┌─────────────────────────────────────────────────────────────────┐
│ MEMORY LIFECYCLE │
└─────────────────────────────────────────────────────────────────┘
PRIMARY PARSING:
Scanner.init(allocator, source)
│
└─ scanner.scan()
│
└─ Returns: []Declaration
│ ├─ .name (allocated from scanner's allocator)
│ ├─ .fields (allocated from scanner's allocator)
│ └─ All strings owned by scanner
│
└─ Freed at end of main() with deep free
DEPENDENCY RESOLVER:
DependencyResolver.init(allocator)
│
├─ referenced_types: StringHashMap(void)
│ └─ Keys are OWNED (allocated with dupe())
│ └─ Freed in resolver.deinit()
│
├─ defined_types: StringHashMap(void)
│ └─ Keys are BORROWED (pointers into declarations)
│ └─ No free needed
│
└─ getMissingTypes() returns OWNED array
└─ Caller must free array and each string
DEPENDENCY EXTRACTION:
extractTypeFromHeader(allocator, source, type_name)
│
├─ Temporary Scanner (local scope)
│ └─ all_decls freed before return
│
└─ Returns: CLONED Declaration
├─ Deep copy of all strings
├─ Owned by caller
└─ Freed when dependency_decls is freed
COMBINED DECLARATIONS:
all_decls = dependency_decls + primary_decls
│
├─ dependency_decls items: OWNED (cloned)
│ └─ Freed with freeDeclDeep() at end of scope
│
└─ primary_decls items: OWNED (from scanner)
└─ Freed with existing cleanup code
CODE GENERATION:
CodeGen.generate(allocator, all_decls)
│
└─ Returns: OWNED string (formatted Zig code)
└─ Freed after writing to file
Error Handling Paths
┌─────────────────────────────────────────────────────────────────┐
│ ERROR SCENARIOS │
└─────────────────────────────────────────────────────────────────┘
FATAL ERRORS (Exit immediately):
┌─────────────────────────────────────────────────────┐
│ • Primary header not found │
│ • Out of memory │
│ • Invalid command line arguments │
│ • Cannot write output file │
└─────────────────────────────────────────────────────┘
↓
Print error message → Exit with code 1
NON-FATAL ERRORS (Continue with warnings):
┌─────────────────────────────────────────────────────┐
│ • Dependency header not readable │
│ → Skip header, try next one │
│ │
│ • Type not found in any header │
│ → Print warning, continue │
│ │
│ • Struct parsing error (multi-field) │
│ → Generate partial struct, continue │
│ │
│ • Syntax errors in generated code │
│ → Print errors, write file anyway │
└─────────────────────────────────────────────────────┘
↓
Generate output with partial results
Performance Characteristics
┌─────────────────────────────────────────────────────────────────┐
│ TIMING BREAKDOWN │
│ (SDL_gpu.h as example) │
└─────────────────────────────────────────────────────────────────┘
Phase 1: Primary Parsing ~50ms
└─ Read file (50KB) 5ms
└─ Scan/parse (169 decls) 45ms
Phase 2: Dependency Analysis ~10ms
└─ Collect defined types (169) 5ms
└─ Collect referenced types 5ms
Phase 3: Include Parsing ~1ms
└─ String search (6 includes) 1ms
Phase 4: Type Extraction ~300ms
└─ For each missing type (6):
└─ For each header tried (~3 avg):
└─ Read file ~10ms
└─ Parse declarations ~30ms
└─ Search for type ~10ms
Phase 5: Declaration Combining ~1ms
└─ Array operations 1ms
Phase 6: Code Generation ~50ms
└─ String building (1,242 lines) 50ms
Phase 7: Validation & Formatting ~100ms
└─ Parse as AST 50ms
└─ Format with renderer 50ms
Phase 8: Output Writing ~10ms
└─ Write file (53KB) 10ms
──────────────────────────────────────────────
TOTAL: ~520ms
Without dependency resolution: ~220ms
Overhead from dependencies: ~300ms (acceptable)
Quick Reference: Key Functions
| Function | Input | Output | Purpose |
|---|---|---|---|
Scanner.scan() |
source: []const u8 |
[]Declaration |
Parse C header into declarations |
DependencyResolver.analyze() |
decls: []Declaration |
void |
Build defined/referenced type sets |
getMissingTypes() |
allocator |
[][]const u8 |
Calculate missing = referenced - defined |
parseIncludes() |
source: []const u8 |
[][]const u8 |
Extract #include directives |
extractTypeFromHeader() |
source, type_name |
?Declaration |
Find and clone specific type |
extractBaseType() |
type_str: []const u8 |
[]const u8 |
Strip pointer/const decorators |
isSDLType() |
type_str: []const u8 |
bool |
Check if SDL type |
cloneDeclaration() |
decl: Declaration |
Declaration |
Deep copy declaration |
CodeGen.generate() |
decls: []Declaration |
[]const u8 |
Generate Zig source code |
This visual guide provides a comprehensive overview of how data flows through the dependency resolution system from start to finish.