Commit ce3cffbd5a

Andrew Kelley <andrew@ziglang.org>
2023-05-06 03:07:43
fill out more InternPool Type methods
particularly, printing types
1 parent 0471638
src/print_air.zig
@@ -95,7 +95,7 @@ const Writer = struct {
         for (w.air.instructions.items(.tag), 0..) |tag, i| {
             const inst = @intCast(Air.Inst.Index, i);
             switch (tag) {
-                .constant, .const_ty => {
+                .constant, .const_ty, .interned => {
                     try w.writeInst(s, inst);
                     try s.writeByte('\n');
                 },
src/Sema.zig
@@ -31485,11 +31485,18 @@ pub fn resolveTypeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
 
     if (ty.ip_index != .none) return switch (mod.intern_pool.indexToKey(ty.ip_index)) {
         .int_type => false,
-        .ptr_type => @panic("TODO"),
-        .array_type => @panic("TODO"),
+        .ptr_type => |ptr_type| {
+            const child_ty = ptr_type.elem_type.toType();
+            if (child_ty.zigTypeTag(mod) == .Fn) {
+                return child_ty.fnInfo().is_generic;
+            } else {
+                return sema.resolveTypeRequiresComptime(child_ty);
+            }
+        },
+        .array_type => |array_type| return sema.resolveTypeRequiresComptime(array_type.child.toType()),
         .vector_type => |vector_type| return sema.resolveTypeRequiresComptime(vector_type.child.toType()),
-        .opt_type => @panic("TODO"),
-        .error_union_type => @panic("TODO"),
+        .opt_type => |child| return sema.resolveTypeRequiresComptime(child.toType()),
+        .error_union_type => |error_union_type| return sema.resolveTypeRequiresComptime(error_union_type.payload_type.toType()),
         .simple_type => |t| switch (t) {
             .f16,
             .f32,
@@ -33528,11 +33535,20 @@ pub fn typeRequiresComptime(sema: *Sema, ty: Type) CompileError!bool {
     if (ty.ip_index != .none) {
         switch (mod.intern_pool.indexToKey(ty.ip_index)) {
             .int_type => return false,
-            .ptr_type => @panic("TODO"),
-            .array_type => @panic("TODO"),
+            .ptr_type => |ptr_type| {
+                const child_ty = ptr_type.elem_type.toType();
+                if (child_ty.zigTypeTag(mod) == .Fn) {
+                    return child_ty.fnInfo().is_generic;
+                } else {
+                    return sema.typeRequiresComptime(child_ty);
+                }
+            },
+            .array_type => |array_type| return sema.typeRequiresComptime(array_type.child.toType()),
             .vector_type => |vector_type| return sema.typeRequiresComptime(vector_type.child.toType()),
-            .opt_type => @panic("TODO"),
-            .error_union_type => @panic("TODO"),
+            .opt_type => |child| return sema.typeRequiresComptime(child.toType()),
+            .error_union_type => |error_union_type| {
+                return sema.typeRequiresComptime(error_union_type.payload_type.toType());
+            },
             .simple_type => |t| return switch (t) {
                 .f16,
                 .f32,
src/type.zig
@@ -1274,11 +1274,77 @@ pub const Type = struct {
                 };
                 return writer.print("{c}{d}", .{ sign_char, int_type.bits });
             },
-            .ptr_type => @panic("TODO"),
-            .array_type => @panic("TODO"),
-            .vector_type => @panic("TODO"),
-            .opt_type => @panic("TODO"),
-            .error_union_type => @panic("TODO"),
+            .ptr_type => {
+                const info = ty.ptrInfo(mod);
+
+                if (info.sentinel) |s| switch (info.size) {
+                    .One, .C => unreachable,
+                    .Many => try writer.print("[*:{}]", .{s.fmtValue(info.pointee_type, mod)}),
+                    .Slice => try writer.print("[:{}]", .{s.fmtValue(info.pointee_type, mod)}),
+                } else switch (info.size) {
+                    .One => try writer.writeAll("*"),
+                    .Many => try writer.writeAll("[*]"),
+                    .C => try writer.writeAll("[*c]"),
+                    .Slice => try writer.writeAll("[]"),
+                }
+                if (info.@"align" != 0 or info.host_size != 0 or info.vector_index != .none) {
+                    if (info.@"align" != 0) {
+                        try writer.print("align({d}", .{info.@"align"});
+                    } else {
+                        const alignment = info.pointee_type.abiAlignment(mod);
+                        try writer.print("align({d}", .{alignment});
+                    }
+
+                    if (info.bit_offset != 0 or info.host_size != 0) {
+                        try writer.print(":{d}:{d}", .{ info.bit_offset, info.host_size });
+                    }
+                    if (info.vector_index == .runtime) {
+                        try writer.writeAll(":?");
+                    } else if (info.vector_index != .none) {
+                        try writer.print(":{d}", .{@enumToInt(info.vector_index)});
+                    }
+                    try writer.writeAll(") ");
+                }
+                if (info.@"addrspace" != .generic) {
+                    try writer.print("addrspace(.{s}) ", .{@tagName(info.@"addrspace")});
+                }
+                if (!info.mutable) try writer.writeAll("const ");
+                if (info.@"volatile") try writer.writeAll("volatile ");
+                if (info.@"allowzero" and info.size != .C) try writer.writeAll("allowzero ");
+
+                try print(info.pointee_type, writer, mod);
+                return;
+            },
+            .array_type => |array_type| {
+                if (array_type.sentinel == .none) {
+                    try writer.print("[{d}]", .{array_type.len});
+                    try print(array_type.child.toType(), writer, mod);
+                } else {
+                    try writer.print("[{d}:{}]", .{
+                        array_type.len,
+                        array_type.sentinel.toValue().fmtValue(array_type.child.toType(), mod),
+                    });
+                    try print(array_type.child.toType(), writer, mod);
+                }
+                return;
+            },
+            .vector_type => |vector_type| {
+                try writer.print("@Vector({d}, ", .{vector_type.len});
+                try print(vector_type.child.toType(), writer, mod);
+                try writer.writeAll(")");
+                return;
+            },
+            .opt_type => |child| {
+                try writer.writeByte('?');
+                try print(child.toType(), writer, mod);
+                return;
+            },
+            .error_union_type => |error_union_type| {
+                try print(error_union_type.error_set_type.toType(), writer, mod);
+                try writer.writeByte('!');
+                try print(error_union_type.payload_type.toType(), writer, mod);
+                return;
+            },
             .simple_type => |s| return writer.writeAll(@tagName(s)),
             .struct_type => @panic("TODO"),
             .union_type => @panic("TODO"),
@@ -2055,8 +2121,8 @@ pub const Type = struct {
                 return AbiAlignmentAdvanced{ .scalar = alignment };
             },
 
-            .opt_type => @panic("TODO"),
-            .error_union_type => @panic("TODO"),
+            .opt_type => return abiAlignmentAdvancedOptional(ty, mod, strat),
+            .error_union_type => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
             .simple_type => |t| switch (t) {
                 .bool,
                 .atomic_order,
@@ -2157,64 +2223,8 @@ pub const Type = struct {
 
             .array, .array_sentinel => return ty.childType(mod).abiAlignmentAdvanced(mod, strat),
 
-            .optional => {
-                const child_type = ty.optionalChild(mod);
-
-                switch (child_type.zigTypeTag(mod)) {
-                    .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
-                    .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat),
-                    .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 },
-                    else => {},
-                }
-
-                switch (strat) {
-                    .eager, .sema => {
-                        if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
-                            error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
-                            else => |e| return e,
-                        })) {
-                            return AbiAlignmentAdvanced{ .scalar = 1 };
-                        }
-                        return child_type.abiAlignmentAdvanced(mod, strat);
-                    },
-                    .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(mod, strat)) {
-                        .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) },
-                        .val => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
-                    },
-                }
-            },
-
-            .error_union => {
-                // This code needs to be kept in sync with the equivalent switch prong
-                // in abiSizeAdvanced.
-                const data = ty.castTag(.error_union).?.data;
-                const code_align = abiAlignment(Type.anyerror, mod);
-                switch (strat) {
-                    .eager, .sema => {
-                        if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
-                            error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
-                            else => |e| return e,
-                        })) {
-                            return AbiAlignmentAdvanced{ .scalar = code_align };
-                        }
-                        return AbiAlignmentAdvanced{ .scalar = @max(
-                            code_align,
-                            (try data.payload.abiAlignmentAdvanced(mod, strat)).scalar,
-                        ) };
-                    },
-                    .lazy => |arena| {
-                        switch (try data.payload.abiAlignmentAdvanced(mod, strat)) {
-                            .scalar => |payload_align| {
-                                return AbiAlignmentAdvanced{
-                                    .scalar = @max(code_align, payload_align),
-                                };
-                            },
-                            .val => {},
-                        }
-                        return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
-                    },
-                }
-            },
+            .optional => return abiAlignmentAdvancedOptional(ty, mod, strat),
+            .error_union => return abiAlignmentAdvancedErrorUnion(ty, mod, strat),
 
             .@"struct" => {
                 const struct_obj = ty.castTag(.@"struct").?.data;
@@ -2321,6 +2331,74 @@ pub const Type = struct {
         }
     }
 
+    fn abiAlignmentAdvancedErrorUnion(
+        ty: Type,
+        mod: *const Module,
+        strat: AbiAlignmentAdvancedStrat,
+    ) Module.CompileError!AbiAlignmentAdvanced {
+        // This code needs to be kept in sync with the equivalent switch prong
+        // in abiSizeAdvanced.
+        const data = ty.castTag(.error_union).?.data;
+        const code_align = abiAlignment(Type.anyerror, mod);
+        switch (strat) {
+            .eager, .sema => {
+                if (!(data.payload.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
+                    error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
+                    else => |e| return e,
+                })) {
+                    return AbiAlignmentAdvanced{ .scalar = code_align };
+                }
+                return AbiAlignmentAdvanced{ .scalar = @max(
+                    code_align,
+                    (try data.payload.abiAlignmentAdvanced(mod, strat)).scalar,
+                ) };
+            },
+            .lazy => |arena| {
+                switch (try data.payload.abiAlignmentAdvanced(mod, strat)) {
+                    .scalar => |payload_align| {
+                        return AbiAlignmentAdvanced{
+                            .scalar = @max(code_align, payload_align),
+                        };
+                    },
+                    .val => {},
+                }
+                return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) };
+            },
+        }
+    }
+
+    fn abiAlignmentAdvancedOptional(
+        ty: Type,
+        mod: *const Module,
+        strat: AbiAlignmentAdvancedStrat,
+    ) Module.CompileError!AbiAlignmentAdvanced {
+        const target = mod.getTarget();
+        const child_type = ty.optionalChild(mod);
+
+        switch (child_type.zigTypeTag(mod)) {
+            .Pointer => return AbiAlignmentAdvanced{ .scalar = @divExact(target.ptrBitWidth(), 8) },
+            .ErrorSet => return abiAlignmentAdvanced(Type.anyerror, mod, strat),
+            .NoReturn => return AbiAlignmentAdvanced{ .scalar = 0 },
+            else => {},
+        }
+
+        switch (strat) {
+            .eager, .sema => {
+                if (!(child_type.hasRuntimeBitsAdvanced(mod, false, strat) catch |err| switch (err) {
+                    error.NeedLazy => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(strat.lazy, ty) },
+                    else => |e| return e,
+                })) {
+                    return AbiAlignmentAdvanced{ .scalar = 1 };
+                }
+                return child_type.abiAlignmentAdvanced(mod, strat);
+            },
+            .lazy => |arena| switch (try child_type.abiAlignmentAdvanced(mod, strat)) {
+                .scalar => |x| return AbiAlignmentAdvanced{ .scalar = @max(x, 1) },
+                .val => return AbiAlignmentAdvanced{ .val = try Value.Tag.lazy_align.create(arena, ty) },
+            },
+        }
+    }
+
     pub fn abiAlignmentAdvancedUnion(
         ty: Type,
         mod: *const Module,
src/value.zig
@@ -1848,8 +1848,6 @@ pub const Value = struct {
     /// Asserts the value is comparable.
     /// If opt_sema is null then this function asserts things are resolved and cannot fail.
     pub fn orderAdvanced(lhs: Value, rhs: Value, mod: *const Module, opt_sema: ?*Sema) !std.math.Order {
-        const lhs_tag = lhs.tag();
-        const rhs_tag = rhs.tag();
         const lhs_against_zero = try lhs.orderAgainstZeroAdvanced(mod, opt_sema);
         const rhs_against_zero = try rhs.orderAgainstZeroAdvanced(mod, opt_sema);
         switch (lhs_against_zero) {
@@ -1866,6 +1864,8 @@ pub const Value = struct {
         const lhs_float = lhs.isFloat();
         const rhs_float = rhs.isFloat();
         if (lhs_float and rhs_float) {
+            const lhs_tag = lhs.tag();
+            const rhs_tag = rhs.tag();
             if (lhs_tag == rhs_tag) {
                 return switch (lhs.tag()) {
                     .float_16 => return std.math.order(lhs.castTag(.float_16).?.data, rhs.castTag(.float_16).?.data),
@@ -2601,12 +2601,15 @@ pub const Value = struct {
     /// to a decl, or if it points to some part of a decl (like field_ptr or element_ptr),
     /// this function returns null.
     pub fn pointerDecl(val: Value) ?Module.Decl.Index {
-        return switch (val.tag()) {
-            .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl_index,
-            .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
-            .function => val.castTag(.function).?.data.owner_decl,
-            .variable => val.castTag(.variable).?.data.owner_decl,
-            .decl_ref => val.cast(Payload.Decl).?.data,
+        return switch (val.ip_index) {
+            .none => switch (val.tag()) {
+                .decl_ref_mut => val.castTag(.decl_ref_mut).?.data.decl_index,
+                .extern_fn => val.castTag(.extern_fn).?.data.owner_decl,
+                .function => val.castTag(.function).?.data.owner_decl,
+                .variable => val.castTag(.variable).?.data.owner_decl,
+                .decl_ref => val.cast(Payload.Decl).?.data,
+                else => null,
+            },
             else => null,
         };
     }
@@ -3831,35 +3834,44 @@ pub const Value = struct {
 
     /// Returns true if the value is a floating point type and is NaN. Returns false otherwise.
     pub fn isNan(val: Value) bool {
-        return switch (val.tag()) {
-            .float_16 => std.math.isNan(val.castTag(.float_16).?.data),
-            .float_32 => std.math.isNan(val.castTag(.float_32).?.data),
-            .float_64 => std.math.isNan(val.castTag(.float_64).?.data),
-            .float_80 => std.math.isNan(val.castTag(.float_80).?.data),
-            .float_128 => std.math.isNan(val.castTag(.float_128).?.data),
+        return switch (val.ip_index) {
+            .none => switch (val.tag()) {
+                .float_16 => std.math.isNan(val.castTag(.float_16).?.data),
+                .float_32 => std.math.isNan(val.castTag(.float_32).?.data),
+                .float_64 => std.math.isNan(val.castTag(.float_64).?.data),
+                .float_80 => std.math.isNan(val.castTag(.float_80).?.data),
+                .float_128 => std.math.isNan(val.castTag(.float_128).?.data),
+                else => false,
+            },
             else => false,
         };
     }
 
     /// Returns true if the value is a floating point type and is infinite. Returns false otherwise.
     pub fn isInf(val: Value) bool {
-        return switch (val.tag()) {
-            .float_16 => std.math.isInf(val.castTag(.float_16).?.data),
-            .float_32 => std.math.isInf(val.castTag(.float_32).?.data),
-            .float_64 => std.math.isInf(val.castTag(.float_64).?.data),
-            .float_80 => std.math.isInf(val.castTag(.float_80).?.data),
-            .float_128 => std.math.isInf(val.castTag(.float_128).?.data),
+        return switch (val.ip_index) {
+            .none => switch (val.tag()) {
+                .float_16 => std.math.isInf(val.castTag(.float_16).?.data),
+                .float_32 => std.math.isInf(val.castTag(.float_32).?.data),
+                .float_64 => std.math.isInf(val.castTag(.float_64).?.data),
+                .float_80 => std.math.isInf(val.castTag(.float_80).?.data),
+                .float_128 => std.math.isInf(val.castTag(.float_128).?.data),
+                else => false,
+            },
             else => false,
         };
     }
 
     pub fn isNegativeInf(val: Value) bool {
-        return switch (val.tag()) {
-            .float_16 => std.math.isNegativeInf(val.castTag(.float_16).?.data),
-            .float_32 => std.math.isNegativeInf(val.castTag(.float_32).?.data),
-            .float_64 => std.math.isNegativeInf(val.castTag(.float_64).?.data),
-            .float_80 => std.math.isNegativeInf(val.castTag(.float_80).?.data),
-            .float_128 => std.math.isNegativeInf(val.castTag(.float_128).?.data),
+        return switch (val.ip_index) {
+            .none => switch (val.tag()) {
+                .float_16 => std.math.isNegativeInf(val.castTag(.float_16).?.data),
+                .float_32 => std.math.isNegativeInf(val.castTag(.float_32).?.data),
+                .float_64 => std.math.isNegativeInf(val.castTag(.float_64).?.data),
+                .float_80 => std.math.isNegativeInf(val.castTag(.float_80).?.data),
+                .float_128 => std.math.isNegativeInf(val.castTag(.float_128).?.data),
+                else => false,
+            },
             else => false,
         };
     }