authorgravatar for der.teufel.mail@gmail.comKrzysztof Wolicki <der.teufel.mail@gmail.com> 2023-10-30 22:04:49+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-10-30 21:04:49+00:00
log1880c799aebed7efe524c040998b27a2b361ff43
treece18489983965e0cb92255e07245f1a0dce02ec9
parentf52a228a5db89386e4ec0ef40370e53d99be8666
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

autodoc: Some support for field_call (#16853)

* autodoc: Some support for field_call * autodoc: Change handling of field_call to respect tryResolveRefPath, add fieldVal to Expr * autodoc: Fixed errors * autodoc: sync with latest master changes --------- Co-authored-by: Loris Cro <kappaloris@gmail.com>

2 files changed, 119 insertions(+), 7 deletions(-)

lib/docs/main.js+8-1
...@@ -1573,7 +1573,8 @@ Happy writing!...@@ -1573,7 +1573,8 @@ Happy writing!
1573 for (let i = 0; i < expr.struct.length; i++) {1573 for (let i = 0; i < expr.struct.length; i++) {
1574 const fv = expr.struct[i];1574 const fv = expr.struct[i];
1575 const field_name = fv.name;1575 const field_name = fv.name;
1576 const field_value = ex(fv.val.expr, opts);1576 const field_expr = zigAnalysis.exprs[fv.val.expr];
1577 const field_value = ex(field_expr, opts);
1577 yield Tok.period;1578 yield Tok.period;
1578 yield { src: field_name, tag: Tag.identifier };1579 yield { src: field_name, tag: Tag.identifier };
1579 yield Tok.space;1580 yield Tok.space;
...@@ -1628,7 +1629,13 @@ Happy writing!...@@ -1628,7 +1629,13 @@ Happy writing!
1628 } else {1629 } else {
1629 yield* ex(param, opts);1630 yield* ex(param, opts);
1630 }1631 }
1632 return;
1633 }
1631 1634
1635 case "fieldVal": {
1636 const fv = expr.fieldVal;
1637 const field_name = fv.name;
1638 yield { src: field_name, tag: Tag.identifier };
1632 return;1639 return;
1633 }1640 }
16341641
src/Autodoc.zig+111-6
...@@ -741,6 +741,7 @@ const DocData = struct {...@@ -741,6 +741,7 @@ const DocData = struct {
741 null: struct {},741 null: struct {},
742 undefined: struct {},742 undefined: struct {},
743 @"struct": []FieldVal,743 @"struct": []FieldVal,
744 fieldVal: FieldVal,
744 bool: bool,745 bool: bool,
745 @"anytype": struct {},746 @"anytype": struct {},
746 @"&": usize, // index in `exprs`747 @"&": usize, // index in `exprs`
...@@ -867,7 +868,10 @@ const DocData = struct {...@@ -867,7 +868,10 @@ const DocData = struct {
867868
868 const FieldVal = struct {869 const FieldVal = struct {
869 name: []const u8,870 name: []const u8,
870 val: WalkResult,871 val: struct {
872 typeRef: ?usize, // index in `exprs`
873 expr: usize, // index in `exprs`
874 },
871 };875 };
872876
873 const ElemVal = struct {877 const ElemVal = struct {
...@@ -921,8 +925,8 @@ const DocData = struct {...@@ -921,8 +925,8 @@ const DocData = struct {
921 /// Since the type information is only needed in certain contexts, the925 /// Since the type information is only needed in certain contexts, the
922 /// underlying normalized data (Expr) is untyped.926 /// underlying normalized data (Expr) is untyped.
923 const WalkResult = struct {927 const WalkResult = struct {
924 typeRef: ?Expr = null, // index in `exprs`928 typeRef: ?Expr = null,
925 expr: Expr, // index in `exprs`929 expr: Expr,
926 };930 };
927};931};
928932
...@@ -2874,7 +2878,20 @@ fn walkInstruction(...@@ -2874,7 +2878,20 @@ fn walkInstruction(
2874 need_type,2878 need_type,
2875 call_ctx,2879 call_ctx,
2876 );2880 );
2877 fv.* = .{ .name = field_name, .val = value };2881 const exprIdx = self.exprs.items.len;
2882 try self.exprs.append(self.arena, value.expr);
2883 var typeRefIdx: ?usize = null;
2884 if (value.typeRef) |ref| {
2885 typeRefIdx = self.exprs.items.len;
2886 try self.exprs.append(self.arena, ref);
2887 }
2888 fv.* = .{
2889 .name = field_name,
2890 .val = .{
2891 .typeRef = typeRefIdx,
2892 .expr = exprIdx,
2893 },
2894 };
2878 }2895 }
28792896
2880 return DocData.WalkResult{2897 return DocData.WalkResult{
...@@ -2942,7 +2959,23 @@ fn walkInstruction(...@@ -2942,7 +2959,23 @@ fn walkInstruction(
2942 need_type,2959 need_type,
2943 call_ctx,2960 call_ctx,
2944 );2961 );
2945 fv.* = .{ .name = field_name, .val = value };2962
2963 const exprIdx = self.exprs.items.len;
2964 try self.exprs.append(self.arena, value.expr);
2965 var typeRefIdx: ?usize = null;
2966 if (value.typeRef) |ref| {
2967 typeRefIdx = self.exprs.items.len;
2968 try self.exprs.append(self.arena, ref);
2969 }
2970
2971 fv.* = .{
2972 .name = field_name,
2973 .val = .{
2974 .typeRef = typeRefIdx,
2975 .expr = exprIdx,
2976 },
2977 };
2978
2946 idx = init_extra.end;2979 idx = init_extra.end;
2947 }2980 }
29482981
...@@ -3085,6 +3118,75 @@ fn walkInstruction(...@@ -3085,6 +3118,75 @@ fn walkInstruction(
3085 .expr = .{ .call = call_slot_index },3118 .expr = .{ .call = call_slot_index },
3086 };3119 };
3087 },3120 },
3121 .field_call => {
3122 const pl_node = data[@intFromEnum(inst)].pl_node;
3123 const extra = file.zir.extraData(Zir.Inst.FieldCall, pl_node.payload_index);
3124
3125 const obj_ptr = try self.walkRef(
3126 file,
3127 parent_scope,
3128 parent_src,
3129 extra.data.obj_ptr,
3130 need_type,
3131 call_ctx,
3132 );
3133
3134 var field_call = try self.arena.alloc(DocData.Expr, 2);
3135
3136 if (obj_ptr.typeRef) |ref| {
3137 field_call[0] = ref;
3138 } else {
3139 field_call[0] = obj_ptr.expr;
3140 }
3141 field_call[1] = .{ .declName = file.zir.nullTerminatedString(extra.data.field_name_start) };
3142 try self.tryResolveRefPath(file, inst, field_call);
3143
3144 const args_len = extra.data.flags.args_len;
3145 var args = try self.arena.alloc(DocData.Expr, args_len);
3146 const body = file.zir.extra[extra.end..];
3147
3148 try self.repurposed_insts.put(self.arena, inst, {});
3149 defer _ = self.repurposed_insts.remove(inst);
3150
3151 var i: usize = 0;
3152 while (i < args_len) : (i += 1) {
3153 const arg_end = file.zir.extra[extra.end + i];
3154 const break_index = body[arg_end - 1];
3155 const ref = data[break_index].@"break".operand;
3156 // TODO: consider toggling need_type to true if we ever want
3157 // to show discrepancies between the types of provided
3158 // arguments and the types declared in the function
3159 // signature for its parameters.
3160 const wr = try self.walkRef(
3161 file,
3162 parent_scope,
3163 parent_src,
3164 ref,
3165 false,
3166 &.{
3167 .inst = inst,
3168 .prev = call_ctx,
3169 },
3170 );
3171 args[i] = wr.expr;
3172 }
3173
3174 const cte_slot_index = self.comptime_exprs.items.len;
3175 try self.comptime_exprs.append(self.arena, .{
3176 .code = "field call",
3177 });
3178
3179 const call_slot_index = self.calls.items.len;
3180 try self.calls.append(self.arena, .{
3181 .func = .{ .refPath = field_call },
3182 .args = args,
3183 .ret = .{ .comptimeExpr = cte_slot_index },
3184 });
3185
3186 return DocData.WalkResult{
3187 .expr = .{ .call = call_slot_index },
3188 };
3189 },
3088 .func, .func_inferred => {3190 .func, .func_inferred => {
3089 const type_slot_index = self.types.items.len;3191 const type_slot_index = self.types.items.len;
3090 try self.types.append(self.arena, .{ .Unanalyzed = .{} });3192 try self.types.append(self.arena, .{ .Unanalyzed = .{} });
...@@ -4374,6 +4476,9 @@ fn tryResolveRefPath(...@@ -4374,6 +4476,9 @@ fn tryResolveRefPath(
4374 },4476 },
4375 }4477 }
4376 },4478 },
4479 .fieldVal => |fv| {
4480 resolved_parent = self.exprs.items[fv.val.expr];
4481 },
4377 }4482 }
4378 } else {4483 } else {
4379 panicWithContext(4484 panicWithContext(
...@@ -4675,7 +4780,7 @@ fn tryResolveRefPath(...@@ -4675,7 +4780,7 @@ fn tryResolveRefPath(
4675 .@"struct" => |st| {4780 .@"struct" => |st| {
4676 for (st) |field| {4781 for (st) |field| {
4677 if (std.mem.eql(u8, field.name, child_string)) {4782 if (std.mem.eql(u8, field.name, child_string)) {
4678 path[i + 1] = field.val.expr;4783 path[i + 1] = .{ .fieldVal = field };
4679 continue :outer;4784 continue :outer;
4680 }4785 }
4681 }4786 }