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;...@@ -816,6 +816,9 @@ var zigAnalysis;
816 function exprName(expr, opts) {816 function exprName(expr, opts) {
817 switch (Object.keys(expr)[0]) {817 switch (Object.keys(expr)[0]) {
818 default: throw "oh no";818 default: throw "oh no";
819 case "&": {
820 return "&" + exprName(zigAnalysis.exprs[expr["&"]]);
821 }
819 case "enumLiteral": {822 case "enumLiteral": {
820 let literal = expr.enumLiteral;823 let literal = expr.enumLiteral;
821 return literal;824 return literal;
...@@ -1482,7 +1485,7 @@ var zigAnalysis;...@@ -1482,7 +1485,7 @@ var zigAnalysis;
1482 }1485 }
1483 case typeKinds.Array:1486 case typeKinds.Array:
1484 {1487 {
1485 let arrayObj = (typeObj);1488 let arrayObj = typeObj;
1486 let name = "[";1489 let name = "[";
1487 let lenName = exprName(arrayObj.len, opts);1490 let lenName = exprName(arrayObj.len, opts);
1488 let sentinel = arrayObj.sentinel ? ":"+exprName(arrayObj.sentinel, opts) : "";1491 let sentinel = arrayObj.sentinel ? ":"+exprName(arrayObj.sentinel, opts) : "";
src/Autodoc.zig+132-250
...@@ -563,6 +563,7 @@ const DocData = struct {...@@ -563,6 +563,7 @@ const DocData = struct {
563 @"struct": []FieldVal,563 @"struct": []FieldVal,
564 bool: bool,564 bool: bool,
565 @"anytype": struct {},565 @"anytype": struct {},
566 @"&": usize, // index in `exprs`
566 type: usize, // index in `types`567 type: usize, // index in `types`
567 this: usize, // index in `types`568 this: usize, // index in `types`
568 declRef: usize, // index in `decls`569 declRef: usize, // index in `decls`
...@@ -1314,18 +1315,18 @@ fn walkInstruction(...@@ -1314,18 +1315,18 @@ fn walkInstruction(
1314 .expr = .{ .errorSets = type_slot_index },1315 .expr = .{ .errorSets = type_slot_index },
1315 };1316 };
1316 },1317 },
1317 .elem_type => {1318 // .elem_type => {
1318 const un_node = data[inst_index].un_node;1319 // const un_node = data[inst_index].un_node;
13191320
1320 var operand: DocData.WalkResult = try self.walkRef(1321 // var operand: DocData.WalkResult = try self.walkRef(
1321 file,1322 // file,
1322 parent_scope,1323 // parent_scope,
1323 un_node.operand,1324 // un_node.operand,
1324 false,1325 // false,
1325 );1326 // );
13261327
1327 return operand;1328 // return operand;
1328 },1329 // },
1329 .ptr_type_simple => {1330 .ptr_type_simple => {
1330 const ptr = data[inst_index].ptr_type_simple;1331 const ptr = data[inst_index].ptr_type_simple;
1331 const elem_type_ref = try self.walkRef(file, parent_scope, ptr.elem_type, false);1332 const elem_type_ref = try self.walkRef(file, parent_scope, ptr.elem_type, false);
...@@ -1452,72 +1453,23 @@ fn walkInstruction(...@@ -1452,72 +1453,23 @@ fn walkInstruction(
1452 };1453 };
1453 },1454 },
1454 .array_init => {1455 .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 => {
1492 const pl_node = data[inst_index].pl_node;1456 const pl_node = data[inst_index].pl_node;
1493 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);1457 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
1494 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);1458 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
1495 const array_data = try self.arena.alloc(usize, operands.len - 1);1459 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 real1461 std.debug.assert(operands.len > 0);
1498 // then update this code to conform to your choice.1462 var array_type = try self.walkRef(file, parent_scope, operands[0], false);
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 }
15081463
1509 if (idx == extra.data.operands_len - 1) {1464 for (operands[1..]) |op, idx| {
1510 sentinel = self.exprs.items[wr.expr.as.exprArg];1465 const wr = try self.walkRef(file, parent_scope, op, false);
1511 } else {1466 const expr_index = self.exprs.items.len;
1512 array_data[idx] = wr.expr.as.exprArg;1467 try self.exprs.append(self.arena, wr.expr);
1513 }1468 array_data[idx] = expr_index;
1514 }1469 }
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
1519 return DocData.WalkResult{1471 return DocData.WalkResult{
1520 .typeRef = .{ .type = type_slot_index },1472 .typeRef = array_type.expr,
1521 .expr = .{ .array = array_data },1473 .expr = .{ .array = array_data },
1522 };1474 };
1523 },1475 },
...@@ -1527,110 +1479,48 @@ fn walkInstruction(...@@ -1527,110 +1479,48 @@ fn walkInstruction(
1527 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);1479 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
1528 const array_data = try self.arena.alloc(usize, operands.len);1480 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;
1534 for (operands) |op, idx| {1482 for (operands) |op, idx| {
1535 // we only ask to figure out type info for the first element1483 const wr = try self.walkRef(file, parent_scope, op, false);
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
1545 const expr_index = self.exprs.items.len;1484 const expr_index = self.exprs.items.len;
1546 try self.exprs.append(self.arena, wr.expr);1485 try self.exprs.append(self.arena, wr.expr);
1547 array_data[idx] = expr_index;1486 array_data[idx] = expr_index;
1548 }1487 }
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
1572 return DocData.WalkResult{1489 return DocData.WalkResult{
1573 .typeRef = .{ .type = type_slot_index },1490 .typeRef = null,
1574 .expr = .{ .array = array_data },1491 .expr = .{ .array = array_data },
1575 };1492 };
1576 },1493 },
1577 .array_init_ref => {1494 .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 => {
1604 const pl_node = data[inst_index].pl_node;1495 const pl_node = data[inst_index].pl_node;
1605 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);1496 const extra = file.zir.extraData(Zir.Inst.MultiOp, pl_node.payload_index);
1606 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);1497 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
1607 const array_data = try self.arena.alloc(usize, operands.len - 1);1498 const array_data = try self.arena.alloc(usize, operands.len - 1);
16081499
1609 // TODO: This should output:1500 std.debug.assert(operands.len > 0);
1610 // const array: *[value:sentinel]type = &.{};1501 var array_type = try self.walkRef(file, parent_scope, operands[0], false);
1611 // but right now it's printing:
1612 // const array: [value:sentinel]u8 = .{};
16131502
1614 var sentinel: ?DocData.Expr = null;1503 for (operands[1..]) |op, idx| {
1615 var array_type: ?DocData.Expr = null;1504 const wr = try self.walkRef(file, parent_scope, op, false);
1616 for (operands) |op, idx| {1505 const expr_index = self.exprs.items.len;
1617 const wr = try self.walkRef(file, parent_scope, op, idx == 0);1506 try self.exprs.append(self.arena, wr.expr);
1618 if (idx == 0) {1507 array_data[idx] = expr_index;
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 }
1626 }1508 }
16271509
1628 const type_slot_index = self.types.items.len;1510 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
1631 return DocData.WalkResult{1521 return DocData.WalkResult{
1632 .typeRef = .{ .type = type_slot_index },1522 .typeRef = .{ .type = type_slot_index },
1633 .expr = .{ .array = array_data },1523 .expr = .{ .@"&" = expr_index },
1634 };1524 };
1635 },1525 },
1636 .array_init_anon_ref => {1526 .array_init_anon_ref => {
...@@ -1639,29 +1529,19 @@ fn walkInstruction(...@@ -1639,29 +1529,19 @@ fn walkInstruction(
1639 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);1529 const operands = file.zir.refSlice(extra.end, extra.data.operands_len);
1640 const array_data = try self.arena.alloc(usize, operands.len);1530 const array_data = try self.arena.alloc(usize, operands.len);
16411531
1642 var array_type: ?DocData.Expr = null;
1643 for (operands) |op, idx| {1532 for (operands) |op, idx| {
1644 const wr = try self.walkRef(file, parent_scope, op, idx == 0);1533 const wr = try self.walkRef(file, parent_scope, op, false);
1645 if (idx == 0) {
1646 array_type = wr.typeRef;
1647 }
1648
1649 const expr_index = self.exprs.items.len;1534 const expr_index = self.exprs.items.len;
1650 try self.exprs.append(self.arena, wr.expr);1535 try self.exprs.append(self.arena, wr.expr);
1651 array_data[idx] = expr_index;1536 array_data[idx] = expr_index;
1652 }1537 }
16531538
1654 const type_slot_index = self.types.items.len;1539 const expr_index = self.exprs.items.len;
1655 try self.types.append(self.arena, .{ .Pointer = .{1540 try self.exprs.append(self.arena, .{ .array = array_data });
1656 .size = .Slice,
1657 .child = array_type.?,
1658 .is_mutable = true,
1659 .is_ref = true,
1660 } });
16611541
1662 return DocData.WalkResult{1542 return DocData.WalkResult{
1663 .typeRef = .{ .type = type_slot_index },1543 .typeRef = null,
1664 .expr = .{ .array = array_data },1544 .expr = .{ .@"&" = expr_index },
1665 };1545 };
1666 },1546 },
1667 .float => {1547 .float => {
...@@ -2188,20 +2068,20 @@ fn walkInstruction(...@@ -2188,20 +2068,20 @@ fn walkInstruction(
21882068
2189 return result;2069 return result;
2190 },2070 },
2191 .func_extended => {2071 // .func_extended => {
2192 const type_slot_index = self.types.items.len;2072 // const type_slot_index = self.types.items.len;
2193 try self.types.append(self.arena, .{ .Unanalyzed = .{} });2073 // try self.types.append(self.arena, .{ .Unanalyzed = .{} });
21942074
2195 const result = self.analyzeFunctionExtended(2075 // const result = self.analyzeFunctionExtended(
2196 file,2076 // file,
2197 parent_scope,2077 // parent_scope,
2198 inst_index,2078 // inst_index,
2199 self_ast_node_index,2079 // self_ast_node_index,
2200 type_slot_index,2080 // type_slot_index,
2201 );2081 // );
22022082
2203 return result;2083 // return result;
2204 },2084 // },
2205 .extended => {2085 .extended => {
2206 const extended = data[inst_index].extended;2086 const extended = data[inst_index].extended;
2207 switch (extended.opcode) {2087 switch (extended.opcode) {
...@@ -2766,81 +2646,83 @@ fn walkDecls(...@@ -2766,81 +2646,83 @@ fn walkDecls(
2766 break :blk "test";2646 break :blk "test";
2767 } else if (decl_name_index == 2) {2647 } else if (decl_name_index == 2) {
2768 is_test = true;2648 is_test = true;
2769 // it is a decltest2649 // TODO: remove temporary hack
2770 const decl_being_tested = scope.resolveDeclName(doc_comment_index);2650 break :blk "test";
2771 const ast_node_index = idx: {2651 // // it is a decltest
2772 const idx = self.ast_nodes.items.len;2652 // const decl_being_tested = scope.resolveDeclName(doc_comment_index);
2773 const file_source = file.getSource(self.module.gpa) catch unreachable; // TODO fix this2653 // const ast_node_index = idx: {
2774 const source_of_decltest_function = srcloc: {2654 // const idx = self.ast_nodes.items.len;
2775 const func_index = getBlockInlineBreak(file.zir, value_index);2655 // const file_source = file.getSource(self.module.gpa) catch unreachable; // TODO fix this
2776 // a decltest is always a function2656 // const source_of_decltest_function = srcloc: {
2777 const tag = file.zir.instructions.items(.tag)[Zir.refToIndex(func_index).?];2657 // const func_index = getBlockInlineBreak(file.zir, value_index);
2778 std.debug.assert(tag == .func_extended);2658 // // a decltest is always a function
27792659 // const tag = file.zir.instructions.items(.tag)[Zir.refToIndex(func_index).?];
2780 const pl_node = file.zir.instructions.items(.data)[Zir.refToIndex(func_index).?].pl_node;2660 // std.debug.assert(tag == .func_extended);
2781 const extra = file.zir.extraData(Zir.Inst.ExtendedFunc, pl_node.payload_index);2661
2782 const bits = @bitCast(Zir.Inst.ExtendedFunc.Bits, extra.data.bits);2662 // const pl_node = file.zir.instructions.items(.data)[Zir.refToIndex(func_index).?].pl_node;
27832663 // const extra = file.zir.extraData(Zir.Inst.ExtendedFunc, pl_node.payload_index);
2784 var extra_index_for_this_func: usize = extra.end;2664 // const bits = @bitCast(Zir.Inst.ExtendedFunc.Bits, extra.data.bits);
2785 if (bits.has_lib_name) extra_index_for_this_func += 1;2665
2786 if (bits.has_cc) extra_index_for_this_func += 1;2666 // var extra_index_for_this_func: usize = extra.end;
2787 if (bits.has_align) extra_index_for_this_func += 1;2667 // if (bits.has_lib_name) extra_index_for_this_func += 1;
27882668 // if (bits.has_cc) extra_index_for_this_func += 1;
2789 const ret_ty_body = file.zir.extra[extra_index_for_this_func..][0..extra.data.ret_body_len];2669 // if (bits.has_align) extra_index_for_this_func += 1;
2790 extra_index_for_this_func += ret_ty_body.len;2670
27912671 // const ret_ty_body = file.zir.extra[extra_index_for_this_func..][0..extra.data.ret_body_len];
2792 const body = file.zir.extra[extra_index_for_this_func..][0..extra.data.body_len];2672 // extra_index_for_this_func += ret_ty_body.len;
2793 extra_index_for_this_func += body.len;2673
27942674 // const body = file.zir.extra[extra_index_for_this_func..][0..extra.data.body_len];
2795 var src_locs: Zir.Inst.Func.SrcLocs = undefined;2675 // extra_index_for_this_func += body.len;
2796 if (body.len != 0) {2676
2797 src_locs = file.zir.extraData(Zir.Inst.Func.SrcLocs, extra_index_for_this_func).data;2677 // var src_locs: Zir.Inst.Func.SrcLocs = undefined;
2798 } else {2678 // if (body.len != 0) {
2799 src_locs = .{2679 // src_locs = file.zir.extraData(Zir.Inst.Func.SrcLocs, extra_index_for_this_func).data;
2800 .lbrace_line = line,2680 // } else {
2801 .rbrace_line = line,2681 // src_locs = .{
2802 .columns = 0, // TODO get columns when body.len == 02682 // .lbrace_line = line,
2803 };2683 // .rbrace_line = line,
2804 }2684 // .columns = 0, // TODO get columns when body.len == 0
2805 break :srcloc src_locs;2685 // };
2806 };2686 // }
2807 const source_slice = slice: {2687 // break :srcloc src_locs;
2808 var start_byte_offset: u32 = 0;2688 // };
2809 var end_byte_offset: u32 = 0;2689 // const source_slice = slice: {
2810 const rbrace_col = @truncate(u16, source_of_decltest_function.columns >> 16);2690 // var start_byte_offset: u32 = 0;
2811 var lines: u32 = 0;2691 // var end_byte_offset: u32 = 0;
2812 for (file_source.bytes) |b, i| {2692 // const rbrace_col = @truncate(u16, source_of_decltest_function.columns >> 16);
2813 if (b == '\n') {2693 // var lines: u32 = 0;
2814 lines += 1;2694 // for (file_source.bytes) |b, i| {
2815 }2695 // if (b == '\n') {
2816 if (lines == source_of_decltest_function.lbrace_line) {2696 // lines += 1;
2817 start_byte_offset = @intCast(u32, i);2697 // }
2818 }2698 // if (lines == source_of_decltest_function.lbrace_line) {
2819 if (lines == source_of_decltest_function.rbrace_line) {2699 // start_byte_offset = @intCast(u32, i);
2820 end_byte_offset = @intCast(u32, i) + rbrace_col;2700 // }
2821 break;2701 // if (lines == source_of_decltest_function.rbrace_line) {
2822 }2702 // end_byte_offset = @intCast(u32, i) + rbrace_col;
2823 }2703 // break;
2824 break :slice file_source.bytes[start_byte_offset..end_byte_offset];2704 // }
2825 };2705 // }
2826 try self.ast_nodes.append(self.arena, .{2706 // break :slice file_source.bytes[start_byte_offset..end_byte_offset];
2827 .file = 0,2707 // };
2828 .line = line,2708 // try self.ast_nodes.append(self.arena, .{
2829 .col = 0,2709 // .file = 0,
2830 .name = try self.arena.dupe(u8, source_slice),2710 // .line = line,
2831 });2711 // .col = 0,
2832 break :idx idx;2712 // .name = try self.arena.dupe(u8, source_slice),
2833 };2713 // });
2834 self.decls.items[decl_being_tested].decltest = ast_node_index;2714 // break :idx idx;
2835 self.decls.items[decls_slot_index] = .{2715 // };
2836 ._analyzed = true,2716 // self.decls.items[decl_being_tested].decltest = ast_node_index;
2837 .name = "test",2717 // self.decls.items[decls_slot_index] = .{
2838 .isTest = true,2718 // ._analyzed = true,
2839 .src = ast_node_index,2719 // .name = "test",
2840 .value = .{ .expr = .{ .type = 0 } },2720 // .isTest = true,
2841 .kind = "const",2721 // .src = ast_node_index,
2842 };2722 // .value = .{ .expr = .{ .type = 0 } },
2843 continue;2723 // .kind = "const",
2724 // };
2725 // continue;
2844 } else {2726 } else {
2845 const raw_decl_name = file.zir.nullTerminatedString(decl_name_index);2727 const raw_decl_name = file.zir.nullTerminatedString(decl_name_index);
2846 if (raw_decl_name.len == 0) {2728 if (raw_decl_name.len == 0) {