Added conversion from malloc to CONTAINER.resize()

This commit is contained in:
kevstone 2024-02-08 12:11:15 +00:00
parent a481d3896c
commit 0d3692512e
7 changed files with 122 additions and 16 deletions

View File

@ -4,6 +4,7 @@ import clang.cindex
import ast_object.ast_utils as ast_utils
import code_object.array_access as array_access
import code_object.binary_operation as binary_operation
import code_object.cast_expression as cast_expression
import code_object.code_objects as code_objects
import code_object.compound_statement as compound_statement
import code_object.conditional_operation as conditional_operation
@ -516,19 +517,24 @@ class AstParser:
return c_paren_expr
def parse_CXX_UNARY_EXPR(self, node):
keyword = node.spelling
if not keyword:
# Some unary expressions (e.g. sizeof) give an empty keyword, but we can extract it
# from the first token
# from the first token. In this case we have no child nodes and have to extract
# the expression from the tokens as well
tokens = [token.spelling for token in node.get_tokens()]
keyword = tokens[0]
assert keyword == "sizeof", f"Unexpected keyword [{keyword}] - not able to parse this (yet!)"
expression_text = literal.Literal(" ".join([t for t in tokens[2:-1]]))
expression = paren_expression.ParenExpression(expression_text)
else:
children = list(node.get_children())
assert len(children) == 1, f"Expected exactly one child for unary expression, got [{len(children)}]"
expression = self.parse_ast_node(children[0])
children = list(node.get_children())
assert len(children) == 1, f"Expected exactly one child for unary expression"
expression = children[0]
expression_value = self.parse_ast_node(expression)
c_unary_expr = unary_expression.UnaryExpression(keyword, expression_value)
c_unary_expr = unary_expression.UnaryExpression(keyword, expression)
debug.line("parse_CXX_UNARY_EXPR", f"Created c_unary_expr=[{debug.as_debug_string(c_unary_expr)}]")
return c_unary_expr
def parse_UNARY_OPERATOR(self, node):
@ -670,16 +676,25 @@ class AstParser:
def parse_CSTYLE_CAST_EXPR(self, node):
for child in node.get_children():
if child.kind == clang.cindex.CursorKind.UNEXPOSED_EXPR:
# We ignore the cast, and just return the object
return literal.Literal(child.spelling)
debug.line("parse_CSTYLE_CAST_EXPR", f"*** IGNORING *** child spelling=[{child.spelling}] type=[{child.type.spelling}] kind=[{child.kind}]")
cast_expression = "".join([t.spelling for t in node.get_tokens()])
debug.line("parse_CSTYLE_CAST_EXPR", f"Commenting out cast expression [{cast_expression}]")
return as_commented_out_code(cast_expression, "Removing unecessary cast")
tokens = [token.spelling for token in node.get_tokens()]
assert tokens[0] == "("
# Extract the cast value by finding the first ')' [note this will throw if not found!]
cast_value_end_index = tokens.index(")")
ccast_value = literal.Literal(f"{' '.join([t for t in tokens[1:cast_value_end_index]])}")
children = list(node.get_children())
child_count = len(children)
assert child_count == 1, f"Expected exactly one child node for cast expression, but got [{child_count}]"
cexpression = self.parse_ast_node(children[0])
ccast_expression = cast_expression.CastExpression("C", ccast_value, cexpression)
debug.line("parse_CSTYLE_CAST_EXPR", f"Created ccast_expression = [{debug.as_debug_string(ccast_expression)}]")
return ccast_expression
def parse_ARRAY_SUBSCRIPT_EXPR(self, node):
# We expect two children: the variable name and the index

View File

@ -0,0 +1,49 @@
import utils.debug as debug
import code_object.code_interface as code_interface
from utils.string_funcs import strip_semicolon
# Represent a cast expression form CAST EXPRESSION
#
# CAST can be:
# 1. C-style e.g. (char*)foo;
# 2. C++ style e.g. static_cast<char*>(foo)
cast_types = [
"C",
"static",
"dynamic",
"reinterpret"
]
class CastExpression(code_interface.CodeInterface):
def __init__(self, cast_type, cast_value, expression) -> None:
self._cast_type = cast_type
self._cast_value = cast_value
self._expression = expression
assert self._cast_type in cast_types, f"Invalid cast type [{self._cast_type}]"
assert isinstance(self._cast_value, code_interface.CodeInterface), f"Cast value must be a CodeInterface class"
assert isinstance(self._expression, code_interface.CodeInterface), f"Expression must be a CodeInterface class"
@property
def cast_type(self):
return self._cast_type
@property
def cast_value(self):
return self._cast_value
@property
def expression(self):
return self._expression
def as_lines(self):
if self._cast_type == "C":
cast_expression_string = f"({self._cast_value.as_string()}){strip_semicolon(self._expression.as_string())}"
else:
cast_expression_string = f"{self._cast_type}_cast<{self._cast_value.as_string()}>({strip_semicolon(self._expression.as_string())})"
if not cast_expression_string.endswith(";"):
cast_expression_string += ";"
return [cast_expression_string]

View File

@ -21,6 +21,11 @@ class FunctionCall(code_interface.CodeInterface):
def args(self):
return self._args
# return the arguments as a comma-separated list
@property
def arg_string(self):
return ",".join([strip_semicolon(a.as_string()) for a in self._args])
def add_arg(self, arg_entry):
assert isinstance(arg_entry, code_interface.CodeInterface), f"arg_entry must be a CodeInterface class, supplied=[{arg_entry}]"
self._args.append(arg_entry)

View File

@ -0,0 +1,19 @@
import utils.debug as debug
import code_object.cast_expression as cast_expression
import code_object_converter.code_interface_converter as code_interface_converter
import code_object_converter.conversion_funcs as conversion_funcs
class CastExpressionConverter(code_interface_converter.CodeInterfaceConverter):
def __init__(self, ccode_object) -> None:
super().__init__(ccode_object)
assert isinstance(ccode_object, cast_expression.CastExpression), f"Expected CastExpression, got type=[{type(ccode_object)}]"
def create_cpp_code_object(self, conversion_pack):
# By default, just switch to static_cast
cpp_cast_type = "static"
cpp_cast_value = conversion_funcs.convert_ccode_object(self._ccode_object.cast_value, conversion_pack)
cpp_expression = conversion_funcs.convert_ccode_object(self._ccode_object.expression, conversion_pack)
cppcast_expression = cast_expression.CastExpression(cpp_cast_type, cpp_cast_value, cpp_expression)
return conversion_pack.conversion_validation.validate_cast_expression(self._ccode_object, cppcast_expression)

View File

@ -2,6 +2,7 @@
import code_object.array_access as arr_access
import code_object.arg as arg
import code_object.binary_operation as binary_operation
import code_object.cast_expression as cast_expression
import code_object.code_objects as code_objects
import code_object.compound_statement as compound_statement
import code_object.conditional_operation as conditional_operation
@ -36,6 +37,7 @@ import code_object.while_statement as while_statement
import code_object_converter.array_access_converter as array_access_converter
import code_object_converter.arg_converter as arg_converter
import code_object_converter.binary_operation_converter as binary_operation_converter
import code_object_converter.cast_expression_converter as cast_expression_converter
import code_object_converter.code_objects_converter as code_objects_converter
import code_object_converter.compound_statement_converter as compound_statement_converter
import code_object_converter.conditional_operation_converter as conditional_operation_converter
@ -76,6 +78,7 @@ CodeInterfaceConverterClasses = {
arr_access.ArrayAccess : array_access_converter.ArrayAccessConverter,
arg.Arg : arg_converter.ArgConverter,
binary_operation.BinaryOperation : binary_operation_converter.BinaryOperationConverter,
cast_expression.CastExpression : cast_expression_converter.CastExpressionConverter,
code_objects.CodeObjects : code_objects_converter.CodeObjectsConverter,
compound_statement.CompoundStatement : compound_statement_converter.CompoundStatementConverter,
conditional_operation.ConditionalOperation : conditional_operation_converter.ConditionalOperationConverter,

View File

@ -27,6 +27,9 @@ class ConversionValidation:
def validate_binary_operation(self, cbinary_operation, cppbinary_operation):
return cppbinary_operation
def validate_cast_expression(self, ccast_expression, cppcast_expression):
return cppcast_expression
def validate_code_objects(self, ccode_objects, cppcode_objects):
return cppcode_objects

View File

@ -13,11 +13,13 @@ import code_object.virtual_member_function as virtual_member_function
import code_object.constructor_function as constructor_function
import code_object.function_call as function_call
import code_object_converter.conversion_pack.arg_utils as arg_utils
import code_object.cast_expression as cast_expression
from grib_accessor.grib_accessor_conversion_pack.grib_accessor_special_function_call_conversion import special_function_name_mapping
from code_object.code_interface import NONE_VALUE
import grib_accessor.grib_accessor_conversion_pack.grib_accessor_type_info as grib_accessor_type_info
from code_object_converter.conversion_funcs import as_commented_out_code
# Pass this to the conversion_data object to be accessed by the conversion routines
class GribAccessorConversionValidation(default_conversion_validation.DefaultConversionValidation):
@ -126,6 +128,16 @@ 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)
cppright = cppbinary_operation.right_operand
if isinstance(cppright, cast_expression.CastExpression):
cpp_func_call = cppright.expression
assert isinstance(cpp_func_call, function_call.FunctionCall), f"Expected cast expression to be a FunctionCall, not [{type(cpp_func_call)}]"
if cpp_func_call.name in ["gribContextMalloc", "gribContextRealloc"]:
# For now, we'll assume we're allocating a container (may need to revisit)
cpp_alloc = literal.Literal(f"{arg_utils.extract_name(cppbinary_operation.left_operand)}.resize({cpp_func_call.arg_string});")
debug.line("validate_binary_operation", f"Changed allocation operation from=[{debug.as_debug_string(cppbinary_operation)}] to [{debug.as_debug_string(cpp_alloc)}]")
return cpp_alloc
return super().validate_binary_operation(cbinary_operation, cppbinary_operation)