| author | |
| committer | |
| log | 30a555eed4d48b602b2c92a05c443e03c4660d48 |
| tree | 00c94859ba91bd12419aa48b5bee66306d10070b |
| parent | 8aa20227ed45294da9606222d0b20eb922cecb2e |
| signature |
-fgenerate-docs is replaced ith -femit-docs
-fno-emit-bin is added to prevent outputting binary8 files changed, 154 insertions(+), 27 deletions(-)
lib/std/hash.zig+2| ... | @@ -3,6 +3,8 @@ pub const Adler32 = adler.Adler32; | ... | @@ -3,6 +3,8 @@ pub const Adler32 = adler.Adler32; |
| 3 | 3 | ||
| 4 | const auto_hash = @import("hash/auto_hash.zig"); | 4 | const auto_hash = @import("hash/auto_hash.zig"); |
| 5 | pub const autoHash = auto_hash.autoHash; | 5 | pub const autoHash = auto_hash.autoHash; |
| 6 | pub const autoHashStrat = auto_hash.hash; | ||
| 7 | pub const Strategy = auto_hash.HashStrategy; | ||
| 6 | 8 | ||
| 7 | // pub for polynomials + generic crc32 construction | 9 | // pub for polynomials + generic crc32 construction |
| 8 | pub const crc = @import("hash/crc.zig"); | 10 | pub const crc = @import("hash/crc.zig"); |
lib/std/hash_map.zig+10| ... | @@ -550,3 +550,13 @@ pub fn getAutoEqlFn(comptime K: type) (fn (K, K) bool) { | ... | @@ -550,3 +550,13 @@ pub fn getAutoEqlFn(comptime K: type) (fn (K, K) bool) { |
| 550 | } | 550 | } |
| 551 | }.eql; | 551 | }.eql; |
| 552 | } | 552 | } |
| 553 | |||
| 554 | pub fn getAutoHashStratFn(comptime K: type, comptime strategy: std.hash.Strategy) (fn (K) u32) { | ||
| 555 | return struct { | ||
| 556 | fn hash(key: K) u32 { | ||
| 557 | var hasher = Wyhash.init(0); | ||
| 558 | std.hash.autoHashStrat(&hasher, key, strategy); | ||
| 559 | return @truncate(u32, hasher.final()); | ||
| 560 | } | ||
| 561 | }.hash; | ||
| 562 | } |
lib/std/json/write_stream.zig+11-4| ... | @@ -152,10 +152,17 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { | ... | @@ -152,10 +152,17 @@ pub fn WriteStream(comptime OutStream: type, comptime max_depth: usize) type { |
| 152 | ) !void { | 152 | ) !void { |
| 153 | assert(self.state[self.state_index] == State.Value); | 153 | assert(self.state[self.state_index] == State.Value); |
| 154 | switch (@typeInfo(@typeOf(value))) { | 154 | switch (@typeInfo(@typeOf(value))) { |
| 155 | .Int => |info| if (info.bits < 53 or (value < 4503599627370496 and value > -4503599627370496)) { | 155 | .Int => |info| { |
| 156 | try self.stream.print("{}", value); | 156 | if (info.bits < 53) { |
| 157 | self.popState(); | 157 | try self.stream.print("{}", value); |
| 158 | return; | 158 | self.popState(); |
| 159 | return; | ||
| 160 | } | ||
| 161 | if (value < 4503599627370496 and (!info.is_signed or value > -4503599627370496)) { | ||
| 162 | try self.stream.print("{}", value); | ||
| 163 | self.popState(); | ||
| 164 | return; | ||
| 165 | } | ||
| 159 | }, | 166 | }, |
| 160 | .Float => if (@floatCast(f64, value) == value) { | 167 | .Float => if (@floatCast(f64, value) == value) { |
| 161 | try self.stream.print("{}", value); | 168 | try self.stream.print("{}", value); |
src/all_types.hpp+1| ... | @@ -2091,6 +2091,7 @@ struct CodeGen { | ... | @@ -2091,6 +2091,7 @@ struct CodeGen { |
| 2091 | bool function_sections; | 2091 | bool function_sections; |
| 2092 | bool enable_dump_analysis; | 2092 | bool enable_dump_analysis; |
| 2093 | bool enable_doc_generation; | 2093 | bool enable_doc_generation; |
| 2094 | bool disable_bin_generation; | ||
| 2094 | 2095 | ||
| 2095 | Buf *mmacosx_version_min; | 2096 | Buf *mmacosx_version_min; |
| 2096 | Buf *mios_version_min; | 2097 | Buf *mios_version_min; |
src/codegen.cpp+5-1| ... | @@ -7586,6 +7586,8 @@ static void zig_llvm_emit_output(CodeGen *g) { | ... | @@ -7586,6 +7586,8 @@ static void zig_llvm_emit_output(CodeGen *g) { |
| 7586 | char *err_msg = nullptr; | 7586 | char *err_msg = nullptr; |
| 7587 | switch (g->emit_file_type) { | 7587 | switch (g->emit_file_type) { |
| 7588 | case EmitFileTypeBinary: | 7588 | case EmitFileTypeBinary: |
| 7589 | if (g->disable_bin_generation) | ||
| 7590 | return; | ||
| 7589 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), | 7591 | if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path), |
| 7590 | ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small, | 7592 | ZigLLVM_EmitBinary, &err_msg, g->build_mode == BuildModeDebug, is_small, |
| 7591 | g->enable_time_report)) | 7593 | g->enable_time_report)) |
| ... | @@ -10158,6 +10160,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { | ... | @@ -10158,6 +10160,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) { |
| 10158 | cache_bool(ch, g->function_sections); | 10160 | cache_bool(ch, g->function_sections); |
| 10159 | cache_bool(ch, g->enable_dump_analysis); | 10161 | cache_bool(ch, g->enable_dump_analysis); |
| 10160 | cache_bool(ch, g->enable_doc_generation); | 10162 | cache_bool(ch, g->enable_doc_generation); |
| 10163 | cache_bool(ch, g->disable_bin_generation); | ||
| 10161 | cache_buf_opt(ch, g->mmacosx_version_min); | 10164 | cache_buf_opt(ch, g->mmacosx_version_min); |
| 10162 | cache_buf_opt(ch, g->mios_version_min); | 10165 | cache_buf_opt(ch, g->mios_version_min); |
| 10163 | cache_usize(ch, g->version_major); | 10166 | cache_usize(ch, g->version_major); |
| ... | @@ -10396,7 +10399,8 @@ void codegen_build_and_link(CodeGen *g) { | ... | @@ -10396,7 +10399,8 @@ void codegen_build_and_link(CodeGen *g) { |
| 10396 | // If there is more than one object, we have to link them (with -r). | 10399 | // If there is more than one object, we have to link them (with -r). |
| 10397 | // Finally, if we didn't make an object from zig source, and we don't have caching enabled, | 10400 | // Finally, if we didn't make an object from zig source, and we don't have caching enabled, |
| 10398 | // then we have an object from C source that we must copy to the output dir which we do with a -r link. | 10401 | // then we have an object from C source that we must copy to the output dir which we do with a -r link. |
| 10399 | if (g->emit_file_type == EmitFileTypeBinary && (g->out_type != OutTypeObj || g->link_objects.length > 1 || | 10402 | if (!g->disable_bin_generation && g->emit_file_type == EmitFileTypeBinary && |
| 10403 | (g->out_type != OutTypeObj || g->link_objects.length > 1 || | ||
| 10400 | (!need_llvm_module(g) && !g->enable_cache))) | 10404 | (!need_llvm_module(g) && !g->enable_cache))) |
| 10401 | { | 10405 | { |
| 10402 | codegen_link(g); | 10406 | codegen_link(g); |
src/dump_analysis.cpp+9-9| ... | @@ -1309,15 +1309,6 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const | ... | @@ -1309,15 +1309,6 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const |
| 1309 | } | 1309 | } |
| 1310 | jw_end_array(jw); | 1310 | jw_end_array(jw); |
| 1311 | 1311 | ||
| 1312 | jw_object_field(jw, "files"); | ||
| 1313 | jw_begin_array(jw); | ||
| 1314 | for (uint32_t i = 0; i < ctx.file_list.length; i += 1) { | ||
| 1315 | Buf *file = ctx.file_list.at(i); | ||
| 1316 | jw_array_elem(jw); | ||
| 1317 | anal_dump_file(&ctx, file); | ||
| 1318 | } | ||
| 1319 | jw_end_array(jw); | ||
| 1320 | |||
| 1321 | jw_object_field(jw, "errors"); | 1312 | jw_object_field(jw, "errors"); |
| 1322 | jw_begin_array(jw); | 1313 | jw_begin_array(jw); |
| 1323 | for (uint32_t i = 0; i < ctx.err_list.length; i += 1) { | 1314 | for (uint32_t i = 0; i < ctx.err_list.length; i += 1) { |
| ... | @@ -1336,5 +1327,14 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const | ... | @@ -1336,5 +1327,14 @@ void zig_print_analysis_dump(CodeGen *g, FILE *f, const char *one_indent, const |
| 1336 | } | 1327 | } |
| 1337 | jw_end_array(jw); | 1328 | jw_end_array(jw); |
| 1338 | 1329 | ||
| 1330 | jw_object_field(jw, "files"); | ||
| 1331 | jw_begin_array(jw); | ||
| 1332 | for (uint32_t i = 0; i < ctx.file_list.length; i += 1) { | ||
| 1333 | Buf *file = ctx.file_list.at(i); | ||
| 1334 | jw_array_elem(jw); | ||
| 1335 | anal_dump_file(&ctx, file); | ||
| 1336 | } | ||
| 1337 | jw_end_array(jw); | ||
| 1338 | |||
| 1339 | jw_end_object(jw); | 1339 | jw_end_object(jw); |
| 1340 | } | 1340 | } |
src/main.cpp+12-2| ... | @@ -65,7 +65,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { | ... | @@ -65,7 +65,8 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 65 | " -ftime-report print timing diagnostics\n" | 65 | " -ftime-report print timing diagnostics\n" |
| 66 | " -fstack-report print stack size diagnostics\n" | 66 | " -fstack-report print stack size diagnostics\n" |
| 67 | " -fdump-analysis write analysis.json file with type information\n" | 67 | " -fdump-analysis write analysis.json file with type information\n" |
| 68 | " -fgenerate-docs create a docs/ dir with html documentation\n" | 68 | " -femit-docs create a docs/ dir with html documentation\n" |
| 69 | " -fno-emit-bin skip emitting machine code\n" | ||
| 69 | " --libc [file] Provide a file which specifies libc paths\n" | 70 | " --libc [file] Provide a file which specifies libc paths\n" |
| 70 | " --name [name] override output name\n" | 71 | " --name [name] override output name\n" |
| 71 | " --output-dir [dir] override output directory (defaults to cwd)\n" | 72 | " --output-dir [dir] override output directory (defaults to cwd)\n" |
| ... | @@ -483,6 +484,7 @@ int main(int argc, char **argv) { | ... | @@ -483,6 +484,7 @@ int main(int argc, char **argv) { |
| 483 | bool stack_report = false; | 484 | bool stack_report = false; |
| 484 | bool enable_dump_analysis = false; | 485 | bool enable_dump_analysis = false; |
| 485 | bool enable_doc_generation = false; | 486 | bool enable_doc_generation = false; |
| 487 | bool disable_bin_generation = false; | ||
| 486 | const char *cache_dir = nullptr; | 488 | const char *cache_dir = nullptr; |
| 487 | CliPkg *cur_pkg = allocate<CliPkg>(1); | 489 | CliPkg *cur_pkg = allocate<CliPkg>(1); |
| 488 | BuildMode build_mode = BuildModeDebug; | 490 | BuildMode build_mode = BuildModeDebug; |
| ... | @@ -668,8 +670,10 @@ int main(int argc, char **argv) { | ... | @@ -668,8 +670,10 @@ int main(int argc, char **argv) { |
| 668 | stack_report = true; | 670 | stack_report = true; |
| 669 | } else if (strcmp(arg, "-fdump-analysis") == 0) { | 671 | } else if (strcmp(arg, "-fdump-analysis") == 0) { |
| 670 | enable_dump_analysis = true; | 672 | enable_dump_analysis = true; |
| 671 | } else if (strcmp(arg, "-fgenerate-docs") == 0) { | 673 | } else if (strcmp(arg, "-femit-docs") == 0) { |
| 672 | enable_doc_generation = true; | 674 | enable_doc_generation = true; |
| 675 | } else if (strcmp(arg, "-fno-emit-bin") == 0) { | ||
| 676 | disable_bin_generation = true; | ||
| 673 | } else if (strcmp(arg, "--enable-valgrind") == 0) { | 677 | } else if (strcmp(arg, "--enable-valgrind") == 0) { |
| 674 | valgrind_support = ValgrindSupportEnabled; | 678 | valgrind_support = ValgrindSupportEnabled; |
| 675 | } else if (strcmp(arg, "--disable-valgrind") == 0) { | 679 | } else if (strcmp(arg, "--disable-valgrind") == 0) { |
| ... | @@ -1148,6 +1152,7 @@ int main(int argc, char **argv) { | ... | @@ -1148,6 +1152,7 @@ int main(int argc, char **argv) { |
| 1148 | g->enable_stack_report = stack_report; | 1152 | g->enable_stack_report = stack_report; |
| 1149 | g->enable_dump_analysis = enable_dump_analysis; | 1153 | g->enable_dump_analysis = enable_dump_analysis; |
| 1150 | g->enable_doc_generation = enable_doc_generation; | 1154 | g->enable_doc_generation = enable_doc_generation; |
| 1155 | g->disable_bin_generation = disable_bin_generation; | ||
| 1151 | codegen_set_out_name(g, buf_out_name); | 1156 | codegen_set_out_name(g, buf_out_name); |
| 1152 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); | 1157 | codegen_set_lib_version(g, ver_major, ver_minor, ver_patch); |
| 1153 | g->want_single_threaded = want_single_threaded; | 1158 | g->want_single_threaded = want_single_threaded; |
| ... | @@ -1290,6 +1295,11 @@ int main(int argc, char **argv) { | ... | @@ -1290,6 +1295,11 @@ int main(int argc, char **argv) { |
| 1290 | zig_print_stack_report(g, stdout); | 1295 | zig_print_stack_report(g, stdout); |
| 1291 | } | 1296 | } |
| 1292 | 1297 | ||
| 1298 | if (g->disable_bin_generation) { | ||
| 1299 | fprintf(stderr, "Semantic analysis complete. No binary produced due to -fno-emit-bin.\n"); | ||
| 1300 | return 0; | ||
| 1301 | } | ||
| 1302 | |||
| 1293 | Buf *test_exe_path_unresolved = &g->output_file_path; | 1303 | Buf *test_exe_path_unresolved = &g->output_file_path; |
| 1294 | Buf *test_exe_path = buf_alloc(); | 1304 | Buf *test_exe_path = buf_alloc(); |
| 1295 | *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); | 1305 | *test_exe_path = os_path_resolve(&test_exe_path_unresolved, 1); |
tools/merge_anal_dumps.zig+104-11| ... | @@ -24,19 +24,49 @@ pub fn main() anyerror!void { | ... | @@ -24,19 +24,49 @@ pub fn main() anyerror!void { |
| 24 | try dump.render(&stdout.outStream().stream); | 24 | try dump.render(&stdout.outStream().stream); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | /// AST source node | ||
| 28 | const Node = struct { | ||
| 29 | file: usize, | ||
| 30 | line: usize, | ||
| 31 | col: usize, | ||
| 32 | fields: []usize, | ||
| 33 | |||
| 34 | fn hash(n: Node) u32 { | ||
| 35 | var hasher = std.hash.Wyhash.init(0); | ||
| 36 | std.hash.autoHash(&hasher, n.file); | ||
| 37 | std.hash.autoHash(&hasher, n.line); | ||
| 38 | std.hash.autoHash(&hasher, n.col); | ||
| 39 | return @truncate(u32, hasher.final()); | ||
| 40 | } | ||
| 41 | |||
| 42 | fn eql(a: Node, b: Node) bool { | ||
| 43 | return a.file == b.file and | ||
| 44 | a.line == b.line and | ||
| 45 | a.col == b.col; | ||
| 46 | } | ||
| 47 | }; | ||
| 48 | |||
| 27 | const Dump = struct { | 49 | const Dump = struct { |
| 28 | zig_id: ?[]const u8 = null, | 50 | zig_id: ?[]const u8 = null, |
| 29 | zig_version: ?[]const u8 = null, | 51 | zig_version: ?[]const u8 = null, |
| 30 | root_name: ?[]const u8 = null, | 52 | root_name: ?[]const u8 = null, |
| 31 | targets: std.ArrayList([]const u8), | 53 | targets: std.ArrayList([]const u8), |
| 32 | files_list: std.ArrayList([]const u8), | 54 | |
| 33 | files_map: std.StringHashMap(usize), | 55 | const FileMap = std.StringHashMap(usize); |
| 56 | file_list: std.ArrayList([]const u8), | ||
| 57 | file_map: FileMap, | ||
| 58 | |||
| 59 | const NodeMap = std.HashMap(Node, usize, Node.hash, Node.eql); | ||
| 60 | node_list: std.ArrayList(Node), | ||
| 61 | node_map: NodeMap, | ||
| 34 | 62 | ||
| 35 | fn init(allocator: *mem.Allocator) Dump { | 63 | fn init(allocator: *mem.Allocator) Dump { |
| 36 | return Dump{ | 64 | return Dump{ |
| 37 | .targets = std.ArrayList([]const u8).init(allocator), | 65 | .targets = std.ArrayList([]const u8).init(allocator), |
| 38 | .files_list = std.ArrayList([]const u8).init(allocator), | 66 | .file_list = std.ArrayList([]const u8).init(allocator), |
| 39 | .files_map = std.StringHashMap(usize).init(allocator), | 67 | .file_map = FileMap.init(allocator), |
| 68 | .node_list = std.ArrayList(Node).init(allocator), | ||
| 69 | .node_map = NodeMap.init(allocator), | ||
| 40 | }; | 70 | }; |
| 41 | } | 71 | } |
| 42 | 72 | ||
| ... | @@ -56,17 +86,45 @@ const Dump = struct { | ... | @@ -56,17 +86,45 @@ const Dump = struct { |
| 56 | const other_files = root.Object.get("files").?.value.Array.toSliceConst(); | 86 | const other_files = root.Object.get("files").?.value.Array.toSliceConst(); |
| 57 | var other_file_to_mine = std.AutoHashMap(usize, usize).init(self.a()); | 87 | var other_file_to_mine = std.AutoHashMap(usize, usize).init(self.a()); |
| 58 | for (other_files) |other_file, i| { | 88 | for (other_files) |other_file, i| { |
| 59 | const gop = try self.files_map.getOrPut(other_file.String); | 89 | const gop = try self.file_map.getOrPut(other_file.String); |
| 60 | if (gop.found_existing) { | 90 | if (!gop.found_existing) { |
| 61 | try other_file_to_mine.putNoClobber(i, gop.kv.value); | 91 | gop.kv.value = self.file_list.len; |
| 62 | } else { | 92 | try self.file_list.append(other_file.String); |
| 63 | gop.kv.value = self.files_list.len; | ||
| 64 | try self.files_list.append(other_file.String); | ||
| 65 | } | 93 | } |
| 94 | try other_file_to_mine.putNoClobber(i, gop.kv.value); | ||
| 66 | } | 95 | } |
| 67 | 96 | ||
| 97 | // Merge ast nodes | ||
| 68 | const other_ast_nodes = root.Object.get("astNodes").?.value.Array.toSliceConst(); | 98 | const other_ast_nodes = root.Object.get("astNodes").?.value.Array.toSliceConst(); |
| 69 | var other_ast_node_to_mine = std.AutoHashMap(usize, usize).init(self.a()); | 99 | var other_ast_node_to_mine = std.AutoHashMap(usize, usize).init(self.a()); |
| 100 | for (other_ast_nodes) |other_ast_node_json, i| { | ||
| 101 | const other_file_id = jsonObjInt(other_ast_node_json, "file"); | ||
| 102 | const other_node = Node{ | ||
| 103 | .line = jsonObjInt(other_ast_node_json, "line"), | ||
| 104 | .col = jsonObjInt(other_ast_node_json, "col"), | ||
| 105 | .file = other_file_to_mine.getValue(other_file_id).?, | ||
| 106 | .fields = ([*]usize)(undefined)[0..0], | ||
| 107 | }; | ||
| 108 | const gop = try self.node_map.getOrPut(other_node); | ||
| 109 | if (!gop.found_existing) { | ||
| 110 | gop.kv.value = self.node_list.len; | ||
| 111 | try self.node_list.append(other_node); | ||
| 112 | } | ||
| 113 | try other_ast_node_to_mine.putNoClobber(i, gop.kv.value); | ||
| 114 | } | ||
| 115 | // convert fields lists | ||
| 116 | for (other_ast_nodes) |other_ast_node_json, i| { | ||
| 117 | const my_node_index = other_ast_node_to_mine.get(i).?.value; | ||
| 118 | const my_node = &self.node_list.toSlice()[my_node_index]; | ||
| 119 | if (other_ast_node_json.Object.get("fields")) |fields_json_kv| { | ||
| 120 | const other_fields = fields_json_kv.value.Array.toSliceConst(); | ||
| 121 | my_node.fields = try self.a().alloc(usize, other_fields.len); | ||
| 122 | for (other_fields) |other_field_index, field_i| { | ||
| 123 | const other_index = @intCast(usize, other_field_index.Integer); | ||
| 124 | my_node.fields[field_i] = other_ast_node_to_mine.get(other_index).?.value; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | } | ||
| 70 | } | 128 | } |
| 71 | 129 | ||
| 72 | fn render(self: *Dump, stream: var) !void { | 130 | fn render(self: *Dump, stream: var) !void { |
| ... | @@ -81,9 +139,39 @@ const Dump = struct { | ... | @@ -81,9 +139,39 @@ const Dump = struct { |
| 81 | } | 139 | } |
| 82 | try jw.endArray(); | 140 | try jw.endArray(); |
| 83 | 141 | ||
| 142 | try jw.objectField("astNodes"); | ||
| 143 | try jw.beginArray(); | ||
| 144 | for (self.node_list.toSliceConst()) |node| { | ||
| 145 | try jw.arrayElem(); | ||
| 146 | try jw.beginObject(); | ||
| 147 | |||
| 148 | try jw.objectField("file"); | ||
| 149 | try jw.emitNumber(node.file); | ||
| 150 | |||
| 151 | try jw.objectField("line"); | ||
| 152 | try jw.emitNumber(node.line); | ||
| 153 | |||
| 154 | try jw.objectField("col"); | ||
| 155 | try jw.emitNumber(node.col); | ||
| 156 | |||
| 157 | if (node.fields.len != 0) { | ||
| 158 | try jw.objectField("fields"); | ||
| 159 | try jw.beginArray(); | ||
| 160 | |||
| 161 | for (node.fields) |field_node_index| { | ||
| 162 | try jw.arrayElem(); | ||
| 163 | try jw.emitNumber(field_node_index); | ||
| 164 | } | ||
| 165 | try jw.endArray(); | ||
| 166 | } | ||
| 167 | |||
| 168 | try jw.endObject(); | ||
| 169 | } | ||
| 170 | try jw.endArray(); | ||
| 171 | |||
| 84 | try jw.objectField("files"); | 172 | try jw.objectField("files"); |
| 85 | try jw.beginArray(); | 173 | try jw.beginArray(); |
| 86 | for (self.files_list.toSliceConst()) |file| { | 174 | for (self.file_list.toSliceConst()) |file| { |
| 87 | try jw.arrayElem(); | 175 | try jw.arrayElem(); |
| 88 | try jw.emitString(file); | 176 | try jw.emitString(file); |
| 89 | } | 177 | } |
| ... | @@ -105,3 +193,8 @@ const Dump = struct { | ... | @@ -105,3 +193,8 @@ const Dump = struct { |
| 105 | } | 193 | } |
| 106 | } | 194 | } |
| 107 | }; | 195 | }; |
| 196 | |||
| 197 | fn jsonObjInt(json_val: json.Value, field: []const u8) usize { | ||
| 198 | const uncasted = json_val.Object.get(field).?.value.Integer; | ||
| 199 | return @intCast(usize, uncasted); | ||
| 200 | } |