Finish second phase of typechecking, resolve hinted values
This commit is contained in:
		
							parent
							
								
									61ab5002e4
								
							
						
					
					
						commit
						557d5f9722
					
				@ -1,4 +1,4 @@
 | 
				
			|||||||
use std::{cell::RefCell, collections::HashMap, fmt::Error, rc::Rc};
 | 
					use std::{cell::RefCell, collections::HashMap, rc::Rc};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use super::{
 | 
					use super::{
 | 
				
			||||||
    typecheck::{Collapsable, ErrorKind},
 | 
					    typecheck::{Collapsable, ErrorKind},
 | 
				
			||||||
@ -9,12 +9,8 @@ use super::{
 | 
				
			|||||||
pub struct ScopeHint<'scope>(TypeIdRef, &'scope ScopeHints<'scope>);
 | 
					pub struct ScopeHint<'scope>(TypeIdRef, &'scope ScopeHints<'scope>);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<'scope> ScopeHint<'scope> {
 | 
					impl<'scope> ScopeHint<'scope> {
 | 
				
			||||||
    pub unsafe fn raw_type(&self) -> TypeKind {
 | 
					    pub unsafe fn resolve_type(&self) -> TypeKind {
 | 
				
			||||||
        if let Some(ty) = self.1.types.hints.borrow().get(*self.0.borrow()) {
 | 
					        unsafe { *self.1.types.hints.borrow().get_unchecked(*self.0.borrow()) }
 | 
				
			||||||
            *ty
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            panic!("TODO")
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub fn narrow(&mut self, ty_ref: &TypeRef) -> Result<ScopeHint<'scope>, ErrorKind> {
 | 
					    pub fn narrow(&mut self, ty_ref: &TypeRef) -> Result<ScopeHint<'scope>, ErrorKind> {
 | 
				
			||||||
@ -33,7 +29,7 @@ impl<'scope> std::fmt::Debug for ScopeHint<'scope> {
 | 
				
			|||||||
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
					    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 | 
				
			||||||
        f.debug_tuple("Hint")
 | 
					        f.debug_tuple("Hint")
 | 
				
			||||||
            .field(&self.0)
 | 
					            .field(&self.0)
 | 
				
			||||||
            .field(unsafe { &self.raw_type() })
 | 
					            .field(unsafe { &self.resolve_type() })
 | 
				
			||||||
            .finish()
 | 
					            .finish()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -74,6 +70,22 @@ impl<'outer> ScopeHints<'outer> {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn retrieve_type(&self, mut idx: usize) -> Option<TypeKind> {
 | 
				
			||||||
 | 
					        // 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(
 | 
					    pub fn new_var(
 | 
				
			||||||
        &'outer self,
 | 
					        &'outer self,
 | 
				
			||||||
        name: String,
 | 
					        name: String,
 | 
				
			||||||
 | 
				
			|||||||
@ -84,9 +84,8 @@ impl FunctionDefinition {
 | 
				
			|||||||
                let types = TypeHints::default();
 | 
					                let types = TypeHints::default();
 | 
				
			||||||
                let hints = ScopeHints::from(&types);
 | 
					                let hints = ScopeHints::from(&types);
 | 
				
			||||||
                if let Ok(_) = block.infer_hints(state, &hints) {
 | 
					                if let Ok(_) = block.infer_hints(state, &hints) {
 | 
				
			||||||
                    dbg!(&block, &hints);
 | 
					                    print!("{}", block);
 | 
				
			||||||
                    // block.typecheck(state, &hints, Some(return_type))
 | 
					                    block.typecheck(state, &hints, Some(return_type))
 | 
				
			||||||
                    Ok(Vague(Unknown))
 | 
					 | 
				
			||||||
                } else {
 | 
					                } else {
 | 
				
			||||||
                    Ok(Vague(Unknown))
 | 
					                    Ok(Vague(Unknown))
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -130,7 +129,6 @@ impl Block {
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
                StmtKind::Set(var, expr) => {
 | 
					                StmtKind::Set(var, expr) => {
 | 
				
			||||||
                    let var_ref = inner_hints.find_hint(&var.1);
 | 
					                    let var_ref = inner_hints.find_hint(&var.1);
 | 
				
			||||||
                    dbg!(&var_ref);
 | 
					 | 
				
			||||||
                    if let Some((_, var_ref)) = &var_ref {
 | 
					                    if let Some((_, var_ref)) = &var_ref {
 | 
				
			||||||
                        var.0 = var_ref.as_type()
 | 
					                        var.0 = var_ref.as_type()
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
@ -181,7 +179,11 @@ impl Block {
 | 
				
			|||||||
        for statement in &mut self.statements {
 | 
					        for statement in &mut self.statements {
 | 
				
			||||||
            let ret = match &mut statement.0 {
 | 
					            let ret = match &mut statement.0 {
 | 
				
			||||||
                StmtKind::Let(variable_reference, mutable, expression) => {
 | 
					                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
 | 
					                    // If expression resolution itself was erronous, resolve as
 | 
				
			||||||
                    // Unknown.
 | 
					                    // Unknown.
 | 
				
			||||||
@ -189,7 +191,7 @@ impl Block {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    // Make sure the expression and variable type really is the same
 | 
					                    // Make sure the expression and variable type really is the same
 | 
				
			||||||
                    let res_t = state.or_else(
 | 
					                    let res_t = state.or_else(
 | 
				
			||||||
                        res.collapse_into(&variable_reference.0),
 | 
					                        res.collapse_into(&var_t_resolved),
 | 
				
			||||||
                        Vague(Unknown),
 | 
					                        Vague(Unknown),
 | 
				
			||||||
                        variable_reference.2 + expression.1,
 | 
					                        variable_reference.2 + expression.1,
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
@ -240,7 +242,7 @@ impl Block {
 | 
				
			|||||||
                        // Make sure the expression and variable type to really
 | 
					                        // Make sure the expression and variable type to really
 | 
				
			||||||
                        // be the same
 | 
					                        // be the same
 | 
				
			||||||
                        let res_t = state.or_else(
 | 
					                        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),
 | 
					                            Vague(Unknown),
 | 
				
			||||||
                            variable_reference.2 + expression.1,
 | 
					                            variable_reference.2 + expression.1,
 | 
				
			||||||
                        );
 | 
					                        );
 | 
				
			||||||
@ -413,7 +415,7 @@ impl Expression {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                // Update typing to be more accurate
 | 
					                // Update typing to be more accurate
 | 
				
			||||||
                var_ref.0 = state.or_else(
 | 
					                var_ref.0 = state.or_else(
 | 
				
			||||||
                    var_ref.0.collapse_into(&existing),
 | 
					                    var_ref.0.resolve_hinted(hints).collapse_into(&existing),
 | 
				
			||||||
                    Vague(Unknown),
 | 
					                    Vague(Unknown),
 | 
				
			||||||
                    var_ref.2,
 | 
					                    var_ref.2,
 | 
				
			||||||
                );
 | 
					                );
 | 
				
			||||||
@ -479,7 +481,9 @@ impl Expression {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    // Make sure function return type is the same as the claimed
 | 
					                    // Make sure function return type is the same as the claimed
 | 
				
			||||||
                    // return type
 | 
					                    // 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
 | 
					                    // Update typing to be more accurate
 | 
				
			||||||
                    function_call.return_type = ret_t;
 | 
					                    function_call.return_type = ret_t;
 | 
				
			||||||
                    Ok(ret_t)
 | 
					                    Ok(ret_t)
 | 
				
			||||||
@ -592,6 +596,13 @@ impl TypeKind {
 | 
				
			|||||||
            BinaryOperator::Cmp(_) => Bool,
 | 
					            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 {
 | 
					pub trait Collapsable: Sized + Clone {
 | 
				
			||||||
 | 
				
			|||||||
@ -82,7 +82,6 @@ impl ReturnType for IfExpression {
 | 
				
			|||||||
        let then_r = self.1.return_type()?;
 | 
					        let then_r = self.1.return_type()?;
 | 
				
			||||||
        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()?;
 | 
				
			||||||
            dbg!(&then_r, &else_r);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            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
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user