Add slice builtin

This commit is contained in:
jaina heartles 2022-12-14 00:46:24 -08:00
parent 0f5751e7ed
commit 1269aeeac1
2 changed files with 44 additions and 4 deletions

View file

@ -8,11 +8,13 @@ pub fn main() !void {
@embedFile("./test.tmp.html"), @embedFile("./test.tmp.html"),
.{ .{
.community = .{ .name = "<abcd>" }, .community = .{ .name = "<abcd>" },
.foo = [_][]const u8{ "5", "4", "3", "2", "1" }, .foo = &[_][]const u8{ "5", "4", "3", "2", "1" },
.baz = [_][]const []const u8{ .baz = &[_][]const []const u8{
&.{ "5", "4", "3", "2", "1" }, &.{ "5", "4", "3", "2", "1" },
&.{ "5", "4", "3", "2", "1" }, &.{ "5", "4", "3", "2", "1" },
}, },
.start = 1,
.end = 3,
.bar = .{ .x = "x" }, .bar = .{ .x = "x" },
.qux = false, .qux = false,
.quxx = true, .quxx = true,
@ -236,7 +238,7 @@ fn deref(arg: anytype, comptime names: []const DerefDecl) DerefError!Deref(@Type
} }
} }
const ExpressionError = DerefError; const ExpressionError = error{IndexOutOfBounds} || DerefError;
fn EvaluateExpression( fn EvaluateExpression(
comptime expression: Expression, comptime expression: Expression,
@ -251,6 +253,7 @@ fn EvaluateExpression(
.equals => bool, .equals => bool,
.builtin => |call| switch (call.*) { .builtin => |call| switch (call.*) {
.isTag => bool, .isTag => bool,
.slice => |sl| []const std.meta.Elem(EvaluateExpression(sl.iterable, Args, Captures, Context)),
}, },
}; };
} }
@ -280,6 +283,15 @@ fn evaluateExpression(
const val = try evaluateExpression(hdr.expression, args, captures, context); const val = try evaluateExpression(hdr.expression, args, captures, context);
return std.meta.isTag(val, hdr.tag); return std.meta.isTag(val, hdr.tag);
}, },
.slice => |sl| {
const iterable = try evaluateExpression(sl.iterable, args, captures, context);
const start = try evaluateExpression(sl.start, args, captures, context);
const end = try evaluateExpression(sl.end, args, captures, context);
if (comptime std.meta.trait.is(.Array)(@TypeOf(iterable))) @compileError("Cannot slice an array, pass a slice or pointer to array instead");
if (start > iterable.len or end > iterable.len) return error.IndexOutOfBounds;
return iterable[start..end];
},
}, },
}; };
} }
@ -635,7 +647,7 @@ fn parseBuiltin(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIter,
const call = switch (builtin) { const call = switch (builtin) {
.isTag => blk: { .isTag => blk: {
const expr = parseExpression(iter); const expr = parseExpression(iter);
iter = expr.new_iter; iter = skipWhitespace(expr.new_iter);
expectToken(iter.next(), .comma); expectToken(iter.next(), .comma);
iter = skipWhitespace(iter); iter = skipWhitespace(iter);
const tag = iter.next(); const tag = iter.next();
@ -647,6 +659,26 @@ fn parseBuiltin(comptime tokens: ControlTokenIter) ParseResult(ControlTokenIter,
}, },
}; };
}, },
.slice => blk: {
const expr = parseExpression(iter);
iter = skipWhitespace(expr.new_iter);
expectToken(iter.next(), .comma);
iter = skipWhitespace(iter);
const start = parseExpression(iter);
iter = skipWhitespace(start.new_iter);
expectToken(iter.next(), .comma);
iter = skipWhitespace(iter);
const end = parseExpression(iter);
iter = skipWhitespace(end.new_iter);
break :blk .{
.slice = .{
.iterable = expr.item,
.start = start.item,
.end = end.item,
},
};
},
}; };
iter = skipWhitespace(iter); iter = skipWhitespace(iter);
expectToken(iter.next(), .close_paren); expectToken(iter.next(), .close_paren);
@ -1165,6 +1197,7 @@ const EndKeyword = enum {
const Builtin = enum { const Builtin = enum {
isTag, isTag,
slice,
}; };
const BuiltinCall = union(Builtin) { const BuiltinCall = union(Builtin) {
@ -1172,6 +1205,11 @@ const BuiltinCall = union(Builtin) {
tag: []const u8, tag: []const u8,
expression: Expression, expression: Expression,
}, },
slice: struct {
iterable: Expression,
start: Expression,
end: Expression,
},
}; };
const ControlToken = union(enum) { const ControlToken = union(enum) {

View file

@ -26,6 +26,8 @@
neither neither
{=/if} {=/if}
sliced: {#for @slice(.foo, .start, .end) |$s|}{$s}, {/for}
format: {#format "s" .x} format: {#format "s" .x}
{#switch .snap case foo =} {#switch .snap case foo =}