Commit 80c1d48ccb

Krzysztof Wolicki <der.teufel.mail@gmail.com>
2023-09-03 17:18:16
autodoc: Implement `a[b]`, `a.?`, and `a.*` (#16863)
* autodoc: Implement elem_val_node and basic optional_payload_* * autodoc: Add `.*` loads
1 parent 0516a4d
Changed files (3)
lib/docs/main.js
@@ -1352,6 +1352,14 @@ Happy writing!
         yield* ex(zigAnalysis.exprs[expr["&"]], opts);
         return;
       }
+
+      case "load": {
+        yield* ex(zigAnalysis.exprs[expr.load], opts);
+        yield Tok.period;
+        yield Tok.asterisk;
+        return;
+      }
+
       case "call": {
 
         let call = zigAnalysis.calls[expr.call];
@@ -1453,6 +1461,24 @@ Happy writing!
         return;
       }
 
+      case "optionalPayload": {
+        const opt = zigAnalysis.exprs[expr.optionalPayload];
+        yield* ex(opt, opts);
+        yield Tok.period;
+        yield Tok.question_mark;
+        return;
+      }
+
+      case "elemVal": {
+        const lhs = zigAnalysis.exprs[expr.elemVal.lhs];
+        const rhs = zigAnalysis.exprs[expr.elemVal.rhs];
+        yield* ex(lhs);
+        yield Tok.l_bracket;
+        yield* ex(rhs);
+        yield Tok.r_bracket;
+        return;
+      }
+
       case "string": {
         yield { src: '"' + expr.string + '"', tag: Tag.string_literal };
         return;
@@ -1882,7 +1908,7 @@ Happy writing!
             return;
           }
           case typeKinds.Optional: {
-            yield { src: "?", tag: Tag.question_mark };
+            yield Tok.question_mark;
             yield* ex(typeObj.child, opts);
             return;
           }
lib/docs/ziglexer.js
@@ -144,6 +144,8 @@ const Tok = {
     r_paren: { src: ")", tag: Tag.r_paren },
     period: { src: ".", tag: Tag.period },
     comma: { src: ",", tag: Tag.comma },
+    question_mark: { src: "?", tag: Tag.question_mark },
+    asterisk: { src: "*", tag: Tag.asterisk },
     identifier: (name) => { return { src: name, tag: Tag.identifier } },
 };
 
src/Autodoc.zig
@@ -775,7 +775,9 @@ const DocData = struct {
         sizeOf: usize, // index in `exprs`
         bitSizeOf: usize, // index in `exprs`
         intFromEnum: usize, // index in `exprs`
-        compileError: usize, //index in `exprs`
+        compileError: usize, // index in `exprs`
+        optionalPayload: usize, // index in `exprs`
+        elemVal: ElemVal,
         errorSets: usize,
         string: []const u8, // direct value
         sliceIndex: usize,
@@ -791,6 +793,7 @@ const DocData = struct {
         switchOp: SwitchOp,
         binOp: BinOp,
         binOpIndex: usize,
+        load: usize, // index in `exprs`
         const BinOp = struct {
             lhs: usize, // index in `exprs`
             rhs: usize, // index in `exprs`
@@ -846,6 +849,11 @@ const DocData = struct {
             val: WalkResult,
         };
 
+        const ElemVal = struct {
+            lhs: usize, // index in `exprs`
+            rhs: usize, // index in `exprs`
+        };
+
         pub fn jsonStringify(self: Expr, jsw: anytype) !void {
             const active_tag = std.meta.activeTag(self);
             try jsw.beginObject();
@@ -1463,6 +1471,38 @@ fn walkInstruction(
             };
         },
 
+        .load => {
+            const un_node = data[inst_index].un_node;
+            const operand = try self.walkRef(
+                file,
+                parent_scope,
+                parent_src,
+                un_node.operand,
+                need_type,
+                call_ctx,
+            );
+            const load_idx = self.exprs.items.len;
+            try self.exprs.append(self.arena, operand.expr);
+
+            var typeRef: ?DocData.Expr = null;
+            if (operand.typeRef) |ref| {
+                switch (ref) {
+                    .type => |t_index| {
+                        switch (self.types.items[t_index]) {
+                            .Pointer => |p| typeRef = p.child,
+                            else => {},
+                        }
+                    },
+                    else => {},
+                }
+            }
+
+            return DocData.WalkResult{
+                .typeRef = typeRef,
+                .expr = .{ .load = load_idx },
+            };
+        },
+
         // @check array_cat and array_mul
         .add,
         .addwrap,
@@ -2862,6 +2902,72 @@ fn walkInstruction(
 
             return result;
         },
+        .optional_payload_safe, .optional_payload_unsafe => {
+            const un_node = data[inst_index].un_node;
+            const operand = try self.walkRef(
+                file,
+                parent_scope,
+                parent_src,
+                un_node.operand,
+                need_type,
+                call_ctx,
+            );
+            const optional_idx = self.exprs.items.len;
+            try self.exprs.append(self.arena, operand.expr);
+
+            var typeRef: ?DocData.Expr = null;
+            if (operand.typeRef) |ref| {
+                switch (ref) {
+                    .type => |t_index| {
+                        const t = self.types.items[t_index];
+                        switch (t) {
+                            .Optional => |opt| typeRef = opt.child,
+                            else => {
+                                printWithContext(file, inst_index, "Invalid type for optional_payload_*: {}\n", .{t});
+                            },
+                        }
+                    },
+                    else => {},
+                }
+            }
+
+            return DocData.WalkResult{
+                .typeRef = typeRef,
+                .expr = .{ .optionalPayload = optional_idx },
+            };
+        },
+        .elem_val_node => {
+            const pl_node = data[inst_index].pl_node;
+            const extra = file.zir.extraData(Zir.Inst.Bin, pl_node.payload_index);
+            const lhs = try self.walkRef(
+                file,
+                parent_scope,
+                parent_src,
+                extra.data.lhs,
+                need_type,
+                call_ctx,
+            );
+            const rhs = try self.walkRef(
+                file,
+                parent_scope,
+                parent_src,
+                extra.data.rhs,
+                need_type,
+                call_ctx,
+            );
+            const lhs_idx = self.exprs.items.len;
+            try self.exprs.append(self.arena, lhs.expr);
+            const rhs_idx = self.exprs.items.len;
+            try self.exprs.append(self.arena, rhs.expr);
+            return DocData.WalkResult{
+                .expr = .{
+                    .elemVal = .{
+                        .lhs = lhs_idx,
+                        .rhs = rhs_idx,
+                    },
+                },
+            };
+        },
         .extended => {
             const extended = data[inst_index].extended;
             switch (extended.opcode) {