Add capture syntax

This commit is contained in:
jaina heartles 2022-11-16 00:01:45 -08:00
parent 9d74bce266
commit 8ebe77541f
2 changed files with 33 additions and 17 deletions

View file

@ -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 {

View file

@ -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>