diff --git a/src/template/lib.zig b/src/template/lib.zig index 07a93b5..dd48587 100644 --- a/src/template/lib.zig +++ b/src/template/lib.zig @@ -12,31 +12,40 @@ const logging = false; pub fn execute(writer: anytype, comptime template: []const u8, args: anytype) !void { @setEvalBranchQuota(@intCast(u32, template.len * 6)); const tmpl = comptime parseTemplate(TokenIter{ .text = template }, .root); - try executeTemplate(writer, tmpl.item, args); + try executeTemplate(writer, tmpl.item, args, .{ .bar = "abc" }); } -fn executeTemplate(writer: anytype, comptime items: []const TemplateItem, args: anytype) !void { +fn executeTemplate(writer: anytype, comptime items: []const TemplateItem, args: anytype, captures: anytype) !void { inline for (items) |it| switch (it) { .text => |text| try writer.writeAll(text), - .statement => |stmt| try executeStatement(writer, stmt, args), + .statement => |stmt| try executeStatement(writer, stmt, args, captures), }; } -fn executeStatement(writer: anytype, comptime stmt: Statement, args: anytype) !void { +fn executeStatement(writer: anytype, comptime stmt: Statement, args: anytype, captures: anytype) !void { switch (stmt) { .expression => |expr| switch (expr) { .arg_deref => |fields| { - const arg = argDeref(args, fields); + const arg = deref(args, fields); + try print(writer, arg); + }, + .capture_deref => |fields| { + const arg = deref(captures, fields); try print(writer, arg); }, }, .for_loop => |loop| { const fields = loop.iterable.arg_deref; - const iterable = argDeref(args, fields); + const iterable = deref(args, fields); const subtemplate = loop.subtemplate; try writer.writeAll("capture on " ++ loop.capture ++ ": "); for (iterable) |_| { - try executeTemplate(writer, subtemplate, args); + try executeTemplate( + writer, + subtemplate, + args, + captures, + ); } }, else => @compileError("TODO"), @@ -49,7 +58,7 @@ fn print(writer: anytype, arg: anytype) !void { @compileError("TODO"); } -fn ArgDeref(comptime T: type, comptime names: []const []const u8) type { +fn Deref(comptime T: type, comptime names: []const []const u8) type { if (names.len == 0) return T; // Compiler segfaults when I use std.meta to get this info so we search it manually @@ -57,12 +66,12 @@ fn ArgDeref(comptime T: type, comptime names: []const []const u8) type { if (std.mem.eql(u8, f.name, names[0])) break f; } else @compileError("Unknown field " ++ names[0] ++ " in type " ++ @typeName(T)); - return ArgDeref(field.field_type, names[1..]); + return Deref(field.field_type, names[1..]); } -fn argDeref(arg: anytype, comptime names: []const []const u8) ArgDeref(@TypeOf(arg), names) { +fn deref(arg: anytype, comptime names: []const []const u8) Deref(@TypeOf(arg), names) { if (names.len == 0) return arg; - return argDeref(@field(arg, names[0]), names[1..]); + return deref(@field(arg, names[0]), names[1..]); } const TemplateType = enum { @@ -146,9 +155,14 @@ fn parseStatement(comptime tokens: TokenIter) ParseResult(Statement) { } }, .period => { - const expr = parseArgDeref(iter); - iter = expr.new_iter; - break .{ .expression = .{ .arg_deref = expr.item } }; + const names = parseDeref(iter); + iter = names.new_iter; + break .{ .expression = .{ .arg_deref = names.item } }; + }, + .dollar => { + const names = parseDeref(iter); + iter = names.new_iter; + break .{ .expression = .{ .capture_deref = names.item } }; }, else => @compileError(""), }; @@ -229,8 +243,8 @@ fn parseExpression(comptime tokens: TokenIter) ParseResult(Expression) { while (iter.next()) |token| switch (token) { .whitespace => {}, .period => { - const deref = parseArgDeref(iter); - return .{ .new_iter = deref.new_iter, .item = .{ .arg_deref = deref.item } }; + const names = parseDeref(iter); + return .{ .new_iter = names.new_iter, .item = .{ .arg_deref = names.item } }; }, else => @compileError("Expected Expression"), }; @@ -239,7 +253,7 @@ fn parseExpression(comptime tokens: TokenIter) ParseResult(Expression) { } } -fn parseArgDeref(comptime tokens: TokenIter) ParseResult([]const []const u8) { +fn parseDeref(comptime tokens: TokenIter) ParseResult([]const []const u8) { comptime { var iter = tokens; var fields: []const []const u8 = &.{}; @@ -280,6 +294,7 @@ const TemplateItem = union(enum) { const Expression = union(enum) { arg_deref: []const []const u8, + capture_deref: []const []const u8, }; const ForLoop = struct { diff --git a/src/template/test.tmp.html b/src/template/test.tmp.html index 2f39f2a..7b7e597 100644 --- a/src/template/test.tmp.html +++ b/src/template/test.tmp.html @@ -9,6 +9,7 @@