diff --git a/lang/README.md b/lang/README.md index c0f77249..3a90e58d 100644 --- a/lang/README.md +++ b/lang/README.md @@ -160,7 +160,7 @@ drop := fn(a: uint): void { #### nullable_types ```hb -main := fn(): int { +main := fn(): uint { a := &1 b := @as(?^uint, null) @@ -174,13 +174,21 @@ main := fn(): int { if c != null return 42 d := @as(?u16, null) - if decide() d = 0 + if decide() d = 1 if d == null return 69 - return d + f := @as(?Foo, null) + + if decide() f = .(a, 1) + + if f == null return 34 + + return d - *f.a } +Foo := struct {a: ^uint, b: uint} + decide := fn(): bool return true ``` diff --git a/lang/src/son.rs b/lang/src/son.rs index ec816638..d4a4542a 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -2471,6 +2471,7 @@ impl<'a> Codegen<'a> { Expr::Field { target, name, pos } => { let mut vtarget = self.raw_expr(target)?; self.strip_var(&mut vtarget); + self.unwrap_opt(pos, &mut vtarget); let tty = vtarget.ty; if let ty::Kind::Module(m) = tty.expand() { @@ -2632,6 +2633,7 @@ impl<'a> Codegen<'a> { { let mut lhs = self.raw_expr_ctx(left, ctx)?; self.strip_var(&mut lhs); + self.unwrap_opt(left.pos(), &mut lhs); match lhs.ty.expand() { _ if lhs.ty.is_pointer() @@ -2645,6 +2647,7 @@ impl<'a> Codegen<'a> { self.ci.nodes.unlock(lhs.id); let mut rhs = rhs?; self.strip_var(&mut rhs); + self.unwrap_opt(right.pos(), &mut rhs); let (ty, aclass, mem) = self.binop_ty(pos, &mut lhs, &mut rhs, op); let inps = [VOID, lhs.id, rhs.id]; let bop = @@ -3113,7 +3116,9 @@ impl<'a> Codegen<'a> { }) } Expr::Tupl { pos, ty, fields, .. } => { - ctx.ty = ty.map(|ty| self.ty(ty)).or(ctx.ty); + ctx.ty = ty + .map(|ty| self.ty(ty)) + .or(ctx.ty.map(|ty| self.tys.inner_of(ty).unwrap_or(ty))); inference!(sty, ctx, self, pos, "struct or slice", ".(...)"); match sty.expand() { @@ -3204,7 +3209,9 @@ impl<'a> Codegen<'a> { Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, value)) } Expr::Ctor { pos, ty, fields, .. } => { - ctx.ty = ty.map(|ty| self.ty(ty)).or(ctx.ty); + ctx.ty = ty + .map(|ty| self.ty(ty)) + .or(ctx.ty.map(|ty| self.tys.inner_of(ty).unwrap_or(ty))); inference!(sty, ctx, self, pos, "struct", ".{...}"); let ty::Kind::Struct(s) = sty.expand() else { @@ -4061,7 +4068,7 @@ impl<'a> Codegen<'a> { cmped.id = self.offset(cmped.id, flag_offset); cmped.ty = flag_ty; self.strip_ptr(&mut cmped); - let inps = [VOID, cmped.id, self.ci.nodes.new_const(ty, 0)]; + let inps = [VOID, cmped.id, self.ci.nodes.new_const(flag_ty, 0)]; self.ci.nodes.new_node(ty::Id::BOOL, Kind::BinOp { op }, inps) } } diff --git a/lang/src/son/hbvm.rs b/lang/src/son/hbvm.rs index 248f80ab..7a4d9040 100644 --- a/lang/src/son/hbvm.rs +++ b/lang/src/son/hbvm.rs @@ -227,8 +227,8 @@ impl ItemCtx { let mut extend = |base: ty::Id, dest: ty::Id, from: usize, to: usize| { let (bsize, dsize) = (tys.size_of(base), tys.size_of(dest)); - debug_assert!(bsize <= 8); - debug_assert!(dsize <= 8); + debug_assert!(bsize <= 8, "{}", ty::Display::new(tys, files, base)); + debug_assert!(dsize <= 8, "{}", ty::Display::new(tys, files, dest)); if bsize == dsize { return Default::default(); } diff --git a/lang/tests/son_tests_nullable_types.txt b/lang/tests/son_tests_nullable_types.txt index c2fe65f0..01334e5d 100644 --- a/lang/tests/son_tests_nullable_types.txt +++ b/lang/tests/son_tests_nullable_types.txt @@ -2,50 +2,68 @@ decide: LI8 r1, 1b JALA r0, r31, 0a main: - ADDI64 r254, r254, -40d - ST r31, r254, 24a, 16h + ADDI64 r254, r254, -72d + ST r31, r254, 40a, 32h JAL r31, r0, :decide - LI64 r3, 0d + LI64 r4, 0d + ADDI64 r32, r254, 32d ANDI r1, r1, 255d JNE r1, r0, :0 - CP r32, r3 + CP r33, r4 JMP :1 - 0: ADDI64 r32, r254, 16d - 1: JNE r32, r3, :2 + 0: CP r33, r32 + 1: JNE r33, r4, :2 LI64 r1, 9001d JMP :3 2: JAL r31, r0, :decide + LI8 r8, 0b ANDI r1, r1, 255d JNE r1, r0, :4 - LI8 r6, 1b - ST r6, r254, 0a, 1h - LD r7, r32, 0a, 8h - ST r7, r254, 8a, 8h + LI8 r9, 1b + ST r9, r254, 16a, 1h + LD r9, r33, 0a, 8h + ST r9, r254, 24a, 8h JMP :5 - 4: LI8 r1, 0b - ST r1, r254, 0a, 1h - 5: LI64 r6, 0d - LD r7, r254, 0a, 1h - ANDI r7, r7, 255d - JEQ r7, r6, :6 + 4: ST r8, r254, 16a, 1h + 5: LD r6, r254, 16a, 1h + ANDI r6, r6, 255d + ANDI r8, r8, 255d + JEQ r6, r8, :6 LI64 r1, 42d JMP :3 6: JAL r31, r0, :decide LI32 r2, 0w ANDI r1, r1, 255d JNE r1, r0, :7 - CP r8, r2 + CP r34, r2 JMP :8 - 7: LI32 r8, 8388608w - 8: ANDI r8, r8, 4294967295d + 7: LI32 r34, 8388609w + 8: ANDI r34, r34, 4294967295d ANDI r2, r2, 4294967295d - JNE r8, r2, :9 + JNE r34, r2, :9 LI64 r1, 69d JMP :3 - 9: ANDI r1, r8, 65535d - 3: LD r31, r254, 24a, 16h - ADDI64 r254, r254, 40d + 9: JAL r31, r0, :decide + LI64 r3, 0d + ANDI r1, r1, 255d + JNE r1, r0, :10 + ST r3, r254, 0a, 8h + JMP :11 +10: ST r32, r254, 0a, 8h + LI64 r4, 1d + ST r4, r254, 8a, 8h + ST r4, r254, 32a, 8h +11: LD r2, r254, 0a, 8h + JNE r2, r3, :12 + LI64 r1, 34d + JMP :3 +12: LD r8, r254, 0a, 8h + LD r10, r8, 0a, 8h + ANDI r12, r34, 65535d + SUB64 r1, r12, r10 + 3: LD r31, r254, 40a, 32h + ADDI64 r254, r254, 72d JALA r0, r31, 0a -code size: 389 +code size: 556 ret: 0 status: Ok(())