| ... | ... | @@ -46,6 +46,21 @@ const Node = struct { |
| 46 | 46 | } |
| 47 | 47 | }; |
| 48 | 48 | |
| 49 | const Error = struct { |
| 50 | src: usize, |
| 51 | name: []const u8, |
| 52 | |
| 53 | fn hash(n: Error) u32 { |
| 54 | var hasher = std.hash.Wyhash.init(0); |
| 55 | std.hash.autoHash(&hasher, n.src); |
| 56 | return @truncate(u32, hasher.final()); |
| 57 | } |
| 58 | |
| 59 | fn eql(a: Error, b: Error) bool { |
| 60 | return a.src == b.src; |
| 61 | } |
| 62 | }; |
| 63 | |
| 49 | 64 | const Dump = struct { |
| 50 | 65 | zig_id: ?[]const u8 = null, |
| 51 | 66 | zig_version: ?[]const u8 = null, |
| ... | ... | @@ -60,6 +75,10 @@ const Dump = struct { |
| 60 | 75 | node_list: std.ArrayList(Node), |
| 61 | 76 | node_map: NodeMap, |
| 62 | 77 | |
| 78 | const ErrorMap = std.HashMap(Error, usize, Error.hash, Error.eql); |
| 79 | error_list: std.ArrayList(Error), |
| 80 | error_map: ErrorMap, |
| 81 | |
| 63 | 82 | fn init(allocator: *mem.Allocator) Dump { |
| 64 | 83 | return Dump{ |
| 65 | 84 | .targets = std.ArrayList([]const u8).init(allocator), |
| ... | ... | @@ -67,6 +86,8 @@ const Dump = struct { |
| 67 | 86 | .file_map = FileMap.init(allocator), |
| 68 | 87 | .node_list = std.ArrayList(Node).init(allocator), |
| 69 | 88 | .node_map = NodeMap.init(allocator), |
| 89 | .error_list = std.ArrayList(Error).init(allocator), |
| 90 | .error_map = ErrorMap.init(allocator), |
| 70 | 91 | }; |
| 71 | 92 | } |
| 72 | 93 | |
| ... | ... | @@ -129,6 +150,21 @@ const Dump = struct { |
| 129 | 150 | } |
| 130 | 151 | |
| 131 | 152 | // Merge errors. If the AST Node matches, it's the same error value. |
| 153 | const other_errors = root.Object.get("errors").?.value.Array.toSliceConst(); |
| 154 | var other_error_to_mine = std.AutoHashMap(usize, usize).init(self.a()); |
| 155 | for (other_errors) |other_error_json, i| { |
| 156 | const other_src_id = jsonObjInt(other_error_json, "src"); |
| 157 | const other_error = Error{ |
| 158 | .src = other_ast_node_to_mine.getValue(other_src_id).?, |
| 159 | .name = other_error_json.Object.get("name").?.value.String, |
| 160 | }; |
| 161 | const gop = try self.error_map.getOrPut(other_error); |
| 162 | if (!gop.found_existing) { |
| 163 | gop.kv.value = self.error_list.len; |
| 164 | try self.error_list.append(other_error); |
| 165 | } |
| 166 | try other_error_to_mine.putNoClobber(i, gop.kv.value); |
| 167 | } |
| 132 | 168 | } |
| 133 | 169 | |
| 134 | 170 | fn render(self: *Dump, stream: var) !void { |
| ... | ... | @@ -168,6 +204,22 @@ const Dump = struct { |
| 168 | 204 | |
| 169 | 205 | try jw.endObject(); |
| 170 | 206 | |
| 207 | try jw.objectField("errors"); |
| 208 | try jw.beginArray(); |
| 209 | for (self.error_list.toSliceConst()) |zig_error| { |
| 210 | try jw.arrayElem(); |
| 211 | try jw.beginObject(); |
| 212 | |
| 213 | try jw.objectField("src"); |
| 214 | try jw.emitNumber(zig_error.src); |
| 215 | |
| 216 | try jw.objectField("name"); |
| 217 | try jw.emitString(zig_error.name); |
| 218 | |
| 219 | try jw.endObject(); |
| 220 | } |
| 221 | try jw.endArray(); |
| 222 | |
| 171 | 223 | try jw.objectField("astNodes"); |
| 172 | 224 | try jw.beginArray(); |
| 173 | 225 | for (self.node_list.toSliceConst()) |node| { |