106 lines
2.7 KiB
Zig
106 lines
2.7 KiB
Zig
const std = @import("std");
|
|
const spv = @import("spv.zig");
|
|
|
|
const RuntimeError = @import("Runtime.zig").RuntimeError;
|
|
|
|
const SpvWord = spv.SpvWord;
|
|
|
|
const Self = @This();
|
|
|
|
buffer: []const SpvWord,
|
|
index: usize,
|
|
did_jump: bool,
|
|
next_force_skip: ?usize,
|
|
|
|
pub fn init(buffer: []const SpvWord) Self {
|
|
return .{
|
|
.buffer = buffer,
|
|
.index = 0,
|
|
.did_jump = false,
|
|
.next_force_skip = null,
|
|
};
|
|
}
|
|
|
|
pub inline fn nextOrNull(self: *Self) ?SpvWord {
|
|
const word = self.peek() orelse return null;
|
|
self.index += 1;
|
|
return word;
|
|
}
|
|
|
|
/// self.index + index will be automatically skipped
|
|
pub inline fn forceSkipIndex(self: *Self, index: SpvWord) void {
|
|
self.next_force_skip = self.index + index;
|
|
}
|
|
|
|
pub inline fn nextAsOrNull(self: *Self, comptime E: type) ?E {
|
|
if (self.next_force_skip) |skip_index| {
|
|
if (self.index == skip_index) {
|
|
_ = self.skip();
|
|
self.next_force_skip = null;
|
|
}
|
|
}
|
|
return if (self.nextOrNull()) |word| std.enums.fromInt(E, word) else null;
|
|
}
|
|
|
|
pub inline fn next(self: *Self) RuntimeError!SpvWord {
|
|
if (self.next_force_skip) |skip_index| {
|
|
if (self.index == skip_index) {
|
|
_ = self.skip();
|
|
self.next_force_skip = null;
|
|
}
|
|
}
|
|
return self.nextOrNull() orelse return RuntimeError.InvalidSpirV;
|
|
}
|
|
|
|
pub inline fn nextAs(self: *Self, comptime E: type) RuntimeError!E {
|
|
if (self.next_force_skip) |skip_index| {
|
|
if (self.index == skip_index) {
|
|
_ = self.skip();
|
|
}
|
|
}
|
|
return self.nextAsOrNull(E) orelse return RuntimeError.InvalidSpirV;
|
|
}
|
|
|
|
pub inline fn peek(self: *const Self) ?SpvWord {
|
|
return if (self.index >= self.buffer.len) null else self.buffer[self.index];
|
|
}
|
|
|
|
pub inline fn skip(self: *Self) bool {
|
|
if (self.index >= self.buffer.len) {
|
|
return false;
|
|
}
|
|
self.index += 1;
|
|
return true;
|
|
}
|
|
|
|
pub inline fn skipN(self: *Self, count: usize) bool {
|
|
if (self.index >= self.buffer.len) {
|
|
return false;
|
|
}
|
|
self.index += count;
|
|
return true;
|
|
}
|
|
|
|
pub inline fn skipToEnd(self: *Self) void {
|
|
self.index = self.buffer.len;
|
|
self.did_jump = true;
|
|
}
|
|
|
|
pub inline fn emitSourceLocation(self: *const Self) usize {
|
|
return self.index;
|
|
}
|
|
|
|
pub inline fn jumpToSourceLocation(self: *Self, source_location: usize) bool {
|
|
if (source_location > self.buffer.len) return false;
|
|
self.index = source_location;
|
|
self.did_jump = true;
|
|
return true;
|
|
}
|
|
|
|
/// Like jumpToSourceLocation without toggling self.did_jump
|
|
pub inline fn goToSourceLocation(self: *Self, source_location: usize) bool {
|
|
if (source_location > self.buffer.len) return false;
|
|
self.index = source_location;
|
|
return true;
|
|
}
|