diff --git a/src/ast.rs b/src/ast.rs index d4ca7d2f75..b453e1b681 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -160,6 +160,10 @@ impl TypeNature { pub fn is_real(&self) -> bool { self.derives(TypeNature::Real) } + + pub fn is_bit(&self) -> bool { + self.derives(TypeNature::Bit) + } } impl DirectAccessType { diff --git a/src/resolver.rs b/src/resolver.rs index 611f698adb..2636f12ae8 100644 --- a/src/resolver.rs +++ b/src/resolver.rs @@ -898,10 +898,14 @@ impl<'i> TypeAnnotator<'i> { let bigger_type = if l_intrinsic_type.is_bool() && r_intrinsic_type.is_bool() { left_type } else { - let dint = self.index.get_type_or_panic(DINT_TYPE); + let ty = if left_type.is_bit() && right_type.is_bit() { + right_type + } else { + self.index.get_type_or_panic(DINT_TYPE) + }; get_bigger_type( get_bigger_type(left_type, right_type, self.index), - dint, + ty, self.index, ) }; diff --git a/src/resolver/tests/resolve_expressions_tests.rs b/src/resolver/tests/resolve_expressions_tests.rs index e722318cc3..acee32b85d 100644 --- a/src/resolver/tests/resolve_expressions_tests.rs +++ b/src/resolver/tests/resolve_expressions_tests.rs @@ -557,7 +557,7 @@ fn resolve_binary_expressions() { let statements = &unit.implementations[0].statements; let expected_types = vec![ - "DINT", "DINT", "DINT", "LWORD", "DINT", "DINT", "DINT", "DINT", "DINT", "DINT", "LINT", "ULINT", + "BYTE", "WORD", "DWORD", "LWORD", "DINT", "DINT", "DINT", "DINT", "DINT", "DINT", "LINT", "ULINT", ]; let type_names: Vec<&str> = statements.iter().map(|s| annotations.get_type_or_void(s, &index).get_name()).collect(); @@ -805,7 +805,7 @@ fn qualified_expressions_resolve_types() { let (annotations, _) = TypeAnnotator::visit_unit(&index, &unit, id_provider); let statements = &unit.implementations[1].statements; - let expected_types = vec!["BYTE", "WORD", "DWORD", "LWORD", "DINT", "DINT", "LWORD"]; + let expected_types = vec!["BYTE", "WORD", "DWORD", "LWORD", "WORD", "DWORD", "LWORD"]; let type_names: Vec<&str> = statements.iter().map(|s| annotations.get_type_or_void(s, &index).get_name()).collect(); diff --git a/src/typesystem.rs b/src/typesystem.rs index c62c3439bc..d2258ca41b 100644 --- a/src/typesystem.rs +++ b/src/typesystem.rs @@ -138,6 +138,10 @@ impl DataType { self.nature.is_real() } + pub fn is_bit(&self) -> bool { + self.nature.is_bit() + } + /// returns true if this type is an internal, auto-generated type pub fn is_internal(&self) -> bool { self.location.is_internal() diff --git a/src/validation/tests/generic_validation_tests.rs b/src/validation/tests/generic_validation_tests.rs index 506085dcb2..a13fa81023 100644 --- a/src/validation/tests/generic_validation_tests.rs +++ b/src/validation/tests/generic_validation_tests.rs @@ -1118,6 +1118,20 @@ fn any_bit_allows_bits() { FUNCTION func3 : INT VAR x : WORD; END_VAR test(x); END_FUNCTION FUNCTION func4 : INT VAR x : DWORD; END_VAR test(x); END_FUNCTION FUNCTION func5 : INT VAR x : LWORD; END_VAR test(x); END_FUNCTION + // binary expressions + FUNCTION func6 : INT + VAR + a : BOOL; + b : BYTE; + c : WORD; + d : DWORD; + e : LWORD; + END_VAR + test(a + b); + test(d - c); + test(d * d); + test(b + e); + END_FUNCTION "; let diagnostics = parse_and_validate(src);