const std = @import("std"); const patterns = @import("patterns.zig"); const Allocator = std.mem.Allocator; pub const MockCodeGen = struct { decls: []patterns.Declaration, allocator: Allocator, output: std.ArrayList(u8), pub fn generate(allocator: Allocator, decls: []patterns.Declaration) ![]const u8 { var gen = MockCodeGen{ .decls = decls, .allocator = allocator, .output = try std.ArrayList(u8).initCapacity(allocator, 4096), }; try gen.writeHeader(); try gen.writeOpaqueDeclarations(); try gen.writeFunctionMocks(); return try gen.output.toOwnedSlice(allocator); } fn writeHeader(self: *MockCodeGen) !void { const header = \\// Auto-generated C mock implementations \\// DO NOT EDIT - Generated by sdl-parser --mocks \\ \\#include \\#include \\#include \\ \\ ; try self.output.appendSlice(self.allocator, header); } fn writeOpaqueDeclarations(self: *MockCodeGen) !void { var has_opaques = false; for (self.decls) |decl| { if (decl == .opaque_type) { if (!has_opaques) { try self.output.appendSlice(self.allocator, "// Forward declarations for opaque types\n"); has_opaques = true; } const opaque_type = decl.opaque_type; try self.output.writer(self.allocator).print("typedef struct {s} {s};\n", .{ opaque_type.name, opaque_type.name }); } } if (has_opaques) { try self.output.appendSlice(self.allocator, "\n"); } } fn writeFunctionMocks(self: *MockCodeGen) !void { var has_functions = false; for (self.decls) |decl| { if (decl == .function_decl) { if (!has_functions) { try self.output.appendSlice(self.allocator, "// Function implementations\n\n"); has_functions = true; } try self.writeFunctionMock(decl.function_decl); } } } fn writeFunctionMock(self: *MockCodeGen, func: patterns.FunctionDecl) !void { const writer = self.output.writer(self.allocator); // Write return type and function name try writer.print("{s} {s}(", .{ func.return_type, func.name }); // Write parameters if (func.params.len == 0) { try writer.writeAll("void"); } else { for (func.params, 0..) |param, i| { if (i > 0) { try writer.writeAll(", "); } try writer.print("{s}", .{param.type_name}); if (param.name.len > 0) { try writer.print(" {s}", .{param.name}); } } } try writer.writeAll(") {\n"); // Void all parameters to avoid unused warnings for (func.params) |param| { if (param.name.len > 0) { try writer.print(" (void){s};\n", .{param.name}); } } // Return appropriate default value const return_value = getDefaultReturnValue(func.return_type); if (return_value.len > 0) { try writer.print(" return {s};\n", .{return_value}); } try writer.writeAll("}\n\n"); } fn getDefaultReturnValue(return_type: []const u8) []const u8 { const trimmed = std.mem.trim(u8, return_type, " \t"); if (std.mem.eql(u8, trimmed, "void")) { return ""; } // Check for pointer types if (std.mem.indexOf(u8, trimmed, "*") != null) { return "NULL"; } // Check for bool if (std.mem.eql(u8, trimmed, "bool") or std.mem.eql(u8, trimmed, "SDL_bool")) { return "false"; } // Check for integer types if (std.mem.indexOf(u8, trimmed, "int") != null or std.mem.startsWith(u8, trimmed, "Uint") or std.mem.startsWith(u8, trimmed, "Sint") or std.mem.eql(u8, trimmed, "size_t")) { return "0"; } // Check for float types if (std.mem.eql(u8, trimmed, "float") or std.mem.eql(u8, trimmed, "double")) { return "0.0"; } // For enum/struct types, return zero return "0"; } };