Fix type-inferrer on arrays
This commit is contained in:
parent
f9f9360efc
commit
a511331be2
@ -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)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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)]
|
||||
|
@ -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
|
||||
|
@ -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>(
|
||||
|
@ -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)>>,
|
||||
|
Loading…
Reference in New Issue
Block a user