From e65c72e19f1cd9cdcff9daf11466507c84dd13e6 Mon Sep 17 00:00:00 2001 From: Jakub Doka Date: Mon, 16 Dec 2024 23:32:08 +0100 Subject: [PATCH] properly type checking, null checks are fixed Signed-off-by: Jakub Doka --- lang/README.md | 8 +++++++- lang/src/son.rs | 47 ++++++++++++++++++++++------------------------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/lang/README.md b/lang/README.md index 3719d53..9720bff 100644 --- a/lang/README.md +++ b/lang/README.md @@ -937,8 +937,14 @@ StructB := struct {g: ^uint, c: StructC} StructC := struct {c: uint} +some_index := fn(): ?uint return 0 + +heap := [u8].(0, 1, 2) + optionala := fn(): ?StructA { - return .(.(&0, .(1)), &0, 0) + i := some_index() + if i == null die + return .(.(&0, .(1)), &0, heap[i]) } Struct := struct {inner: uint} diff --git a/lang/src/son.rs b/lang/src/son.rs index d0e7dcb..89a966e 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -28,11 +28,9 @@ use { fmt::{self, Debug, Display, Write}, format_args as fa, mem, ops::{self, Range}, - usize, }, hashbrown::hash_map, hbbytecode::DisasmError, - std::panic, }; pub const VOID: Nid = 0; @@ -515,10 +513,6 @@ impl Nodes { } cursor = self.idom(cursor, Some(scheds)); } - - //if out == 110 && load == 108 { - // panic!("{min} {cursor} {}", antideps[cursor as usize] == load) - //} break; } Kind::Phi => { @@ -3293,9 +3287,7 @@ impl<'a> Codegen<'a> { } Expr::BinOp { left, pos, op: TokenKind::Assign, right } => { let dest = self.raw_expr(left)?; - let mut value = self.expr_ctx(right, Ctx::default().with_ty(dest.ty))?; - - self.assert_ty(pos, &mut value, dest.ty, "assignment source"); + let value = self.checked_expr(right, dest.ty, "assignment source")?; if dest.var { let var = &mut self.ci.scope.vars[(u16::MAX - dest.id) as usize]; @@ -3425,13 +3417,12 @@ impl<'a> Codegen<'a> { bs.ty = base; } - let mut idx = self.expr_ctx(index, Ctx::default().with_ty(ty::Id::DINT))?; + let idx = self.checked_expr(index, ty::Id::DINT, "subscript")?; match bs.ty.expand() { ty::Kind::Slice(s) => { let elem = self.tys.ins.slices[s].elem; let size = self.ci.nodes.new_const(ty::Id::INT, self.tys.size_of(elem)); - self.assert_ty(index.pos(), &mut idx, ty::Id::DINT, "subscript"); let inps = [VOID, idx.id, size]; let offset = self.ci.nodes.new_node( ty::Id::INT, @@ -3747,10 +3738,8 @@ impl<'a> Codegen<'a> { break; }; - let mut value = self.expr_ctx(field, Ctx::default().with_ty(ty))?; - _ = self.assert_ty(field.pos(), &mut value, ty, "tuple field"); + let value = self.checked_expr(field, ty, "tuple field")?; let mem = self.offset(mem, offset); - self.store_mem(mem, ty, value.id); } @@ -3794,8 +3783,7 @@ impl<'a> Codegen<'a> { for (field, offset) in fields.iter().zip((0u32..).step_by(elem_size as usize)) { - let mut value = self.expr_ctx(field, Ctx::default().with_ty(elem))?; - _ = self.assert_ty(field.pos(), &mut value, elem, "array value"); + let value = self.checked_expr(field, elem, "array value")?; let mem = self.offset(mem, offset); self.store_mem(mem, elem, value.id); } @@ -3843,8 +3831,7 @@ impl<'a> Codegen<'a> { let (ty, offset) = (field.ty, 0); - let mut value = self.expr_ctx(&value, Ctx::default().with_ty(ty))?; - self.assert_ty(fpos, &mut value, ty, fa!("field {}", name)); + let value = self.checked_expr(&value, ty, fa!("field {}", name))?; let mem = self.offset(mem, offset); self.store_mem(mem, ty, value.id); @@ -3877,9 +3864,8 @@ impl<'a> Codegen<'a> { continue; } - let mut value = - self.expr_ctx(&field.value, Ctx::default().with_ty(ty))?; - self.assert_ty(field.pos, &mut value, ty, fa!("field {}", field.name)); + let value = + self.checked_expr(&field.value, ty, fa!("field {}", field.name))?; let mem = self.offset(mem, offset); self.store_mem(mem, ty, value.id); } @@ -3919,7 +3905,7 @@ impl<'a> Codegen<'a> { let mut ret = Some(Value::VOID); for stmt in stmts { ret = ret.and(self.expr_ctx(stmt, Ctx::default().with_ty(ty::Id::VOID))); - if let Some(mut id) = ret { + if let Some(id) = ret { if id.ty != ty::Id::VOID { self.warn( stmt.pos(), @@ -3931,7 +3917,6 @@ impl<'a> Codegen<'a> { ), ); } - self.assert_ty(stmt.pos(), &mut id, ty::Id::VOID, "statement"); } else { break; } @@ -4235,8 +4220,7 @@ impl<'a> Codegen<'a> { Expr::Break { pos } => self.jump_to(pos, 1), Expr::Continue { pos } => self.jump_to(pos, 0), Expr::If { cond, then, else_, .. } => { - let mut cnd = self.expr_ctx(cond, Ctx::default().with_ty(ty::Id::BOOL))?; - self.assert_ty(cond.pos(), &mut cnd, ty::Id::BOOL, "condition"); + let cnd = self.checked_expr(cond, ty::Id::BOOL, "condition")?; let if_node = self.ci.nodes.new_node( ty::Id::VOID, @@ -4391,6 +4375,19 @@ impl<'a> Codegen<'a> { } } + fn checked_expr( + &mut self, + expr: &Expr, + expected_ty: ty::Id, + hint: impl Display, + ) -> Option { + let mut value = self.raw_expr_ctx(expr, Ctx::default().with_ty(expected_ty))?; + self.strip_var(&mut value); + self.assert_ty(expr.pos(), &mut value, expected_ty, hint); + self.strip_ptr(&mut value); + Some(value) + } + fn gen_field( &mut self, ctx: Ctx,