placeness solver on ast after parsing

This commit is contained in:
Janis 2025-03-06 15:41:34 +01:00
parent d6450b5f32
commit 8b3789d7b0
4 changed files with 480 additions and 58 deletions

View file

@ -17,7 +17,7 @@ enum Error {
use super::{ use super::{
intern::InternPoolWrapper as InternPool, intern::InternPoolWrapper as InternPool,
visitor::{AstExt, AstVisitorTrait}, visitor::{AstExt, AstVisitorTrait},
TypeCache, Ast, Data, PlaceOrValue, Tag, TypeCache,
}; };
struct IrBuilder { struct IrBuilder {
@ -46,7 +46,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> {
ast: &'a mut super::Ast, ast: &'a mut super::Ast,
idx: super::Index, idx: super::Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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(); let (a, b) = data.as_extra_range();
ast.extra[a..b] ast.extra[a..b]
@ -64,7 +64,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> {
ast: &'a mut super::Ast, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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(); let expr = data.as_index();
// idx's (this) type is the pointee type // 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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(); let expr = data.as_index();
// expr's type is the pointee type // 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 decl = data.as_index();
let alloca = self.ref_lookup.get(&decl).cloned().expect("declref"); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 expr = data.as_index();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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, value) = data.as_index_intern();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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(); let (lhs, index) = data.as_two_indices();
// pointer type // pointer type
@ -217,7 +217,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> {
ast: &'a mut super::Ast, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 (func, arguments) = data.as_two_indices();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 expr = data.as_index();
let arg = self.visit_any(ast, expr)?.unwrap(); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 (a, b) = data.as_extra_range();
let args = ast.extra[a..b] 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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(); 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, ast: &'a mut super::Ast,
idx: super::Index, idx: super::Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 (_, extra) = data.as_intern_and_extra_offset();
let (_return_type, parameter_list) = ( 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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(); let (a, b) = data.as_extra_range();
ast.extra[a..b] ast.extra[a..b]
@ -348,7 +348,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> {
ast: &'a mut super::Ast, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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, _name) = data.as_index_intern();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, ty); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 expr = data.as_index();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 (dst, src) = data.as_two_indices();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 (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, lhs);
@ -424,7 +424,7 @@ impl<'b, 'a> AstVisitorTrait<&'a mut super::Ast> for IrFunctionBuilder<'b> {
ast: &'a mut super::Ast, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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, body) = data.as_two_indices();
let cond = self.visit_any(ast, cond)?.unwrap(); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 (cond, extra) = data.as_index_and_extra_offset();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 expr = data.as_index();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 expr = data.as_index();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 expr = data.as_index();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, expr); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 (a, b) = data.as_two_indices();
let ty = ast.get_type_of_node(&self.ip, &mut self.type_cache, idx); 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, ast: &'a mut super::Ast,
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
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 (a, b) = data.as_two_indices();
// TODO: make this an error instead of a panic // TODO: make this an error instead of a panic
@ -734,7 +734,7 @@ impl IrFunctionBuilder<'_> {
let _name = range.get(0).unwrap(); let _name = range.get(0).unwrap();
let (expr, typed_index) = match tag { let (expr, typed_index) = match tag {
super::Tag::VarDecl | super::Tag::MutVarDecl => { Tag::VarDecl | Tag::MutVarDecl => {
let typed_index = range let typed_index = range
.get(1) .get(1)
.cloned() .cloned()
@ -743,7 +743,7 @@ impl IrFunctionBuilder<'_> {
.unwrap(); .unwrap();
(None, typed_index) (None, typed_index)
} }
super::Tag::VarDeclAssignment | super::Tag::MutVarDeclAssignment => { Tag::VarDeclAssignment | Tag::MutVarDeclAssignment => {
let expr = range let expr = range
.get(1) .get(1)
.cloned() .cloned()
@ -799,24 +799,24 @@ impl IrFunctionBuilder<'_> {
let rhs = self.visit_any(ast, rhs)?.unwrap(); let rhs = self.visit_any(ast, rhs)?.unwrap();
let (inst, data) = match tag { let (inst, data) = match tag {
super::Tag::BitOr => (Inst::BitOr(ty), Data::new(lhs, rhs)), Tag::BitOr => (Inst::BitOr(ty), Data::new(lhs, rhs)),
super::Tag::BitXOr => (Inst::BitOr(ty), Data::new(lhs, rhs)), Tag::BitXOr => (Inst::BitOr(ty), Data::new(lhs, rhs)),
super::Tag::BitAnd => (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)), Tag::Eq => (Inst::Eq(ty), Data::new(lhs, rhs)),
super::Tag::NEq => (Inst::Neq(ty), Data::new(lhs, rhs)), Tag::NEq => (Inst::Neq(ty), Data::new(lhs, rhs)),
super::Tag::Lt => (Inst::Lt(ty), Data::new(lhs, rhs)), Tag::Lt => (Inst::Lt(ty), Data::new(lhs, rhs)),
super::Tag::Gt => (Inst::Gt(ty), Data::new(lhs, rhs)), Tag::Gt => (Inst::Gt(ty), Data::new(lhs, rhs)),
super::Tag::Le => (Inst::Le(ty), Data::new(lhs, rhs)), Tag::Le => (Inst::Le(ty), Data::new(lhs, rhs)),
super::Tag::Ge => (Inst::Ge(ty), Data::new(lhs, rhs)), Tag::Ge => (Inst::Ge(ty), Data::new(lhs, rhs)),
super::Tag::Shl => (Inst::ShiftLeft(ty), Data::new(lhs, rhs)), Tag::Shl => (Inst::ShiftLeft(ty), Data::new(lhs, rhs)),
super::Tag::Shr => (Inst::ShiftRight(ty), Data::new(lhs, rhs)), Tag::Shr => (Inst::ShiftRight(ty), Data::new(lhs, rhs)),
super::Tag::Add => (Inst::Add(ty), Data::new(lhs, rhs)), Tag::Add => (Inst::Add(ty), Data::new(lhs, rhs)),
super::Tag::Sub => (Inst::Sub(ty), Data::new(lhs, rhs)), Tag::Sub => (Inst::Sub(ty), Data::new(lhs, rhs)),
super::Tag::Div => (Inst::Div(ty), Data::new(lhs, rhs)), Tag::Div => (Inst::Div(ty), Data::new(lhs, rhs)),
super::Tag::Rem => (Inst::Rem(ty), Data::new(lhs, rhs)), Tag::Rem => (Inst::Rem(ty), Data::new(lhs, rhs)),
super::Tag::Mul => (Inst::Mul(ty), Data::new(lhs, rhs)), Tag::Mul => (Inst::Mul(ty), Data::new(lhs, rhs)),
_ => panic!("not a binop"), _ => panic!("not a binop"),
}; };
@ -834,7 +834,7 @@ impl<'a> AstVisitorTrait<&'a mut super::Ast> for IrBuilder {
ast: &'a mut super::Ast, ast: &'a mut super::Ast,
idx: super::Index, idx: super::Index,
) -> Result<(), Self::Error> { ) -> 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(); let (proto, block) = data.as_two_indices();
// visit proto // visit proto
@ -844,3 +844,389 @@ impl<'a> AstVisitorTrait<&'a mut super::Ast> for IrBuilder {
todo!() 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<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
Ok(PlaceOrValue::Value(idx))
}
fn visit_var_decl(&mut self, ast: &'a mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
Ok(PlaceOrValue::Place(idx))
}
fn visit_global_decl(
&mut self,
ast: &'a mut Ast,
idx: Index,
) -> Result<Self::Value, Self::Error> {
Ok(PlaceOrValue::Place(idx))
}
fn visit_address_of_expr(
&mut self,
ast: &'a mut Ast,
idx: Index,
) -> Result<Self::Value, Self::Error> {
Ok(PlaceOrValue::Value(idx))
}
fn visit_decl_ref(&mut self, ast: &'a mut Ast, idx: Index) -> Result<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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::Value, Self::Error> {
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<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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, Self::Error> {
self.value_index(ast, idx)
}
fn visit_explicit_cast_expr(
&mut self,
ast: &'a mut Ast,
idx: Index,
) -> Result<Self::Value, Self::Error> {
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<Self::Value, Self::Error> {
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<PlaceOrValue, ()> {
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<PlaceOrValue, ()> {
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<PlaceOrValue, ()> {
// 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<PlaceOrValue, ()> {
self.visit_children(ast, idx)?;
Ok(PlaceOrValue::Place(idx))
}
fn visit_children<'a>(
&mut self,
ast: &'a mut super::Ast,
idx: Index,
) -> Result<PlaceOrValue, ()> {
for child in ast.get_node_children(idx) {
self.visit_any(ast, child)?;
}
Ok(PlaceOrValue::Value(idx))
}
}

View file

@ -522,6 +522,24 @@ impl PlaceOrValue {
PlaceOrValue::Place(_) => Self::Place(index), PlaceOrValue::Place(_) => Self::Place(index),
} }
} }
fn map_value<F>(self, f: F) -> Self
where
F: FnOnce(Index) -> Self,
{
match self {
PlaceOrValue::Value(index) => f(index),
_ => self,
}
}
fn map_place<F>(self, f: F) -> Self
where
F: FnOnce(Index) -> Self,
{
match self {
PlaceOrValue::Place(index) => f(index),
_ => self,
}
}
} }
impl From<index::Index> for PlaceOrValue { impl From<index::Index> for PlaceOrValue {
@ -592,6 +610,14 @@ mod index {
inner.map(Self) inner.map(Self)
} }
pub fn from_slice(slice: &[u32]) -> &[Option<Self>] {
unsafe { core::mem::transmute(slice) }
}
pub unsafe fn from_slice_unchecked(slice: &[u32]) -> &[Self] {
unsafe { core::mem::transmute(slice) }
}
pub fn kind(&self) -> Kind { pub fn kind(&self) -> Kind {
Kind::try_from(((self.0.get() >> 28) & 0b1111) as u8).unwrap() 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. /// 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 loc = self.get_loc(index);
let i = self.reserve_node_other(); let i = self.reserve_node_other();
self.set_tag_data_source_loc(i, Tag::PlaceToValueConversion, Data::index(index), loc); 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. /// 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 loc = self.get_loc(index);
let i = self.reserve_node_other(); let i = self.reserve_node_other();
self.set_tag_data_source_loc(i, Tag::ValueToPlaceConversion, Data::index(index), loc); 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 { fn push_binary(&mut self, tag: Tag, lhs: Index, rhs: Index, loc: SourceLocation) -> Index {

View file

@ -1167,18 +1167,12 @@ impl Parser {
/// converts the expression to a value expression, if it isn't one already. /// converts the expression to a value expression, if it isn't one already.
fn convert_to_value_expr(&mut self, lrvalue: PlaceOrValue) -> Index { fn convert_to_value_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
match lrvalue { self.ast.convert_to_value_expr(lrvalue)
PlaceOrValue::Value(index) => index,
PlaceOrValue::Place(index) => self.ast.push_place_to_value_conversion(index),
}
} }
/// converts the expression to a place expression, if it isn't one already. /// converts the expression to a place expression, if it isn't one already.
fn convert_to_place_expr(&mut self, lrvalue: PlaceOrValue) -> Index { fn convert_to_place_expr(&mut self, lrvalue: PlaceOrValue) -> Index {
match lrvalue { self.ast.convert_to_place_expr(lrvalue)
PlaceOrValue::Place(index) => index,
PlaceOrValue::Value(index) => self.ast.push_value_to_place_conversion(index),
}
} }
/// PREFIX_EXPR <- /// PREFIX_EXPR <-

View file

@ -287,8 +287,8 @@ pub trait AstVisitorTrait<Ast: AstExt> {
idx: Index, idx: Index,
) -> Result<Self::Value, Self::Error> { ) -> Result<Self::Value, Self::Error> {
match ast.get_node_tag_and_data(idx).0 { match ast.get_node_tag_and_data(idx).0 {
Tag::BlockTrailingExpr => self.visit_block(ast, idx), Tag::BlockTrailingExpr => self.visit_block_trailing_expr(ast, idx),
Tag::Block => self.visit_block_trailing_expr(ast, idx), Tag::Block => self.visit_block(ast, idx),
_ => unreachable!(), _ => unreachable!(),
} }
} }