authorgravatar for kappaloris@gmail.comLoris Cro <kappaloris@gmail.com> 2022-06-10 19:00:40+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-07-19 19:10:12-07:00
log24a79426ecebc5ef4cdc8d1f16dacfdf74497e07
tree1fe656915d22bc3bb330d45bc43d2a0042dfe9a9
parent866bbb2e7a6ddffc28a3f68c41f3b8ea0ab4682b

autodoc: update array analysis to new Zir


2 files changed, 136 insertions(+), 251 deletions(-)

lib/docs/main.js+4-1
......@@ -816,6 +816,9 @@ var zigAnalysis;
816816 function exprName(expr, opts) {
817817 switch (Object.keys(expr)[0]) {
818818 default: throw "oh no";
819 case "&": {
820 return "&" + exprName(zigAnalysis.exprs[expr["&"]]);
821 }
819822 case "enumLiteral": {
820823 let literal = expr.enumLiteral;
821824 return literal;
......@@ -1482,7 +1485,7 @@ var zigAnalysis;
14821485 }
14831486 case typeKinds.Array:
14841487 {
1485 let arrayObj = (typeObj);
1488 let arrayObj = typeObj;
14861489 let name = "[";
14871490 let lenName = exprName(arrayObj.len, opts);
14881491 let sentinel = arrayObj.sentinel ? ":"+exprName(arrayObj.sentinel, opts) : "";
src/Autodoc.zig+132-250
......@@ -563,6 +563,7 @@ const DocData = struct {
563563 @"struct": []FieldVal,
564564 bool: bool,
565565 @"anytype": struct {},
566 @"&": usize, // index in `exprs`
566567 type: usize, // index in `types`
567568 this: usize, // index in `types`
568569 declRef: usize, // index in `decls`
......@@ -1314,18 +1315,18 @@ fn walkInstruction(
13141315 .expr = .{ .errorSets = type_slot_index },
13151316 };
13161317 },
1317 .elem_type => {
1318 const un_node = data[inst_index].un_node;
1318 // .elem_type => {
1319 // const un_node = data[inst_index].un_node;
13191320
1320 var operand: DocData.WalkResult = try self.walkRef(
1321 file,
1322 parent_scope,
1323 un_node.operand,
1324 false,
1325 );
1321 // var operand: DocData.WalkResult = try self.walkRef(
1322 // file,
1323 // parent_scope,
1324 // un_node.operand,
1325 // false,
1326 // );
13261327
1327 return operand;
1328 },
1328 // return operand;
1329 // },
13291330 .ptr_type_simple => {
13301331 const ptr = data[inst_index].ptr_type_simple;
13311332 const elem_type_ref = try self.walkRef(file, parent_scope, ptr.elem_type, false);
......@@ -1452,72 +1453,23 @@ fn walkInstruction(
14521453 };
14531454 },
14541455 .array_init => {
1455 const pl_node = data[inst_index].pl_node;
1456 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
1457 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
1458 const array_data = try self.arena.alloc(usize, operands.len);
1459
1460 // TODO: make sure that you want the array to be fully normalized for real
1461 // then update this code to conform to your choice.
1462
1463 var array_type: ?DocData.Expr = null;
1464 for (operands) |op, idx| {
1465 // we only ask to figure out type info for the first element
1466 // as it will be used later on to find out the array type!
1467 const wr = try self.walkRef(file, parent_scope, op, idx == 0);
1468
1469 if (idx == 0) {
1470 array_type = wr.typeRef;
1471 }
1472
1473 // We know that Zir wraps every operand in an @as expression
1474 // so we want to peel it away and only save the target type
1475 // once, since we need it later to define the array type.
1476 array_data[idx] = wr.expr.as.exprArg;
1477 }
1478
1479 const type_slot_index = self.types.items.len;
1480 try self.types.append(self.arena, .{ .Pointer = .{
1481 .size = .Slice,
1482 .child = array_type.?,
1483 .is_mutable = true,
1484 } });
1485
1486 return DocData.WalkResult{
1487 .typeRef = .{ .type = type_slot_index },
1488 .expr = .{ .array = array_data },
1489 };
1490 },
1491 .array_init_sent => {
14921456 const pl_node = data[inst_index].pl_node;
14931457 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
14941458 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
14951459 const array_data = try self.arena.alloc(usize, operands.len - 1);
14961460
1497 // TODO: make sure that you want the array to be fully normalized for real
1498 // then update this code to conform to your choice.
1499 var sentinel: ?DocData.Expr = null;
1500 var array_type: ?DocData.Expr = null;
1501 for (operands) |op, idx| {
1502 // we only ask to figure out type info for the first element
1503 // as it will be used later on to find out the array type!
1504 const wr = try self.walkRef(file, parent_scope, op, idx == 0);
1505 if (idx == 0) {
1506 array_type = wr.typeRef;
1507 }
1461 std.debug.assert(operands.len > 0);
1462 var array_type = try self.walkRef(file, parent_scope, operands[0], false);
15081463
1509 if (idx == extra.data.operands_len - 1) {
1510 sentinel = self.exprs.items[wr.expr.as.exprArg];
1511 } else {
1512 array_data[idx] = wr.expr.as.exprArg;
1513 }
1464 for (operands[1..]) |op, idx| {
1465 const wr = try self.walkRef(file, parent_scope, op, false);
1466 const expr_index = self.exprs.items.len;
1467 try self.exprs.append(self.arena, wr.expr);
1468 array_data[idx] = expr_index;
15141469 }
15151470
1516 const type_slot_index = self.types.items.len;
1517 try self.types.append(self.arena, .{ .Pointer = .{ .size = .Slice, .child = array_type.?, .is_mutable = true, .sentinel = sentinel } });
1518
15191471 return DocData.WalkResult{
1520 .typeRef = .{ .type = type_slot_index },
1472 .typeRef = array_type.expr,
15211473 .expr = .{ .array = array_data },
15221474 };
15231475 },
......@@ -1527,110 +1479,48 @@ fn walkInstruction(
15271479 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
15281480 const array_data = try self.arena.alloc(usize, operands.len);
15291481
1530 // TODO: make sure that you want the array to be fully normalized for real
1531 // then update this code to conform to your choice.
1532
1533 var array_type: ?DocData.Expr = null;
15341482 for (operands) |op, idx| {
1535 // we only ask to figure out type info for the first element
1536 // as it will be used later on to find out the array type!
1537 const wr = try self.walkRef(file, parent_scope, op, idx == 0);
1538 if (idx == 0) {
1539 array_type = wr.typeRef;
1540 }
1541
1542 // array_init_anon doesn't have the elements in @as nodes
1543 // so it's necessary append them to expr array
1544 // and remember their positions
1483 const wr = try self.walkRef(file, parent_scope, op, false);
15451484 const expr_index = self.exprs.items.len;
15461485 try self.exprs.append(self.arena, wr.expr);
15471486 array_data[idx] = expr_index;
15481487 }
15491488
1550 if (array_type == null) {
1551 panicWithContext(
1552 file,
1553 inst_index,
1554 "array_type was null!!",
1555 .{},
1556 );
1557 }
1558
1559 const type_slot_index = self.types.items.len;
1560 try self.types.append(self.arena, .{
1561 .Array = .{
1562 .len = .{
1563 .int = .{
1564 .value = operands.len,
1565 .negated = false,
1566 },
1567 },
1568 .child = array_type.?,
1569 },
1570 });
1571
15721489 return DocData.WalkResult{
1573 .typeRef = .{ .type = type_slot_index },
1490 .typeRef = null,
15741491 .expr = .{ .array = array_data },
15751492 };
15761493 },
15771494 .array_init_ref => {
1578 const pl_node = data[inst_index].pl_node;
1579 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
1580 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
1581 const array_data = try self.arena.alloc(usize, operands.len);
1582
1583 var array_type: ?DocData.Expr = null;
1584 for (operands) |op, idx| {
1585 const wr = try self.walkRef(file, parent_scope, op, idx == 0);
1586 if (idx == 0) {
1587 array_type = wr.typeRef;
1588 }
1589 array_data[idx] = wr.expr.as.exprArg;
1590 }
1591
1592 const type_slot_index = self.types.items.len;
1593 try self.types.append(self.arena, .{ .Pointer = .{
1594 .size = .One,
1595 .child = array_type.?,
1596 } });
1597
1598 return DocData.WalkResult{
1599 .typeRef = .{ .type = type_slot_index },
1600 .expr = .{ .array = array_data },
1601 };
1602 },
1603 .array_init_sent_ref => {
16041495 const pl_node = data[inst_index].pl_node;
16051496 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
16061497 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
16071498 const array_data = try self.arena.alloc(usize, operands.len - 1);
16081499
1609 // TODO: This should output:
1610 // const array: *[value:sentinel]type = &.{};
1611 // but right now it's printing:
1612 // const array: [value:sentinel]u8 = .{};
1500 std.debug.assert(operands.len > 0);
1501 var array_type = try self.walkRef(file, parent_scope, operands[0], false);
16131502
1614 var sentinel: ?DocData.Expr = null;
1615 var array_type: ?DocData.Expr = null;
1616 for (operands) |op, idx| {
1617 const wr = try self.walkRef(file, parent_scope, op, idx == 0);
1618 if (idx == 0) {
1619 array_type = wr.typeRef;
1620 }
1621 if (idx == extra.data.operands_len - 1) {
1622 sentinel = self.exprs.items[wr.expr.as.exprArg];
1623 } else {
1624 array_data[idx] = wr.expr.as.exprArg;
1625 }
1503 for (operands[1..]) |op, idx| {
1504 const wr = try self.walkRef(file, parent_scope, op, false);
1505 const expr_index = self.exprs.items.len;
1506 try self.exprs.append(self.arena, wr.expr);
1507 array_data[idx] = expr_index;
16261508 }
16271509
16281510 const type_slot_index = self.types.items.len;
1629 try self.types.append(self.arena, .{ .Pointer = .{ .size = .Slice, .child = array_type.?, .is_mutable = true, .sentinel = sentinel } });
1511 try self.types.append(self.arena, .{
1512 .Pointer = .{
1513 .size = .One,
1514 .child = array_type.expr,
1515 },
1516 });
1517
1518 const expr_index = self.exprs.items.len;
1519 try self.exprs.append(self.arena, .{ .array = array_data });
16301520
16311521 return DocData.WalkResult{
16321522 .typeRef = .{ .type = type_slot_index },
1633 .expr = .{ .array = array_data },
1523 .expr = .{ .@"&" = expr_index },
16341524 };
16351525 },
16361526 .array_init_anon_ref => {
......@@ -1639,29 +1529,19 @@ fn walkInstruction(
16391529 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
16401530 const array_data = try self.arena.alloc(usize, operands.len);
16411531
1642 var array_type: ?DocData.Expr = null;
16431532 for (operands) |op, idx| {
1644 const wr = try self.walkRef(file, parent_scope, op, idx == 0);
1645 if (idx == 0) {
1646 array_type = wr.typeRef;
1647 }
1648
1533 const wr = try self.walkRef(file, parent_scope, op, false);
16491534 const expr_index = self.exprs.items.len;
16501535 try self.exprs.append(self.arena, wr.expr);
16511536 array_data[idx] = expr_index;
16521537 }
16531538
1654 const type_slot_index = self.types.items.len;
1655 try self.types.append(self.arena, .{ .Pointer = .{
1656 .size = .Slice,
1657 .child = array_type.?,
1658 .is_mutable = true,
1659 .is_ref = true,
1660 } });
1539 const expr_index = self.exprs.items.len;
1540 try self.exprs.append(self.arena, .{ .array = array_data });
16611541
16621542 return DocData.WalkResult{
1663 .typeRef = .{ .type = type_slot_index },
1664 .expr = .{ .array = array_data },
1543 .typeRef = null,
1544 .expr = .{ .@"&" = expr_index },
16651545 };
16661546 },
16671547 .float => {
......@@ -2188,20 +2068,20 @@ fn walkInstruction(
21882068
21892069 return result;
21902070 },
2191 .func_extended => {
2192 const type_slot_index = self.types.items.len;
2193 try self.types.append(self.arena, .{ .Unanalyzed = .{} });
2071 // .func_extended => {
2072 // const type_slot_index = self.types.items.len;
2073 // try self.types.append(self.arena, .{ .Unanalyzed = .{} });
21942074
2195 const result = self.analyzeFunctionExtended(
2196 file,
2197 parent_scope,
2198 inst_index,
2199 self_ast_node_index,
2200 type_slot_index,
2201 );
2075 // const result = self.analyzeFunctionExtended(
2076 // file,
2077 // parent_scope,
2078 // inst_index,
2079 // self_ast_node_index,
2080 // type_slot_index,
2081 // );
22022082
2203 return result;
2204 },
2083 // return result;
2084 // },
22052085 .extended => {
22062086 const extended = data[inst_index].extended;
22072087 switch (extended.opcode) {
......@@ -2766,81 +2646,83 @@ fn walkDecls(
27662646 break :blk "test";
27672647 } else if (decl_name_index == 2) {
27682648 is_test = true;
2769 // it is a decltest
2770 const decl_being_tested = scope.resolveDeclName(doc_comment_index);
2771 const ast_node_index = idx: {
2772 const idx = self.ast_nodes.items.len;
2773 const file_source = file.getSource(self.module.gpa) catch unreachable; // TODO fix this
2774 const source_of_decltest_function = srcloc: {
2775 const func_index = getBlockInlineBreak(file.zir, value_index);
2776 // a decltest is always a function
2777 const tag = file.zir.instructions.items(.tag)[Zir.refToIndex(func_index).?];
2778 std.debug.assert(tag == .func_extended);
2779
2780 const pl_node = file.zir.instructions.items(.data)[Zir.refToIndex(func_index).?].pl_node;
2781 const extra = file.zir.extraData(Zir.Inst.ExtendedFunc, pl_node.payload_index);
2782 const bits = @bitCast(Zir.Inst.ExtendedFunc.Bits, extra.data.bits);
2783
2784 var extra_index_for_this_func: usize = extra.end;
2785 if (bits.has_lib_name) extra_index_for_this_func += 1;
2786 if (bits.has_cc) extra_index_for_this_func += 1;
2787 if (bits.has_align) extra_index_for_this_func += 1;
2788
2789 const ret_ty_body = file.zir.extra[extra_index_for_this_func..][0..extra.data.ret_body_len];
2790 extra_index_for_this_func += ret_ty_body.len;
2791
2792 const body = file.zir.extra[extra_index_for_this_func..][0..extra.data.body_len];
2793 extra_index_for_this_func += body.len;
2794
2795 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
2796 if (body.len != 0) {
2797 src_locs = file.zir.extraData(Zir.Inst.Func.SrcLocs, extra_index_for_this_func).data;
2798 } else {
2799 src_locs = .{
2800 .lbrace_line = line,
2801 .rbrace_line = line,
2802 .columns = 0, // TODO get columns when body.len == 0
2803 };
2804 }
2805 break :srcloc src_locs;
2806 };
2807 const source_slice = slice: {
2808 var start_byte_offset: u32 = 0;
2809 var end_byte_offset: u32 = 0;
2810 const rbrace_col = @truncate(u16, source_of_decltest_function.columns >> 16);
2811 var lines: u32 = 0;
2812 for (file_source.bytes) |b, i| {
2813 if (b == '\n') {
2814 lines += 1;
2815 }
2816 if (lines == source_of_decltest_function.lbrace_line) {
2817 start_byte_offset = @intCast(u32, i);
2818 }
2819 if (lines == source_of_decltest_function.rbrace_line) {
2820 end_byte_offset = @intCast(u32, i) + rbrace_col;
2821 break;
2822 }
2823 }
2824 break :slice file_source.bytes[start_byte_offset..end_byte_offset];
2825 };
2826 try self.ast_nodes.append(self.arena, .{
2827 .file = 0,
2828 .line = line,
2829 .col = 0,
2830 .name = try self.arena.dupe(u8, source_slice),
2831 });
2832 break :idx idx;
2833 };
2834 self.decls.items[decl_being_tested].decltest = ast_node_index;
2835 self.decls.items[decls_slot_index] = .{
2836 ._analyzed = true,
2837 .name = "test",
2838 .isTest = true,
2839 .src = ast_node_index,
2840 .value = .{ .expr = .{ .type = 0 } },
2841 .kind = "const",
2842 };
2843 continue;
2649 // TODO: remove temporary hack
2650 break :blk "test";
2651 // // it is a decltest
2652 // const decl_being_tested = scope.resolveDeclName(doc_comment_index);
2653 // const ast_node_index = idx: {
2654 // const idx = self.ast_nodes.items.len;
2655 // const file_source = file.getSource(self.module.gpa) catch unreachable; // TODO fix this
2656 // const source_of_decltest_function = srcloc: {
2657 // const func_index = getBlockInlineBreak(file.zir, value_index);
2658 // // a decltest is always a function
2659 // const tag = file.zir.instructions.items(.tag)[Zir.refToIndex(func_index).?];
2660 // std.debug.assert(tag == .func_extended);
2661
2662 // const pl_node = file.zir.instructions.items(.data)[Zir.refToIndex(func_index).?].pl_node;
2663 // const extra = file.zir.extraData(Zir.Inst.ExtendedFunc, pl_node.payload_index);
2664 // const bits = @bitCast(Zir.Inst.ExtendedFunc.Bits, extra.data.bits);
2665
2666 // var extra_index_for_this_func: usize = extra.end;
2667 // if (bits.has_lib_name) extra_index_for_this_func += 1;
2668 // if (bits.has_cc) extra_index_for_this_func += 1;
2669 // if (bits.has_align) extra_index_for_this_func += 1;
2670
2671 // const ret_ty_body = file.zir.extra[extra_index_for_this_func..][0..extra.data.ret_body_len];
2672 // extra_index_for_this_func += ret_ty_body.len;
2673
2674 // const body = file.zir.extra[extra_index_for_this_func..][0..extra.data.body_len];
2675 // extra_index_for_this_func += body.len;
2676
2677 // var src_locs: Zir.Inst.Func.SrcLocs = undefined;
2678 // if (body.len != 0) {
2679 // src_locs = file.zir.extraData(Zir.Inst.Func.SrcLocs, extra_index_for_this_func).data;
2680 // } else {
2681 // src_locs = .{
2682 // .lbrace_line = line,
2683 // .rbrace_line = line,
2684 // .columns = 0, // TODO get columns when body.len == 0
2685 // };
2686 // }
2687 // break :srcloc src_locs;
2688 // };
2689 // const source_slice = slice: {
2690 // var start_byte_offset: u32 = 0;
2691 // var end_byte_offset: u32 = 0;
2692 // const rbrace_col = @truncate(u16, source_of_decltest_function.columns >> 16);
2693 // var lines: u32 = 0;
2694 // for (file_source.bytes) |b, i| {
2695 // if (b == '\n') {
2696 // lines += 1;
2697 // }
2698 // if (lines == source_of_decltest_function.lbrace_line) {
2699 // start_byte_offset = @intCast(u32, i);
2700 // }
2701 // if (lines == source_of_decltest_function.rbrace_line) {
2702 // end_byte_offset = @intCast(u32, i) + rbrace_col;
2703 // break;
2704 // }
2705 // }
2706 // break :slice file_source.bytes[start_byte_offset..end_byte_offset];
2707 // };
2708 // try self.ast_nodes.append(self.arena, .{
2709 // .file = 0,
2710 // .line = line,
2711 // .col = 0,
2712 // .name = try self.arena.dupe(u8, source_slice),
2713 // });
2714 // break :idx idx;
2715 // };
2716 // self.decls.items[decl_being_tested].decltest = ast_node_index;
2717 // self.decls.items[decls_slot_index] = .{
2718 // ._analyzed = true,
2719 // .name = "test",
2720 // .isTest = true,
2721 // .src = ast_node_index,
2722 // .value = .{ .expr = .{ .type = 0 } },
2723 // .kind = "const",
2724 // };
2725 // continue;
28442726 } else {
28452727 const raw_decl_name = file.zir.nullTerminatedString(decl_name_index);
28462728 if (raw_decl_name.len == 0) {