Make AST contain only abstract Numbers
This commit is contained in:
		
							parent
							
								
									95b3ffe8ef
								
							
						
					
					
						commit
						9b9fcd4ec4
					
				| @ -13,7 +13,7 @@ pub enum TypeKind { | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub enum Literal { | ||||
|     I32(i32), | ||||
|     Number(u64), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
|  | ||||
| @ -58,7 +58,7 @@ impl Parse for PrimaryExpression { | ||||
|                     Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap()) | ||||
|                 } | ||||
|                 Token::DecimalValue(v) => Expression( | ||||
|                     Kind::Literal(Literal::I32(v.parse().unwrap())), | ||||
|                     Kind::Literal(Literal::Number(v.parse().unwrap())), | ||||
|                     stream.get_range().unwrap(), | ||||
|                 ), | ||||
|                 Token::ParenOpen => { | ||||
|  | ||||
| @ -240,7 +240,7 @@ impl ast::BinaryOperator { | ||||
| impl ast::Literal { | ||||
|     fn mir(&self) -> mir::Literal { | ||||
|         match *self { | ||||
|             ast::Literal::I32(v) => mir::Literal::I32(v), | ||||
|             ast::Literal::Number(v) => mir::Literal::Vague(mir::VagueLiteral::Number(v)), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -297,6 +297,7 @@ impl mir::Literal { | ||||
|         InstructionKind::Constant(match *self { | ||||
|             mir::Literal::I32(val) => ConstValue::I32(val), | ||||
|             mir::Literal::I16(val) => ConstValue::I16(val), | ||||
|             mir::Literal::Vague(_) => panic!("Got vague literal!"), | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -53,6 +53,7 @@ pub fn compile(source: &str) -> Result<String, ReidError> { | ||||
|     dbg!(&mir_module); | ||||
| 
 | ||||
|     let state = mir_module.typecheck(); | ||||
|     dbg!(&mir_module); | ||||
|     dbg!(&state); | ||||
|     if !state.errors.is_empty() { | ||||
|         return Err(ReidError::TypeCheckErrors(state.errors)); | ||||
|  | ||||
| @ -51,6 +51,8 @@ pub enum TypeKind { | ||||
| pub enum VagueType { | ||||
|     #[error("Unknown")] | ||||
|     Unknown, | ||||
|     #[error("Number")] | ||||
|     Number, | ||||
| } | ||||
| 
 | ||||
| impl TypeKind { | ||||
| @ -88,6 +90,12 @@ impl TypeKind { | ||||
| pub enum Literal { | ||||
|     I32(i32), | ||||
|     I16(i16), | ||||
|     Vague(VagueLiteral), | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone, Copy)] | ||||
| pub enum VagueLiteral { | ||||
|     Number(u64), | ||||
| } | ||||
| 
 | ||||
| impl Literal { | ||||
| @ -95,6 +103,7 @@ impl Literal { | ||||
|         match self { | ||||
|             Literal::I32(_) => TypeKind::I32, | ||||
|             Literal::I16(_) => TypeKind::I16, | ||||
|             Literal::Vague(VagueLiteral::Number(_)) => TypeKind::Vague(VagueType::Number), | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -175,7 +175,9 @@ impl FunctionDefinition { | ||||
| 
 | ||||
|         let return_type = self.return_type.clone(); | ||||
|         let inferred = match &mut self.kind { | ||||
|             FunctionDefinitionKind::Local(block, _) => block.typecheck(state, scope), | ||||
|             FunctionDefinitionKind::Local(block, _) => { | ||||
|                 block.typecheck(state, scope, Some(return_type), Some(return_type)) | ||||
|             } | ||||
|             FunctionDefinitionKind::Extern => Ok(Vague(Unknown)), | ||||
|         }; | ||||
| 
 | ||||
| @ -188,13 +190,24 @@ impl FunctionDefinition { | ||||
| } | ||||
| 
 | ||||
| impl Block { | ||||
|     fn typecheck(&mut self, state: &mut State, scope: &mut Scope) -> Result<TypeKind, ErrorKind> { | ||||
|     fn typecheck( | ||||
|         &mut self, | ||||
|         state: &mut State, | ||||
|         scope: &mut Scope, | ||||
|         soft_hint: Option<TypeKind>, | ||||
|         hard_hint: Option<TypeKind>, | ||||
|     ) -> Result<TypeKind, ErrorKind> { | ||||
|         let mut scope = scope.inner(); | ||||
| 
 | ||||
|         for statement in &mut self.statements { | ||||
|             match &mut statement.0 { | ||||
|                 StmtKind::Let(variable_reference, expression) => { | ||||
|                     let res = expression.typecheck(state, &mut scope); | ||||
|                     let res = expression.typecheck( | ||||
|                         state, | ||||
|                         &mut scope, | ||||
|                         Some(variable_reference.0), | ||||
|                         hard_hint, | ||||
|                     ); | ||||
| 
 | ||||
|                     // If expression resolution itself was erronous, resolve as
 | ||||
|                     // Unknown.
 | ||||
| @ -224,14 +237,14 @@ impl Block { | ||||
|                 } | ||||
|                 StmtKind::Import(_) => todo!(), | ||||
|                 StmtKind::Expression(expression) => { | ||||
|                     let res = expression.typecheck(state, &mut scope); | ||||
|                     let res = expression.typecheck(state, &mut scope, soft_hint, hard_hint); | ||||
|                     state.ok(res, expression.1); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if let Some((_, expr)) = &mut self.return_expression { | ||||
|             let res = expr.typecheck(state, &mut scope); | ||||
|             let res = expr.typecheck(state, &mut scope, hard_hint, hard_hint); | ||||
|             Ok(state.or_else(res, Vague(Unknown), expr.1)) | ||||
|         } else { | ||||
|             Ok(Void) | ||||
| @ -240,7 +253,13 @@ impl Block { | ||||
| } | ||||
| 
 | ||||
| impl Expression { | ||||
|     fn typecheck(&mut self, state: &mut State, scope: &mut Scope) -> Result<TypeKind, ErrorKind> { | ||||
|     fn typecheck( | ||||
|         &mut self, | ||||
|         state: &mut State, | ||||
|         scope: &mut Scope, | ||||
|         soft_hint: Option<TypeKind>, | ||||
|         hard_hint: Option<TypeKind>, | ||||
|     ) -> Result<TypeKind, ErrorKind> { | ||||
|         match &mut self.0 { | ||||
|             ExprKind::Variable(var_ref) => { | ||||
|                 let existing = state.or_else( | ||||
| @ -262,15 +281,19 @@ impl Expression { | ||||
| 
 | ||||
|                 Ok(var_ref.0) | ||||
|             } | ||||
|             ExprKind::Literal(literal) => Ok(literal.as_type()), | ||||
|             ExprKind::Literal(literal) => { | ||||
|                 *literal = literal.try_coerce(soft_hint)?; | ||||
|                 Ok(literal.as_type()) | ||||
|             } | ||||
|             ExprKind::BinOp(op, lhs, rhs) => { | ||||
|                 // TODO make sure lhs and rhs can actually do this binary
 | ||||
|                 // operation once relevant
 | ||||
|                 let lhs_res = lhs.typecheck(state, scope); | ||||
|                 let rhs_res = rhs.typecheck(state, scope); | ||||
|                 let lhs_res = lhs.typecheck(state, scope, soft_hint, hard_hint); // TODO
 | ||||
|                 let lhs_type = state.or_else(lhs_res, Vague(Unknown), lhs.1); | ||||
|                 let rhs_res = rhs.typecheck(state, scope, Some(lhs_type), hard_hint); // TODO
 | ||||
|                 let rhs_type = state.or_else(rhs_res, Vague(Unknown), rhs.1); | ||||
|                 lhs_type.binop_type(&op, &rhs_type) | ||||
|                 let res = lhs_type.binop_type(&op, &rhs_type)?; | ||||
|                 Ok(res) | ||||
|             } | ||||
|             ExprKind::FunctionCall(function_call) => { | ||||
|                 let true_function = scope | ||||
| @ -289,7 +312,8 @@ impl Expression { | ||||
|                     for (param, true_param_t) in | ||||
|                         function_call.parameters.iter_mut().zip(true_params_iter) | ||||
|                     { | ||||
|                         let param_res = param.typecheck(state, scope); | ||||
|                         let param_res = | ||||
|                             param.typecheck(state, scope, Some(true_param_t), hard_hint); | ||||
|                         let param_t = state.or_else(param_res, Vague(Unknown), param.1); | ||||
|                         state.ok(param_t.collapse_into(&true_param_t), param.1); | ||||
|                     } | ||||
| @ -306,21 +330,39 @@ impl Expression { | ||||
|             } | ||||
|             ExprKind::If(IfExpression(cond, lhs, rhs)) => { | ||||
|                 // TODO make sure cond_res is Boolean here
 | ||||
|                 let cond_res = cond.typecheck(state, scope); | ||||
|                 let cond_res = cond.typecheck(state, scope, Some(Bool), hard_hint); | ||||
|                 let cond_t = state.or_else(cond_res, Vague(Unknown), cond.1); | ||||
|                 state.ok(cond_t.collapse_into(&Bool), cond.1); | ||||
| 
 | ||||
|                 let lhs_res = lhs.typecheck(state, scope); | ||||
|                 let lhs_res = lhs.typecheck(state, scope, soft_hint, hard_hint); | ||||
|                 let lhs_type = state.or_else(lhs_res, Vague(Unknown), lhs.meta); | ||||
|                 let rhs_type = if let Some(rhs) = rhs { | ||||
|                     let res = rhs.typecheck(state, scope); | ||||
|                     let res = rhs.typecheck(state, scope, soft_hint, hard_hint); | ||||
|                     state.or_else(res, Vague(Unknown), rhs.meta) | ||||
|                 } else { | ||||
|                     Vague(Unknown) | ||||
|                 }; | ||||
|                 lhs_type.collapse_into(&rhs_type) | ||||
|             } | ||||
|             ExprKind::Block(block) => block.typecheck(state, scope), | ||||
|             ExprKind::Block(block) => block.typecheck(state, scope, soft_hint, hard_hint), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Literal { | ||||
|     fn try_coerce(self, hint: Option<TypeKind>) -> Result<Self, ErrorKind> { | ||||
|         if let Some(hint) = hint { | ||||
|             use Literal as L; | ||||
|             use VagueLiteral as VagueL; | ||||
|             Ok(match (self, hint) { | ||||
|                 (L::I32(_), I32) => self, | ||||
|                 (L::I16(_), I16) => self, | ||||
|                 (L::Vague(VagueL::Number(v)), I32) => L::I32(v as i32), | ||||
|                 (L::Vague(VagueL::Number(v)), I16) => L::I16(v as i16), | ||||
|                 _ => Err(ErrorKind::TypesIncompatible(self.as_type(), hint))?, | ||||
|             }) | ||||
|         } else { | ||||
|             Ok(self) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user