slang_frontend/semantic_analysis/operations/
relational.rs1use super::super::traits::SemanticResult;
2use super::helpers::{
3 bool_type, is_unspecified_float_type, is_unspecified_integer_type,
4 operation_type_mismatch_error, types_are_identical,
5};
6use slang_ir::Location;
7use slang_ir::ast::BinaryOperator;
8use slang_shared::CompilationContext;
9use slang_types::TypeId;
10
11use super::super::type_system;
12
13fn is_strictly_relational_operator(operator: &BinaryOperator) -> bool {
21 matches!(
22 operator,
23 BinaryOperator::GreaterThan
24 | BinaryOperator::LessThan
25 | BinaryOperator::GreaterThanOrEqual
26 | BinaryOperator::LessThanOrEqual
27 )
28}
29
30fn can_coerce_for_relational(
40 context: &CompilationContext,
41 left_type: &TypeId,
42 right_type: &TypeId,
43) -> bool {
44 (is_unspecified_integer_type(left_type) && type_system::is_integer_type(context, right_type))
45 || (is_unspecified_integer_type(right_type)
46 && type_system::is_integer_type(context, left_type))
47 || (is_unspecified_float_type(left_type) && type_system::is_float_type(context, right_type))
48 || (is_unspecified_float_type(right_type) && type_system::is_float_type(context, left_type))
49}
50
51pub fn check_relational_operation(
68 context: &CompilationContext,
69 left_type: &TypeId,
70 right_type: &TypeId,
71 operator: &BinaryOperator,
72 location: &Location,
73) -> SemanticResult {
74 if is_strictly_relational_operator(operator)
76 && (!context.is_numeric_type(left_type) || !context.is_numeric_type(right_type))
77 {
78 return Err(operation_type_mismatch_error(
79 &operator.to_string(),
80 left_type,
81 right_type,
82 location,
83 ));
84 }
85
86 if (types_are_identical(left_type, right_type) && *left_type != TypeId::unit())
88 || can_coerce_for_relational(context, left_type, right_type)
89 {
90 Ok(bool_type())
91 } else {
92 Err(operation_type_mismatch_error(
93 &operator.to_string(),
94 left_type,
95 right_type,
96 location,
97 ))
98 }
99}