366 lines
24 KiB
Markdown
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.
|