| ... | @@ -22,13 +22,16 @@ pub fn parse(comptime input: string) astgen.Value { | ... | @@ -22,13 +22,16 @@ pub fn parse(comptime input: string) astgen.Value { |
| 22 | | 22 | |
| 23 | pub fn compile(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype) !void { | 23 | pub 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, 0, false); | 25 | try do(Ctx, alloc, writer, value, data, data, .{ |
| | 26 | .indent = 0, |
| | 27 | .flag1 = false, |
| | 28 | }); |
| 26 | try writer.writeAll("\n"); | 29 | try writer.writeAll("\n"); |
| 27 | } | 30 | } |
| 28 | | 31 | |
| 29 | pub const Writer = std.ArrayList(u8).Writer; | 32 | pub const Writer = std.ArrayList(u8).Writer; |
| 30 | | 33 | |
| 31 | inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype, indent: usize, flag1: bool) anyerror!void { | 34 | inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime value: astgen.Value, data: anytype, ctx: anytype, opts: DoOptions) anyerror!void { |
| 32 | switch (comptime value) { | 35 | switch (comptime value) { |
| 33 | .element => |v| { | 36 | .element => |v| { |
| 34 | const hastext = for (v.children) |x| { | 37 | const hastext = for (v.children) |x| { |
| ... | @@ -38,7 +41,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp | ... | @@ -38,7 +41,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 38 | } | 41 | } |
| 39 | } else false; | 42 | } else false; |
| 40 | | 43 | |
| 41 | if (flag1) for (range(indent)) |_| try writer.writeAll(" "); | 44 | if (opts.flag1) for (range(opts.indent)) |_| try writer.writeAll(" "); |
| 42 | try writer.writeAll("<"); | 45 | try writer.writeAll("<"); |
| 43 | try writer.writeAll(v.name); | 46 | try writer.writeAll(v.name); |
| 44 | | 47 | |
| ... | @@ -47,7 +50,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp | ... | @@ -47,7 +50,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 47 | .string => try writer.print(" {s}=\"{}\"", .{ it.key, std.zig.fmtEscapes(it.value.string[1 .. it.value.string.len - 1]) }), | 50 | .string => try writer.print(" {s}=\"{}\"", .{ it.key, std.zig.fmtEscapes(it.value.string[1 .. it.value.string.len - 1]) }), |
| 48 | .body => { | 51 | .body => { |
| 49 | try writer.print(" {s}=\"", .{it.key}); | 52 | try writer.print(" {s}=\"", .{it.key}); |
| 50 | try do(Ctx, alloc, writer, astgen.Value{ .body = it.value.body }, data, ctx, indent, flag1); | 53 | try do(Ctx, alloc, writer, astgen.Value{ .body = it.value.body }, data, ctx, opts); |
| 51 | try writer.print("\"", .{}); | 54 | try writer.print("\"", .{}); |
| 52 | }, | 55 | }, |
| 53 | } | 56 | } |
| ... | @@ -64,11 +67,14 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp | ... | @@ -64,11 +67,14 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 64 | | 67 | |
| 65 | if (!hastext) try writer.writeAll("\n"); | 68 | if (!hastext) try writer.writeAll("\n"); |
| 66 | inline for (v.children) |it| { | 69 | inline for (v.children) |it| { |
| 67 | try do(Ctx, alloc, writer, it, data, ctx, indent + 1, !hastext); | 70 | try do(Ctx, alloc, writer, it, data, ctx, .{ |
| | 71 | .indent = opts.indent + 1, |
| | 72 | .flag1 = !hastext, |
| | 73 | }); |
| 68 | } | 74 | } |
| 69 | if (!hastext) for (range(indent)) |_| try writer.writeAll(" "); | 75 | if (!hastext) for (range(opts.indent)) |_| try writer.writeAll(" "); |
| 70 | try writer.print("</{s}>", .{v.name}); | 76 | try writer.print("</{s}>", .{v.name}); |
| 71 | if (flag1) try writer.writeAll("\n"); | 77 | if (opts.flag1) try writer.writeAll("\n"); |
| 72 | } | 78 | } |
| 73 | }, | 79 | }, |
| 74 | .string => |v| { | 80 | .string => |v| { |
| ... | @@ -111,25 +117,25 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp | ... | @@ -111,25 +117,25 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 111 | switch (v.name) { | 117 | switch (v.name) { |
| 112 | .each => { | 118 | .each => { |
| 113 | comptime assertEqual(v.args.len, 1); | 119 | comptime assertEqual(v.args.len, 1); |
| 114 | for (x) |item| try do(Ctx, alloc, writer, body, item, ctx, indent, flag1); | 120 | for (x) |item| try do(Ctx, alloc, writer, body, item, ctx, opts); |
| 115 | }, | 121 | }, |
| 116 | .@"if" => { | 122 | .@"if" => { |
| 117 | comptime assertEqual(v.args.len, 1); | 123 | comptime assertEqual(v.args.len, 1); |
| 118 | if (comptime std.meta.trait.isIndexable(T)) { | 124 | if (comptime std.meta.trait.isIndexable(T)) { |
| 119 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x.len > 0); | 125 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x.len > 0); |
| 120 | return; | 126 | return; |
| 121 | } | 127 | } |
| 122 | switch (comptime TI) { | 128 | switch (comptime TI) { |
| 123 | .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x), | 129 | .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x), |
| 124 | .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x), | 130 | .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, opts, x), |
| 125 | else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #if block", .{@typeName(T)})), | 131 | else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #if block", .{@typeName(T)})), |
| 126 | } | 132 | } |
| 127 | }, | 133 | }, |
| 128 | .ifnot => { | 134 | .ifnot => { |
| 129 | comptime assertEqual(v.args.len, 1); | 135 | comptime assertEqual(v.args.len, 1); |
| 130 | switch (comptime TI) { | 136 | switch (comptime TI) { |
| 131 | .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, !x), | 137 | .Bool => try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, !x), |
| 132 | .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, !x), | 138 | .Optional => try docap(Ctx, alloc, writer, body, bottom, data, ctx, opts, !x), |
| 133 | else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #ifnot block", .{@typeName(T)})), | 139 | else => @compileError(std.fmt.comptimePrint("pek: unable to use '{s}' in an #ifnot block", .{@typeName(T)})), |
| 134 | } | 140 | } |
| 135 | }, | 141 | }, |
| ... | @@ -137,23 +143,23 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp | ... | @@ -137,23 +143,23 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 137 | comptime assertEqual(v.args.len, 2); | 143 | comptime assertEqual(v.args.len, 2); |
| 138 | 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); | 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); |
| 139 | if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) { | 145 | if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) { |
| 140 | return try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, std.mem.eql(u8, @tagName(x), y)); | 146 | return try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y)); |
| 141 | } | 147 | } |
| 142 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x == y); | 148 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x == y); |
| 143 | }, | 149 | }, |
| 144 | .ifnotequal => { | 150 | .ifnotequal => { |
| 145 | comptime assertEqual(v.args.len, 2); | 151 | comptime assertEqual(v.args.len, 2); |
| 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); | 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); |
| 147 | if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) { | 153 | if (@typeInfo(@TypeOf(x)) == .Enum and comptime std.meta.trait.isZigString(@TypeOf(y))) { |
| 148 | return try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, std.mem.eql(u8, @tagName(x), y)); | 154 | return try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, std.mem.eql(u8, @tagName(x), y)); |
| 149 | } | 155 | } |
| 150 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, indent, flag1, x != y); | 156 | try doif(Ctx, alloc, writer, body, bottom, data, ctx, opts, x != y); |
| 151 | }, | 157 | }, |
| 152 | } | 158 | } |
| 153 | }, | 159 | }, |
| 154 | .body => |v| { | 160 | .body => |v| { |
| 155 | inline for (v) |val| { | 161 | inline for (v) |val| { |
| 156 | try do(Ctx, alloc, writer, val, data, ctx, indent, flag1); | 162 | try do(Ctx, alloc, writer, val, data, ctx, opts); |
| 157 | } | 163 | } |
| 158 | }, | 164 | }, |
| 159 | .function => |v| { | 165 | .function => |v| { |
| ... | @@ -173,7 +179,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp | ... | @@ -173,7 +179,7 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 173 | } | 179 | } |
| 174 | const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } }; | 180 | const repvalue = astgen.Value{ .replacement = .{ .arms = &.{"this"}, .raw = v.raw } }; |
| 175 | try @call(.auto, func, args); | 181 | try @call(.auto, func, args); |
| 176 | try do(Ctx, alloc, writer, repvalue, try list.toOwnedSlice(), ctx, indent, flag1); | 182 | try do(Ctx, alloc, writer, repvalue, try list.toOwnedSlice(), ctx, opts); |
| 177 | return; | 183 | return; |
| 178 | } | 184 | } |
| 179 | @compileError("pek: unknown custom function: " ++ v.name); | 185 | @compileError("pek: unknown custom function: " ++ v.name); |
| ... | @@ -182,6 +188,11 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp | ... | @@ -182,6 +188,11 @@ inline fn do(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comp |
| 182 | } | 188 | } |
| 183 | } | 189 | } |
| 184 | | 190 | |
| | 191 | pub const DoOptions = struct { |
| | 192 | indent: usize, |
| | 193 | flag1: bool, |
| | 194 | }; |
| | 195 | |
| 185 | fn search(comptime args: []const string, ctx: anytype) FieldSearch(@TypeOf(ctx), args) { | 196 | fn search(comptime args: []const string, ctx: anytype) FieldSearch(@TypeOf(ctx), args) { |
| 186 | if (args.len == 0) return ctx; | 197 | if (args.len == 0) return ctx; |
| 187 | if (args[0][0] == '"') return std.mem.trim(u8, args[0], "\""); | 198 | if (args[0][0] == '"') return std.mem.trim(u8, args[0], "\""); |
| ... | @@ -289,18 +300,18 @@ fn contains(haystack: []const string, needle: string) bool { | ... | @@ -289,18 +300,18 @@ fn contains(haystack: []const string, needle: string) bool { |
| 289 | return false; | 300 | return false; |
| 290 | } | 301 | } |
| 291 | | 302 | |
| 292 | fn doif(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, indent: usize, flag1: bool, flag2: bool) anyerror!void { | 303 | fn 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 { |
| 293 | if (flag2) { | 304 | if (flag2) { |
| 294 | try do(Ctx, alloc, writer, top, data, ctx, indent, flag1); | 305 | try do(Ctx, alloc, writer, top, data, ctx, opts); |
| 295 | } else { | 306 | } else { |
| 296 | try do(Ctx, alloc, writer, bottom, data, ctx, indent, flag1); | 307 | try do(Ctx, alloc, writer, bottom, data, ctx, opts); |
| 297 | } | 308 | } |
| 298 | } | 309 | } |
| 299 | | 310 | |
| 300 | fn docap(comptime Ctx: type, alloc: std.mem.Allocator, writer: anytype, comptime top: astgen.Value, comptime bottom: astgen.Value, data: anytype, ctx: anytype, indent: usize, flag1: bool, flag2: anytype) anyerror!void { | 311 | fn 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 { |
| 301 | if (flag2) |_| { | 312 | if (flag2) |_| { |
| 302 | try do(Ctx, alloc, writer, top, data, ctx, indent, flag1); | 313 | try do(Ctx, alloc, writer, top, data, ctx, opts); |
| 303 | } else { | 314 | } else { |
| 304 | try do(Ctx, alloc, writer, bottom, data, ctx, indent, flag1); | 315 | try do(Ctx, alloc, writer, bottom, data, ctx, opts); |
| 305 | } | 316 | } |
| 306 | } | 317 | } |