Compare commits
No commits in common. "a82482378646ae7112c288078117d046a2a9eec7" and "cfc288e279631c18f6e22ef517068c52f2dc8621" have entirely different histories.
a824823786
...
cfc288e279
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,2 @@
|
|||||||
zig-out/
|
zig-out/
|
||||||
zig-cache/
|
zig-cache/
|
||||||
.vscode/
|
|
||||||
target/
|
|
||||||
|
@ -4,7 +4,7 @@ const types = @import("types.zig");
|
|||||||
|
|
||||||
pub fn interpret(root: parser.ChunkNode, allocator: std.mem.Allocator) !void
|
pub fn interpret(root: parser.ChunkNode, allocator: std.mem.Allocator) !void
|
||||||
{
|
{
|
||||||
var _ENV = types.Table { .entries= std.ArrayList(types.TableEntry).init(allocator) };
|
var _ENV = types.Table { .items = std.HashMap(types.Value, types.Value, std.hash_map.AutoContext(types.Value), std.hash_map.default_max_load_percentage).init(allocator) };
|
||||||
try walkChunk(root, &_ENV, allocator);
|
try walkChunk(root, &_ENV, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
171
src/types.zig
171
src/types.zig
@ -1,187 +1,34 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub const NumeralTag = enum
|
pub const Numeral = union(enum)
|
||||||
{
|
|
||||||
Integer,
|
|
||||||
Float,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn isFloatExactInt(value: f64) bool
|
|
||||||
{
|
|
||||||
return value == 0 or (std.math.isNormal(value) and @floor(value) == value);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const Numeral = union(NumeralTag)
|
|
||||||
{
|
{
|
||||||
Integer: i64,
|
Integer: i64,
|
||||||
Float: f64,
|
Float: f64,
|
||||||
|
|
||||||
pub fn rawEqual(self: Numeral, other: Numeral) bool
|
|
||||||
{
|
|
||||||
if(@as(NumeralTag, self) == @as(NumeralTag, other))
|
|
||||||
{
|
|
||||||
switch(self)
|
|
||||||
{
|
|
||||||
.Float => |value| return value == other.Float,
|
|
||||||
.Integer => |value| return value == other.Integer,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Other is the respective other type
|
|
||||||
switch(self)
|
|
||||||
{
|
|
||||||
.Float => |value|
|
|
||||||
{
|
|
||||||
return isFloatExactInt(value) and @as(u64, @intFromFloat(value)) == other.Integer;
|
|
||||||
},
|
|
||||||
.Integer => |value|
|
|
||||||
{
|
|
||||||
return isFloatExactInt(other.Float) and @as(u64, @intFromFloat(other.Float)) == value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
test "float int equality"
|
|
||||||
{
|
|
||||||
const a = Numeral { .Float = 12.0 };
|
|
||||||
const b = Numeral { .Integer = 12 };
|
|
||||||
try std.testing.expect(a.rawEqual(b));
|
|
||||||
try std.testing.expect(b.rawEqual(a));
|
|
||||||
try std.testing.expect(a.rawEqual(a));
|
|
||||||
try std.testing.expect(b.rawEqual(b));
|
|
||||||
const c = Numeral { .Float = (0.2 + 0.1) * 10.0 };
|
|
||||||
const d = Numeral { .Integer = 3 };
|
|
||||||
try std.testing.expect(c.rawEqual(d));
|
|
||||||
try std.testing.expect(d.rawEqual(c));
|
|
||||||
try std.testing.expect(c.rawEqual(c));
|
|
||||||
try std.testing.expect(d.rawEqual(d));
|
|
||||||
const e = Numeral { .Float = 3.2 };
|
|
||||||
try std.testing.expect(!a.rawEqual(e));
|
|
||||||
try std.testing.expect(!b.rawEqual(e));
|
|
||||||
try std.testing.expect(!c.rawEqual(e));
|
|
||||||
try std.testing.expect(!d.rawEqual(e));
|
|
||||||
try std.testing.expect(!e.rawEqual(a));
|
|
||||||
try std.testing.expect(!e.rawEqual(b));
|
|
||||||
try std.testing.expect(!e.rawEqual(c));
|
|
||||||
try std.testing.expect(!e.rawEqual(d));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const TableEntry = struct
|
|
||||||
{
|
|
||||||
key: Value,
|
|
||||||
value: Value,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const Table = struct
|
pub const Table = struct
|
||||||
{
|
{
|
||||||
entries: std.ArrayList(TableEntry),
|
items: std.HashMap(Value, Value, std.hash_map.AutoContext(Value), std.hash_map.default_max_load_percentage),
|
||||||
|
|
||||||
pub fn get(self: Table, key: Value) Value
|
pub fn insert(self: *const Table, key: Value, value: Value) !bool
|
||||||
{
|
{
|
||||||
if(@as(ValueTag, key) == ValueTag.Nil)
|
self.items.put(key, value);
|
||||||
{
|
|
||||||
return Value.Nil;
|
|
||||||
}
|
}
|
||||||
for (self.entries.items) |entry|
|
|
||||||
|
pub fn get(self: *const Table, key: Value) !Value
|
||||||
{
|
{
|
||||||
if(entry.key.rawEqual(key))
|
const value = self.items.get(key);
|
||||||
{
|
return if(value == null) Value.Nil else value.?;
|
||||||
return entry.value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Value.Nil;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
pub const Value = union(enum)
|
||||||
pub const ValueTag = enum
|
|
||||||
{
|
|
||||||
Nil,
|
|
||||||
Bool,
|
|
||||||
Numeral,
|
|
||||||
String,
|
|
||||||
Table,
|
|
||||||
};
|
|
||||||
pub const Value = union(ValueTag)
|
|
||||||
{
|
{
|
||||||
Nil,
|
Nil,
|
||||||
Bool: bool,
|
Bool: bool,
|
||||||
Numeral: Numeral,
|
Numeral: Numeral,
|
||||||
String: []const u8,
|
String: []const u8,
|
||||||
Table: *Table,
|
Table: *Table,
|
||||||
|
|
||||||
pub fn rawEqual(self: Value, other: Value) bool
|
|
||||||
{
|
|
||||||
if(@as(ValueTag, self) != @as(ValueTag, other))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
switch(self)
|
|
||||||
{
|
|
||||||
.Nil => return true,
|
|
||||||
.Bool => |value| return value == other.Bool,
|
|
||||||
.Numeral => |value| return value.rawEqual(other.Numeral),
|
|
||||||
.String => |value| return std.mem.eql(u8, value, other.String),
|
|
||||||
.Table => |value| return value == other.Table,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
test "Value equalities"
|
|
||||||
{
|
|
||||||
const a = Value { .Bool = true };
|
|
||||||
const b = Value { .Numeral = Numeral { .Integer = 1 } };
|
|
||||||
// true != 1
|
|
||||||
try std.testing.expect(!a.rawEqual(b));
|
|
||||||
// 1 != true
|
|
||||||
try std.testing.expect(!b.rawEqual(a));
|
|
||||||
const c = Value { .Bool = false };
|
|
||||||
// true != false
|
|
||||||
try std.testing.expect(!a.rawEqual(c));
|
|
||||||
// false!= true
|
|
||||||
try std.testing.expect(!c.rawEqual(a));
|
|
||||||
const d = Value { .Bool = true };
|
|
||||||
// true == true
|
|
||||||
try std.testing.expect(a.rawEqual(d));
|
|
||||||
// true == true
|
|
||||||
try std.testing.expect(d.rawEqual(a));
|
|
||||||
const e = Value { .String = "foo" };
|
|
||||||
const f = Value { .String = "bar" };
|
|
||||||
// foo != bar
|
|
||||||
try std.testing.expect(!e.rawEqual(f));
|
|
||||||
// bar != foo
|
|
||||||
try std.testing.expect(!f.rawEqual(e));
|
|
||||||
const g = Value { .String = "foo" };
|
|
||||||
// foo != foo
|
|
||||||
try std.testing.expect(e.rawEqual(g));
|
|
||||||
// foo != foo
|
|
||||||
try std.testing.expect(g.rawEqual(e));
|
|
||||||
var table = Table { .entries = std.ArrayList(TableEntry).init(std.testing.allocator) };
|
|
||||||
const h = Value { .Table = &table };
|
|
||||||
var table2 = Table { .entries = std.ArrayList(TableEntry).init(std.testing.allocator) };
|
|
||||||
const i = Value { .Table = &table2 };
|
|
||||||
const j = Value { .Table = &table2 };
|
|
||||||
|
|
||||||
try std.testing.expect(h.rawEqual(h));
|
|
||||||
try std.testing.expect(i.rawEqual(i));
|
|
||||||
try std.testing.expect(!h.rawEqual(i));
|
|
||||||
try std.testing.expect(!i.rawEqual(h));
|
|
||||||
try std.testing.expect(i.rawEqual(j));
|
|
||||||
try std.testing.expect(!h.rawEqual(j));
|
|
||||||
}
|
|
||||||
|
|
||||||
test "Table get"
|
|
||||||
{
|
|
||||||
var a = Table { .entries = std.ArrayList(TableEntry).init(std.testing.allocator) };
|
|
||||||
defer a.entries.deinit();
|
|
||||||
try a.entries.append(TableEntry { .key = Value { .Bool = true }, .value = Value { .String = "foo" } });
|
|
||||||
try std.testing.expectEqualStrings(a.get(Value { .Bool = true }).String, "foo");
|
|
||||||
try std.testing.expectEqual(a.get(Value.Nil), Value.Nil);
|
|
||||||
try std.testing.expectEqual(a.get(Value { .Numeral = Numeral { .Integer = 12 } }), Value.Nil);
|
|
||||||
var c = a.get(Value { .Bool = true });
|
|
||||||
c.String = "bar";
|
|
||||||
try std.testing.expectEqual(a.get(Value { .Bool = true }).String, "foo");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const CodeRegion = struct
|
pub const CodeRegion = struct
|
||||||
{
|
{
|
||||||
start: ?CodeLocation,
|
start: ?CodeLocation,
|
||||||
|
Reference in New Issue
Block a user