Fix variable type let inference
This commit is contained in:
		
							parent
							
								
									a7292f4719
								
							
						
					
					
						commit
						22737f022e
					
				| @ -1,6 +1,7 @@ | ||||
| // Main | ||||
| fn main() -> i32 { | ||||
|     return fibonacci(3); | ||||
|     let a = fibonacci(3); | ||||
|     return a; | ||||
| } | ||||
| 
 | ||||
| // Fibonacci | ||||
|  | ||||
| @ -48,7 +48,7 @@ pub fn compile(source: &str) -> Result<String, ReidError> { | ||||
|     }; | ||||
| 
 | ||||
|     dbg!(&ast_module); | ||||
|     let mir_module = ast_module.process(); | ||||
|     let mut mir_module = ast_module.process(); | ||||
| 
 | ||||
|     dbg!(&mir_module); | ||||
| 
 | ||||
|  | ||||
| @ -137,7 +137,7 @@ pub enum Inferred { | ||||
| } | ||||
| 
 | ||||
| impl Module { | ||||
|     pub fn typecheck(&self) -> State { | ||||
|     pub fn typecheck(&mut self) -> State { | ||||
|         let mut state = State::new(); | ||||
|         let mut scope = Scope::default(); | ||||
| 
 | ||||
| @ -154,7 +154,7 @@ impl Module { | ||||
|             ); | ||||
|         } | ||||
| 
 | ||||
|         for function in &self.functions { | ||||
|         for function in &mut self.functions { | ||||
|             let res = function.typecheck(&mut state, &mut scope); | ||||
|             state.ok(res, function.block_meta()); | ||||
|         } | ||||
| @ -164,7 +164,7 @@ impl Module { | ||||
| } | ||||
| 
 | ||||
| impl FunctionDefinition { | ||||
|     fn typecheck(&self, state: &mut State, scope: &mut Scope) -> Result<TypeKind, ErrorKind> { | ||||
|     fn typecheck(&mut self, state: &mut State, scope: &mut Scope) -> Result<TypeKind, ErrorKind> { | ||||
|         for param in &self.parameters { | ||||
|             let param_t = state.or_else(param.1.assert_known(), Vague(Unknown), self.signature()); | ||||
|             state.ok( | ||||
| @ -174,7 +174,7 @@ impl FunctionDefinition { | ||||
|         } | ||||
| 
 | ||||
|         let return_type = self.return_type.clone(); | ||||
|         let inferred = match &self.kind { | ||||
|         let inferred = match &mut self.kind { | ||||
|             FunctionDefinitionKind::Local(block, _) => block.typecheck(state, scope), | ||||
|             FunctionDefinitionKind::Extern => Ok(Vague(Unknown)), | ||||
|         }; | ||||
| @ -188,11 +188,11 @@ impl FunctionDefinition { | ||||
| } | ||||
| 
 | ||||
| impl Block { | ||||
|     fn typecheck(&self, state: &mut State, scope: &mut Scope) -> Result<TypeKind, ErrorKind> { | ||||
|     fn typecheck(&mut self, state: &mut State, scope: &mut Scope) -> Result<TypeKind, ErrorKind> { | ||||
|         let mut scope = scope.inner(); | ||||
| 
 | ||||
|         for statement in &self.statements { | ||||
|             match &statement.0 { | ||||
|         for statement in &mut self.statements { | ||||
|             match &mut statement.0 { | ||||
|                 StmtKind::Let(variable_reference, expression) => { | ||||
|                     let res = expression.typecheck(state, &mut scope); | ||||
| 
 | ||||
| @ -201,12 +201,18 @@ impl Block { | ||||
|                     let res = state.or_else(res, Vague(Unknown), expression.1); | ||||
| 
 | ||||
|                     // Make sure the expression and variable type really is the same
 | ||||
|                     state.ok( | ||||
|                     let res_t = state.or_else( | ||||
|                         res.collapse_into(&variable_reference.0), | ||||
|                         Vague(Unknown), | ||||
|                         variable_reference.2 + expression.1, | ||||
|                     ); | ||||
| 
 | ||||
|                     // TODO make sure expression/variable type is NOT vague anymore
 | ||||
|                     // Make sure expression/variable type is NOT vague anymore
 | ||||
|                     let res_t = | ||||
|                         state.or_else(res_t.assert_known(), Vague(Unknown), variable_reference.2); | ||||
| 
 | ||||
|                     // Update typing to be more accurate
 | ||||
|                     variable_reference.0 = res_t; | ||||
| 
 | ||||
|                     // Variable might already be defined, note error
 | ||||
|                     state.ok( | ||||
| @ -224,7 +230,7 @@ impl Block { | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if let Some((_, expr)) = &self.return_expression { | ||||
|         if let Some((_, expr)) = &mut self.return_expression { | ||||
|             let res = expr.typecheck(state, &mut scope); | ||||
|             Ok(state.or_else(res, Vague(Unknown), expr.1)) | ||||
|         } else { | ||||
| @ -234,8 +240,8 @@ impl Block { | ||||
| } | ||||
| 
 | ||||
| impl Expression { | ||||
|     fn typecheck(&self, state: &mut State, scope: &mut Scope) -> Result<TypeKind, ErrorKind> { | ||||
|         match &self.0 { | ||||
|     fn typecheck(&mut self, state: &mut State, scope: &mut Scope) -> Result<TypeKind, ErrorKind> { | ||||
|         match &mut self.0 { | ||||
|             ExprKind::Variable(var_ref) => { | ||||
|                 let existing = state.or_else( | ||||
|                     scope | ||||
| @ -247,11 +253,14 @@ impl Expression { | ||||
|                     var_ref.2, | ||||
|                 ); | ||||
| 
 | ||||
|                 Ok(state.or_else( | ||||
|                 // Update typing to be more accurate
 | ||||
|                 var_ref.0 = state.or_else( | ||||
|                     var_ref.0.collapse_into(&existing), | ||||
|                     Vague(Unknown), | ||||
|                     var_ref.2, | ||||
|                 )) | ||||
|                 ); | ||||
| 
 | ||||
|                 Ok(var_ref.0) | ||||
|             } | ||||
|             ExprKind::Literal(literal) => Ok(literal.as_type()), | ||||
|             ExprKind::BinOp(op, lhs, rhs) => { | ||||
| @ -261,7 +270,7 @@ impl Expression { | ||||
|                 let rhs_res = rhs.typecheck(state, scope); | ||||
|                 let lhs_type = state.or_else(lhs_res, Vague(Unknown), lhs.1); | ||||
|                 let rhs_type = state.or_else(rhs_res, Vague(Unknown), rhs.1); | ||||
|                 lhs_type.binop_type(op, &rhs_type) | ||||
|                 lhs_type.binop_type(&op, &rhs_type) | ||||
|             } | ||||
|             ExprKind::FunctionCall(function_call) => { | ||||
|                 let true_function = scope | ||||
| @ -278,7 +287,7 @@ impl Expression { | ||||
|                     let true_params_iter = f.params.into_iter().chain(iter::repeat(Vague(Unknown))); | ||||
| 
 | ||||
|                     for (param, true_param_t) in | ||||
|                         function_call.parameters.iter().zip(true_params_iter) | ||||
|                         function_call.parameters.iter_mut().zip(true_params_iter) | ||||
|                     { | ||||
|                         let param_res = param.typecheck(state, scope); | ||||
|                         let param_t = state.or_else(param_res, Vague(Unknown), param.1); | ||||
| @ -287,8 +296,10 @@ impl Expression { | ||||
| 
 | ||||
|                     // Make sure function return type is the same as the claimed
 | ||||
|                     // return type
 | ||||
|                     // TODO: Set return type here actually
 | ||||
|                     try_collapse(&f.ret, &function_call.return_type) | ||||
|                     let ret_t = try_collapse(&f.ret, &function_call.return_type)?; | ||||
|                     // Update typing to be more accurate
 | ||||
|                     function_call.return_type = ret_t; | ||||
|                     Ok(ret_t) | ||||
|                 } else { | ||||
|                     Ok(function_call.return_type) | ||||
|                 } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user