Skip to content

Commit d914e86

Browse files
authored
Introduce ssort in CI (#438)
We use `ssort` to sort the definitions in the source files in a systematic way, so that we do not have to that manually anymore.
1 parent 8d1185e commit d914e86

40 files changed

+1817
-1790
lines changed

aas_core_codegen/common.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -182,10 +182,6 @@ def __new__(cls, lines: Sequence[str]) -> "Lines":
182182
"""
183183
return cast(Lines, lines)
184184

185-
def __add__(self, other: "Lines") -> "Lines":
186-
"""Concatenate two list of lines."""
187-
raise NotImplementedError("Only for type annotations")
188-
189185
# pylint: disable=function-redefined
190186

191187
@overload
@@ -202,12 +198,16 @@ def __getitem__(self, index: Union[int, slice]) -> Union[str, "Lines"]:
202198
"""Get the line(s) at the given index."""
203199
raise NotImplementedError("Only for type annotations")
204200

201+
def __iter__(self) -> Iterator[str]:
202+
"""Iterate over the lines."""
203+
raise NotImplementedError("Only for type annotations")
204+
205205
def __len__(self) -> int:
206206
"""Return the number of the lines."""
207207
raise NotImplementedError("Only for type annotations")
208208

209-
def __iter__(self) -> Iterator[str]:
210-
"""Iterate over the lines."""
209+
def __add__(self, other: "Lines") -> "Lines":
210+
"""Concatenate two list of lines."""
211211
raise NotImplementedError("Only for type annotations")
212212

213213

aas_core_codegen/cpp/common.py

+37-37
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,26 @@ def generate_primitive_type(primitive_type: intermediate.PrimitiveType) -> Strip
293293
return PRIMITIVE_TYPE_MAP[primitive_type]
294294

295295

296+
def primitive_type_is_referencable(primitive_type: intermediate.PrimitiveType) -> bool:
297+
"""Return ``True`` if the primitive type denotes a referencable value in C++."""
298+
if primitive_type is intermediate.PrimitiveType.BOOL:
299+
return False
300+
301+
elif primitive_type is intermediate.PrimitiveType.INT:
302+
return False
303+
304+
elif primitive_type is intermediate.PrimitiveType.FLOAT:
305+
return False
306+
307+
elif primitive_type is intermediate.PrimitiveType.STR:
308+
return True
309+
310+
elif primitive_type is intermediate.PrimitiveType.BYTEARRAY:
311+
return True
312+
else:
313+
assert_never(primitive_type)
314+
315+
296316
def generate_primitive_type_with_const_ref_if_applicable(
297317
primitive_type: intermediate.PrimitiveType,
298318
) -> Stripped:
@@ -391,6 +411,23 @@ def generate_type(
391411
raise AssertionError("Should not have gotten here")
392412

393413

414+
def is_referencable(type_annotation: intermediate.TypeAnnotationUnion) -> bool:
415+
"""Return ``True`` if the type annotation denotes a referencable value in C++."""
416+
if isinstance(type_annotation, intermediate.OptionalTypeAnnotation):
417+
return True
418+
419+
primitive_type = intermediate.try_primitive_type(type_annotation)
420+
if primitive_type is not None:
421+
return primitive_type_is_referencable(primitive_type)
422+
423+
if isinstance(type_annotation, intermediate.OurTypeAnnotation) and isinstance(
424+
type_annotation.our_type, intermediate.Enumeration
425+
):
426+
return False
427+
428+
return True
429+
430+
394431
def generate_type_with_const_ref_if_applicable(
395432
type_annotation: intermediate.TypeAnnotationUnion,
396433
types_namespace: Optional[Identifier] = None,
@@ -544,43 +581,6 @@ def generate_namespace_closing(library_namespace: Stripped) -> Stripped:
544581
)
545582

546583

547-
def primitive_type_is_referencable(primitive_type: intermediate.PrimitiveType) -> bool:
548-
"""Return ``True`` if the primitive type denotes a referencable value in C++."""
549-
if primitive_type is intermediate.PrimitiveType.BOOL:
550-
return False
551-
552-
elif primitive_type is intermediate.PrimitiveType.INT:
553-
return False
554-
555-
elif primitive_type is intermediate.PrimitiveType.FLOAT:
556-
return False
557-
558-
elif primitive_type is intermediate.PrimitiveType.STR:
559-
return True
560-
561-
elif primitive_type is intermediate.PrimitiveType.BYTEARRAY:
562-
return True
563-
else:
564-
assert_never(primitive_type)
565-
566-
567-
def is_referencable(type_annotation: intermediate.TypeAnnotationUnion) -> bool:
568-
"""Return ``True`` if the type annotation denotes a referencable value in C++."""
569-
if isinstance(type_annotation, intermediate.OptionalTypeAnnotation):
570-
return True
571-
572-
primitive_type = intermediate.try_primitive_type(type_annotation)
573-
if primitive_type is not None:
574-
return primitive_type_is_referencable(primitive_type)
575-
576-
if isinstance(type_annotation, intermediate.OurTypeAnnotation) and isinstance(
577-
type_annotation.our_type, intermediate.Enumeration
578-
):
579-
return False
580-
581-
return True
582-
583-
584584
def include_guard_var(namespace: Stripped) -> Stripped:
585585
"""
586586
Generate the variable name of the include guard.

aas_core_codegen/cpp/description.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,18 @@ def transform_document(
453453
)
454454

455455

456+
def documentation_comment(text: Stripped) -> Stripped:
457+
"""Generate the documentation comment with the given ``text``."""
458+
commented_lines = [] # type: List[str]
459+
for line in text.splitlines():
460+
if len(line.strip()) == 0:
461+
commented_lines.append("///")
462+
else:
463+
commented_lines.append(f"/// {line}")
464+
465+
return Stripped("\n".join(commented_lines))
466+
467+
456468
def generate_comment_for_summary_remarks(
457469
description: intermediate.SummaryRemarksDescription, context: Context
458470
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:
@@ -548,18 +560,6 @@ def generate_comment_for_summary_remarks_constraints(
548560
return documentation_comment(Stripped("\n\n".join(blocks))), None
549561

550562

551-
def documentation_comment(text: Stripped) -> Stripped:
552-
"""Generate the documentation comment with the given ``text``."""
553-
commented_lines = [] # type: List[str]
554-
for line in text.splitlines():
555-
if len(line.strip()) == 0:
556-
commented_lines.append("///")
557-
else:
558-
commented_lines.append(f"/// {line}")
559-
560-
return Stripped("\n".join(commented_lines))
561-
562-
563563
def generate_comment_for_signature(
564564
description: intermediate.DescriptionOfSignature, context: Context
565565
) -> Tuple[Optional[Stripped], Optional[List[Error]]]:

aas_core_codegen/cpp/structure/_generate.py

+63-63
Original file line numberDiff line numberDiff line change
@@ -75,69 +75,6 @@ def _human_readable_identifier(
7575
return result
7676

7777

78-
def _verify_structure_name_collisions(
79-
symbol_table: intermediate.SymbolTable,
80-
) -> List[Error]:
81-
"""Verify that the C++ names of the structures do not collide."""
82-
observed_type_names: Dict[
83-
Identifier,
84-
Union[
85-
intermediate.Enumeration,
86-
intermediate.AbstractClass,
87-
intermediate.ConcreteClass,
88-
],
89-
] = dict()
90-
91-
errors = [] # type: List[Error]
92-
93-
# region Inter-structure collisions
94-
95-
for enum_or_cls in itertools.chain(symbol_table.enumerations, symbol_table.classes):
96-
names: List[Identifier]
97-
98-
if isinstance(enum_or_cls, intermediate.Enumeration):
99-
names = [cpp_naming.enum_name(enum_or_cls.name)]
100-
elif isinstance(enum_or_cls, intermediate.AbstractClass):
101-
names = [cpp_naming.interface_name(enum_or_cls.name)]
102-
elif isinstance(enum_or_cls, intermediate.ConcreteClass):
103-
names = [
104-
cpp_naming.interface_name(enum_or_cls.name),
105-
cpp_naming.class_name(enum_or_cls.name),
106-
]
107-
else:
108-
assert_never(enum_or_cls)
109-
110-
for name in names:
111-
other = observed_type_names.get(name, None)
112-
113-
if other is not None:
114-
errors.append(
115-
Error(
116-
enum_or_cls.parsed.node,
117-
f"The C++ name {name!r} "
118-
f"of the {_human_readable_identifier(enum_or_cls)} "
119-
f"collides with the C++ name "
120-
f"of the {_human_readable_identifier(other)}",
121-
)
122-
)
123-
else:
124-
observed_type_names[name] = enum_or_cls
125-
126-
# endregion
127-
128-
# region Intra-structure collisions
129-
130-
for our_type in symbol_table.our_types:
131-
collision_error = _verify_intra_structure_collisions(our_type=our_type)
132-
133-
if collision_error is not None:
134-
errors.append(collision_error)
135-
136-
# endregion
137-
138-
return errors
139-
140-
14178
def _verify_intra_structure_collisions(
14279
our_type: intermediate.OurType,
14380
) -> Optional[Error]:
@@ -265,6 +202,69 @@ def _verify_intra_structure_collisions(
265202
return None
266203

267204

205+
def _verify_structure_name_collisions(
206+
symbol_table: intermediate.SymbolTable,
207+
) -> List[Error]:
208+
"""Verify that the C++ names of the structures do not collide."""
209+
observed_type_names: Dict[
210+
Identifier,
211+
Union[
212+
intermediate.Enumeration,
213+
intermediate.AbstractClass,
214+
intermediate.ConcreteClass,
215+
],
216+
] = dict()
217+
218+
errors = [] # type: List[Error]
219+
220+
# region Inter-structure collisions
221+
222+
for enum_or_cls in itertools.chain(symbol_table.enumerations, symbol_table.classes):
223+
names: List[Identifier]
224+
225+
if isinstance(enum_or_cls, intermediate.Enumeration):
226+
names = [cpp_naming.enum_name(enum_or_cls.name)]
227+
elif isinstance(enum_or_cls, intermediate.AbstractClass):
228+
names = [cpp_naming.interface_name(enum_or_cls.name)]
229+
elif isinstance(enum_or_cls, intermediate.ConcreteClass):
230+
names = [
231+
cpp_naming.interface_name(enum_or_cls.name),
232+
cpp_naming.class_name(enum_or_cls.name),
233+
]
234+
else:
235+
assert_never(enum_or_cls)
236+
237+
for name in names:
238+
other = observed_type_names.get(name, None)
239+
240+
if other is not None:
241+
errors.append(
242+
Error(
243+
enum_or_cls.parsed.node,
244+
f"The C++ name {name!r} "
245+
f"of the {_human_readable_identifier(enum_or_cls)} "
246+
f"collides with the C++ name "
247+
f"of the {_human_readable_identifier(other)}",
248+
)
249+
)
250+
else:
251+
observed_type_names[name] = enum_or_cls
252+
253+
# endregion
254+
255+
# region Intra-structure collisions
256+
257+
for our_type in symbol_table.our_types:
258+
collision_error = _verify_intra_structure_collisions(our_type=our_type)
259+
260+
if collision_error is not None:
261+
errors.append(collision_error)
262+
263+
# endregion
264+
265+
return errors
266+
267+
268268
class VerifiedIntermediateSymbolTable(intermediate.SymbolTable):
269269
"""Represent a verified symbol table which can be used for code generation."""
270270

aas_core_codegen/cpp/transpilation.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,15 @@ class Transpiler(
292292
):
293293
"""Transpile a node of our AST to C++ code, or return an error."""
294294

295+
_CPP_COMPARISON_MAP = {
296+
parse_tree.Comparator.LT: "<",
297+
parse_tree.Comparator.LE: "<=",
298+
parse_tree.Comparator.GT: ">",
299+
parse_tree.Comparator.GE: ">=",
300+
parse_tree.Comparator.EQ: "==",
301+
parse_tree.Comparator.NE: "!=",
302+
}
303+
295304
def __init__(
296305
self,
297306
type_map: Mapping[
@@ -495,15 +504,6 @@ def transform_index(
495504

496505
return Stripped(f"{collection}.at({index})"), None
497506

498-
_CPP_COMPARISON_MAP = {
499-
parse_tree.Comparator.LT: "<",
500-
parse_tree.Comparator.LE: "<=",
501-
parse_tree.Comparator.GT: ">",
502-
parse_tree.Comparator.GE: ">=",
503-
parse_tree.Comparator.EQ: "==",
504-
parse_tree.Comparator.NE: "!=",
505-
}
506-
507507
@ensure(lambda result: (result[0] is not None) ^ (result[1] is not None))
508508
def transform_comparison(
509509
self, node: parse_tree.Comparison

0 commit comments

Comments
 (0)