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 {
|
pub fn execute(writer: anytype, comptime template: []const u8, args: anytype) !void {
|
||||||
@setEvalBranchQuota(@intCast(u32, template.len * 6));
|
@setEvalBranchQuota(@intCast(u32, template.len * 6));
|
||||||
const tmpl = comptime parseTemplate(TokenIter{ .text = template }, .root);
|
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) {
|
inline for (items) |it| switch (it) {
|
||||||
.text => |text| try writer.writeAll(text),
|
.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) {
|
switch (stmt) {
|
||||||
.expression => |expr| switch (expr) {
|
.expression => |expr| switch (expr) {
|
||||||
.arg_deref => |fields| {
|
.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);
|
try print(writer, arg);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
.for_loop => |loop| {
|
.for_loop => |loop| {
|
||||||
const fields = loop.iterable.arg_deref;
|
const fields = loop.iterable.arg_deref;
|
||||||
const iterable = argDeref(args, fields);
|
const iterable = deref(args, fields);
|
||||||
const subtemplate = loop.subtemplate;
|
const subtemplate = loop.subtemplate;
|
||||||
try writer.writeAll("capture on " ++ loop.capture ++ ": ");
|
try writer.writeAll("capture on " ++ loop.capture ++ ": ");
|
||||||
for (iterable) |_| {
|
for (iterable) |_| {
|
||||||
try executeTemplate(writer, subtemplate, args);
|
try executeTemplate(
|
||||||
|
writer,
|
||||||
|
subtemplate,
|
||||||
|
args,
|
||||||
|
captures,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
else => @compileError("TODO"),
|
else => @compileError("TODO"),
|
||||||
|
@ -49,7 +58,7 @@ fn print(writer: anytype, arg: anytype) !void {
|
||||||
@compileError("TODO");
|
@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;
|
if (names.len == 0) return T;
|
||||||
|
|
||||||
// Compiler segfaults when I use std.meta to get this info so we search it manually
|
// 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;
|
if (std.mem.eql(u8, f.name, names[0])) break f;
|
||||||
} else @compileError("Unknown field " ++ names[0] ++ " in type " ++ @typeName(T));
|
} 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;
|
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 {
|
const TemplateType = enum {
|
||||||
|
@ -146,9 +155,14 @@ fn parseStatement(comptime tokens: TokenIter) ParseResult(Statement) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.period => {
|
.period => {
|
||||||
const expr = parseArgDeref(iter);
|
const names = parseDeref(iter);
|
||||||
iter = expr.new_iter;
|
iter = names.new_iter;
|
||||||
break .{ .expression = .{ .arg_deref = expr.item } };
|
break .{ .expression = .{ .arg_deref = names.item } };
|
||||||
|
},
|
||||||
|
.dollar => {
|
||||||
|
const names = parseDeref(iter);
|
||||||
|
iter = names.new_iter;
|
||||||
|
break .{ .expression = .{ .capture_deref = names.item } };
|
||||||
},
|
},
|
||||||
else => @compileError(""),
|
else => @compileError(""),
|
||||||
};
|
};
|
||||||
|
@ -229,8 +243,8 @@ fn parseExpression(comptime tokens: TokenIter) ParseResult(Expression) {
|
||||||
while (iter.next()) |token| switch (token) {
|
while (iter.next()) |token| switch (token) {
|
||||||
.whitespace => {},
|
.whitespace => {},
|
||||||
.period => {
|
.period => {
|
||||||
const deref = parseArgDeref(iter);
|
const names = parseDeref(iter);
|
||||||
return .{ .new_iter = deref.new_iter, .item = .{ .arg_deref = deref.item } };
|
return .{ .new_iter = names.new_iter, .item = .{ .arg_deref = names.item } };
|
||||||
},
|
},
|
||||||
else => @compileError("Expected Expression"),
|
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 {
|
comptime {
|
||||||
var iter = tokens;
|
var iter = tokens;
|
||||||
var fields: []const []const u8 = &.{};
|
var fields: []const []const u8 = &.{};
|
||||||
|
@ -280,6 +294,7 @@ const TemplateItem = union(enum) {
|
||||||
|
|
||||||
const Expression = union(enum) {
|
const Expression = union(enum) {
|
||||||
arg_deref: []const []const u8,
|
arg_deref: []const []const u8,
|
||||||
|
capture_deref: []const []const u8,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ForLoop = struct {
|
const ForLoop = struct {
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
<h2> {{ REAL BRACKETS }} </h2>
|
<h2> {{ REAL BRACKETS }} </h2>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
{$bar}
|
||||||
{#for .foo |$f|}a testing thing {#end_for}
|
{#for .foo |$f|}a testing thing {#end_for}
|
||||||
{{#for args.notes |$note, $i|}}
|
{{#for args.notes |$note, $i|}}
|
||||||
<h3>Note no. {{$i}}</h3>
|
<h3>Note no. {{$i}}</h3>
|
||||||
|
|
Loading…
Reference in a new issue