Backlog/lib/sdl3/parser/DEPENDENCY_PLAN.md

4.9 KiB

SDL3 Header Parser: Dependency Resolution Plan

Problem Statement

The generated gpu.zig references types from other SDL headers:

  • FColor (SDL_pixels.h)
  • Rect (SDL_rect.h)
  • PropertiesID (SDL_properties.h)
  • Window (SDL_video.h - opaque type)
  • FlipMode (SDL_surface.h)
  • GPUShaderFormat (special case: #define flags)

Without these types, the generated code won't compile.

Analysis of SDL Header Structure

SDL_gpu.h includes:

#include <SDL3/SDL_stdinc.h>     // Basic types (Uint32, etc.)
#include <SDL3/SDL_pixels.h>     // SDL_FColor
#include <SDL3/SDL_properties.h> // SDL_PropertiesID
#include <SDL3/SDL_rect.h>       // SDL_Rect
#include <SDL3/SDL_surface.h>    // SDL_FlipMode
#include <SDL3/SDL_video.h>      // SDL_Window (opaque)

Solution Options

Option 1: Parse Dependencies Recursively (REJECTED - Too Complex)

  • Parse all included headers
  • Build dependency graph
  • Generate all files in correct order
  • Issues:
    • SDL has circular dependencies
    • Would need to parse entire SDL API
    • Overkill for our use case

Option 2: Manual Type Imports (REJECTED - Not Maintainable)

  • Manually copy type definitions
  • Issues:
    • Not automated
    • Breaks on SDL updates
    • Defeats purpose of parser

Phase 1: Dependency Detection

  1. Parse target header (e.g., SDL_gpu.h)
  2. Collect all non-GPU SDL types referenced in signatures
  3. Map types to their source headers (from #include directives)

Phase 2: Selective Type Extraction

For each dependency header, extract ONLY referenced types:

  • Parse dependency header in "extract mode"
  • Only output declarations that match our needed types
  • Generate minimal <module>.zig files (e.g., pixels.zig, rect.zig)

Phase 3: Code Generation

Generate main file with imports:

pub const c = @import("c.zig").c;

// Import minimal dependencies
const pixels = @import("pixels.zig");
const rect = @import("rect.zig");
const properties = @import("properties.zig");
const video = @import("video.zig");
const surface = @import("surface.zig");

// Re-export needed types
pub const FColor = pixels.FColor;
pub const Rect = rect.Rect;
pub const PropertiesID = properties.PropertiesID;
pub const Window = video.Window;
pub const FlipMode = surface.FlipMode;

// Manual override for #define-based types
pub const GPUShaderFormat = packed struct(u32) {
    // ... handwritten
};

// Generated GPU declarations follow...

Implementation Plan

Step 1: Add Dependency Analysis

const DependencyInfo = struct {
    types_needed: []const []const u8,
    source_headers: std.StringHashMap([]const u8), // type -> header
};

fn analyzeDependencies(decls: []Declaration) !DependencyInfo {
    // Scan all function signatures for SDL_ types
    // Map types to headers based on SDL conventions
}

Step 2: Extract Types from Dependencies

fn extractTypesFromHeader(
    header_path: []const u8,
    types_to_extract: []const []const u8,
) ![]Declaration {
    // Parse dependency header
    // Filter to only needed types
    // Return minimal declaration set
}

Step 3: Generate Import Structure

fn generateWithDependencies(
    main_decls: []Declaration,
    deps: DependencyInfo,
    output_dir: []const u8,
) !void {
    // Generate dependency .zig files
    // Generate main file with imports
}

Step 4: Handle Special Cases

Opaque Types (e.g., Window):

  • SDL_Window is typedef struct SDL_Window SDL_Window; (forward decl)
  • Generate as: pub const Window = opaque {}; or pub const Window = c.SDL_Window;
  • Decision: Use c.SDL_Window for true opaque types

#define Flags (e.g., GPUShaderFormat):

  • Cannot be auto-parsed
  • Maintain "overrides" file: overrides.zig
  • User can provide manual definitions for unparseable types

File Structure

v2/
├── gpu.zig           # Main generated file with imports
├── pixels.zig        # Minimal: FColor only
├── rect.zig          # Minimal: Rect only
├── properties.zig    # Minimal: PropertiesID only
├── video.zig         # Minimal: Window only
├── surface.zig       # Minimal: FlipMode only
└── overrides.zig     # Manual definitions (GPUShaderFormat)

Advantages

  1. Automated - no manual copying
  2. Minimal - only extracts needed types
  3. Maintainable - regenerate on SDL updates
  4. Avoids circular dependencies - only extracts leaf types
  5. Flexible - handles special cases via overrides

Testing Strategy

  1. Parse SDL_gpu.h → detect dependencies
  2. Parse dependency headers → extract types
  3. Generate all files
  4. Run zig build to verify compilation
  5. Compare API compatibility with handwritten version

Future Enhancements

  • Cache parsed headers to avoid re-parsing
  • Support transitive dependencies (if type A needs type B)
  • Auto-generate overrides file with placeholders
  • Support multiple target headers in one run