sdlparser-scrap/docs/DEPENDENCY_RESOLUTION.md

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:

  1. Scans all function signatures and struct fields
  2. Extracts all referenced type names
  3. Compares against types defined in the header
  4. Identifies missing types

Example:

// SDL_gpu.h
extern void SDL_ClaimWindow(SDL_GPUDevice *device, SDL_Window *window);
  • SDL_GPUDevice is defined in SDL_gpu.h ✓
  • SDL_Window is 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:

  1. Try each included header in order
  2. Parse the header completely
  3. Search for matching type definition
  4. If found, clone the declaration and stop searching
  5. 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:

  1. Remove leading: const, struct, ?, *
  2. Handle C arrays: [*c]TT
  3. Remove trailing: *, *const, const
  4. 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:

  1. The temporary scanner will be freed
  2. Original strings will be deallocated
  3. 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

  1. SDL_FColor
  2. SDL_PropertiesID
  3. SDL_Rect
  4. SDL_Window
  5. 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

  1. Function pointer typedefs - Not yet supported

    typedef void (*SDL_Callback)(void *userdata);
    
  2. #define-based types - Requires preprocessor

    #define SDL_VALUE (1u << 0)
    typedef Uint32 SDL_Type; // Not found by scanner
    
  3. 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:


Next: See API Reference for command-line options.