From 2d18e033c075573ff2544b7de39e48442ca72b33 Mon Sep 17 00:00:00 2001 From: Philippe Proulx Date: Tue, 8 Sep 2020 21:21:33 -0400 Subject: [PATCH] cgen.py: use C type classes for _CodeGen._ft_c_type() This patch introduces new classes to represent C types in `cgen.py`. The C type class hierarchy is: _CType _ArithCType _PointerCType A `_PointerCType` object contains another `_CType` object. You can get the string representation of a C type object with its __str__() method. A C type constructor's `is_const` parameter controls whether or not the _value_ is const. For example: `const char *`: `_PointerCType` containing a const `_ArithCType`. `const char * const`: Const `_PointerCType` containing a const `_ArithCType`. _CodeGen._ft_c_type() now returns a `_CType` object instead of a string. Signed-off-by: Philippe Proulx --- barectf/cgen.py | 68 ++++++++++++++++++++---- barectf/templates/c/func-proto-params.j2 | 2 +- 2 files changed, 58 insertions(+), 12 deletions(-) diff --git a/barectf/cgen.py b/barectf/cgen.py index 9e4707d..5d2e9c3 100644 --- a/barectf/cgen.py +++ b/barectf/cgen.py @@ -389,6 +389,54 @@ _ROOT_FT_PREFIX_NAMES = { _FtParam = collections.namedtuple('_FtParam', ['ft', 'name']) +# C type abstract base class. +class _CType: + def __init__(self, is_const: bool): + self._is_const = is_const + + @property + def is_const(self) -> bool: + return self._is_const + + +# Arithmetic C type. +class _ArithCType(_CType): + def __init__(self, name: str, is_const: bool): + super().__init__(is_const) + self._name = name + + @property + def name(self) -> str: + return self._name + + def __str__(self) -> str: + return f'{"const " if self._is_const else ""}{self._name}' + + +# Pointer C type. +class _PointerCType(_CType): + def __init__(self, pointed_c_type: _CType, is_const: bool): + super().__init__(is_const) + self._pointed_c_type = pointed_c_type + + @property + def pointed_c_type(self) -> _CType: + return self._pointed_c_type + + def __str__(self) -> str: + s = str(self._pointed_c_type) + + if not s.endswith('*'): + s += ' ' + + s += '*' + + if self._is_const: + s += ' const' + + return s + + # A C code generator. # # Such a code generator can generate: @@ -454,11 +502,9 @@ class _CodeGen: def _trace_type(self) -> barectf_config.TraceType: return self._cfg.trace.type - # Returns the C type for the field type `ft`, returning a `const` C - # type if `is_const` is `True`. - def _ft_c_type(self, ft: barectf_config._FieldType, is_const: bool = False) -> str: - const_beg_str = 'const ' - + # Returns the C type for the field type `ft`, making it `const` if + # `is_const` is `True`. + def _ft_c_type(self, ft: barectf_config._FieldType, is_const: bool = False): if isinstance(ft, barectf_config._IntegerFieldType): ft = typing.cast(barectf_config._IntegerFieldType, ft) sign_prefix = 'u' if isinstance(ft, barectf_config.UnsignedIntegerFieldType) else '' @@ -473,21 +519,21 @@ class _CodeGen: assert ft.size <= 64 sz = 64 - return f'{const_beg_str if is_const else ""}{sign_prefix}int{sz}_t' + return _ArithCType(f'{sign_prefix}int{sz}_t', is_const) elif type(ft) is barectf_config.RealFieldType: ft = typing.cast(barectf_config.RealFieldType, ft) if ft.size == 32 and ft.alignment == 32: - c_type = 'float' + s = 'float' elif ft.size == 64 and ft.alignment == 64: - c_type = 'double' + s = 'double' else: - c_type = 'uint64_t' + s = 'uint64_t' - return f'{const_beg_str if is_const else ""}{c_type}' + return _ArithCType(s, is_const) else: assert type(ft) is barectf_config.StringFieldType - return f'const char *{" const" if is_const else ""}' + return _PointerCType(_ArithCType('char', True), is_const) # Returns the function prototype parameters for the members of the # root structure field type `root_ft`. diff --git a/barectf/templates/c/func-proto-params.j2 b/barectf/templates/c/func-proto-params.j2 index 10af150..198af79 100644 --- a/barectf/templates/c/func-proto-params.j2 +++ b/barectf/templates/c/func-proto-params.j2 @@ -23,6 +23,6 @@ # SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #} {% for param in params %} - {% set c_type = param.ft | ft_c_type(const_params) %}, + {% set c_type = param.ft | ft_c_type(const_params) | string %}, {{ c_type }}{{ ' ' if not c_type.endswith('*') }}{{ prefix }}_{{ param.name }} {%- endfor %} -- 2.34.1