From 8b3789d7b0ae3020555afd472166020e1b249f3e Mon Sep 17 00:00:00 2001 From: Janis Date: Thu, 6 Mar 2025 15:41:34 +0100 Subject: [PATCH] placeness solver on ast after parsing --- src/ast2/ir.rs | 474 ++++++++++++++++++++++++++++++++++++++++---- src/ast2/mod.rs | 50 ++++- src/ast2/parser.rs | 10 +- src/ast2/visitor.rs | 4 +- 4 files changed, 480 insertions(+), 58 deletions(-) diff --git a/src/ast2/ir.rs b/src/ast2/ir.rs index 6a3b105..860cf37 100644 --- a/src/ast2/ir.rs +++ b/src/ast2/ir.rs @@ -17,7 +17,7 @@ enum Error { use super::{ intern::InternPoolWrapper as InternPool, visitor::{AstExt, AstVisitorTrait}, - TypeCache, + Ast, Data, PlaceOrValue, Tag, TypeCache, }; struct IrBuilder { @@ -46,7 +46,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: super::Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Block); + let data = ast.expect_node_data_for_tag(idx, Tag::Block); let (a, b) = data.as_extra_range(); ast.extra[a..b] @@ -64,7 +64,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::PlaceToValueConversion); + let data = ast.expect_node_data_for_tag(idx, Tag::PlaceToValueConversion); let expr = data.as_index(); // idx's (this) type is the pointee type @@ -81,7 +81,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::ValueToPlaceConversion); + let data = ast.expect_node_data_for_tag(idx, Tag::ValueToPlaceConversion); let expr = data.as_index(); // expr's type is the pointee type @@ -108,7 +108,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::DeclRef); + 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"); @@ -163,7 +163,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::ReturnExprStmt); + 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); @@ -180,7 +180,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Constant); + 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); @@ -194,7 +194,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::SubscriptExpr); + let data = ast.expect_node_data_for_tag(idx, Tag::SubscriptExpr); let (lhs, index) = data.as_two_indices(); // pointer type @@ -217,7 +217,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::CallExpr); + 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); @@ -239,7 +239,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Argument); + let data = ast.expect_node_data_for_tag(idx, Tag::Argument); let expr = data.as_index(); let arg = self.visit_any(ast, expr)?.unwrap(); @@ -263,7 +263,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::ArgumentList); + let data = ast.expect_node_data_for_tag(idx, Tag::ArgumentList); let (a, b) = data.as_extra_range(); let args = ast.extra[a..b] @@ -292,7 +292,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::BlockTrailingExpr); + let data = ast.expect_node_data_for_tag(idx, Tag::BlockTrailingExpr); let (a, b) = data.as_extra_range(); @@ -312,7 +312,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: super::Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::FunctionProto); + let data = ast.expect_node_data_for_tag(idx, Tag::FunctionProto); let (_, extra) = data.as_intern_and_extra_offset(); let (_return_type, parameter_list) = ( @@ -330,7 +330,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::ParameterList); + let data = ast.expect_node_data_for_tag(idx, Tag::ParameterList); let (a, b) = data.as_extra_range(); ast.extra[a..b] @@ -348,7 +348,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Parameter); + 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); @@ -367,7 +367,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::AddressOf); + 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); @@ -384,7 +384,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Assign); + 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); @@ -403,7 +403,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::ExplicitCast); + 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); @@ -424,7 +424,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::IfExpr); + 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(); @@ -450,7 +450,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::IfElseExpr); + 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); @@ -495,7 +495,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Not); + 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); @@ -510,7 +510,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Not); + 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); @@ -525,7 +525,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Negate); + 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); @@ -542,7 +542,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Or); + 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); @@ -580,7 +580,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> { ast: &'a mut super::Ast, idx: Index, ) -> Result { - let data = ast.expect_node_data_for_tag(idx, super::Tag::Or); + 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 @@ -734,7 +734,7 @@ impl IrFunctionBuilder<'_> { let _name = range.get(0).unwrap(); let (expr, typed_index) = match tag { - super::Tag::VarDecl | super::Tag::MutVarDecl => { + Tag::VarDecl | Tag::MutVarDecl => { let typed_index = range .get(1) .cloned() @@ -743,7 +743,7 @@ impl IrFunctionBuilder<'_> { .unwrap(); (None, typed_index) } - super::Tag::VarDeclAssignment | super::Tag::MutVarDeclAssignment => { + Tag::VarDeclAssignment | Tag::MutVarDeclAssignment => { let expr = range .get(1) .cloned() @@ -799,24 +799,24 @@ impl IrFunctionBuilder<'_> { let rhs = self.visit_any(ast, rhs)?.unwrap(); let (inst, data) = match tag { - super::Tag::BitOr => (Inst::BitOr(ty), Data::new(lhs, rhs)), - super::Tag::BitXOr => (Inst::BitOr(ty), Data::new(lhs, rhs)), - super::Tag::BitAnd => (Inst::BitOr(ty), Data::new(lhs, rhs)), + Tag::BitOr => (Inst::BitOr(ty), Data::new(lhs, rhs)), + Tag::BitXOr => (Inst::BitOr(ty), Data::new(lhs, rhs)), + Tag::BitAnd => (Inst::BitOr(ty), Data::new(lhs, rhs)), - super::Tag::Eq => (Inst::Eq(ty), Data::new(lhs, rhs)), - super::Tag::NEq => (Inst::Neq(ty), Data::new(lhs, rhs)), - super::Tag::Lt => (Inst::Lt(ty), Data::new(lhs, rhs)), - super::Tag::Gt => (Inst::Gt(ty), Data::new(lhs, rhs)), - super::Tag::Le => (Inst::Le(ty), Data::new(lhs, rhs)), - super::Tag::Ge => (Inst::Ge(ty), Data::new(lhs, rhs)), + Tag::Eq => (Inst::Eq(ty), Data::new(lhs, rhs)), + Tag::NEq => (Inst::Neq(ty), Data::new(lhs, rhs)), + Tag::Lt => (Inst::Lt(ty), Data::new(lhs, rhs)), + Tag::Gt => (Inst::Gt(ty), Data::new(lhs, rhs)), + Tag::Le => (Inst::Le(ty), Data::new(lhs, rhs)), + Tag::Ge => (Inst::Ge(ty), Data::new(lhs, rhs)), - super::Tag::Shl => (Inst::ShiftLeft(ty), Data::new(lhs, rhs)), - super::Tag::Shr => (Inst::ShiftRight(ty), Data::new(lhs, rhs)), - super::Tag::Add => (Inst::Add(ty), Data::new(lhs, rhs)), - super::Tag::Sub => (Inst::Sub(ty), Data::new(lhs, rhs)), - super::Tag::Div => (Inst::Div(ty), Data::new(lhs, rhs)), - super::Tag::Rem => (Inst::Rem(ty), Data::new(lhs, rhs)), - super::Tag::Mul => (Inst::Mul(ty), Data::new(lhs, rhs)), + Tag::Shl => (Inst::ShiftLeft(ty), Data::new(lhs, rhs)), + Tag::Shr => (Inst::ShiftRight(ty), Data::new(lhs, rhs)), + Tag::Add => (Inst::Add(ty), Data::new(lhs, rhs)), + Tag::Sub => (Inst::Sub(ty), Data::new(lhs, rhs)), + Tag::Div => (Inst::Div(ty), Data::new(lhs, rhs)), + Tag::Rem => (Inst::Rem(ty), Data::new(lhs, rhs)), + Tag::Mul => (Inst::Mul(ty), Data::new(lhs, rhs)), _ => panic!("not a binop"), }; @@ -834,7 +834,7 @@ impl<'a> AstVisitorTrait<&'a mut super::Ast> for IrBuilder { ast: &'a mut super::Ast, idx: super::Index, ) -> Result<(), Self::Error> { - let data = ast.expect_node_data_for_tag(idx, super::Tag::FunctionDecl); + let data = ast.expect_node_data_for_tag(idx, Tag::FunctionDecl); let (proto, block) = data.as_two_indices(); // visit proto @@ -844,3 +844,389 @@ impl<'a> AstVisitorTrait<&'a mut super::Ast> for IrBuilder { todo!() } } + +pub struct PlacenessSolver; + +impl<'a> AstVisitorTrait<&'a mut Ast> for PlacenessSolver { + type Error = (); + + type Value = PlaceOrValue; + + const UNIMPL: Self::Error = (); + + fn visit_subscript_expr( + &mut self, + ast: &'a mut Ast, + idx: 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)?; + + let lhs = ast.convert_to_value_expr(lhs); + let index = ast.convert_to_value_expr(index); + + ast.datas[idx] = Data::two_indices(lhs, index); + + Ok(PlaceOrValue::Place(idx)) + } + + fn visit_deref_expr( + &mut self, + ast: &'a mut Ast, + idx: Index, + ) -> Result { + let data = ast.expect_node_data_for_tag(idx, Tag::Deref); + + let expr = self.visit_any(ast, data.as_index())?; + let expr = ast.convert_to_value_expr(expr); + + ast.datas[idx] = Data::index(expr); + + Ok(PlaceOrValue::Place(idx)) + } + + fn visit_parameter( + &mut self, + ast: &'a mut Ast, + idx: Index, + ) -> Result { + Ok(PlaceOrValue::Value(idx)) + } + + fn visit_var_decl(&mut self, ast: &'a mut Ast, idx: Index) -> Result { + Ok(PlaceOrValue::Place(idx)) + } + + fn visit_global_decl( + &mut self, + ast: &'a mut Ast, + idx: Index, + ) -> Result { + Ok(PlaceOrValue::Place(idx)) + } + + fn visit_address_of_expr( + &mut self, + ast: &'a mut Ast, + idx: 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())?; + + // copy the placeness of the decl referenced. + // parameters are values, var decls are places + Ok(decl.with_index(idx)) + } + + fn visit_function_decl( + &mut self, + ast: &'a mut Ast, + idx: 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( + &mut self, + ast: &'a mut Ast, + idx: Index, + ) -> 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)?; + } + + // copy placeness of trailing expression + Ok(self.visit_any(ast, *expr)?.with_index(idx)) + } + + fn visit_return_expr( + &mut self, + ast: &'a mut Ast, + idx: Index, + ) -> Result { + let data = ast.expect_node_data_for_tag(idx, Tag::ReturnExprStmt); + let expr = self.visit_any(ast, data.as_index())?; + let expr = ast.convert_to_value_expr(expr); + + ast.datas[idx] = Data::index(expr); + + 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(); + + let dst = self.visit_any(ast, dst)?; + let src = self.visit_any(ast, src)?; + + let dst = ast.convert_to_place_expr(dst); + let src = ast.convert_to_value_expr(src); + + ast.datas[idx] = Data::two_indices(dst, src); + + 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(); + + let cond = self.visit_any(ast, cond)?; + let body = self.visit_any(ast, body)?; + + let cond = ast.convert_to_value_expr(cond); + + ast.datas[idx] = Data::two_indices(cond, body.into_index()); + + Ok(body.with_index(idx)) + } + + fn visit_if_else_expr( + &mut self, + ast: &'a mut Ast, + idx: 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 a = self.visit_any(ast, a)?; + let b = self.visit_any(ast, b)?; + + let bodies = if !a.eq_discriminant(&b) { + [ast.convert_to_value_expr(a), ast.convert_to_value_expr(b)] + } else { + [a.into_index(), b.into_index()] + } + .map(|a| a.as_u32()); + + ast.extra[extra..][..2].copy_from_slice(&bodies); + + Ok(a.with_index(idx)) + } + + fn visit_call_expr( + &mut self, + ast: &'a mut Ast, + idx: 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)?; + + ast.datas[idx] = Data::two_indices(func, arguments); + + Ok(PlaceOrValue::Value(idx)) + } + + fn visit_argument_list( + &mut self, + ast: &'a mut Ast, + idx: Index, + ) -> 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)?; + } + + 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( + &mut self, + ast: &'a mut Ast, + idx: Index, + ) -> Result { + let data = ast.expect_node_data_for_tag(idx, Tag::ExplicitCast); + let (lhs, ty) = data.as_two_indices(); + + let lhs = self.visit_any(ast, lhs)?; + let lhs = ast.convert_to_value_expr(lhs); + + ast.datas[idx] = Data::two_indices(lhs, ty); + + Ok(PlaceOrValue::Value(idx)) + } + + fn visit_any(&mut self, ast: &'a mut Ast, idx: Index) -> Result { + let tag = ast.tags[idx]; + match tag { + Tag::Parameter => self.visit_parameter(ast, idx)?, + Tag::VarDecl | Tag::MutVarDecl | Tag::VarDeclAssignment | Tag::MutVarDeclAssignment => { + self.visit_var_decl_common(ast, idx)? + } + 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::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::ExprStmt | Tag::Constant | Tag::ReturnStmt => PlaceOrValue::Value(idx), + Tag::ReturnExprStmt => self.visit_return_expr(ast, idx)?, + Tag::ArgumentList => self.visit_argument_list(ast, idx)?, + Tag::ExplicitCast => self.visit_explicit_cast_expr(ast, idx)?, + Tag::CallExpr => self.visit_call_expr(ast, idx)?, + Tag::Argument | Tag::Not | Tag::Negate => self.value_index(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 => self.value_two_indices(ast, idx)?, + Tag::Assign => self.visit_assign(ast, idx)?, + Tag::IfExpr => self.visit_if_expr(ast, idx)?, + Tag::IfElseExpr => self.visit_if_else_expr(ast, idx)?, + Tag::File | Tag::Root => self.visit_children(ast, idx)?, + + Tag::FieldAccess => todo!(), + Tag::PlaceToValueConversion => todo!(), + Tag::ValueToPlaceConversion => todo!(), + Tag::NamedArgument => todo!(), + Tag::StructDecl => todo!(), + Tag::FieldDecl => todo!(), + Tag::TypeDeclRef => todo!(), + + Tag::DeclRefUnresolved => todo!(), + Tag::InternedType => todo!(), + Tag::TypeDeclRefUnresolved => todo!(), + Tag::PointerType => todo!(), + Tag::ArrayType => todo!(), + Tag::Error => todo!(), + Tag::Undefined => todo!(), + }; + //_ => Err(())?, + + Ok(todo!()) + } +} + +impl PlacenessSolver { + fn value_two_indices<'a>( + &mut self, + ast: &'a mut super::Ast, + idx: Index, + ) -> Result { + let (a, b) = ast.datas[idx].as_two_indices(); + + let a = self.visit_any(ast, a)?; + let b = self.visit_any(ast, b)?; + + let a = ast.convert_to_value_expr(a); + let b = ast.convert_to_value_expr(b); + + ast.datas[idx] = Data::two_indices(a, b); + + Ok(PlaceOrValue::Value(idx)) + } + + fn value_index<'a>(&mut self, ast: &'a mut super::Ast, idx: Index) -> Result { + let a = ast.datas[idx].as_index(); + + let a = self.visit_any(ast, a)?; + + let a = ast.convert_to_value_expr(a); + + ast.datas[idx] = Data::index(a); + + Ok(PlaceOrValue::Value(idx)) + } + + /// this ensures the trailing expression of a block is a value-expression + fn visit_block_maybe_trailing_as_value<'a>( + &mut self, + 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(); + 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)?; + } + + let expr = self.visit_any(ast, *expr)?; + ast.extra[b - 1] = ast.convert_to_value_expr(expr).into_u32(); + } + Tag::Block => { + self.visit_block(ast, idx)?; + } + _ => unreachable!(), + }; + + Ok(PlaceOrValue::Value(idx)) + } + + fn visit_var_decl_common<'a>( + &mut self, + ast: &'a mut super::Ast, + idx: Index, + ) -> Result { + self.visit_children(ast, idx)?; + Ok(PlaceOrValue::Place(idx)) + } + + fn visit_children<'a>( + &mut self, + ast: &'a mut super::Ast, + idx: Index, + ) -> Result { + for child in ast.get_node_children(idx) { + self.visit_any(ast, child)?; + } + + Ok(PlaceOrValue::Value(idx)) + } +} diff --git a/src/ast2/mod.rs b/src/ast2/mod.rs index 4284bae..791d987 100644 --- a/src/ast2/mod.rs +++ b/src/ast2/mod.rs @@ -522,6 +522,24 @@ impl PlaceOrValue { PlaceOrValue::Place(_) => Self::Place(index), } } + fn map_value(self, f: F) -> Self + where + F: FnOnce(Index) -> Self, + { + match self { + PlaceOrValue::Value(index) => f(index), + _ => self, + } + } + fn map_place(self, f: F) -> Self + where + F: FnOnce(Index) -> Self, + { + match self { + PlaceOrValue::Place(index) => f(index), + _ => self, + } + } } impl From for PlaceOrValue { @@ -592,6 +610,14 @@ mod index { inner.map(Self) } + + pub fn from_slice(slice: &[u32]) -> &[Option] { + unsafe { core::mem::transmute(slice) } + } + pub unsafe fn from_slice_unchecked(slice: &[u32]) -> &[Self] { + unsafe { core::mem::transmute(slice) } + } + pub fn kind(&self) -> Kind { Kind::try_from(((self.0.get() >> 28) & 0b1111) as u8).unwrap() } @@ -1025,21 +1051,37 @@ impl Ast { } /// converts from a place expression to a value expression. - fn push_place_to_value_conversion(&mut self, index: Index) -> Index { + fn push_place_to_value_conversion(&mut self, index: Index) -> PlaceOrValue { let loc = self.get_loc(index); let i = self.reserve_node_other(); self.set_tag_data_source_loc(i, Tag::PlaceToValueConversion, Data::index(index), loc); - i + PlaceOrValue::Value(i) } /// converts from a value expression to a place expression. - fn push_value_to_place_conversion(&mut self, index: Index) -> Index { + fn push_value_to_place_conversion(&mut self, index: Index) -> PlaceOrValue { let loc = self.get_loc(index); let i = self.reserve_node_other(); self.set_tag_data_source_loc(i, Tag::ValueToPlaceConversion, Data::index(index), loc); - i + PlaceOrValue::Place(i) + } + + /// converts the expression to a value expression, if it isn't one already. + fn convert_to_value_expr(&mut self, lrvalue: PlaceOrValue) -> Index { + match lrvalue { + PlaceOrValue::Value(index) => index, + PlaceOrValue::Place(index) => self.push_place_to_value_conversion(index).into_index(), + } + } + + /// converts the expression to a place expression, if it isn't one already. + fn convert_to_place_expr(&mut self, lrvalue: PlaceOrValue) -> Index { + match lrvalue { + PlaceOrValue::Place(index) => index, + PlaceOrValue::Value(index) => self.push_value_to_place_conversion(index).into_index(), + } } fn push_binary(&mut self, tag: Tag, lhs: Index, rhs: Index, loc: SourceLocation) -> Index { diff --git a/src/ast2/parser.rs b/src/ast2/parser.rs index 1a68792..c7bdde7 100644 --- a/src/ast2/parser.rs +++ b/src/ast2/parser.rs @@ -1167,18 +1167,12 @@ impl Parser { /// converts the expression to a value expression, if it isn't one already. fn convert_to_value_expr(&mut self, lrvalue: PlaceOrValue) -> Index { - match lrvalue { - PlaceOrValue::Value(index) => index, - PlaceOrValue::Place(index) => self.ast.push_place_to_value_conversion(index), - } + self.ast.convert_to_value_expr(lrvalue) } /// converts the expression to a place expression, if it isn't one already. fn convert_to_place_expr(&mut self, lrvalue: PlaceOrValue) -> Index { - match lrvalue { - PlaceOrValue::Place(index) => index, - PlaceOrValue::Value(index) => self.ast.push_value_to_place_conversion(index), - } + self.ast.convert_to_place_expr(lrvalue) } /// PREFIX_EXPR <- diff --git a/src/ast2/visitor.rs b/src/ast2/visitor.rs index d536139..1f760f0 100644 --- a/src/ast2/visitor.rs +++ b/src/ast2/visitor.rs @@ -287,8 +287,8 @@ pub trait AstVisitorTrait { idx: Index, ) -> Result { match ast.get_node_tag_and_data(idx).0 { - Tag::BlockTrailingExpr => self.visit_block(ast, idx), - Tag::Block => self.visit_block_trailing_expr(ast, idx), + Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx), + Tag::Block => self.visit_block(ast, idx), _ => unreachable!(), } }