145 lines
4.5 KiB
Zig
145 lines
4.5 KiB
Zig
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 <stdint.h>
|
|
\\#include <stdbool.h>
|
|
\\#include <stddef.h>
|
|
\\
|
|
\\
|
|
;
|
|
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";
|
|
}
|
|
};
|