Skip to content

Commit

Permalink
Add support for RecordType in TypeGenerator
Browse files Browse the repository at this point in the history
  • Loading branch information
cogu committed Oct 16, 2023
1 parent 6b615a2 commit 144fea9
Show file tree
Hide file tree
Showing 13 changed files with 411 additions and 101 deletions.
5 changes: 3 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,14 +49,15 @@ Notable changes.

* ArrayType
* BaseType
* PointerType
* RecordType
* RefType
* ScalarType
* StructType
* PointerType

### RTE Data Type Generator

* ArrayType
* BaseType
* RecordType
* RefType
* ScalarType
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Classic AUTOSAR only.
### Requirements (v0.4)

* Python 3.4+
* cfile
* cfile v0.2.0

### Installation (v0.4)

Expand Down Expand Up @@ -58,7 +58,7 @@ Only Clasic AUTOSAR is supported.

* Python 3.10+
* lxml
* cfile 0.3.0 (Used by RTE generator)
* cfile v0.3.1+

### Installation (v0.5)

Expand All @@ -75,6 +75,11 @@ Run in either venv or local.
```bash
python -m pip install --upgrade pip
python -m pip install --upgrade setuptools
git clone https://github.com/cogu/cfile.git cfile_0.3
cd cfile_0.3
git checkout v0.3.1
cd ..
python -m pip install --upgrade .
```

#### Standard install
Expand Down
45 changes: 45 additions & 0 deletions examples/generator/data_types/gen_type_defs_array.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"""
Example generation of RTE type header - Array type
Requires cfile v0.3.1
"""
import autosar
import autosar.xml.element as ar_element
from autosar.model import ImplementationModel
import autosar.generator


def main():
"""
Create workspace and print type header to stdout
"""
workspace = autosar.xml.Workspace()
packages = dict(zip(["BaseTypes", "ImplementationDataTypes"],
workspace.make_packages("DataTypes/BaseTypes",
"DataTypes/ImplementationDataTypes")))

uint8_base_type = ar_element.SwBaseType("uint8")
packages["BaseTypes"].append(uint8_base_type)
package = workspace.find("DataTypes/ImplementationDataTypes")
workspace.append(package)
sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref())
value_type = ar_element.ImplementationDataType("InactiveActive_T",
category="VALUE",
sw_data_def_props=sw_data_def_props)
packages["ImplementationDataTypes"].append(value_type)
sw_data_def_props = ar_element.SwDataDefPropsConditional(impl_data_type_ref=value_type.ref())
sub_element = ar_element.ImplementationDataTypeElement("Element",
category="TYPE_REFERENCE",
array_size=3,
sw_data_def_props=sw_data_def_props)
array_type = ar_element.ImplementationDataType("InactiveActiveArray_T",
category="ARRAY",
sub_elements=[sub_element])
packages["ImplementationDataTypes"].append(array_type)
implementation = ImplementationModel(workspace)
implementation.create_from_element(array_type)
type_generator = autosar.generator.TypeGenerator(implementation)
print(type_generator.write_type_header_str())


if __name__ == "__main__":
main()
33 changes: 0 additions & 33 deletions examples/generator/data_types/gen_type_defs_custom.py

This file was deleted.

55 changes: 55 additions & 0 deletions examples/generator/data_types/gen_type_defs_record.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
Example generation of RTE type header - Record type
Requires cfile v0.3.1
"""
import autosar
import autosar.xml.element as ar_element
from autosar.model import ImplementationModel
import autosar.generator


def main():
"""
Create workspace and print type header to stdout
"""
workspace = autosar.xml.Workspace()
packages = dict(zip(["BaseTypes", "ImplementationDataTypes"],
workspace.make_packages("DataTypes/BaseTypes",
"DataTypes/ImplementationDataTypes")))
uint8_base_type = ar_element.SwBaseType("uint8")
packages["BaseTypes"].append(uint8_base_type)
uint32_base_type = ar_element.SwBaseType("uint32")
packages["BaseTypes"].append(uint32_base_type)
sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref())
uint32_impl_type = ar_element.ImplementationDataType("uint32",
category="VALUE",
sw_data_def_props=sw_data_def_props,
type_emitter="Platform_Types")
packages["ImplementationDataTypes"].append(uint32_impl_type)
inactive_active_t = ar_element.ImplementationDataType("InactiveActive_T",
category="VALUE",
sw_data_def_props=sw_data_def_props)
packages["ImplementationDataTypes"].append(inactive_active_t)

record_members = []
sw_data_def_props = ar_element.SwDataDefPropsConditional(impl_data_type_ref=inactive_active_t.ref())
record_members.append(ar_element.ImplementationDataTypeElement("First",
category="TYPE_REFERENCE",
sw_data_def_props=sw_data_def_props))
sw_data_def_props = ar_element.SwDataDefPropsConditional(impl_data_type_ref=uint32_impl_type.ref())
record_members.append(ar_element.ImplementationDataTypeElement("Second",
category="TYPE_REFERENCE",
sw_data_def_props=sw_data_def_props))
record_type = ar_element.ImplementationDataType("MyRecord_T",
category="STRUCTURE",
sub_elements=record_members)
packages["ImplementationDataTypes"].append(record_type)

implementation = ImplementationModel(workspace)
implementation.create_from_element(record_type)
type_generator = autosar.generator.TypeGenerator(implementation)
print(type_generator.write_type_header_str())


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
Example generation of RTE type header
Requires cfile v0.3.0 (unreleased)
Example generation of RTE type header - Scalar type
Requires cfile v0.3.1
"""
import autosar
import autosar.xml.element as ar_element
Expand All @@ -10,23 +10,24 @@

def main():
"""
Prints header to stdout
Create workspace and print type header to stdout
"""
workspace = autosar.xml.Workspace()
packages = workspace.make_packages("DataTypes/BaseTypes",
"DataTypes/ImplementationDataTypes")
uint8_base_type = ar_element.SwBaseType('uint8')
packages[0].append(uint8_base_type)
packages = dict(zip(["BaseTypes", "ImplementationDataTypes"],
workspace.make_packages("DataTypes/BaseTypes",
"DataTypes/ImplementationDataTypes")))
uint8_base_type = ar_element.SwBaseType("uint8")
packages["BaseTypes"].append(uint8_base_type)
sw_data_def_props = ar_element.SwDataDefPropsConditional(base_type_ref=uint8_base_type.ref())
uint8_impl_type = ar_element.ImplementationDataType("uint8",
category="VALUE",
sw_data_def_props=sw_data_def_props, type_emitter="Platform")
packages[1].append(uint8_impl_type)
packages["ImplementationDataTypes"].append(uint8_impl_type)
sw_data_def_props = ar_element.SwDataDefPropsConditional(impl_data_type_ref=uint8_impl_type.ref())
inactive_active_t = ar_element.ImplementationDataType("InactiveActive_T",
category="TYPE_REFERENCE",
sw_data_def_props=sw_data_def_props)
packages[1].append(inactive_active_t)
packages["ImplementationDataTypes"].append(inactive_active_t)

implementation = ImplementationModel(workspace)
implementation.create_from_element(inactive_active_t)
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "autosar"
version = "0.5.0a7"
version = "0.5.0a8"
description = "A set of Python modules for working with AUTOSAR XML files"
readme = "README.md"
requires-python = ">=3.10"
Expand Down
33 changes: 27 additions & 6 deletions src/autosar/generator/type_generator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
RTE type generator
Requires cfile v0.3.0
Requires cfile v0.3.1
"""
import os
from typing import Iterator
Expand Down Expand Up @@ -48,10 +48,10 @@ def _create_code_sequence(self) -> cfile.core.Sequence:
code.append(C.ifndef(include_guard))
code.append(C.define(include_guard))
code.append(C.blank())
code.append(C.ifndef("__cplusplus", adjust=1))
code.append(C.ifndef("__cplusplus"))
code.append(C.line(C.extern("C")))
code.append(C.line("{"))
code.append(C.endif(adjust=1))
code.append(C.endif())
code.append(C.blank())
code.append(C.block_comment("* INCLUDES *", width=35))
code.append(C.include("Rte.h"))
Expand All @@ -60,10 +60,9 @@ def _create_code_sequence(self) -> cfile.core.Sequence:
code.append(C.blank())
code.extend(self._gen_type_defs(self.gen_data_type_creation_order()))
code.append(C.blank())
code.append(C.ifndef("__cplusplus", adjust=1))
code.append(C.line(C.extern("C")))
code.append(C.ifndef("__cplusplus"))
code.append(C.line("}"))
code.append(C.endif(adjust=1))
code.append([C.endif(), C.line_comment(" __cplusplus")])
code.append([C.endif(), C.line_comment(" " + include_guard)])
return code

Expand Down Expand Up @@ -112,6 +111,8 @@ def _gen_type_defs(self, data_types: Iterator[rte_element.Element]) -> cfile.cor
code.append(C.statement(C.typedef(data_type.name, data_type.impl_type.name)))
elif isinstance(data_type, rte_element.ArrayType):
code.append(self._gen_array_type_def(data_type))
elif isinstance(data_type, rte_element.RecordType):
code.extend(self._gen_record_type_def(data_type))
else:
raise NotImplementedError(str(type(data_type)))
return code
Expand All @@ -129,3 +130,23 @@ def _gen_array_type_def(self, data_type: rte_element.ArrayType) -> cfile.core.St
else:
raise NotImplementedError(str(type(last_element.data_type)))
return C.statement(C.typedef(data_type.name, target_type, array=last_element.array_size))

def _gen_record_type_def(self, data_type: rte_element.RecordType) -> cfile.core.Statement:
members = []
for element in data_type.sub_elements:
if isinstance(element.data_type, rte_element.ScalarType):
scalar_type: rte_element.ScalarType = element.data_type
if scalar_type.base_type.native_declaration:
target_type = C.type(scalar_type.base_type.native_declaration)
else:
target_type = C.type(scalar_type.base_type.name)
elif isinstance(element.data_type, rte_element.RefType):
target_type = C.type(element.data_type.impl_type.name)
else:
raise NotImplementedError(str(type(element.data_type)))
members.append(C.struct_member(element.name, target_type))
struct_name = "Rte_struct_" + data_type.name
code = C.sequence()
code.append(C.statement(C.struct(struct_name, members)))
code.append(C.statement(C.typedef(data_type.name, C.struct_ref(struct_name))))
return code
6 changes: 3 additions & 3 deletions src/autosar/model/element.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ def __init__(self,
self.target_type = target_type


class StructTypeElement(Element):
class RecordTypeElement(Element):
"""
Element of a struct
"""
Expand All @@ -160,7 +160,7 @@ def __init__(self,
self.data_type = data_type


class StructType(ImplementationType):
class RecordType(ImplementationType):
"""
A data type that can represent a structure.
Created from ar_elements where the category is set to STRUCTURE.
Expand All @@ -172,7 +172,7 @@ def __init__(self,
symbol_name: str | None = None,
type_emitter: str | None = None) -> None:
super().__init__(xml_ref, name, symbol_name, False, type_emitter)
self.sub_elements: list[StructTypeElement] = []
self.sub_elements: list[RecordTypeElement] = []


class UnionType(ImplementationType):
Expand Down
28 changes: 17 additions & 11 deletions src/autosar/model/implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,12 @@ def _create_array_type_element_from_ref_type(self,
element.array_size,
ref_type)

def _create_struct_type_from_element(self, element: ar_element.ImplementationDataType) -> rte_element.StructType:
def _create_struct_type_from_element(self, element: ar_element.ImplementationDataType) -> rte_element.RecordType:
elem_ref = str(element.ref())
symbol = None
if element.symbol_props is not None:
symbol = element.symbol_props.symbol
data_type = rte_element.StructType(elem_ref,
data_type = rte_element.RecordType(elem_ref,
element.name,
symbol_name=symbol,
type_emitter=element.type_emitter)
Expand All @@ -229,7 +229,7 @@ def _create_struct_type_element_from_scalar_type(self,
scalar_type = rte_element.ScalarType(element_ref,
element.name,
base_type)
return rte_element.StructTypeElement(element_ref,
return rte_element.RecordTypeElement(element_ref,
element.name,
scalar_type)

Expand All @@ -241,7 +241,7 @@ def _create_struct_type_element_from_ref_type(self,
sw_data_def_props = element.sw_data_def_props
impl_type = self.create_from_ref(sw_data_def_props[0].impl_data_type_ref, False)
ref_type = rte_element.RefType(element_ref, element.name, impl_type)
return rte_element.StructTypeElement(element_ref,
return rte_element.RecordTypeElement(element_ref,
element.name,
ref_type)

Expand Down Expand Up @@ -273,14 +273,20 @@ def _create_tree_node(self, data_type: rte_element.Element) -> Node:
node.add_child(self._create_tree_node(data_type.base_type))
elif isinstance(data_type, rte_element.RefType):
node.add_child(self._create_tree_node(data_type.impl_type))
elif isinstance(data_type, (rte_element.ArrayType, )):
elif isinstance(data_type, rte_element.ArrayType):
last_element: rte_element.ArrayTypeElement = data_type.sub_elements[-1]
if isinstance(last_element.data_type, rte_element.ScalarType):
pass # Arrays uses the native declaration directly instead of the base type name
elif isinstance(last_element.data_type, rte_element.RefType):
node.add_child(self._create_tree_node(last_element.data_type.impl_type))
else:
raise NotImplementedError(str(type(last_element.data_type)))
self._process_array_or_record_element_tree_node(node, last_element.data_type)
elif isinstance(data_type, rte_element.RecordType):
for element in data_type.sub_elements:
self._process_array_or_record_element_tree_node(node, element.data_type)
else:
raise NotImplementedError(str(type(data_type)))
return node

def _process_array_or_record_element_tree_node(self, node: Node, element: rte_element.Element) -> None:
if isinstance(element, rte_element.ScalarType):
pass # Arrays and records/structs use the native declaration directly instead of the base type name
elif isinstance(element, rte_element.RefType):
node.add_child(self._create_tree_node(element.impl_type))
else:
raise NotImplementedError(str(type(element)))
Loading

0 comments on commit 144fea9

Please sign in to comment.