authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2020-08-12 21:06:29+03:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-13 08:12:17-07:00
log5c1fe5861389462f309e3f0b69096a85f330dc20
tree947c6d050169327de882ea79db3a47101df4df0f
parent75eaf15740bc42167592f3bdd7205236828191c7

stage2: gen optional types


5 files changed, 81 insertions(+), 4 deletions(-)

src-self-hosted/Module.zig+18
...@@ -2476,6 +2476,24 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst...@@ -2476,6 +2476,24 @@ pub fn coerce(self: *Module, scope: *Scope, dest_type: Type, inst: *Inst) !*Inst
2476 }2476 }
2477 assert(inst.ty.zigTypeTag() != .Undefined);2477 assert(inst.ty.zigTypeTag() != .Undefined);
24782478
2479 // null to ?T
2480 if (dest_type.zigTypeTag() == .Optional and inst.ty.zigTypeTag() == .Null) {
2481 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = inst.ty.onePossibleValue().? });
2482 }
2483
2484 // T to ?T
2485 if (dest_type.zigTypeTag() == .Optional) {
2486 const child_type = dest_type.elemType();
2487 if (inst.value()) |val| {
2488 if (child_type.eql(inst.ty)) {
2489 return self.constInst(scope, inst.src, .{ .ty = dest_type, .val = val });
2490 }
2491 return self.fail(scope, inst.src, "TODO optional wrap {} to {}", .{ val, inst.ty });
2492 } else if (child_type.eql(inst.ty)) {
2493 return self.fail(scope, inst.src, "TODO optional wrap {}", .{inst.ty});
2494 }
2495 }
2496
2479 // *[N]T to []T2497 // *[N]T to []T
2480 if (inst.ty.isSinglePointer() and dest_type.isSlice() and2498 if (inst.ty.isSinglePointer() and dest_type.isSlice() and
2481 (!inst.ty.isConstPtr() or dest_type.isConstPtr()))2499 (!inst.ty.isConstPtr() or dest_type.isConstPtr()))
src-self-hosted/astgen.zig+12
...@@ -105,6 +105,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr...@@ -105,6 +105,7 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: *ast.Node) InnerEr
105 .UndefinedLiteral => return rlWrap(mod, scope, rl, try undefLiteral(mod, scope, node.castTag(.UndefinedLiteral).?)),105 .UndefinedLiteral => return rlWrap(mod, scope, rl, try undefLiteral(mod, scope, node.castTag(.UndefinedLiteral).?)),
106 .BoolLiteral => return rlWrap(mod, scope, rl, try boolLiteral(mod, scope, node.castTag(.BoolLiteral).?)),106 .BoolLiteral => return rlWrap(mod, scope, rl, try boolLiteral(mod, scope, node.castTag(.BoolLiteral).?)),
107 .NullLiteral => return rlWrap(mod, scope, rl, try nullLiteral(mod, scope, node.castTag(.NullLiteral).?)),107 .NullLiteral => return rlWrap(mod, scope, rl, try nullLiteral(mod, scope, node.castTag(.NullLiteral).?)),
108 .OptionalType => return rlWrap(mod, scope, rl, try optionalType(mod, scope, node.castTag(.OptionalType).?)),
108 else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}),109 else => return mod.failNode(scope, node, "TODO implement astgen.Expr for {}", .{@tagName(node.tag)}),
109 }110 }
110}111}
...@@ -293,6 +294,17 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr...@@ -293,6 +294,17 @@ fn boolNot(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerErr
293 return addZIRUnOp(mod, scope, src, .boolnot, operand);294 return addZIRUnOp(mod, scope, src, .boolnot, operand);
294}295}
295296
297fn optionalType(mod: *Module, scope: *Scope, node: *ast.Node.SimplePrefixOp) InnerError!*zir.Inst {
298 const tree = scope.tree();
299 const src = tree.token_locs[node.op_token].start;
300 const meta_type = try addZIRInstConst(mod, scope, src, .{
301 .ty = Type.initTag(.type),
302 .val = Value.initTag(.type_type),
303 });
304 const operand = try expr(mod, scope, .{ .ty = meta_type }, node.rhs);
305 return addZIRUnOp(mod, scope, src, .optional_type, operand);
306}
307
296/// Identifier token -> String (allocated in scope.arena())308/// Identifier token -> String (allocated in scope.arena())
297pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex) InnerError![]const u8 {309pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex) InnerError![]const u8 {
298 const tree = scope.tree();310 const tree = scope.tree();
src-self-hosted/type.zig+4-4
...@@ -569,16 +569,16 @@ pub const Type = extern union {...@@ -569,16 +569,16 @@ pub const Type = extern union {
569 .single_const_pointer_to_comptime_int,569 .single_const_pointer_to_comptime_int,
570 .const_slice_u8,570 .const_slice_u8,
571 .array_u8_sentinel_0,571 .array_u8_sentinel_0,
572 .optional,
573 .optional_single_mut_pointer,
574 .optional_single_const_pointer,
575 => true,
572 // TODO lazy types576 // TODO lazy types
573 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,577 .array => self.elemType().hasCodeGenBits() and self.arrayLen() != 0,
574 .single_const_pointer => self.elemType().hasCodeGenBits(),578 .single_const_pointer => self.elemType().hasCodeGenBits(),
575 .single_mut_pointer => self.elemType().hasCodeGenBits(),579 .single_mut_pointer => self.elemType().hasCodeGenBits(),
576 .int_signed => self.cast(Payload.IntSigned).?.bits == 0,580 .int_signed => self.cast(Payload.IntSigned).?.bits == 0,
577 .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0,581 .int_unsigned => self.cast(Payload.IntUnsigned).?.bits == 0,
578 .optional,
579 .optional_single_mut_pointer,
580 .optional_single_const_pointer,
581 => true,
582582
583 .c_void,583 .c_void,
584 .void,584 .void,
src-self-hosted/zir.zig+18
...@@ -212,6 +212,8 @@ pub const Inst = struct {...@@ -212,6 +212,8 @@ pub const Inst = struct {
212 @"unreachable",212 @"unreachable",
213 /// Bitwise XOR. `^`213 /// Bitwise XOR. `^`
214 xor,214 xor,
215 /// Create an optional type '?T'
216 optional_type,
215217
216 pub fn Type(tag: Tag) type {218 pub fn Type(tag: Tag) type {
217 return switch (tag) {219 return switch (tag) {
...@@ -240,6 +242,7 @@ pub const Inst = struct {...@@ -240,6 +242,7 @@ pub const Inst = struct {
240 .typeof,242 .typeof,
241 .single_const_ptr_type,243 .single_const_ptr_type,
242 .single_mut_ptr_type,244 .single_mut_ptr_type,
245 .optional_type,
243 => UnOp,246 => UnOp,
244247
245 .add,248 .add,
...@@ -372,6 +375,7 @@ pub const Inst = struct {...@@ -372,6 +375,7 @@ pub const Inst = struct {
372 .subwrap,375 .subwrap,
373 .typeof,376 .typeof,
374 .xor,377 .xor,
378 .optional_type,
375 => false,379 => false,
376380
377 .@"break",381 .@"break",
...@@ -2242,6 +2246,20 @@ const EmitZIR = struct {...@@ -2242,6 +2246,20 @@ const EmitZIR = struct {
2242 std.debug.panic("TODO implement emitType for {}", .{ty});2246 std.debug.panic("TODO implement emitType for {}", .{ty});
2243 }2247 }
2244 },2248 },
2249 .Optional => {
2250 const inst = try self.arena.allocator.create(Inst.UnOp);
2251 inst.* = .{
2252 .base = .{
2253 .src = src,
2254 .tag = .optional_type,
2255 },
2256 .positionals = .{
2257 .operand = (try self.emitType(src, ty.elemType())).inst,
2258 },
2259 .kw_args = .{},
2260 };
2261 return self.emitUnnamedDecl(&inst.base);
2262 },
2245 else => std.debug.panic("TODO implement emitType for {}", .{ty}),2263 else => std.debug.panic("TODO implement emitType for {}", .{ty}),
2246 },2264 },
2247 }2265 }
src-self-hosted/zir_sema.zig+29
...@@ -106,6 +106,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!...@@ -106,6 +106,7 @@ pub fn analyzeInst(mod: *Module, scope: *Scope, old_inst: *zir.Inst) InnerError!
106 .isnonnull => return analyzeInstIsNonNull(mod, scope, old_inst.castTag(.isnonnull).?, false),106 .isnonnull => return analyzeInstIsNonNull(mod, scope, old_inst.castTag(.isnonnull).?, false),
107 .boolnot => return analyzeInstBoolNot(mod, scope, old_inst.castTag(.boolnot).?),107 .boolnot => return analyzeInstBoolNot(mod, scope, old_inst.castTag(.boolnot).?),
108 .typeof => return analyzeInstTypeOf(mod, scope, old_inst.castTag(.typeof).?),108 .typeof => return analyzeInstTypeOf(mod, scope, old_inst.castTag(.typeof).?),
109 .optional_type => return analyzeInstOptionalType(mod, scope, old_inst.castTag(.optional_type).?),
109 }110 }
110}111}
111112
...@@ -620,6 +621,34 @@ fn analyzeInstIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) I...@@ -620,6 +621,34 @@ fn analyzeInstIntType(mod: *Module, scope: *Scope, inttype: *zir.Inst.IntType) I
620 return mod.fail(scope, inttype.base.src, "TODO implement inttype", .{});621 return mod.fail(scope, inttype.base.src, "TODO implement inttype", .{});
621}622}
622623
624fn analyzeInstOptionalType(mod: *Module, scope: *Scope, optional: *zir.Inst.UnOp) InnerError!*Inst {
625 const child_type = try resolveType(mod, scope, optional.positionals.operand);
626
627 return mod.constType(scope, optional.base.src, Type.initPayload(switch (child_type.tag()) {
628 .single_const_pointer => blk: {
629 const payload = try scope.arena().create(Type.Payload.OptionalSingleConstPointer);
630 payload.* = .{
631 .pointee_type = child_type.elemType(),
632 };
633 break :blk &payload.base;
634 },
635 .single_mut_pointer => blk: {
636 const payload = try scope.arena().create(Type.Payload.OptionalSingleMutPointer);
637 payload.* = .{
638 .pointee_type = child_type.elemType(),
639 };
640 break :blk &payload.base;
641 },
642 else => blk: {
643 const payload = try scope.arena().create(Type.Payload.Optional);
644 payload.* = .{
645 .child_type = child_type,
646 };
647 break :blk &payload.base;
648 },
649 }));
650}
651
623fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {652fn analyzeInstFnType(mod: *Module, scope: *Scope, fntype: *zir.Inst.FnType) InnerError!*Inst {
624 const return_type = try resolveType(mod, scope, fntype.positionals.return_type);653 const return_type = try resolveType(mod, scope, fntype.positionals.return_type);
625654