diff --git a/src/cfile/core.py b/src/cfile/core.py index 5115432..3f215c5 100644 --- a/src/cfile/core.py +++ b/src/cfile/core.py @@ -1,7 +1,7 @@ """ cfile core """ -from typing import Union, Any +from typing import Any, Self class Element: @@ -136,7 +136,7 @@ class DataType(Element): """ Base class for all data types """ - def __init__(self, name: str | None) -> None: + def __init__(self, name: str = "") -> None: self.name = name @@ -145,12 +145,12 @@ class Type(DataType): Data type """ def __init__(self, - base_type: Union[str, "Type"], + base_type: str | Self, const: bool = False, pointer: bool = False, volatile: bool = False, array: int | None = None) -> None: # Only used for typedefs to other array types - super().__init__(None) + super().__init__("") self.base_type = base_type self.const = const self.volatile = volatile @@ -168,6 +168,54 @@ def qualifier(self, name) -> bool: else: raise KeyError(name) +class EnumMember(Element): + """ + Enum element. + """ + + def __init__(self, + name: str, + value: int | None) -> None: + self.name = name + self.value = value + + +class Enum(DataType): + """ + A enum definition + """ + + def __init__(self, name: str, members: list[EnumMember] | None = None, attributes: list[str] | None = None) -> None: + super().__init__(name) + + if members == None: + self.members = [] + elif isinstance(members, list): + self.members = list(members) + enumValue = -1 + for enum in self.members: + if enum.value == None: + enumValue += 1 + enum.value = enumValue + else: + enumValue = enum.value + else: + raise TypeError('Invalid argument type for "members"') + + if attributes == None: + self.attributes = [] + elif isinstance(attributes, list): + self.attributes: list[str] = list(attributes) + else: + raise TypeError('Invalid argument type for "attributes"') + + def append(self, member: EnumMember) -> None: + """ + Appends new element to the struct definition + """ + if not isinstance(member, EnumMember): + raise TypeError(f'Invalid type, expected "EnumMember", got {str(type(member))}') + self.members.append(member) class StructMember(Element): """ @@ -197,17 +245,22 @@ class Struct(DataType): """ A struct definition """ - def __init__(self, name: str | None, members: StructMember | list[StructMember] | None = None) -> None: + def __init__(self, name: str = "", members: list[StructMember] | None = None, attributes: list[str] | None = None) -> None: super().__init__(name) - self.members: list[StructMember] = [] - if members is not None: - if isinstance(members, StructMember): - self.append(members) - elif isinstance(members, list): - for member in members: - self.append(member) - else: - raise TypeError('Invalid argument type for "elements"') + + if members == None: + self.members = [] + elif isinstance(members, list): + self.members: list[StructMember] = list(members) + else: + raise TypeError('Invalid argument type for "members"') + + if attributes == None: + self.attributes = [] + elif isinstance(attributes, list): + self.attributes: list[str] = list(attributes) + else: + raise TypeError('Invalid argument type for "attributes"') def append(self, member: StructMember) -> None: """ @@ -231,46 +284,39 @@ def make_member(self, return member -class TypeDef(DataType): - """ - Type definition (typedef) - """ - def __init__(self, - name: str, - base_type: Union[str, "DataType", "Declaration"], - const: bool = False, - pointer: bool = False, - volatile: bool = False, - array: int | None = None) -> None: - super().__init__(name) - self.const = const - self.volatile = volatile +class UnionMember(Element): + def __init__(self, name: str, data_type: DataType, pointer: bool = False, array: int | None = None): + self.name = name + self.data_type = data_type self.pointer = pointer self.array = array - self.base_type: DataType | Declaration - if isinstance(base_type, DataType): - self.base_type = base_type - elif isinstance(base_type, str): - self.base_type = Type(base_type) - elif isinstance(base_type, Declaration): - if not isinstance(base_type.element, DataType): - err_msg = f'base_type: Declaration must declare a type, not {str(type(base_type.element))}' - self.base_type = base_type + + +class Union(DataType): + def __init__(self, name: str, members: list[UnionMember] | None = None, attributes: list[str] | None = None): + self.name = name + + if members == None: + self.members = [] + elif isinstance(members, list): + self.members: list[UnionMember] = list(members) else: - err_msg = 'base_type: Invalid type, expected "str" | "DataType" | "Declaration",' - err_msg += ' got {str(type(base_type))}' - raise TypeError(err_msg) + raise TypeError('Invalid argument type for "members"') - def qualifier(self, name) -> bool: + if attributes == None: + self.attributes = [] + elif isinstance(attributes, list): + self.attributes: list[str] = list(attributes) + else: + raise TypeError('Invalid argument type for "attributes"') + + def append(self, member: UnionMember) -> None: """ - Returns the status of named qualifier + Appends new element to the struct definition """ - if name == "const": - return self.const - if name == "volatile": - return self.volatile - else: - raise KeyError(name) + if not isinstance(member, UnionMember): + raise TypeError(f'Invalid type, expected "UnionMember", got {str(type(member))}') + self.members.append(member) class Variable(Element): @@ -322,7 +368,7 @@ def __init__(self, static: bool = False, const: bool = False, # const function (as seen in C++) extern: bool = False, - params: Variable | list[Variable] | None = None) -> None: + params: list[Variable] | None = None) -> None: self.name = name self.static = static self.const = const @@ -335,13 +381,11 @@ def __init__(self, self.return_type = Type("void") else: raise TypeError(str(type(return_type))) - self.params: list[Variable] = [] - if params is not None: - if isinstance(params, Variable): - self.append(params) - elif isinstance(params, list): - for param in params: - self.append(param) + + if isinstance(params, list): + self.params: list[Variable] = list(params) + else: + raise TypeError('Invalid argument type for "params"') def append(self, param: Variable) -> "Function": """ @@ -374,7 +418,7 @@ class Declaration(Element): - Function """ def __init__(self, - element: Union[Variable, Function, DataType], + element: Variable | Function | DataType, init_value: Any | None = None) -> None: if isinstance(element, (Variable, Function, DataType)): self.element = element @@ -422,6 +466,8 @@ def __init__(self, self.expression = "true" if expression else "false" elif isinstance(expression, (int, float)): self.expression = str(expression) + elif isinstance(expression, EnumMember): + self.expression = expression.name elif isinstance(expression, (str, Element)): self.expression = expression else: @@ -484,7 +530,7 @@ class Sequence: A sequence of statements, comments or whitespace """ def __init__(self) -> None: - self.elements: list[Union[Comment, Statement, "Sequence"]] = [] + self.elements: list[Comment | Statement | "Sequence"] = [] def __len__(self) -> int: return len(self.elements) @@ -511,3 +557,134 @@ class Block(Sequence): """ A sequence wrapped in braces """ + + +class Condition(Block): + """ + A sequence for condition wrapped in braces + """ + + def __init__(self, condition: str): + super().__init__() + self.condition = condition + + +class Conditions(Element): + """ + A condition wrapped in braces + """ + + def __init__(self, conditions: list[Condition] | None = None): + super().__init__() + + if conditions == None: + self.conditions = [] + elif isinstance(conditions, list): + self.conditions: list[Condition] = list(conditions) + else: + raise TypeError('Invalid argument type for "conditions"') + + def append(self, member: Condition) -> None: + """ + Appends new element to the conditions definition + """ + if not isinstance(member, Condition): + raise TypeError(f'Invalid type, expected "Condition", got {str(type(member))}') + self.conditions.append(member) + + +class SwitchCase(Block): + """ + A sequence for switch case wrapped in braces + """ + + def __init__(self, cases: list[int | EnumMember | str] | None = None): + """ + Empty values means default + """ + super().__init__() + + if cases == None: + self.cases = [] + elif isinstance(cases, list): + self.cases: list[int | EnumMember | str] = list(cases) + else: + raise TypeError('Invalid argument type for "cases"') + + +class Switch(Element): + """ + A sequence for switch case wrapped in braces + """ + + def __init__(self, switchVar: str | Variable, cases: list[SwitchCase] | None = None): + super().__init__() + + if switchVar == "" or not (isinstance(switchVar, str) or isinstance(switchVar, Variable)): + raise ValueError("switchVar cannot be empty ") + + self.switchVar = switchVar + + if cases == None: + self.cases = [] + elif isinstance(cases, list): + self.cases: list[SwitchCase] = list(cases) + else: + raise TypeError('Invalid argument type for "cases"') + + def append(self, case: SwitchCase) -> None: + """ + Appends new element to the conditions definition + """ + if not isinstance(case, SwitchCase): + raise TypeError(f'Invalid type, expected "SwitchCase", got {str(type(case))}') + self.cases.append(case) + + +class Break(Element): + """ + Adding break into block + """ + + +class TypeDef(DataType): + """ + Type definition (typedef) + """ + + def __init__(self, + name: str, + base_type: str | DataType | Declaration, + const: bool = False, + pointer: bool = False, + volatile: bool = False, + array: int | None = None) -> None: + super().__init__(name) + self.const = const + self.volatile = volatile + self.pointer = pointer + self.array = array + self.base_type: DataType | Declaration + if isinstance(base_type, DataType): + self.base_type = base_type + elif isinstance(base_type, str): + self.base_type = Type(base_type) + elif isinstance(base_type, Declaration): + if not isinstance(base_type.element, DataType): + err_msg = f'base_type: Declaration must declare a type, not {str(type(base_type.element))}' + self.base_type = base_type + else: + err_msg = 'base_type: Invalid type, expected "str" | "DataType" | "Declaration",' + err_msg += ' got {str(type(base_type))}' + raise TypeError(err_msg) + + def qualifier(self, name) -> bool: + """ + Returns the status of named qualifier + """ + if name == "const": + return self.const + if name == "volatile": + return self.volatile + else: + raise KeyError(name) diff --git a/src/cfile/factory.py b/src/cfile/factory.py index 71a609e..37f43f9 100644 --- a/src/cfile/factory.py +++ b/src/cfile/factory.py @@ -120,7 +120,7 @@ def function(self, static: bool = False, const: bool = False, # This is not const of the return type extern: bool = False, - params: core.Variable | list[core.Variable] | None = None) -> core.Function: + params: list[core.Variable] | None = None) -> core.Function: """ New function """ @@ -137,9 +137,26 @@ def type(self, """ return core.Type(type_ref, const, pointer, volatile, array) + def enum_member(self, + name: str, + value: int | None = None): + """ + New EnumMember + """ + return core.EnumMember(name, value) + + def enum(self, + name: str, + members: list[core.EnumMember] | None = None, + attributes: list[str] | None = None): + """ + New Enum + """ + return core.Enum(name, members, attributes) + def struct_member(self, name: str, - data_type: str | core.Type | core.Struct, + data_type: str | core.DataType, const: bool = False, # Pointer qualifier only pointer: bool = False, array: int | None = None) -> core.StructMember: @@ -150,12 +167,13 @@ def struct_member(self, def struct(self, name: str, - members: core.StructMember | list[core.StructMember] | None = None + members: list[core.StructMember] | None = None, + attributes: list[str] | None = None ) -> core.Struct: """ New Struct """ - return core.Struct(name, members) + return core.Struct(name, members, attributes) def variable(self, name: str, @@ -204,16 +222,15 @@ def str_literal(self, text: str) -> core.StringLiteral: def func_call(self, name: str, - args: list[arg_types] | arg_types | None = None) -> core.FunctionCall: + args: list[arg_types] | None = None) -> core.FunctionCall: """ New function call """ - if args is None: - return core.FunctionCall(name, None) - elif isinstance(args, list): - return core.FunctionCall(name, args) - else: - return core.FunctionCall(name, [args]) + if isinstance(name, core.Function): + if ((isinstance(name.params, list) or isinstance(args, list)) and len(name.params) != len(args)) or ((not name.params or not args) and name.params != args): + raise ValueError('Function declaration and function call params doesn\'t matched in size.') + name = name.name + return core.FunctionCall(name, args) def func_return(self, expression: int | float | str | core.Element) -> core.FunctionReturn: """ @@ -224,6 +241,41 @@ def func_return(self, expression: int | float | str | core.Element) -> core.Func def declaration(self, element: Union[core.Variable, core.Function, core.DataType], init_value: Any | None = None) -> core.Declaration: - - """New declaration""" + """ + New declaration + """ return core.Declaration(element, init_value) + + def condition(self, condition: str) -> core.Condition: + """ + New condition + """ + return core.Condition(condition) + + def conditions(self, conditions: list[core.Condition] | None = None) -> core.Conditions: + """ + New condition + """ + return core.Conditions(conditions) + + def switch_case(self, cases: list[int | core.EnumMember | str] | None = None) -> core.SwitchCase: + + return core.SwitchCase(cases) + + def switch(self, switchVar: str | core.Variable, cases: list[core.SwitchCase] | None = None) -> core.Switch: + + return core.Switch(switchVar, cases) + + def union_member(self, name: str, dataType: core.DataType, pointer: bool = False, array: int | None = None) -> core.UnionMember: + + return core.UnionMember(name, dataType, pointer, array) + + def union(self, name: str, members: list[core.UnionMember] | None = None, attributes: list[str] | None = None) -> core.Union: + + return core.Union(name, members, attributes) + + def breakBlock(self) -> core.Break: + """ + Adding break into block + """ + return core.Break() diff --git a/src/cfile/writer.py b/src/cfile/writer.py index e842e8f..da03695 100644 --- a/src/cfile/writer.py +++ b/src/cfile/writer.py @@ -17,17 +17,20 @@ class ElementType(Enum): DIRECTIVE = 1 COMMENT = 2 TYPE_DECLARATION = 3 - STRUCT_DECLARATION = 4 # Should this be separate from type declaration? - VARIABLE_DECLARATION = 5 - FUNCTION_DECLARATION = 6 - TYPEDEF = 7 - TYPE_INSTANCE = 8 - STRUCT_INSTANCE = 9 - VARIABLE_USAGE = 10 - FUNCTION_CALL = 11 - STATEMENT = 12 - BLOCK_START = 13 - BLOCK_END = 14 + ENUM_DECLARATION = 4 # Should this be separate from type declaration? + STRUCT_DECLARATION = 5 # Should this be separate from type declaration? + VARIABLE_DECLARATION = 6 + FUNCTION_DECLARATION = 7 + UNION_DECLARATION = 8 + TYPEDEF = 9 + TYPE_INSTANCE = 10 + STRUCT_INSTANCE = 11 + UNION_INSTANCE = 12 + VARIABLE_USAGE = 13 + FUNCTION_CALL = 14 + STATEMENT = 15 + BLOCK_START = 16 + BLOCK_END = 17 class Formatter: @@ -75,8 +78,11 @@ def _dedent(self): self.indentation_str = self.indentation_char * \ (self.indentation_level * self.indent_width) - def _start_line(self): - self.fh.write(self.indentation_str) + def _start_line(self, indent: bool = True): + if indent: + self.fh.write(self.indentation_str) + else: + self.fh.write("") def _write(self, text): self.fh.write(text) @@ -102,6 +108,7 @@ def __init__(self, style: c_style.StyleOptions) -> None: self.switcher_all = { "Type": self._write_base_type, "TypeDef": self._write_typedef_usage, + "Enum": self._write_enum_usage, "Struct": self._write_struct_usage, "Variable": self._write_variable_usage, "Function": self._write_function_usage, @@ -123,6 +130,10 @@ def __init__(self, style: c_style.StyleOptions) -> None: "IfndefDirective": self._write_ifndef_directive, "EndifDirective": self._write_endif_directive, "Extern": self._write_extern, + "Conditions": self._write_conditions, + "Switch": self._write_switch, + "Break": self._write_break, + "Union": self._write_union_usage, } self.last_element = ElementType.NONE @@ -182,14 +193,23 @@ def _write_sequence(self, sequence: core.Sequence) -> None: self._start_line() self._write_line_comment(elem) self._eol() + elif isinstance(elem, core.Conditions): + self._write_conditions(elem) + elif isinstance(elem, core.Switch): + self._write_switch(elem) elif isinstance(elem, core.Block): self._start_line() self._write_block(elem) elif isinstance(elem, core.Line): self._start_line() self._write_line_element(elem) + elif isinstance(elem, core.Break): + self._write_break(elem) else: - self._start_line() + if isinstance(elem, core.Blank): + self._start_line(False) + else: + self._start_line() class_name = elem.__class__.__name__ write_method = self.switcher_all.get(class_name, None) if write_method is not None: @@ -280,8 +300,12 @@ def _write_declaration(self, elem: core.Declaration) -> None: self._write_type_declaration(elem.element) elif isinstance(elem.element, core.TypeDef): self._write_typedef_declaration(elem.element) + elif isinstance(elem.element, core.Enum): + self._write_enum_declaration(elem.element) elif isinstance(elem.element, core.Struct): self._write_struct_declaration(elem.element) + elif isinstance(elem.element, core.Union): + self._write_union_declaration(elem.element) elif isinstance(elem.element, core.Variable): self._write_variable_declaration(elem.element) elif isinstance(elem.element, core.Function): @@ -310,10 +334,14 @@ def _write_initializer_member(self, value: Any) -> None: """ Writes initializer member """ - if isinstance(value, int): + if isinstance(value, bool): + self._write(str(value).lower()) + elif isinstance(value, int): self._write(str(value)) elif isinstance(value, str): self._write(f'"{value}"') + elif isinstance(value, core.EnumMember): + self._write(f'{value.name}') else: raise NotImplementedError(str(type(value))) @@ -383,8 +411,12 @@ def _write_variable_declaration(self, elem: core.Variable) -> None: self._write("extern ") if isinstance(elem.data_type, core.Type): self._write_type_declaration(elem.data_type) + elif isinstance(elem.data_type, core.Enum): + self._write_enum_usage(elem.data_type) elif isinstance(elem.data_type, core.Struct): self._write_struct_usage(elem.data_type) + elif isinstance(elem.data_type, core.Union): + self._write_union_usage(elem.data_type) elif isinstance(elem.data_type, core.Declaration): self._write_declaration(elem.data_type) elif isinstance(elem.data_type, core.TypeDef): @@ -446,47 +478,58 @@ def _write_typedef_declaration(self, elem: core.TypeDef): self._write("const ") if isinstance(elem.base_type, core.Type): self._write_type_declaration(elem.base_type) + elif isinstance(elem.base_type, core.TypeDef): + self._write(elem.base_type.name) + elif isinstance(elem.base_type, core.Enum): + self._write_enum_usage(elem.base_type) elif isinstance(elem.base_type, core.Struct): self._write_struct_usage(elem.base_type) + elif isinstance(elem.base_type, core.Union): + self._write_union_usage(elem.base_type) elif isinstance(elem.base_type, core.Declaration): - self._write_declaration(elem.base_type) + baseType = elem.base_type + if isinstance(elem.base_type.element, core.Function): + baseType = core.Declaration(core.Function("(*"+elem.name+")", elem.base_type.element.return_type, elem.base_type.element.static, + elem.base_type.element.const, elem.base_type.element.extern, elem.base_type.element.params)) + self._write_declaration(baseType) else: raise NotImplementedError(str(type(elem.base_type))) - result = "" - if elem.pointer: - if elem.const: - if self.style.space_around_pointer_qualifiers == c_style.SpaceLocation.DEFAULT: + if not (isinstance(elem.base_type, core.Declaration) and isinstance(elem.base_type.element, core.Function)): + result = "" + if elem.pointer: + if elem.const: + if self.style.space_around_pointer_qualifiers == c_style.SpaceLocation.DEFAULT: + if self.style.pointer_alignment == c_style.Alignment.LEFT: + result += "* const " + elif self.style.pointer_alignment == c_style.Alignment.RIGHT: + result += "*const " + elif self.style.pointer_alignment == c_style.Alignment.MIDDLE: + result += " * const " + else: + raise ValueError(self.style.pointer_alignment) + else: + raise NotImplementedError("Only default space location supported for pointer qualifiers") + else: if self.style.pointer_alignment == c_style.Alignment.LEFT: - result += "* const " + result += "* " elif self.style.pointer_alignment == c_style.Alignment.RIGHT: - result += "*const " + if isinstance(elem.base_type, core.Type) and elem.base_type.pointer: + result += "*" + else: + result += " *" elif self.style.pointer_alignment == c_style.Alignment.MIDDLE: - result += " * const " + result += " * " else: raise ValueError(self.style.pointer_alignment) - else: - raise NotImplementedError("Only default space location supported for pointer qualifiers") else: - if self.style.pointer_alignment == c_style.Alignment.LEFT: - result += "* " - elif self.style.pointer_alignment == c_style.Alignment.RIGHT: - if isinstance(elem.base_type, core.Type) and elem.base_type.pointer: - result += "*" - else: - result += " *" - elif self.style.pointer_alignment == c_style.Alignment.MIDDLE: - result += " * " - else: - raise ValueError(self.style.pointer_alignment) - else: - if not ((isinstance(elem.base_type, core.Type) and elem.base_type.pointer) and ( - self.style.pointer_alignment == c_style.Alignment.RIGHT)): - result += " " - assert elem.name is not None - result += elem.name - if elem.array is not None: - result += f"[{elem.array}]" - self._write(result) + if not ((isinstance(elem.base_type, core.Type) and elem.base_type.pointer) and ( + self.style.pointer_alignment == c_style.Alignment.RIGHT)): + result += " " + assert elem.name is not None + result += elem.name + if elem.array is not None: + result += f"[{elem.array}]" + self._write(result) self.last_element = ElementType.TYPEDEF def _write_function_usage(self, elem: core.Function) -> None: @@ -507,8 +550,14 @@ def _write_function_declaration(self, elem: core.Function) -> None: self._write("static ") if isinstance(elem.return_type, core.Type): self._write_type_declaration(elem.return_type) + elif isinstance(elem.return_type, core.TypeDef): + self._write_typedef_usage(elem.return_type) + elif isinstance(elem.return_type, core.Enum): + self._write_enum_usage(elem.return_type) elif isinstance(elem.return_type, core.Struct): self._write_struct_usage(elem.return_type) + elif isinstance(elem.return_type, core.Union): + self._write_union_usage(elem.return_type) else: raise NotImplementedError(str(type(elem.return_type))) self._write(f" {elem.name}(") @@ -599,6 +648,47 @@ def _write_func_call(self, elem: core.FunctionCall) -> None: self._write_expression(arg) self._write(")") + def _write_enum_usage(self, elem: core.Enum) -> None: + """ + Writes enum usage + """ + if not elem.name: + raise ValueError("enum doesn't have a name. Did you mean to use a declaration?") + self._write(f"enum {elem.name}") + + def _write_enum_declaration(self, elem: core.Enum): + """ + Writes enum declaration + """ + self._write(f"enum{" ".join([' __attribute__(('+attribute+'))' for attribute in elem.attributes])} {elem.name}") + if self.style.brace_wrapping.after_struct: + self._eol() + self._start_line() + self._write("{") + self._eol() + else: + self._write(" {") + self._eol() + if len(elem.members): + self._indent() + for member in elem.members: + self._start_line() + self._write_enum_member(member) + self._write(",") + self._eol() + if len(elem.members): + self._dedent() + self._start_line() + self._write("}") + self.last_element = ElementType.ENUM_DECLARATION + + def _write_enum_member(self, elem: core.EnumMember) -> None: + """ + Writes enum member + """ + result = elem.name + " = " + str(elem.value) + self._write(result) + def _write_struct_usage(self, elem: core.Struct) -> None: """ Writes struct usage @@ -611,7 +701,7 @@ def _write_struct_declaration(self, elem: core.Struct) -> None: """ Writes struct declaration """ - self._write(f"struct {elem.name}") + self._write(f"struct{" ".join([' __attribute__(('+attribute+'))' for attribute in elem.attributes])} {elem.name}") if self.style.brace_wrapping.after_struct: self._eol() self._start_line() @@ -641,6 +731,10 @@ def _write_struct_member(self, elem: core.StructMember) -> None: self._write_type_declaration(elem.data_type) elif isinstance(elem.data_type, core.Struct): self._write_struct_usage(elem.data_type) + elif isinstance(elem.data_type, core.Union): + self._write_union_usage(elem.data_type) + elif isinstance(elem.data_type, core.TypeDef): + self._write_typedef_usage(elem.data_type) else: raise NotImplementedError(str(type(elem.data_type))) result = "" @@ -709,3 +803,132 @@ def _write_endif_directive(self, elem: core.EndifDirective) -> None: def _write_extern(self, elem: core.Extern) -> None: self._write(f'extern "{elem.language}"') self.last_element = ElementType.DIRECTIVE + + def _write_conditions(self, elem: core.Conditions) -> None: + elseCondition = None + firstCondition = False + + for condition in elem.conditions: + if condition.condition == "": + if elseCondition == None: + elseCondition = condition + continue + else: + raise ValueError("Empty condition (else) can be defined only once.") + self._start_line() + if not firstCondition: + firstCondition = True + self._write(f"if ({condition.condition})") + else: + self._write(f"else if ({condition.condition})") + self._write_block(condition) + if elseCondition: + self._start_line() + self._write(f"else") + self._write_block(elseCondition) + + def _write_switch(self, elem: core.Switch): + defaultCase = None + self._start_line() + if type(elem.switchVar) == core.Variable: + self._write(f"switch({elem.switchVar.name}){{") + else: + self._write(f"switch({elem.switchVar}){{") + self._eol() + self._indent() + for case in elem.cases: + if not case.cases: + if defaultCase == None: + defaultCase = case + continue + else: + raise ValueError("Empty case (default) can be defined only once.") + firstCase = False + for condition in case.cases: + if not firstCase: + firstCase = True + else: + self._write_line("") + self._eol() + self._start_line() + self._write(f"case {condition if type(condition) == int or type(condition) == str else condition.name}:") + self._write_block(case) + if defaultCase: + self._start_line() + self._write(f"default:") + self._write_block(defaultCase) + self._dedent() + self._start_line() + self._write("}") + self._eol() + + def _write_break(self, elem: core.Break): + self._write("break") + + def _write_union_member(self, elem: core.UnionMember): + """ + Writes struct member + """ + if isinstance(elem.data_type, core.Type): + self._write_type_declaration(elem.data_type) + elif isinstance(elem.data_type, core.Struct): + self._write_struct_usage(elem.data_type) + elif isinstance(elem.data_type, core.Union): + self._write_union_usage(elem.data_type) + elif isinstance(elem.data_type, core.TypeDef): + self._write_typedef_usage(elem.data_type) + elif isinstance(elem.data_type, str): + self._write(elem.data_type) + else: + raise NotImplementedError(str(type(elem.data_type))+" "+ elem.name) + result = "" + if elem.pointer: + if self.style.pointer_alignment == c_style.Alignment.LEFT: + result += "* " + elif self.style.pointer_alignment == c_style.Alignment.RIGHT: + if isinstance(elem.data_type, core.Type) and elem.data_type.pointer: + result += "*" + else: + result += " *" + elif self.style.pointer_alignment == c_style.Alignment.MIDDLE: + result += " * " + else: + raise ValueError(self.style.pointer_alignment) + else: + if not (isinstance(elem.data_type, core.Type) and elem.data_type.pointer and ( + self.style.pointer_alignment == c_style.Alignment.RIGHT)): + result += " " + result += elem.name + self._write(result) + + def _write_union_usage(self, elem: core.Union): + """ + Writes union usage + """ + if not elem.name: + raise ValueError("union doesn't have a name. Did you mean to use a declaration?") + self._write(f"union {elem.name}") + + + def _write_union_declaration(self, elem: core.Union): + self._write(f"union{" ".join([' __attribute__(('+attribute+'))' for attribute in elem.attributes])} {elem.name}") + if self.style.brace_wrapping.after_struct: + self._eol() + self._start_line() + self._write("{") + self._eol() + else: + self._write(" {") + self._eol() + if len(elem.members): + self._indent() + for member in elem.members: + self._start_line() + self._write_union_member(member) + self._write(";") + self._eol() + if len(elem.members): + self._dedent() + self._start_line() + self._write("}") + self.last_element = ElementType.UNION_DECLARATION