Finish type checking and inferrence for arrays
This commit is contained in:
parent
b14a62bc34
commit
515c031f19
@ -93,6 +93,7 @@ pub fn compile(source: &str) -> Result<String, ReidError> {
|
|||||||
|
|
||||||
let state = mir_context.pass(&mut TypeInference { refs: &refs });
|
let state = mir_context.pass(&mut TypeInference { refs: &refs });
|
||||||
dbg!(&state, &refs);
|
dbg!(&state, &refs);
|
||||||
|
dbg!(&mir_context);
|
||||||
println!("{}", &mir_context);
|
println!("{}", &mir_context);
|
||||||
|
|
||||||
let state = mir_context.pass(&mut TypeCheck { refs: &refs });
|
let state = mir_context.pass(&mut TypeCheck { refs: &refs });
|
||||||
|
@ -254,17 +254,19 @@ impl Expression {
|
|||||||
) -> Result<TypeKind, ErrorKind> {
|
) -> Result<TypeKind, ErrorKind> {
|
||||||
match &mut self.0 {
|
match &mut self.0 {
|
||||||
ExprKind::Variable(var_ref) => {
|
ExprKind::Variable(var_ref) => {
|
||||||
let existing = state.or_else(
|
let existing = state
|
||||||
state
|
.or_else(
|
||||||
.scope
|
state
|
||||||
.variables
|
.scope
|
||||||
.get(&var_ref.1)
|
.variables
|
||||||
.map(|var| &var.ty)
|
.get(&var_ref.1)
|
||||||
.cloned()
|
.map(|var| &var.ty)
|
||||||
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
|
.cloned()
|
||||||
Vague(Unknown),
|
.ok_or(ErrorKind::VariableNotDefined(var_ref.1.clone())),
|
||||||
var_ref.2,
|
Vague(Unknown),
|
||||||
);
|
var_ref.2,
|
||||||
|
)
|
||||||
|
.resolve_hinted(hints);
|
||||||
|
|
||||||
// Update typing to be more accurate
|
// Update typing to be more accurate
|
||||||
var_ref.0 = state.or_else(
|
var_ref.0 = state.or_else(
|
||||||
@ -339,9 +341,9 @@ impl Expression {
|
|||||||
.collapse_into(&function_call.return_type.resolve_hinted(hints))?;
|
.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.clone();
|
function_call.return_type = ret_t.clone();
|
||||||
Ok(ret_t)
|
Ok(ret_t.resolve_hinted(hints))
|
||||||
} else {
|
} else {
|
||||||
Ok(function_call.return_type.clone())
|
Ok(function_call.return_type.clone().resolve_hinted(hints))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
ExprKind::If(IfExpression(cond, lhs, rhs)) => {
|
||||||
@ -379,9 +381,15 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
ExprKind::Block(block) => block.typecheck(state, &hints, hint_t),
|
ExprKind::Block(block) => block.typecheck(state, &hints, hint_t),
|
||||||
ExprKind::Index(expression, idx) => {
|
ExprKind::Index(expression, idx) => {
|
||||||
|
// Try to unwrap hint type from array if possible
|
||||||
|
let hint_t = hint_t.map(|t| match t {
|
||||||
|
Array(type_kind, _) => &type_kind,
|
||||||
|
_ => t,
|
||||||
|
});
|
||||||
|
|
||||||
let expr_t = expression.typecheck(state, hints, hint_t)?;
|
let expr_t = expression.typecheck(state, hints, hint_t)?;
|
||||||
if let TypeKind::Array(elem_t, len) = expr_t {
|
if let TypeKind::Array(elem_t, len) = expr_t {
|
||||||
if len >= *idx {
|
if len < *idx {
|
||||||
return Err(ErrorKind::IndexOutOfBounds(*idx, len));
|
return Err(ErrorKind::IndexOutOfBounds(*idx, len));
|
||||||
}
|
}
|
||||||
Ok(*elem_t)
|
Ok(*elem_t)
|
||||||
@ -390,6 +398,12 @@ impl Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprKind::Array(expressions) => {
|
ExprKind::Array(expressions) => {
|
||||||
|
// Try to unwrap hint type from array if possible
|
||||||
|
let hint_t = hint_t.map(|t| match t {
|
||||||
|
Array(type_kind, _) => &type_kind,
|
||||||
|
_ => t,
|
||||||
|
});
|
||||||
|
|
||||||
let mut expr_result = try_all(
|
let mut expr_result = try_all(
|
||||||
expressions
|
expressions
|
||||||
.iter_mut()
|
.iter_mut()
|
||||||
@ -403,7 +417,7 @@ impl Expression {
|
|||||||
for other in iter {
|
for other in iter {
|
||||||
state.ok(first.collapse_into(other), self.1);
|
state.ok(first.collapse_into(other), self.1);
|
||||||
}
|
}
|
||||||
Ok(first.clone())
|
Ok(Array(Box::new(first.clone()), expressions.len() as u64))
|
||||||
} else {
|
} else {
|
||||||
Ok(Array(Box::new(Void), 0))
|
Ok(Array(Box::new(Void), 0))
|
||||||
}
|
}
|
||||||
@ -479,9 +493,13 @@ impl TypeKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind {
|
fn resolve_hinted(&self, hints: &TypeRefs) -> TypeKind {
|
||||||
match self {
|
let resolved = match self {
|
||||||
Vague(TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(),
|
Vague(TypeRef(idx)) => hints.retrieve_type(*idx).unwrap(),
|
||||||
_ => self.clone(),
|
_ => self.clone(),
|
||||||
|
};
|
||||||
|
match resolved {
|
||||||
|
Array(t, len) => Array(Box::new(t.resolve_hinted(hints)), len),
|
||||||
|
_ => resolved,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@ use std::{
|
|||||||
rc::Rc,
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::mir::VagueType;
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
typecheck::{Collapsable, ErrorKind},
|
typecheck::{Collapsable, ErrorKind},
|
||||||
BinaryOperator, TypeKind,
|
BinaryOperator, TypeKind,
|
||||||
@ -15,12 +17,22 @@ pub struct TypeRef<'scope>(TypeIdRef, &'scope ScopeTypeRefs<'scope>);
|
|||||||
impl<'scope> TypeRef<'scope> {
|
impl<'scope> TypeRef<'scope> {
|
||||||
pub unsafe fn resolve_type(&self) -> TypeKind {
|
pub unsafe fn resolve_type(&self) -> TypeKind {
|
||||||
unsafe {
|
unsafe {
|
||||||
self.1
|
let resolved = self
|
||||||
|
.1
|
||||||
.types
|
.types
|
||||||
.hints
|
.hints
|
||||||
.borrow()
|
.borrow()
|
||||||
.get_unchecked(*self.0.borrow())
|
.get_unchecked(*self.0.borrow())
|
||||||
.clone()
|
.clone();
|
||||||
|
|
||||||
|
match resolved {
|
||||||
|
TypeKind::Array(elem_ty, len) => {
|
||||||
|
let resolved_elem_ty = self.1.from_type(&elem_ty).unwrap().resolve_type();
|
||||||
|
dbg!(&elem_ty, &resolved_elem_ty);
|
||||||
|
TypeKind::Array(Box::new(resolved_elem_ty), len)
|
||||||
|
}
|
||||||
|
_ => resolved,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +108,15 @@ impl TypeRefs {
|
|||||||
|
|
||||||
pub fn retrieve_type(&self, idx: usize) -> Option<TypeKind> {
|
pub fn retrieve_type(&self, idx: usize) -> Option<TypeKind> {
|
||||||
let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() };
|
let inner_idx = unsafe { *self.recurse_type_ref(idx).borrow() };
|
||||||
self.hints.borrow().get(inner_idx).cloned()
|
self.hints
|
||||||
|
.borrow()
|
||||||
|
.get(inner_idx)
|
||||||
|
.cloned()
|
||||||
|
.map(|t| match t {
|
||||||
|
TypeKind::Vague(VagueType::TypeRef(id)) => self.retrieve_type(id),
|
||||||
|
_ => Some(t),
|
||||||
|
})
|
||||||
|
.flatten()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user