diff --git a/docs/API_REFERENCE.md b/docs/API_REFERENCE.md deleted file mode 100644 index cc2ae72..0000000 --- a/docs/API_REFERENCE.md +++ /dev/null @@ -1,348 +0,0 @@ -# API Reference - -Complete reference for the SDL3 header parser command-line interface. - -## Command Syntax - -```bash -zig build run -- [options] -``` - -## Arguments - -### Required - -**``** - Path to SDL C header file - -Examples: -```bash -zig build run -- ../SDL/include/SDL3/SDL_gpu.h -zig build run -- /full/path/to/SDL_video.h -zig build run -- relative/path/to/header.h -``` - -### Optional - -**`--output=`** - Write output to file instead of stdout - -Examples: -```bash ---output=gpu.zig ---output=bindings/video.zig ---output=/tmp/test.zig -``` - -**`--mocks=`** - Generate C mock implementations - -Examples: -```bash ---mocks=gpu_mock.c ---mocks=test/mocks.c -``` - -**`--generate-json=`** - Generate JSON representation of parsed types - -Examples: -```bash ---generate-json=gpu.json ---generate-json=api/types.json -``` - -## Output Formats - -### Zig Bindings (Default) - -Generated when `--output` is specified (or to stdout if not): - -```zig -pub const c = @import("c.zig").c; - -pub const GPUDevice = opaque { - pub inline fn createGPUDevice(debug_mode: bool) ?*GPUDevice { - return c.SDL_CreateGPUDevice(debug_mode); - } -}; -``` - -**Features**: -- Type conversions (C → Zig) -- Method organization -- Dependency inclusion -- Doc comments preserved - -### C Mocks (Optional) - -Generated when `--mocks` is specified: - -```c -// Auto-generated C mock implementations -#include - -SDL_GPUDevice* SDL_CreateGPUDevice(bool debug_mode) { - return NULL; // Mock: always returns null -} - -void SDL_DestroyGPUDevice(SDL_GPUDevice *device) { - // Mock: no-op -} -``` - -**Use Case**: Testing without real SDL implementation - -### JSON Output (Optional) - -Generated when `--generate-json` is specified: - -```json -{ - "header": "SDL_gpu.h", - "opaque_types": [ - {"name": "SDL_GPUDevice"} - ], - "typedefs": [ - {"name": "SDL_PropertiesID", "underlying_type": "Uint32"} - ], - "enums": [ - { - "name": "SDL_GPUPrimitiveType", - "values": [ - {"name": "SDL_GPU_PRIMITIVETYPE_TRIANGLELIST"}, - {"name": "SDL_GPU_PRIMITIVETYPE_TRIANGLESTRIP"} - ] - } - ], - "structs": [ - { - "name": "SDL_GPUViewport", - "fields": [ - {"name": "x", "type": "float"}, - {"name": "y", "type": "float"} - ] - } - ], - "functions": [ - { - "name": "SDL_CreateGPUDevice", - "return_type": "SDL_GPUDevice*", - "parameters": [ - {"name": "debug_mode", "type": "bool"} - ] - } - ] -} -``` - -**Use Cases**: -- API documentation generation -- Schema validation -- Cross-language binding generation -- Type introspection tools - -## Build System Integration - -### In build.zig - -```zig -const parser_dep = b.dependency("sdl3_parser", .{ - .target = target, - .optimize = optimize, -}); -const parser_exe = parser_dep.artifact("sdl-parser"); - -const gen = b.addRunArtifact(parser_exe); -gen.addFileArg(b.path("SDL/include/SDL3/SDL_gpu.h")); -gen.addArg("--output=src/gpu.zig"); - -const gen_step = b.step("generate", "Generate SDL bindings"); -gen_step.dependOn(&gen.step); -``` - -Then run: -```bash -zig build generate -``` - -## Parser Behavior - -### Dependency Resolution - -**Automatic** - No configuration needed - -When the parser detects missing types, it: -1. Parses `#include` directives from the header -2. Searches each included header -3. Extracts matching type definitions -4. Includes them in the output - -**Progress Reporting**: -``` -Analyzing dependencies... -Found 5 missing types: - - SDL_Window - - SDL_Rect - ... - -Resolving dependencies... - ✓ Found SDL_Window in SDL_video.h - ✓ Found SDL_Rect in SDL_rect.h -``` - -### Type Filtering - -Only SDL types are processed: -- Types starting with `SDL_` -- Known SDL types (Window, Rect, etc.) - -Primitive types are ignored: -- `bool`, `int`, `float`, `void`, etc. - -### Pattern Matching Order - -Patterns are tried in this order: -1. Opaque types (`typedef struct X X;`) -2. Enums (`typedef enum {...} X;`) -3. Structs (`typedef struct {...} X;`) -4. Flags (`typedef Uint32 SDL_Flags;` + `#define` values) -5. Typedefs (`typedef Type SDL_Alias;`) -6. Functions (`extern SDL_DECLSPEC ...`) - -**Note**: Order matters! Flags must be tried before simple typedefs. - -### Naming Conventions - -**Types**: -- `SDL_GPUDevice` → `GPUDevice` (strip `SDL_` prefix) -- `SDL_GPU_PRIMITIVE_TYPE` → `GPUPrimitiveType` (remove first underscore) - -**Functions**: -- `SDL_CreateGPUDevice` → `createGPUDevice` (strip `SDL_`, camelCase) - -**Enum Values**: -- `SDL_GPU_PRIMITIVETYPE_TRIANGLELIST` → `primitiveTypeTrianglelist` - -**Parameters**: -- `SDL_GPUDevice *device` → `device: ?*GPUDevice` - -## Exit Codes - -- `0` - Success -- `1` - Error (file not found, out of memory, invalid arguments) - -## Console Output - -### Normal Operation - -``` -SDL3 Header Parser -================== - -Parsing: header.h - -Found N declarations - - Opaque types: X - - Typedefs: X - - Enums: X - - Structs: X - - Flags: X - - Functions: X - -Analyzing dependencies... -[dependency information] - -Generated: output.zig -``` - -File is still written, but may need manual fixes. - -## Type Conversion Reference - -### Integer Types - -| C Type | Zig Type | -|--------|----------| -| `Uint8` | `u8` | -| `Uint16` | `u16` | -| `Uint32` | `u32` | -| `Uint64` | `u64` | -| `Sint8` | `i8` | -| `Sint16` | `i16` | -| `Sint32` | `i32` | -| `Sint64` | `i64` | -| `int` | `c_int` | -| `unsigned int` | `c_uint` | -| `size_t` | `usize` | - -### Pointer Types - -| C Type | Zig Type | -|--------|----------| -| `SDL_Type*` | `?*Type` (nullable) | -| `const SDL_Type*` | `*const Type` | -| `SDL_Type**` | `?*?*Type` | -| `void*` | `?*anyopaque` | -| `const void*` | `*const anyopaque` | -| `const char*` | `[*c]const u8` | - -### Special Types - -| C Type | Zig Type | -|--------|----------| -| `bool` | `bool` | -| `float` | `f32` | -| `double` | `f64` | -| `size_t` | `usize` | - -## Examples - - -### Example - -**Input** (depends.h): -```c -#include - -extern void SDL_UseRect(SDL_Rect *rect); -``` - -**Command**: -```bash -zig build run -- depends.h --output=depends.zig -``` - -**Output**: -```zig -pub const c = @import("c.zig").c; - -// Dependency automatically included -pub const Rect = extern struct { - x: c_int, - y: c_int, - w: c_int, - h: c_int, -}; - -pub inline fn useRect(rect: *Rect) void { - return c.SDL_UseRect(rect); -} -``` - -### Mocks example - -**Command**: -```bash -zig build run -- simple.h --output=thing.zig --mocks=thing_mock.c -``` - -**Output** (thing_mock.c): -```c -#include - -SDL_ThingID SDL_CreateThing(void) { - return 0; -} - -void SDL_DestroyThing(SDL_Thing *thing) { - // No-op -} -``` - diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md deleted file mode 100644 index c6471da..0000000 --- a/docs/ARCHITECTURE.md +++ /dev/null @@ -1,430 +0,0 @@ -# ## Documentation - -- **[README](../README.md)** - Project overview and quick start -- **[Getting Started](GETTING_STARTED.md)** - Installation and first steps -- **[Architecture](ARCHITECTURE.md)** - How the parser works -- **[Dependency Resolution](DEPENDENCY_RESOLUTION.md)** - Automatic type extraction -- **[API Reference](API_REFERENCE.md)** - Command-line options and features -- **[Known Issues](KNOWN_ISSUES.md)** - Limitations and workarounds -- **[Quickstart Guide](QUICKSTART.md)** - Quick reference -- **[Roadmap](ROADMAP.md)** - Future plans and priorities - -## Technical Deep Dives - -For implementation details and visual guides: -- **[Dependency Flow](DEPENDENCY_FLOW.md)** - Complete technical walkthrough -- **[Visual Flow Diagrams](VISUAL_FLOW.md)** - Quick reference diagrams -- **[Multi-Field Structs](MULTI_FIELD_IMPLEMENTATION.md)** - Struct parsing details -- **[Typedef Support](TYPEDEF_IMPLEMENTATION.md)** - Typedef implementation -- **[Multi-Header Testing](MULTI_HEADER_TEST_RESULTS.md)** - Test results - -## Development - -- **[Development Guide](DEVELOPMENT.md)** - Contributing and extending the parser - -## Archive - -Historical planning documents are in `archive/` for reference. - -## High-Level Architecture - -``` -Input (C Header) → Scanner → Declarations → Dependency Resolver → CodeGen → Output (Zig) -``` - -## Core Components - -### 1. Scanner (`src/patterns.zig`) - -**Purpose**: Parse C header files into structured declarations - -**Process**: -1. Reads header file line by line -2. Tries to match each line against known patterns -3. Extracts type information, comments, and structure -4. Returns array of `Declaration` structures - -**Supported Patterns**: -- Opaque types: `typedef struct SDL_X SDL_X;` -- Typedefs: `typedef Uint32 SDL_PropertiesID;` -- Enums: `typedef enum { ... } SDL_Type;` -- Structs: `typedef struct { int x, y; } SDL_Rect;` -- Flags: `typedef Uint32 SDL_Flags;` + `#define` values -- Functions: `extern SDL_DECLSPEC void SDLCALL SDL_Func(...);` - -### 2. Dependency Resolver (`src/dependency_resolver.zig`) - -**Purpose**: Automatically find and extract missing type definitions - -**Process**: -1. Scans all declarations to find referenced types -2. Compares referenced types against defined types -3. Identifies missing types -4. Parses `#include` directives from source -5. Searches included headers for missing types -6. Extracts and clones matching declarations - -**Key Features**: -- Type string normalization (strips `*`, `const`, etc.) -- Deduplication using HashMaps -- Deep cloning for safe ownership -- Selective extraction (only types needed) - -### 3. Code Generator (`src/codegen.zig`) - -**Purpose**: Convert C declarations to idiomatic Zig code - -**Process**: -1. Groups functions by first parameter type (method categorization) -2. Generates type declarations -3. Generates function wrappers -4. Applies naming conventions -5. Performs type conversion - -**Features**: -- Method organization for opaque types -- Inline function wrappers -- Automatic type conversion -- Doc comment preservation - -### 4. Type Converter (`src/types.zig`) - -**Purpose**: Convert C types to Zig equivalents - -**Conversions**: -```zig -"bool" → "bool" -"Uint32" → "u32" -"int" → "c_int" -"SDL_Type *" → "?*Type" -"const SDL_Type *" → "*const Type" -``` - -### 5. Naming Convention Handler (`src/naming.zig`) - -**Purpose**: Convert C names to idiomatic Zig - -**Rules**: -- Strip `SDL_` prefix: `SDL_GPUDevice` → `GPUDevice` -- Remove first underscore: `SDL_GPU_TYPE` → `GPUType` -- CamelCase functions: `SDL_CreateDevice` → `createDevice` -- Lowercase first letter for values - -## Data Flow - -### 1. Parsing Phase - -``` -C Header File - ↓ -Scanner.scan() - ↓ -[]Declaration { - .opaque_type, - .typedef_decl, - .enum_decl, - .struct_decl, - .flag_decl, - .function_decl, -} -``` - -### 2. Dependency Analysis Phase - -``` -[]Declaration - ↓ -DependencyResolver.analyze() - ├─ collectDefinedTypes() → defined_types HashMap - └─ collectReferencedTypes() → referenced_types HashMap - ↓ -getMissingTypes() - ↓ -missing_types = referenced - defined -``` - -### 3. Dependency Resolution Phase - -``` -For each missing_type: - Parse #include directives - ↓ - For each included header: - Read header file - ↓ - Scanner.scan() - ↓ - Search for matching type - ↓ - If found: cloneDeclaration() -``` - -### 4. Code Generation Phase - -``` -[]Declaration (primary + dependencies) - ↓ -CodeGen.generate() - ├─ categorizeDeclarations() (group methods) - ├─ writeHeader() - └─ writeDeclarations() - ├─ writeOpaqueWithMethods() - ├─ writeTypedef() - ├─ writeEnum() - ├─ writeStruct() - ├─ writeFlags() - └─ writeFunction() - ↓ -Zig source code (string) -``` - -### 5. Validation Phase - -``` -Generated Zig code - ↓ -std.zig.Ast.parse() - ↓ -Check for syntax errors - ↓ -ast.renderAlloc() (format) - ↓ -Write to file or stdout -``` - -## Key Algorithms - -### Type Extraction - -**Purpose**: Strip pointer/const decorators to get base type - -```zig -"SDL_Window *" → "SDL_Window" -"?*const SDL_Rect" → "SDL_Rect" -"SDL_Buffer *const *" → "SDL_Buffer" -``` - -**Algorithm**: -1. Trim whitespace -2. Remove leading qualifiers (`const`, `*`, `?`) -3. Remove trailing qualifiers (`*`, `*const`, ` const`) -4. Handle special patterns (`[*c]`) -5. Return base type string - -### Multi-Field Parsing - -**Purpose**: Handle C compact syntax like `int x, y;` - -**Algorithm**: -1. Detect comma in field declaration -2. Extract common type (before first field name) -3. Split remaining part on commas -4. Create separate `FieldDecl` for each name -5. Return array of fields - -**Example**: -```c -int x, y; → [FieldDecl{.name="x", .type="int"}, - FieldDecl{.name="y", .type="int"}] -``` - -### Method Categorization - -**Purpose**: Determine if function should be a method - -**Algorithm**: -1. Check if function has parameters -2. Get type of first parameter -3. Check if type is an opaque type pointer -4. If yes, add to opaque type's methods -5. If no, write as standalone function - -**Example**: -```c -void SDL_Destroy(SDL_Device *d) → Method of GPUDevice -void SDL_Init(void) → Standalone function -``` - -## Memory Management - -### Ownership Rules - -1. **Scanner owns strings** during parsing (allocated from its allocator) -2. **Parser owns declarations** after scanning (freed at end of main) -3. **Resolver owns HashMap keys** (duped when inserted, freed in deinit) -4. **Cloned declarations own strings** (allocated explicitly, freed by caller) - -### Allocation Strategy - -``` -GPA (General Purpose Allocator) - ├─ Primary header source (freed at end) - ├─ Primary declarations (freed with deep free) - ├─ DependencyResolver - │ ├─ referenced_types HashMap (keys owned) - │ └─ defined_types HashMap (keys borrowed) - ├─ Missing types array (freed explicitly) - ├─ Includes array (freed explicitly) - ├─ Dependency declarations (freed with deep free) - └─ Generated output (freed after writing) -``` - -### Cleanup Pattern - -```zig -defer { - for (decls) |decl| { - freeDeclDeep(allocator, decl); - } - allocator.free(decls); -} -``` - -## Error Handling - -### Fatal Errors (Exit Immediately) - -- File not found (primary header) -- Out of memory -- Cannot write output file - -### Non-Fatal Errors (Continue with Warnings) - -- Dependency header not readable → Skip, try next -- Type not found in any header → Print warning, continue -- Struct parsing error → Generate partial, continue -- Syntax errors in output → Print errors, write anyway - -### Error Recovery - -The parser uses graceful degradation: -1. Try to extract as much as possible -2. Warn about issues -3. Continue processing -4. Generate best-effort output - -This allows partial success even with problematic headers. - -## Extension Points - -### Adding New Pattern Support - -1. Add new variant to `Declaration` union in `patterns.zig` -2. Implement `scan*()` function to match pattern -3. Add to pattern matching chain in `Scanner.scan()` -4. Update all switch statements: - - Cleanup code in `parser.zig` - - `cloneDeclaration()` in `dependency_resolver.zig` - - `freeDeclaration()` in `dependency_resolver.zig` -5. Implement `write*()` in `codegen.zig` - -### Adding Type Conversions - -Edit `src/types.zig`: -```zig -pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 { - // Add new conversion here - if (std.mem.eql(u8, c_type, "MyType")) { - return try allocator.dupe(u8, "MyZigType"); - } - // ... -} -``` - -### Adding Naming Rules - -Edit `src/naming.zig`: -```zig -pub fn typeNameToZig(c_name: []const u8) []const u8 { - // Add custom naming logic -} -``` - -## Performance Characteristics - -### Time Complexity - -- **Primary parsing**: O(n) where n = source lines -- **Dependency analysis**: O(d) where d = declarations -- **Type extraction**: O(h × d) where h = headers, d = declarations per header -- **Code generation**: O(d) where d = total declarations - -**Overall**: O(n + h×d) - Linear for typical use - -### Space Complexity - -- **Declarations**: O(d) where d = declaration count -- **HashMaps**: O(t) where t = unique type names -- **Output**: O(d) where d = declaration count - -**Peak memory**: ~2-5MB for SDL_gpu.h (169 declarations) - -### Optimization Points - -Current optimizations: -- HashMap-based deduplication -- Early exit when type found -- Selective parsing (only missing types) -- String interning for type names - -Potential improvements: -- Cache parsed headers (avoid re-parsing) -- Parallel header processing -- Lazy header loading - -## Testing Strategy - -### Unit Tests (`test/`) - -- Pattern matching tests (each C pattern) -- Type conversion tests -- Naming convention tests -- Dependency resolution tests -- Multi-field parsing tests - -### Integration Tests - -- Real SDL headers (SDL_gpu.h) -- Dependency chain resolution -- End-to-end parsing and generation - -### Validation - -- AST parsing of generated code -- Memory leak detection (GPA) -- No regressions (all tests must pass) - -## Code Organization - -``` -src/ -├── parser.zig # Main entry point, CLI handling -├── patterns.zig # Pattern matching and scanning -├── types.zig # C to Zig type conversion -├── naming.zig # Naming convention handling -├── codegen.zig # Zig code generation -├── mock_codegen.zig # C mock generation -└── dependency_resolver.zig # Dependency analysis and extraction - -test/ -└── (various test files) - -docs/ -├── GETTING_STARTED.md # This file -├── ARCHITECTURE.md # Architecture overview -├── DEPENDENCY_RESOLUTION.md # Dependency system details -└── ... -``` - -## Next Steps - -- Read [Dependency Resolution](DEPENDENCY_RESOLUTION.md) for details on automatic type extraction -- See [API Reference](API_REFERENCE.md) for all command-line options -- Check [Known Issues](KNOWN_ISSUES.md) for current limitations -- Review [Development](DEVELOPMENT.md) to contribute - ---- - -**Related Documents**: -- Technical deep dive: [docs/DEPENDENCY_FLOW.md](DEPENDENCY_FLOW.md) -- Visual diagrams: [docs/VISUAL_FLOW.md](VISUAL_FLOW.md) diff --git a/docs/DEPENDENCY_RESOLUTION.md b/docs/DEPENDENCY_RESOLUTION.md deleted file mode 100644 index 92ea71d..0000000 --- a/docs/DEPENDENCY_RESOLUTION.md +++ /dev/null @@ -1,283 +0,0 @@ -# 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**: -```c -// 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: -```c -#include -#include -#include -``` - -**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 - -```zig -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 - -```zig -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]T` → `T` -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**: -```zig -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 - ```c - typedef void (*SDL_Callback)(void *userdata); - ``` - -2. **#define-based types** - Requires preprocessor - ```c - #define SDL_VALUE (1u << 0) - typedef Uint32 SDL_Type; // Not found by scanner - ``` - -3. **External library types** - Expected - ```c - SDL_EGLConfig // From EGL, not SDL - ``` - -### Workarounds - -**Manual Definitions**: Add missing types to a separate file -```zig -// manual_types.zig -pub const Callback = *const fn(?*anyopaque) void; -``` - -**Preprocessor**: Use clang to preprocess before parsing -```bash -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](KNOWN_ISSUES.md) - -## Technical Details - -For implementation details, see: -- [Technical Flow](DEPENDENCY_FLOW.md) - Step-by-step walkthrough -- [Visual Guide](VISUAL_FLOW.md) - Diagrams and quick reference - ---- - -**Next**: See [API Reference](API_REFERENCE.md) for command-line options. diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md deleted file mode 100644 index 77c8f5c..0000000 --- a/docs/DEVELOPMENT.md +++ /dev/null @@ -1,634 +0,0 @@ -# Development Guide - -Guide for contributing to and extending the SDL3 header parser. - -## Quick Start for Developers - -```bash -# Clone and build -cd lib/sdl3/parser -zig build - -# Run tests -zig build test - -# Make changes -# ... edit src/*.zig ... - -# Test your changes -zig build test -zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=test.zig -``` - -## Project Structure - -``` -parser/ -├── src/ -│ ├── parser.zig # Main entry point, CLI -│ ├── patterns.zig # Pattern matching & scanning -│ ├── types.zig # C to Zig type conversion -│ ├── naming.zig # Naming conventions -│ ├── codegen.zig # Zig code generation -│ ├── mock_codegen.zig # C mock generation -│ └── dependency_resolver.zig # Dependency analysis -├── test/ -│ └── (test files) -├── docs/ -│ └── (documentation) -└── build.zig -``` - -## Zig 0.15 API Changes - CRITICAL - -**This project uses Zig 0.15**. Key API changes from 0.14: - -### ArrayList Changes - -**Old (0.14)**: -```zig -var list = std.ArrayList(T).init(allocator); -defer list.deinit(); -try list.append(item); -``` - -**New (0.15)** - REQUIRED: -```zig -var list = std.ArrayList(T){}; -defer list.deinit(allocator); -try list.append(allocator, item); -``` - -**Key Points**: -- Initialize with `{}` or `initCapacity()` -- All methods take allocator: `append(allocator, item)` -- Deinit takes allocator: `deinit(allocator)` - -### AST Rendering - -**Old**: `ast.render(allocator)` -**New**: `ast.renderAlloc(allocator)` - -## Adding New Pattern Support - -### Example: Adding Union Support - -1. **Add to Declaration union** (patterns.zig): -```zig -pub const Declaration = union(enum) { - // ... existing variants - union_decl: UnionDecl, // NEW -}; - -pub const UnionDecl = struct { - name: []const u8, - fields: []FieldDecl, - doc_comment: ?[]const u8, -}; -``` - -2. **Add scanner function** (patterns.zig): -```zig -fn scanUnion(self: *Scanner) !?UnionDecl { - // Pattern matching logic - // Return UnionDecl or null -} -``` - -3. **Add to scan chain** (patterns.zig): -```zig -if (try self.scanOpaque()) |opaque_decl| { - // ... -} else if (try self.scanUnion()) |union_decl| { - try decls.append(self.allocator, .{ .union_decl = union_decl }); -} else if (try self.scanEnum()) |enum_decl| { - // ... -} -``` - -4. **Update cleanup code** (parser.zig): -```zig -defer { - for (decls) |decl| { - switch (decl) { - // ... existing cases - .union_decl => |u| { - allocator.free(u.name); - if (u.doc_comment) |doc| allocator.free(doc); - for (u.fields) |field| { - allocator.free(field.name); - allocator.free(field.type_name); - if (field.comment) |c| allocator.free(c); - } - allocator.free(u.fields); - }, - } - } -} -``` - -5. **Update dependency resolver** (dependency_resolver.zig): -```zig -// In collectDefinedTypes: -.union_decl => |u| u.name, - -// In cloneDeclaration: -.union_decl => |u| .{ - .union_decl = .{ - .name = try allocator.dupe(u8, u.name), - .fields = try cloneFields(allocator, u.fields), - .doc_comment = if (u.doc_comment) |doc| - try allocator.dupe(u8, doc) else null, - }, -}, - -// In freeDeclaration: -.union_decl => |u| { - allocator.free(u.name); - if (u.doc_comment) |doc| allocator.free(doc); - for (u.fields) |field| { - allocator.free(field.name); - allocator.free(field.type_name); - if (field.comment) |c| allocator.free(c); - } - allocator.free(u.fields); -}, -``` - -6. **Add code generator** (codegen.zig): -```zig -fn writeUnion(self: *CodeGen, union_decl: patterns.UnionDecl) !void { - const zig_name = naming.typeNameToZig(union_decl.name); - - if (union_decl.doc_comment) |doc| { - try self.writeDocComment(doc); - } - - try self.output.writer(self.allocator).print( - "pub const {s} = extern union {{\n", - .{zig_name} - ); - - for (union_decl.fields) |field| { - const zig_type = try types.convertType(field.type_name, self.allocator); - defer self.allocator.free(zig_type); - - try self.output.writer(self.allocator).print( - " {s}: {s},\n", - .{field.name, zig_type} - ); - } - - try self.output.appendSlice(self.allocator, "};\n\n"); -} -``` - -7. **Update writeDeclarations** (codegen.zig): -```zig -switch (decl) { - // ... existing cases - .union_decl => |union_decl| try self.writeUnion(union_decl), -} -``` - -8. **Add tests**: -```zig -test "parse union" { - const source = - \\typedef union SDL_Color { - \\ Uint32 rgba; - \\ struct { Uint8 r, g, b, a; }; - \\} SDL_Color; - ; - - var scanner = patterns.Scanner.init(allocator, source); - const decls = try scanner.scan(); - // ... test expectations -} -``` - -## Testing Guidelines - -### Unit Tests - -Place tests in `test/` or at bottom of source files: - -```zig -test "descriptive test name" { - const allocator = std.testing.allocator; - - // Setup - const source = "..."; - var scanner = patterns.Scanner.init(allocator, source); - - // Execute - const result = try scanner.scan(); - defer allocator.free(result); - - // Assert - try std.testing.expectEqual(expected, actual); -} -``` - -### Integration Tests - -Test with real SDL headers: -```bash -zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=test.zig -zig ast-check test.zig -``` - -### Memory Testing - -Always run tests with GPA to detect leaks: -```zig -test "my test" { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = gpa.deinit(); - const allocator = gpa.allocator(); - - // Test code using allocator -} -``` - -## Code Style - -### Naming - -- **Functions**: camelCase (`parseStructField`) -- **Types**: PascalCase (`FieldDecl`) -- **Constants**: PascalCase (`Declaration`) -- **Variables**: camelCase (`decl_name`) - -### Comments - -Only comment code that needs clarification: -```zig -// Good: Explains WHY -// Must check flags before typedefs - pattern order matters -if (try self.scanFlagTypedef()) |flag_decl| { ... } - -// Bad: Explains WHAT (obvious from code) -// Append to list -try list.append(allocator, item); -``` - -### Error Handling - -Use graceful degradation: -```zig -// Good: Continue on error -const decl = extractType(source, name) catch |err| { - std.debug.print("Warning: {}\n", .{err}); - continue; -}; - -// Bad: Fail immediately (unless truly fatal) -const decl = try extractType(source, name); -``` - -## Memory Management Rules - -### Ownership - -1. **Scanner owns strings** during parsing -2. **Caller owns result** of scan() -3. **HashMap owns keys** when they're duped -4. **Cloned declarations own strings** after cloning - -### Cleanup Pattern - -Always use defer for cleanup: -```zig -const decls = try scanner.scan(); -defer { - for (decls) |decl| { - freeDeclDeep(allocator, decl); - } - allocator.free(decls); -} -``` - -### HashMap Keys - -Must be owned (not slices into temporary data): -```zig -// Wrong: -try map.put(type_str, {}); // type_str might be freed! - -// Right: -if (!map.contains(type_str)) { - const owned = try allocator.dupe(u8, type_str); - try map.put(owned, {}); -} -``` - -## Common Patterns - -### Pattern Matching - -```zig -fn scanSomething(self: *Scanner) !?SomeDecl { - const start = self.pos; - const line = try self.readLine(); - defer self.allocator.free(line); - - // Check pattern - if (!std.mem.startsWith(u8, line, "expected_start")) { - self.pos = start; // Reset position - return null; - } - - // Parse and return - return SomeDecl{ ... }; -} -``` - -### String Building - -```zig -var buf = std.ArrayList(u8){}; -defer buf.deinit(allocator); - -try buf.appendSlice(allocator, "pub const "); -try buf.appendSlice(allocator, name); -try buf.appendSlice(allocator, " = "); - -return try buf.toOwnedSlice(allocator); -``` - -### HashMap Usage - -```zig -var map = std.StringHashMap(void).init(allocator); -defer { - var it = map.keyIterator(); - while (it.next()) |key| { - allocator.free(key.*); // Free owned keys - } - map.deinit(); -} - -// Add items -const owned_key = try allocator.dupe(u8, key); -try map.put(owned_key, {}); -``` - -## Debugging Tips - -### Print Debugging - -```zig -std.debug.print("Debug: value = {s}\n", .{value}); -std.debug.print("Type: {}\n", .{@TypeOf(variable)}); -``` - -### Memory Leak Detection - -Run with GPA and check output: -```bash -zig build run -- header.h 2>&1 | grep "memory address" -``` - -### AST Debugging - -Check what Zig thinks is wrong: -```bash -zig ast-check generated.zig -``` - -## Performance Optimization - -### Guidelines - -1. **Avoid allocations in hot paths** - Use stack when possible -2. **Reuse buffers** - Clear and reuse instead of allocating new -3. **Early exit** - Return as soon as answer is known -4. **HashMap for lookups** - O(1) instead of O(n) searches - -### Profiling - -```bash -# Build with profiling -zig build -Drelease-safe - -# Run with timing -time zig build run -- large_header.h --output=out.zig -``` - -## Contributing Workflow - -1. **Create branch** from `dev/sdl3-parser` -2. **Make changes** in focused commits -3. **Run tests** - All must pass -4. **Update docs** if behavior changes -5. **Commit** with descriptive message -6. **Push** and create PR - -### Commit Message Format - -``` -feat: Add union type support - -Implements parsing and code generation for C union types. - -- Added UnionDecl to Declaration union -- Implemented scanUnion() pattern matcher -- Added writeUnion() code generator -- Created comprehensive test suite (5 tests) - -Results: -- Successfully parses SDL union types -- Generates proper extern unions -- All tests passing - -Closes: #123 -``` - -## Test-Driven Development - -Recommended workflow: - -1. **Write test first**: -```zig -test "parse union type" { - const source = "typedef union { int x; float y; } SDL_Union;"; - var scanner = patterns.Scanner.init(allocator, source); - const decls = try scanner.scan(); - - try testing.expectEqual(@as(usize, 1), decls.len); - try testing.expect(decls[0] == .union_decl); -} -``` - -2. **Run test** (it will fail) -3. **Implement feature** until test passes -4. **Add more tests** for edge cases -5. **Refactor** if needed - -## Architecture Decisions - -### Why Single-File Output? - -**Alternative**: Generate separate file per type - -**Decision**: Single file with dependencies first - -**Reasons**: -- Simpler for users (one import) -- Zig's structural typing handles it -- Type ordering guaranteed -- Less build system complexity - -### Why On-Demand Resolution? - -**Alternative**: Always parse all includes - -**Decision**: Only parse when missing types detected - -**Reasons**: -- Better performance -- Minimal overhead for self-contained headers -- Users see only relevant dependencies - -### Why Conservative Error Handling? - -**Alternative**: Fail on any error - -**Decision**: Warn and continue - -**Reasons**: -- Partial success is better than no success -- Users can manually fix issues -- Allows incremental improvement - -## Extending the Parser - -### Adding Type Conversions - -Edit `src/types.zig`: -```zig -pub fn convertType(c_type: []const u8, allocator: Allocator) ![]const u8 { - // Check for your pattern first - if (std.mem.eql(u8, c_type, "MyCustomType")) { - return try allocator.dupe(u8, "MyZigType"); - } - - // Fall through to existing logic - // ... -} -``` - -### Adding Naming Rules - -Edit `src/naming.zig`: -```zig -pub fn typeNameToZig(c_name: []const u8) []const u8 { - // Handle special cases - if (std.mem.eql(u8, c_name, "SDL_bool")) { - return "Bool"; // Custom mapping - } - - // Default logic - return stripSDLPrefix(c_name); -} -``` - -### Adding Pattern Matchers - -1. Implement `scan*()` function in `patterns.zig` -2. Add to scan chain with proper ordering -3. Update all switch statements -4. Add code generator -5. Write tests - -See "Adding New Pattern Support" section above for full example. - -## Common Issues When Developing - -### Issue: ArrayList API Changed - -**Error**: `error: no field named 'init' in struct 'ArrayList'` - -**Solution**: Use Zig 0.15 API (see above) - -### Issue: HashMap Key Lifetime - -**Error**: Memory corruption or use-after-free - -**Solution**: Always dupe keys before inserting: -```zig -const owned = try allocator.dupe(u8, key); -try map.put(owned, {}); -``` - -### Issue: Pattern Matching Order - -**Error**: Wrong scanner function matches - -**Solution**: Order matters! More specific patterns first: -```zig -// Correct order: -if (try self.scanFlagTypedef()) { ... } // Specific -else if (try self.scanTypedef()) { ... } // General - -// Wrong order: -if (try self.scanTypedef()) { ... } // Too general - catches flags! -else if (try self.scanFlagTypedef()) { ... } // Never reached -``` - -## Performance Considerations - -### Current Performance - -- Small headers: ~100ms -- Large headers (SDL_gpu.h): ~520ms -- Memory: ~2-5MB peak - -### Bottlenecks - -1. **Dependency extraction**: 300ms (58% of time) - - Parsing multiple headers - - Could cache parsed headers - -2. **String allocations**: Many small allocations - - Could use arena allocator - - String interning would help - -### Optimization Ideas - -```zig -// Cache parsed headers -var header_cache = std.StringHashMap([]Declaration).init(allocator); - -// Use arena for temporary allocations -var arena = std.heap.ArenaAllocator.init(allocator); -defer arena.deinit(); -const temp_alloc = arena.allocator(); -``` - -## Resources - -### Zig Documentation -- [Zig Language Reference](https://ziglang.org/documentation/master/) -- [Zig Standard Library](https://ziglang.org/documentation/master/std/) - -### SDL Documentation -- [SDL3 API](https://wiki.libsdl.org/SDL3/) -- [SDL3 Headers](https://github.com/libsdl-org/SDL) - -### Project Documentation -- [Architecture](ARCHITECTURE.md) - How the parser works -- [Dependency Flow](DEPENDENCY_FLOW.md) - Detailed flow -- [Visual Flow](VISUAL_FLOW.md) - Diagrams - -## Getting Help - -- Check existing tests for examples -- Read [Architecture](ARCHITECTURE.md) for design -- See [Dependency Flow](DEPENDENCY_FLOW.md) for details -- Review git history for patterns - ---- - -**Ready to contribute?** Start with the tests, understand the existing patterns, then extend! diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md deleted file mode 100644 index 744170e..0000000 --- a/docs/GETTING_STARTED.md +++ /dev/null @@ -1,278 +0,0 @@ -# Getting Started with SDL3 Parser - -This guide will help you get up and running with the SDL3 header parser. - -## Prerequisites - -- Zig 0.15 or later -- SDL3 headers (included in `../SDL/include/SDL3/`) - -## Installation - -1. Navigate to the parser directory: -```bash -cd lib/sdl3/parser -``` - -2. Build the parser: -```bash -zig build -``` - -3. Run tests to verify installation: -```bash -zig build test -``` - -You should see: `All tests passed.` - -## Your First Parse - -### Step 1: Parse SDL_gpu.h - -```bash -zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=my_gpu.zig -``` - -You'll see output like: -``` -SDL3 Header Parser -================== - -Parsing: ../SDL/include/SDL3/SDL_gpu.h - -Found 169 declarations - - Opaque types: 13 - - Typedefs: 6 - - Enums: 24 - - Structs: 35 - - Flags: 3 - - Functions: 94 - -Analyzing dependencies... -Found 5 missing types: - - SDL_FColor - - SDL_PropertiesID - - SDL_Rect - - SDL_Window - - SDL_FlipMode - -Resolving dependencies from included headers... - ✓ Found SDL_FColor in SDL_pixels.h - ✓ Found SDL_PropertiesID in SDL_properties.h - ✓ Found SDL_Rect in SDL_rect.h - ✓ Found SDL_Window in SDL_video.h - ✓ Found SDL_FlipMode in SDL_surface.h - -Combining 5 dependency declarations with primary declarations... -Generated: my_gpu.zig -``` - -### Step 2: Examine the Output - -```bash -head -50 my_gpu.zig -``` - -You'll see clean Zig bindings: -```zig -pub const c = @import("c.zig").c; - -// Dependencies (automatically included) -pub const FColor = extern struct { - r: f32, - g: f32, - b: f32, - a: f32, -}; - -pub const PropertiesID = u32; - -pub const Rect = extern struct { - x: c_int, - y: c_int, - w: c_int, - h: c_int, -}; - -pub const Window = opaque {}; - -// Primary declarations -pub const GPUDevice = opaque { - pub inline fn destroyGPUDevice(gpudevice: *GPUDevice) void { - return c.SDL_DestroyGPUDevice(gpudevice); - } - // ... 93 more methods -}; -``` - -### Step 3: Create c.zig Wrapper - -Create a file `c.zig` that imports SDL: -```zig -pub const c = @cImport({ - @cInclude("SDL3/SDL.h"); -}); -``` - -### Step 4: Use in Your Project - -```zig -const std = @import("std"); -const gpu = @import("my_gpu.zig"); - -pub fn main() !void { - const device = gpu.createGPUDevice(true); - if (device) |d| { - defer d.destroyGPUDevice(); - - const driver = d.getGPUDeviceDriver(); - std.debug.print("GPU Driver: {s}\n", .{driver}); - } -} -``` - -## Command-Line Options - -### Basic Options - -```bash -# Output to file -zig build run -- header.h --output=output.zig - -# Output to stdout -zig build run -- header.h -``` - -### Mock Generation - -```bash -# Generate C mocks for testing -zig build run -- header.h --output=bindings.zig --mocks=mocks.c -``` - -The mock file contains stub implementations that return zero/null: -```c -void SDL_DestroyGPUDevice(SDL_GPUDevice *device) { - // Mock implementation -} -``` - -## Understanding the Output - -### Type Name Conversion - -The parser follows consistent naming rules: - -| C Name | Zig Name | Rule | -|--------|----------|------| -| `SDL_GPUDevice` | `GPUDevice` | Strip `SDL_` prefix | -| `SDL_GPU_PRIMITIVE_TYPE_TRIANGLELIST` | `primitiveTypeTrianglelist` | Strip prefix, camelCase | -| `SDL_CreateGPUDevice` | `createGPUDevice` | Strip `SDL_`, camelCase | - -### Method Grouping - -Functions are organized as methods when possible: - -**C API**: -```c -void SDL_DestroyGPUDevice(SDL_GPUDevice *device); -const char* SDL_GetGPUDeviceDriver(SDL_GPUDevice *device); -``` - -**Generated Zig**: -```zig -pub const GPUDevice = opaque { - pub inline fn destroyGPUDevice(self: *GPUDevice) void { ... } - pub inline fn getGPUDeviceDriver(self: *GPUDevice) [*c]const u8 { ... } -}; -``` - -Usage becomes: -```zig -device.destroyGPUDevice(); // Instead of SDL_DestroyGPUDevice(device) -``` - -### Dependency Inclusion - -Dependencies are automatically detected and included at the top of the file: - -```zig -// Dependencies from included headers -pub const FColor = extern struct { ... }; -pub const Rect = extern struct { ... }; -pub const Window = opaque {}; - -// Primary declarations from SDL_gpu.h -pub const GPUDevice = opaque { ... }; -``` - -## Common Workflows - -### Generate Bindings for a Module - -```bash -# From lib/sdl3 directory -zig build regenerate-zig -``` - -This generates bindings for configured headers in `v2/` directory. - -### Test Your Changes - -After modifying the parser: - -```bash -# Run unit tests -zig build test - -# Test with a real header -zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=test.zig - -# Verify output compiles -zig ast-check test.zig -``` - -### Debug Issues - -If you encounter errors: - -1. Check the console output for warnings about missing types -2. Look at the generated file for syntax errors -3. See [Known Issues](docs/KNOWN_ISSUES.md) for common problems - -## Next Steps - -- Read [Architecture](docs/ARCHITECTURE.md) to understand how it works -- See [Dependency Resolution](docs/DEPENDENCY_RESOLUTION.md) for details on automatic type extraction -- Check [Known Issues](docs/KNOWN_ISSUES.md) for current limitations -- Review [Development](docs/DEVELOPMENT.md) to contribute - -## Quick Reference - -```bash -# Build -zig build - -# Test -zig build test - -# Generate bindings -zig build run --
--output= - -# Generate with mocks -zig build run --
--output= --mocks= - -# Generate all configured headers -cd .. && zig build regenerate-zig -``` - -## Getting Help - -- **Documentation**: See `docs/` directory -- **Examples**: Check `test/` directory for usage examples -- **Issues**: See `docs/KNOWN_ISSUES.md` - ---- - -**Next**: Read [Architecture](docs/ARCHITECTURE.md) to understand the parser internals. diff --git a/docs/INDEX.md b/docs/INDEX.md deleted file mode 100644 index 30c65ff..0000000 --- a/docs/INDEX.md +++ /dev/null @@ -1,112 +0,0 @@ -# SDL3 Parser Documentation - -Complete documentation for the SDL3 C header to Zig bindings generator. - -## Quick Links - -- **[README](../README.md)** - Start here for project overview -- **[Getting Started](GETTING_STARTED.md)** - Installation and first use -- **[API Reference](API_REFERENCE.md)** - Command-line options - -## User Guides - -### Essential - -1. **[Getting Started](GETTING_STARTED.md)** - Installation, first parse, basic usage -2. **[Quickstart Guide](QUICKSTART.md)** - Quick reference for common tasks -3. **[API Reference](API_REFERENCE.md)** - Complete command-line reference - -### Features - -4. **[Dependency Resolution](DEPENDENCY_RESOLUTION.md)** - How automatic type extraction works -5. **[Known Issues](KNOWN_ISSUES.md)** - Current limitations and workarounds - -## Technical Documentation - -### Architecture - -6. **[Architecture Overview](ARCHITECTURE.md)** - System design and components -7. **[Dependency Flow](DEPENDENCY_FLOW.md)** - Complete technical walkthrough (845 lines) -8. **[Visual Flow Diagrams](VISUAL_FLOW.md)** - Quick reference diagrams - -### Implementation Details - -9. **[Multi-Field Structs](MULTI_FIELD_IMPLEMENTATION.md)** - How `int x, y;` parsing works -10. **[Typedef Support](TYPEDEF_IMPLEMENTATION.md)** - Simple typedef implementation -11. **[Multi-Header Testing](MULTI_HEADER_TEST_RESULTS.md)** - Test results across SDL headers - -## Development - -12. **[Development Guide](DEVELOPMENT.md)** - Contributing, extending, Zig 0.15 guidelines -13. **[Roadmap](ROADMAP.md)** - Future plans and priorities - -## Quick Start - -```bash -# Install -cd parser/ -zig build -zig build test - -# Generate bindings -zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig - -# Use in code -const gpu = @import("gpu.zig"); -``` - -## Documentation by Use Case - -### "I want to generate Zig bindings" -→ Start with [Getting Started](GETTING_STARTED.md) - -### "I want to understand how it works" -→ Read [Architecture](ARCHITECTURE.md) - -### "I'm hitting an error" -→ Check [Known Issues](KNOWN_ISSUES.md) - -### "I want to extend the parser" -→ See [Development Guide](DEVELOPMENT.md) - -### "I need technical details" -→ Deep dive: [Dependency Flow](DEPENDENCY_FLOW.md) - -## Project Status - -**Version**: 2.1 -**Status**: Production ready for SDL_gpu.h -**Last Updated**: 2026-01-22 - -### Supported Headers - -| Header | Status | Notes | -|--------|--------|-------| -| SDL_gpu.h | ✅ Complete | 100% dependency resolution | -| SDL_keyboard.h | ⚠️ Partial | Large enum issues | -| SDL_video.h | ⚠️ Partial | Some types not found | -| SDL_events.h | ⚠️ Partial | Parse errors | - -See [Known Issues](KNOWN_ISSUES.md) for details. - -## Key Features - -✅ Automatic dependency resolution (100% for SDL_gpu.h) -✅ Multi-field struct parsing (`int x, y;`) -✅ Typedef support (`typedef Uint32 SDL_Type;`) -✅ Method organization (functions → methods) -✅ Mock generation for testing -✅ Comprehensive error reporting - -## Statistics - -- **Code**: ~900 lines (production) -- **Tests**: 26+ unit tests (100% passing) -- **Documentation**: 5,500+ lines -- **Success Rate**: 100% for SDL_gpu.h - ---- - -## Archive - -Historical planning and session documents are in `archive/` for reference. diff --git a/docs/KNOWN_ISSUES.md b/docs/KNOWN_ISSUES.md deleted file mode 100644 index f6b395a..0000000 --- a/docs/KNOWN_ISSUES.md +++ /dev/null @@ -1,299 +0,0 @@ -# Known Issues and Limitations - -This document lists current limitations and remaining issues in the SDL3 header parser. - -## Current Status - -**45+ SDL3 headers** successfully generated with automatic dependency resolution and JSON export. - -### Successfully Generated APIs - -All major SDL3 APIs parse and generate correctly, including: -- Core: audio, camera, clipboard, dialog, events, filesystem, gamepad, gpu, haptic, hints, init, joystick, keyboard, log, mouse, pen, power, properties, rect, render, sensor, storage, surface, time, timer, touch, video -- Platform: iostream, loadso, locale, messagebox, misc, process, stdinc, system, vulkan -- Specialized: blendmode, error, guid, metal, pixels, scancode - -### Intentionally Skipped - -- **assert**: Macro-only header (no types to parse) -- **mutex**: Low-level unsafe primitives (use std.Thread.Mutex instead) -- **thread**: Complex concurrency primitives (use std.Thread instead) -- **hidapi**: Low-level USB/HID interface (specialized use) -- **tray**: Platform-specific system tray (incomplete API) - -## Known Limitations - -### 1. Field Names That Shadow Zig Keywords - -**Issue**: Fields named `type`, `error`, `async`, etc. cause compilation errors - -**Status**: ✅ **FIXED** - Automatic escaping implemented - -**Example**: -```c -typedef struct { - int type; // Automatically escaped now -} SDL_Something; -``` - -**Generated**: -```zig -pub const Something = extern struct { - @"type": c_int, // Auto-escaped! -}; -``` - -**Keywords Handled**: type, error, async, await, suspend, resume, try, catch, if, else, for, while, switch, return, break, continue, defer, unreachable, noreturn, comptime, inline, export, extern, packed, const, var, fn, pub, test, struct, enum, union, opaque - -### 2. Function Pointer Typedefs - -**Issue**: Function pointer types generate as opaque types instead of function pointers - -**Status**: ✅ **FIXED** - Proper function pointer typedef support implemented - -**Example**: -```c -typedef void (*SDL_HitTest)(SDL_Window *window, const SDL_Point *pt, void *data); -``` - -**Generated**: -```zig -pub const HitTest = *const fn (?*Window, *const Point, ?*anyopaque) callconv(.C) void; -``` - -**Support**: Full function pointer parsing with parameters, return types, and proper Zig calling convention - -### 3. SDL_UINT64_C Macro in Bit Positions - -**Issue**: Some 64-bit flag patterns may not parse correctly - -**Example**: -```c -#define SDL_WINDOW_FULLSCREEN SDL_UINT64_C(0x0000000000000001) -``` - -**Status**: Enhanced support added, but not fully tested - -**Workaround**: Manual flag definitions if needed - -**Priority**: Medium -**Effort**: ~30 minutes validation -**Affected**: SDL_video.h WindowFlags - -### 4. External Library Types - -**Issue**: Types from external libraries (EGL, OpenGL) not found - -**Example**: -```c -SDL_EGLConfig -SDL_EGLDisplay -SDL_GLContext -``` - -**Status**: Expected behavior (not SDL types) - -**Workaround**: Use C imports or manual definitions - -**Priority**: N/A (expected) - -### 5. Memory Leaks in Comment Handling - -**Issue**: Small memory leaks in struct comment parsing - -**Status**: ✅ **FIXED** - Proper memory cleanup implemented - -**Impact**: None - all allocations properly freed - -### 6. Array Field Declarations - -**Issue**: Array fields in multi-field syntax not supported - -**Example**: -```c -int array1[10], array2[20]; // Not handled -``` - -**Workaround**: Rare in SDL, can be manually defined - -**Priority**: Low -**Effort**: ~1 hour - -### 7. Bit Field Declarations - -**Issue**: Bit fields not supported - -**Example**: -```c -struct { - unsigned a : 4; - unsigned b : 4; -}; -``` - -**Status**: Not used in SDL public API - -**Priority**: Very Low - -## Workaround Strategies - -### Strategy 1: Manual Type Definitions - -Create a supplementary file with missing types: -```zig -// manual_types.zig -pub const HitTest = *const fn(?*Window, *const Point, ?*anyopaque) callconv(.C) void; -pub const Scancode = c_int; // Simplified if full enum not needed -``` - -### Strategy 2: Direct C Import - -For problematic types, use C directly: -```zig -const c = @cImport(@cInclude("SDL3/SDL.h")); -pub const Scancode = c.SDL_Scancode; -``` - -### Strategy 3: Selective Generation - -Only generate for headers that work: -```bash -# These work well: -zig build run -- SDL_gpu.h --output=gpu.zig -zig build run -- SDL_properties.h --output=properties.zig - -# These need work: -# SDL_keyboard.h, SDL_events.h (use C import for now) -``` - -## Testing Results - -### ✅ Successfully Generated (45+ headers) - -All major SDL3 APIs successfully parse and generate working Zig bindings: - -**Core**: audio, camera, clipboard, dialog, events, filesystem, gamepad, gpu, haptic, hints, init, joystick, keyboard, log, mouse, pen, power, properties, rect, render, sensor, storage, surface, time, timer, touch, video - -**Platform**: iostream, loadso, locale, messagebox, misc, process, stdinc, system, vulkan - -**Specialized**: blendmode, error, guid, metal, pixels, scancode - -**Coverage**: ~95% of SDL3 public API - -## Error Messages Explained - -### "Could not find definition for type: X" - -**Meaning**: Type referenced but not found in any included header - -**Possible Causes**: -1. Type is a function pointer (not supported) -2. Type is external (EGL, GL) (expected) -3. Type is in a header not included -4. Type uses unsupported pattern - -**Action**: Check if type is needed, add manually if so - -### "Syntax errors detected in generated code" - -**Meaning**: Generated Zig code doesn't parse - -**Possible Causes**: -1. Large enum parsing issue -2. Field name shadows keyword -3. Unsupported C pattern - -**Action**: Check line numbers in error, see if manual fix needed - -### "InvalidBitPosition" - -**Meaning**: Flag value pattern not recognized - -**Possible Causes**: -1. Uses SDL_UINT64_C macro (partially supported) -2. Complex bit expression -3. Non-standard format - -**Action**: May need to manually define flags - -### Memory Leak Warnings - -**Meaning**: Small allocations not freed - -**Impact**: Minimal (1-2KB per run) - -**Status**: Known issue in comment handling, functional - -**Action**: None required (will be fixed in future) - -## Supported vs Unsupported - -### ✅ Fully Supported - -- Opaque types -- Simple structs -- Multi-field structs (`int x, y;`) -- Enums (up to ~100 values) -- Flags (with standard patterns) -- Typedefs (simple type aliases) -- Functions (extern declarations) -- Dependency resolution -- Type conversion -- Method grouping - -### ⚠️ Partially Supported - -- Large enums (300+ values) - needs work -- SDL_UINT64_C flags - enhanced but not fully tested -- Some bit position patterns - -### ❌ Not Supported - -- Function pointer typedefs -- #define-based type definitions (without typedef) -- Union types -- Bit field structs -- Complex macro expressions -- Non-SDL types - -## Reporting Issues - -When encountering a new issue: - -1. **Check this document** - May already be known -2. **Test with simple case** - Isolate the problem -3. **Check generated output** - Look at line numbers in errors -4. **Document the pattern** - Save example for future reference - -## Future Improvements - -### Possible Enhancements - -1. **Union support** - Rarely used in SDL (low priority) -2. **Bit field support** - Not in SDL public API (very low priority) -3. **Array field improvements** - Handle complex array patterns (low priority) -4. **Better error messages** - More detailed diagnostics (medium priority) - -## Comparison with Manual Approach - -### Manual Binding Creation - -**Time**: ~30 minutes per header -**Error Rate**: High (missing fields, wrong types) -**Maintenance**: Manual updates needed -**Consistency**: Varies by developer - -### Parser Approach - -**Time**: ~0.5 seconds -**Error Rate**: Low (for supported patterns) -**Maintenance**: Automatic with SDL updates -**Consistency**: Perfect (deterministic) - -**Conclusion**: Parser is vastly superior for supported patterns, with clear workarounds for unsupported cases. - ---- - -**Status**: Production ready - 45+ SDL3 headers successfully generated -**Recommendation**: Use generated bindings for all supported headers -**Next**: See [Development](DEVELOPMENT.md) for extending the parser diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md deleted file mode 100644 index 1c314c9..0000000 --- a/docs/QUICKSTART.md +++ /dev/null @@ -1,203 +0,0 @@ -# SDL3 Parser - Quick Start Guide - -## What It Does - -Automatically generates Zig bindings from SDL3 C headers with automatic dependency resolution. - -## Installation & Build - -```bash -cd parser/ -zig build # Build parser executable -zig build test # Run all tests -``` - -## Basic Usage - -### Parse a Header - -```bash -# Output to stdout -zig build run -- ../SDL/include/SDL3/SDL_gpu.h - -# Output to file -zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig - -# Generate with C mocks -zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig --mocks=gpu_mock.c -``` - -### What It Generates - -**Input** (`SDL_gpu.h` excerpt): -```c -typedef struct SDL_GPUDevice SDL_GPUDevice; -extern SDL_DECLSPEC void SDLCALL SDL_DestroyGPUDevice(SDL_GPUDevice *device); -``` - -**Output** (`gpu.zig`): -```zig -pub const GPUDevice = opaque { - pub inline fn destroyGPUDevice(gpudevice: *GPUDevice) void { - return c.SDL_DestroyGPUDevice(gpudevice); - } -}; -``` - -## Features - -### ✅ Supported C Patterns - -- **Opaque types**: `typedef struct SDL_Type SDL_Type;` -- **Enums**: `typedef enum { VALUE1, VALUE2 } SDL_Type;` -- **Structs**: `typedef struct { int field; } SDL_Type;` -- **Flags**: Packed bitfield enums -- **Functions**: `extern SDL_DECLSPEC RetType SDLCALL SDL_Func(...);` - -### ✅ Automatic Dependency Resolution - -- Detects types referenced but not defined -- Searches included headers for definitions -- Automatically includes needed types in output -- Handles: `SDL_FColor`, `SDL_Rect`, `SDL_Window`, `SDL_FlipMode`, etc. - -### ✅ Type Conversion - -| C Type | Zig Type | -|--------|----------| -| `bool` | `bool` | -| `Uint32` | `u32` | -| `SDL_Type*` | `?*Type` (nullable) | -| `const SDL_Type*` | `*const Type` | -| `void*` | `?*anyopaque` | -| `const char*` | `[*c]const u8` | - -### ✅ Naming Conventions - -- Strip `SDL_` prefix: `SDL_GPUDevice` → `GPUDevice` -- Remove first underscore: `SDL_GPU_Type` → `GPUType` -- camelCase functions: `SDL_CreateDevice` → `createDevice` - -## Current Limitations - -### ⚠️ Not Yet Supported - -1. **Multi-field structs**: `int x, y;` (parsed as single field) - - **Workaround**: Manually expand or wait for next version - -2. **Simple typedefs**: `typedef Uint32 SDL_Type;` - - **Workaround**: Add manually to output - -3. **#define constants**: `#define VALUE (1u << 0)` - - **Workaround**: Use clang preprocessor or manual definitions - -## Project Structure - -``` -parser/ -├── src/ -│ ├── parser.zig # Main entry point -│ ├── patterns.zig # Pattern matching & scanning -│ ├── types.zig # C to Zig type conversion -│ ├── naming.zig # Naming conventions -│ ├── codegen.zig # Zig code generation -│ ├── mock_codegen.zig # C mock generation -│ └── dependency_resolver.zig # Dependency analysis [NEW] -├── test/ # Test files -├── docs/ # Documentation -├── build.zig # Build configuration -└── README.md # Full documentation -``` - -## Documentation - -- `PARSER_OVERVIEW.md` - How the parser works -- `DEPENDENCY_PLAN.md` - Original dependency design -- `DEPENDENCY_IMPLEMENTATION_STATUS.md` - Current status -- `IMPLEMENTATION_SUMMARY.md` - Session summary -- `AGENTS.md` - Zig 0.15 guidelines for AI agents -- `TODO.md` - Next steps - -## Testing - -```bash -# Run all tests -zig build test - -# Test with specific header -zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=test_output.zig - -# Verify output compiles (requires c.zig) -zig ast-check test_output.zig -``` - -## Example Workflow - -1. **Parse header with dependencies**: - ```bash - zig build run -- ../SDL/include/SDL3/SDL_gpu.h --output=gpu.zig - ``` - -2. **Check the output**: - ```bash - cat gpu.zig | head -50 - ``` - -3. **Create c.zig wrapper**: - ```zig - pub const c = @cImport({ - @cInclude("SDL3/SDL.h"); - }); - ``` - -4. **Use in your project**: - ```zig - const gpu = @import("gpu.zig"); - - pub fn main() !void { - const device = gpu.createGPUDevice(true); - defer device.?.destroyGPUDevice(); - } - ``` - -## Common Issues - -### "FileNotFound" error -- Check header path is correct relative to working directory -- Use absolute path: `/full/path/to/SDL/include/SDL3/SDL_gpu.h` - -### "Syntax errors detected" -- Usually multi-field struct issue (known limitation) -- Check output file for specific line numbers -- Manually fix or wait for parser update - -### "Warning: Could not find definition for type" -- Type might be typedef (not yet supported) -- Type might be in different include (check manually) -- Type might be #define-based (use manual definition) - -## Performance - -- Small headers (<100 decls): ~100ms -- Large headers (SDL_gpu.h, 169 decls): ~500ms with dependencies -- Memory usage: ~2-5MB peak -- Output size: ~1KB per declaration - -## Getting Help - -1. Check `DEPENDENCY_IMPLEMENTATION_STATUS.md` for known issues -2. Look at `TODO.md` for planned improvements -3. Read `AGENTS.md` if you're an AI agent working on this -4. Check test files in `test/` for usage examples - -## Version Info - -- **Parser Version**: 2.0 (with dependency resolution) -- **Zig Version**: 0.15.2 -- **SDL Version**: 3.2.0 -- **Status**: Operational with known limitations ✅ - ---- - -**Last Updated**: 2026-01-22 -**Next Milestone**: Fix multi-field struct parsing