Add capture syntax
This commit is contained in:
parent
9d74bce266
commit
8ebe77541f
2 changed files with 33 additions and 17 deletions
|
@ -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 {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
<h2> {{ REAL BRACKETS }} </h2>
|
||||
|
||||
<section>
|
||||
{$bar}
|
||||
{#for .foo |$f|}a testing thing {#end_for}
|
||||
{{#for args.notes |$note, $i|}}
|
||||
<h3>Note no. {{$i}}</h3>
|
||||
|
|
Loading…
Reference in a new issue