Fix type-inferrer on arrays

This commit is contained in:
Sofia 2025-07-19 19:23:24 +03:00
parent f9f9360efc
commit a511331be2
7 changed files with 54 additions and 75 deletions

View File

@ -578,19 +578,6 @@ impl mir::Expression {
lit.as_type(), lit.as_type(),
)), )),
mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => { mir::ExprKind::BinOp(binop, lhs_exp, rhs_exp) => {
lhs_exp
.return_type()
.expect("No ret type in lhs?")
.1
.known()
.expect("lhs ret type is unknown");
rhs_exp
.return_type()
.expect("No ret type in rhs?")
.1
.known()
.expect("rhs ret type is unknown");
let lhs = lhs_exp let lhs = lhs_exp
.codegen(scope, state) .codegen(scope, state)
.expect("lhs has no return value") .expect("lhs has no return value")
@ -741,7 +728,7 @@ impl mir::Expression {
mir::ExprKind::Accessed(expression, type_kind, field) => { mir::ExprKind::Accessed(expression, type_kind, field) => {
let struct_val = expression.codegen(scope, &mut state.load(true)).unwrap(); let struct_val = expression.codegen(scope, &mut state.load(true)).unwrap();
let TypeKind::CustomType(name) = struct_val.1.deref_borrow() else { let TypeKind::CustomType(name) = &struct_val.1 else {
panic!("tried accessing non-custom-type"); panic!("tried accessing non-custom-type");
}; };
let TypeDefinitionKind::Struct(struct_ty) = let TypeDefinitionKind::Struct(struct_ty) =
@ -969,9 +956,6 @@ impl TypeKind {
TypeDefinitionKind::Struct(_) => Type::Ptr(Box::new(custom_t)), TypeDefinitionKind::Struct(_) => Type::Ptr(Box::new(custom_t)),
} }
} }
TypeKind::Borrow(type_kind) => {
Type::Ptr(Box::new(type_kind.get_type(type_vals, typedefs)))
}
} }
} }

View File

@ -46,7 +46,6 @@ impl TypeKind {
TypeKind::Void => 0, TypeKind::Void => 0,
TypeKind::StringPtr => 32, TypeKind::StringPtr => 32,
TypeKind::Array(type_kind, len) => 32, TypeKind::Array(type_kind, len) => 32,
TypeKind::Borrow(_) => todo!(),
TypeKind::CustomType(_) => 32, TypeKind::CustomType(_) => 32,
TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"), TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"),
} }
@ -69,7 +68,6 @@ impl TypeKind {
TypeKind::Void => DwarfEncoding::Address, TypeKind::Void => DwarfEncoding::Address,
TypeKind::StringPtr => DwarfEncoding::Address, TypeKind::StringPtr => DwarfEncoding::Address,
TypeKind::Array(_, _) => DwarfEncoding::Address, TypeKind::Array(_, _) => DwarfEncoding::Address,
TypeKind::Borrow(_) => DwarfEncoding::Address,
TypeKind::CustomType(_) => DwarfEncoding::Address, TypeKind::CustomType(_) => DwarfEncoding::Address,
TypeKind::Vague(_) => panic!("tried fetching debug-type for vague type!"), TypeKind::Vague(_) => panic!("tried fetching debug-type for vague type!"),
}, },
@ -104,7 +102,7 @@ impl Block {
let mut early_return = None; let mut early_return = None;
for statement in &self.statements { for statement in &self.statements {
let ret = statement.return_type(); let ret = statement.return_type(&Default::default());
if let Ok((ReturnKind::Hard, _)) = ret { if let Ok((ReturnKind::Hard, _)) = ret {
early_return = Some(statement); early_return = Some(statement);
} }
@ -128,11 +126,11 @@ impl Block {
.unwrap_or(self.meta) .unwrap_or(self.meta)
} }
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
let mut early_return = None; let mut early_return = None;
for statement in &self.statements { for statement in &self.statements {
let ret = statement.return_type(); let ret = statement.return_type(refs);
if let Ok((ReturnKind::Hard, _)) = ret { if let Ok((ReturnKind::Hard, _)) = ret {
early_return = early_return.or(ret.ok()); early_return = early_return.or(ret.ok());
} }
@ -145,7 +143,7 @@ impl Block {
self.return_expression self.return_expression
.as_ref() .as_ref()
.ok_or(ReturnTypeOther::NoBlockReturn(self.meta)) .ok_or(ReturnTypeOther::NoBlockReturn(self.meta))
.and_then(|(kind, stmt)| Ok((*kind, stmt.return_type()?.1))) .and_then(|(kind, stmt)| Ok((*kind, stmt.return_type(refs)?.1)))
} }
pub fn backing_var(&self) -> Option<&NamedVariableRef> { pub fn backing_var(&self) -> Option<&NamedVariableRef> {
@ -163,16 +161,19 @@ impl Block {
} }
impl Statement { impl Statement {
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
use StmtKind::*; use StmtKind::*;
match &self.0 { match &self.0 {
Let(var, _, expr) => if_hard( Let(var, _, expr) => if_hard(
expr.return_type()?, expr.return_type(refs)?,
Err(ReturnTypeOther::Let(var.2 + expr.1)), Err(ReturnTypeOther::Let(var.2 + expr.1)),
), ),
Set(lhs, rhs) => if_hard(rhs.return_type()?, Err(ReturnTypeOther::Set(lhs.1 + rhs.1))), Set(lhs, rhs) => if_hard(
rhs.return_type(refs)?,
Err(ReturnTypeOther::Set(lhs.1 + rhs.1)),
),
Import(_) => todo!(), Import(_) => todo!(),
Expression(expression) => expression.return_type(), Expression(expression) => expression.return_type(refs),
} }
} }
@ -187,24 +188,25 @@ impl Statement {
} }
impl Expression { impl Expression {
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
use ExprKind::*; use ExprKind::*;
match &self.0 { match &self.0 {
Literal(lit) => Ok((ReturnKind::Soft, lit.as_type())), Literal(lit) => Ok((ReturnKind::Soft, lit.as_type())),
Variable(var) => var.return_type(), Variable(var) => var.return_type(),
BinOp(_, then_e, else_e) => { BinOp(_, then_e, else_e) => {
let then_r = then_e.return_type()?; let then_r = then_e.return_type(refs)?;
let else_r = else_e.return_type()?; let else_r = else_e.return_type(refs)?;
Ok(pick_return(then_r, else_r)) Ok(pick_return(then_r, else_r))
} }
Block(block) => block.return_type(), Block(block) => block.return_type(refs),
FunctionCall(fcall) => fcall.return_type(), FunctionCall(fcall) => fcall.return_type(),
If(expr) => expr.return_type(), If(expr) => expr.return_type(refs),
Indexed(expression, _, _) => { Indexed(expression, _, _) => {
let expr_type = expression.return_type()?; let expr_type = expression.return_type(refs)?;
if let (_, TypeKind::Array(elem_ty, _)) = expr_type { dbg!(&expr_type);
Ok((ReturnKind::Soft, TypeKind::Borrow(Box::new(*elem_ty)))) if let TypeKind::Array(elem_ty, _) = expr_type.1.resolve_weak(refs) {
Ok((ReturnKind::Soft, *elem_ty))
} else { } else {
Err(ReturnTypeOther::IndexingNonArray(expression.1)) Err(ReturnTypeOther::IndexingNonArray(expression.1))
} }
@ -213,17 +215,14 @@ impl Expression {
let first = expressions let first = expressions
.iter() .iter()
.next() .next()
.map(|e| e.return_type()) .map(|e| e.return_type(refs))
.unwrap_or(Ok((ReturnKind::Soft, TypeKind::Void)))?; .unwrap_or(Ok((ReturnKind::Soft, TypeKind::Void)))?;
Ok(( Ok((
ReturnKind::Soft, ReturnKind::Soft,
TypeKind::Array(Box::new(first.1), expressions.len() as u64), TypeKind::Array(Box::new(first.1), expressions.len() as u64),
)) ))
} }
Accessed(_, type_kind, _) => Ok(( Accessed(_, type_kind, _) => Ok((ReturnKind::Soft, type_kind.clone())),
ReturnKind::Soft,
TypeKind::Borrow(Box::new(type_kind.clone())),
)),
Struct(name, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(name.clone()))), Struct(name, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(name.clone()))),
} }
} }
@ -245,10 +244,10 @@ impl Expression {
} }
impl IfExpression { impl IfExpression {
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
let then_r = self.1.return_type()?; let then_r = self.1.return_type(refs)?;
if let Some(else_b) = &self.2 { if let Some(else_b) = &self.2 {
let else_r = else_b.return_type()?; let else_r = else_b.return_type(refs)?;
let kind = if then_r.0 == ReturnKind::Hard && else_r.0 == ReturnKind::Hard { let kind = if then_r.0 == ReturnKind::Hard && else_r.0 == ReturnKind::Hard {
ReturnKind::Hard ReturnKind::Hard
@ -315,21 +314,18 @@ impl TypeKind {
} }
} }
pub fn resolve_ref(&self, refs: &TypeRefs) -> TypeKind { pub fn resolve_weak(&self, refs: &TypeRefs) -> TypeKind {
let resolved = match self { match self {
TypeKind::Vague(Vague::TypeRef(idx)) => refs.retrieve_type(*idx).unwrap(), TypeKind::Vague(Vague::TypeRef(idx)) => refs.retrieve_type(*idx).unwrap(),
_ => self.clone(), _ => self.clone(),
};
match resolved {
TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_ref(refs)), len),
_ => resolved,
} }
} }
pub fn deref_borrow(&self) -> TypeKind { pub fn resolve_ref(&self, refs: &TypeRefs) -> TypeKind {
match self { let resolved = self.resolve_weak(refs);
TypeKind::Borrow(type_kind) => *type_kind.clone(), match resolved {
_ => self.clone(), TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_ref(refs)), len),
_ => resolved,
} }
} }
} }

View File

@ -95,10 +95,10 @@ impl<'map> Pass for LinkerPass<'map> {
modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens)))); modules.insert(module.name.clone(), Rc::new(RefCell::new((module, tokens))));
} }
modules.insert( // modules.insert(
"std".to_owned(), // "std".to_owned(),
Rc::new(RefCell::new(compile_std(&mut self.module_map))), // Rc::new(RefCell::new(compile_std(&mut self.module_map))),
); // );
let mut modules_to_process: Vec<Rc<RefCell<(Module, Vec<FullToken>)>>> = let mut modules_to_process: Vec<Rc<RefCell<(Module, Vec<FullToken>)>>> =
modules.values().cloned().collect(); modules.values().cloned().collect();

View File

@ -107,8 +107,6 @@ pub enum TypeKind {
StringPtr, StringPtr,
#[error("[{0}; {1}]")] #[error("[{0}; {1}]")]
Array(Box<TypeKind>, u64), Array(Box<TypeKind>, u64),
#[error("Borrow({0})")]
Borrow(Box<TypeKind>),
#[error("{0}")] #[error("{0}")]
CustomType(String), CustomType(String),
#[error(transparent)] #[error(transparent)]

View File

@ -299,7 +299,7 @@ impl Block {
StmtKind::Expression(expression) => { StmtKind::Expression(expression) => {
let res = expression.typecheck(&mut state, &typerefs, None); let res = expression.typecheck(&mut state, &typerefs, None);
state.or_else(res, TypeKind::Void, expression.1); state.or_else(res, TypeKind::Void, expression.1);
if let Ok((kind, _)) = expression.return_type() { if let Ok((kind, _)) = expression.return_type(typerefs) {
Some((kind, expression)) Some((kind, expression))
} else { } else {
None None

View File

@ -78,17 +78,17 @@ impl Block {
fn infer_types<'s>( fn infer_types<'s>(
&mut self, &mut self,
state: &mut TypeInferencePassState, state: &mut TypeInferencePassState,
outer_hints: &'s ScopeTypeRefs, outer_refs: &'s ScopeTypeRefs,
) -> Result<(ReturnKind, TypeRef<'s>), ErrorKind> { ) -> Result<(ReturnKind, TypeRef<'s>), ErrorKind> {
let mut state = state.inner(); let mut state = state.inner();
let inner_hints = outer_hints.inner(); let inner_refs = outer_refs.inner();
for statement in &mut self.statements { for statement in &mut self.statements {
match &mut statement.0 { match &mut statement.0 {
StmtKind::Let(var, mutable, expr) => { StmtKind::Let(var, mutable, expr) => {
// Get the TypeRef for this variable declaration // Get the TypeRef for this variable declaration
let mut var_ref = let mut var_ref =
state.ok(inner_hints.new_var(var.1.clone(), *mutable, &var.0), var.2); state.ok(inner_refs.new_var(var.1.clone(), *mutable, &var.0), var.2);
// If ok, update the MIR type to this TypeRef // If ok, update the MIR type to this TypeRef
if let Some(var_ref) = &var_ref { if let Some(var_ref) = &var_ref {
@ -96,7 +96,7 @@ impl Block {
} }
// Infer hints for the expression itself // Infer hints for the expression itself
let inferred = expr.infer_types(&mut state, &inner_hints); let inferred = expr.infer_types(&mut state, &inner_refs);
let mut expr_ty_ref = state.ok(inferred, expr.1); let mut expr_ty_ref = state.ok(inferred, expr.1);
// Try to narrow the variable type declaration with the // Try to narrow the variable type declaration with the
@ -105,16 +105,15 @@ impl Block {
(var_ref.as_mut(), expr_ty_ref.as_mut()) (var_ref.as_mut(), expr_ty_ref.as_mut())
{ {
var_ref.narrow(&expr_ty_ref); var_ref.narrow(&expr_ty_ref);
dbg!(var_ref);
} }
} }
StmtKind::Set(lhs, rhs) => { StmtKind::Set(lhs, rhs) => {
// Infer hints for the expression itself // Infer hints for the expression itself
let lhs_infer = lhs.infer_types(&mut state, &inner_hints); let lhs_infer = lhs.infer_types(&mut state, &inner_refs);
let lhs_ref = state.ok(lhs_infer, rhs.1); let lhs_ref = state.ok(lhs_infer, rhs.1);
// Infer hints for the expression itself // Infer hints for the expression itself
let rhs_infer = rhs.infer_types(&mut state, &inner_hints); let rhs_infer = rhs.infer_types(&mut state, &inner_refs);
let rhs_ref = state.ok(rhs_infer, rhs.1); let rhs_ref = state.ok(rhs_infer, rhs.1);
// Try to narrow the lhs with rhs // Try to narrow the lhs with rhs
@ -124,7 +123,7 @@ impl Block {
} }
StmtKind::Import(_) => todo!(), StmtKind::Import(_) => todo!(),
StmtKind::Expression(expr) => { StmtKind::Expression(expr) => {
let expr_res = expr.infer_types(&mut state, &inner_hints); let expr_res = expr.infer_types(&mut state, &inner_refs);
state.ok(expr_res, expr.1); state.ok(expr_res, expr.1);
} }
}; };
@ -132,18 +131,22 @@ impl Block {
// If there is a return expression, infer it's type // If there is a return expression, infer it's type
if let Some(ret_expr) = &mut self.return_expression { if let Some(ret_expr) = &mut self.return_expression {
let ret_res = ret_expr.1.infer_types(&mut state, &inner_hints); let ret_res = ret_expr.1.infer_types(&mut state, &inner_refs);
state.ok(ret_res, ret_expr.1 .1); state.ok(ret_res, ret_expr.1 .1);
} }
// Fetch the declared return type // Fetch the declared return type
let (kind, ty) = self.return_type().ok().unwrap_or((ReturnKind::Soft, Void)); let (kind, ty) = self
let mut ret_type_ref = outer_hints.from_type(&ty).unwrap(); .return_type(inner_refs.types)
.ok()
.unwrap_or((ReturnKind::Soft, Void));
let mut ret_type_ref = outer_refs.from_type(&ty).unwrap();
dbg!(&self.return_type(inner_refs.types));
// Narow return type to declared type if hard return // Narow return type to declared type if hard return
if kind == ReturnKind::Hard { if kind == ReturnKind::Hard {
if let Some(hint) = &state.scope.return_type_hint { if let Some(hint) = &state.scope.return_type_hint {
ret_type_ref.narrow(&mut outer_hints.from_type(&hint).unwrap()); ret_type_ref.narrow(&mut outer_refs.from_type(&hint).unwrap());
} }
} }
@ -344,10 +347,8 @@ impl Expression {
for field in fields { for field in fields {
if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) { if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) {
let field_ty = field.1.infer_types(state, type_refs); let field_ty = field.1.infer_types(state, type_refs);
dbg!(&field_ty, expected_field_ty);
if let Some(mut field_ty) = state.ok(field_ty, field.1 .1) { if let Some(mut field_ty) = state.ok(field_ty, field.1 .1) {
field_ty.narrow(&type_refs.from_type(&expected_field_ty).unwrap()); field_ty.narrow(&type_refs.from_type(&expected_field_ty).unwrap());
dbg!(&field_ty);
} }
} else { } else {
state.ok::<_, Infallible>( state.ok::<_, Infallible>(

View File

@ -120,7 +120,7 @@ impl TypeRefs {
#[derive(Debug)] #[derive(Debug)]
pub struct ScopeTypeRefs<'outer> { pub struct ScopeTypeRefs<'outer> {
types: &'outer TypeRefs, pub types: &'outer TypeRefs,
outer: Option<&'outer ScopeTypeRefs<'outer>>, outer: Option<&'outer ScopeTypeRefs<'outer>>,
/// Mapping of what types variables point to /// Mapping of what types variables point to
variables: RefCell<HashMap<String, (bool, TypeIdRef)>>, variables: RefCell<HashMap<String, (bool, TypeIdRef)>>,