From 6ae5c4db0101ece2cd956d1b010be67d691be1d9 Mon Sep 17 00:00:00 2001 From: kevstone Date: Thu, 11 Jan 2024 09:56:44 +0000 Subject: [PATCH] Added if() support --- .../code_object/binary_operation.py | 4 +- src/clang_convert/code_object/if_statement.py | 59 +++++++++++++++++++ src/clang_convert/default/cnode_converter.py | 26 +++++++- 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100755 src/clang_convert/code_object/if_statement.py diff --git a/src/clang_convert/code_object/binary_operation.py b/src/clang_convert/code_object/binary_operation.py index 9252f3c52..151bfe836 100755 --- a/src/clang_convert/code_object/binary_operation.py +++ b/src/clang_convert/code_object/binary_operation.py @@ -45,6 +45,8 @@ class BinaryOperation(code_interface.CodeInterface): lines.extend(right_lines[1:]) - lines[-1] += ";" + # Determine whether to add a ; + if self._binary_op.is_assignment(): + lines[-1] += ";" return lines \ No newline at end of file diff --git a/src/clang_convert/code_object/if_statement.py b/src/clang_convert/code_object/if_statement.py new file mode 100755 index 000000000..aab89d922 --- /dev/null +++ b/src/clang_convert/code_object/if_statement.py @@ -0,0 +1,59 @@ +import debug +import code_object.code_interface as code_interface +import code_object.code_lines as code_lines + +# Represents an if statement in the form: +# +# if (expression) action else [...] +# +# [...] represents a child node, which could be another if, another action or None +# +# expression & action can be a string or a code_interface subclass (or None) +class IfStatement(code_interface.CodeInterface): + def __init__(self, expression, action) -> None: + if isinstance(expression, str): + self._expression = code_lines.CodeLines(expression) + else: + self._expression = expression + assert isinstance(self._expression, code_interface.CodeInterface), f"Expression must be a CodeInterface class (or a string)" + + if isinstance(action, str): + self._action = code_lines.CodeLines(action) + else: + self._action = action + assert isinstance(self._action, code_interface.CodeInterface), f"Action must be a CodeInterface class (or a string)" + + self._else = None + + @property + def expression(self): + return self._expression + + @property + def action(self): + return self._action + + def add_else(self, else_statement): + + if isinstance(else_statement, str): + self._else = code_lines.CodeLines(else_statement) + else: + self._else = else_statement + assert isinstance(self._else, code_interface.CodeInterface), f"Else statement must be a CodeInterface class (or a string)" + + def as_lines(self): + if_lines = self._expression.as_lines() + if_lines[0] = "if (" + if_lines[0] + if_lines[-1] += ")" + + action_lines = self._action.as_lines() + #action_lines[0] = "{" + action_lines[0] + #action_lines[-1] += "}" + + if self._else: + else_lines = self._else.as_lines() + else_lines[0] = "else " + else_lines[0] + else: + else_lines = [] + + return if_lines + action_lines + else_lines \ No newline at end of file diff --git a/src/clang_convert/default/cnode_converter.py b/src/clang_convert/default/cnode_converter.py index 5b7ddb526..cf9bc5e0f 100755 --- a/src/clang_convert/default/cnode_converter.py +++ b/src/clang_convert/default/cnode_converter.py @@ -14,6 +14,7 @@ import code_object.unary_operation as unary_operation import code_object.binary_operation as binary_operation import code_object.struct_member_access as struct_member_access import code_object.function_call as function_call +import code_object.if_statement as if_statement # Convert a C node (AST) into lines of C++ code # @@ -82,7 +83,7 @@ class CNodeConverter: debug.line("convert_node_not_implemented", f"*** kind=[{node.kind}] not implemented ***") cnode_utils.dump_node(node,5) debug.line("convert_node_not_implemented", f"No convert routine implemented for kind=[{node.kind}]") - assert False, f"No convert routine implemented for kind=[{node.kind}]" + #assert False, f"No convert routine implemented for kind=[{node.kind}]" return None # =================================== Macros Convert functions [BEGIN] =================================== @@ -124,9 +125,13 @@ class CNodeConverter: stmt_lines = code_lines.CodeLines() + stmt_lines.add_line("{") + for child in node.get_children(): stmt_lines.add_lines(self.convert_node(child)) + stmt_lines.add_line("}") + return stmt_lines # DECL_STMT is an "Adaptor class for mixing declarations with statements and expressions." @@ -161,13 +166,30 @@ class CNodeConverter: return code_lines.CodeLines(return_lines) + def convert_IF_STMT(self, node): + debug.line("convert_IF_STMT", f"IF spelling=[{node.spelling}] type=[{node.type.spelling}] kind=[{node.kind}]") + cnode_utils.dump_node(node, 2) + + children = list(node.get_children()) + child_count = len(children) + assert child_count >= 2, f"Expected at least two children for if statement" + + if_expression = self.convert_node(children[0]) + if_action = self.convert_node(children[1]) + if_stmt = if_statement.IfStatement(if_expression, if_action) + + if child_count == 3: + else_statement = self.convert_node(children[2]) + if_stmt.add_else(else_statement) + + return if_stmt convert_STMT_funcs = { clang.cindex.CursorKind.COMPOUND_STMT: convert_COMPOUND_STMT, clang.cindex.CursorKind.DECL_STMT: convert_DECL_STMT, clang.cindex.CursorKind.CASE_STMT: convert_node_not_implemented, clang.cindex.CursorKind.DEFAULT_STMT: convert_node_not_implemented, - clang.cindex.CursorKind.IF_STMT: convert_node_not_implemented, + clang.cindex.CursorKind.IF_STMT: convert_IF_STMT, clang.cindex.CursorKind.SWITCH_STMT: convert_node_not_implemented, clang.cindex.CursorKind.WHILE_STMT: convert_node_not_implemented, clang.cindex.CursorKind.DO_STMT: convert_node_not_implemented,