mirror of https://github.com/ecmwf/eccodes.git
Added conversion from malloc to CONTAINER.resize()
This commit is contained in:
parent
a481d3896c
commit
0d3692512e
|
@ -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
|
||||
|
|
|
@ -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]
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue