From 2a9d87ec36afef5c2c1d299befd20fba5d8af2c7 Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Thu, 2 May 2024 15:58:48 -0700 Subject: [PATCH 01/10] add test case for a failing syntax --- blark/tests/source/repeated_declaration.st | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 blark/tests/source/repeated_declaration.st diff --git a/blark/tests/source/repeated_declaration.st b/blark/tests/source/repeated_declaration.st new file mode 100644 index 0000000..a394714 --- /dev/null +++ b/blark/tests/source/repeated_declaration.st @@ -0,0 +1,7 @@ +METHOD doSomethingCool : BOOL +VAR_INPUT + AlertTimer, SignalBadTimer, QualityBadTimer : library.TPUDO; +END_VAR + +// do some stuff +END_METHOD From efd3a57afa475229f53ae9eddabdb75efb794dde Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Thu, 2 May 2024 16:19:58 -0700 Subject: [PATCH 02/10] added a test, added some sample code for debugging --- blark/iec.lark | 2 +- blark/tests/source/repeated_declaration.st | 2 +- blark/tests/test_transformer.py | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/blark/iec.lark b/blark/iec.lark index 413538a..7fedff4 100644 --- a/blark/iec.lark +++ b/blark/iec.lark @@ -280,7 +280,7 @@ _type_declaration: array_type_declaration | subrange_type_declaration | enumerated_type_declaration -simple_type_declaration: simple_type_name [ extends ] ":" simple_spec_init +simple_type_declaration: simple_type_name ("," simple_type_name)* [ extends ] ":" simple_spec_init indirection_type: REFERENCE_TO | POINTER_TO+ diff --git a/blark/tests/source/repeated_declaration.st b/blark/tests/source/repeated_declaration.st index a394714..e83f295 100644 --- a/blark/tests/source/repeated_declaration.st +++ b/blark/tests/source/repeated_declaration.st @@ -1,6 +1,6 @@ METHOD doSomethingCool : BOOL VAR_INPUT - AlertTimer, SignalBadTimer, QualityBadTimer : library.TPUDO; + AlertTimer, SignalBadTimer : library.TPUDO; END_VAR // do some stuff diff --git a/blark/tests/test_transformer.py b/blark/tests/test_transformer.py index 2712d28..e517c87 100644 --- a/blark/tests/test_transformer.py +++ b/blark/tests/test_transformer.py @@ -362,6 +362,7 @@ def test_bool_literal_roundtrip(name, value, expected): param("expression", "_directoryFileList.Item(_i).ToString()"), param("expression", "_directoryFileList.Item(_i)^.ToString()"), param("simple_type_declaration", "TypeName : INT"), + param("simple_type_declaration", "TypeName, TypeName2 : INT"), param("simple_type_declaration", "TypeName : INT := 5"), param("simple_type_declaration", "TypeName : INT := 5 + 1 * (2)"), param("simple_type_declaration", "TypeName : REFERENCE TO INT"), From bc08ff9d3ed37cd86556b1ceee104dce17cd16d2 Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Fri, 3 May 2024 10:39:48 -0700 Subject: [PATCH 03/10] reverted incorrect change --- blark/iec.lark | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blark/iec.lark b/blark/iec.lark index 7fedff4..413538a 100644 --- a/blark/iec.lark +++ b/blark/iec.lark @@ -280,7 +280,7 @@ _type_declaration: array_type_declaration | subrange_type_declaration | enumerated_type_declaration -simple_type_declaration: simple_type_name ("," simple_type_name)* [ extends ] ":" simple_spec_init +simple_type_declaration: simple_type_name [ extends ] ":" simple_spec_init indirection_type: REFERENCE_TO | POINTER_TO+ From e28711d4471cecb98db784f28d8ea064c9109ffc Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Fri, 3 May 2024 11:16:46 -0700 Subject: [PATCH 04/10] revision --- blark/iec.lark | 2 +- blark/tests/source/repeated_declaration.st | 12 +++++------- blark/tests/test_transformer.py | 1 - 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/blark/iec.lark b/blark/iec.lark index 413538a..fcd27aa 100644 --- a/blark/iec.lark +++ b/blark/iec.lark @@ -350,7 +350,7 @@ structure_type_declaration: structure_type_name_declaration [ extends ] ":" [ in initialized_structure: structure_type_name ":=" structure_initialization -structure_element_declaration: structure_element_name [ incomplete_location ] ":" ( initialized_structure | array_spec_init | simple_spec_init | subrange_spec_init | enumerated_spec_init | function_call ) +structure_element_declaration: var1_list ":" ( initialized_structure | array_spec_init | simple_spec_init | subrange_spec_init | enumerated_spec_init | function_call ) union_element_declaration: structure_element_name ":" ( array_specification | simple_specification | indirect_simple_specification | subrange_specification | enumerated_specification ) diff --git a/blark/tests/source/repeated_declaration.st b/blark/tests/source/repeated_declaration.st index e83f295..4981b61 100644 --- a/blark/tests/source/repeated_declaration.st +++ b/blark/tests/source/repeated_declaration.st @@ -1,7 +1,5 @@ -METHOD doSomethingCool : BOOL -VAR_INPUT - AlertTimer, SignalBadTimer : library.TPUDO; -END_VAR - -// do some stuff -END_METHOD +TYPE someStruct : +STRUCT + AlertTimer, SignalBadTimer, QualityBadTimer : library.TPUDO; +END_STRUCT +END_TYPE diff --git a/blark/tests/test_transformer.py b/blark/tests/test_transformer.py index e517c87..2712d28 100644 --- a/blark/tests/test_transformer.py +++ b/blark/tests/test_transformer.py @@ -362,7 +362,6 @@ def test_bool_literal_roundtrip(name, value, expected): param("expression", "_directoryFileList.Item(_i).ToString()"), param("expression", "_directoryFileList.Item(_i)^.ToString()"), param("simple_type_declaration", "TypeName : INT"), - param("simple_type_declaration", "TypeName, TypeName2 : INT"), param("simple_type_declaration", "TypeName : INT := 5"), param("simple_type_declaration", "TypeName : INT := 5 + 1 * (2)"), param("simple_type_declaration", "TypeName : REFERENCE TO INT"), From 6a6c10a8d8c6b51ed40effb81be6e0c6ab32c1fb Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Fri, 3 May 2024 12:42:51 -0700 Subject: [PATCH 05/10] added a comment --- blark/iec.lark | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/blark/iec.lark b/blark/iec.lark index fcd27aa..93c7954 100644 --- a/blark/iec.lark +++ b/blark/iec.lark @@ -350,7 +350,8 @@ structure_type_declaration: structure_type_name_declaration [ extends ] ":" [ in initialized_structure: structure_type_name ":=" structure_initialization -structure_element_declaration: var1_list ":" ( initialized_structure | array_spec_init | simple_spec_init | subrange_spec_init | enumerated_spec_init | function_call ) +// I think we need to have var1_list used, here -- need to play around with that some more +structure_element_declaration: structure_element_name [ incomplete_location ] ":" ( initialized_structure | array_spec_init | simple_spec_init | subrange_spec_init | enumerated_spec_init | function_call ) union_element_declaration: structure_element_name ":" ( array_specification | simple_specification | indirect_simple_specification | subrange_specification | enumerated_specification ) From a0d67bbdbd8eab332cef83e42f14f7d6d0360506 Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Mon, 6 May 2024 10:50:24 -0700 Subject: [PATCH 06/10] further exploration and troubleshooting --- blark/iec.lark | 6 +++++- blark/transform.py | 12 +++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/blark/iec.lark b/blark/iec.lark index 93c7954..70b35f2 100644 --- a/blark/iec.lark +++ b/blark/iec.lark @@ -351,7 +351,11 @@ structure_type_declaration: structure_type_name_declaration [ extends ] ":" [ in initialized_structure: structure_type_name ":=" structure_initialization // I think we need to have var1_list used, here -- need to play around with that some more -structure_element_declaration: structure_element_name [ incomplete_location ] ":" ( initialized_structure | array_spec_init | simple_spec_init | subrange_spec_init | enumerated_spec_init | function_call ) +structure_element_declaration: struct_var1_list ":" ( initialized_structure | array_spec_init | simple_spec_init | subrange_spec_init | enumerated_spec_init | function_call ) + +_struct_var1: structure_element_name [ incomplete_location ] + +struct_var1_list: _struct_var1 ( "," _struct_var1 )* union_element_declaration: structure_element_name ":" ( array_specification | simple_specification | indirect_simple_specification | subrange_specification | enumerated_specification ) diff --git a/blark/transform.py b/blark/transform.py index 5d05c2e..a9c420d 100644 --- a/blark/transform.py +++ b/blark/transform.py @@ -1954,8 +1954,7 @@ class StructureElementDeclaration: iValue1 AT %I* : INT := 5; sValue1 : STRING[10] := 'test'; """ - name: lark.Token - location: Optional[IncompleteLocation] + variables: List[DeclaredVariable] init: Union[ StructureInitialization, ArrayTypeInitialization, @@ -1968,11 +1967,6 @@ class StructureElementDeclaration: ] meta: Optional[Meta] = meta_field() - @property - def variables(self) -> List[str]: - """API compat: list of variable names.""" - return [self.name] - @property def value(self) -> str: """The initialization value, if applicable.""" @@ -4585,6 +4579,10 @@ def full_subrange(self): def var1_list(self, *items: DeclaredVariable) -> List[DeclaredVariable]: return list(items) + @_annotator_method_wrapper + def struct_var1_list(self, *items: DeclaredVariable) -> List[DeclaredVariable]: + return list(items) + @_annotator_method_wrapper def fb_decl_name_list(self, *items: lark.Token) -> List[lark.Token]: return list(items) From a8f423d461104119e85c0fdb1ad8c735bdfb937f Mon Sep 17 00:00:00 2001 From: Ken Lauer <5139267+klauer@users.noreply.github.com> Date: Sat, 25 Jan 2025 11:17:18 -0800 Subject: [PATCH 07/10] MAINT: use var1_list as Joe's comment suggested --- blark/iec.lark | 7 +------ blark/summary.py | 25 +++++++++++++------------ blark/transform.py | 4 ++-- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/blark/iec.lark b/blark/iec.lark index 0b106a4..90808d5 100644 --- a/blark/iec.lark +++ b/blark/iec.lark @@ -350,12 +350,7 @@ structure_type_declaration: structure_type_name_declaration [ extends ] ":" [ in initialized_structure: structure_type_name ":=" structure_initialization -// I think we need to have var1_list used, here -- need to play around with that some more -structure_element_declaration: struct_var1_list ":" ( initialized_structure | array_spec_init | simple_spec_init | subrange_spec_init | enumerated_spec_init | function_call ) - -_struct_var1: structure_element_name [ incomplete_location ] - -struct_var1_list: _struct_var1 ( "," _struct_var1 )* +structure_element_declaration: var1_list ":" ( initialized_structure | array_spec_init | simple_spec_init | subrange_spec_init | enumerated_spec_init | function_call ) union_element_declaration: structure_element_name ":" ( array_specification | simple_specification | indirect_simple_specification | subrange_specification | enumerated_specification ) diff --git a/blark/summary.py b/blark/summary.py index 2b15285..f95abe8 100644 --- a/blark/summary.py +++ b/blark/summary.py @@ -174,18 +174,19 @@ def from_declaration( result = {} if isinstance(item, tf.StructureElementDeclaration): - result[item.name] = DeclarationSummary( - name=str(item.name), - item=item, - location=item.location.name if item.location else None, - block=block_header, - type=item.full_type_name, # TODO -> get_type_summary? - base_type=item.base_type_name, - value=str(item.value), - parent=parent.name if parent is not None else "", - filename=filename, - **Summary.get_meta_kwargs(item.meta), - ) + for var in item.variables: + result[var.name] = DeclarationSummary( + name=str(var.name), + item=item, + location=str(var.location) if var.location else None, + block=block_header, + type=item.full_type_name, # TODO -> get_type_summary? + base_type=item.base_type_name, + value=str(item.value), + parent=parent.name if parent is not None else "", + filename=filename, + **Summary.get_meta_kwargs(item.meta), + ) elif isinstance(item, tf.UnionElementDeclaration): result[item.name] = DeclarationSummary( name=str(item.name), diff --git a/blark/transform.py b/blark/transform.py index a9c420d..ce79e71 100644 --- a/blark/transform.py +++ b/blark/transform.py @@ -1989,8 +1989,8 @@ def full_type_name(self) -> lark.Token: return self.init.full_type_name def __str__(self) -> str: - name_and_location = join_if(self.name, " ", self.location) - return f"{name_and_location} : {self.init};" + variables = ", ".join(str(var) for var in self.variables) + return f"{variables} : {self.init};" UnionElementSpecification = Union[ From d22c674956997b71b9d8ca90dcd113e4d55565ef Mon Sep 17 00:00:00 2001 From: Ken Lauer <5139267+klauer@users.noreply.github.com> Date: Sat, 25 Jan 2025 11:45:50 -0800 Subject: [PATCH 08/10] FIX: InitializedStructure is correct, not StructureInitialization --- blark/transform.py | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/blark/transform.py b/blark/transform.py index ce79e71..df7b5c5 100644 --- a/blark/transform.py +++ b/blark/transform.py @@ -1924,7 +1924,7 @@ def __str__(self) -> str: body = "\n".join( ( "STRUCT", - indent("\n".join(str(decl) for decl in self.declarations)), + indent("\n".join(f"{decl};" for decl in self.declarations)), "END_STRUCT", ) ) @@ -1940,23 +1940,25 @@ def __str__(self) -> str: @_rule_handler("structure_element_declaration", comments=True) class StructureElementDeclaration: """ - Declaration of a single element of a structure. + Declaration line of a structure, typically with a single variable name. + + Excludes the trailing semicolon. Examples:: - iValue : INT := 3 + 4; - stTest : ST_Testing := (1, 2); - eValue : E_Test := E_Test.ABC; - arrValue : ARRAY [1..2] OF INT := [1, 2]; - arrValue1 : INT (1..2); - arrValue1 : (Value1 := 1) INT; - sValue : STRING := 'abc'; - iValue1 AT %I* : INT := 5; - sValue1 : STRING[10] := 'test'; + iValue : INT := 3 + 4 + stTest : ST_Testing := (1, 2) + eValue : E_Test := E_Test.ABC + arrValue : ARRAY [1..2] OF INT := [1, 2] + arrValue1 : INT (1..2) + arrValue1 : (Value1 := 1) INT + sValue : STRING := 'abc' + iValue1 AT %I* : INT := 5 + sValue1 : STRING[10] := 'test' + Timer1, Timer2, Timer3 : library.TPUDO """ variables: List[DeclaredVariable] init: Union[ - StructureInitialization, ArrayTypeInitialization, StringTypeInitialization, TypeInitialization, @@ -1970,27 +1972,21 @@ class StructureElementDeclaration: @property def value(self) -> str: """The initialization value, if applicable.""" - if isinstance(self.init, StructureInitialization): - return str(self.init) return str(self.init.value) @property def base_type_name(self) -> Union[lark.Token, str]: """The base type name.""" - if isinstance(self.init, StructureInitialization): - return self.name return self.init.base_type_name @property - def full_type_name(self) -> lark.Token: + def full_type_name(self) -> Union[lark.Token, str]: """The full type name.""" - if isinstance(self.init, StructureInitialization): - return self.name return self.init.full_type_name def __str__(self) -> str: variables = ", ".join(str(var) for var in self.variables) - return f"{variables} : {self.init};" + return f"{variables} : {self.init}" UnionElementSpecification = Union[ From ab95d4ad709a6e46c4b5518bdc5951a270020c6c Mon Sep 17 00:00:00 2001 From: Ken Lauer <5139267+klauer@users.noreply.github.com> Date: Sat, 25 Jan 2025 11:54:02 -0800 Subject: [PATCH 09/10] FIX: summary location '%I*' is probably better than 'input' --- blark/summary.py | 2 +- blark/tests/test_summary.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/blark/summary.py b/blark/summary.py index f95abe8..b66dace 100644 --- a/blark/summary.py +++ b/blark/summary.py @@ -178,7 +178,7 @@ def from_declaration( result[var.name] = DeclarationSummary( name=str(var.name), item=item, - location=str(var.location) if var.location else None, + location=str(var.location).replace("AT ", "") if var.location else None, block=block_header, type=item.full_type_name, # TODO -> get_type_summary? base_type=item.base_type_name, diff --git a/blark/tests/test_summary.py b/blark/tests/test_summary.py index 46ddb47..4f0b849 100644 --- a/blark/tests/test_summary.py +++ b/blark/tests/test_summary.py @@ -237,7 +237,7 @@ def test_twincat_general(twincat_general_281: PlcProjectMetadata): DeclarationCheck( name="I_EcatMaster1", base_type="AMSNETID", - location="input", + location="%I*", comments=[ "{attribute 'naming' := 'omit'}", "(* AMS Net ID used for FB_EcatDiag, among others *)" From cbbbf7cc456ae7f339523257b8deb5788d26a18d Mon Sep 17 00:00:00 2001 From: Ken Lauer <5139267+klauer@users.noreply.github.com> Date: Wed, 29 Jan 2025 17:30:19 -0800 Subject: [PATCH 10/10] TST: explicitly cover repeated structure type definition --- blark/tests/test_transformer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/blark/tests/test_transformer.py b/blark/tests/test_transformer.py index f64bfbd..33ff4ee 100644 --- a/blark/tests/test_transformer.py +++ b/blark/tests/test_transformer.py @@ -392,6 +392,7 @@ def test_bool_literal_roundtrip(name, value, expected): param("var1_init_decl", "stVar1, stVar2 : TypeName := Value"), param("var1_init_decl", "stVar1, stVar2 : (Value1 := 1, Value2 := 2)"), param("var1_init_decl", "stVar1, stVar2 : (Value1 := 1, Value2 := 2) INT := Value1"), + param("structure_element_declaration", "Name1, Name2 : INT"), param("structure_type_declaration", "TypeName :\nSTRUCT\nEND_STRUCT"), param("structure_type_declaration", "TypeName EXTENDS Other.Type :\nSTRUCT\nEND_STRUCT"), param("structure_type_declaration", "TypeName : POINTER TO\nSTRUCT\nEND_STRUCT"),