From 4c7813aa98da07c13abed5ae5d3a6018d25b05d8 Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 6 Mar 2025 23:46:45 +0100 Subject: [PATCH] aaaaaaaaaaaaaaaa --- src/ast2/ir.rs | 547 +++++++++++++++++------------------ src/ast2/mod.rs | 1 + src/ast2/tag.rs | 6 +- src/ast2/typecheck.rs | 330 +++++++++++++++++++++ src/ast2/visitor.rs | 645 ++++++++++++++++++++++-------------------- 5 files changed, 940 insertions(+), 589 deletions(-) create mode 100644 src/ast2/typecheck.rs diff --git a/src/ast2/ir.rs b/src/ast2/ir.rs index 4ed220a..b92efff 100644 --- a/src/ast2/ir.rs +++ b/src/ast2/ir.rs @@ -41,32 +41,29 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { type Value = Option; const UNIMPL: Self::Error = Error::Unimplemented; - fn visit_block( + fn visit_block_impl( &mut self, ast: &'a mut super::Ast, - idx: super::Index, + _idx: Index, + statements: Vec, + expr: Option, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Block); - let (a, b) = data.as_extra_range(); - - ast.extra[a..b] - .to_vec() + statements .into_iter() - .map(|i| Index::from_u32(i).unwrap()) .map(|i| self.visit_any(ast, i)) .try_fold((), |_, e| e.map(crate::unit))?; - Ok(None) + expr.map(|expr| self.visit_any(ast, expr)) + .transpose() + .map(Option::flatten) } - fn visit_place_to_value_conversion( + fn visit_place_to_value_conversion_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::PlaceToValueConversion); - let expr = data.as_index(); - // idx's (this) type is the pointee type let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); @@ -76,14 +73,12 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(ir)) } - fn visit_value_to_place_conversion( + fn visit_value_to_place_conversion_impl( &mut self, ast: &'a mut super::Ast, - idx: Index, + _idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::ValueToPlaceConversion); - let expr = data.as_index(); - // expr's type is the pointee type let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); @@ -103,68 +98,73 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(alloca)) } - fn visit_decl_ref( + fn visit_decl_ref_impl( &mut self, - ast: &'a mut super::Ast, - idx: Index, + _ast: &'a mut super::Ast, + _idx: Index, + decl: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::DeclRef); - let decl = data.as_index(); - let alloca = self.ref_lookup.get(&decl).cloned().expect("declref"); Ok(Some(alloca)) } - fn visit_var_decl( + fn visit_var_decl_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + name: intern::Index, + ty: Index, ) -> Result { self.visit_var_decl_common(ast, idx) } - fn visit_mut_var_decl( + fn visit_mut_var_decl_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + name: intern::Index, + ty: Index, ) -> Result { self.visit_var_decl_common(ast, idx) } - fn visit_var_assign_decl( + fn visit_var_decl_assignment_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + name: intern::Index, + expr: Index, + ty: Option, ) -> Result { self.visit_var_decl_common(ast, idx) } - fn visit_mut_var_assign_decl( + fn visit_mut_var_decl_assignment_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + name: intern::Index, + expr: Index, + ty: Option, ) -> Result { self.visit_var_decl_common(ast, idx) } - fn visit_return( + fn visit_return_stmt_impl( &mut self, - ast: &'a mut super::Ast, - idx: Index, + _ast: &'a mut super::Ast, + _idx: Index, ) -> Result { - _ = (ast, idx); - let ir = self.ir.push(Inst::Return, None); Ok(Some(ir)) } - fn visit_return_expr( + fn visit_return_expr_stmt_impl( &mut self, ast: &'a mut super::Ast, - idx: Index, + _idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::ReturnExprStmt); - let expr = data.as_index(); let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); let expr = self.visit_any(ast, expr)?.unwrap(); @@ -175,28 +175,26 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(ir)) } - fn visit_constant( + fn visit_constant_impl( &mut self, ast: &'a mut super::Ast, - idx: Index, + _idx: Index, + ty: Index, + value: intern::Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Constant); - let (ty, value) = data.as_index_intern(); - let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty); let ir = self.ir.push(Inst::Constant, Some((ty, value).into())); Ok(Some(ir)) } - fn visit_subscript_expr( + fn visit_subscript_expr_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + index: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::SubscriptExpr); - let (lhs, index) = data.as_two_indices(); - // pointer type let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); @@ -212,16 +210,16 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(ir)) } - fn visit_call_expr( + fn visit_call_expr_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + func: Index, + argument_list: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::CallExpr); - let (func, arguments) = data.as_two_indices(); let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); - let len = self.visit_parameter_list(ast, arguments)?.unwrap(); + let len = self.visit_argument_list(ast, argument_list)?.unwrap(); _ = self.ir.push(Inst::InlineType(ty), None); let end = self.ir.nodes.len() as u32; @@ -234,14 +232,13 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(result)) } - fn visit_argument( + fn visit_argument_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + expr: Index, + name: Option, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Argument); - let expr = data.as_index(); - let arg = self.visit_any(ast, expr)?.unwrap(); // let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); @@ -250,32 +247,21 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(arg)) } - // fn visit_named_argument( - // &mut self, - // ast: &'a mut super::Ast, - // idx: Index, - // ) -> Result { - // todo!() - // } - - fn visit_argument_list( + fn visit_argument_list_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + arguments: Vec, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::ArgumentList); - let (a, b) = data.as_extra_range(); - - let args = ast.extra[a..b] - .to_vec() + let args = arguments .into_iter() - .map(|i| Index::from_u32(i).unwrap()) .map(|i| { let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, i); - let arg = self.visit_any_argument(ast, i)?.unwrap(); + let arg = self.visit_argument(ast, i)?.unwrap(); Ok((ty, arg)) }) .collect::, _>>()?; + let count = args.len(); for (ty, arg) in args { _ = self @@ -287,70 +273,40 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(count as u32)) } - fn visit_block_trailing_expr( + fn visit_function_proto_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + name: intern::Index, + return_type: Index, + parameter_list: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::BlockTrailingExpr); - - let (a, b) = data.as_extra_range(); - - let expr = ast.extra[a..b] - .to_vec() - .into_iter() - .map(|i| Index::from_u32(i).unwrap()) - .map(|i| self.visit_any(ast, i)) - // the last node is the trailing - .try_fold(None, |_, e| e)?; - - Ok(expr) - } - - fn visit_function_proto( - &mut self, - ast: &'a mut super::Ast, - idx: super::Index, - ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::FunctionProto); - - let (_, extra) = data.as_intern_and_extra_offset(); - let (_return_type, parameter_list) = ( - Index::from_u32(ast.extra[extra]).unwrap(), - Index::from_u32(ast.extra[extra + 1]).unwrap(), - ); - self.visit_parameter_list(ast, parameter_list)?; // push parameters to ir Ok(None) } - fn visit_parameter_list( + fn visit_parameter_list_impl( &mut self, ast: &'a mut super::Ast, - idx: Index, + _idx: Index, + params: Vec, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::ParameterList); - let (a, b) = data.as_extra_range(); - - ast.extra[a..b] - .to_vec() + params .into_iter() - .map(|i| Index::from_u32(i).unwrap()) .map(|i| self.visit_parameter(ast, i)) .try_fold((), |_, e| e.map(crate::unit))?; Ok(None) } - fn visit_parameter( + fn visit_parameter_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + ty: Index, + _name: intern::Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Parameter); - let (ty, _name) = data.as_index_intern(); - let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty); let info = self.ip.size_of_type(ty, AMD64_POINTER_TYPE_INFO); let ir = self.ir.push( @@ -362,14 +318,12 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(None) } - fn visit_address_of_expr( + fn visit_address_of_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::AddressOf); - let expr = data.as_index(); - let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); let expr = self.visit_any(ast, expr)?.unwrap(); let r = self @@ -379,17 +333,16 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(r)) } - fn visit_assign( + fn visit_assign_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Assign); - let (dst, src) = data.as_two_indices(); - let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); - let dst = self.visit_any(ast, dst)?.unwrap(); - let src = self.visit_any(ast, src)?.unwrap(); + let dst = self.visit_any(ast, lhs)?.unwrap(); + let src = self.visit_any(ast, rhs)?.unwrap(); let ir = self .ir @@ -398,18 +351,17 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(ir)) } - fn visit_explicit_cast_expr( + fn visit_explicit_cast_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + expr: Index, + ty: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::ExplicitCast); - let (lhs, ty) = data.as_two_indices(); - - let lty = ast.get_type_of_node(&self.ip, &mut self.type_cache, lhs); + let lty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); let rty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty); - let lhs = self.visit_any(ast, lhs)?.unwrap(); + let lhs = self.visit_any(ast, expr)?.unwrap(); // TODO: if bitwidth is the same, then this is a noop? let cast = self @@ -419,14 +371,13 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(cast)) } - fn visit_if_expr( + fn visit_if_expr_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + cond: Index, + body: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::IfExpr); - let (cond, body) = data.as_two_indices(); - let cond = self.visit_any(ast, cond)?.unwrap(); let br = self.ir.push(Inst::Branch(cond), None); @@ -445,32 +396,29 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(br)) } - fn visit_if_else_expr( + fn visit_if_else_expr_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + cond: Index, + a: Index, + b: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::IfElseExpr); - let (cond, extra) = data.as_index_and_extra_offset(); let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); - let [a, b] = ast.extra[extra..][..2] else { - unreachable!() - }; - let cond = self.visit_any(ast, cond)?.unwrap(); let br = self.ir.push(Inst::Branch(cond), None); let la = self .ir .push(Inst::Label, Some(intern::Index::EMPTY_STRING.into())); - let a = self.visit_any(ast, Index::from_u32(a).unwrap())?.unwrap(); + let a = self.visit_any(ast, a)?.unwrap(); let jmpa = self.ir.push(Inst::Jump, None); let lb = self .ir .push(Inst::Label, Some(intern::Index::EMPTY_STRING.into())); - let b = self.visit_any(ast, Index::from_u32(b).unwrap())?.unwrap(); + let b = self.visit_any(ast, b)?.unwrap(); let jmpb = self.ir.push(Inst::Jump, None); let lphi = self @@ -490,14 +438,12 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(phi)) } - fn visit_deref_expr( + fn visit_deref_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Not); - let expr = data.as_index(); - let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); let expr = self.visit_any(ast, expr)?.unwrap(); let not = self.ir.push(Inst::Load(ty), Some(triples::Data::lhs(expr))); @@ -505,14 +451,12 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(not)) } - fn visit_not_expr( + fn visit_not_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Not); - let expr = data.as_index(); - let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); let expr = self.visit_any(ast, expr)?.unwrap(); let not = self.ir.push(Inst::Not(ty), Some(triples::Data::lhs(expr))); @@ -520,14 +464,12 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(not)) } - fn visit_negate_expr( + fn visit_negate_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Negate); - let expr = data.as_index(); - let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); let expr = self.visit_any(ast, expr)?.unwrap(); let not = self @@ -537,18 +479,17 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(not)) } - fn visit_or_expr( + fn visit_or_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Or); - let (a, b) = data.as_two_indices(); - let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); // TODO: make this an error instead of a panic - let a = self.visit_any(ast, a)?.unwrap(); + let a = self.visit_any(ast, lhs)?.unwrap(); let not_a = self.ir.push(Inst::Not(ty), Some(triples::Data::lhs(a))); // branch taken if a @@ -557,7 +498,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { .ir .push(Inst::Label, Some(intern::Index::EMPTY_STRING.into())); - let b = self.visit_any(ast, b)?.unwrap(); + let b = self.visit_any(ast, rhs)?.unwrap(); let jmp = self.ir.push(Inst::Jump, None); let la = self @@ -575,16 +516,15 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(or)) } - fn visit_and_expr( + fn visit_and_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Or); - let (a, b) = data.as_two_indices(); - // TODO: make this an error instead of a panic - let a = self.visit_any(ast, a)?.unwrap(); + let a = self.visit_any(ast, lhs)?.unwrap(); // branch taken if a let br = self.ir.push(Inst::Branch(a), None); @@ -592,7 +532,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { let lb = self .ir .push(Inst::Label, Some(intern::Index::EMPTY_STRING.into())); - let b = self.visit_any(ast, b)?.unwrap(); + let b = self.visit_any(ast, rhs)?.unwrap(); let skip = self .ir @@ -607,117 +547,149 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { Ok(Some(and)) } - fn visit_add_expr( + fn visit_add_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_sub_expr( + fn visit_sub_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_div_expr( + fn visit_div_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_rem_expr( + fn visit_rem_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_mul_expr( + fn visit_mul_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_bitand_expr( + fn visit_bit_and_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_bitor_expr( + fn visit_bit_or_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_bitxor_expr( + fn visit_bit_x_or_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_eq_expr( + fn visit_eq_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_neq_expr( + fn visit_n_eq_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_lt_expr( + fn visit_lt_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_gt_expr( + fn visit_gt_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_le_expr( + fn visit_le_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_ge_expr( + fn visit_ge_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_shl_expr( + fn visit_shl_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } - fn visit_shr_expr( + fn visit_shr_impl( &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result { - self.visit_binop_expr(ast, idx) + self.visit_binop_expr(ast, idx, lhs, rhs) } } @@ -787,10 +759,11 @@ impl IrFunctionBuilder<'_> { &mut self, ast: &'a mut super::Ast, idx: Index, + lhs: Index, + rhs: Index, ) -> Result, Error> { use triples::Data; - let (tag, data) = ast.get_node_tag_and_data(idx); - let (lhs, rhs) = data.as_two_indices(); + let tag = ast.tags[idx]; let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); @@ -854,14 +827,13 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { const UNIMPL: Self::Error = (); - fn visit_subscript_expr( + fn visit_subscript_expr_impl( &mut self, ast: &'a mut Ast, idx: Index, + lhs: Index, + index: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::SubscriptExpr); - let (lhs, index) = data.as_two_indices(); - let lhs = self.visit_any(ast, lhs)?; let index = self.visit_any(ast, index)?; @@ -873,14 +845,13 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { Ok(PlaceOrValue::Place(idx)) } - fn visit_deref_expr( + fn visit_deref_impl( &mut self, ast: &'a mut Ast, idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Deref); - - let expr = self.visit_any(ast, data.as_index())?; + let expr = self.visit_any(ast, expr)?; let expr = ast.convert_to_value_expr(expr); ast.datas[idx] = Data::index(expr); @@ -888,91 +859,98 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { Ok(PlaceOrValue::Place(idx)) } - fn visit_parameter( + fn visit_parameter_impl( &mut self, - _ast: &'a mut Ast, + ast: &'a mut Ast, idx: Index, + ty: Index, + name: intern::Index, ) -> Result { Ok(PlaceOrValue::Value(idx)) } - fn visit_var_decl( + fn visit_var_decl_impl( &mut self, - _ast: &'a mut Ast, + ast: &'a mut Ast, idx: Index, + name: intern::Index, + ty: Index, ) -> Result { Ok(PlaceOrValue::Place(idx)) } - fn visit_global_decl( + fn visit_global_decl_impl( &mut self, - _ast: &'a mut Ast, + ast: &'a mut Ast, idx: Index, + name: intern::Index, + expr: Index, + ty: Index, ) -> Result { Ok(PlaceOrValue::Place(idx)) } - fn visit_address_of_expr( + fn visit_address_of_impl( &mut self, - _ast: &'a mut Ast, + ast: &'a mut Ast, idx: Index, + expr: Index, ) -> Result { Ok(PlaceOrValue::Value(idx)) } - fn visit_decl_ref(&mut self, ast: &'a mut Ast, idx: Index) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::DeclRef); - let decl = self.visit_any(ast, data.as_index())?; + fn visit_decl_ref_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + decl: Index, + ) -> Result { + let decl = self.visit_any(ast, decl)?; // copy the placeness of the decl referenced. // parameters are values, var decls are places Ok(decl.with_index(idx)) } - fn visit_function_decl( + fn visit_function_decl_impl( &mut self, ast: &'a mut Ast, idx: Index, + proto: Index, + body: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::FunctionDecl); - let (_, body) = data.as_two_indices(); - let _body = self.visit_block_maybe_trailing_as_value(ast, body)?; Ok(PlaceOrValue::Value(idx)) } - fn visit_block(&mut self, ast: &'a mut Ast, idx: Index) -> Result { - self.visit_children(ast, idx)?; - - // this block returns nothing, so it can safely be a value - Ok(PlaceOrValue::Value(idx)) - } - - fn visit_block_trailing_expr( + fn visit_block_impl( &mut self, ast: &'a mut Ast, idx: Index, + statements: Vec, + expr: Option, ) -> Result { - let (a, b) = ast.datas[idx].as_extra_range(); - let children = unsafe { Index::from_slice_unchecked(&ast.extra[a..b]) }.to_vec(); - let (expr, statements) = children.split_last().unwrap(); - - for statement in statements { - self.visit_any(ast, *statement)?; + for child in statements { + self.visit_any(ast, child)?; } - // copy placeness of trailing expression - Ok(self.visit_any(ast, *expr)?.with_index(idx)) + if let Some(expr) = expr { + // copy placeness of trailing expression + Ok(self.visit_any(ast, expr)?.with_index(idx)) + } else { + // this block returns nothing, so it can safely be a value + Ok(PlaceOrValue::Value(idx)) + } } - fn visit_return_expr( + fn visit_return_expr_stmt_impl( &mut self, ast: &'a mut Ast, idx: Index, + expr: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::ReturnExprStmt); - let expr = self.visit_any(ast, data.as_index())?; + let expr = self.visit_any(ast, expr)?; let expr = ast.convert_to_value_expr(expr); ast.datas[idx] = Data::index(expr); @@ -980,9 +958,14 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { Ok(PlaceOrValue::Value(idx)) } - fn visit_assign(&mut self, ast: &'a mut Ast, idx: Index) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::Assign); - let (dst, src) = data.as_two_indices(); + fn visit_assign_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + lhs: Index, + rhs: Index, + ) -> Result { + let (dst, src) = (lhs, rhs); let dst = self.visit_any(ast, dst)?; let src = self.visit_any(ast, src)?; @@ -995,10 +978,13 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { Ok(PlaceOrValue::Value(idx)) } - fn visit_if_expr(&mut self, ast: &'a mut Ast, idx: Index) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::IfExpr); - let (cond, body) = data.as_two_indices(); - + fn visit_if_expr_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + cond: Index, + body: Index, + ) -> Result { let cond = self.visit_any(ast, cond)?; let body = self.visit_any(ast, body)?; @@ -1009,15 +995,16 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { Ok(body.with_index(idx)) } - fn visit_if_else_expr( + fn visit_if_else_expr_impl( &mut self, ast: &'a mut Ast, idx: Index, + cond: Index, + a: Index, + b: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::IfElseExpr); - let (cond, extra) = data.as_index_and_extra_offset(); - let bodies = unsafe { Index::from_slice_unchecked(&ast.extra[extra..][..2]) }; - let &[a, b] = bodies else { unreachable!() }; + let (_, data) = ast.get_node_tag_and_data(idx); + let (_, extra) = data.as_index_and_extra_offset(); let cond = self.visit_any(ast, cond)?; let cond = ast.convert_to_value_expr(cond); @@ -1025,6 +1012,7 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { let a = self.visit_any(ast, a)?; let b = self.visit_any(ast, b)?; + // if placeness differs between branches, convert both to values. let bodies = if !a.eq_discriminant(&b) { [ast.convert_to_value_expr(a), ast.convert_to_value_expr(b)] } else { @@ -1038,51 +1026,52 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { Ok(a.with_index(idx)) } - fn visit_call_expr( + fn visit_call_expr_impl( &mut self, ast: &'a mut Ast, idx: Index, + func: Index, + argument_list: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::CallExpr); - let (func, arguments) = data.as_two_indices(); let func = self.visit_any(ast, func)?; let func = ast.convert_to_value_expr(func); - let arguments = self.visit_argument_list(ast, arguments)?; + let arguments = self.visit_argument_list(ast, argument_list)?; ast.datas[idx] = Data::two_indices(func, arguments.into_index()); Ok(PlaceOrValue::Value(idx)) } - fn visit_argument_list( + fn visit_argument_list_impl( &mut self, ast: &'a mut Ast, idx: Index, + arguments: Vec, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::ArgumentList); - let (a, b) = data.as_extra_range(); - - let children = unsafe { Index::from_slice_unchecked(&ast.extra[a..b]) }.to_vec(); - - for child in children { - self.visit_any_argument(ast, child)?; + for child in arguments { + self.visit_argument(ast, child)?; } Ok(PlaceOrValue::Value(idx)) } - fn visit_argument(&mut self, ast: &'a mut Ast, idx: Index) -> Result { - self.value_index(ast, idx) - } - - fn visit_explicit_cast_expr( + fn visit_argument_impl( &mut self, ast: &'a mut Ast, idx: Index, + expr: Index, + name: Option, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, Tag::ExplicitCast); - let (lhs, ty) = data.as_two_indices(); + self.value_index(ast, idx) + } + fn visit_explicit_cast_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + lhs: Index, + ty: Index, + ) -> Result { let lhs = self.visit_any(ast, lhs)?; let lhs = ast.convert_to_value_expr(lhs); @@ -1101,18 +1090,18 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { } Tag::GlobalDecl => self.visit_global_decl(ast, idx)?, Tag::DeclRef => self.visit_decl_ref(ast, idx)?, - Tag::Deref => self.visit_deref_expr(ast, idx)?, - Tag::AddressOf => self.visit_address_of_expr(ast, idx)?, + Tag::Deref => self.visit_deref(ast, idx)?, + Tag::AddressOf => self.visit_address_of(ast, idx)?, Tag::SubscriptExpr => self.visit_subscript_expr(ast, idx)?, Tag::FunctionDecl => self.visit_function_decl(ast, idx)?, - Tag::Block => self.visit_block(ast, idx)?, - Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx)?, + Tag::BlockTrailingExpr | Tag::Block => self.visit_block(ast, idx)?, Tag::ExprStmt | Tag::Constant | Tag::ReturnStmt => PlaceOrValue::Value(idx), - Tag::ReturnExprStmt => self.visit_return_expr(ast, idx)?, + Tag::ReturnExprStmt => self.visit_return_expr_stmt(ast, idx)?, Tag::ArgumentList => self.visit_argument_list(ast, idx)?, - Tag::ExplicitCast => self.visit_explicit_cast_expr(ast, idx)?, + Tag::ExplicitCast => self.visit_explicit_cast(ast, idx)?, Tag::CallExpr => self.visit_call_expr(ast, idx)?, - Tag::Argument | Tag::Not | Tag::Negate => self.value_index(ast, idx)?, + Tag::NamedArgument | Tag::Argument => self.visit_argument(ast, idx)?, + Tag::Not | Tag::Negate => self.value_index(ast, idx)?, Tag::Or | Tag::And | Tag::BitOr @@ -1139,7 +1128,6 @@ impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { Tag::FieldAccess => todo!(), Tag::PlaceToValueConversion => todo!(), Tag::ValueToPlaceConversion => todo!(), - Tag::NamedArgument => todo!(), Tag::StructDecl => todo!(), Tag::FieldDecl => todo!(), Tag::TypeDeclRef => todo!(), @@ -1199,7 +1187,6 @@ impl PlacenessSolver { ast: &'a mut super::Ast, idx: Index, ) -> Result { - // self.visit_children(ast, idx)?; match ast.tags[idx] { Tag::BlockTrailingExpr => { let (a, b) = ast.datas[idx].as_extra_range(); diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index ef08414..dde901a 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -18,6 +18,7 @@ pub mod intern; pub mod ir; pub mod parser; pub mod tag; +pub mod typecheck; pub mod visitor; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] diff --git a/src/ast2/tag.rs b/src/ast2/tag.rs index 7e5a454..1b3091d 100644 --- a/src/ast2/tag.rs +++ b/src/ast2/tag.rs @@ -328,8 +328,8 @@ impl AstNodeExt for Ast { AstNode::Assign { lhs, rhs } } Tag::SubscriptExpr => { - let (lhs, rhs) = data.as_two_indices(); - AstNode::SubscriptExpr { lhs, rhs } + let (lhs, index) = data.as_two_indices(); + AstNode::SubscriptExpr { lhs, index } } Tag::IfExpr => { let (cond, body) = data.as_two_indices(); @@ -609,7 +609,7 @@ pub enum AstNode { }, SubscriptExpr { lhs: Index, - rhs: Index, + index: Index, }, IfExpr { cond: Index, diff --git a/src/ast2/typecheck.rs b/src/ast2/typecheck.rs new file mode 100644 index 0000000..b921db9 --- /dev/null +++ b/src/ast2/typecheck.rs @@ -0,0 +1,330 @@ +use crate::variant; + +use super::{ + intern::{self}, + tag::{AstNode, AstNodeExt}, + visitor::{AstExt, AstVisitorTrait}, + Ast, Data, Index, Tag, +}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum ErrorKind { + MismatchingTypes, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct Error { + idx: Index, + kind: ErrorKind, +} + +struct TypeChecker<'a> { + ip: &'a mut intern::InternPool, + errors: Vec, +} + +impl<'a> TypeChecker<'a> { + fn visit_children<'b>( + &mut self, + ast: &'b mut super::Ast, + idx: Index, + ) -> Result, ()> { + for child in ast.get_node_children(idx) { + self.visit_any(ast, child)?; + } + + Ok(None) + } +} + +// TODO: actually handle errors here instead of aborting. +impl<'a> AstVisitorTrait<&'a mut Ast> for TypeChecker<'_> { + type Error = (); + + type Value = Option; + + const UNIMPL: Self::Error = (); + + fn visit_parameter_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + ty: Index, + name: intern::Index, + ) -> Result { + _ = (idx, name); + self.visit_any(ast, ty) + } + + fn visit_array_type_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + length: Index, + pointer: Index, + ) -> Result { + _ = self.visit_any(ast, length)?; + let pointee = self.visit_any(ast, pointer)?.expect("no type?"); + + variant!(self.ip.get_key(pointee) => intern::Key::PointerType { pointee, flags }); + + // get interened value from constant node + let length = { + let value = ast.datas[length].as_index_intern().1; + + match self.ip.get_key(value) { + intern::Key::SIntSmall { bits } => bits as u32, + intern::Key::UIntSmall { bits } => bits as u32, + intern::Key::SInt64 { bits } => bits as u32, + intern::Key::UInt64 { bits } => bits as u32, + intern::Key::NegativeInt { bigint } | intern::Key::PositiveInt { bigint } => { + bigint.iter_u32_digits().next().unwrap_or(0) + } + _ => 0, + } + }; + + let ty = self.ip.get_array_type(pointee, Some(flags), length); + ast.tags[idx] = Tag::InternedType; + ast.datas[idx] = Data::intern(ty); + + Ok(Some(ty)) + } + + fn visit_pointer_type_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + ty: Index, + flags: intern::PointerFlags, + ) -> Result { + let pointee = self.visit_any(ast, ty)?.expect("no type?"); + + let ty = self.ip.get_pointer_type(pointee, Some(flags)); + + ast.tags[idx] = Tag::InternedType; + ast.datas[idx] = Data::intern(ty); + + Ok(Some(ty)) + } + + fn visit_type_decl_ref_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + decl: Index, + ) -> Result { + let ty = self.visit_any(ast, decl)?.expect("no type?"); + + ast.tags[idx] = Tag::InternedType; + ast.datas[idx] = Data::intern(ty); + + Ok(Some(ty)) + } + + fn visit_function_proto_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + name: intern::Index, + return_type: Index, + parameter_list: Index, + ) -> Result { + variant!(ast.get_ast_node(parameter_list) => AstNode::ParameterList { params }); + + let return_type = self.visit_any(ast, return_type)?.expect("no type?"); + + let params = params + .into_iter() + .map(|param| self.visit_parameter(ast, param).map(|a| a.unwrap())) + .collect::, _>>()?; + + let ty = self.ip.get_function_type(return_type, params); + + ast.tags[idx] = Tag::FunctionProtoInterned; + ast.datas[idx] = Data::two_interns(name, ty); + + Ok(Some(ty)) + } + + fn visit_function_proto_interned_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + name: intern::Index, + ty: intern::Index, + ) -> Result { + Ok(Some(ty)) + } + + fn visit_struct_decl_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + name: intern::Index, + flags: intern::StructFlags, + field_names: Vec, + field_types: Vec, + ) -> Result { + let types = field_types + .into_iter() + .map(|i| self.visit_any(ast, i).map(Option::unwrap)) + .collect::, _>>()?; + + let ty = self.ip.insert_or_replace_struct_type( + name, + idx, + flags.packed, + flags.c_like, + field_names.into_iter().zip(types), + ); + + ast.tags[idx] = Tag::StructDeclInterned; + ast.datas[idx] = Data::two_interns(name, ty); + + Ok(Some(ty)) + } + + fn visit_function_decl_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + proto: Index, + body: Index, + ) -> Result { + let ty = self.visit_any(ast, proto)?.expect("no type?"); + let body = self.visit_block(ast, body)?.unwrap_or(intern::Index::VOID); + + let ret_ty = self.ip.try_get_return_type(ty).expect("no type?"); + + if body != ret_ty { + self.errors.push(Error { + idx, + kind: ErrorKind::MismatchingTypes, + }); + Ok(Some(intern::Index::VOID)) + } else { + Ok(Some(ty)) + } + } + + fn visit_block_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + statements: Vec, + expr: Option, + ) -> Result { + for stmt in statements { + self.visit_any(ast, stmt)?; + } + + expr.map(|expr| self.visit_any(ast, expr)) + .transpose() + .map(Option::flatten) + } + + fn visit_file_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + decls: Vec, + ) -> Result { + for decl in decls { + self.visit_any(ast, decl)?; + } + + Ok(None) + } + + fn visit_struct_decl_interned_impl( + &mut self, + ast: &'a mut Ast, + idx: Index, + name: intern::Index, + ty: intern::Index, + ) -> Result { + Ok(Some(ty)) + } + + fn visit_any( + &mut self, + ast: &'a mut Ast, + idx: super::Index, + ) -> Result { + let (tag, data) = ast.get_node_tag_and_data(idx); + + let _ty = match tag { + Tag::Root => unreachable!(), + Tag::InternedType => Some(data.as_intern()), + Tag::File => self.visit_children(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)?, + Tag::FunctionProtoInterned => self.visit_function_proto_interned(ast, idx)?, + 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::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::ReturnExprStmt => todo!(), + Tag::VarDecl => todo!(), + Tag::MutVarDecl => todo!(), + Tag::VarDeclAssignment => todo!(), + Tag::MutVarDeclAssignment => todo!(), + Tag::GlobalDecl => todo!(), + Tag::FieldDecl => todo!(), + Tag::DeclRef => todo!(), + Tag::DeclRefUnresolved => todo!(), + Tag::TypeDeclRefUnresolved => todo!(), + Tag::CallExpr => todo!(), + Tag::FieldAccess => todo!(), + 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::Error => todo!(), + Tag::Undefined => todo!(), + }; + + todo!() + } +} diff --git a/src/ast2/visitor.rs b/src/ast2/visitor.rs index 3e048b1..20b5279 100644 --- a/src/ast2/visitor.rs +++ b/src/ast2/visitor.rs @@ -279,314 +279,347 @@ pub trait AstVisitorTrait { type Value; const UNIMPL: Self::Error; - fn visit_function_decl(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_parameter(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_parameter_list(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_block(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_block_trailing_expr( - &mut self, - ast: Ast, - idx: Index, - ) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_block_maybe_trailing( - &mut self, - ast: Ast, - idx: Index, - ) -> Result { - match ast.get_node_tag_and_data(idx).0 { - Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx), - Tag::Block => self.visit_block(ast, idx), - _ => unreachable!(), - } - } - fn visit_function_proto(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_call_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_add_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_sub_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_mul_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_div_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_rem_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_eq_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_neq_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_lt_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_gt_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_le_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_ge_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_shl_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_shr_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_bitor_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_bitxor_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_bitand_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_or_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_and_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_not_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_negate_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_deref_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_address_of_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_explicit_cast_expr( - &mut self, - ast: Ast, - idx: Index, - ) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_assign(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_subscript_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_if_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_if_else_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_argument(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - - fn visit_any_argument(&mut self, ast: Ast, idx: Index) -> Result { - match ast.get_node_tag_and_data(idx).0 { - Tag::Argument => self.visit_argument(ast, idx), - Tag::NamedArgument => self.visit_named_argument(ast, idx), - _ => unreachable!(), - } - } - - fn visit_named_argument(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - - fn visit_argument_list(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - - fn visit_constant(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - - fn visit_return(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_return_expr(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_global_decl(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_var_decl(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_mut_var_decl(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_var_assign_decl(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_mut_var_assign_decl( - &mut self, - ast: Ast, - idx: Index, - ) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_decl_ref(&mut self, ast: Ast, idx: Index) -> Result { - _ = (ast, idx); - Err(Self::UNIMPL) - } - fn visit_value_to_place_conversion( - &mut self, - ast: Ast, - idx: Index, - ) -> Result { - let idx = ast - .get_node_data_for_tag(idx, Tag::ValueToPlaceConversion) - .unwrap() - .as_index(); - self.visit_any(ast, idx) - } - fn visit_place_to_value_conversion( - &mut self, - ast: Ast, - idx: Index, - ) -> Result { - let idx = ast - .get_node_data_for_tag(idx, Tag::PlaceToValueConversion) - .unwrap() - .as_index(); - self.visit_any(ast, idx) - } + tag_visit_fn!( + File { + decls: Vec, + }, + FunctionProto { + name: Interned, + return_type: Index, + parameter_list: Index, + }, + FunctionProtoInterned { + name: Interned, + ty: Interned, + }, + FunctionDecl { + proto: Index, + body: Index, + }, + ParameterList { + params: Vec, + }, + Parameter { + ty: Index, + name: Interned, + }, + Block { + statements: Vec, + expr: Option, + }, + Constant { + ty: Index, + value: Interned, + }, + ExprStmt { + expr: Index, + }, + ReturnStmt {}, + ReturnExprStmt { + expr: Index, + }, + VarDecl { + name: Interned, + ty: Index, + }, + MutVarDecl { + name: Interned, + ty: Index, + }, + VarDeclAssignment { + name: Interned, + expr: Index, + ty: Option, + }, + MutVarDeclAssignment { + name: Interned, + expr: Index, + ty: Option, + }, + GlobalDecl { + name: Interned, + expr: Index, + ty: Index, + }, + StructDecl { + name: Interned, + flags: StructFlags, + field_names: Vec, + field_types: Vec, + }, + StructDeclInterned { + name: Interned, + ty: Interned, + }, + FieldDecl { + name: Interned, + ty: Index, + }, + DeclRef { + decl: Index, + }, + DeclRefUnresolved { + scope: Index, + name: Interned, + }, + InternedType { + intern: Interned, + }, + TypeDeclRef { + decl: Index, + }, + TypeDeclRefUnresolved { + scope: Index, + name: Interned, + }, + PointerType { + ty: Index, + flags: PointerFlags, + }, + ArrayType { + length: Index, + pointer: Index, + }, + CallExpr { + func: Index, + argument_list: Index, + }, + FieldAccess { + field_name: Interned, + expr: Index, + }, + ArgumentList { + arguments: Vec, + }, + Argument { + expr: Index, + name: Option, + }, + ExplicitCast { + expr: Index, + ty: Index, + }, + Deref { + expr: Index, + }, + AddressOf { + expr: Index, + }, + Not { + expr: Index, + }, + Negate { + expr: Index, + }, + PlaceToValueConversion { + expr: Index, + }, + ValueToPlaceConversion { + expr: Index, + }, + Or { + lhs: Index, + rhs: Index, + }, + And { + lhs: Index, + rhs: Index, + }, + BitOr { + lhs: Index, + rhs: Index, + }, + BitXOr { + lhs: Index, + rhs: Index, + }, + BitAnd { + lhs: Index, + rhs: Index, + }, + Eq { + lhs: Index, + rhs: Index, + }, + NEq { + lhs: Index, + rhs: Index, + }, + Lt { + lhs: Index, + rhs: Index, + }, + Gt { + lhs: Index, + rhs: Index, + }, + Le { + lhs: Index, + rhs: Index, + }, + Ge { + lhs: Index, + rhs: Index, + }, + Shl { + lhs: Index, + rhs: Index, + }, + Shr { + lhs: Index, + rhs: Index, + }, + Add { + lhs: Index, + rhs: Index, + }, + Sub { + lhs: Index, + rhs: Index, + }, + Mul { + lhs: Index, + rhs: Index, + }, + Div { + lhs: Index, + rhs: Index, + }, + Rem { + lhs: Index, + rhs: Index, + }, + Assign { + lhs: Index, + rhs: Index, + }, + SubscriptExpr { + lhs: Index, + index: Index, + }, + IfExpr { + cond: Index, + body: Index, + }, + IfElseExpr { + cond: Index, + a: Index, + b: Index, + }, + Error { + err: ParseError, + }, + Undefined {}, + ); fn visit_any(&mut self, ast: Ast, idx: Index) -> Result { - match ast.get_node_tag_and_data(idx).0 { - Tag::FunctionProto => self.visit_function_proto(ast, idx), - Tag::FunctionDecl => self.visit_function_decl(ast, idx), - Tag::ParameterList => self.visit_parameter_list(ast, idx), - Tag::Parameter => self.visit_parameter(ast, idx), - Tag::Block => self.visit_block(ast, idx), - Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx), - Tag::Constant => self.visit_constant(ast, idx), - Tag::ExprStmt => todo!(), - Tag::ReturnStmt => self.visit_return(ast, idx), - Tag::ReturnExprStmt => self.visit_return_expr(ast, idx), - Tag::VarDecl => self.visit_var_decl(ast, idx), - Tag::MutVarDecl => self.visit_mut_var_decl(ast, idx), - Tag::VarDeclAssignment => self.visit_var_assign_decl(ast, idx), - Tag::MutVarDeclAssignment => self.visit_mut_var_assign_decl(ast, idx), - Tag::GlobalDecl => self.visit_global_decl(ast, idx), - Tag::StructDecl => todo!(), - Tag::StructDeclInterned => todo!(), - Tag::FunctionProtoInterned => todo!(), - Tag::FieldDecl => todo!(), - Tag::DeclRef => self.visit_decl_ref(ast, idx), - Tag::DeclRefUnresolved => todo!(), - Tag::InternedType => todo!(), - Tag::TypeDeclRef => todo!(), - Tag::TypeDeclRefUnresolved => todo!(), - Tag::PointerType => todo!(), - Tag::ArrayType => todo!(), - Tag::CallExpr => self.visit_call_expr(ast, idx), - Tag::FieldAccess => todo!(), - Tag::ArgumentList => self.visit_argument_list(ast, idx), - Tag::Argument => self.visit_argument(ast, idx), - Tag::NamedArgument => self.visit_named_argument(ast, idx), - Tag::ExplicitCast => self.visit_explicit_cast_expr(ast, idx), - Tag::Deref => self.visit_deref_expr(ast, idx), - Tag::AddressOf => self.visit_add_expr(ast, idx), - Tag::Not => self.visit_not_expr(ast, idx), - Tag::Negate => self.visit_negate_expr(ast, idx), - Tag::Or => self.visit_or_expr(ast, idx), - Tag::And => self.visit_and_expr(ast, idx), - Tag::BitOr => self.visit_bitor_expr(ast, idx), - Tag::BitXOr => self.visit_bitxor_expr(ast, idx), - Tag::BitAnd => self.visit_bitand_expr(ast, idx), - Tag::Eq => self.visit_eq_expr(ast, idx), - Tag::NEq => self.visit_neq_expr(ast, idx), - Tag::Lt => self.visit_lt_expr(ast, idx), - Tag::Gt => self.visit_gt_expr(ast, idx), - Tag::Le => self.visit_le_expr(ast, idx), - Tag::Ge => self.visit_ge_expr(ast, idx), - Tag::Shl => self.visit_shl_expr(ast, idx), - Tag::Shr => self.visit_shr_expr(ast, idx), - Tag::Add => self.visit_add_expr(ast, idx), - Tag::Sub => self.visit_sub_expr(ast, idx), - Tag::Mul => self.visit_mul_expr(ast, idx), - Tag::Div => self.visit_div_expr(ast, idx), - Tag::Rem => self.visit_rem_expr(ast, idx), - 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::PlaceToValueConversion => self.visit_place_to_value_conversion(ast, idx), - Tag::ValueToPlaceConversion => self.visit_value_to_place_conversion(ast, idx), - Tag::Error => todo!(), - Tag::Undefined => todo!(), - Tag::Root => todo!(), - Tag::File => todo!(), + match ast.get_ast_node(idx) { + AstNode::File { decls } => self.visit_file_impl(ast, idx, decls), + AstNode::FunctionProto { + name, + return_type, + parameter_list, + } => self.visit_function_proto_impl(ast, idx, name, return_type, parameter_list), + AstNode::FunctionProtoInterned { name, ty } => { + self.visit_function_proto_interned_impl(ast, idx, name, ty) + } + AstNode::FunctionDecl { proto, body } => { + self.visit_function_decl_impl(ast, idx, proto, body) + } + AstNode::ParameterList { params } => self.visit_parameter_list_impl(ast, idx, params), + AstNode::Parameter { ty, name } => self.visit_parameter_impl(ast, idx, ty, name), + AstNode::Block { statements, expr } => { + self.visit_block_impl(ast, idx, statements, expr) + } + AstNode::Constant { ty, value } => self.visit_constant_impl(ast, idx, ty, value), + AstNode::ExprStmt { expr } => self.visit_expr_stmt_impl(ast, idx, expr), + AstNode::ReturnStmt => self.visit_return_stmt_impl(ast, idx), + AstNode::ReturnExprStmt { expr } => self.visit_return_expr_stmt_impl(ast, idx, expr), + AstNode::VarDecl { name, ty } => self.visit_var_decl_impl(ast, idx, name, ty), + AstNode::MutVarDecl { name, ty } => self.visit_mut_var_decl_impl(ast, idx, name, ty), + AstNode::VarDeclAssignment { name, expr, ty } => { + self.visit_var_decl_assignment_impl(ast, idx, name, expr, ty) + } + AstNode::MutVarDeclAssignment { name, expr, ty } => { + self.visit_mut_var_decl_assignment_impl(ast, idx, name, expr, ty) + } + AstNode::GlobalDecl { name, expr, ty } => { + self.visit_global_decl_impl(ast, idx, name, expr, ty) + } + AstNode::StructDecl { + name, + flags, + field_names, + field_types, + } => self.visit_struct_decl_impl(ast, idx, name, flags, field_names, field_types), + AstNode::StructDeclInterned { name, ty } => { + self.visit_struct_decl_interned_impl(ast, idx, name, ty) + } + AstNode::FieldDecl { name, ty } => self.visit_field_decl_impl(ast, idx, name, ty), + AstNode::DeclRef { decl } => self.visit_decl_ref_impl(ast, idx, decl), + AstNode::DeclRefUnresolved { scope, name } => { + self.visit_decl_ref_unresolved_impl(ast, idx, scope, name) + } + AstNode::InternedType { intern } => self.visit_interned_type_impl(ast, idx, intern), + AstNode::TypeDeclRef { decl } => self.visit_type_decl_ref_impl(ast, idx, decl), + AstNode::TypeDeclRefUnresolved { scope, name } => { + self.visit_type_decl_ref_unresolved_impl(ast, idx, scope, name) + } + AstNode::PointerType { ty, flags } => self.visit_pointer_type_impl(ast, idx, ty, flags), + AstNode::ArrayType { length, pointer } => { + self.visit_array_type_impl(ast, idx, length, pointer) + } + AstNode::CallExpr { + func, + argument_list, + } => self.visit_call_expr_impl(ast, idx, func, argument_list), + AstNode::FieldAccess { field_name, expr } => { + self.visit_field_access_impl(ast, idx, field_name, expr) + } + AstNode::ArgumentList { arguments } => { + self.visit_argument_list_impl(ast, idx, arguments) + } + AstNode::Argument { expr, name } => self.visit_argument_impl(ast, idx, expr, name), + AstNode::ExplicitCast { expr, ty } => self.visit_explicit_cast_impl(ast, idx, expr, ty), + AstNode::Deref { expr } => self.visit_deref_impl(ast, idx, expr), + AstNode::AddressOf { expr } => self.visit_address_of_impl(ast, idx, expr), + AstNode::Not { expr } => self.visit_not_impl(ast, idx, expr), + AstNode::Negate { expr } => self.visit_negate_impl(ast, idx, expr), + AstNode::PlaceToValueConversion { expr } => { + self.visit_place_to_value_conversion_impl(ast, idx, expr) + } + AstNode::ValueToPlaceConversion { expr } => { + self.visit_value_to_place_conversion_impl(ast, idx, expr) + } + AstNode::Or { lhs, rhs } => self.visit_or_impl(ast, idx, lhs, rhs), + AstNode::And { lhs, rhs } => self.visit_and_impl(ast, idx, lhs, rhs), + AstNode::BitOr { lhs, rhs } => self.visit_bit_or_impl(ast, idx, lhs, rhs), + AstNode::BitXOr { lhs, rhs } => self.visit_bit_x_or_impl(ast, idx, lhs, rhs), + AstNode::BitAnd { lhs, rhs } => self.visit_bit_and_impl(ast, idx, lhs, rhs), + AstNode::Eq { lhs, rhs } => self.visit_eq_impl(ast, idx, lhs, rhs), + AstNode::NEq { lhs, rhs } => self.visit_n_eq_impl(ast, idx, lhs, rhs), + AstNode::Lt { lhs, rhs } => self.visit_lt_impl(ast, idx, lhs, rhs), + AstNode::Gt { lhs, rhs } => self.visit_gt_impl(ast, idx, lhs, rhs), + AstNode::Le { lhs, rhs } => self.visit_le_impl(ast, idx, lhs, rhs), + AstNode::Ge { lhs, rhs } => self.visit_ge_impl(ast, idx, lhs, rhs), + AstNode::Shl { lhs, rhs } => self.visit_shl_impl(ast, idx, lhs, rhs), + AstNode::Shr { lhs, rhs } => self.visit_shr_impl(ast, idx, lhs, rhs), + AstNode::Add { lhs, rhs } => self.visit_add_impl(ast, idx, lhs, rhs), + AstNode::Sub { lhs, rhs } => self.visit_sub_impl(ast, idx, lhs, rhs), + AstNode::Mul { lhs, rhs } => self.visit_mul_impl(ast, idx, lhs, rhs), + AstNode::Div { lhs, rhs } => self.visit_div_impl(ast, idx, lhs, rhs), + AstNode::Rem { lhs, rhs } => self.visit_rem_impl(ast, idx, lhs, rhs), + AstNode::Assign { lhs, rhs } => self.visit_assign_impl(ast, idx, lhs, rhs), + AstNode::SubscriptExpr { lhs, index: rhs } => { + self.visit_subscript_expr_impl(ast, idx, lhs, rhs) + } + AstNode::IfExpr { cond, body } => self.visit_if_expr_impl(ast, idx, cond, body), + AstNode::IfElseExpr { cond, a, b } => { + self.visit_if_else_expr_impl(ast, idx, cond, a, b) + } + AstNode::Error { err } => self.visit_error_impl(ast, idx, err), + AstNode::Undefined => self.visit_undefined_impl(ast, idx), + AstNode::Root { .. } => unreachable!(), } } }