Compare commits
2 Commits
3fecb795e9
...
0fbdc001d4
Author | SHA1 | Date | |
---|---|---|---|
0fbdc001d4 | |||
919d32e714 |
@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
# Test comment.
|
# Test comment.
|
||||||
|
|
||||||
|
pos = [10, 20, 0.3]
|
||||||
|
|
||||||
options = {
|
options = {
|
||||||
.title = "Afterglow",
|
.title = "Afterglow",
|
||||||
.width = 1280,
|
.width = 1280,
|
||||||
|
@ -207,6 +207,16 @@ pub fn Tag(comptime Element: type) type {
|
|||||||
|
|
||||||
pub const Writer = Generator(?usize, []const Byte);
|
pub const Writer = Generator(?usize, []const Byte);
|
||||||
|
|
||||||
|
pub fn all_equals(target: []const Byte, match: Byte) bool {
|
||||||
|
for (0 .. target.len) |index| {
|
||||||
|
if (target[index] != match) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn allocate_copy(allocator: Allocator, source: []const Byte) AllocationError![]Byte {
|
pub fn allocate_copy(allocator: Allocator, source: []const Byte) AllocationError![]Byte {
|
||||||
const allocation = try allocator.actions.reallocate(allocator.context, @returnAddress(), null, source.len);
|
const allocation = try allocator.actions.reallocate(allocator.context, @returnAddress(), null, source.len);
|
||||||
|
|
||||||
@ -265,6 +275,20 @@ pub fn allocate_string(allocator: Allocator, source: []const Byte) AllocationErr
|
|||||||
return @ptrCast(allocation);
|
return @ptrCast(allocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn are_equal(target: []const Byte, match: []const Byte) bool {
|
||||||
|
if (target.len != match.len) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (0 .. target.len) |index| {
|
||||||
|
if (target[index] != match[index]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn bytes_of(value: anytype) []const Byte {
|
pub fn bytes_of(value: anytype) []const Byte {
|
||||||
const pointer_info = @typeInfo(@TypeOf(value)).Pointer;
|
const pointer_info = @typeInfo(@TypeOf(value)).Pointer;
|
||||||
|
|
||||||
@ -326,20 +350,6 @@ pub fn ends_with(target: []const Byte, match: []const Byte) bool {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn equals(target: []const Byte, match: []const Byte) bool {
|
|
||||||
if (target.len != match.len) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (0 .. target.len) |index| {
|
|
||||||
if (target[index] != match[index]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find_first(haystack: []const Byte, needle: Byte) ?usize {
|
pub fn find_first(haystack: []const Byte, needle: Byte) ?usize {
|
||||||
for (0 .. haystack.len) |i| {
|
for (0 .. haystack.len) |i| {
|
||||||
if (haystack[i] == needle) {
|
if (haystack[i] == needle) {
|
||||||
@ -350,15 +360,23 @@ pub fn find_first(haystack: []const Byte, needle: Byte) ?usize {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var null_context = @as(usize, 0);
|
pub fn jenkins_hash(comptime int: std.builtin.Type.Int, bytes: []const Byte) math.Int(int) {
|
||||||
|
var hash = @as(math.Int(int), 0);
|
||||||
|
|
||||||
pub const null_writer = Writer.bind(usize, &null_context, struct {
|
for (bytes) |byte| {
|
||||||
fn write(context: *usize, buffer: []const u8) ?usize {
|
hash +%= byte;
|
||||||
debug.assert(context.* == 0);
|
hash +%= (hash << 10);
|
||||||
|
hash ^= (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
return buffer.len;
|
hash +%= (hash << 3);
|
||||||
}
|
hash ^= (hash >> 11);
|
||||||
}.write);
|
hash +%= (hash << 15);
|
||||||
|
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const null_writer = Writer.from(write_null);
|
||||||
|
|
||||||
pub fn slice_sentineled(comptime sen: anytype, ptr: [*:sen]const @TypeOf(sen)) [:sen]const @TypeOf(sen) {
|
pub fn slice_sentineled(comptime sen: anytype, ptr: [*:sen]const @TypeOf(sen)) [:sen]const @TypeOf(sen) {
|
||||||
var len = @as(usize, 0);
|
var len = @as(usize, 0);
|
||||||
@ -374,6 +392,10 @@ pub fn tag_of(comptime value: anytype) Tag(@TypeOf(value)) {
|
|||||||
return @as(Tag(@TypeOf(value)), value);
|
return @as(Tag(@TypeOf(value)), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn write_null(buffer: []const u8) ?usize {
|
||||||
|
return buffer.len;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn zero(target: []Byte) void {
|
pub fn zero(target: []Byte) void {
|
||||||
for (target) |*t| t.* = 0;
|
for (target) |*t| t.* = 0;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ pub fn StringTable(comptime Value: type) type {
|
|||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
||||||
fn equals(key_a: []const io.Byte, key_b: []const io.Byte) bool {
|
fn equals(key_a: []const io.Byte, key_b: []const io.Byte) bool {
|
||||||
return io.equals(key_a, key_b);
|
return io.are_equal(key_a, key_b);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn hash(key: []const io.Byte) usize {
|
fn hash(key: []const io.Byte) usize {
|
||||||
|
@ -40,7 +40,7 @@ pub const DecimalFormat = struct {
|
|||||||
},
|
},
|
||||||
|
|
||||||
else => {
|
else => {
|
||||||
if (self.delimiter.len == 0 or !io.equals(self.delimiter, utf8[index ..])) {
|
if (self.delimiter.len == 0 or !io.are_equal(self.delimiter, utf8[index ..])) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -39,6 +39,8 @@ pub const RuntimeEnv = struct {
|
|||||||
push_false,
|
push_false,
|
||||||
push_const: u16,
|
push_const: u16,
|
||||||
push_local: u8,
|
push_local: u8,
|
||||||
|
push_vector2,
|
||||||
|
push_vector3,
|
||||||
push_table: u32,
|
push_table: u32,
|
||||||
push_builtin: Builtin,
|
push_builtin: Builtin,
|
||||||
local_set: u8,
|
local_set: u8,
|
||||||
@ -108,6 +110,19 @@ pub const RuntimeEnv = struct {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.vector2_literal => |literal| {
|
||||||
|
try self.compile_expression(chunk, literal.y_expression.*);
|
||||||
|
try self.compile_expression(chunk, literal.x_expression.*);
|
||||||
|
try chunk.opcodes.push_one(.push_vector2);
|
||||||
|
},
|
||||||
|
|
||||||
|
.vector3_literal => |literal| {
|
||||||
|
try self.compile_expression(chunk, literal.z_expression.*);
|
||||||
|
try self.compile_expression(chunk, literal.y_expression.*);
|
||||||
|
try self.compile_expression(chunk, literal.x_expression.*);
|
||||||
|
try chunk.opcodes.push_one(.push_vector3);
|
||||||
|
},
|
||||||
|
|
||||||
.table_literal => |fields| {
|
.table_literal => |fields| {
|
||||||
if (fields.values.len > coral.math.max_int(@typeInfo(u32).Int)) {
|
if (fields.values.len > coral.math.max_int(@typeInfo(u32).Int)) {
|
||||||
return error.OutOfMemory;
|
return error.OutOfMemory;
|
||||||
@ -257,7 +272,7 @@ pub const RuntimeEnv = struct {
|
|||||||
var index = @as(u8, self.local_identifiers_count - 1);
|
var index = @as(u8, self.local_identifiers_count - 1);
|
||||||
|
|
||||||
while (true) : (index -= 1) {
|
while (true) : (index -= 1) {
|
||||||
if (coral.io.equals(local_identifier, self.local_identifiers_buffer[index])) {
|
if (coral.io.are_equal(local_identifier, self.local_identifiers_buffer[index])) {
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -324,6 +339,47 @@ pub const RuntimeEnv = struct {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.push_vector2 => {
|
||||||
|
const x = try self.env.expect(try self.pop_local());
|
||||||
|
|
||||||
|
defer self.env.discard(x);
|
||||||
|
|
||||||
|
const y = try self.env.expect(try self.pop_local());
|
||||||
|
|
||||||
|
defer self.env.discard(y);
|
||||||
|
|
||||||
|
const vector = try self.env.new_vector2(
|
||||||
|
@floatCast(try self.env.unbox_float(x)),
|
||||||
|
@floatCast(try self.env.unbox_float(y)));
|
||||||
|
|
||||||
|
errdefer self.env.discard(vector);
|
||||||
|
|
||||||
|
try self.env.locals.push_one(vector);
|
||||||
|
},
|
||||||
|
|
||||||
|
.push_vector3 => {
|
||||||
|
const x = try self.env.expect(try self.pop_local());
|
||||||
|
|
||||||
|
defer self.env.discard(x);
|
||||||
|
|
||||||
|
const y = try self.env.expect(try self.pop_local());
|
||||||
|
|
||||||
|
defer self.env.discard(y);
|
||||||
|
|
||||||
|
const z = try self.env.expect(try self.pop_local());
|
||||||
|
|
||||||
|
defer self.env.discard(z);
|
||||||
|
|
||||||
|
const vector = try self.env.new_vector3(
|
||||||
|
@floatCast(try self.env.unbox_float(x)),
|
||||||
|
@floatCast(try self.env.unbox_float(y)),
|
||||||
|
@floatCast(try self.env.unbox_float(z)));
|
||||||
|
|
||||||
|
errdefer self.env.discard(vector);
|
||||||
|
|
||||||
|
try self.env.locals.push_one(vector);
|
||||||
|
},
|
||||||
|
|
||||||
.push_table => |push_table| {
|
.push_table => |push_table| {
|
||||||
const table = try self.env.new_table();
|
const table = try self.env.new_table();
|
||||||
|
|
||||||
@ -991,7 +1047,7 @@ pub const RuntimeEnv = struct {
|
|||||||
|
|
||||||
if (object.ref_count == 0) {
|
if (object.ref_count == 0) {
|
||||||
switch (object.payload) {
|
switch (object.payload) {
|
||||||
.false, .true, .float, .fixed, .symbol, .syscall => {},
|
.false, .true, .float, .fixed, .symbol, .vector2, .vector3, .syscall => {},
|
||||||
|
|
||||||
.string => |string| {
|
.string => |string| {
|
||||||
coral.debug.assert(string.len >= 0);
|
coral.debug.assert(string.len >= 0);
|
||||||
@ -1190,6 +1246,20 @@ pub const RuntimeEnv = struct {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_vector2(self: *RuntimeEnv, x: f32, y: f32) RuntimeError!*RuntimeRef {
|
||||||
|
return RuntimeRef.allocate(self.allocator, .{
|
||||||
|
.ref_count = 1,
|
||||||
|
.payload = .{.vector2 = .{x, y}},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_vector3(self: *RuntimeEnv, x: f32, y: f32, z: f32) RuntimeError!*RuntimeRef {
|
||||||
|
return RuntimeRef.allocate(self.allocator, .{
|
||||||
|
.ref_count = 1,
|
||||||
|
.payload = .{.vector3 = .{x, y, z}},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn print(self: *RuntimeEnv, buffer: []const coral.io.Byte) void {
|
pub fn print(self: *RuntimeEnv, buffer: []const coral.io.Byte) void {
|
||||||
if (self.options.print) |bound_print| {
|
if (self.options.print) |bound_print| {
|
||||||
bound_print(buffer);
|
bound_print(buffer);
|
||||||
@ -1287,6 +1357,8 @@ pub const RuntimeRef = opaque {
|
|||||||
float: Float,
|
float: Float,
|
||||||
fixed: Fixed,
|
fixed: Fixed,
|
||||||
symbol: [*:0]const coral.io.Byte,
|
symbol: [*:0]const coral.io.Byte,
|
||||||
|
vector2: [2]f32,
|
||||||
|
vector3: [3]f32,
|
||||||
syscall: *const Syscall,
|
syscall: *const Syscall,
|
||||||
|
|
||||||
string: struct {
|
string: struct {
|
||||||
@ -1357,13 +1429,23 @@ pub const RuntimeRef = opaque {
|
|||||||
else => false,
|
else => false,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.vector2 => |self_vector| switch (other.object().payload) {
|
||||||
|
.vector2 => |other_vector| coral.io.are_equal(coral.io.bytes_of(&self_vector), coral.io.bytes_of(&other_vector)),
|
||||||
|
else => false,
|
||||||
|
},
|
||||||
|
|
||||||
|
.vector3 => |self_vector| switch (other.object().payload) {
|
||||||
|
.vector3 => |other_vector| coral.io.are_equal(coral.io.bytes_of(&self_vector), coral.io.bytes_of(&other_vector)),
|
||||||
|
else => false,
|
||||||
|
},
|
||||||
|
|
||||||
.syscall => |self_syscall| switch (other.object().payload) {
|
.syscall => |self_syscall| switch (other.object().payload) {
|
||||||
.syscall => |other_syscall| self_syscall == other_syscall,
|
.syscall => |other_syscall| self_syscall == other_syscall,
|
||||||
else => false,
|
else => false,
|
||||||
},
|
},
|
||||||
|
|
||||||
.string => |self_string| switch (other.object().payload) {
|
.string => |self_string| switch (other.object().payload) {
|
||||||
.string => |other_string| coral.io.equals(self_string.unpack(), other_string.unpack()),
|
.string => |other_string| coral.io.are_equal(self_string.unpack(), other_string.unpack()),
|
||||||
else => false,
|
else => false,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -1384,6 +1466,8 @@ pub const RuntimeRef = opaque {
|
|||||||
.float => |float| @bitCast(float),
|
.float => |float| @bitCast(float),
|
||||||
.fixed => |fixed| @intCast(@as(u32, @bitCast(fixed))),
|
.fixed => |fixed| @intCast(@as(u32, @bitCast(fixed))),
|
||||||
.symbol => |symbol| @intFromPtr(symbol),
|
.symbol => |symbol| @intFromPtr(symbol),
|
||||||
|
.vector2 => |vector| @bitCast(vector),
|
||||||
|
.vector3 => |vector| coral.io.jenkins_hash(@typeInfo(usize).Int, coral.io.bytes_of(&vector)),
|
||||||
.syscall => |syscall| @intFromPtr(syscall),
|
.syscall => |syscall| @intFromPtr(syscall),
|
||||||
.string => |string| coral.io.djb2_hash(@typeInfo(usize).Int, string.unpack()),
|
.string => |string| coral.io.djb2_hash(@typeInfo(usize).Int, string.unpack()),
|
||||||
.dynamic => |dynamic| @intFromPtr(dynamic.typeinfo()) ^ @intFromPtr(dynamic.userdata().ptr),
|
.dynamic => |dynamic| @intFromPtr(dynamic.typeinfo()) ^ @intFromPtr(dynamic.userdata().ptr),
|
||||||
@ -1404,6 +1488,8 @@ pub const RuntimeRef = opaque {
|
|||||||
.float => |float| float != 0,
|
.float => |float| float != 0,
|
||||||
.fixed => |fixed| fixed != 0,
|
.fixed => |fixed| fixed != 0,
|
||||||
.symbol => true,
|
.symbol => true,
|
||||||
|
.vector2 => |vector| coral.io.all_equals(coral.io.bytes_of(&vector), 0),
|
||||||
|
.vector3 => |vector| coral.io.all_equals(coral.io.bytes_of(&vector), 0),
|
||||||
.syscall => true,
|
.syscall => true,
|
||||||
.string => |string| string.len != 0,
|
.string => |string| string.len != 0,
|
||||||
.dynamic => true,
|
.dynamic => true,
|
||||||
|
@ -60,6 +60,17 @@ pub const Expression = union (enum) {
|
|||||||
argument_expressions: List,
|
argument_expressions: List,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
vector2_literal: struct {
|
||||||
|
x_expression: *Expression,
|
||||||
|
y_expression: *Expression,
|
||||||
|
},
|
||||||
|
|
||||||
|
vector3_literal: struct {
|
||||||
|
x_expression: *Expression,
|
||||||
|
y_expression: *Expression,
|
||||||
|
z_expression: *Expression,
|
||||||
|
},
|
||||||
|
|
||||||
pub const BinaryOperator = enum {
|
pub const BinaryOperator = enum {
|
||||||
addition,
|
addition,
|
||||||
subtraction,
|
subtraction,
|
||||||
@ -357,6 +368,57 @@ fn parse_factor(self: *Self) ParseError!Expression {
|
|||||||
break: parse .{.builtin = builtin};
|
break: parse .{.builtin = builtin};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.symbol_bracket_left => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
var expressions = [3]?*Expression{null, null, null};
|
||||||
|
var size = @as(u2, 0);
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (size == expressions.len) {
|
||||||
|
return self.report("vector literals cannot contain more than 3 elements");
|
||||||
|
}
|
||||||
|
|
||||||
|
expressions[size] = try coral.io.allocate_one(allocator, try self.parse_expression());
|
||||||
|
size += 1;
|
||||||
|
|
||||||
|
switch (self.tokenizer.token) {
|
||||||
|
.symbol_comma => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
continue;
|
||||||
|
},
|
||||||
|
|
||||||
|
.symbol_bracket_right => {
|
||||||
|
self.tokenizer.skip_newlines();
|
||||||
|
|
||||||
|
break;
|
||||||
|
},
|
||||||
|
|
||||||
|
else => return self.report("expected `,` or `]` after vector literal element expression"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break: parse switch (size) {
|
||||||
|
0, 1 => return self.report("vector literals must contain at least 2 elements"),
|
||||||
|
|
||||||
|
2 => .{
|
||||||
|
.vector2_literal = .{
|
||||||
|
.x_expression = expressions[0] orelse unreachable,
|
||||||
|
.y_expression = expressions[1] orelse unreachable,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
3 => .{
|
||||||
|
.vector3_literal = .{
|
||||||
|
.x_expression = expressions[0] orelse unreachable,
|
||||||
|
.y_expression = expressions[1] orelse unreachable,
|
||||||
|
.z_expression = expressions[2] orelse unreachable,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
.symbol_brace_left => {
|
.symbol_brace_left => {
|
||||||
var table_literal = Expression.TableLiteral.make(allocator);
|
var table_literal = Expression.TableLiteral.make(allocator);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user