Skip to content

Commit 750d3e5

Browse files
committed
wip init impl
1 parent dcc0be6 commit 750d3e5

File tree

3 files changed

+77
-130
lines changed

3 files changed

+77
-130
lines changed

compiler/plc_driver/src/lib.rs

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -200,9 +200,7 @@ impl<T: SourceContainer> BuildPipeline<T> {
200200
pub fn from_sources(name: &str, src: Vec<T>, diagnostician: Diagnostician) -> Result<Self, Diagnostic> {
201201
// Parse the source to ast
202202
let project = Project::new(name.to_string()).with_sources(src);
203-
let Ok(context) = GlobalContext::new().with_source(project.get_sources(), None) else {
204-
return Err(Diagnostic::new(diagnostician.buffer().unwrap_or_default()));
205-
};
203+
let context = GlobalContext::new().with_source(project.get_sources(), None)?;
206204
let pipeline = BuildPipeline {
207205
context,
208206
project,
@@ -219,15 +217,9 @@ impl<T: SourceContainer> BuildPipeline<T> {
219217
/// Parses, indexes and annotates the project, returning any diagnostics found along the way
220218
/// Used for tests where we don't want to run the full pipeline
221219
pub fn parse_and_annotate(&mut self) -> Result<AnnotatedProject, Diagnostic> {
222-
let Ok(project) = self.parse() else {
223-
return Err(Diagnostic::new(self.diagnostician.buffer().unwrap_or_default()));
224-
};
225-
let Ok(project) = self.index(project) else {
226-
return Err(Diagnostic::new(self.diagnostician.buffer().unwrap_or_default()));
227-
};
228-
let Ok(project) = self.annotate(project) else {
229-
return Err(Diagnostic::new(self.diagnostician.buffer().unwrap_or_default()));
230-
};
220+
let project = self.parse()?;
221+
let project = self.index(project)?;
222+
let project = self.annotate(project)?;
231223
Ok(project)
232224
}
233225
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{"run_id":"1763542345-452133141","line":401,"new":{"module_name":"plc_lowering__initializer__tests","snapshot_name":"programs_are_globals","metadata":{"source":"compiler/plc_lowering/src/initializer.rs","assertion_line":401,"expression":"print_to_string(&initializer.global_constructor)"},"snapshot":"\"\""},"old":{"module_name":"plc_lowering__initializer__tests","metadata":{},"snapshot":""}}
2+
{"run_id":"1763542345-452133141","line":428,"new":{"module_name":"plc_lowering__initializer__tests","snapshot_name":"external_structs_and_variables_are_not_initialized","metadata":{"source":"compiler/plc_lowering/src/initializer.rs","assertion_line":428,"expression":"print_to_string(&initializer.global_constructor)"},"snapshot":"\"\""},"old":{"module_name":"plc_lowering__initializer__tests","metadata":{},"snapshot":""}}
3+
{"run_id":"1763542345-452133141","line":360,"new":{"module_name":"plc_lowering__initializer__tests","snapshot_name":"function_constructors_have_the_function_name","metadata":{"source":"compiler/plc_lowering/src/initializer.rs","assertion_line":360,"expression":"print_body_to_string(initializer.stack_constructor.get(\"MyFunction\").unwrap())"},"snapshot":"\"\""},"old":{"module_name":"plc_lowering__initializer__tests","metadata":{},"snapshot":""}}
4+
{"run_id":"1763542540-898226143","line":362,"new":{"module_name":"plc_lowering__initializer__tests","snapshot_name":"function_constructors_have_the_function_name","metadata":{"source":"compiler/plc_lowering/src/initializer.rs","assertion_line":362,"expression":"print_body_to_string(initializer.stack_constructor.get(\"MyFunction\").unwrap())"},"snapshot":"\"\""},"old":{"module_name":"plc_lowering__initializer__tests","metadata":{},"snapshot":""}}
5+
{"run_id":"1763542540-898226143","line":431,"new":{"module_name":"plc_lowering__initializer__tests","snapshot_name":"external_structs_and_variables_are_not_initialized","metadata":{"source":"compiler/plc_lowering/src/initializer.rs","assertion_line":431,"expression":"print_to_string(&initializer.global_constructor)"},"snapshot":"\"\""},"old":{"module_name":"plc_lowering__initializer__tests","metadata":{},"snapshot":""}}
6+
{"run_id":"1763542540-898226143","line":387,"new":{"module_name":"plc_lowering__initializer__tests","snapshot_name":"program_temp_variables_are_in_stack_constructor","metadata":{"source":"compiler/plc_lowering/src/initializer.rs","assertion_line":387,"expression":"print_body_to_string(initializer.stack_constructor.get(\"MyProgram\").unwrap())"},"snapshot":"\"\""},"old":{"module_name":"plc_lowering__initializer__tests","metadata":{},"snapshot":""}}
7+
{"run_id":"1763542540-898226143","line":340,"new":{"module_name":"plc_lowering__initializer__tests","snapshot_name":"global_constructor_is_generated","metadata":{"source":"compiler/plc_lowering/src/initializer.rs","assertion_line":340,"expression":"print_to_string(&initializer.global_constructor)"},"snapshot":"\"\""},"old":{"module_name":"plc_lowering__initializer__tests","metadata":{},"snapshot":""}}
8+
{"run_id":"1763542540-898226143","line":404,"new":{"module_name":"plc_lowering__initializer__tests","snapshot_name":"programs_are_globals","metadata":{"source":"compiler/plc_lowering/src/initializer.rs","assertion_line":404,"expression":"print_to_string(&initializer.global_constructor)"},"snapshot":"\"\""},"old":{"module_name":"plc_lowering__initializer__tests","metadata":{},"snapshot":""}}

compiler/plc_lowering/src/initializer.rs

Lines changed: 65 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ enum Body {
4040
None,
4141
}
4242

43-
pub struct Initializer<'idx> {
43+
pub struct Initializer {
4444
id_provider: IdProvider,
45-
index: &'idx Index,
45+
index: Index,
4646
/// Stateful constructor per POU/struct
4747
constructors: FxIndexMap<String, Body>,
4848
/// Constructors for temp and stack variables per POU
@@ -52,7 +52,7 @@ pub struct Initializer<'idx> {
5252
}
5353

5454
//TODO: might need to be a mutable ast visitor
55-
impl AstVisitor for Initializer<'_> {
55+
impl AstVisitor for Initializer {
5656
fn visit_pou(&mut self, pou: &plc_ast::ast::Pou) {
5757
match pou.linkage {
5858
plc_ast::ast::LinkageType::External => {
@@ -93,13 +93,25 @@ impl AstVisitor for Initializer<'_> {
9393
self.stack_constructor.insert(pou.name.clone(), Body::Internal(stack_constructor));
9494
}
9595

96-
fn visit_user_type_declaration(&mut self, user_type: &plc_ast::ast::UserTypeDeclaration) {}
96+
fn visit_user_type_declaration(&mut self, user_type: &plc_ast::ast::UserTypeDeclaration) {
97+
match user_type.linkage {
98+
plc_ast::ast::LinkageType::External => {
99+
self.constructors.insert(user_type.name.clone(), Body::External);
100+
return;
101+
}
102+
plc_ast::ast::LinkageType::BuiltIn => {
103+
self.constructors.insert(user_type.name.clone(), Body::None);
104+
return;
105+
}
106+
_ => {}
107+
};
97108

98-
fn visit_variable_block(&mut self, var_block: &plc_ast::ast::VariableBlock) {}
109+
let mut constructor = vec![];
110+
}
99111
}
100112

101-
impl Initializer<'_> {
102-
pub fn new(id_provider: IdProvider, index: &Index) -> Initializer<'_> {
113+
impl Initializer {
114+
pub fn new(id_provider: IdProvider, index: Index) -> Initializer {
103115
Initializer {
104116
id_provider,
105117
index,
@@ -110,9 +122,14 @@ impl Initializer<'_> {
110122
}
111123
}
112124

125+
#[cfg(test)]
113126
mod tests {
114127
use plc_ast::{ast::AstNode, visitor::AstVisitor};
115128
use plc_diagnostics::diagnostician::Diagnostician;
129+
use plc_driver::pipelines::BuildPipeline;
130+
use plc_source::SourceCode;
131+
132+
use crate::initializer::Initializer;
116133

117134
fn print_to_string(nodes: &[AstNode]) -> String {
118135
nodes.iter().map(|it| it.as_string()).collect::<Vec<_>>().join("\n")
@@ -126,6 +143,20 @@ mod tests {
126143
}
127144
}
128145

146+
fn parse_and_init(src: &str) -> Initializer {
147+
let src: SourceCode = src.into();
148+
let diagnostician = Diagnostician::buffered();
149+
let mut pipeline = BuildPipeline::from_sources("test.st", vec![(src)], diagnostician).unwrap();
150+
let mut project = pipeline.parse_and_annotate().unwrap();
151+
// Visit the AST with the Initializer
152+
let mut initializer =
153+
super::Initializer::new(pipeline.context.provider(), std::mem::take(&mut project.index));
154+
for unit in &project.units {
155+
initializer.visit_compilation_unit(unit.get_unit());
156+
}
157+
initializer
158+
}
159+
129160
#[test]
130161
fn struct_gets_imlicit_initializer_and_constructor() {
131162
let src = r#"
@@ -134,18 +165,10 @@ mod tests {
134165
b : REAL := 3.14;
135166
c : BOOL := TRUE;
136167
END_STRUCT
168+
END_TYPE
137169
"#;
138170

139-
let diagnostician = Diagnostician::buffered();
140-
let mut pipeline =
141-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
142-
.unwrap();
143-
let project = pipeline.parse_and_annotate().unwrap();
144-
// Visit the AST with the Initializer
145-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
146-
for unit in &project.units {
147-
initializer.visit_compilation_unit(unit.get_unit());
148-
}
171+
let initializer = parse_and_init(src);
149172
// Expecting a function declaration: void MyStruct_ctor(MyStruct* self)
150173
// Expecting assignments inside the constructor: self->a = 5; self->b = 3.14; self->c = 1;
151174
insta::assert_debug_snapshot!(print_body_to_string(initializer.constructors.get("MyStruct").unwrap()), @r#""#);
@@ -158,23 +181,16 @@ mod tests {
158181
x : INT := 10;
159182
y : INT := 20;
160183
END_STRUCT
184+
END_TYPE
161185
162186
TYPE OuterStruct : STRUCT
163187
inner : InnerStruct;
164188
z : REAL := 2.71;
165189
END_STRUCT
190+
END_TYPE
166191
"#;
167192

168-
let diagnostician = Diagnostician::buffered();
169-
let mut pipeline =
170-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
171-
.unwrap();
172-
let project = pipeline.parse_and_annotate().unwrap();
173-
// Visit the AST with the Initializer
174-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
175-
for unit in &project.units {
176-
initializer.visit_compilation_unit(unit.get_unit());
177-
}
193+
let initializer = parse_and_init(src);
178194
// Check for constructors
179195
// Expecting a function declaration: void InnerStruct_ctor(InnerStruct* self)
180196
// Expecting assignments inside the constructor: self->x = 10; self->y = 20;
@@ -192,24 +208,17 @@ mod tests {
192208
x : INT := 10;
193209
y : INT := 20;
194210
END_STRUCT
211+
END_TYPE
195212
196213
TYPE OuterStruct : STRUCT
197214
inner : InnerStruct := (x := 1, y := 2);
198215
inner2 : InnerStruct := (y := 3);
199216
z : REAL := 2.71;
200217
END_STRUCT
218+
END_TYPE
201219
"#;
202220

203-
let diagnostician = Diagnostician::buffered();
204-
let mut pipeline =
205-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
206-
.unwrap();
207-
let project = pipeline.parse_and_annotate().unwrap();
208-
// Visit the AST with the Initializer
209-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
210-
for unit in &project.units {
211-
initializer.visit_compilation_unit(unit.get_unit());
212-
}
221+
let initializer = parse_and_init(src);
213222
// Check for constructors
214223
// Expecting a function declaration: void InnerStruct_ctor(InnerStruct* self)
215224
// Expecting assignments inside the constructor: self->x = 10; self->y = 20;
@@ -235,18 +244,10 @@ mod tests {
235244
b : POINTER TO INT := ADR(gVar);
236245
c : BOOL := TRUE;
237246
END_STRUCT
247+
END_TYPE
238248
"#;
239249

240-
let diagnostician = Diagnostician::buffered();
241-
let mut pipeline =
242-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
243-
.unwrap();
244-
let project = pipeline.parse_and_annotate().unwrap();
245-
// Visit the AST with the Initializer
246-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
247-
for unit in &project.units {
248-
initializer.visit_compilation_unit(unit.get_unit());
249-
}
250+
let initializer = parse_and_init(src);
250251
// Check for constructor
251252
// Expecting a function declaration: void MyStruct_ctor(MyStruct* self)
252253
// Expecting assignments inside the constructor: self->a = 5; self->c = 1;
@@ -257,23 +258,15 @@ mod tests {
257258
#[test]
258259
fn enum_default_values_in_struct() {
259260
let src = r#"
260-
TYPE MyEnum : (Option1, Option2, Option3) := Option3;
261+
TYPE MyEnum : (Option1, Option2, Option3) := Option3; END_TYPE
261262
TYPE MyStruct : STRUCT
262263
e : MyEnum := Option2;
263264
n : INT := 42;
264265
END_STRUCT
266+
END_TYPE
265267
"#;
266268

267-
let diagnostician = Diagnostician::buffered();
268-
let mut pipeline =
269-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
270-
.unwrap();
271-
let project = pipeline.parse_and_annotate().unwrap();
272-
// Visit the AST with the Initializer
273-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
274-
for unit in &project.units {
275-
initializer.visit_compilation_unit(unit.get_unit());
276-
}
269+
let initializer = parse_and_init(src);
277270
// Expecting a function declaration: void MyEnum_ctor(MyEnum* self)
278271
// Expecting an assignment inside the constructor: *self = 2;
279272
insta::assert_debug_snapshot!(print_body_to_string(initializer.constructors.get("MyEnum").unwrap()), @r#""#);
@@ -295,32 +288,26 @@ mod tests {
295288
a : INT := 1;
296289
b : POINTER TO INT := ADR(gVar);
297290
END_STRUCT
291+
END_TYPE
298292
299293
TYPE InnerStruct2 : STRUCT
300294
c : INT := 4;
301295
d : INT := 5;
302296
inner : InnerStruct := (a := 6);
303297
inner2 : InnerStruct := (b := ADR(gVar));
304298
END_STRUCT
299+
END_TYPE
305300
306301
TYPE OuterStruct : STRUCT
307302
e : INT := 0;
308303
inner : InnerStruct2 := (a := 1, b := 2, inner := (a := 3));
309304
inner2 : InnerStruct2 := (d := 8, inner := (b := ADR(gVar)));
310305
inner3 : InnerStruct2 := (inner (a := 9));
311306
END_STRUCT
307+
END_TYPE
312308
"#;
313309

314-
let diagnostician = Diagnostician::buffered();
315-
let mut pipeline =
316-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
317-
.unwrap();
318-
let project = pipeline.parse_and_annotate().unwrap();
319-
// Visit the AST with the Initializer
320-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
321-
for unit in &project.units {
322-
initializer.visit_compilation_unit(unit.get_unit());
323-
}
310+
let initializer = parse_and_init(src);
324311
// Check for constructors
325312
// Expecting a function declaration: void InnerStruct_ctor(InnerStruct* self)
326313
// Expecting assignments inside the constructor: self->a = 1; self->b = &gVar;
@@ -356,18 +343,10 @@ mod tests {
356343
b : POINTER TO INT := ADR(gVar1);
357344
c : BOOL := TRUE;
358345
END_STRUCT
346+
END_TYPE
359347
"#;
360348

361-
let diagnostician = Diagnostician::buffered();
362-
let mut pipeline =
363-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
364-
.unwrap();
365-
let project = pipeline.parse_and_annotate().unwrap();
366-
// Visit the AST with the Initializer
367-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
368-
for unit in &project.units {
369-
initializer.visit_compilation_unit(unit.get_unit());
370-
}
349+
let initializer = parse_and_init(src);
371350
// Check for global constructor
372351
// Expecting a call to MyStruct_ctor(&gStructVar);
373352
insta::assert_debug_snapshot!(print_to_string(&initializer.global_constructor), @r#""#);
@@ -386,18 +365,10 @@ mod tests {
386365
a : INT := 5;
387366
b : BOOL := TRUE;
388367
END_STRUCT
368+
END_TYPE
389369
"#;
390370

391-
let diagnostician = Diagnostician::buffered();
392-
let mut pipeline =
393-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
394-
.unwrap();
395-
let project = pipeline.parse_and_annotate().unwrap();
396-
// Visit the AST with the Initializer
397-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
398-
for unit in &project.units {
399-
initializer.visit_compilation_unit(unit.get_unit());
400-
}
371+
let initializer = parse_and_init(src);
401372
// Check for function constructor on the stack
402373
// Expecting a call to MyStruct_ctor(&localStruct);
403374
insta::assert_debug_snapshot!(print_body_to_string(initializer.stack_constructor.get("MyFunction").unwrap()), @r#""#);
@@ -413,23 +384,16 @@ mod tests {
413384
VAR
414385
localStruct : MyStruct;
415386
END_VAR
387+
END_PROGRAM
416388
417389
TYPE MyStruct : STRUCT
418390
a : INT := 5;
419391
b : BOOL := TRUE;
420392
END_STRUCT
393+
END_TYPE
421394
"#;
422395

423-
let diagnostician = Diagnostician::buffered();
424-
let mut pipeline =
425-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
426-
.unwrap();
427-
let project = pipeline.parse_and_annotate().unwrap();
428-
// Visit the AST with the Initializer
429-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
430-
for unit in &project.units {
431-
initializer.visit_compilation_unit(unit.get_unit());
432-
}
396+
let initializer = parse_and_init(src);
433397
// Check for program constructor on the stack
434398
// Expecting a call to MyStruct_ctor(&localStruct);
435399
insta::assert_debug_snapshot!(print_body_to_string(initializer.stack_constructor.get("MyProgram").unwrap()), @r#""#);
@@ -446,16 +410,7 @@ mod tests {
446410
END_PROGRAM
447411
"#;
448412

449-
let diagnostician = Diagnostician::buffered();
450-
let mut pipeline =
451-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
452-
.unwrap();
453-
let project = pipeline.parse_and_annotate().unwrap();
454-
// Visit the AST with the Initializer
455-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
456-
for unit in &project.units {
457-
initializer.visit_compilation_unit(unit.get_unit());
458-
}
413+
let initializer = parse_and_init(src);
459414
// Check for program constructor
460415
// Expecting a call to MyProgram_ctor(&progStruct);
461416
insta::assert_debug_snapshot!(print_to_string(&initializer.global_constructor), @r#""#);
@@ -478,18 +433,10 @@ mod tests {
478433
a : INT := 5;
479434
b : BOOL := TRUE;
480435
END_STRUCT
436+
END_TYPE
481437
"#;
482438

483-
let diagnostician = Diagnostician::buffered();
484-
let mut pipeline =
485-
plc_driver::pipelines::BuildPipeline::from_sources("test.st", vec![(src)], diagnostician)
486-
.unwrap();
487-
let project = pipeline.parse_and_annotate().unwrap();
488-
// Visit the AST with the Initializer
489-
let mut initializer = super::Initializer::new(pipeline.context.provider(), &project.index);
490-
for unit in &project.units {
491-
initializer.visit_compilation_unit(unit.get_unit());
492-
}
439+
let initializer = parse_and_init(src);
493440
// Check for internal var assignment in global constructor
494441
// Expecting a call to MyExtStruct_ctor(&internalVar);
495442
// No call to MyExtStruct_ctor(&extVar);

0 commit comments

Comments
 (0)