Make hint be HintKind and not Option
This commit is contained in:
		
							parent
							
								
									c466b8eb2a
								
							
						
					
					
						commit
						17e8cf4807
					
				| @ -5,7 +5,5 @@ fn main() -> u32 { | |||||||
|   let value = 0b110; |   let value = 0b110; | ||||||
|   let other = 0o17; |   let other = 0o17; | ||||||
| 
 | 
 | ||||||
|   let b = [5.0, 0.0 -5.0]; |   return value * other + 7 * -value; | ||||||
| 
 | } | ||||||
|   return value -1; |  | ||||||
| } |  | ||||||
| @ -78,6 +78,34 @@ pub enum ErrorKind { | |||||||
|     InvalidBinop(BinaryOperator, TypeKind, TypeKind), |     InvalidBinop(BinaryOperator, TypeKind, TypeKind), | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Clone, Debug, PartialEq, Eq)] | ||||||
|  | pub enum HintKind { | ||||||
|  |     Coerce(TypeKind), | ||||||
|  |     Default, | ||||||
|  |     None, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl HintKind { | ||||||
|  |     pub fn map<T>(&self, fun: T) -> HintKind | ||||||
|  |     where | ||||||
|  |         T: FnOnce(&TypeKind) -> TypeKind, | ||||||
|  |     { | ||||||
|  |         match self { | ||||||
|  |             HintKind::Coerce(type_kind) => HintKind::Coerce(fun(type_kind)), | ||||||
|  |             _ => self.clone(), | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | impl From<Option<TypeKind>> for HintKind { | ||||||
|  |     fn from(value: Option<TypeKind>) -> Self { | ||||||
|  |         match value { | ||||||
|  |             Some(ty) => HintKind::Coerce(ty), | ||||||
|  |             None => HintKind::None, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| impl TypeKind { | impl TypeKind { | ||||||
|     pub(super) fn narrow_into(&self, other: &TypeKind) -> Result<TypeKind, ErrorKind> { |     pub(super) fn narrow_into(&self, other: &TypeKind) -> Result<TypeKind, ErrorKind> { | ||||||
|         if self == other { |         if self == other { | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ use VagueType as Vague; | |||||||
| use super::{ | use super::{ | ||||||
|     super::pass::{Pass, PassResult, ScopeVariable}, |     super::pass::{Pass, PassResult, ScopeVariable}, | ||||||
|     typerefs::TypeRefs, |     typerefs::TypeRefs, | ||||||
|     ErrorKind, TypecheckPassState, |     ErrorKind, HintKind, TypecheckPassState, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| /// Struct used to implement a type-checking pass that can be performed on the
 | /// Struct used to implement a type-checking pass that can be performed on the
 | ||||||
| @ -188,7 +188,7 @@ impl FunctionDefinitionKind { | |||||||
|         match self { |         match self { | ||||||
|             FunctionDefinitionKind::Local(block, _) => { |             FunctionDefinitionKind::Local(block, _) => { | ||||||
|                 state.scope.return_type_hint = hint.clone(); |                 state.scope.return_type_hint = hint.clone(); | ||||||
|                 block.typecheck(&mut state.inner(), &typerefs, hint.as_ref()) |                 block.typecheck(&mut state.inner(), &typerefs, hint.into()) | ||||||
|             } |             } | ||||||
|             FunctionDefinitionKind::Extern(_) => Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))), |             FunctionDefinitionKind::Extern(_) => Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))), | ||||||
|             FunctionDefinitionKind::Intrinsic(..) => Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))), |             FunctionDefinitionKind::Intrinsic(..) => Ok((ReturnKind::Soft, TypeKind::Vague(Vague::Unknown))), | ||||||
| @ -201,7 +201,7 @@ impl Block { | |||||||
|         &mut self, |         &mut self, | ||||||
|         state: &mut TypecheckPassState, |         state: &mut TypecheckPassState, | ||||||
|         typerefs: &TypeRefs, |         typerefs: &TypeRefs, | ||||||
|         hint_t: Option<&TypeKind>, |         hint_t: HintKind, | ||||||
|     ) -> Result<(ReturnKind, TypeKind), ErrorKind> { |     ) -> Result<(ReturnKind, TypeKind), ErrorKind> { | ||||||
|         let mut state = state.inner(); |         let mut state = state.inner(); | ||||||
| 
 | 
 | ||||||
| @ -220,7 +220,7 @@ impl Block { | |||||||
|                     dbg!(&var_t_resolved); |                     dbg!(&var_t_resolved); | ||||||
| 
 | 
 | ||||||
|                     // Typecheck (and coerce) expression with said type
 |                     // Typecheck (and coerce) expression with said type
 | ||||||
|                     let res = expression.typecheck(&mut state, &typerefs, Some(&var_t_resolved)); |                     let res = expression.typecheck(&mut state, &typerefs, HintKind::Coerce(var_t_resolved.clone())); | ||||||
|                     // If expression resolution itself was erronous, resolve as
 |                     // If expression resolution itself was erronous, resolve as
 | ||||||
|                     // Unknown and note error.
 |                     // Unknown and note error.
 | ||||||
|                     let res = state.or_else(res, TypeKind::Vague(Vague::Unknown), expression.1); |                     let res = state.or_else(res, TypeKind::Vague(Vague::Unknown), expression.1); | ||||||
| @ -248,7 +248,7 @@ impl Block { | |||||||
|                         ); |                         ); | ||||||
| 
 | 
 | ||||||
|                         // Re-typecheck and coerce expression to default type
 |                         // Re-typecheck and coerce expression to default type
 | ||||||
|                         let expr_res = expression.typecheck(&mut state, &typerefs, Some(&res_t)); |                         let expr_res = expression.typecheck(&mut state, &typerefs, HintKind::Coerce(res_t.clone())); | ||||||
|                         state.ok(expr_res, expression.1); |                         state.ok(expr_res, expression.1); | ||||||
| 
 | 
 | ||||||
|                         res_t |                         res_t | ||||||
| @ -276,13 +276,13 @@ impl Block { | |||||||
|                 } |                 } | ||||||
|                 StmtKind::Set(lhs, rhs) => { |                 StmtKind::Set(lhs, rhs) => { | ||||||
|                     // Typecheck expression and coerce to variable type
 |                     // Typecheck expression and coerce to variable type
 | ||||||
|                     let lhs_res = lhs.typecheck(&mut state, typerefs, None); |                     let lhs_res = lhs.typecheck(&mut state, typerefs, HintKind::Default); | ||||||
|                     // If expression resolution itself was erronous, resolve as
 |                     // If expression resolution itself was erronous, resolve as
 | ||||||
|                     // Unknown.
 |                     // Unknown.
 | ||||||
|                     let lhs_ty = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1); |                     let lhs_ty = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1); | ||||||
| 
 | 
 | ||||||
|                     // Typecheck expression and coerce to variable type
 |                     // Typecheck expression and coerce to variable type
 | ||||||
|                     let res = rhs.typecheck(&mut state, &typerefs, Some(&lhs_ty)); |                     let res = rhs.typecheck(&mut state, &typerefs, HintKind::Coerce(lhs_ty.clone())); | ||||||
| 
 | 
 | ||||||
|                     // If expression resolution itself was erronous, resolve as
 |                     // If expression resolution itself was erronous, resolve as
 | ||||||
|                     // Unknown.
 |                     // Unknown.
 | ||||||
| @ -317,7 +317,7 @@ impl Block { | |||||||
|                 } |                 } | ||||||
|                 StmtKind::Import(_) => todo!(), |                 StmtKind::Import(_) => todo!(), | ||||||
|                 StmtKind::Expression(expression) => { |                 StmtKind::Expression(expression) => { | ||||||
|                     let res = expression.typecheck(&mut state, &typerefs, None); |                     let res = expression.typecheck(&mut state, &typerefs, HintKind::None); | ||||||
|                     state.or_else(res, TypeKind::Void, expression.1); |                     state.or_else(res, TypeKind::Void, expression.1); | ||||||
|                     if let Ok((kind, _)) = expression.return_type(typerefs, state.module_id.unwrap()) { |                     if let Ok((kind, _)) = expression.return_type(typerefs, state.module_id.unwrap()) { | ||||||
|                         Some((kind, expression)) |                         Some((kind, expression)) | ||||||
| @ -326,12 +326,12 @@ impl Block { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 StmtKind::While(WhileStatement { condition, block, meta }) => { |                 StmtKind::While(WhileStatement { condition, block, meta }) => { | ||||||
|                     let condition_ty = condition.typecheck(&mut state, typerefs, Some(&TypeKind::Bool))?; |                     let condition_ty = condition.typecheck(&mut state, typerefs, HintKind::Coerce(TypeKind::Bool))?; | ||||||
|                     if condition_ty.assert_known(typerefs, &state)? != TypeKind::Bool { |                     if condition_ty.assert_known(typerefs, &state)? != TypeKind::Bool { | ||||||
|                         state.note_errors(&vec![ErrorKind::TypesIncompatible(condition_ty, TypeKind::Bool)], *meta); |                         state.note_errors(&vec![ErrorKind::TypesIncompatible(condition_ty, TypeKind::Bool)], *meta); | ||||||
|                     } |                     } | ||||||
| 
 | 
 | ||||||
|                     block.typecheck(&mut state, typerefs, None)?; |                     block.typecheck(&mut state, typerefs, HintKind::None)?; | ||||||
| 
 | 
 | ||||||
|                     None |                     None | ||||||
|                 } |                 } | ||||||
| @ -347,7 +347,7 @@ impl Block { | |||||||
|         // block)
 |         // block)
 | ||||||
|         if let Some((ReturnKind::Hard, expr)) = early_return { |         if let Some((ReturnKind::Hard, expr)) = early_return { | ||||||
|             let hint = state.scope.return_type_hint.clone(); |             let hint = state.scope.return_type_hint.clone(); | ||||||
|             let res = expr.typecheck(&mut state, &typerefs, hint.as_ref()); |             let res = expr.typecheck(&mut state, &typerefs, hint.into()); | ||||||
|             return Ok(( |             return Ok(( | ||||||
|                 ReturnKind::Hard, |                 ReturnKind::Hard, | ||||||
|                 state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1), |                 state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1), | ||||||
| @ -357,11 +357,11 @@ impl Block { | |||||||
|         if let Some((return_kind, expr)) = &mut self.return_expression { |         if let Some((return_kind, expr)) = &mut self.return_expression { | ||||||
|             // Use function return type as hint if return is hard.
 |             // Use function return type as hint if return is hard.
 | ||||||
|             let ret_hint_t = match return_kind { |             let ret_hint_t = match return_kind { | ||||||
|                 ReturnKind::Hard => state.scope.return_type_hint.clone(), |                 ReturnKind::Hard => state.scope.return_type_hint.clone().into(), | ||||||
|                 ReturnKind::Soft => hint_t.cloned(), |                 ReturnKind::Soft => hint_t, | ||||||
|             }; |             }; | ||||||
|             if let Some(expr) = expr { |             if let Some(expr) = expr { | ||||||
|                 let res = expr.typecheck(&mut state, &typerefs, ret_hint_t.as_ref()); |                 let res = expr.typecheck(&mut state, &typerefs, ret_hint_t.into()); | ||||||
|                 Ok(( |                 Ok(( | ||||||
|                     *return_kind, |                     *return_kind, | ||||||
|                     state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1), |                     state.or_else(res, TypeKind::Vague(Vague::Unknown), expr.1), | ||||||
| @ -380,7 +380,7 @@ impl Expression { | |||||||
|         &mut self, |         &mut self, | ||||||
|         state: &mut TypecheckPassState, |         state: &mut TypecheckPassState, | ||||||
|         typerefs: &TypeRefs, |         typerefs: &TypeRefs, | ||||||
|         hint_t: Option<&TypeKind>, |         hint_t: HintKind, | ||||||
|     ) -> Result<TypeKind, ErrorKind> { |     ) -> Result<TypeKind, ErrorKind> { | ||||||
|         match &mut self.0 { |         match &mut self.0 { | ||||||
|             ExprKind::Variable(var_ref) => { |             ExprKind::Variable(var_ref) => { | ||||||
| @ -408,20 +408,20 @@ impl Expression { | |||||||
|                 Ok(var_ref.0.clone()) |                 Ok(var_ref.0.clone()) | ||||||
|             } |             } | ||||||
|             ExprKind::Literal(literal) => { |             ExprKind::Literal(literal) => { | ||||||
|                 *literal = literal.clone().try_coerce(hint_t.cloned())?; |                 *literal = literal.clone().try_coerce(hint_t)?; | ||||||
|                 Ok(literal.as_type()) |                 Ok(literal.as_type()) | ||||||
|             } |             } | ||||||
|             ExprKind::BinOp(op, lhs, rhs, ret_ty) => { |             ExprKind::BinOp(op, lhs, rhs, ret_ty) => { | ||||||
|                 // First find unfiltered parameters to binop
 |                 // First find unfiltered parameters to binop
 | ||||||
|                 let lhs_res = lhs.typecheck(state, &typerefs, None); |                 let lhs_res = lhs.typecheck(state, &typerefs, HintKind::None); | ||||||
|                 let rhs_res = rhs.typecheck(state, &typerefs, None); |                 let rhs_res = rhs.typecheck(state, &typerefs, HintKind::None); | ||||||
|                 let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1); |                 let lhs_type = state.or_else(lhs_res, TypeKind::Vague(Vague::Unknown), lhs.1); | ||||||
|                 let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1); |                 let rhs_type = state.or_else(rhs_res, TypeKind::Vague(Vague::Unknown), rhs.1); | ||||||
| 
 | 
 | ||||||
|                 let mut expected_return_ty = ret_ty.resolve_ref(typerefs); |                 let mut expected_return_ty = ret_ty.resolve_ref(typerefs); | ||||||
|                 if let Some(hint_t) = hint_t { |                 if let HintKind::Coerce(hint_t) = hint_t { | ||||||
|                     expected_return_ty = state.or_else( |                     expected_return_ty = state.or_else( | ||||||
|                         expected_return_ty.narrow_into(hint_t), |                         expected_return_ty.narrow_into(&hint_t), | ||||||
|                         TypeKind::Vague(VagueType::Unknown), |                         TypeKind::Vague(VagueType::Unknown), | ||||||
|                         self.1, |                         self.1, | ||||||
|                     ); |                     ); | ||||||
| @ -437,8 +437,8 @@ impl Expression { | |||||||
|                     .map(|v| (v.1.clone())) |                     .map(|v| (v.1.clone())) | ||||||
|                     .next() |                     .next() | ||||||
|                 { |                 { | ||||||
|                     lhs.typecheck(state, &typerefs, Some(&binop.hands.0))?; |                     lhs.typecheck(state, &typerefs, HintKind::Coerce(binop.hands.0.clone()))?; | ||||||
|                     rhs.typecheck(state, &typerefs, Some(&binop.hands.1))?; |                     rhs.typecheck(state, &typerefs, HintKind::Coerce(binop.hands.1.clone()))?; | ||||||
|                     *ret_ty = binop.narrow(&lhs_type, &rhs_type).unwrap().2; |                     *ret_ty = binop.narrow(&lhs_type, &rhs_type).unwrap().2; | ||||||
|                     Ok(ret_ty.clone()) |                     Ok(ret_ty.clone()) | ||||||
|                 } else { |                 } else { | ||||||
| @ -477,7 +477,7 @@ impl Expression { | |||||||
| 
 | 
 | ||||||
|                     for (param, true_param_t) in function_call.parameters.iter_mut().zip(true_params_iter) { |                     for (param, true_param_t) in function_call.parameters.iter_mut().zip(true_params_iter) { | ||||||
|                         // Typecheck every param separately
 |                         // Typecheck every param separately
 | ||||||
|                         let param_res = param.typecheck(state, &typerefs, Some(&true_param_t)); |                         let param_res = param.typecheck(state, &typerefs, HintKind::Coerce(true_param_t.clone())); | ||||||
|                         let param_t = state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1); |                         let param_t = state.or_else(param_res, TypeKind::Vague(Vague::Unknown), param.1); | ||||||
|                         state.ok(param_t.narrow_into(&true_param_t), param.1); |                         state.ok(param_t.narrow_into(&true_param_t), param.1); | ||||||
|                     } |                     } | ||||||
| @ -493,16 +493,16 @@ impl Expression { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             ExprKind::If(IfExpression(cond, lhs, rhs)) => { |             ExprKind::If(IfExpression(cond, lhs, rhs)) => { | ||||||
|                 let cond_res = cond.typecheck(state, &typerefs, Some(&TypeKind::Bool)); |                 let cond_res = cond.typecheck(state, &typerefs, HintKind::Coerce(TypeKind::Bool)); | ||||||
|                 let cond_t = state.or_else(cond_res, TypeKind::Vague(Vague::Unknown), cond.1); |                 let cond_t = state.or_else(cond_res, TypeKind::Vague(Vague::Unknown), cond.1); | ||||||
|                 state.ok(cond_t.narrow_into(&TypeKind::Bool), cond.1); |                 state.ok(cond_t.narrow_into(&TypeKind::Bool), cond.1); | ||||||
| 
 | 
 | ||||||
|                 // Typecheck then/else return types and make sure they are the
 |                 // Typecheck then/else return types and make sure they are the
 | ||||||
|                 // same, if else exists.
 |                 // same, if else exists.
 | ||||||
|                 let then_res = lhs.typecheck(state, &typerefs, hint_t); |                 let then_res = lhs.typecheck(state, &typerefs, hint_t.clone()); | ||||||
|                 let then_ret_t = state.or_else(then_res, TypeKind::Vague(Vague::Unknown), lhs.1); |                 let then_ret_t = state.or_else(then_res, TypeKind::Vague(Vague::Unknown), lhs.1); | ||||||
|                 let else_ret_t = if let Some(else_expr) = rhs.as_mut() { |                 let else_ret_t = if let Some(else_expr) = rhs.as_mut() { | ||||||
|                     let res = else_expr.typecheck(state, &typerefs, hint_t); |                     let res = else_expr.typecheck(state, &typerefs, hint_t.clone()); | ||||||
|                     let else_ret_t = state.or_else(res, TypeKind::Vague(Vague::Unknown), else_expr.1); |                     let else_ret_t = state.or_else(res, TypeKind::Vague(Vague::Unknown), else_expr.1); | ||||||
| 
 | 
 | ||||||
|                     else_ret_t |                     else_ret_t | ||||||
| @ -520,8 +520,8 @@ impl Expression { | |||||||
|                 if let Some(rhs) = rhs.as_mut() { |                 if let Some(rhs) = rhs.as_mut() { | ||||||
|                     // If rhs existed, typecheck both sides to perform type
 |                     // If rhs existed, typecheck both sides to perform type
 | ||||||
|                     // coercion.
 |                     // coercion.
 | ||||||
|                     let lhs_res = lhs.typecheck(state, &typerefs, Some(&collapsed)); |                     let lhs_res = lhs.typecheck(state, &typerefs, HintKind::Coerce(collapsed.clone())); | ||||||
|                     let rhs_res = rhs.typecheck(state, &typerefs, Some(&collapsed)); |                     let rhs_res = rhs.typecheck(state, &typerefs, HintKind::Coerce(collapsed.clone())); | ||||||
|                     state.ok(lhs_res, lhs.1); |                     state.ok(lhs_res, lhs.1); | ||||||
|                     state.ok(rhs_res, rhs.1); |                     state.ok(rhs_res, rhs.1); | ||||||
|                 } |                 } | ||||||
| @ -536,12 +536,13 @@ impl Expression { | |||||||
|             ExprKind::Indexed(expression, elem_ty, idx_expr) => { |             ExprKind::Indexed(expression, elem_ty, idx_expr) => { | ||||||
|                 // Try to unwrap hint type from array if possible
 |                 // Try to unwrap hint type from array if possible
 | ||||||
|                 let hint_t = hint_t.map(|t| match t { |                 let hint_t = hint_t.map(|t| match t { | ||||||
|                     TypeKind::Array(type_kind, _) => &type_kind, |                     TypeKind::Array(type_kind, _) => *type_kind.clone(), | ||||||
|                     _ => t, |                     _ => t.clone(), | ||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
|                 // Typecheck and narrow index-expression
 |                 // Typecheck and narrow index-expression
 | ||||||
|                 let idx_expr_res = idx_expr.typecheck(state, typerefs, Some(&TypeKind::Vague(VagueType::Integer))); |                 let idx_expr_res = | ||||||
|  |                     idx_expr.typecheck(state, typerefs, HintKind::Coerce(TypeKind::Vague(VagueType::Integer))); | ||||||
|                 state.ok(idx_expr_res, idx_expr.1); |                 state.ok(idx_expr_res, idx_expr.1); | ||||||
| 
 | 
 | ||||||
|                 // TODO it could be possible to check length against constants..
 |                 // TODO it could be possible to check length against constants..
 | ||||||
| @ -563,14 +564,14 @@ impl Expression { | |||||||
|             ExprKind::Array(expressions) => { |             ExprKind::Array(expressions) => { | ||||||
|                 // Try to unwrap hint type from array if possible
 |                 // Try to unwrap hint type from array if possible
 | ||||||
|                 let hint_t = hint_t.map(|t| match t { |                 let hint_t = hint_t.map(|t| match t { | ||||||
|                     TypeKind::Array(type_kind, _) => type_kind, |                     TypeKind::Array(type_kind, _) => *type_kind.clone(), | ||||||
|                     _ => t, |                     _ => t.clone(), | ||||||
|                 }); |                 }); | ||||||
| 
 | 
 | ||||||
|                 let mut expr_result = try_all( |                 let mut expr_result = try_all( | ||||||
|                     expressions |                     expressions | ||||||
|                         .iter_mut() |                         .iter_mut() | ||||||
|                         .map(|e| e.typecheck(state, typerefs, hint_t)) |                         .map(|e| e.typecheck(state, typerefs, hint_t.clone())) | ||||||
|                         .collect(), |                         .collect(), | ||||||
|                 ); |                 ); | ||||||
|                 match &mut expr_result { |                 match &mut expr_result { | ||||||
| @ -599,7 +600,7 @@ impl Expression { | |||||||
|                 let expected_ty = type_kind.resolve_ref(typerefs); |                 let expected_ty = type_kind.resolve_ref(typerefs); | ||||||
| 
 | 
 | ||||||
|                 // Typecheck expression
 |                 // Typecheck expression
 | ||||||
|                 let expr_res = expression.typecheck(state, typerefs, Some(&expected_ty)); |                 let expr_res = expression.typecheck(state, typerefs, HintKind::Coerce(expected_ty.clone())); | ||||||
|                 let expr_ty = state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1); |                 let expr_ty = state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), expression.1); | ||||||
| 
 | 
 | ||||||
|                 if let TypeKind::CustomType(key) = expr_ty { |                 if let TypeKind::CustomType(key) = expr_ty { | ||||||
| @ -642,7 +643,7 @@ impl Expression { | |||||||
|                     ); |                     ); | ||||||
| 
 | 
 | ||||||
|                     // Typecheck the actual expression
 |                     // Typecheck the actual expression
 | ||||||
|                     let expr_res = field_expr.typecheck(state, typerefs, Some(expected_ty)); |                     let expr_res = field_expr.typecheck(state, typerefs, HintKind::Coerce(expected_ty.clone())); | ||||||
|                     let expr_ty = state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), field_expr.1); |                     let expr_ty = state.or_else(expr_res, TypeKind::Vague(Vague::Unknown), field_expr.1); | ||||||
| 
 | 
 | ||||||
|                     // Make sure both are the same type, report error if not
 |                     // Make sure both are the same type, report error if not
 | ||||||
| @ -708,7 +709,7 @@ impl Expression { | |||||||
|                 Ok(*inner) |                 Ok(*inner) | ||||||
|             } |             } | ||||||
|             ExprKind::CastTo(expression, type_kind) => { |             ExprKind::CastTo(expression, type_kind) => { | ||||||
|                 let expr = expression.typecheck(state, typerefs, None)?; |                 let expr = expression.typecheck(state, typerefs, HintKind::Default)?; | ||||||
|                 expr.resolve_ref(typerefs).cast_into(type_kind) |                 expr.resolve_ref(typerefs).cast_into(type_kind) | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -718,11 +719,11 @@ impl Expression { | |||||||
| impl Literal { | impl Literal { | ||||||
|     /// Try to coerce this literal, ie. convert it to a more specific type in
 |     /// Try to coerce this literal, ie. convert it to a more specific type in
 | ||||||
|     /// regards to the given hint if any.
 |     /// regards to the given hint if any.
 | ||||||
|     fn try_coerce(self, hint: Option<TypeKind>) -> Result<Self, ErrorKind> { |     fn try_coerce(self, hint: HintKind) -> Result<Self, ErrorKind> { | ||||||
|         if let Some(hint) = &hint { |         use Literal as L; | ||||||
|             use Literal as L; |         use VagueLiteral as VagueL; | ||||||
|             use VagueLiteral as VagueL; |  | ||||||
| 
 | 
 | ||||||
|  |         if let HintKind::Coerce(hint) = &hint { | ||||||
|             if *hint == self.as_type() { |             if *hint == self.as_type() { | ||||||
|                 return Ok(self); |                 return Ok(self); | ||||||
|             } |             } | ||||||
| @ -757,6 +758,14 @@ impl Literal { | |||||||
|                 (_, TypeKind::Vague(_)) => self, |                 (_, TypeKind::Vague(_)) => self, | ||||||
|                 _ => Err(ErrorKind::LiteralIncompatible(self, hint.clone()))?, |                 _ => Err(ErrorKind::LiteralIncompatible(self, hint.clone()))?, | ||||||
|             }) |             }) | ||||||
|  |         } else if hint == HintKind::Default { | ||||||
|  |             match self { | ||||||
|  |                 Literal::Vague(vague) => match vague { | ||||||
|  |                     VagueLiteral::Number(val) => Ok(L::I32(val as i32)), | ||||||
|  |                     VagueLiteral::Decimal(val) => Ok(L::F32(val as f32)), | ||||||
|  |                 }, | ||||||
|  |                 _ => Ok(self), | ||||||
|  |             } | ||||||
|         } else { |         } else { | ||||||
|             Ok(self) |             Ok(self) | ||||||
|         } |         } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user