2727use plc:: index:: { FxIndexMap , Index } ;
2828use plc_ast:: { ast:: AstNode , visitor:: AstVisitor } ;
2929
30+ #[ derive( Debug ) ]
3031enum Body {
3132 Internal ( Vec < AstNode > ) ,
3233 External ,
@@ -44,12 +45,6 @@ pub struct Initializer<'idx> {
4445impl AstVisitor for Initializer < ' _ > {
4546 fn visit_compilation_unit ( & mut self , unit : & plc_ast:: ast:: CompilationUnit ) {
4647 // Read all structs and POU structs, collect their implicit initializers if available
47- unit. pous . iter ( ) . for_each ( |pou| {
48- // find the pou index entry
49- if let Some ( pie) = self . index . find_pou_type ( & pou. name ) {
50- pie. initial_value
51- }
52- } ) ;
5348 // Add a call to the constructor to memcpy the imlicit initializer
5449 // For each of the call statement or reference in the pou initializer, add an assignment to
5550 // the constructor
@@ -68,14 +63,121 @@ impl Initializer<'_> {
6863}
6964
7065mod tests {
66+ use plc_ast:: visitor:: AstVisitor ;
67+ use plc_diagnostics:: diagnostician:: Diagnostician ;
68+
7169 #[ test]
72- fn struct_gets_imlicit_initializer_and_constructor ( ) { }
70+ fn struct_gets_imlicit_initializer_and_constructor ( ) {
71+ let src = r#"
72+ TYPE MyStruct : STRUCT
73+ a : INT := 5;
74+ b : REAL := 3.14;
75+ c : BOOL := TRUE;
76+ END_STRUCT
77+ "# ;
78+
79+ let diagnostician = Diagnostician :: buffered ( ) ;
80+ let mut pipeline =
81+ plc_driver:: pipelines:: BuildPipeline :: from_sources ( "test.st" , vec ! [ ( src) ] , diagnostician)
82+ . unwrap ( ) ;
83+ let project = pipeline. parse_and_annotate ( ) . unwrap ( ) ;
84+ // Visit the AST with the Initializer
85+ let mut initializer = super :: Initializer :: new ( & project. index ) ;
86+ for unit in & project. units {
87+ initializer. visit_compilation_unit ( unit. get_unit ( ) ) ;
88+ }
89+ // Check for implicit initializer
90+ // Expecting a variable declaration: MyStruct MyStruct_init = {5, 3.14, TRUE};
91+ insta:: assert_debug_snapshot!( initializer. implicit_initializers. get( "MyStruct" ) , @r#""# ) ;
92+ // Check for an empty constructor
93+ // Expecting a function declaration: void MyStruct_ctor(MyStruct* self)
94+ // Expecting a call to memcpy inside the constructor: memcpy(self, &MyStruct_init,
95+ // sizeof(MyStruct));
96+ insta:: assert_debug_snapshot!( initializer. constructors. get( "MyStruct" ) , @r#""# ) ;
97+ }
7398
7499 #[ test]
75- fn struct_gets_constructor ( ) { }
100+ fn nested_structs_get_initializers_and_constructors ( ) {
101+ let src = r#"
102+ TYPE InnerStruct : STRUCT
103+ x : INT := 10;
104+ y : INT := 20;
105+ END_STRUCT
106+
107+ TYPE OuterStruct : STRUCT
108+ inner : InnerStruct;
109+ z : REAL := 2.71;
110+ END_STRUCT
111+ "# ;
112+
113+ let diagnostician = Diagnostician :: buffered ( ) ;
114+ let mut pipeline =
115+ plc_driver:: pipelines:: BuildPipeline :: from_sources ( "test.st" , vec ! [ ( src) ] , diagnostician)
116+ . unwrap ( ) ;
117+ let project = pipeline. parse_and_annotate ( ) . unwrap ( ) ;
118+ // Visit the AST with the Initializer
119+ let mut initializer = super :: Initializer :: new ( & project. index ) ;
120+ for unit in & project. units {
121+ initializer. visit_compilation_unit ( unit. get_unit ( ) ) ;
122+ }
123+ // Check for implicit initializers
124+ // Expecting a variable declaration: InnerStruct InnerStruct_init = {10, 20};
125+ insta:: assert_debug_snapshot!( initializer. implicit_initializers. get( "InnerStruct" ) , @r#""# ) ;
126+ // Expecting a variable declaration: OuterStruct OuterStruct_init = {0, 0, 2.71};
127+ insta:: assert_debug_snapshot!( initializer. implicit_initializers. get( "OuterStruct" ) , @r#""# ) ;
128+ // Check for constructors
129+ // Expecting a function declaration: void InnerStruct_ctor(InnerStruct* self)
130+ // Expecting a call to memcpy inside the constructor: memcpy(self, &InnerStruct_init,
131+ // sizeof(InnerStruct));
132+ insta:: assert_debug_snapshot!( initializer. constructors. get( "InnerStruct" ) , @r#""# ) ;
133+ // Expecting a function declaration: void OuterStruct_ctor(OuterStruct* self)
134+ // Expecting a call to memcpy inside the constructor: memcpy(self, &OuterStruct_init,
135+ // sizeof(OuterStruct));
136+ // Expecting a call to InnerStruct_ctor(&self->inner);
137+ insta:: assert_debug_snapshot!( initializer. constructors. get( "OuterStruct" ) , @r#""# ) ;
138+ }
76139
77140 #[ test]
78- fn nested_structs_get_initializers_and_constructors ( ) { }
141+ fn nested_structs_with_values_get_initializers_and_constructors ( ) {
142+ let src = r#"
143+ TYPE InnerStruct : STRUCT
144+ x : INT := 10;
145+ y : INT := 20;
146+ END_STRUCT
147+
148+ TYPE OuterStruct : STRUCT
149+ inner : InnerStruct := (x := 1, y := 2);
150+ z : REAL := 2.71;
151+ END_STRUCT
152+ "# ;
153+
154+ let diagnostician = Diagnostician :: buffered ( ) ;
155+ let mut pipeline =
156+ plc_driver:: pipelines:: BuildPipeline :: from_sources ( "test.st" , vec ! [ ( src) ] , diagnostician)
157+ . unwrap ( ) ;
158+ let project = pipeline. parse_and_annotate ( ) . unwrap ( ) ;
159+ // Visit the AST with the Initializer
160+ let mut initializer = super :: Initializer :: new ( & project. index ) ;
161+ for unit in & project. units {
162+ initializer. visit_compilation_unit ( unit. get_unit ( ) ) ;
163+ }
164+ // Check for implicit initializers
165+ // Expecting a variable declaration: InnerStruct InnerStruct_init = {10, 20};
166+ insta:: assert_debug_snapshot!( initializer. implicit_initializers. get( "InnerStruct" ) , @r#""# ) ;
167+ // Expecting a variable declaration: OuterStruct OuterStruct_init = {1, 2, 2.71};
168+ insta:: assert_debug_snapshot!( initializer. implicit_initializers. get( "OuterStruct" ) , @r#""# ) ;
169+ // Check for constructors
170+ // Expecting a function declaration: void InnerStruct_ctor(InnerStruct* self)
171+ // Expecting a call to memcpy inside the constructor: memcpy(self, &InnerStruct_init,
172+ // sizeof(InnerStruct));
173+ insta:: assert_debug_snapshot!( initializer. constructors. get( "InnerStruct" ) , @r#""# ) ;
174+ // Expecting a function declaration: void OuterStruct_ctor(OuterStruct* self)
175+ // Expecting a call to memcpy inside the constructor: memcpy(self, &OuterStruct_init,
176+ // sizeof(OuterStruct));
177+ // TODO: how do we prevent this from overriding the set values?
178+ // Expecting a call to InnerStruct_ctor(&self->inner);
179+ insta:: assert_debug_snapshot!( initializer. constructors. get( "OuterStruct" ) , @r#""# ) ;
180+ }
79181
80182 #[ test]
81183 fn variable_with_pointer_initializer_is_added_to_constructor ( ) { }
0 commit comments