Add loop index capture support

This commit is contained in:
jaina heartles 2022-12-14 02:35:23 -08:00
parent f2a23db588
commit 73ba42d2d5
2 changed files with 18 additions and 26 deletions

View File

@ -82,13 +82,15 @@ fn executeStatement(
const iterable = try evaluateExpression(loop.header.iterable, args, captures, context); const iterable = try evaluateExpression(loop.header.iterable, args, captures, context);
const subtemplate = loop.subtemplate; const subtemplate = loop.subtemplate;
//std.log.debug("{any}", .{subtemplate}); //std.log.debug("{any}", .{subtemplate});
for (iterable) |v| { for (iterable) |v, i| {
const with_item_capture = addCapture(captures, loop.header.item_capture, v);
const with_idx_capture = if (comptime loop.header.idx_capture) |name| addCapture(with_item_capture, name, i) else with_item_capture;
try executeTemplate( try executeTemplate(
writer, writer,
templates, templates,
subtemplate, subtemplate,
args, args,
addCapture(captures, loop.header.capture, v), with_idx_capture,
context, context,
); );
} }
@ -227,7 +229,7 @@ fn EvaluateExpression(
const T = EvaluateExpression(expr.container, Args, Captures, Context); const T = EvaluateExpression(expr.container, Args, Captures, Context);
for (@typeInfo(T).Struct.fields) |f| { for (@typeInfo(T).Struct.fields) |f| {
if (std.mem.eql(u8, expr.field, f.name)) return f.field_type; if (std.mem.eql(u8, expr.field, f.name)) return f.field_type;
} } else @compileError("Field " ++ expr.field ++ " does not exist on type " ++ @typeName(T));
}, },
.equals => bool, .equals => bool,
.builtin => |call| switch (call.*) { .builtin => |call| switch (call.*) {
@ -875,32 +877,21 @@ fn endControlBlock(comptime tokens: ControlTokenIter) ControlTokenIter {
fn parseForHeader(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIter, ForHeader) { fn parseForHeader(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIter, ForHeader) {
comptime { comptime {
const iterable = parseExpression(tokens); const iterable = parseExpression(tokens);
var iter = iterable.new_iter; var iter = skipWhitespace(iterable.new_iter);
iter = skipWhitespace(iter); const captures = tryParseCapture(iter) orelse {
{ @compileLog(iter.row);
const token = iter.next() orelse @compileError("Unexpected end of template"); @compileError("Expected capture");
if (token != .pipe) @compileError("Unexpected token");
}
{
const token = iter.next() orelse @compileError("Unexpected end of template");
if (token != .dollar) @compileError("Unexpected token");
}
const capture = blk: {
const token = iter.next() orelse @compileError("Unexpected end of template");
if (token != .text) @compileError("Unexpected token");
break :blk token.text;
}; };
{
const token = iter.next() orelse @compileError("Unexpected end of template"); if (captures.item.len == 0 or captures.item.len > 2) @compileError("Expected 1 or 2 captures");
if (token != .pipe) @compileError("Unexpected token");
}
return .{ return .{
.new_iter = iter, .new_iter = captures.new_iter,
.item = .{ .item = .{
.iterable = iterable.item, .iterable = iterable.item,
.capture = capture, .item_capture = captures.item[0],
.idx_capture = if (captures.item.len == 2) captures.item[1] else null,
}, },
}; };
} }
@ -908,9 +899,8 @@ fn parseForHeader(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIte
fn tryParseCapture(comptime tokens: ControlTokenIter) ?ParseResult(ControlTokenIter, []const []const u8) { fn tryParseCapture(comptime tokens: ControlTokenIter) ?ParseResult(ControlTokenIter, []const []const u8) {
comptime { comptime {
var iter = tokens; var iter = skipWhitespace(tokens);
iter = skipWhitespace(iter);
if ((iter.next() orelse return null) != .pipe) return null; if ((iter.next() orelse return null) != .pipe) return null;
var captures: []const []const u8 = &.{}; var captures: []const []const u8 = &.{};
while (true) { while (true) {
@ -1115,7 +1105,8 @@ const For = struct {
const ForHeader = struct { const ForHeader = struct {
iterable: Expression, iterable: Expression,
capture: []const u8, item_capture: []const u8,
idx_capture: ?[]const u8,
}; };
const If = struct { const If = struct {

View File

@ -14,6 +14,7 @@
{$b}: {$b}:
{= /for =} {= /for =}
{= /for} {= /for}
{#for .baz |$f, $i| =}{$i}{/for}
{#if .quxx == .quxx2}eql{#else}neq{/if} {#if .quxx == .quxx2}eql{#else}neq{/if}
{#if .quxx == .qux}eql{#else}neq{/if} {#if .quxx == .qux}eql{#else}neq{/if}
{#if @isTag(.snap, foo)}foo{/if} {#if @isTag(.snap, foo)}foo{/if}