| ... | @@ -33,7 +33,7 @@ pub fn run( | ... | @@ -33,7 +33,7 @@ pub fn run( |
| 33 | sema: *Sema, | 33 | sema: *Sema, |
| 34 | file: *File, | 34 | file: *File, |
| 35 | file_index: Zcu.File.Index, | 35 | file_index: Zcu.File.Index, |
| 36 | res_ty: Type, | 36 | res_ty_interned: InternPool.Index, |
| 37 | import_loc: LazySrcLoc, | 37 | import_loc: LazySrcLoc, |
| 38 | block: *Sema.Block, | 38 | block: *Sema.Block, |
| 39 | ) CompileError!InternPool.Index { | 39 | ) CompileError!InternPool.Index { |
| ... | @@ -53,13 +53,167 @@ pub fn run( | ... | @@ -53,13 +53,167 @@ pub fn run( |
| 53 | .base_node_inst = tracked_inst, | 53 | .base_node_inst = tracked_inst, |
| 54 | }; | 54 | }; |
| 55 | | 55 | |
| 56 | try lower_zon.checkType(res_ty); | 56 | if (res_ty_interned == .none) { |
| | 57 | return lower_zon.lowerExprAnonResTy(.root); |
| | 58 | } else { |
| | 59 | const res_ty: Type = .fromInterned(res_ty_interned); |
| | 60 | try lower_zon.checkType(res_ty); |
| | 61 | return lower_zon.lowerExprKnownResTy(.root, res_ty); |
| | 62 | } |
| | 63 | } |
| 57 | | 64 | |
| 58 | return lower_zon.lowerExpr(.root, res_ty); | 65 | fn lowerExprAnonResTy(self: *LowerZon, node: Zoir.Node.Index) CompileError!InternPool.Index { |
| | 66 | const gpa = self.sema.gpa; |
| | 67 | const pt = self.sema.pt; |
| | 68 | const ip = &pt.zcu.intern_pool; |
| | 69 | switch (node.get(self.file.zoir.?)) { |
| | 70 | .true => return .bool_true, |
| | 71 | .false => return .bool_false, |
| | 72 | .null => return .null_value, |
| | 73 | .pos_inf => return self.fail(node, "infinity requires a known result type", .{}), |
| | 74 | .neg_inf => return self.fail(node, "negative infinity requires a known result type", .{}), |
| | 75 | .nan => return self.fail(node, "NaN requires a known result type", .{}), |
| | 76 | .int_literal => |int| switch (int) { |
| | 77 | .small => |val| return pt.intern(.{ .int = .{ |
| | 78 | .ty = .comptime_int_type, |
| | 79 | .storage = .{ .i64 = val }, |
| | 80 | } }), |
| | 81 | .big => |val| return pt.intern(.{ .int = .{ |
| | 82 | .ty = .comptime_int_type, |
| | 83 | .storage = .{ .big_int = val }, |
| | 84 | } }), |
| | 85 | }, |
| | 86 | .float_literal => |val| { |
| | 87 | const result = try pt.floatValue(.comptime_float, val); |
| | 88 | return result.toIntern(); |
| | 89 | }, |
| | 90 | .char_literal => |val| return pt.intern(.{ .int = .{ |
| | 91 | .ty = .comptime_int_type, |
| | 92 | .storage = .{ .i64 = val }, |
| | 93 | } }), |
| | 94 | .enum_literal => |val| return pt.intern(.{ |
| | 95 | .enum_literal = try ip.getOrPutString( |
| | 96 | gpa, |
| | 97 | pt.tid, |
| | 98 | val.get(self.file.zoir.?), |
| | 99 | .no_embedded_nulls, |
| | 100 | ), |
| | 101 | }), |
| | 102 | .string_literal => |val| { |
| | 103 | const ip_str = try ip.getOrPutString(gpa, pt.tid, val, .maybe_embedded_nulls); |
| | 104 | const result = try self.sema.addStrLit(ip_str, val.len); |
| | 105 | return result.toInterned().?; |
| | 106 | }, |
| | 107 | .empty_literal => return .empty_tuple, |
| | 108 | .array_literal => |nodes| { |
| | 109 | const types = try self.sema.arena.alloc(InternPool.Index, nodes.len); |
| | 110 | const values = try self.sema.arena.alloc(InternPool.Index, nodes.len); |
| | 111 | for (0..nodes.len) |i| { |
| | 112 | values[i] = try self.lowerExprAnonResTy(nodes.at(@intCast(i))); |
| | 113 | types[i] = Value.fromInterned(values[i]).typeOf(pt.zcu).toIntern(); |
| | 114 | } |
| | 115 | const ty = try ip.getTupleType( |
| | 116 | gpa, |
| | 117 | pt.tid, |
| | 118 | .{ |
| | 119 | .types = types, |
| | 120 | .values = values, |
| | 121 | }, |
| | 122 | ); |
| | 123 | return pt.intern(.{ .aggregate = .{ |
| | 124 | .ty = ty, |
| | 125 | .storage = .{ .elems = values }, |
| | 126 | } }); |
| | 127 | }, |
| | 128 | .struct_literal => |init| { |
| | 129 | const elems = try self.sema.arena.alloc(InternPool.Index, init.names.len); |
| | 130 | for (0..init.names.len) |i| { |
| | 131 | elems[i] = try self.lowerExprAnonResTy(init.vals.at(@intCast(i))); |
| | 132 | } |
| | 133 | const struct_ty = switch (try ip.getStructType( |
| | 134 | gpa, |
| | 135 | pt.tid, |
| | 136 | .{ |
| | 137 | .layout = .auto, |
| | 138 | .fields_len = @intCast(init.names.len), |
| | 139 | .known_non_opv = false, |
| | 140 | .requires_comptime = .no, |
| | 141 | .any_comptime_fields = true, |
| | 142 | .any_default_inits = true, |
| | 143 | .inits_resolved = true, |
| | 144 | .any_aligned_fields = false, |
| | 145 | .key = .{ .reified = .{ |
| | 146 | .zir_index = self.base_node_inst, |
| | 147 | .type_hash = hash: { |
| | 148 | var hasher: std.hash.Wyhash = .init(0); |
| | 149 | hasher.update(std.mem.asBytes(&node)); |
| | 150 | hasher.update(std.mem.sliceAsBytes(elems)); |
| | 151 | hasher.update(std.mem.sliceAsBytes(init.names)); |
| | 152 | break :hash hasher.final(); |
| | 153 | }, |
| | 154 | } }, |
| | 155 | }, |
| | 156 | false, |
| | 157 | )) { |
| | 158 | .wip => |wip| ty: { |
| | 159 | errdefer wip.cancel(ip, pt.tid); |
| | 160 | wip.setName(ip, try self.sema.createTypeName( |
| | 161 | self.block, |
| | 162 | .anon, |
| | 163 | "struct", |
| | 164 | self.base_node_inst.resolve(ip), |
| | 165 | wip.index, |
| | 166 | )); |
| | 167 | |
| | 168 | const struct_type = ip.loadStructType(wip.index); |
| | 169 | |
| | 170 | for (init.names, 0..) |name, field_idx| { |
| | 171 | const name_interned = try ip.getOrPutString( |
| | 172 | gpa, |
| | 173 | pt.tid, |
| | 174 | name.get(self.file.zoir.?), |
| | 175 | .no_embedded_nulls, |
| | 176 | ); |
| | 177 | assert(struct_type.addFieldName(ip, name_interned) == null); |
| | 178 | struct_type.setFieldComptime(ip, field_idx); |
| | 179 | } |
| | 180 | |
| | 181 | @memcpy(struct_type.field_inits.get(ip), elems); |
| | 182 | const types = struct_type.field_types.get(ip); |
| | 183 | for (0..init.names.len) |i| { |
| | 184 | types[i] = Value.fromInterned(elems[i]).typeOf(pt.zcu).toIntern(); |
| | 185 | } |
| | 186 | |
| | 187 | const new_namespace_index = try pt.createNamespace(.{ |
| | 188 | .parent = self.block.namespace.toOptional(), |
| | 189 | .owner_type = wip.index, |
| | 190 | .file_scope = self.block.getFileScopeIndex(pt.zcu), |
| | 191 | .generation = pt.zcu.generation, |
| | 192 | }); |
| | 193 | try pt.zcu.comp.queueJob(.{ .resolve_type_fully = wip.index }); |
| | 194 | codegen_type: { |
| | 195 | if (pt.zcu.comp.config.use_llvm) break :codegen_type; |
| | 196 | if (self.block.ownerModule().strip) break :codegen_type; |
| | 197 | try pt.zcu.comp.queueJob(.{ .codegen_type = wip.index }); |
| | 198 | } |
| | 199 | break :ty wip.finish(ip, new_namespace_index); |
| | 200 | }, |
| | 201 | .existing => |ty| ty, |
| | 202 | }; |
| | 203 | try self.sema.declareDependency(.{ .interned = struct_ty }); |
| | 204 | try self.sema.addTypeReferenceEntry(self.nodeSrc(node), struct_ty); |
| | 205 | |
| | 206 | return try pt.intern(.{ .aggregate = .{ |
| | 207 | .ty = struct_ty, |
| | 208 | .storage = .{ .elems = elems }, |
| | 209 | } }); |
| | 210 | }, |
| | 211 | } |
| 59 | } | 212 | } |
| 60 | | 213 | |
| 61 | /// Validate that `ty` is a valid ZON type. If not, emit a compile error. | 214 | /// Validate that `ty` is a valid ZON type, or emit a compile error. |
| 62 | /// i.e. no nested optionals, no error sets, etc. | 215 | /// |
| | 216 | /// Rules out nested optionals, error sets, etc. |
| 63 | fn checkType(self: *LowerZon, ty: Type) !void { | 217 | fn checkType(self: *LowerZon, ty: Type) !void { |
| 64 | var visited: std.AutoHashMapUnmanaged(InternPool.Index, void) = .empty; | 218 | var visited: std.AutoHashMapUnmanaged(InternPool.Index, void) = .empty; |
| 65 | try self.checkTypeInner(ty, null, &visited); | 219 | try self.checkTypeInner(ty, null, &visited); |
| ... | @@ -201,9 +355,9 @@ fn fail( | ... | @@ -201,9 +355,9 @@ fn fail( |
| 201 | return self.sema.failWithOwnedErrorMsg(self.block, err_msg); | 355 | return self.sema.failWithOwnedErrorMsg(self.block, err_msg); |
| 202 | } | 356 | } |
| 203 | | 357 | |
| 204 | fn lowerExpr(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!InternPool.Index { | 358 | fn lowerExprKnownResTy(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError!InternPool.Index { |
| 205 | const pt = self.sema.pt; | 359 | const pt = self.sema.pt; |
| 206 | return self.lowerExprInner(node, res_ty) catch |err| switch (err) { | 360 | return self.lowerExprKnownResTyInner(node, res_ty) catch |err| switch (err) { |
| 207 | error.WrongType => return self.fail( | 361 | error.WrongType => return self.fail( |
| 208 | node, | 362 | node, |
| 209 | "expected type '{}'", | 363 | "expected type '{}'", |
| ... | @@ -213,7 +367,7 @@ fn lowerExpr(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError! | ... | @@ -213,7 +367,7 @@ fn lowerExpr(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) CompileError! |
| 213 | }; | 367 | }; |
| 214 | } | 368 | } |
| 215 | | 369 | |
| 216 | fn lowerExprInner( | 370 | fn lowerExprKnownResTyInner( |
| 217 | self: *LowerZon, | 371 | self: *LowerZon, |
| 218 | node: Zoir.Node.Index, | 372 | node: Zoir.Node.Index, |
| 219 | res_ty: Type, | 373 | res_ty: Type, |
| ... | @@ -227,7 +381,7 @@ fn lowerExprInner( | ... | @@ -227,7 +381,7 @@ fn lowerExprInner( |
| 227 | break :b .none; | 381 | break :b .none; |
| 228 | } else b: { | 382 | } else b: { |
| 229 | const child_type = res_ty.optionalChild(pt.zcu); | 383 | const child_type = res_ty.optionalChild(pt.zcu); |
| 230 | break :b try self.lowerExprInner(node, child_type); | 384 | break :b try self.lowerExprKnownResTyInner(node, child_type); |
| 231 | }, | 385 | }, |
| 232 | }, | 386 | }, |
| 233 | }), | 387 | }), |
| ... | @@ -239,7 +393,7 @@ fn lowerExprInner( | ... | @@ -239,7 +393,7 @@ fn lowerExprInner( |
| 239 | .base_addr = .{ | 393 | .base_addr = .{ |
| 240 | .uav = .{ | 394 | .uav = .{ |
| 241 | .orig_ty = res_ty.toIntern(), | 395 | .orig_ty = res_ty.toIntern(), |
| 242 | .val = try self.lowerExprInner(node, .fromInterned(ptr_info.child)), | 396 | .val = try self.lowerExprKnownResTyInner(node, .fromInterned(ptr_info.child)), |
| 243 | }, | 397 | }, |
| 244 | }, | 398 | }, |
| 245 | .byte_offset = 0, | 399 | .byte_offset = 0, |
| ... | @@ -486,7 +640,7 @@ fn lowerArray(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. | ... | @@ -486,7 +640,7 @@ fn lowerArray(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 486 | ); | 640 | ); |
| 487 | | 641 | |
| 488 | for (0..nodes.len) |i| { | 642 | for (0..nodes.len) |i| { |
| 489 | elems[i] = try self.lowerExpr(nodes.at(@intCast(i)), array_info.elem_type); | 643 | elems[i] = try self.lowerExprKnownResTy(nodes.at(@intCast(i)), array_info.elem_type); |
| 490 | } | 644 | } |
| 491 | | 645 | |
| 492 | if (array_info.sentinel) |sentinel| { | 646 | if (array_info.sentinel) |sentinel| { |
| ... | @@ -587,7 +741,7 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. | ... | @@ -587,7 +741,7 @@ fn lowerTuple(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 587 | ); | 741 | ); |
| 588 | } | 742 | } |
| 589 | | 743 | |
| 590 | const val = try self.lowerExpr(elem_nodes.at(@intCast(i)), .fromInterned(field_types[i])); | 744 | const val = try self.lowerExprKnownResTy(elem_nodes.at(@intCast(i)), .fromInterned(field_types[i])); |
| 591 | | 745 | |
| 592 | if (elems[i] != .none and val != elems[i]) { | 746 | if (elems[i] != .none and val != elems[i]) { |
| 593 | const elem_node = elem_nodes.at(@intCast(i)); | 747 | const elem_node = elem_nodes.at(@intCast(i)); |
| ... | @@ -650,7 +804,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool | ... | @@ -650,7 +804,7 @@ fn lowerStruct(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool |
| 650 | }; | 804 | }; |
| 651 | | 805 | |
| 652 | const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]); | 806 | const field_type: Type = .fromInterned(struct_info.field_types.get(ip)[name_index]); |
| 653 | field_values[name_index] = try self.lowerExpr(field_node, field_type); | 807 | field_values[name_index] = try self.lowerExprKnownResTy(field_node, field_type); |
| 654 | | 808 | |
| 655 | if (struct_info.comptime_bits.getBit(ip, name_index)) { | 809 | if (struct_info.comptime_bits.getBit(ip, name_index)) { |
| 656 | const val = ip.indexToKey(field_values[name_index]); | 810 | const val = ip.indexToKey(field_values[name_index]); |
| ... | @@ -715,7 +869,7 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. | ... | @@ -715,7 +869,7 @@ fn lowerSlice(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 715 | const elems = try self.sema.arena.alloc(InternPool.Index, elem_nodes.len + @intFromBool(ptr_info.sentinel != .none)); | 869 | const elems = try self.sema.arena.alloc(InternPool.Index, elem_nodes.len + @intFromBool(ptr_info.sentinel != .none)); |
| 716 | | 870 | |
| 717 | for (elems, 0..) |*elem, i| { | 871 | for (elems, 0..) |*elem, i| { |
| 718 | elem.* = try self.lowerExpr(elem_nodes.at(@intCast(i)), .fromInterned(ptr_info.child)); | 872 | elem.* = try self.lowerExprKnownResTy(elem_nodes.at(@intCast(i)), .fromInterned(ptr_info.child)); |
| 719 | } | 873 | } |
| 720 | | 874 | |
| 721 | if (ptr_info.sentinel != .none) { | 875 | if (ptr_info.sentinel != .none) { |
| ... | @@ -810,7 +964,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. | ... | @@ -810,7 +964,7 @@ fn lowerUnion(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool. |
| 810 | if (field_type.toIntern() == .void_type) { | 964 | if (field_type.toIntern() == .void_type) { |
| 811 | return self.fail(field_node, "expected type 'void'", .{}); | 965 | return self.fail(field_node, "expected type 'void'", .{}); |
| 812 | } | 966 | } |
| 813 | break :b try self.lowerExpr(field_node, field_type); | 967 | break :b try self.lowerExprKnownResTy(field_node, field_type); |
| 814 | } else b: { | 968 | } else b: { |
| 815 | if (field_type.toIntern() != .void_type) { | 969 | if (field_type.toIntern() != .void_type) { |
| 816 | return error.WrongType; | 970 | return error.WrongType; |
| ... | @@ -846,7 +1000,7 @@ fn lowerVector(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool | ... | @@ -846,7 +1000,7 @@ fn lowerVector(self: *LowerZon, node: Zoir.Node.Index, res_ty: Type) !InternPool |
| 846 | } | 1000 | } |
| 847 | | 1001 | |
| 848 | for (elems, 0..) |*elem, i| { | 1002 | for (elems, 0..) |*elem, i| { |
| 849 | elem.* = try self.lowerExpr(elem_nodes.at(@intCast(i)), .fromInterned(vector_info.child)); | 1003 | elem.* = try self.lowerExprKnownResTy(elem_nodes.at(@intCast(i)), .fromInterned(vector_info.child)); |
| 850 | } | 1004 | } |
| 851 | | 1005 | |
| 852 | return self.sema.pt.intern(.{ .aggregate = .{ | 1006 | return self.sema.pt.intern(.{ .aggregate = .{ |