Make tables work and add rawEquals methods
Since hashtables are a hassle with strings and complex datastructures like the table they are an arraylist for now. Also implement rawEquals for numerals and values to make table.get work
This commit is contained in:
parent
cfc288e279
commit
5dc1b9d50b
@ -4,7 +4,7 @@ const types = @import("types.zig");
|
||||
|
||||
pub fn interpret(root: parser.ChunkNode, allocator: std.mem.Allocator) !void
|
||||
{
|
||||
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) };
|
||||
var _ENV = types.Table { .entries= std.ArrayList(types.TableEntry).init(allocator) };
|
||||
try walkChunk(root, &_ENV, allocator);
|
||||
}
|
||||
|
||||
|
162
src/types.zig
162
src/types.zig
@ -1,34 +1,174 @@
|
||||
const std = @import("std");
|
||||
|
||||
pub const Numeral = union(enum)
|
||||
pub const NumeralTag = 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,
|
||||
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
|
||||
{
|
||||
items: std.HashMap(Value, Value, std.hash_map.AutoContext(Value), std.hash_map.default_max_load_percentage),
|
||||
entries: std.ArrayList(TableEntry),
|
||||
|
||||
pub fn insert(self: *const Table, key: Value, value: Value) !bool
|
||||
pub fn get(self: Table, key: Value) Value
|
||||
{
|
||||
self.items.put(key, value);
|
||||
}
|
||||
|
||||
pub fn get(self: *const Table, key: Value) !Value
|
||||
{
|
||||
const value = self.items.get(key);
|
||||
return if(value == null) Value.Nil else value.?;
|
||||
if(@as(ValueTag, key) == ValueTag.Nil)
|
||||
{
|
||||
return Value.Nil;
|
||||
}
|
||||
for (self.entries.items) |entry|
|
||||
{
|
||||
if(entry.key.rawEqual(key))
|
||||
{
|
||||
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,
|
||||
Bool: bool,
|
||||
Numeral: Numeral,
|
||||
String: []const u8,
|
||||
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));
|
||||
}
|
||||
|
||||
pub const CodeRegion = struct
|
||||
{
|
||||
start: ?CodeLocation,
|
||||
|
Loading…
x
Reference in New Issue
Block a user