-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Previously a Scripty expression would immediately evaluate into an iterator, instead of doing expr -> array -> iterator, which made it awkward to implement things like sorting. The new implementation creates an array of scripty values always, which can then be turned into an array when passed to :loop. The new Array type and its builtins are implemented in src/context/Array.zig. We currently don't have many builtins for arrays and crucially we don't have yet sorting because it requires thinking though how to expose the functionality to the user. That said, builtins for arrays are welcome if anybody is blocked on that.
- Loading branch information
1 parent
1d66842
commit f9af143
Showing
16 changed files
with
316 additions
and
1,020 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,170 @@ | ||
const Array = @This(); | ||
|
||
const std = @import("std"); | ||
const ziggy = @import("ziggy"); | ||
const superhtml = @import("superhtml"); | ||
const scripty = @import("scripty"); | ||
const context = @import("../context.zig"); | ||
const doctypes = @import("doctypes.zig"); | ||
const Signature = doctypes.Signature; | ||
const Allocator = std.mem.Allocator; | ||
const Value = context.Value; | ||
const Template = context.Template; | ||
const Site = context.Site; | ||
const Page = context.Page; | ||
const Map = context.Map; | ||
|
||
len: usize, | ||
empty: bool, | ||
_items: []const Value, | ||
|
||
pub fn init(gpa: Allocator, T: type, items: []const T) error{OutOfMemory}!Value { | ||
if (T == Value) return .{ | ||
.array = .{ | ||
.len = items.len, | ||
.empty = items.len == 0, | ||
._items = items, | ||
}, | ||
}; | ||
|
||
const boxed_items = try gpa.alloc(Value, items.len); | ||
|
||
for (items, boxed_items) |i, *bi| { | ||
bi.* = try Value.from(gpa, i); | ||
} | ||
|
||
return .{ | ||
.array = .{ | ||
.len = items.len, | ||
.empty = items.len == 0, | ||
._items = boxed_items, | ||
}, | ||
}; | ||
} | ||
|
||
// pub fn deinit(iter: *const Iterator, gpa: Allocator) void { | ||
// gpa.destroy(iter); | ||
// } | ||
|
||
pub const dot = scripty.defaultDot(Array, Value, false); | ||
pub const description = "An array of items."; | ||
pub const Fields = struct { | ||
pub const len = | ||
\\The length of the array. | ||
; | ||
pub const empty = | ||
\\True when len is 0. | ||
; | ||
}; | ||
|
||
pub const Builtins = struct { | ||
pub const slice = struct { | ||
pub const signature: Signature = .{ | ||
.params = &.{ .Int, .{ .Opt = .Int } }, | ||
.ret = .{ .Many = .any }, | ||
}; | ||
pub const description = | ||
\\Slices an array from the first value (inclusive) to the | ||
\\second value (exclusive). | ||
\\ | ||
\\The second value can be omitted and defaults to the array's | ||
\\length, meaning that invoking `slice` with one argunent | ||
\\produces **suffixes** of the original sequence (i.e. it | ||
\\removes a prefix from the original sequence). | ||
\\ | ||
\\Note that negative values are not allowed at the moment. | ||
; | ||
pub const examples = | ||
\\$page.tags.slice(0,1) | ||
; | ||
pub fn call( | ||
arr: Array, | ||
gpa: Allocator, | ||
args: []const Value, | ||
) !Value { | ||
const bad_arg = .{ .err = "expected 1 or 2 integer argument(s)" }; | ||
if (args.len < 1 or args.len > 2) return bad_arg; | ||
|
||
const start = switch (args[0]) { | ||
.int => |i| i.value, | ||
else => return bad_arg, | ||
}; | ||
const end: i64 = if (args.len == 1) @intCast(arr.len) else switch (args[1]) { | ||
.int => |i| i.value, | ||
else => return bad_arg, | ||
}; | ||
|
||
if (start < 0) return Value.errFmt( | ||
gpa, | ||
"start value {} is negative", | ||
.{start}, | ||
); | ||
|
||
if (end < 0) return Value.errFmt( | ||
gpa, | ||
"end value {} is negative", | ||
.{end}, | ||
); | ||
|
||
if (start >= arr.len) return Value.errFmt(gpa, "start value {} exceeds array of length {}", .{ | ||
start, arr.len, | ||
}); | ||
|
||
if (end > arr.len) return Value.errFmt(gpa, "end value {} exceeds array of length {}", .{ | ||
end, arr.len, | ||
}); | ||
|
||
if (start > end) return Value.errFmt(gpa, "start value {} is bigger than end value {}!", .{ | ||
start, end, | ||
}); | ||
|
||
const new = arr._items[@intCast(start)..@intCast(end)]; | ||
|
||
return .{ | ||
.array = .{ | ||
.len = new.len, | ||
.empty = new.len == 0, | ||
._items = new, | ||
}, | ||
}; | ||
} | ||
}; | ||
|
||
pub const at = struct { | ||
pub const signature: Signature = .{ | ||
.params = &.{.Int}, | ||
.ret = .any, | ||
}; | ||
pub const description = | ||
\\Returns the value at the provided index. | ||
; | ||
pub const examples = | ||
\\$page.tags.at(0) | ||
; | ||
pub fn call( | ||
arr: Array, | ||
gpa: Allocator, | ||
args: []const Value, | ||
) !Value { | ||
const bad_arg = .{ .err = "expected 1 integer argument" }; | ||
if (args.len != 1) return bad_arg; | ||
|
||
const idx = switch (args[0]) { | ||
.int => |i| i.value, | ||
else => return bad_arg, | ||
}; | ||
|
||
if (idx < 0) return Value.errFmt( | ||
gpa, | ||
"index value {} is negative", | ||
.{idx}, | ||
); | ||
|
||
if (idx >= arr.len) return Value.errFmt(gpa, "index {} exceeds array of length {}", .{ | ||
idx, arr.len, | ||
}); | ||
|
||
return arr._items[@intCast(idx)]; | ||
} | ||
}; | ||
}; |
Oops, something went wrong.