Add @isTag builtin
This commit is contained in:
parent
4e3450de4e
commit
b2007131c8
2 changed files with 90 additions and 1 deletions
|
@ -1,6 +1,7 @@
|
|||
const std = @import("std");
|
||||
|
||||
pub fn main() !void {
|
||||
const Enum = enum { foo, bar };
|
||||
try execute(
|
||||
std.io.getStdOut().writer(),
|
||||
.{ .test_tmpl = "{.x} {%context_foo}" },
|
||||
|
@ -18,6 +19,7 @@ pub fn main() !void {
|
|||
.quxx2 = true,
|
||||
.maybe_foo = @as(?[]const u8, "foo"),
|
||||
.maybe_bar = @as(?[]const u8, null),
|
||||
.snap = Enum.bar,
|
||||
.x = "y",
|
||||
},
|
||||
.{
|
||||
|
@ -170,6 +172,9 @@ fn EvaluateExpression(
|
|||
.capture_deref => |names| Deref(Captures, names),
|
||||
.context_deref => |names| Deref(Context, names),
|
||||
.equals => bool,
|
||||
.builtin => |call| switch (call.*) {
|
||||
.isTag => bool,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -193,6 +198,12 @@ fn evaluateExpression(
|
|||
return T.eql(lhs, rhs);
|
||||
} else return lhs == rhs;
|
||||
},
|
||||
.builtin => |call| switch (call.*) {
|
||||
.isTag => |hdr| {
|
||||
const val = evaluateExpression(hdr.expression, args, captures, context);
|
||||
return std.meta.isTag(val, hdr.tag);
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -402,6 +413,8 @@ fn parseTemplateTokens(comptime tokens: ControlTokenIter) []const TemplateToken
|
|||
.at => items = items ++ [_]TemplateToken{.{ .text = "@" }},
|
||||
.comma => items = items ++ [_]TemplateToken{.{ .text = "," }},
|
||||
.percent => items = items ++ [_]TemplateToken{.{ .text = "%" }},
|
||||
.open_paren => items = items ++ [_]TemplateToken{.{ .text = "(" }},
|
||||
.close_paren => items = items ++ [_]TemplateToken{.{ .text = ")" }},
|
||||
};
|
||||
|
||||
return items;
|
||||
|
@ -419,18 +432,21 @@ fn parseExpression(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIt
|
|||
.period => {
|
||||
const names = parseDeref(iter);
|
||||
iter = names.new_iter;
|
||||
if (expr != null) break;
|
||||
expr = .{ .arg_deref = names.item };
|
||||
last_valid_iter = iter;
|
||||
},
|
||||
.dollar => {
|
||||
const names = parseDeref(iter);
|
||||
iter = names.new_iter;
|
||||
if (expr != null) break;
|
||||
expr = .{ .capture_deref = names.item };
|
||||
last_valid_iter = iter;
|
||||
},
|
||||
.percent => {
|
||||
const names = parseDeref(iter);
|
||||
iter = names.new_iter;
|
||||
if (expr != null) break;
|
||||
expr = .{ .context_deref = names.item };
|
||||
last_valid_iter = iter;
|
||||
},
|
||||
|
@ -450,6 +466,13 @@ fn parseExpression(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIt
|
|||
last_valid_iter = iter;
|
||||
} else break;
|
||||
},
|
||||
.at => {
|
||||
if (expr != null) break;
|
||||
const builtin = parseBuiltin(iter);
|
||||
iter = builtin.new_iter;
|
||||
expr = .{ .builtin = &builtin.item };
|
||||
last_valid_iter = iter;
|
||||
},
|
||||
else => break,
|
||||
};
|
||||
|
||||
|
@ -460,6 +483,54 @@ fn parseExpression(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIt
|
|||
}
|
||||
}
|
||||
|
||||
fn expectToken(comptime token: ?ControlToken, comptime exp: std.meta.Tag(ControlToken)) void {
|
||||
comptime {
|
||||
if (token == null) @compileError("Unexpected End Of Template");
|
||||
const token_tag = std.meta.activeTag(token.?);
|
||||
|
||||
if (token_tag != exp)
|
||||
@compileError("Expected " ++ @tagName(exp) ++ ", got " ++ @tagName(token_tag));
|
||||
}
|
||||
}
|
||||
|
||||
fn parseBuiltin(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIter, BuiltinCall) {
|
||||
comptime {
|
||||
var iter = tokens;
|
||||
const builtin = blk: {
|
||||
const next = iter.next() orelse @compileError("Invalid Builtin");
|
||||
if (next != .text) @compileError("Invalid Builtin");
|
||||
break :blk std.meta.stringToEnum(Builtin, next.text) orelse @compileError("Invalid Builtin");
|
||||
};
|
||||
|
||||
iter = skipWhitespace(iter);
|
||||
expectToken(iter.next(), .open_paren);
|
||||
iter = skipWhitespace(iter);
|
||||
const call = switch (builtin) {
|
||||
.isTag => blk: {
|
||||
const expr = parseExpression(iter);
|
||||
iter = expr.new_iter;
|
||||
expectToken(iter.next(), .comma);
|
||||
iter = skipWhitespace(iter);
|
||||
const tag = iter.next();
|
||||
expectToken(tag, .text);
|
||||
break :blk .{
|
||||
.isTag = .{
|
||||
.tag = tag.?.text,
|
||||
.expression = expr.item,
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
iter = skipWhitespace(iter);
|
||||
expectToken(iter.next(), .close_paren);
|
||||
|
||||
return .{
|
||||
.new_iter = iter,
|
||||
.item = call,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn parseControlBlock(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIter, ControlBlock) {
|
||||
comptime {
|
||||
var iter = tokens;
|
||||
|
@ -745,6 +816,7 @@ const Expression = union(enum) {
|
|||
capture_deref: []const []const u8,
|
||||
context_deref: []const []const u8,
|
||||
equals: *const EqualsExpr,
|
||||
builtin: *const BuiltinCall,
|
||||
};
|
||||
|
||||
const For = struct {
|
||||
|
@ -812,6 +884,17 @@ const EndKeyword = enum {
|
|||
@"if",
|
||||
};
|
||||
|
||||
const Builtin = enum {
|
||||
isTag,
|
||||
};
|
||||
|
||||
const BuiltinCall = union(Builtin) {
|
||||
isTag: struct {
|
||||
tag: []const u8,
|
||||
expression: Expression,
|
||||
},
|
||||
};
|
||||
|
||||
const ControlToken = union(enum) {
|
||||
text: []const u8,
|
||||
open_bracket: void,
|
||||
|
@ -826,6 +909,8 @@ const ControlToken = union(enum) {
|
|||
at: void,
|
||||
comma: void,
|
||||
percent: void,
|
||||
open_paren: void,
|
||||
close_paren: void,
|
||||
};
|
||||
|
||||
const ControlTokenIter = struct {
|
||||
|
@ -858,6 +943,8 @@ const ControlTokenIter = struct {
|
|||
'@' => return .{ .at = {} },
|
||||
',' => return .{ .comma = {} },
|
||||
'%' => return .{ .percent = {} },
|
||||
'(' => return .{ .open_paren = {} },
|
||||
')' => return .{ .close_paren = {} },
|
||||
' ', '\t', '\n', '\r' => {
|
||||
var idx: usize = 0;
|
||||
while (idx < remaining.len and std.mem.indexOfScalar(u8, " \t\n\r", remaining[idx]) != null) : (idx += 1) {}
|
||||
|
@ -869,7 +956,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] };
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
{= /for}
|
||||
{#if .quxx == .quxx2}eql{#else}neq{/if}
|
||||
{#if .quxx == .qux}eql{#else}neq{/if}
|
||||
{#if @isTag(.snap, foo)}foo{/if}
|
||||
{#if @isTag(.snap, bar)}bar{/if}
|
||||
{#if .qux=}
|
||||
qux
|
||||
{=#elif .quxx=}
|
||||
|
|
Loading…
Reference in a new issue