authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-05-20 10:52:49 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-05-20 10:52:49 -07:00
log7062632e64ba10c8d18c53586b02eb015fe43ba9
treeb784b2c53a38786f1aec75382ea39139146e3d17
parent6eac31e028be7d8972590ca342e33bda882f813c

put Ctx inside DoOptions


1 files changed, 44 insertions(+), 36 deletions(-)

src/lib.zig+44-36
...@@ -22,7 +22,8 @@ pub fn parse(comptime input: string) astgen.Value {...@@ -22,7 +22,8 @@ pub fn parse(comptime input: string) astgen.Value {
2222
23pub fn compile(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype) !void {23pub fn compile(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype) !void {
24 try writer.writeAll("<!DOCTYPE html>\n");24 try writer.writeAll("<!DOCTYPE html>\n");
25 try do(Ctx, alloc, writer, value, data, data, .{25 try do(alloc, writer, value, data, data, .{
26 .Ctx = Ctx,
26 .indent = 0,27 .indent = 0,
27 .flag1 = false,28 .flag1 = false,
28 });29 });
...@@ -31,10 +32,10 @@ pub fn compile(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, co...@@ -31,10 +32,10 @@ pub fn compile(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, co
3132
32pub const Writer = std.ArrayList(u8).Writer;33pub const Writer = std.ArrayList(u8).Writer;
3334
34inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype, opts: DoOptions) anyerror!void {35inline fn do(alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype, comptime opts: DoOptions) anyerror!void {
35 switch (comptime value) {36 switch (comptime value) {
36 .element => |v| {37 .element => |v| {
37 const hastext = for (v.children) |x| {38 const hastext = comptime for (v.children) |x| {
38 switch (x) {39 switch (x) {
39 .string, .replacement, .function => break true,40 .string, .replacement, .function => break true,
40 .element, .attr, .block, .body => {},41 .element, .attr, .block, .body => {},
...@@ -50,7 +51,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp...@@ -50,7 +51,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp
50 .string => try writer.print(" {s}=\"{}\"", .{ it.key, std.zig.fmtEscapes(it.value.string[1 .. it.value.string.len - 1]) }),51 .string => try writer.print(" {s}=\"{}\"", .{ it.key, std.zig.fmtEscapes(it.value.string[1 .. it.value.string.len - 1]) }),
51 .body => {52 .body => {
52 try writer.print(" {s}=\"", .{it.key});53 try writer.print(" {s}=\"", .{it.key});
53 try do(Ctx, alloc, writer, astgen.Value{ .body = it.value.body }, data, ctx, opts);54 try do(alloc, writer, astgen.Value{ .body = it.value.body }, data, ctx, opts);
54 try writer.print("\"", .{});55 try writer.print("\"", .{});
55 },56 },
56 }57 }
...@@ -67,7 +68,8 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp...@@ -67,7 +68,8 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp
6768
68 if (!hastext) try writer.writeAll("\n");69 if (!hastext) try writer.writeAll("\n");
69 inline for (v.children) |it| {70 inline for (v.children) |it| {
70 try do(Ctx, alloc, writer, it, data, ctx, .{71 try do(alloc, writer, it, data, ctx, .{
72 .Ctx = opts.Ctx,
71 .indent = opts.indent + 1,73 .indent = opts.indent + 1,
72 .flag1 = !hastext,74 .flag1 = !hastext,
73 });75 });
...@@ -117,25 +119,25 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp...@@ -117,25 +119,25 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp
117 switch (v.name) {119 switch (v.name) {
118 .each => {120 .each => {
119 comptime assertEqual(v.args.len, 1);121 comptime assertEqual(v.args.len, 1);
120 for (x) |item| try do(Ctx, alloc, writer, body, item, ctx, opts);122 for (x) |item| try do(alloc, writer, body, item, ctx, opts);
121 },123 },
122 .@"if" => {124 .@"if" => {
123 comptime assertEqual(v.args.len, 1);125 comptime assertEqual(v.args.len, 1);
124 if (comptime std.meta.trait.isIndexable(T)) {126 if (comptime std.meta.trait.isIndexable(T)) {
125 try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x.len > 0);127 try doif(alloc, writer, body, bottom, data, ctx, opts, x.len > 0);
126 return;128 return;
127 }129 }
128 switch (comptime TI) {130 switch (comptime TI) {
129 .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x),131 .Bool => try doif(alloc, writer, body, bottom, data, ctx, opts, x),
130 .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, opts, x),132 .Optional => try docap(alloc, writer, body, bottom, data, ctx, opts, x),
131 else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #if block", .{@typeName(T)})),133 else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #if block", .{@typeName(T)})),
132 }134 }
133 },135 },
134 .ifnot => {136 .ifnot => {
135 comptime assertEqual(v.args.len, 1);137 comptime assertEqual(v.args.len, 1);
136 switch (comptime TI) {138 switch (comptime TI) {
137 .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, !x),139 .Bool => try doif(alloc, writer, body, bottom, data, ctx, opts, !x),
138 .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, opts, !x),140 .Optional => try docap(alloc, writer, body, bottom, data, ctx, opts, !x),
139 else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #ifnot block", .{@typeName(T)})),141 else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #ifnot block", .{@typeName(T)})),
140 }142 }
141 },143 },
...@@ -143,31 +145,31 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp...@@ -143,31 +145,31 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp
143 comptime assertEqual(v.args.len, 2);145 comptime assertEqual(v.args.len, 2);
144 const y = if (comptime std.mem.eql(u8, v.args[1][0], "this")) search(v.args[1][1..], data) else search(v.args[1], ctx);146 const y = if (comptime std.mem.eql(u8, v.args[1][0], "this")) search(v.args[1][1..], data) else search(v.args[1], ctx);
145 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {147 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {
146 return try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));148 return try doif(alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));
147 }149 }
148 try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x == y);150 try doif(alloc, writer, body, bottom, data, ctx, opts, x == y);
149 },151 },
150 .ifnotequal => {152 .ifnotequal => {
151 comptime assertEqual(v.args.len, 2);153 comptime assertEqual(v.args.len, 2);
152 const y = if (comptime std.mem.eql(u8, v.args[1][0], "this")) search(v.args[1][1..], data) else search(v.args[1], ctx);154 const y = if (comptime std.mem.eql(u8, v.args[1][0], "this")) search(v.args[1][1..], data) else search(v.args[1], ctx);
153 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {155 if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) {
154 return try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));156 return try doif(alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y));
155 }157 }
156 try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x != y);158 try doif(alloc, writer, body, bottom, data, ctx, opts, x != y);
157 },159 },
158 }160 }
159 },161 },
160 .body => |v| {162 .body => |v| {
161 inline for (v) |val| {163 inline for (v) |val| {
162 try do(Ctx, alloc, writer, val, data, ctx, opts);164 try do(alloc, writer, val, data, ctx, opts);
163 }165 }
164 },166 },
165 .function => |v| {167 .function => |v| {
166 var arena = std.heap.ArenaAllocator.init(alloc);168 var arena = std.heap.ArenaAllocator.init(alloc);
167 defer arena.deinit();169 defer arena.deinit();
168170
169 if (!v.raw and @hasDecl(Ctx, "pek_" ++ v.name)) {171 if (!v.raw and @hasDecl(opts.Ctx, "pek_" ++ v.name)) {
170 const func = @field(Ctx, "pek_" ++ v.name);172 const func = @field(opts.Ctx, "pek_" ++ v.name);
171 var list = std.ArrayList(u8).init(arena.allocator());173 var list = std.ArrayList(u8).init(arena.allocator());
172 errdefer list.deinit();174 errdefer list.deinit();
173 var args: std.meta.ArgsTuple(@TypeOf(func)) = undefined;175 var args: std.meta.ArgsTuple(@TypeOf(func)) = undefined;
...@@ -179,30 +181,35 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp...@@ -179,30 +181,35 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp
179 }181 }
180 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };182 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };
181 try @call(.auto, func, args);183 try @call(.auto, func, args);
182 try do(Ctx, alloc, writer, repvalue, try list.toOwnedSlice(), ctx, opts);184 try do(alloc, writer, repvalue, try list.toOwnedSlice(), ctx, opts);
183 return;185 return;
184 }186 }
185 if (v.raw and @hasDecl(Ctx, "pek__" ++ v.name)) {187 if (v.raw and @hasDecl(opts.Ctx, "pek__" ++ v.name)) {
186 const func = @field(Ctx, "pek__" ++ v.name);188 const func = @field(opts.Ctx, "pek__" ++ v.name);
187 var list = std.ArrayList(u8).init(arena.allocator());189 var list = std.ArrayList(u8).init(arena.allocator());
188 errdefer list.deinit();190 errdefer list.deinit();
189 var args: std.meta.ArgsTuple(@TypeOf(func)) = undefined;191 const AT = std.meta.ArgsTuple(@TypeOf(func));
190 args.@"0" = alloc;192 const ATT = std.meta.fieldInfo(AT, .@"3").type;
191 args.@"1" = list.writer();193 var tupargs = @as(ATT, undefined);
192 args[2] = opts;194 var args = .{
195 alloc,
196 list.writer(),
197 opts,
198 tupargs,
199 };
193 inline for (v.args, 0..) |arg, i| {200 inline for (v.args, 0..) |arg, i| {
194 const field_name = comptime std.fmt.comptimePrint("{d}", .{i + 3});201 const field_name = comptime std.fmt.comptimePrint("{d}", .{i});
195 @field(args, field_name) = if (comptime std.mem.eql(u8, arg[0], "this")) search(arg[1..], data) else search(arg, ctx);202 @field(args[3], field_name) = if (comptime std.mem.eql(u8, arg[0], "this")) search(arg[1..], data) else search(arg, ctx);
196 }203 }
197 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };204 const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } };
198 try @call(.auto, func, args);205 try @call(.auto, func, args);
199 try do(Ctx, alloc, writer, repvalue, try list.toOwnedSlice(), ctx, opts);206 try do(alloc, writer, repvalue, try list.toOwnedSlice(), ctx, opts);
200 return;207 return;
201 }208 }
202 if (v.raw and @hasDecl(Ctx, "pek_" ++ v.name)) {209 if (v.raw and @hasDecl(opts.Ctx, "pek_" ++ v.name)) {
203 @compileError("pek: attempted to call safe custom function: '" ++ v.name ++ "' but did not use '{" ++ v.name ++ "}'");210 @compileError("pek: attempted to call safe custom function: '" ++ v.name ++ "' but did not use '{" ++ v.name ++ "}'");
204 }211 }
205 if (!v.raw and @hasDecl(Ctx, "pek__" ++ v.name)) {212 if (!v.raw and @hasDecl(opts.Ctx, "pek__" ++ v.name)) {
206 @compileError("pek: attempted to call raw custom function: '_" ++ v.name ++ "' but did not use '{#" ++ v.name ++ "}'");213 @compileError("pek: attempted to call raw custom function: '_" ++ v.name ++ "' but did not use '{#" ++ v.name ++ "}'");
207 }214 }
208 @compileError("pek: unknown custom function: " ++ v.name);215 @compileError("pek: unknown custom function: " ++ v.name);
...@@ -212,6 +219,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp...@@ -212,6 +219,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp
212}219}
213220
214pub const DoOptions = struct {221pub const DoOptions = struct {
222 Ctx: type,
215 indent: usize,223 indent: usize,
216 flag1: bool,224 flag1: bool,
217};225};
...@@ -328,18 +336,18 @@ fn contains(haystack: []const string, needle: string) bool {...@@ -328,18 +336,18 @@ fn contains(haystack: []const string, needle: string) bool {
328 return false;336 return false;
329}337}
330338
331fn doif(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, opts: DoOptions, flag2: bool) anyerror!void {339fn doif(alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, comptime opts: DoOptions, flag2: bool) anyerror!void {
332 if (flag2) {340 if (flag2) {
333 try do(Ctx, alloc, writer, top, data, ctx, opts);341 try do(alloc, writer, top, data, ctx, opts);
334 } else {342 } else {
335 try do(Ctx, alloc, writer, bottom, data, ctx, opts);343 try do(alloc, writer, bottom, data, ctx, opts);
336 }344 }
337}345}
338346
339fn docap(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, opts: DoOptions, flag2: anytype) anyerror!void {347fn docap(alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, comptime opts: DoOptions, flag2: anytype) anyerror!void {
340 if (flag2) |_| {348 if (flag2) |_| {
341 try do(Ctx, alloc, writer, top, data, ctx, opts);349 try do(alloc, writer, top, data, ctx, opts);
342 } else {350 } else {
343 try do(Ctx, alloc, writer, bottom, data, ctx, opts);351 try do(alloc, writer, bottom, data, ctx, opts);
344 }352 }
345}353}