Backlog/lib/sdl3/parser/docs/VISUAL_FLOW.md

366 lines
24 KiB
Markdown

# 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.