@@ -14,7 +14,9 @@ use plc_ast::{
14
14
use plc_diagnostics:: diagnostics:: Diagnostic ;
15
15
use plc_source:: source_location:: SourceLocation ;
16
16
17
+ use super :: { array:: validate_array_assignment, ValidationContext , Validator , Validators } ;
17
18
use crate :: index:: ImplementationType ;
19
+ use crate :: typesystem:: VOID_TYPE ;
18
20
use crate :: validation:: statement:: helper:: { get_datatype_name_or_slice, get_literal_int_or_const_expr_value} ;
19
21
use crate :: {
20
22
builtins:: { self , BuiltIn } ,
@@ -27,8 +29,6 @@ use crate::{
27
29
} ,
28
30
} ;
29
31
30
- use super :: { array:: validate_array_assignment, ValidationContext , Validator , Validators } ;
31
-
32
32
macro_rules! visit_all_statements {
33
33
( $validator: expr, $context: expr, $last: expr ) => {
34
34
visit_statement( $validator, $last, $context) ;
@@ -777,24 +777,59 @@ fn validate_ref_assignment<T: AnnotationMap>(
777
777
assignment : & Assignment ,
778
778
assignment_location : & SourceLocation ,
779
779
) {
780
- let mut assert_reference = |node : & AstNode | {
781
- if !node. is_reference ( ) {
782
- validator. push_diagnostic (
783
- Diagnostic :: new ( "Invalid assignment, expected a reference" )
784
- . with_location ( & node. location )
785
- . with_error_code ( "E098" ) ,
786
- ) ;
787
- }
788
- } ;
789
-
790
- assert_reference ( & assignment. left ) ;
791
- assert_reference ( & assignment. right ) ;
792
-
793
- // Lastly, assert the type the lhs references matches with the rhs
794
780
let type_lhs = context. annotations . get_type_or_void ( & assignment. left , context. index ) ;
795
781
let type_rhs = context. annotations . get_type_or_void ( & assignment. right , context. index ) ;
796
782
let type_info_lhs = context. index . find_elementary_pointer_type ( type_lhs. get_type_information ( ) ) ;
797
783
let type_info_rhs = context. index . find_elementary_pointer_type ( type_rhs. get_type_information ( ) ) ;
784
+ let annotation_lhs = context. annotations . get ( & assignment. left ) ;
785
+
786
+ // Assert that the right-hand side is a reference
787
+ if !assignment. right . is_reference ( ) {
788
+ validator. push_diagnostic (
789
+ Diagnostic :: new ( "Invalid assignment, expected a reference" )
790
+ . with_location ( & assignment. right . location )
791
+ . with_error_code ( "E098" ) ,
792
+ ) ;
793
+ }
794
+
795
+ // Assert that the left-hand side is a valid pointer-reference
796
+ if !annotation_lhs. is_some_and ( StatementAnnotation :: is_reference_to) && !type_lhs. is_pointer ( ) {
797
+ validator. push_diagnostic (
798
+ Diagnostic :: new ( "Invalid assignment, expected a pointer reference" )
799
+ . with_location ( & assignment. left . location )
800
+ . with_error_code ( "E098" ) ,
801
+ )
802
+ }
803
+
804
+ if type_info_lhs. is_array ( ) && type_info_rhs. is_array ( ) {
805
+ let mut messages = Vec :: new ( ) ;
806
+
807
+ let len_lhs = type_info_lhs. get_array_length ( context. index ) . unwrap_or_default ( ) ;
808
+ let len_rhs = type_info_rhs. get_array_length ( context. index ) . unwrap_or_default ( ) ;
809
+
810
+ if len_lhs < len_rhs {
811
+ messages. push ( format ! ( "Invalid assignment, array lengths {len_lhs} and {len_rhs} differ" ) ) ;
812
+ }
813
+
814
+ let inner_ty_name_lhs = type_info_lhs. get_inner_array_type_name ( ) . unwrap_or ( VOID_TYPE ) ;
815
+ let inner_ty_name_rhs = type_info_rhs. get_inner_array_type_name ( ) . unwrap_or ( VOID_TYPE ) ;
816
+ let inner_ty_lhs = context. index . find_effective_type_by_name ( inner_ty_name_lhs) ;
817
+ let inner_ty_rhs = context. index . find_effective_type_by_name ( inner_ty_name_rhs) ;
818
+
819
+ if inner_ty_lhs != inner_ty_rhs {
820
+ messages. push ( format ! (
821
+ "Invalid assignment, array types {inner_ty_name_lhs} and {inner_ty_name_rhs} differ"
822
+ ) ) ;
823
+ }
824
+
825
+ for message in messages {
826
+ validator. push_diagnostic (
827
+ Diagnostic :: new ( message) . with_location ( assignment_location) . with_error_code ( "E098" ) ,
828
+ )
829
+ }
830
+
831
+ return ;
832
+ }
798
833
799
834
if type_info_lhs != type_info_rhs {
800
835
validator. push_diagnostic (
0 commit comments