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