6.7 KiB
Dependency Resolution System
The parser automatically detects and resolves type dependencies from SDL headers.
Overview
When parsing a header like SDL_gpu.h, functions often reference types defined in other headers (SDL_Window, SDL_Rect, etc.). The dependency resolver automatically finds and includes these types.
How It Works
Step 1: Detect Missing Types
After parsing the primary header, the system:
- Scans all function signatures and struct fields
- Extracts all referenced type names
- Compares against types defined in the header
- Identifies missing types
Example:
// SDL_gpu.h
extern void SDL_ClaimWindow(SDL_GPUDevice *device, SDL_Window *window);
SDL_GPUDeviceis defined in SDL_gpu.h ✓SDL_Windowis NOT defined in SDL_gpu.h ✗
Result: SDL_Window added to missing types list
Step 2: Parse Include Directives
Extracts #include directives from the header:
#include <SDL3/SDL_stdinc.h>
#include <SDL3/SDL_video.h>
#include <SDL3/SDL_rect.h>
Result: List of headers to search: [SDL_stdinc.h, SDL_video.h, SDL_rect.h]
Step 3: Search for Missing Types
For each missing type:
- Try each included header in order
- Parse the header completely
- Search for matching type definition
- If found, clone the declaration and stop searching
- If not found, continue to next header
Example Search for SDL_Window:
Try SDL_stdinc.h → Not found
Try SDL_video.h → Found! ✓
└─ Extract SDL_Window definition
└─ Stop searching
Step 4: Combine Declarations
final_declarations = [
// Dependencies FIRST (so types are defined before use)
SDL_Window,
SDL_Rect,
SDL_FColor,
// Primary declarations
SDL_GPUDevice,
SDL_GPUTexture,
...
]
Step 5: Generate Unified Output
pub const c = @import("c.zig").c;
// Dependencies (automatically included)
pub const Window = opaque {};
pub const Rect = extern struct { x: c_int, y: c_int, w: c_int, h: c_int };
// Primary declarations
pub const GPUDevice = opaque {
pub fn claimWindow(device: *GPUDevice, window: ?*Window) bool {
return c.SDL_ClaimWindowForGPUDevice(device, window);
}
};
Type Extraction Details
Type String Normalization
C type strings often have pointer and const decorators that need to be stripped:
"SDL_Window *" → "SDL_Window"
"?*SDL_GPUDevice" → "SDL_GPUDevice"
"*const SDL_Rect" → "SDL_Rect"
"SDL_Buffer *const *" → "SDL_Buffer"
"[*c]const u8" → "u8"
Algorithm:
- Remove leading:
const,struct,?,* - Handle C arrays:
[*c]T→T - Remove trailing:
*,*const,const - Repeat until no changes
SDL Type Detection
A type is considered "SDL" if:
- Name starts with
SDL_prefix, OR - Name is in known SDL types list (Window, Rect, etc.)
Non-SDL types (primitives) are ignored:
bool,int,float,void, etc.
Declaration Cloning
When extracting types from dependency headers, we must clone them because:
- The temporary scanner will be freed
- Original strings will be deallocated
- We need owned copies with stable lifetime
Cloning Process:
fn cloneDeclaration(allocator: Allocator, decl: Declaration) !Declaration {
return switch (decl) {
.struct_decl => |s| .{
.struct_decl = .{
.name = try allocator.dupe(u8, s.name),
.fields = try cloneFields(allocator, s.fields),
.doc_comment = if (s.doc_comment) |doc|
try allocator.dupe(u8, doc) else null,
},
},
// ... similar for other types
};
}
All strings are duplicated so the cloned declaration owns them.
Success Metrics
SDL_gpu.h Results
Missing Types Detected: 5
- SDL_FColor
- SDL_PropertiesID
- SDL_Rect
- SDL_Window
- SDL_FlipMode
Resolution Results: 5/5 (100%) ✅
Where Found:
- SDL_FColor → SDL_pixels.h (struct)
- SDL_PropertiesID → SDL_properties.h (typedef)
- SDL_Rect → SDL_rect.h (struct)
- SDL_Window → SDL_video.h (opaque)
- SDL_FlipMode → SDL_surface.h (enum)
Configuration
Behavior
The dependency resolver is always enabled - no configuration needed.
When missing types are detected, it automatically:
- ✅ Searches included headers
- ✅ Extracts matching types
- ✅ Combines into output
- ✅ Reports progress
Error Handling
Warnings (non-fatal):
- Type not found in any header
- Dependency header not readable
- Parsing errors in dependency
Result: Partial output with warnings
Performance
Timing Breakdown (SDL_gpu.h)
| Phase | Time | Notes |
|---|---|---|
| Primary parsing | 50ms | Parse SDL_gpu.h |
| Dependency analysis | 10ms | Build HashMaps |
| Include parsing | 1ms | Extract #includes |
| Type extraction | 300ms | Parse 5 dependency headers |
| Code generation | 150ms | Generate + validate |
| Total | ~520ms | Acceptable |
Optimization
Current:
- Selective parsing (only types needed)
- Early exit (stop when found)
- HashMap deduplication
Future:
- Cache parsed headers
- Parallel header parsing
- Header dependency graph
Limitations
Not Resolved
-
Function pointer typedefs - Not yet supported
typedef void (*SDL_Callback)(void *userdata); -
#define-based types - Requires preprocessor
#define SDL_VALUE (1u << 0) typedef Uint32 SDL_Type; // Not found by scanner -
External library types - Expected
SDL_EGLConfig // From EGL, not SDL
Workarounds
Manual Definitions: Add missing types to a separate file
// manual_types.zig
pub const Callback = *const fn(?*anyopaque) void;
Preprocessor: Use clang to preprocess before parsing
clang -E -I/path/to/SDL3 header.h | zig build run --
Debugging
Enable Verbose Output
The parser already prints detailed progress:
Analyzing dependencies...
Found 5 missing types:
- SDL_FColor
- SDL_Rect
...
Resolving dependencies from included headers...
✓ Found SDL_FColor in SDL_pixels.h
✓ Found SDL_Rect in SDL_rect.h
⚠ Warning: Could not find definition for type: SDL_Unknown
Common Issues
"Could not find definition for type"
- Type might be typedef (check if recently added)
- Type might be in different include
- Type might be external (EGL, GL, etc.)
"Syntax errors in generated code"
- Check generated file line numbers
- Usually struct/enum parsing issues
- See Known Issues
Technical Details
For implementation details, see:
- Technical Flow - Step-by-step walkthrough
- Visual Guide - Diagrams and quick reference
Next: See API Reference for command-line options.