lib/choir/src/core/mapping.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const Value = @import("value.zig").Value;
3 const Block = @import("block.zig").Block;
4 const Operation = @import("operation/root.zig").Operation;
5
6 pub const Mapping = struct {
7 allocator: std.mem.Allocator,
8
9 values: std.AutoHashMapUnmanaged(*const Value, *Value) = .{},
10
11 blocks: std.AutoHashMapUnmanaged(*const Block, *Block) = .{},
12
13 operations: std.AutoHashMapUnmanaged(*const Operation, *Operation) = .{},
14
15 pub fn init(allocator: std.mem.Allocator) Mapping {
16 return .{ .allocator = allocator };
17 }
18
19 pub fn deinit(self: *Mapping) void {
20 self.values.deinit(self.allocator);
21 self.blocks.deinit(self.allocator);
22 self.operations.deinit(self.allocator);
23 }
24
25 pub fn mapValue(self: *Mapping, source: *const Value, dest: *Value) !void {
26 try self.values.put(self.allocator, source, dest);
27 }
28
29 pub fn lookupValue(self: *const Mapping, source: *const Value) ?*Value {
30 return self.values.get(source);
31 }
32
33 pub fn lookupOrDefaultValue(self: *const Mapping, source: *Value) *Value {
34 return self.lookupValue(source) orelse source;
35 }
36
37 pub fn mapBlock(self: *Mapping, source: *const Block, dest: *Block) !void {
38 try self.blocks.put(self.allocator, source, dest);
39 }
40
41 pub fn lookupBlock(self: *const Mapping, source: *const Block) ?*Block {
42 return self.blocks.get(source);
43 }
44
45 pub fn lookupOrDefaultBlock(self: *const Mapping, source: *Block) *Block {
46 return self.lookupBlock(source) orelse source;
47 }
48
49 pub fn mapOperation(self: *Mapping, source: *const Operation, dest: *Operation) !void {
50 try self.operations.put(self.allocator, source, dest);
51 }
52
53 pub fn lookupOperation(self: *const Mapping, source: *const Operation) ?*Operation {
54 return self.operations.get(source);
55 }
56
57 pub fn lookupOrDefaultOperation(self: *const Mapping, source: *Operation) *Operation {
58 return self.lookupOperation(source) orelse source;
59 }
60 };
61
62 test "mapping stores value block and operation remaps with identity fallback" {
63 const testing = std.testing;
64 const Context = @import("context/root.zig").Context;
65
66 var mapping = Mapping.init(testing.allocator);
67 defer mapping.deinit();
68
69 var ctx = try Context.init(testing.allocator, Context.Limits.testing);
70 defer ctx.deinit(testing.allocator);
71 try ctx.allowUnregistered();
72 const value_type = try ctx.getDialectTypeFromName("test.value");
73
74 var source_block = Block.init(testing.allocator);
75 defer source_block.deinit();
76 var dest_block = Block.init(testing.allocator);
77 defer dest_block.deinit();
78 var external_block = Block.init(testing.allocator);
79 defer external_block.deinit();
80
81 const source_op = try ctx.createOperation(Operation.State.init("test.source", .unknown));
82 const dest_op = try ctx.createOperation(Operation.State.init("test.dest", .unknown));
83 const external_op = try ctx.createOperation(Operation.State.init("test.external", .unknown));
84
85 var source_value = Value{
86 .kind = .{ .block_argument = .{
87 .owner = &source_block,
88 .arg_number = 0,
89 } },
90 .type = value_type,
91 .id = 1,
92 };
93 var dest_value = Value{
94 .kind = .{ .block_argument = .{
95 .owner = &dest_block,
96 .arg_number = 0,
97 } },
98 .type = value_type,
99 .id = 2,
100 };
101 var external_value = Value{
102 .kind = .{ .block_argument = .{
103 .owner = &external_block,
104 .arg_number = 0,
105 } },
106 .type = value_type,
107 .id = 3,
108 };
109
110 try mapping.mapValue(&source_value, &dest_value);
111 try mapping.mapBlock(&source_block, &dest_block);
112 try mapping.mapOperation(source_op, dest_op);
113
114 try testing.expect(mapping.lookupValue(&source_value).? == &dest_value);
115 try testing.expect(mapping.lookupBlock(&source_block).? == &dest_block);
116 try testing.expect(mapping.lookupOperation(source_op).? == dest_op);
117 try testing.expect(mapping.lookupOrDefaultValue(&external_value) == &external_value);
118 try testing.expect(mapping.lookupOrDefaultBlock(&external_block) == &external_block);
119 try testing.expect(mapping.lookupOrDefaultOperation(external_op) == external_op);
120 }