| ... | @@ -239,11 +239,47 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! | ... | @@ -239,11 +239,47 @@ pub fn run(gpa: Allocator, arena: Allocator, io: Io, args: []const []const u8) ! |
| 239 | | 239 | |
| 240 | if (fmt.stats) |stats| { | 240 | if (fmt.stats) |stats| { |
| 241 | if (stats.files > 1) { | 241 | if (stats.files > 1) { |
| 242 | try stats.root_struct.field("files", stats.files, .{}); | 242 | var agg_struct = try stats.root_struct.beginStructField("aggregate", .{}); |
| 243 | try stats.root_struct.field("tokens", stats.tokens, .{}); | 243 | try agg_struct.field("file_count", stats.files, .{}); |
| 244 | try stats.root_struct.field("nodes", stats.nodes, .{}); | 244 | try agg_struct.field("token_count", stats.tokens, .{}); |
| | 245 | try agg_struct.field("node_count", stats.nodes, .{}); |
| | 246 | |
| | 247 | const token_names = @typeInfo(std.zig.Token.Tag).@"enum".field_names; |
| | 248 | const node_names = @typeInfo(std.zig.Ast.Node.Tag).@"enum".field_names; |
| | 249 | |
| | 250 | var token_order: [token_names.len]usize = undefined; |
| | 251 | var node_order: [node_names.len]usize = undefined; |
| | 252 | { |
| | 253 | for (&token_order, 0..) |*elem, i| elem.* = i; |
| | 254 | std.mem.sortContext(0, token_names.len, @as(SortContext, .{ |
| | 255 | .stats = stats.token_stats, |
| | 256 | .order = &token_order, |
| | 257 | })); |
| | 258 | var tokens_struct = try agg_struct.beginStructField("tokens", .{}); |
| | 259 | for (&token_order) |i| { |
| | 260 | const n = stats.token_stats[i]; |
| | 261 | if (n != 0) try tokens_struct.field(token_names[i], n, .{}); |
| | 262 | } |
| | 263 | try tokens_struct.end(); |
| | 264 | } |
| | 265 | { |
| | 266 | for (&node_order, 0..) |*elem, i| elem.* = i; |
| | 267 | std.mem.sortContext(0, node_names.len, @as(SortContext, .{ |
| | 268 | .stats = stats.node_stats, |
| | 269 | .order = &node_order, |
| | 270 | })); |
| | 271 | var nodes_struct = try agg_struct.beginStructField("nodes", .{}); |
| | 272 | for (&node_order) |i| { |
| | 273 | const n = stats.node_stats[i]; |
| | 274 | if (n != 0) try nodes_struct.field(node_names[i], n, .{}); |
| | 275 | } |
| | 276 | try nodes_struct.end(); |
| | 277 | } |
| | 278 | |
| | 279 | try agg_struct.end(); |
| 245 | } | 280 | } |
| 246 | try stats.root_struct.end(); | 281 | try stats.root_struct.end(); |
| | 282 | try fmt.stdout_writer.interface.writeByte('\n'); |
| 247 | } | 283 | } |
| 248 | | 284 | |
| 249 | try fmt.stdout_writer.flush(); | 285 | try fmt.stdout_writer.flush(); |
| ... | @@ -413,19 +449,6 @@ fn fmtPathFile( | ... | @@ -413,19 +449,6 @@ fn fmtPathFile( |
| 413 | node_stats[@backingInt(tag)] += 1; | 449 | node_stats[@backingInt(tag)] += 1; |
| 414 | } | 450 | } |
| 415 | | 451 | |
| 416 | const SortContext = struct { | | |
| 417 | stats: []const u64, | | |
| 418 | order: []usize, | | |
| 419 | | | |
| 420 | pub fn lessThan(this: @This(), a_index: usize, b_index: usize) bool { | | |
| 421 | return this.stats[this.order[b_index]] < this.stats[this.order[a_index]]; | | |
| 422 | } | | |
| 423 | | | |
| 424 | pub fn swap(this: @This(), a_index: usize, b_index: usize) void { | | |
| 425 | std.mem.swap(usize, &this.order[a_index], &this.order[b_index]); | | |
| 426 | } | | |
| 427 | }; | | |
| 428 | | | |
| 429 | { | 452 | { |
| 430 | for (&token_order, 0..) |*elem, i| elem.* = i; | 453 | for (&token_order, 0..) |*elem, i| elem.* = i; |
| 431 | std.mem.sortContext(0, token_names.len, @as(SortContext, .{ | 454 | std.mem.sortContext(0, token_names.len, @as(SortContext, .{ |
| ... | @@ -435,7 +458,7 @@ fn fmtPathFile( | ... | @@ -435,7 +458,7 @@ fn fmtPathFile( |
| 435 | var s = try zon_struct.beginStructField("tokens", .{}); | 458 | var s = try zon_struct.beginStructField("tokens", .{}); |
| 436 | for (&token_order) |i| { | 459 | for (&token_order) |i| { |
| 437 | const n = token_stats[i]; | 460 | const n = token_stats[i]; |
| 438 | if (n != 0) try zon_struct.field(token_names[i], n, .{}); | 461 | if (n != 0) try s.field(token_names[i], n, .{}); |
| 439 | } | 462 | } |
| 440 | try s.end(); | 463 | try s.end(); |
| 441 | } | 464 | } |
| ... | @@ -449,13 +472,14 @@ fn fmtPathFile( | ... | @@ -449,13 +472,14 @@ fn fmtPathFile( |
| 449 | var s = try zon_struct.beginStructField("nodes", .{}); | 472 | var s = try zon_struct.beginStructField("nodes", .{}); |
| 450 | for (&node_order) |i| { | 473 | for (&node_order) |i| { |
| 451 | const n = node_stats[i]; | 474 | const n = node_stats[i]; |
| 452 | if (n != 0) try zon_struct.field(node_names[i], n, .{}); | 475 | if (n != 0) try s.field(node_names[i], n, .{}); |
| 453 | } | 476 | } |
| 454 | try s.end(); | 477 | try s.end(); |
| 455 | } | 478 | } |
| 456 | | 479 | |
| 457 | stats.tokens += tree.tokens.len; | 480 | stats.tokens += tree.tokens.len; |
| 458 | stats.nodes += tree.nodes.len; | 481 | stats.nodes += tree.nodes.len; |
| | 482 | stats.files += 1; |
| 459 | } | 483 | } |
| 460 | | 484 | |
| 461 | // As a heuristic, we make enough capacity for the same as the input source. | 485 | // As a heuristic, we make enough capacity for the same as the input source. |
| ... | @@ -485,6 +509,19 @@ fn fmtPathFile( | ... | @@ -485,6 +509,19 @@ fn fmtPathFile( |
| 485 | if (fmt.stats != null) try zon_struct.end(); | 509 | if (fmt.stats != null) try zon_struct.end(); |
| 486 | } | 510 | } |
| 487 | | 511 | |
| | 512 | const SortContext = struct { |
| | 513 | stats: []const u64, |
| | 514 | order: []usize, |
| | 515 | |
| | 516 | pub fn lessThan(this: @This(), a_index: usize, b_index: usize) bool { |
| | 517 | return this.stats[this.order[b_index]] < this.stats[this.order[a_index]]; |
| | 518 | } |
| | 519 | |
| | 520 | pub fn swap(this: @This(), a_index: usize, b_index: usize) void { |
| | 521 | std.mem.swap(usize, &this.order[a_index], &this.order[b_index]); |
| | 522 | } |
| | 523 | }; |
| | 524 | |
| 488 | /// Provided for debugging/testing purposes; unused by the compiler. | 525 | /// Provided for debugging/testing purposes; unused by the compiler. |
| 489 | pub fn main(init: process.Init) !void { | 526 | pub fn main(init: process.Init) !void { |
| 490 | const args = try init.minimal.args.toSlice(init.arena.allocator()); | 527 | const args = try init.minimal.args.toSlice(init.arena.allocator()); |