| ... | @@ -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 { |
| 867 | | 868 | |
| 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 | }; |
| 872 | | 876 | |
| 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, the | 925 | /// 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 | }; |
| 928 | | 932 | |
| ... | @@ -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 | } |
| 2879 | | 2896 | |
| 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 | } |
| 2948 | | 2981 | |
| ... | @@ -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 | } |