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