mirror of
https://github.com/lightpanda-io/browser.git
synced 2025-10-28 22:53:28 +00:00
Add generate function for Tuple
Signed-off-by: Francis Bouvier <francis.bouvier@gmail.com>
This commit is contained in:
69
src/dom.zig
69
src/dom.zig
@@ -1,3 +1,5 @@
|
||||
const generate = @import("generate.zig");
|
||||
|
||||
const Console = @import("jsruntime").Console;
|
||||
|
||||
// DOM
|
||||
@@ -12,7 +14,7 @@ pub const HTMLDocument = @import("html/document.zig").HTMLDocument;
|
||||
const E = @import("html/elements.zig");
|
||||
|
||||
// Interfaces
|
||||
pub const Interfaces = .{
|
||||
const interfaces = .{
|
||||
Console,
|
||||
|
||||
// DOM
|
||||
@@ -23,69 +25,8 @@ pub const Interfaces = .{
|
||||
|
||||
// HTML
|
||||
HTMLDocument,
|
||||
|
||||
E.HTMLElement,
|
||||
E.HTMLMediaElement,
|
||||
|
||||
// TODO: generate HTMLElements comptime
|
||||
E.HTMLUnknownElement,
|
||||
E.HTMLAnchorElement,
|
||||
E.HTMLAreaElement,
|
||||
E.HTMLAudioElement,
|
||||
E.HTMLBRElement,
|
||||
E.HTMLBaseElement,
|
||||
E.HTMLBodyElement,
|
||||
E.HTMLButtonElement,
|
||||
E.HTMLCanvasElement,
|
||||
E.HTMLDListElement,
|
||||
E.HTMLDialogElement,
|
||||
E.HTMLDataElement,
|
||||
E.HTMLDivElement,
|
||||
E.HTMLEmbedElement,
|
||||
E.HTMLFieldSetElement,
|
||||
E.HTMLFormElement,
|
||||
E.HTMLFrameSetElement,
|
||||
E.HTMLHRElement,
|
||||
E.HTMLHeadElement,
|
||||
E.HTMLHeadingElement,
|
||||
E.HTMLHtmlElement,
|
||||
E.HTMLIFrameElement,
|
||||
E.HTMLImageElement,
|
||||
E.HTMLInputElement,
|
||||
E.HTMLLIElement,
|
||||
E.HTMLLabelElement,
|
||||
E.HTMLLegendElement,
|
||||
E.HTMLLinkElement,
|
||||
E.HTMLMapElement,
|
||||
E.HTMLMetaElement,
|
||||
E.HTMLMeterElement,
|
||||
E.HTMLModElement,
|
||||
E.HTMLOListElement,
|
||||
E.HTMLObjectElement,
|
||||
E.HTMLOptGroupElement,
|
||||
E.HTMLOptionElement,
|
||||
E.HTMLOutputElement,
|
||||
E.HTMLParagraphElement,
|
||||
E.HTMLPictureElement,
|
||||
E.HTMLPreElement,
|
||||
E.HTMLProgressElement,
|
||||
E.HTMLQuoteElement,
|
||||
E.HTMLScriptElement,
|
||||
E.HTMLSelectElement,
|
||||
E.HTMLSourceElement,
|
||||
E.HTMLSpanElement,
|
||||
E.HTMLStyleElement,
|
||||
E.HTMLTableElement,
|
||||
E.HTMLTableCaptionElement,
|
||||
E.HTMLTableCellElement,
|
||||
E.HTMLTableColElement,
|
||||
E.HTMLTableRowElement,
|
||||
E.HTMLTableSectionElement,
|
||||
E.HTMLTemplateElement,
|
||||
E.HTMLTextAreaElement,
|
||||
E.HTMLTimeElement,
|
||||
E.HTMLTitleElement,
|
||||
E.HTMLTrackElement,
|
||||
E.HTMLUListElement,
|
||||
E.HTMLVideoElement,
|
||||
E.HTMLElementsTypes,
|
||||
};
|
||||
pub const Interfaces = generate.TupleInst(generate.TupleT(interfaces), interfaces);
|
||||
|
||||
149
src/generate.zig
149
src/generate.zig
@@ -6,6 +6,8 @@ fn fmtName(comptime T: type) []const u8 {
|
||||
return it.first();
|
||||
}
|
||||
|
||||
// Generate a flatten tagged Union from various structs and union of structs
|
||||
// TODO: make this function more generic
|
||||
pub const Union = struct {
|
||||
_enum: type,
|
||||
_union: type,
|
||||
@@ -23,7 +25,7 @@ pub const Union = struct {
|
||||
const tuple_T = @TypeOf(tuple);
|
||||
const tuple_info = @typeInfo(tuple_T);
|
||||
if (tuple_info != .Struct or !tuple_info.Struct.is_tuple) {
|
||||
return error.GenerateUnionArgNotTuple;
|
||||
return error.GenerateArgNotTuple;
|
||||
}
|
||||
|
||||
const tuple_members = tuple_info.Struct.fields;
|
||||
@@ -39,7 +41,7 @@ pub const Union = struct {
|
||||
} else if (member_info == .Struct) {
|
||||
members_nb += 1;
|
||||
} else {
|
||||
return error.GenerateUnionMemberNotUnionOrStruct;
|
||||
return error.GenerateMemberNotUnionOrStruct;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +66,7 @@ pub const Union = struct {
|
||||
} else if (members_nb < 65536) {
|
||||
tag_type = u16;
|
||||
} else {
|
||||
return error.GenerateUnionTooMuchMembers;
|
||||
return error.GenerateTooMuchMembers;
|
||||
}
|
||||
|
||||
// second iteration to generate tags
|
||||
@@ -100,7 +102,7 @@ pub const Union = struct {
|
||||
};
|
||||
const enum_T = @Type(std.builtin.Type{ .Enum = enum_info });
|
||||
|
||||
// third iteration to generate union
|
||||
// third iteration to generate union type
|
||||
comptime var union_fields: [members_nb]std.builtin.Type.UnionField = undefined;
|
||||
done = 0;
|
||||
inline for (tuple_members) |member, i| {
|
||||
@@ -141,13 +143,123 @@ pub const Union = struct {
|
||||
}
|
||||
};
|
||||
|
||||
fn itoa(comptime i: u8) ![]u8 {
|
||||
comptime {
|
||||
var len: usize = undefined;
|
||||
if (i < 10) {
|
||||
len = 1;
|
||||
} else if (i < 100) {
|
||||
len = 2;
|
||||
} else {
|
||||
return error.GenerateTooMuchMembers;
|
||||
}
|
||||
var buf: [len]u8 = undefined;
|
||||
return try std.fmt.bufPrint(buf[0..], "{d}", .{i});
|
||||
}
|
||||
}
|
||||
|
||||
// Generate a flatten tuple type from various structs and tuple of structs.
|
||||
// TODO: make this function more generic
|
||||
pub fn TupleT(comptime tuple: anytype) type {
|
||||
|
||||
// check types provided
|
||||
const tuple_T = @TypeOf(tuple);
|
||||
const tuple_info = @typeInfo(tuple_T);
|
||||
if (tuple_info != .Struct or !tuple_info.Struct.is_tuple) {
|
||||
@compileError("GenerateArgNotTuple");
|
||||
}
|
||||
|
||||
const tuple_members = tuple_info.Struct.fields;
|
||||
|
||||
// first iteration to get the total number of members
|
||||
comptime var members_nb = 0;
|
||||
for (tuple_members) |member| {
|
||||
const member_T = @field(tuple, member.name);
|
||||
if (@TypeOf(member_T) == type) {
|
||||
members_nb += 1;
|
||||
} else {
|
||||
const member_info = @typeInfo(@TypeOf(member_T));
|
||||
if (member_info != .Struct and !member_info.Struct.is_tuple) {
|
||||
@compileError("GenerateMemberNotTypeOrTuple");
|
||||
}
|
||||
for (member_info.Struct.fields) |field| {
|
||||
if (@TypeOf(@field(member_T, field.name)) != type) {
|
||||
@compileError("GenerateMemberTupleChildNotType");
|
||||
}
|
||||
}
|
||||
members_nb += member_info.Struct.fields.len;
|
||||
}
|
||||
}
|
||||
|
||||
// second iteration to generate the tuple type
|
||||
var fields: [members_nb]std.builtin.Type.StructField = undefined;
|
||||
var done = 0;
|
||||
while (done < members_nb) {
|
||||
fields[done] = .{
|
||||
.name = try itoa(done),
|
||||
.field_type = type,
|
||||
.default_value = null,
|
||||
.is_comptime = false,
|
||||
.alignment = @alignOf(type),
|
||||
};
|
||||
done += 1;
|
||||
}
|
||||
const decls: [0]std.builtin.Type.Declaration = undefined;
|
||||
const info = std.builtin.Type.Struct{
|
||||
.layout = .Auto,
|
||||
.fields = &fields,
|
||||
.decls = &decls,
|
||||
.is_tuple = true,
|
||||
};
|
||||
return @Type(std.builtin.Type{ .Struct = info });
|
||||
}
|
||||
|
||||
// Instantiate a flatten tuple from various structs and tuple of structs
|
||||
// You need to call first TupleT to generate the according type
|
||||
// TODO: make this function more generic
|
||||
pub fn TupleInst(comptime T: type, comptime tuple: anytype) T {
|
||||
|
||||
// check types provided
|
||||
const tuple_T = @TypeOf(tuple);
|
||||
const tuple_info = @typeInfo(tuple_T);
|
||||
const tuple_members = tuple_info.Struct.fields;
|
||||
|
||||
// instantiate the tuple
|
||||
var t: T = undefined;
|
||||
var done = 0;
|
||||
for (tuple_members) |member| {
|
||||
const member_T = @field(tuple, member.name);
|
||||
var member_info: std.builtin.Type = undefined;
|
||||
if (@TypeOf(member_T) == type) {
|
||||
member_info = @typeInfo(member_T);
|
||||
} else {
|
||||
member_info = @typeInfo(@TypeOf(member_T));
|
||||
}
|
||||
var member_detail = member_info.Struct;
|
||||
if (member_detail.is_tuple) {
|
||||
for (member_detail.fields) |field| {
|
||||
const name = try itoa(done);
|
||||
@field(t, name) = @field(member_T, field.name);
|
||||
done += 1;
|
||||
}
|
||||
} else {
|
||||
const name = try itoa(done);
|
||||
@field(t, name) = @field(tuple, member.name);
|
||||
done += 1;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
// Tests
|
||||
// -----
|
||||
|
||||
const Error = error{
|
||||
UnionArgNotTuple,
|
||||
UnionMemberNotUnionOrStruct,
|
||||
UnionTooMuchMembers,
|
||||
GenerateArgNotTuple,
|
||||
GenerateMemberNotUnionOrStruct,
|
||||
GenerateMemberNotTupleOrStruct,
|
||||
GenerateMemberTupleNotStruct,
|
||||
GenerateTooMuchMembers,
|
||||
};
|
||||
|
||||
const Astruct = struct {
|
||||
@@ -200,4 +312,27 @@ pub fn tests() !void {
|
||||
try std.testing.expectEqualStrings(from_mix_union.Union.fields[3].name, "Dstruct");
|
||||
|
||||
std.debug.print("Generate Union: OK\n", .{});
|
||||
|
||||
// Tuple from structs
|
||||
const tuple_structs = .{ Astruct, Bstruct };
|
||||
const tFromStructs = TupleInst(TupleT(tuple_structs), tuple_structs);
|
||||
const t_from_structs = @typeInfo(@TypeOf(tFromStructs));
|
||||
try std.testing.expect(t_from_structs == .Struct);
|
||||
try std.testing.expect(t_from_structs.Struct.is_tuple);
|
||||
try std.testing.expect(t_from_structs.Struct.fields.len == 2);
|
||||
try std.testing.expect(@field(tFromStructs, "0") == Astruct);
|
||||
try std.testing.expect(@field(tFromStructs, "1") == Bstruct);
|
||||
|
||||
// Tuple from tuple and structs
|
||||
const tuple_mix = .{ tFromStructs, Cstruct };
|
||||
const tFromMix = TupleInst(TupleT(tuple_mix), tuple_mix);
|
||||
const t_from_mix = @typeInfo(@TypeOf(tFromMix));
|
||||
try std.testing.expect(t_from_mix == .Struct);
|
||||
try std.testing.expect(t_from_mix.Struct.is_tuple);
|
||||
try std.testing.expect(t_from_mix.Struct.fields.len == 3);
|
||||
try std.testing.expect(@field(tFromMix, "0") == Astruct);
|
||||
try std.testing.expect(@field(tFromMix, "1") == Bstruct);
|
||||
try std.testing.expect(@field(tFromMix, "2") == Cstruct);
|
||||
|
||||
std.debug.print("Generate Tuple: OK\n", .{});
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ pub const HTMLElement = struct {
|
||||
}
|
||||
};
|
||||
|
||||
const HTMLElementsTypes = .{
|
||||
pub const HTMLElementsTypes = .{
|
||||
HTMLUnknownElement,
|
||||
HTMLAnchorElement,
|
||||
HTMLAreaElement,
|
||||
@@ -78,10 +78,7 @@ const HTMLElementsTypes = .{
|
||||
HTMLUListElement,
|
||||
HTMLVideoElement,
|
||||
};
|
||||
fn generateElements() generate.Union {
|
||||
return generate.Union.compile(HTMLElementsTypes);
|
||||
}
|
||||
const HTMLElementsGenerated = generateElements();
|
||||
const HTMLElementsGenerated = generate.Union.compile(HTMLElementsTypes);
|
||||
pub const HTMLElements = HTMLElementsGenerated._union;
|
||||
pub const HTMLElementsTags = HTMLElementsGenerated._enum;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user