Added additional C to C++ conversions

This commit is contained in:
kevstone 2024-01-26 11:55:35 +00:00
parent 61ad744fcf
commit a4af69f1b5
7 changed files with 54 additions and 18 deletions

View File

@ -459,22 +459,18 @@ class AstParser:
def parse_DECL_REF_EXPR(self, node):
return value_declaration_reference.ValueDeclarationReference(node.spelling)
# This is simplified for now, need to come back to...
# The top-level node contains the tokens showing the access, e.g. [['self', '->', 'grid_type']]
# The child node defines the first parameter ("self" in this case)
# However, as we're just storing strings, we'll use the tokens directly!
def parse_MEMBER_REF_EXPR(self, node):
member_name = node.spelling
cstruct_member_access = struct_member_access.StructMemberAccess(None, member_name, None)
tokens = [token.spelling for token in node.get_tokens()]
debug.line("parse_MEMBER_REF_EXPR", f"[IN] node spelling=[{node.spelling}] type=[{node.type.spelling}] tokens=[{tokens}]")
assert len(tokens) == 3, f"Expected exactly 3 tokens for member ref, but got [{len(tokens)}]"
for child in node.get_children():
if child.kind == clang.cindex.CursorKind.UNEXPOSED_EXPR:
parent_name = child.spelling
cparent_struct_member_access = struct_member_access.StructMemberAccess(None, parent_name, None)
cstruct_member_access.access = "->"
cparent_struct_member_access.member = cstruct_member_access
return cparent_struct_member_access
debug.line("parse_MEMBER_REF_EXPR", f"*** IGNORING *** child spelling=[{child.spelling}] type=[{child.type.spelling}] kind=[{child.kind}]")
cstruct_member_access = struct_member_access.StructMemberAccess(None, tokens[0], None)
cstruct_member_access.member = struct_member_access.StructMemberAccess(tokens[1], tokens[2], None)
return None
return cstruct_member_access
def parse_CALL_EXPR(self, node):
tokens = [token.spelling for token in node.get_tokens()]

View File

@ -1,6 +1,7 @@
import utils.debug as debug
import code_object.code_interface as code_interface
import code_object.operation as operation
from utils.string_funcs import strip_semicolon
# Represent a binary operation of the form LEFT_OPERAND OP RIGHT_OPERAND
# Models the BINARY_OPERATOR CursorKind in libclang
@ -39,6 +40,8 @@ class BinaryOperation(code_interface.CodeInterface):
def as_lines(self):
lines = []
lines.extend(self._left_operand.as_lines())
lines[-1] = strip_semicolon(lines[-1])
lines[-1] += " " + self._binary_op.as_string()
right_lines = []

View File

@ -20,6 +20,10 @@ class ConversionValidation:
def validate_binary_operation(self, cbinary_operation, cppbinary_operation):
return cppbinary_operation
def validate_if_statement(self, cif_statement, cppif_statement):
return cppif_statement
# ---------- CodeObject Validation : End -----------------------------------------------------

View File

@ -13,4 +13,6 @@ class IfStatementConverter(code_interface_converter.CodeInterfaceConverter):
cpp_expression = conversion_funcs.convert_ccode_object(self._ccode_object.expression, conversion_pack)
cpp_action = conversion_funcs.convert_ccode_object(self._ccode_object.action, conversion_pack)
return if_statement.IfStatement(cpp_expression, cpp_action)
cpp_if = if_statement.IfStatement(cpp_expression, cpp_action)
return conversion_pack.conversion_validation.validate_if_statement(self._ccode_object, cpp_if)

View File

@ -6,12 +6,13 @@ from code_object.code_interface import NONE_VALUE
import code_object.function_call as function_call
import code_object.literal as literal
import re
import code_object.binary_operation as binary_operation
# Pass this to the conversion_data object to be accessed by the conversion routines
class DefaultConversionValidation(conversion_validation.ConversionValidation):
def validate_function_call(self, cfunction_call, cppfunction_call, callee_funcsig_mapping):
if callee_funcsig_mapping:
if callee_funcsig_mapping:
cpp_args = []
for arg_entry in callee_funcsig_mapping.cppfuncsig.args:
if arg_entry != NONE_VALUE:
@ -20,7 +21,10 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
cpp_args.append(cpp_arg_entry)
return function_call.FunctionCall(cppfunction_call.name, cpp_args)
return cppfunction_call
if cfunction_call.name == "strcmp":
return binary_operation.BinaryOperation(cppfunction_call.args[0], "==", cppfunction_call.args[1])
return cppfunction_call
# Check use of references when calling functions...
def validate_function_call_arg(self, calling_arg_value, target_arg):
@ -45,6 +49,13 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
if cpparg and self.is_cpp_container_type(cpparg.decl_spec):
return literal.Literal(f"{cpparg.name}.size()")
# If we've updated a strcmp function call, we need to remove the return value comparison
if cbinary_operation.left_operand.as_string().startswith("strcmp") and \
not cppbinary_operation.left_operand.as_string().startswith("strcmp"):
debug.line("validate_binary_operation", f"Removed strcmp return value comparison [{debug.as_debug_string(cppbinary_operation.binary_op)}][{debug.as_debug_string(cppbinary_operation.right_operand)}]")
return cppbinary_operation.left_operand
return cppbinary_operation
# Returns True is the name is a pointer to a class instance

View File

@ -3,8 +3,11 @@ import utils.debug as debug
import default.default_conversion_pack.default_conversion_validation as default_conversion_validation
import code_object.literal as literal
import code_object.variable_declaration as variable_declaration
import code_object.value_declaration_reference as value_declaration_reference
import code_object.binary_operation as binary_operation
from grib_accessor.grib_accessor_conversion_pack.grib_accessor_special_function_call_conversion import apply_special_function_call_conversions
from code_object.code_interface import NONE_VALUE
import code_object.if_statement as if_statement
# Pass this to the conversion_data object to be accessed by the conversion routines
class GribAccessorConversionValidation(default_conversion_validation.DefaultConversionValidation):
@ -37,9 +40,23 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv
if cppbinary_operation.right_operand.as_string().startswith("GribAccessorFlag"):
updated_right_operand = literal.Literal(f"toInt({cppbinary_operation.right_operand.as_string()})")
return binary_operation.BinaryOperation(cppbinary_operation.left_operand, cppbinary_operation.binary_op, updated_right_operand)
return super().validate_binary_operation(cbinary_operation, cppbinary_operation)
def validate_if_statement(self, cif_statement, cppif_statement):
# Update if(x) statement when type of x is enum GribStatus
if isinstance(cppif_statement.expression, value_declaration_reference.ValueDeclarationReference):
expression_value = cppif_statement.expression.as_string()
cpparg = self._conversion_data.funcbody_cpparg_for_carg_name(expression_value)
if cpparg and cpparg != NONE_VALUE and cpparg.decl_spec.type == "GribStatus":
updated_expression = literal.Literal(f"isError({cpparg.name})")
updated_cppif_statement = if_statement.IfStatement(updated_expression, cppif_statement.action)
debug.line("validate_if_statement", f"updated_cppif_statement=[{debug.as_debug_string(updated_cppif_statement)}]")
return updated_cppif_statement
return super().validate_if_statement(cif_statement, cppif_statement)
def is_pointer_to_class_instance(self, arg_name):
if arg_name in ["a"]:
return True

View File

@ -15,5 +15,8 @@ def apply_special_function_call_conversions(cfunction_call, cppfunction_call):
if cfunction_call.name == "snprintf":
return function_call.FunctionCall("fmtString", cppfunction_call.args)
if cfunction_call.name == "strlen":
return function_call.FunctionCall("fmtString", cppfunction_call.args)
return None