From 557d5f9722735950f6d07c4679ccfc31b0987dde Mon Sep 17 00:00:00 2001 From: sofia Date: Sat, 12 Jul 2025 23:35:35 +0300 Subject: [PATCH] Finish second phase of typechecking, resolve hinted values --- reid/src/mir/scopehints.rs | 28 ++++++++++++++++++++-------- reid/src/mir/typecheck.rs | 29 ++++++++++++++++++++--------- reid/src/mir/types.rs | 1 - 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/reid/src/mir/scopehints.rs b/reid/src/mir/scopehints.rs index 12eea26..eefee7b 100644 --- a/reid/src/mir/scopehints.rs +++ b/reid/src/mir/scopehints.rs @@ -1,4 +1,4 @@ -use std::{cell::RefCell, collections::HashMap, fmt::Error, rc::Rc}; +use std::{cell::RefCell, collections::HashMap, rc::Rc}; use super::{ typecheck::{Collapsable, ErrorKind}, @@ -9,12 +9,8 @@ use super::{ pub struct ScopeHint<'scope>(TypeIdRef, &'scope ScopeHints<'scope>); impl<'scope> ScopeHint<'scope> { - pub unsafe fn raw_type(&self) -> TypeKind { - if let Some(ty) = self.1.types.hints.borrow().get(*self.0.borrow()) { - *ty - } else { - panic!("TODO") - } + pub unsafe fn resolve_type(&self) -> TypeKind { + unsafe { *self.1.types.hints.borrow().get_unchecked(*self.0.borrow()) } } pub fn narrow(&mut self, ty_ref: &TypeRef) -> Result, ErrorKind> { @@ -33,7 +29,7 @@ impl<'scope> std::fmt::Debug for ScopeHint<'scope> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_tuple("Hint") .field(&self.0) - .field(unsafe { &self.raw_type() }) + .field(unsafe { &self.resolve_type() }) .finish() } } @@ -74,6 +70,22 @@ impl<'outer> ScopeHints<'outer> { } } + pub fn retrieve_type(&self, mut idx: usize) -> Option { + // Just make sure we have the correct idx + let mut inner_idx = self.types.types.borrow().get(idx).map(|i| *i.borrow())?; + let mut limit = 50; + while inner_idx != idx { + idx = inner_idx; + inner_idx = self.types.types.borrow().get(idx).map(|i| *i.borrow())?; + limit -= 1; + if limit < 0 { + // Should never happen, but just to avoid infinite loops + panic!("Limit reached!"); + } + } + self.types.hints.borrow().get(inner_idx).copied() + } + pub fn new_var( &'outer self, name: String, diff --git a/reid/src/mir/typecheck.rs b/reid/src/mir/typecheck.rs index 6cdb424..ea96772 100644 --- a/reid/src/mir/typecheck.rs +++ b/reid/src/mir/typecheck.rs @@ -84,9 +84,8 @@ impl FunctionDefinition { let types = TypeHints::default(); let hints = ScopeHints::from(&types); if let Ok(_) = block.infer_hints(state, &hints) { - dbg!(&block, &hints); - // block.typecheck(state, &hints, Some(return_type)) - Ok(Vague(Unknown)) + print!("{}", block); + block.typecheck(state, &hints, Some(return_type)) } else { Ok(Vague(Unknown)) } @@ -130,7 +129,6 @@ impl Block { } StmtKind::Set(var, expr) => { let var_ref = inner_hints.find_hint(&var.1); - dbg!(&var_ref); if let Some((_, var_ref)) = &var_ref { var.0 = var_ref.as_type() } @@ -181,7 +179,11 @@ impl Block { for statement in &mut self.statements { let ret = match &mut statement.0 { StmtKind::Let(variable_reference, mutable, expression) => { - let res = expression.typecheck(&mut state, &hints, Some(variable_reference.0)); + // Resolve possible hint in var reference + let var_t_resolved = variable_reference.0.resolve_hinted(&hints); + + // Typecheck (and coerce) expression with said type + let res = expression.typecheck(&mut state, &hints, Some(var_t_resolved)); // If expression resolution itself was erronous, resolve as // Unknown. @@ -189,7 +191,7 @@ impl Block { // Make sure the expression and variable type really is the same let res_t = state.or_else( - res.collapse_into(&variable_reference.0), + res.collapse_into(&var_t_resolved), Vague(Unknown), variable_reference.2 + expression.1, ); @@ -240,7 +242,7 @@ impl Block { // Make sure the expression and variable type to really // be the same let res_t = state.or_else( - expr_ty.collapse_into(&variable_reference.0), + expr_ty.collapse_into(&variable_reference.0.resolve_hinted(&hints)), Vague(Unknown), variable_reference.2 + expression.1, ); @@ -413,7 +415,7 @@ impl Expression { // Update typing to be more accurate var_ref.0 = state.or_else( - var_ref.0.collapse_into(&existing), + var_ref.0.resolve_hinted(hints).collapse_into(&existing), Vague(Unknown), var_ref.2, ); @@ -479,7 +481,9 @@ impl Expression { // Make sure function return type is the same as the claimed // return type - let ret_t = f.ret.collapse_into(&function_call.return_type)?; + let ret_t = f + .ret + .collapse_into(&function_call.return_type.resolve_hinted(hints))?; // Update typing to be more accurate function_call.return_type = ret_t; Ok(ret_t) @@ -592,6 +596,13 @@ impl TypeKind { BinaryOperator::Cmp(_) => Bool, }) } + + fn resolve_hinted(&self, hints: &ScopeHints) -> TypeKind { + match self { + Vague(Hinted(idx)) => hints.retrieve_type(*idx).unwrap(), + _ => *self, + } + } } pub trait Collapsable: Sized + Clone { diff --git a/reid/src/mir/types.rs b/reid/src/mir/types.rs index 448908b..7e007bf 100644 --- a/reid/src/mir/types.rs +++ b/reid/src/mir/types.rs @@ -82,7 +82,6 @@ impl ReturnType for IfExpression { let then_r = self.1.return_type()?; if let Some(else_b) = &self.2 { let else_r = else_b.return_type()?; - dbg!(&then_r, &else_r); let kind = if then_r.0 == ReturnKind::Hard && else_r.0 == ReturnKind::Hard { ReturnKind::Hard