Add equals operator to template engine

This commit is contained in:
jaina heartles 2022-12-10 00:02:04 -08:00
parent aee81e27b6
commit 4e3450de4e
2 changed files with 50 additions and 9 deletions

View file

@ -15,6 +15,7 @@ pub fn main() !void {
.bar = .{ .x = "x" },
.qux = false,
.quxx = true,
.quxx2 = true,
.maybe_foo = @as(?[]const u8, "foo"),
.maybe_bar = @as(?[]const u8, null),
.x = "y",
@ -168,6 +169,7 @@ fn EvaluateExpression(
.arg_deref => |names| Deref(Args, names),
.capture_deref => |names| Deref(Captures, names),
.context_deref => |names| Deref(Context, names),
.equals => bool,
};
}
@ -181,6 +183,16 @@ fn evaluateExpression(
.arg_deref => |names| deref(args, names),
.capture_deref => |names| deref(captures, names),
.context_deref => |names| deref(context, names),
.equals => |eql| {
const lhs = evaluateExpression(eql.lhs, args, captures, context);
const rhs = evaluateExpression(eql.rhs, args, captures, context);
const T = @TypeOf(lhs, rhs);
if (comptime std.meta.trait.isZigString(T)) {
return std.mem.eql(u8, lhs, rhs);
} else if (comptime std.meta.trait.isContainer(T) and @hasDecl(T, "eql")) {
return T.eql(lhs, rhs);
} else return lhs == rhs;
},
};
}
@ -400,29 +412,50 @@ fn parseExpression(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIt
comptime {
var iter = tokens;
var expr: Expression = while (iter.next()) |token| switch (token) {
var last_valid_iter: ?ControlTokenIter = null;
var expr: ?Expression = null;
while (iter.next()) |token| switch (token) {
.whitespace => {},
.period => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .arg_deref = names.item };
expr = .{ .arg_deref = names.item };
last_valid_iter = iter;
},
.dollar => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .capture_deref = names.item };
expr = .{ .capture_deref = names.item };
last_valid_iter = iter;
},
.percent => {
const names = parseDeref(iter);
iter = names.new_iter;
break .{ .context_deref = names.item };
expr = .{ .context_deref = names.item };
last_valid_iter = iter;
},
else => @compileError("TODO"),
.equals => {
const next = iter.next() orelse break;
if (next == .equals) {
const lhs = expr orelse break;
const rhs = parseExpression(iter);
iter = rhs.new_iter;
expr = .{
.equals = &.{
.lhs = lhs,
.rhs = rhs.item,
},
};
last_valid_iter = iter;
} else break;
},
else => break,
};
return .{
.new_iter = iter,
.item = expr,
.new_iter = last_valid_iter orelse @compileError("Invalid Expression"),
.item = expr orelse @compileError("Invalid Expression"),
};
}
}
@ -518,7 +551,7 @@ fn parseControlBlock(comptime tokens: ControlTokenIter) ParseResult(ControlToken
},
else => {
@compileLog(iter.row);
@compileError("TODO" ++ @tagName(token));
@compileError("TODO " ++ @tagName(token) ++ " " ++ token.text);
},
};
@ -702,10 +735,16 @@ const TemplateItem = union(enum) {
statement: Statement,
};
const EqualsExpr = struct {
lhs: Expression,
rhs: Expression,
};
const Expression = union(enum) {
arg_deref: []const []const u8,
capture_deref: []const []const u8,
context_deref: []const []const u8,
equals: *const EqualsExpr,
};
const For = struct {
@ -830,7 +869,7 @@ const ControlTokenIter = struct {
},
else => {
var idx: usize = 0;
while (idx < remaining.len and std.mem.indexOfScalar(u8, "{}.#|$/=@ \t\n\r", remaining[idx]) == null) : (idx += 1) {}
while (idx < remaining.len and std.mem.indexOfScalar(u8, "{}.#|$/=@,% \t\n\r", remaining[idx]) == null) : (idx += 1) {}
self.start += idx - 1;
return .{ .text = remaining[0..idx] };

View file

@ -14,6 +14,8 @@
{$b}:
{= /for =}
{= /for}
{#if .quxx == .quxx2}eql{#else}neq{/if}
{#if .quxx == .qux}eql{#else}neq{/if}
{#if .qux=}
qux
{=#elif .quxx=}