update: add clone function

This commit is contained in:
Lucas F. 2026-01-11 20:36:49 -03:00
parent a55831d0ce
commit cba0c8d749
2 changed files with 358 additions and 4 deletions

View file

@ -81,6 +81,7 @@ pub fn build(b: *std.Build) void {
.{ .name = "zdt_prov", .module = mod },
},
}),
.use_llvm = true,
});
// This declares intent for the executable to be installed into the

View file

@ -236,6 +236,7 @@ pub const Node = struct {
.tag => if (self.tag) |t| {
allocator.free(t.name);
allocator.free(t.args);
allocator.free(t.raw);
},
.if_block => if (self.@"if") |ib| {
allocator.free(ib.condition);
@ -245,6 +246,8 @@ pub const Node = struct {
const false_copy = ib.false_body;
for (false_copy) |n| n.deinit(allocator);
allocator.free(ib.false_body);
allocator.free(ib.raw_open);
allocator.free(ib.raw_close);
},
.for_block => if (self.@"for") |fb| {
allocator.free(fb.loop_var);
@ -255,7 +258,10 @@ pub const Node = struct {
const empty_copy = fb.empty_body;
for (empty_copy) |n| n.deinit(allocator);
allocator.free(fb.empty_body);
allocator.free(fb.raw_open);
allocator.free(fb.raw_close);
},
.include => if (self.include) |inc| allocator.free(inc.template_name),
.with_block => if (self.with) |w| {
for (w.assignments) |a| {
allocator.free(a.key);
@ -265,13 +271,20 @@ pub const Node = struct {
const body_copy = w.body;
for (body_copy) |n| n.deinit(allocator);
allocator.free(w.body);
allocator.free(w.raw_open);
allocator.free(w.raw_close);
},
.now => if (self.now) |n| allocator.free(n.format),
.extends => if (self.extends) |e| allocator.free(e.parent_name),
.block => if (self.block) |b| {
allocator.free(b.name);
const body_copy = b.body;
for (body_copy) |n| n.deinit(allocator);
allocator.free(b.body);
allocator.free(b.raw_open);
allocator.free(b.raw_close);
},
.super => {},
.filter_block => if (self.filter_block) |fb| {
allocator.free(fb.filters);
const body_copy = fb.body;
@ -282,16 +295,16 @@ pub const Node = struct {
const body_copy = ae.body;
for (body_copy) |n| n.deinit(allocator);
allocator.free(ae.body);
allocator.free(ae.raw_open);
allocator.free(ae.raw_close);
},
.spaceless => if (self.spaceless) |sl| {
const body_copy = sl.body;
for (body_copy) |n| n.deinit(allocator);
allocator.free(sl.body);
allocator.free(sl.raw_open);
allocator.free(sl.raw_close);
},
.include => if (self.include) |inc| allocator.free(inc.template_name),
.now => if (self.now) |n| allocator.free(n.format),
.extends => if (self.extends) |e| allocator.free(e.parent_name),
.super => {},
.url => if (self.url) |u| {
allocator.free(u.name);
for (u.args) |a| allocator.free(a);
@ -318,6 +331,8 @@ pub const Node = struct {
.debug => {},
.partialdef => if (self.partialdef) |pd| {
allocator.free(pd.name);
allocator.free(pd.raw_open);
allocator.free(pd.raw_close);
for (pd.body) |n| n.deinit(allocator);
allocator.free(pd.body);
},
@ -344,6 +359,344 @@ pub const Node = struct {
.templatetag => {},
}
}
pub fn clone(self: Node, allocator: std.mem.Allocator) !Node {
switch (self.type) {
.text => {
return Node{
.type = .text,
.text = .{ .content = try allocator.dupe(u8, self.text.?.content) },
};
},
.variable => {
const filters_copy = try allocator.alloc(Filter, self.variable.?.filters.len);
errdefer allocator.free(filters_copy);
for (self.variable.?.filters, 0..) |f, i| {
filters_copy[i] = .{
.name = try allocator.dupe(u8, f.name),
.arg = if (f.arg) |a| try allocator.dupe(u8, a) else null,
};
}
return Node{
.type = .variable,
.variable = .{
.expr = try allocator.dupe(u8, self.variable.?.expr),
.filters = filters_copy,
},
};
},
.if_block => {
const true_body_copy = try allocator.alloc(Node, self.@"if".?.true_body.len);
errdefer allocator.free(true_body_copy);
for (self.@"if".?.true_body, 0..) |child, j| {
true_body_copy[j] = try child.clone(allocator);
}
const false_body_copy = try allocator.alloc(Node, self.@"if".?.false_body.len);
errdefer allocator.free(false_body_copy);
for (self.@"if".?.false_body, 0..) |child, j| {
false_body_copy[j] = try child.clone(allocator);
}
return Node{
.type = .if_block,
.@"if" = .{
.condition = try allocator.dupe(u8, self.@"if".?.condition),
.true_body = true_body_copy,
.false_body = false_body_copy,
.raw_open = try allocator.dupe(u8, self.@"if".?.raw_open),
.raw_close = try allocator.dupe(u8, self.@"if".?.raw_close),
},
};
},
.for_block => {
const body_copy = try allocator.alloc(Node, self.@"for".?.body.len);
errdefer allocator.free(body_copy);
for (self.@"for".?.body, 0..) |child, j| {
body_copy[j] = try child.clone(allocator);
}
const empty_body_copy = try allocator.alloc(Node, self.@"for".?.empty_body.len);
errdefer allocator.free(empty_body_copy);
for (self.@"for".?.empty_body, 0..) |child, j| {
empty_body_copy[j] = try child.clone(allocator);
}
return Node{
.type = .for_block,
.@"for" = .{
.loop_var = try allocator.dupe(u8, self.@"for".?.loop_var),
.iterable = try allocator.dupe(u8, self.@"for".?.iterable),
.body = body_copy,
.empty_body = empty_body_copy,
.raw_open = try allocator.dupe(u8, self.@"for".?.raw_open),
.raw_close = try allocator.dupe(u8, self.@"for".?.raw_close),
},
};
},
.block => {
const body_copy = try allocator.alloc(Node, self.block.?.body.len);
errdefer allocator.free(body_copy);
for (self.block.?.body, 0..) |child, j| {
body_copy[j] = try child.clone(allocator);
}
return Node{
.type = .block,
.block = .{
.name = try allocator.dupe(u8, self.block.?.name),
.body = body_copy,
.raw_open = try allocator.dupe(u8, self.block.?.raw_open),
.raw_close = try allocator.dupe(u8, self.block.?.raw_close),
},
};
},
.extends => {
return Node{
.type = .extends,
.extends = .{
.parent_name = try allocator.dupe(u8, self.extends.?.parent_name),
},
};
},
.super => {
return Node{
.type = .super,
};
},
.tag => {
return Node{
.type = .tag,
.tag = .{
.name = try allocator.dupe(u8, self.tag.?.name),
.args = try allocator.dupe(u8, self.tag.?.args),
.raw = try allocator.dupe(u8, self.tag.?.raw),
},
};
},
.include => {
return Node{
.type = .include,
.include = .{
.template_name = try allocator.dupe(u8, self.include.?.template_name),
},
};
},
.with_block => {
const body_copy = try allocator.alloc(Node, self.block.?.body.len);
errdefer allocator.free(body_copy);
for (self.block.?.body, 0..) |child, j| {
body_copy[j] = try child.clone(allocator);
}
const assignments_copy = try allocator.alloc(Assignment, self.with.?.assignments.len);
errdefer allocator.free(assignments_copy);
for (self.with.?.assignments, 0..) |f, i| {
assignments_copy[i] = .{
.key = try allocator.dupe(u8, f.key),
.value_expr = try allocator.dupe(u8, f.value_expr),
.is_literal = f.is_literal,
};
}
return Node{
.type = .with_block,
.with = .{
.assignments = assignments_copy,
.body = body_copy,
.raw_open = try allocator.dupe(u8, self.with.?.raw_open),
.raw_close = try allocator.dupe(u8, self.with.?.raw_close),
},
};
},
.now => {
return Node{ .type = .now, .now = .{ .format = try allocator.dupe(u8, self.now.?.format) } };
},
.filter_block => {
const body_copy = try allocator.alloc(Node, self.filter_block.?.body.len);
errdefer allocator.free(body_copy);
for (self.filter_block.?.body, 0..) |child, j| {
body_copy[j] = try child.clone(allocator);
}
return Node{
.type = .filter_block,
.filter_block = .{
.filters = try allocator.dupe(u8, self.filter_block.?.filters),
.body = body_copy,
.raw_open = try allocator.dupe(u8, self.filter_block.?.raw_open),
.raw_close = try allocator.dupe(u8, self.filter_block.?.raw_close),
},
};
},
.autoescape => {
const body_copy = try allocator.alloc(Node, self.autoescape.?.body.len);
errdefer allocator.free(body_copy);
for (self.autoescape.?.body, 0..) |child, j| {
body_copy[j] = try child.clone(allocator);
}
return Node{
.type = .autoescape,
.autoescape = .{
.body = body_copy,
.raw_open = try allocator.dupe(u8, self.autoescape.?.raw_open),
.raw_close = try allocator.dupe(u8, self.autoescape.?.raw_close),
.enabled = self.autoescape.?.enabled,
},
};
},
.spaceless => {
const body_copy = try allocator.alloc(Node, self.spaceless.?.body.len);
errdefer allocator.free(body_copy);
for (self.spaceless.?.body, 0..) |child, j| {
body_copy[j] = try child.clone(allocator);
}
return Node{
.type = .spaceless,
.spaceless = .{
.body = body_copy,
.raw_open = try allocator.dupe(u8, self.spaceless.?.raw_open),
.raw_close = try allocator.dupe(u8, self.spaceless.?.raw_close),
},
};
},
.url => {
const args_copy = try allocator.alloc([]const u8, self.url.?.args.len);
errdefer allocator.free(args_copy);
for (self.url.?.args, 0..) |f, i| {
args_copy[i] = try allocator.dupe(u8, f);
}
return Node{ .type = .url, .url = .{
.name = try allocator.dupe(u8, self.url.?.name),
.args = args_copy,
} };
},
.cycle => {
const values_copy = try allocator.alloc([]const u8, self.cycle.?.values.len);
errdefer allocator.free(values_copy);
for (self.cycle.?.values, 0..) |f, i| {
values_copy[i] = try allocator.dupe(u8, f);
}
return Node{ .type = .cycle, .cycle = .{ .values = values_copy } };
},
.firstof => {
const values_copy = try allocator.alloc([]const u8, self.firstof.?.values.len);
errdefer allocator.free(values_copy);
for (self.firstof.?.values, 0..) |f, i| {
values_copy[i] = try allocator.dupe(u8, f);
}
return Node{ .type = .firstof, .firstof = .{ .values = values_copy } };
},
.load => {
const libraries_copy = try allocator.alloc([]const u8, self.load.?.libraries.len);
errdefer allocator.free(libraries_copy);
for (self.load.?.libraries, 0..) |f, i| {
libraries_copy[i] = try allocator.dupe(u8, f);
}
return Node{ .type = .load, .load = .{ .libraries = libraries_copy } };
},
.csrf_token => {
return Node{
.type = .csrf_token,
};
},
.lorem => {
return Node{
.type = .lorem,
.lorem = .{
.count = if (self.lorem.?.count) |c| try allocator.dupe(u8, c) else null,
.method = if (self.lorem.?.method) |m| try allocator.dupe(u8, m) else null,
.format = if (self.lorem.?.format) |f| try allocator.dupe(u8, f) else null,
},
};
},
.debug => {
return Node{ .type = .debug };
},
.partialdef => {
const body_copy = try allocator.alloc(Node, self.partialdef.?.body.len);
errdefer allocator.free(body_copy);
for (self.partialdef.?.body, 0..) |child, j| {
body_copy[j] = try child.clone(allocator);
}
return Node{ .type = .partialdef, .partialdef = .{
.name = try allocator.dupe(u8, self.partialdef.?.name),
.body = body_copy,
.raw_open = try allocator.dupe(u8, self.partialdef.?.raw_open),
.raw_close = try allocator.dupe(u8, self.partialdef.?.raw_close),
} };
},
.partial => {
return Node{ .type = .partial, .partial = .{
.name = try allocator.dupe(u8, self.partial.?.name),
} };
},
.querystring => {
const modifications = try allocator.alloc([]const u8, self.querystring.?.modifications.len);
errdefer allocator.free(modifications);
for (self.querystring.?.modifications, 0..) |f, i| {
modifications[i] = try allocator.dupe(u8, f);
}
return Node{ .type = .querystring, .querystring = .{
.modifications = modifications,
} };
},
.regroup => {
return Node{ .type = .regroup, .regroup = .{
.source = try allocator.dupe(u8, self.regroup.?.source),
.by = try allocator.dupe(u8, self.regroup.?.by),
.as_var = try allocator.dupe(u8, self.regroup.?.as_var),
} };
},
.resetcycle => {
return Node{ .type = .resetcycle, .resetcycle = .{
.cycle_name = if (self.resetcycle.?.cycle_name) |n| try allocator.dupe(u8, n) else null,
} };
},
.widthratio => {
return Node{ .type = .widthratio, .widthratio = .{
.value = try allocator.dupe(u8, self.widthratio.?.value),
.max_value = try allocator.dupe(u8, self.widthratio.?.max_value),
.divisor = if (self.widthratio.?.divisor) |d| try allocator.dupe(u8, d) else null,
} };
},
.templatetag => {
return Node{ .type = .templatetag, .templatetag = .{ .kind = self.templatetag.?.kind } };
},
}
}
};
pub const Parser = struct {