Commit 13b2f1e90b

Vexu <git@vexu.eu>
2020-08-16 20:51:05
address review feedback
1 parent ece4a2f
src-self-hosted/astgen.zig
@@ -453,8 +453,6 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
 }
 
 fn addressOf(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
-    const tree = scope.tree();
-    const src = tree.token_locs[node.op_token].start;
     return expr(mod, scope, .lvalue, node.rhs);
 }
 
@@ -490,8 +488,6 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir
             .single_const_ptr_type, child_type);
     }
 
-    const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
-
     var kw_args: std.meta.fieldInfo(zir.Inst.PtrType, "kw_args").field_type = .{};
     kw_args.@"allowzero" = node.ptr_info.allowzero_token != null;
     if (node.ptr_info.align_info) |some| {
@@ -504,7 +500,12 @@ fn ptrType(mod: *Module, scope: *Scope, node: *ast.Node.PtrType) InnerError!*zir
     kw_args.@"const" = node.ptr_info.const_token != null;
     kw_args.@"volatile" = node.ptr_info.volatile_token != null;
     if (node.ptr_info.sentinel) |some| {
-        kw_args.sentinel = try expr(mod, scope, .{ .ty = child_type }, some);
+        kw_args.sentinel = try expr(mod, scope, .none, some);
+    }
+
+    const child_type = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
+    if (kw_args.sentinel) |some| {
+        kw_args.sentinel = try addZIRBinOp(mod, scope, some.src, .as, child_type, some);
     }
 
     return addZIRInst(mod, scope, src, zir.Inst.PtrType, .{ .child_type = child_type }, kw_args);
@@ -629,7 +630,9 @@ const CondKind = union(enum) {
         const payload = payload_node.?.castTag(.PointerPayload).?;
         const is_ptr = payload.ptr_token != null;
         const ident_node = payload.value_symbol.castTag(.Identifier).?;
-        const ident_name = try identifierTokenString(mod, &then_scope.base, ident_node.token);
+
+        // This intentionally does not support @"_" syntax.
+        const ident_name = then_scope.base.tree().tokenSlice(ident_node.token);
         if (mem.eql(u8, ident_name, "_")) {
             if (is_ptr)
                 return mod.failTok(&then_scope.base, payload.ptr_token.?, "pointer modifier invalid on discard", .{});
@@ -646,7 +649,9 @@ const CondKind = union(enum) {
 
         const payload = payload_node.?.castTag(.Payload).?;
         const ident_node = payload.error_symbol.castTag(.Identifier).?;
-        const ident_name = try identifierTokenString(mod, &else_scope.base, ident_node.token);
+
+        // This intentionally does not support @"_" syntax.
+        const ident_name = else_scope.base.tree().tokenSlice(ident_node.token);
         if (mem.eql(u8, ident_name, "_")) {
             return &else_scope.base;
         }
@@ -660,9 +665,6 @@ fn ifExpr(mod: *Module, scope: *Scope, rl: ResultLoc, if_node: *ast.Node.If) Inn
     if (if_node.payload) |_| cond_kind = .{ .optional = null };
     if (if_node.@"else") |else_node| {
         if (else_node.payload) |payload| {
-            if (cond_kind != .optional) {
-                return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{});
-            }
             cond_kind = .{ .err_union = null };
         }
     }
@@ -760,9 +762,6 @@ fn whileExpr(mod: *Module, scope: *Scope, rl: ResultLoc, while_node: *ast.Node.W
     if (while_node.payload) |_| cond_kind = .{ .optional = null };
     if (while_node.@"else") |else_node| {
         if (else_node.payload) |payload| {
-            if (cond_kind != .optional) {
-                return mod.failNode(scope, payload, "else payload invalid on bool conditions", .{});
-            }
             cond_kind = .{ .err_union = null };
         }
     }
src-self-hosted/codegen.zig
@@ -2052,7 +2052,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
             return mcv;
         }
 
-        fn genTypedValue(self: *Self, src: usize, typed_value: TypedValue) error{ CodegenFail, OutOfMemory }!MCValue {
+        fn genTypedValue(self: *Self, src: usize, typed_value: TypedValue) InnerError!MCValue {
             if (typed_value.val.isUndef())
                 return MCValue{ .undef = {} };
             const ptr_bits = self.target.cpu.arch.ptrBitWidth();
@@ -2199,7 +2199,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
             };
         }
 
-        fn fail(self: *Self, src: usize, comptime format: []const u8, args: anytype) error{ CodegenFail, OutOfMemory } {
+        fn fail(self: *Self, src: usize, comptime format: []const u8, args: anytype) InnerError {
             @setCold(true);
             assert(self.err_msg == null);
             self.err_msg = try ErrorMsg.create(self.bin_file.base.allocator, src, format, args);
src-self-hosted/Module.zig
@@ -2433,7 +2433,6 @@ fn wrapOptional(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*In
         return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val });
     }
 
-    // TODO how do we get the result location
     const b = try self.requireRuntimeBlock(scope, inst.src);
     return self.addUnOp(b, inst.src, dest_type, .wrap_optional, inst);
 }
src-self-hosted/type.zig
@@ -362,7 +362,7 @@ pub const Type = extern union {
             .single_mut_pointer,
             .optional_single_mut_pointer,
             .optional_single_const_pointer,
-             => return self.copyPayloadSingleField(allocator, Payload.Pointer, "pointee_type"),
+            => return self.copyPayloadSingleField(allocator, Payload.Pointer, "pointee_type"),
         }
     }
 
@@ -1086,14 +1086,14 @@ pub const Type = extern union {
             .optional_single_mut_pointer => {
                 buf.* = .{
                     .base = .{ .tag = .single_mut_pointer },
-                    .pointee_type = self.castPointer().?.pointee_type
+                    .pointee_type = self.castPointer().?.pointee_type,
                 };
                 return Type.initPayload(&buf.base);
             },
             .optional_single_const_pointer => {
                 buf.* = .{
                     .base = .{ .tag = .single_const_pointer },
-                    .pointee_type = self.castPointer().?.pointee_type
+                    .pointee_type = self.castPointer().?.pointee_type,
                 };
                 return Type.initPayload(&buf.base);
             },
@@ -1101,6 +1101,28 @@ pub const Type = extern union {
         };
     }
 
+    /// Asserts that the type is an optional.
+    /// Same as `optionalChild` but allocates the buffer if needed.
+    pub fn optionalChildAlloc(self: Type, allocator: *Allocator) !Type {
+        return switch (self.tag()) {
+            .optional => self.cast(Payload.Optional).?.child_type,
+            .optional_single_mut_pointer, .optional_single_const_pointer => {
+                const payload = try allocator.create(Payload.Pointer);
+                payload.* = .{
+                    .base = .{
+                        .tag = if (self.tag() == .optional_single_const_pointer)
+                            .single_const_pointer
+                        else
+                            .single_mut_pointer,
+                    },
+                    .pointee_type = self.castPointer().?.pointee_type,
+                };
+                return Type.initPayload(&payload.base);
+            },
+            else => unreachable,
+        };
+    }
+
     /// Asserts the type is an array or vector.
     pub fn arrayLen(self: Type) u64 {
         return switch (self.tag()) {
src-self-hosted/zir_sema.zig
@@ -710,8 +710,7 @@ fn analyzeInstUnwrapOptional(mod: *Module, scope: *Scope, unwrap: *zir.Inst.UnOp
         return mod.fail(scope, unwrap.base.src, "expected optional type, found {}", .{operand.ty.elemType()});
     }
 
-    var buf: Type.Payload.Pointer = undefined;
-    const child_type = try operand.ty.elemType().optionalChild(&buf).copy(scope.arena());
+    const child_type = try operand.ty.elemType().optionalChildAlloc(scope.arena());
     const child_pointer = try mod.singlePtrType(scope, unwrap.base.src, operand.ty.isConstPtr(), child_type);
 
     if (operand.value()) |val| {