Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 66 additions & 38 deletions src/cfile/core.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""
cfile core
"""
from typing import Union, Any
from typing import Any, Self


class Element:
Expand Down Expand Up @@ -145,7 +145,7 @@ 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,
Expand Down Expand Up @@ -231,46 +231,32 @@ 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):
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:
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):
Expand Down Expand Up @@ -374,7 +360,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
Expand Down Expand Up @@ -484,7 +470,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 | Self] = []

def __len__(self) -> int:
return len(self.elements)
Expand All @@ -511,3 +497,45 @@ class Block(Sequence):
"""
A sequence wrapped in braces
"""

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)
8 changes: 8 additions & 0 deletions src/cfile/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,3 +227,11 @@ def declaration(self,

"""New declaration"""
return core.Declaration(element, init_value)

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) -> core.Union:

return core.Union(name, members, attributes)
97 changes: 89 additions & 8 deletions src/cfile/writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ class ElementType(Enum):
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
UNION_DECLARATION = 7
TYPEDEF = 8
TYPE_INSTANCE = 9
STRUCT_INSTANCE = 10
UNION_INSTANCE = 11
VARIABLE_USAGE = 12
FUNCTION_CALL = 13
STATEMENT = 14
BLOCK_START = 15
BLOCK_END = 16


class Formatter:
Expand Down Expand Up @@ -123,6 +125,7 @@ def __init__(self, style: c_style.StyleOptions) -> None:
"IfndefDirective": self._write_ifndef_directive,
"EndifDirective": self._write_endif_directive,
"Extern": self._write_extern,
"Union": self._write_union_usage,
}
self.last_element = ElementType.NONE

Expand Down Expand Up @@ -282,6 +285,8 @@ def _write_declaration(self, elem: core.Declaration) -> None:
self._write_typedef_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):
Expand Down Expand Up @@ -385,6 +390,8 @@ def _write_variable_declaration(self, elem: core.Variable) -> 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.Declaration):
self._write_declaration(elem.data_type)
elif isinstance(elem.data_type, core.TypeDef):
Expand Down Expand Up @@ -448,6 +455,8 @@ def _write_typedef_declaration(self, elem: core.TypeDef):
self._write_type_declaration(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)
else:
Expand Down Expand Up @@ -509,6 +518,8 @@ def _write_function_declaration(self, elem: core.Function) -> None:
self._write_type_declaration(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}(")
Expand Down Expand Up @@ -641,6 +652,8 @@ 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)
else:
raise NotImplementedError(str(type(elem.data_type)))
result = ""
Expand Down Expand Up @@ -709,3 +722,71 @@ 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_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 {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