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" }, .bar = .{ .x = "x" },
.qux = false, .qux = false,
.quxx = true, .quxx = true,
.quxx2 = true,
.maybe_foo = @as(?[]const u8, "foo"), .maybe_foo = @as(?[]const u8, "foo"),
.maybe_bar = @as(?[]const u8, null), .maybe_bar = @as(?[]const u8, null),
.x = "y", .x = "y",
@ -168,6 +169,7 @@ fn EvaluateExpression(
.arg_deref => |names| Deref(Args, names), .arg_deref => |names| Deref(Args, names),
.capture_deref => |names| Deref(Captures, names), .capture_deref => |names| Deref(Captures, names),
.context_deref => |names| Deref(Context, names), .context_deref => |names| Deref(Context, names),
.equals => bool,
}; };
} }
@ -181,6 +183,16 @@ fn evaluateExpression(
.arg_deref => |names| deref(args, names), .arg_deref => |names| deref(args, names),
.capture_deref => |names| deref(captures, names), .capture_deref => |names| deref(captures, names),
.context_deref => |names| deref(context, 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 { comptime {
var iter = tokens; 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 => {}, .whitespace => {},
.period => { .period => {
const names = parseDeref(iter); const names = parseDeref(iter);
iter = names.new_iter; iter = names.new_iter;
break .{ .arg_deref = names.item }; expr = .{ .arg_deref = names.item };
last_valid_iter = iter;
}, },
.dollar => { .dollar => {
const names = parseDeref(iter); const names = parseDeref(iter);
iter = names.new_iter; iter = names.new_iter;
break .{ .capture_deref = names.item }; expr = .{ .capture_deref = names.item };
last_valid_iter = iter;
}, },
.percent => { .percent => {
const names = parseDeref(iter); const names = parseDeref(iter);
iter = names.new_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 .{ return .{
.new_iter = iter, .new_iter = last_valid_iter orelse @compileError("Invalid Expression"),
.item = expr, .item = expr orelse @compileError("Invalid Expression"),
}; };
} }
} }
@ -518,7 +551,7 @@ fn parseControlBlock(comptime tokens: ControlTokenIter) ParseResult(ControlToken
}, },
else => { else => {
@compileLog(iter.row); @compileLog(iter.row);
@compileError("TODO" ++ @tagName(token)); @compileError("TODO " ++ @tagName(token) ++ " " ++ token.text);
}, },
}; };
@ -702,10 +735,16 @@ const TemplateItem = union(enum) {
statement: Statement, statement: Statement,
}; };
const EqualsExpr = struct {
lhs: Expression,
rhs: Expression,
};
const Expression = union(enum) { const Expression = union(enum) {
arg_deref: []const []const u8, arg_deref: []const []const u8,
capture_deref: []const []const u8, capture_deref: []const []const u8,
context_deref: []const []const u8, context_deref: []const []const u8,
equals: *const EqualsExpr,
}; };
const For = struct { const For = struct {
@ -830,7 +869,7 @@ const ControlTokenIter = struct {
}, },
else => { else => {
var idx: usize = 0; 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; self.start += idx - 1;
return .{ .text = remaining[0..idx] }; return .{ .text = remaining[0..idx] };

View file

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