From aeab786fe3bfb652db9a2e86b8352b081fb0e1a7 Mon Sep 17 00:00:00 2001 From: Janis Date: Sat, 8 Mar 2025 12:22:53 +0100 Subject: [PATCH] todo: typechecking, then ensure placeness and IR still work as expected --- src/ast2/typecheck.rs | 249 +++++++++++++++++++++++++++++++++++------- 1 file changed, 209 insertions(+), 40 deletions(-) diff --git a/src/ast2/typecheck.rs b/src/ast2/typecheck.rs index b921db9..fef8123 100644 --- a/src/ast2/typecheck.rs +++ b/src/ast2/typecheck.rs @@ -10,6 +10,7 @@ use super::{ #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum ErrorKind { MismatchingTypes, + DerefNonPointer, } #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -247,6 +248,15 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for TypeChecker<'_> { Ok(Some(ty)) } + fn visit_interned_type_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + intern: intern::Index, + ) -> Result { + Ok(Some(intern)) + } + fn visit_any( &mut self, ast: &'a mut Ast, @@ -257,7 +267,7 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for TypeChecker<'_> { let _ty = match tag { Tag::Root => unreachable!(), Tag::InternedType => Some(data.as_intern()), - Tag::File => self.visit_children(ast, idx)?, + Tag::File => self.visit_file(ast, idx)?, Tag::ArrayType => self.visit_array_type(ast, idx)?, Tag::PointerType => self.visit_pointer_type(ast, idx)?, Tag::TypeDeclRef => self.visit_type_decl_ref(ast, idx)?, @@ -265,18 +275,13 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for TypeChecker<'_> { Tag::FunctionProto => self.visit_function_proto(ast, idx)?, Tag::Parameter => self.visit_parameter(ast, idx)?, Tag::StructDecl => self.visit_struct_decl(ast, idx)?, - Tag::StructDeclInterned => { - let (_, ty) = data.as_two_interns(); - - Some(ty) - } + Tag::StructDeclInterned => self.visit_struct_decl_interned(ast, idx)?, Tag::FunctionDecl => self.visit_function_decl(ast, idx)?, Tag::ParameterList => todo!(), - Tag::Block => todo!(), - Tag::BlockTrailingExpr => todo!(), - Tag::Constant => todo!(), - Tag::ExprStmt => todo!(), - Tag::ReturnStmt => todo!(), + Tag::Block | Tag::BlockTrailingExpr => self.visit_block(ast, idx)?, + Tag::Constant => self.visit_constant(ast, idx)?, + Tag::ExprStmt => self.visit_expr_stmt(ast, idx)?, + Tag::ReturnStmt => self.visit_return_stmt(ast, idx)?, Tag::ReturnExprStmt => todo!(), Tag::VarDecl => todo!(), Tag::MutVarDecl => todo!(), @@ -292,39 +297,203 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for TypeChecker<'_> { Tag::ArgumentList => todo!(), Tag::Argument => todo!(), Tag::NamedArgument => todo!(), - Tag::ExplicitCast => todo!(), - Tag::Deref => todo!(), - Tag::AddressOf => todo!(), - Tag::Not => todo!(), - Tag::Negate => todo!(), - Tag::PlaceToValueConversion => todo!(), - Tag::ValueToPlaceConversion => todo!(), - Tag::Or => todo!(), - Tag::And => todo!(), - Tag::BitOr => todo!(), - Tag::BitXOr => todo!(), - Tag::BitAnd => todo!(), - Tag::Eq => todo!(), - Tag::NEq => todo!(), - Tag::Lt => todo!(), - Tag::Gt => todo!(), - Tag::Le => todo!(), - Tag::Ge => todo!(), - Tag::Shl => todo!(), - Tag::Shr => todo!(), - Tag::Add => todo!(), - Tag::Sub => todo!(), - Tag::Mul => todo!(), - Tag::Div => todo!(), - Tag::Rem => todo!(), - Tag::Assign => todo!(), - Tag::SubscriptExpr => todo!(), - Tag::IfExpr => todo!(), - Tag::IfElseExpr => todo!(), + Tag::ExplicitCast => self.visit_explicit_cast(ast, idx)?, + Tag::Deref => self.visit_deref(ast, idx)?, + Tag::AddressOf => self.visit_address_of(ast, idx)?, + Tag::Not | Tag::Negate => { + let ty = self.visit_any(ast, data.as_index())?; + ty + } + Tag::PlaceToValueConversion => self.visit_place_to_value_conversion(ast, idx)?, + Tag::ValueToPlaceConversion => self.visit_value_to_place_conversion(ast, idx)?, + Tag::Or + | Tag::And + | Tag::BitOr + | Tag::BitXOr + | Tag::BitAnd + | Tag::Eq + | Tag::NEq + | Tag::Lt + | Tag::Gt + | Tag::Le + | Tag::Ge + | Tag::Shl + | Tag::Shr + | Tag::Add + | Tag::Sub + | Tag::Mul + | Tag::Div + | Tag::Rem => { + let (lhs, rhs) = data.as_two_indices(); + let lhs = self.visit_any(ast, lhs)?.unwrap(); + let rhs = self.visit_any(ast, rhs)?.unwrap(); + + if lhs != rhs { + self.errors.push(Error { + idx, + kind: ErrorKind::MismatchingTypes, + }); + } + + Some(lhs) + } + Tag::Assign => self.visit_assign(ast, idx)?, + Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx)?, + Tag::IfExpr => self.visit_if_expr(ast, idx)?, + Tag::IfElseExpr => self.visit_if_else_expr(ast, idx)?, Tag::Error => todo!(), Tag::Undefined => todo!(), }; todo!() } + + fn visit_explicit_cast_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + expr: Index, + ty: Index, + ) -> Result { + _ = self.visit_any(ast, expr)?; + // TODO: make sure this cast is legal + let ty = self.visit_any(ast, ty)?; + + Ok(ty) + } + + fn visit_address_of_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + expr: Index, + ) -> Result { + self.visit_any(ast, expr) + } + + fn visit_deref_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + expr: Index, + ) -> Result { + let ty = self.visit_any(ast, expr)?.unwrap(); + if let intern::Key::PointerType { pointee, .. } = self.ip.get_key(ty) { + Ok(Some(pointee)) + } else { + Ok(None) + } + } + + fn visit_place_to_value_conversion_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + expr: Index, + ) -> Result { + let ty = self.visit_any(ast, expr)?; + + if let Some(ty) = ty { + Ok(self.ip.try_get_pointee_type(ty)) + } else { + self.errors.push(Error { + idx, + kind: ErrorKind::DerefNonPointer, + }); + Ok(None) + } + } + + fn visit_value_to_place_conversion_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + expr: Index, + ) -> Result { + let ty = self.visit_any(ast, expr)?; + + if let Some(ty) = ty { + Ok(Some(self.ip.get_pointer_type(ty, None))) + } else { + Ok(None) + } + } + + fn visit_if_else_expr_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + cond: Index, + a: Index, + b: Index, + ) -> Result { + self.visit_any(ast, cond)?; + let a = self.visit_block(ast, a)?; + let b = self.visit_block(ast, b)?; + + if a != b { + self.errors.push(Error { + idx, + kind: ErrorKind::MismatchingTypes, + }); + } + + Ok(a) + } + + fn visit_if_expr_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + cond: Index, + body: Index, + ) -> Result { + self.visit_any(ast, cond)?; + self.visit_block(ast, body)?; + + Ok(None) + } + + fn visit_subscript_expr_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + lhs: Index, + index: Index, + ) -> Result { + let lhs = self.visit_any(ast, lhs)?.unwrap(); + let index = self.visit_any(ast, index)?.unwrap(); + + if index != intern::Index::USIZE { + self.errors.push(Error { + idx, + kind: ErrorKind::MismatchingTypes, + }); + } + + let pointee = self.ip.try_get_pointee_type(lhs).unwrap(); + let pointer = self.ip.get_pointer_type(pointee, None); + + Ok(Some(pointer)) + } + + fn visit_assign_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + lhs: Index, + rhs: Index, + ) -> Result { + let lhs = self.visit_any(ast, lhs)?.unwrap(); + let rhs = self.visit_any(ast, rhs)?.unwrap(); + + if self.ip.try_get_pointee_type(lhs) != Some(rhs) { + self.errors.push(Error { + idx, + kind: ErrorKind::MismatchingTypes, + }); + } + + Ok(None) + } }