lang 2.1: Pack as a type-system value
Add a `pack` variant to IR `TypeInfo` — an ordered, interned sequence of
per-position element types (`PackInfo { elements: []const TypeId }`) — with
constructor (`packType`), structural equality + hashing, and a `pack(T0, …)`
printer. A pack is comptime-only: it lowers to flat positional args before
codegen and has no runtime layout, so `sizeOf` and `toLLVMType` bail loudly
rather than inventing a size. 5 unit tests (N=0/1/3, dedup, order/arity
distinctness, distinct-from-tuple, printer).
Also: give TypeTable an arena for the slices its constructors dupe (freed at
deinit), and add the missing `usize`/`isize` arms to `sizeOf` (a latent
non-exhaustive switch) so types.test.zig compiles and runs leak-free.
This commit is contained in:
@@ -119,3 +119,78 @@ test "typeName for builtins" {
|
||||
try std.testing.expectEqualStrings("void", table.typeName(.void));
|
||||
try std.testing.expectEqualStrings("Any", table.typeName(.any));
|
||||
}
|
||||
|
||||
// ── Pack type (Feature 1, Step 2.1) ──────────────────────────────────
|
||||
|
||||
test "pack type: construct, element access, intern dedup (N=3)" {
|
||||
const alloc = std.testing.allocator;
|
||||
var table = TypeTable.init(alloc);
|
||||
defer table.deinit();
|
||||
|
||||
const elems = &[_]TypeId{ .bool, .s32, .string };
|
||||
const p1 = table.packType(elems);
|
||||
const p2 = table.packType(elems);
|
||||
try std.testing.expectEqual(p1, p2); // structural dedup
|
||||
|
||||
const info = table.get(p1);
|
||||
try std.testing.expect(info == .pack);
|
||||
try std.testing.expectEqual(@as(usize, 3), info.pack.elements.len);
|
||||
try std.testing.expectEqual(TypeId.bool, info.pack.elements[0]);
|
||||
try std.testing.expectEqual(TypeId.s32, info.pack.elements[1]);
|
||||
try std.testing.expectEqual(TypeId.string, info.pack.elements[2]);
|
||||
}
|
||||
|
||||
test "pack type: empty pack (N=0)" {
|
||||
const alloc = std.testing.allocator;
|
||||
var table = TypeTable.init(alloc);
|
||||
defer table.deinit();
|
||||
|
||||
const empty1 = table.packType(&.{});
|
||||
const empty2 = table.packType(&.{});
|
||||
try std.testing.expectEqual(empty1, empty2);
|
||||
const info = table.get(empty1);
|
||||
try std.testing.expect(info == .pack);
|
||||
try std.testing.expectEqual(@as(usize, 0), info.pack.elements.len);
|
||||
}
|
||||
|
||||
test "pack type: single element (N=1)" {
|
||||
const alloc = std.testing.allocator;
|
||||
var table = TypeTable.init(alloc);
|
||||
defer table.deinit();
|
||||
|
||||
const p = table.packType(&[_]TypeId{.f64});
|
||||
const info = table.get(p);
|
||||
try std.testing.expectEqual(@as(usize, 1), info.pack.elements.len);
|
||||
try std.testing.expectEqual(TypeId.f64, info.pack.elements[0]);
|
||||
}
|
||||
|
||||
test "pack type: distinct element lists are distinct types" {
|
||||
const alloc = std.testing.allocator;
|
||||
var table = TypeTable.init(alloc);
|
||||
defer table.deinit();
|
||||
|
||||
const a = table.packType(&[_]TypeId{ .bool, .s32 });
|
||||
const b = table.packType(&[_]TypeId{ .s32, .bool }); // order matters
|
||||
const c = table.packType(&[_]TypeId{.bool}); // arity matters
|
||||
try std.testing.expect(a != b);
|
||||
try std.testing.expect(a != c);
|
||||
try std.testing.expect(b != c);
|
||||
// A pack is distinct from the tuple of the same elements.
|
||||
const tup = table.intern(.{ .tuple = .{ .fields = &[_]TypeId{ .bool, .s32 }, .names = null } });
|
||||
try std.testing.expect(a != tup);
|
||||
}
|
||||
|
||||
test "pack type: formatTypeName" {
|
||||
const alloc = std.testing.allocator;
|
||||
var table = TypeTable.init(alloc);
|
||||
defer table.deinit();
|
||||
|
||||
var arena = std.heap.ArenaAllocator.init(alloc);
|
||||
defer arena.deinit();
|
||||
|
||||
const p = table.packType(&[_]TypeId{ .bool, .s32, .string });
|
||||
try std.testing.expectEqualStrings("pack(bool, s32, string)", table.formatTypeName(arena.allocator(), p));
|
||||
|
||||
const empty = table.packType(&.{});
|
||||
try std.testing.expectEqualStrings("pack()", table.formatTypeName(arena.allocator(), empty));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user