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(),
)),
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
.codegen(scope, state)
.expect("lhs has no return value")
@ -741,7 +728,7 @@ impl mir::Expression {
mir::ExprKind::Accessed(expression, type_kind, field) => {
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");
};
let TypeDefinitionKind::Struct(struct_ty) =
@ -969,9 +956,6 @@ impl TypeKind {
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::StringPtr => 32,
TypeKind::Array(type_kind, len) => 32,
TypeKind::Borrow(_) => todo!(),
TypeKind::CustomType(_) => 32,
TypeKind::Vague(_) => panic!("Tried to sizeof a vague type!"),
}
@ -69,7 +68,6 @@ impl TypeKind {
TypeKind::Void => DwarfEncoding::Address,
TypeKind::StringPtr => DwarfEncoding::Address,
TypeKind::Array(_, _) => DwarfEncoding::Address,
TypeKind::Borrow(_) => DwarfEncoding::Address,
TypeKind::CustomType(_) => DwarfEncoding::Address,
TypeKind::Vague(_) => panic!("tried fetching debug-type for vague type!"),
},
@ -104,7 +102,7 @@ impl Block {
let mut early_return = None;
for statement in &self.statements {
let ret = statement.return_type();
let ret = statement.return_type(&Default::default());
if let Ok((ReturnKind::Hard, _)) = ret {
early_return = Some(statement);
}
@ -128,11 +126,11 @@ impl Block {
.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;
for statement in &self.statements {
let ret = statement.return_type();
let ret = statement.return_type(refs);
if let Ok((ReturnKind::Hard, _)) = ret {
early_return = early_return.or(ret.ok());
}
@ -145,7 +143,7 @@ impl Block {
self.return_expression
.as_ref()
.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> {
@ -163,16 +161,19 @@ impl Block {
}
impl Statement {
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
use StmtKind::*;
match &self.0 {
Let(var, _, expr) => if_hard(
expr.return_type()?,
expr.return_type(refs)?,
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!(),
Expression(expression) => expression.return_type(),
Expression(expression) => expression.return_type(refs),
}
}
@ -187,24 +188,25 @@ impl Statement {
}
impl Expression {
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
use ExprKind::*;
match &self.0 {
Literal(lit) => Ok((ReturnKind::Soft, lit.as_type())),
Variable(var) => var.return_type(),
BinOp(_, then_e, else_e) => {
let then_r = then_e.return_type()?;
let else_r = else_e.return_type()?;
let then_r = then_e.return_type(refs)?;
let else_r = else_e.return_type(refs)?;
Ok(pick_return(then_r, else_r))
}
Block(block) => block.return_type(),
Block(block) => block.return_type(refs),
FunctionCall(fcall) => fcall.return_type(),
If(expr) => expr.return_type(),
If(expr) => expr.return_type(refs),
Indexed(expression, _, _) => {
let expr_type = expression.return_type()?;
if let (_, TypeKind::Array(elem_ty, _)) = expr_type {
Ok((ReturnKind::Soft, TypeKind::Borrow(Box::new(*elem_ty))))
let expr_type = expression.return_type(refs)?;
dbg!(&expr_type);
if let TypeKind::Array(elem_ty, _) = expr_type.1.resolve_weak(refs) {
Ok((ReturnKind::Soft, *elem_ty))
} else {
Err(ReturnTypeOther::IndexingNonArray(expression.1))
}
@ -213,17 +215,14 @@ impl Expression {
let first = expressions
.iter()
.next()
.map(|e| e.return_type())
.map(|e| e.return_type(refs))
.unwrap_or(Ok((ReturnKind::Soft, TypeKind::Void)))?;
Ok((
ReturnKind::Soft,
TypeKind::Array(Box::new(first.1), expressions.len() as u64),
))
}
Accessed(_, type_kind, _) => Ok((
ReturnKind::Soft,
TypeKind::Borrow(Box::new(type_kind.clone())),
)),
Accessed(_, type_kind, _) => Ok((ReturnKind::Soft, type_kind.clone())),
Struct(name, _) => Ok((ReturnKind::Soft, TypeKind::CustomType(name.clone()))),
}
}
@ -245,10 +244,10 @@ impl Expression {
}
impl IfExpression {
pub fn return_type(&self) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
let then_r = self.1.return_type()?;
pub fn return_type(&self, refs: &TypeRefs) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> {
let then_r = self.1.return_type(refs)?;
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 {
ReturnKind::Hard
@ -315,21 +314,18 @@ impl TypeKind {
}
}
pub fn resolve_ref(&self, refs: &TypeRefs) -> TypeKind {
let resolved = match self {
pub fn resolve_weak(&self, refs: &TypeRefs) -> TypeKind {
match self {
TypeKind::Vague(Vague::TypeRef(idx)) => refs.retrieve_type(*idx).unwrap(),
_ => self.clone(),
};
match resolved {
TypeKind::Array(t, len) => TypeKind::Array(Box::new(t.resolve_ref(refs)), len),
_ => resolved,
}
}
pub fn deref_borrow(&self) -> TypeKind {
match self {
TypeKind::Borrow(type_kind) => *type_kind.clone(),
_ => self.clone(),
pub fn resolve_ref(&self, refs: &TypeRefs) -> TypeKind {
let resolved = self.resolve_weak(refs);
match resolved {
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(
"std".to_owned(),
Rc::new(RefCell::new(compile_std(&mut self.module_map))),
);
// modules.insert(
// "std".to_owned(),
// Rc::new(RefCell::new(compile_std(&mut self.module_map))),
// );
let mut modules_to_process: Vec<Rc<RefCell<(Module, Vec<FullToken>)>>> =
modules.values().cloned().collect();

View File

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

View File

@ -299,7 +299,7 @@ impl Block {
StmtKind::Expression(expression) => {
let res = expression.typecheck(&mut state, &typerefs, None);
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))
} else {
None

View File

@ -78,17 +78,17 @@ impl Block {
fn infer_types<'s>(
&mut self,
state: &mut TypeInferencePassState,
outer_hints: &'s ScopeTypeRefs,
outer_refs: &'s ScopeTypeRefs,
) -> Result<(ReturnKind, TypeRef<'s>), ErrorKind> {
let mut state = state.inner();
let inner_hints = outer_hints.inner();
let inner_refs = outer_refs.inner();
for statement in &mut self.statements {
match &mut statement.0 {
StmtKind::Let(var, mutable, expr) => {
// Get the TypeRef for this variable declaration
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 let Some(var_ref) = &var_ref {
@ -96,7 +96,7 @@ impl Block {
}
// 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);
// 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.narrow(&expr_ty_ref);
dbg!(var_ref);
}
}
StmtKind::Set(lhs, rhs) => {
// 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);
// 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);
// Try to narrow the lhs with rhs
@ -124,7 +123,7 @@ impl Block {
}
StmtKind::Import(_) => todo!(),
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);
}
};
@ -132,18 +131,22 @@ impl Block {
// If there is a return expression, infer it's type
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);
}
// Fetch the declared return type
let (kind, ty) = self.return_type().ok().unwrap_or((ReturnKind::Soft, Void));
let mut ret_type_ref = outer_hints.from_type(&ty).unwrap();
let (kind, ty) = self
.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
if kind == ReturnKind::Hard {
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 {
if let Some(expected_field_ty) = expected_struct_ty.get_field_ty(&field.0) {
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) {
field_ty.narrow(&type_refs.from_type(&expected_field_ty).unwrap());
dbg!(&field_ty);
}
} else {
state.ok::<_, Infallible>(

View File

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