Additions/fixes to improve level 2 compilation count - now at 30 accessors

This commit is contained in:
kevstone 2024-02-21 21:41:12 +00:00
parent 9e89efabc6
commit 6c506b3111
42 changed files with 588 additions and 141 deletions

View File

@ -838,7 +838,7 @@ class AstParser:
debug.line("parse_MEMBER_REF_EXPR", f"[IN] node spelling=[{node.spelling}] type=[{node.type.spelling}] tokens=[{tokens}]")
assert len(tokens) >= 3, f"Expected at least 3 tokens for member ref, but got [{len(tokens)}]"
cstruct_member_access = ast_utils.create_code_object_from_tokens(tokens)
cstruct_member_access = ast_utils.create_struct_member_access_from_tokens(tokens)
debug.line("parse_MEMBER_REF_EXPR", f"[OUT] cstruct_member_access=[{debug.as_debug_string(cstruct_member_access)}]")

View File

@ -154,59 +154,8 @@ def create_cinit_list(cnode):
symbol_tokens = ["[", "]", "->", "."]
# Iterate over list of tokens and create the appropriate code_objects
def create_code_object_from_tokens(tokens, depth=0):
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}:IN] tokens={tokens}")
# Iterate over list of tokens and create the appropriate struct_member_access
def create_struct_member_access_from_tokens(tokens, depth=0):
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:IN] tokens={tokens}")
assert len(tokens) != 0
name = ""
# Build the name from the non-symbol token(s)
for tok in list(tokens):
if tok not in symbol_tokens:
name += tokens.pop(0)
else:
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] name = [{debug.as_debug_string(name)}] tokens={tokens}")
break
assert name and name not in symbol_tokens, f"Name token can't be in {symbol_tokens}!"
name_obj = literal.Literal(name)
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] name_obj=[{debug.as_debug_string(name_obj)}] [{type(name_obj)}]")
if len(tokens) == 0:
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}:OUT] No more tokens: name_obj=[{debug.as_debug_string(name_obj)}] [{type(name_obj)}]")
return name_obj
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}.1] tokens={tokens}")
symbol = tokens.pop(0)
if symbol == "[":
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] Found a [ - creating an array access object, tokens={tokens}")
index_obj = create_code_object_from_tokens(tokens, depth+1)
array_access_obj = array_access.ArrayAccess(name_obj, index_obj)
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] array_access_obj=[{debug.as_debug_string(array_access_obj)}] [{type(array_access_obj)}] tokens={tokens}")
name_obj = array_access_obj
if len(tokens) == 0:
return name_obj
symbol = tokens.pop(0)
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}.2] tokens={tokens}")
if symbol == "]":
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}:OUT] Found ], name_obj=[{debug.as_debug_string(name_obj)}] tokens={tokens}")
return name_obj
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}.3] tokens={tokens}")
if symbol in ["->", "."]:
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] Creating StructMemberAccess from tokens={tokens}")
member_name_obj = create_code_object_from_tokens(tokens, depth+1)
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] member_name_obj=[{debug.as_debug_string(member_name_obj)}]")
member_obj = struct_member_access.StructMemberAccess(symbol, member_name_obj)
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] member_obj=[{debug.as_debug_string(member_obj)}]")
struct_member_access_obj = struct_member_access.StructMemberAccess("", name_obj, member_obj)
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}:OUT] struct_member_access_obj=[{debug.as_debug_string(struct_member_access_obj)}] [{type(struct_member_access_obj)}]")
return struct_member_access_obj
debug.line("create_code_object_from_tokens", f"{' ' * depth}[{depth}.4] tokens={tokens}")
assert False, "Didn't expect to get here! tokens={tokens}"
return struct_member_access.create_struct_member_access_from_tokens(tokens)

View File

@ -22,4 +22,4 @@ class ArrayAccess(code_interface.CodeInterface):
return self._index
def as_lines(self):
return [f"{strip_semicolon(self._name.as_string())}[{self._index.as_string()}]"]
return [f"{strip_semicolon(self._name.as_string())}[{strip_semicolon(self._index.as_string())}]"]

View File

@ -51,7 +51,8 @@ class BinaryOperation(code_interface.CodeInterface):
lines.extend(right_lines[1:])
# Determine whether to add a ;
if self._binary_op.is_assignment() and not lines[-1].endswith(";"):
lines[-1] += ";"
if self._binary_op.is_assignment() or self._binary_op.is_arithmetic():
if not lines[-1].endswith(";"):
lines[-1] += ";"
return lines

View File

@ -1,5 +1,6 @@
import code_object.code_interface as code_interface
import code_object.code_objects as code_objects
from utils import debug
# Represents a group of code objects (CodeInterface classes) that make up a coherent collection of code (e.g. a function body)
# Provides convenient ways of accessing the underlying code

View File

@ -113,7 +113,10 @@ class DeclSpec(code_interface.CodeInterface):
def is_array_type(self):
return self._pointer.startswith("[")
def is_raw_pointer(self):
return self._pointer.startswith("*")
def array_size(self):
if self.is_array_type() and len(self._pointer) > 2:
return self._pointer[1:-1]

View File

@ -1,5 +1,6 @@
import utils.debug as debug
import code_object.code_interface as code_interface
from code_object.code_interface import NONE_VALUE
# Represents any literal: integer, float, char, string (quoted)
class Literal(code_interface.CodeInterface):
@ -10,5 +11,20 @@ class Literal(code_interface.CodeInterface):
def value(self):
return self._value
# ---------- Support for use as a dict key: Begin ----------
def __hash__(self):
return hash((self.value))
def __eq__(self, other):
if self is NONE_VALUE or other is NONE_VALUE:
return self is other
# Ensure the other object is an instance of StructMemberAccess for comparison.
if not isinstance(other, Literal):
return False
return self.value == other.value
# ---------- Support for use as a dict key: End ----------
def as_lines(self):
return [f"{self._value}"]

View File

@ -1,5 +1,6 @@
import code_object.code_interface as code_interface
import code_object.code_objects as code_objects
from utils import debug
# Represents a macro instantiation, for example
# BAR(42)
@ -24,7 +25,12 @@ class MacroInstantation(code_interface.CodeInterface):
return self._expression
def as_lines(self):
text = f"{self._name}{self._expression.as_string()};"
# Ensure it is all on one line!
text = text.replace("\n", "")
expression_string = self._expression.as_string().replace("\n", "")
if expression_string.endswith(";)"):
expression_string = expression_string[:-2] + ")"
text = f"{self._name}{expression_string};"
return [text]

View File

@ -19,14 +19,16 @@ class Operation(code_interface.CodeInterface):
return [f"{self._value}"]
def is_assignment(self):
return self._value in ["=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>="]
return self._value in ["="]
#return self._value in ["=", "+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>="]
def is_inc_dec(self):
return self._value in ["++", "--"]
def is_arithmetic(self):
return self._value in ["+", "-", "*", "/", "%", "~", "&", "|", "^", "<<", ">>"]
return self._value in ["+", "-", "*", "/", "%", "~", "&", "|", "^", "<<", ">>", #]
"+=", "-=", "*=", "/=", "%=", "&=", "|=", "^=", "<<=", ">>="]
def is_logical(self):
return self._value in ["!", "&&", "||"]

View File

@ -1,7 +1,10 @@
import code_object.code_interface as code_interface
import code_object.literal as literal
import code_object.array_access as array_access
import utils.debug as debug
from code_object.code_interface import NONE_VALUE
import re
# Represent the accessing of a struct member as defined in code, in order to manipulate/transform it
#
@ -56,6 +59,22 @@ class StructMemberAccess(code_interface.CodeInterface):
assert isinstance(value, StructMemberAccess), f"Member must be a StructMemberAccess class"
self._member = value
# ---------- Support for use as a dict key: Begin ----------
def __hash__(self):
return hash((self.access, self._variable, self._member))
def __eq__(self, other):
if self is NONE_VALUE or other is NONE_VALUE:
return self is other
# Ensure the other object is an instance of StructMemberAccess for comparison.
if not isinstance(other, StructMemberAccess):
return False
return self.access == other.access and self.variable == other.variable and self.member == other.member
# ---------- Support for use as a dict key: End ----------
def as_lines(self):
access_str = self._access if self._access is not None else ""
access_str += self._variable.as_string() if self._variable is not None else ""
@ -66,3 +85,79 @@ class StructMemberAccess(code_interface.CodeInterface):
access_str += ";"
return [access_str]
symbol_tokens = ["[", "]", "->", "."]
# Create from tokens e.g. ["a","->","b","->","c"]
def create_struct_member_access_from_tokens(tokens, depth=0):
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:IN] tokens={tokens}")
assert len(tokens) != 0
name = ""
# Build the name from the non-symbol token(s)
for tok in list(tokens):
if tok not in symbol_tokens:
name += tokens.pop(0)
else:
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] name = [{debug.as_debug_string(name)}] tokens={tokens}")
break
assert name and name not in symbol_tokens, f"Name token can't be in {symbol_tokens}!"
name_obj = literal.Literal(name)
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] name_obj=[{debug.as_debug_string(name_obj)}] [{type(name_obj)}]")
if len(tokens) == 0:
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:OUT] No more tokens: name_obj=[{debug.as_debug_string(name_obj)}] [{type(name_obj)}]")
return name_obj
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}.1] tokens={tokens}")
symbol = tokens.pop(0)
if symbol == "[":
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] Found a [ - creating an array access object, tokens={tokens}")
index_obj = create_struct_member_access_from_tokens(tokens, depth+1)
array_access_obj = array_access.ArrayAccess(name_obj, index_obj)
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] array_access_obj=[{debug.as_debug_string(array_access_obj)}] [{type(array_access_obj)}] tokens={tokens}")
name_obj = array_access_obj
if len(tokens) == 0:
return name_obj
symbol = tokens.pop(0)
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}.2] tokens={tokens}")
if symbol == "]":
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:OUT] Found ], name_obj=[{debug.as_debug_string(name_obj)}] tokens={tokens}")
return name_obj
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}.3] tokens={tokens}")
if symbol in ["->", "."]:
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] Creating StructMemberAccess from tokens={tokens}")
member_name_obj = create_struct_member_access_from_tokens(tokens, depth+1)
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] member_name_obj=[{debug.as_debug_string(member_name_obj)}]")
member_obj = StructMemberAccess(symbol, member_name_obj)
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}] [{symbol}] member_obj=[{debug.as_debug_string(member_obj)}]")
struct_member_access_obj = StructMemberAccess("", name_obj, member_obj)
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}:OUT] struct_member_access_obj=[{debug.as_debug_string(struct_member_access_obj)}] [{type(struct_member_access_obj)}]")
return struct_member_access_obj
debug.line("create_struct_member_access_from_tokens", f"{' ' * depth}[{depth}.4] tokens={tokens}")
assert False, f"Didn't expect to get here! tokens={tokens}"
# Helper to create from a string e.g. "a->b->c->"
def struct_member_access_from_string(tokenstring, depth=0):
# Create a regular expression pattern that captures any of the tokens
# and also matches sequences of characters that are not the tokens
# The pattern has two parts:
# 1. A non-capturing group (?:...) with alternatives for each token, escaped as needed
# 2. A segment to match any sequence of characters not matching the first part, using [^...]+
pattern = '(' + '|'.join(re.escape(token) for token in symbol_tokens) + ')|([^' + ''.join(re.escape(token) for token in symbol_tokens) + ']+)'
# Use re.findall() with the pattern to find all matches, including tokens
matches = re.findall(pattern, tokenstring)
# Flatten the resulting list of tuples and filter out empty strings
tokens = [item for sublist in matches for item in sublist if item]
return create_struct_member_access_from_tokens(tokens)

View File

@ -38,7 +38,7 @@ class ArgConverter(code_interface_converter.CodeInterfaceConverter):
if cpp_arg:
return cpp_arg
debug.line("convert_funcsig_arg", f"--[2]-- carg=[{debug.as_debug_string(cpp_arg)}]")
debug.line("convert_funcsig_arg", f"--[2]-- cpp_arg=[{debug.as_debug_string(cpp_arg)}]")
# 2. Check if the C type should not be converted (e.g. grib_handle*)
test_decl_spec = declaration_specifier.DeclSpec.from_instance(carg.decl_spec)
@ -86,6 +86,8 @@ class ArgConverter(code_interface_converter.CodeInterfaceConverter):
cpp_arg = arg.Arg(new_decl_spec, cpp_name, cpp_is_func_arg)
debug.line("create_funcsig_cpparg", f"Created cpp_arg=[{debug.as_debug_string(cpp_arg)}] from carg=[{debug.as_debug_string(carg)}]")
self._conversion_pack.conversion_data.add_funcsig_arg_mapping(carg, cpp_arg)
debug.line("create_funcsig_cpparg", f"Arg conversion arg mapping: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpp_arg)}]")

View File

@ -10,6 +10,7 @@ class CodeMappings:
self._funcsig_type_mappings = {}
self._funcsig_buffer_mappings = [] # Don't expect more than one entry, but just in case!
self._data_member_mappings = {}
self._struct_member_access_mappings = {}
self._funcsig_mappings = []
self._funcsig_pointer_mappings = []
self._member_funcsig_mappings = []
@ -43,6 +44,10 @@ class CodeMappings:
def data_member_mappings(self):
return self._data_member_mappings
@property
def struct_member_access_mappings(self):
return self._struct_member_access_mappings
@property
def all_funcsig_mappings(self):
return self._funcsig_mappings + self._member_funcsig_mappings + self._virtual_member_funcsig_mappings

View File

@ -8,6 +8,7 @@ from code_object.arg import Arg
from code_object.function_call import FunctionCall
from code_object.funcsig import FuncSig
from code_object.data_member import DataMember
from code_object.struct_member_access import StructMemberAccess
from code_object.declaration_specifier import DeclSpec
from code_object_converter.conversion_pack.conversion_data_helper import *
from code_object.code_interface import NONE_VALUE
@ -58,6 +59,10 @@ class ConversionData:
else:
return [self._global_mappings]
@property
def current_cfuncname(self):
return self._current_cfuncname
# ============================== Funcsig mappings: start ==============================
# ------------------------------ SET ------------------------------
@ -201,6 +206,11 @@ class ConversionData:
def add_funcsig_arg_mapping(self, carg, cpparg):
assert isinstance(carg, Arg), f"Expected Arg, got [{carg}]"
assert isinstance(cpparg, Arg) or cpparg==NONE_VALUE, f"Expected Arg, got [{cpparg}]"
if not carg.name or (cpparg and cpparg != NONE_VALUE and not cpparg.name):
debug.line("add_funcsig_arg_mapping", f"*** WARNING *** Not adding arg mapping due to missing name (must be an anonymous/unused funcsig arg) : carg=[{debug.as_debug_string(carg)}] cpparg=[{debug.as_debug_string(cpparg)}]")
return
if carg in self.active_map.funcsig_arg_mappings:
assert self.active_map.funcsig_arg_mappings[carg] == cpparg, f"Updating an existing funcsig arg: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpparg)}] Previous function arg=[{debug.as_debug_string(self.active_map.funcsig_arg_mappings[carg])}]"
else:
@ -265,6 +275,7 @@ class ConversionData:
# See conversion_data_helper.find_best_matching_cdecl_spec() for more info
#
def closest_funcbody_cppdecl_spec_for_cdecl_spec(self, cdecl_spec):
matches = []
for mapping in self.all_mappings():
for key, value in mapping.funcbody_type_mappings.items():
@ -348,6 +359,16 @@ class ConversionData:
self.active_map.data_member_mappings[cmember] = cppmember
debug.line("add_data_member_mapping", f"Adding data member: [{debug.as_debug_string(cmember)}] -> [{debug.as_debug_string(cppmember)}]")
def add_struct_member_access_mapping(self, cstruct_member_access, cppstruct_member_access):
assert isinstance(cstruct_member_access, StructMemberAccess), f"Expected StructMemberAccess, got [{cstruct_member_access}]"
assert isinstance(cppstruct_member_access, StructMemberAccess) or cppstruct_member_access==NONE_VALUE, f"Expected StructMemberAccess, got [{cppstruct_member_access}]"
if cstruct_member_access in self.active_map.struct_member_access_mappings:
assert self.active_map.struct_member_access_mappings[cstruct_member_access] == cppstruct_member_access, f"Updating an existing data member: [{debug.as_debug_string(cstruct_member_access)}] -> [{debug.as_debug_string(cppstruct_member_access)}] Previous value=[{debug.as_debug_string(self.active_map.data_member_mappings[cstruct_member_access])}]"
else:
self.active_map.struct_member_access_mappings[cstruct_member_access] = cppstruct_member_access
debug.line("add_struct_member_access_mapping", f"Adding StructMemberAccess: [{debug.as_debug_string(cstruct_member_access)}] -> [{debug.as_debug_string(cppstruct_member_access)}]")
def add_literal_mapping(self, cstring, cppstring):
assert isinstance(cstring, str), f"Expected str, got [{cstring}]"
assert isinstance(cppstring, str), f"Expected str, got [{cppstring}]"
@ -491,7 +512,14 @@ class ConversionData:
return value
return None
#def funcsig_buffer_mapping_for
def get_cppstruct_member_access(self, cstruct_member_access):
for mapping in self.all_mappings():
for key, value in mapping.struct_member_access_mappings.items():
if key == cstruct_member_access:
return value
return None
# Searches both C and C++ member and virtual member maps
# NOTE: cppfuncsig will be none for "discovered" virtual functions until they have been converted!

View File

@ -76,13 +76,26 @@ def create_best_matching_cdecl_spec(cdecl_spec, matches):
# Rank the results
ranked_scored_matches = sorted(scored_matches.items(), key=lambda x: x[1], reverse=True)
result, score = ranked_scored_matches[0]
debug.line("create_best_matching_cdecl_spec", f" Result: key=[{debug.as_debug_string(result[key])}] value=[{debug.as_debug_string(result[value])}] match=[{score}]")
result_decl_spec = result[value]
debug.line("create_best_matching_cdecl_spec", f" Result: key=[{debug.as_debug_string(result[key])}] value=[{debug.as_debug_string(result_decl_spec)}] match=[{score}]")
# Create the new DeclSpec
if result[value] == NONE_VALUE:
if result_decl_spec == NONE_VALUE:
new_decl_spec = NONE_VALUE
else:
new_decl_spec = declaration_specifier.DeclSpec.from_instance(result[value])
# Check we're not assigning a container to a non-container type
if cdecl_spec.pointer == "" and result_decl_spec.type.startswith("std::"):
if result_decl_spec.type == "std::string":
new_decl_spec = declaration_specifier.DeclSpec.from_decl_specifier_seq("char")
else:
# Assume it is std::CONTAINER<TYPE>
start = result_decl_spec.type.index("<") + 1
end = result_decl_spec.type.index(">")
new_decl_spec = declaration_specifier.DeclSpec.from_decl_specifier_seq(result_decl_spec.type[start:end])
else:
new_decl_spec = declaration_specifier.DeclSpec.from_instance(result_decl_spec)
if not (score & DeclSpecMatchType.POINTER.value):
new_decl_spec.pointer = cdecl_spec.pointer

View File

@ -15,14 +15,20 @@ class StructMemberAccessConverter(code_interface_converter.CodeInterfaceConverte
def create_cpp_code_object(self, conversion_pack):
self._conversion_pack = conversion_pack
cstruct_member_access = self._ccode_object
cppstruct_member_access = None
debug.line("create_cpp_code_object",f"StructMemberAccessConverter [IN] cstruct_member_access=[{debug.as_debug_string(cstruct_member_access)}]")
# Check if this is a pointer to a class member
variable_name = arg_utils.extract_name(cstruct_member_access.variable)
if conversion_pack.conversion_data.is_self_class_pointer_name(variable_name):
debug.line("create_cpp_code_object",f"StructMemberAccessConverter [1] cstruct_member_access.variable=[{debug.as_debug_string(cstruct_member_access.variable)}] is a self class pointer variable")
cppstruct_member_access = self.try_to_convert_data_member_access(cstruct_member_access.member)
# Do we have a mapping?
cppstruct_member_access = conversion_pack.conversion_data.get_cppstruct_member_access(cstruct_member_access)
debug.line("create_cpp_code_object",f"StructMemberAccessConverter Mapping check: cppstruct_member_access=[{debug.as_debug_string(cppstruct_member_access)}]")
if not cppstruct_member_access:
# Check if this is a pointer to a class member
variable_name = arg_utils.extract_name(cstruct_member_access.variable)
debug.line("create_cpp_code_object",f"StructMemberAccessConverter [1.1] variable_name=[{debug.as_debug_string(variable_name)}]")
if conversion_pack.conversion_data.is_self_class_pointer_name(variable_name):
debug.line("create_cpp_code_object",f"StructMemberAccessConverter [1.2] cstruct_member_access.variable=[{debug.as_debug_string(cstruct_member_access.variable)}] is a self class pointer variable")
cppstruct_member_access = self.try_to_convert_data_member_access(cstruct_member_access.member)
if not cppstruct_member_access:
# Check if the primary member is valid...

View File

@ -12,9 +12,11 @@ import code_object_converter.conversion_pack.arg_utils as arg_utils
import code_object.variable_declaration as variable_declaration
import code_object.paren_expression as paren_expression
import code_object.array_access as array_access
import code_object.if_statement as if_statement
from code_object_converter.conversion_utils import as_commented_out_code
from utils.string_funcs import is_number
import code_object.cast_expression as cast_expression
from utils.string_funcs import strip_semicolon
# Pass this to the conversion_data object to be accessed by the conversion routines
class DefaultConversionValidation(conversion_validation.ConversionValidation):
@ -112,9 +114,9 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
cpp_empty_call = literal.Literal(f"{cpparg.name}.empty()")
debug.line("validate_unary_operation", f"Updating empty evaluation: [{debug.as_debug_string(cppunary_operation)}]->[{debug.as_debug_string(cpp_empty_call)}]")
return cpp_empty_call
else:
elif cppunary_operation.unary_op.value[0] in ["*", "&", "["]:
# C++ variable is a container, so we'll strip the *
debug.line("validate_unary_operation", f"Stripping [*] from cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]")
debug.line("validate_unary_operation", f"Stripping [{cppunary_operation.unary_op.value[0]}] from cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]")
return cppunary_operation.operand
elif cpparg.decl_spec.pointer == "&" and cppunary_operation.unary_op.is_member_access():
debug.line("validate_unary_operation", f"Stripping [*] from ref type: current cppunary_operation=[{debug.as_debug_string(cppunary_operation)}]")
@ -161,7 +163,7 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
elif cppright.as_string() == "0":
cppleft.member.name = literal.Literal("clear()")
else:
cppleft.member.name = literal.Literal(f"resize({cppright.as_string()})")
cppleft.member.name = literal.Literal(f"resize({strip_semicolon(cppright.as_string())})")
# Double-check it's not const!
debug.line("validate_binary_operation", f"Performing const check cppleft.name=[{debug.as_debug_string(cppleft.name)}] cpparg=[{debug.as_debug_string(cpparg)}]")
@ -172,12 +174,16 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
# See if we're assigning a single value to a container type
if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type):
cppright_value = cppright.as_string()
right_cpparg = arg_utils.to_cpparg(cppright, self._conversion_data)
if right_cpparg and self._conversion_data.is_container_type(right_cpparg.decl_spec.type):
debug.line("validate_binary_operation", f"Assigning container to container - nothing to do: left arg=[{debug.as_debug_string(cpparg)}] right arg=[{debug.as_debug_string(right_cpparg)}]")
else:
cppright_value = cppright.as_string()
if is_number(cppright_value) or not self.is_cppfunction_returning_container(cppright):
cppleft = array_access.ArrayAccess(cppleft.name, literal.Literal("0"))
debug.line("validate_binary_operation", f"Assigning number to container, so updating it to access first element: cppleft=[{debug.as_debug_string(cppleft)}] cppright_value=[{cppright_value}]")
return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright)
if is_number(cppright_value) or not self.is_cppfunction_returning_container(cppright):
cppleft = array_access.ArrayAccess(cppleft.name, literal.Literal("0"))
debug.line("validate_binary_operation", f"Assigning number to container, so updating it to access first element: cppleft=[{debug.as_debug_string(cppleft)}] cppright_value=[{cppright_value}]")
return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright)
# Check if we're assigning to a data member and need to ensure the function is non-const
data_member_name = arg_utils.extract_name(cppleft.name)
@ -186,11 +192,32 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
if self._conversion_data.is_cppdata_member(data_member_name):
self._conversion_data.set_current_cfuncname_non_const()
else:
# Other checks when assigning a container to a variable...
left_cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data)
right_cpparg = arg_utils.to_cpparg(cppright, self._conversion_data)
if left_cpparg and right_cpparg:
debug.line("validate_binary_operation", f"Container assignment check: left_cpparg=[{debug.as_debug_string(left_cpparg)}] right_cpparg=[{debug.as_debug_string(right_cpparg)}] ")
if self._conversion_data.is_container_type(right_cpparg.decl_spec.type) and \
not self._conversion_data.is_container_type(left_cpparg.decl_spec.type):
if left_cpparg.decl_spec.is_raw_pointer():
# We are assigning a container value to a pointer arg, so need to call .data()
cppright = literal.Literal(f"{right_cpparg.name}.data()")
return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright)
if not left_cpparg.decl_spec.pointer:
# We are assigning a container value to a basic variable, so use index 0
cppright = array_access.ArrayAccess(literal.Literal(right_cpparg.name), literal.Literal("0"))
return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright)
elif cppbinary_op.is_comparison():
cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data)
if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type):
cppleft = literal.Literal(f"{cpparg.name}.size()")
return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright)
if cppright.as_string() in ["NULL", "0"]:
return literal.Literal(f"{cpparg.name}.empty()")
else:
cppleft = literal.Literal(f"{cpparg.name}.size()")
return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright)
elif cppbinary_op.value == "+":
cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data)
@ -199,7 +226,7 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
cpparray_access = array_access.ArrayAccess(literal.Literal(cpparg.name), cppright)
return cpparray_access
elif cppbinary_op.is_arithmetic:
elif cppbinary_op.is_arithmetic():
cpparg = arg_utils.to_cpparg(cppleft, self._conversion_data)
if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type):
# We'll assume the arithmetic is against index 0
@ -211,6 +238,11 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
return updated_cppbinary_operation
elif cppbinary_op.is_logical():
cppleft = self.try_to_make_boolean(cppleft)
cppright = self.try_to_make_boolean(cppright)
return binary_operation.BinaryOperation(cppleft, cppbinary_op, cppright)
return cppbinary_operation
def validate_variable_declaration(self, cvariable_declaration, cppvariable_declaration):
@ -225,14 +257,38 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
cppcontainer_constructor_call = literal.Literal(f"{cppvariable.as_string()}({cvariable.decl_spec.array_size()},{{}});")
debug.line("validate_variable_declaration", f"Creating cppvariable=[{debug.as_debug_string(cppvariable)}] with initial size=[{cvariable.decl_spec.array_size()}] cppcontainer_constructor_call=[{debug.as_debug_string(cppcontainer_constructor_call)}]")
return cppcontainer_constructor_call
if cppvalue.as_string() == "NULL":
if cppvalue.as_string() in ["NULL", "0"]:
# Init as {}
debug.line("validate_variable_declaration", f"Changing NULL initialiser for container cppvariable=[{debug.as_debug_string(cppvariable)}] to [= {{}}")
cppvalue = literal.Literal("{}")
return variable_declaration.VariableDeclaration(cppvariable, cppvalue)
# Checks when assigning a container to a variable...
variable_cpparg = arg_utils.to_cpparg(cppvariable, self._conversion_data)
value_cpparg = arg_utils.to_cpparg(cppvariable_declaration.value, self._conversion_data)
if variable_cpparg and value_cpparg:
debug.line("validate_variable_declaration", f"Container assignment check: variable_cpparg=[{debug.as_debug_string(variable_cpparg)}] value_cpparg=[{debug.as_debug_string(value_cpparg)}] ")
if self._conversion_data.is_container_type(value_cpparg.decl_spec.type) and \
not self._conversion_data.is_container_type(variable_cpparg.decl_spec.type):
if variable_cpparg.decl_spec.is_raw_pointer():
# We are assigning a container value to a pointer arg, so need to call .data()
updated_value = literal.Literal(f"{value_cpparg.name}.data()")
return variable_declaration.VariableDeclaration(cppvariable, updated_value)
if not variable_cpparg.decl_spec.pointer:
# We are assigning a container value to a basic variable, so use index 0
updated_value = array_access.ArrayAccess(literal.Literal(value_cpparg.name), literal.Literal("0"))
return variable_declaration.VariableDeclaration(cppvariable, updated_value)
return cppvariable_declaration
def validate_if_statement(self, cif_statement, cppif_statement):
cppexpression = self.try_to_make_boolean(cppif_statement.expression)
return if_statement.IfStatement(cppexpression, cppif_statement.action)
# Helper to determine how a container should receive the value returned by the function
# Returns True if the function returns e.g. std::vector<int> instead of int
# Override as required...
@ -244,4 +300,22 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
if cppfuncsig and self._conversion_data.is_container_type(cppfuncsig.return_type.type):
return True
return False
return False
# If there is a boolean output available, return it, else just return the original object
#
# NOTE: Add more types as required (perhaps put in a separate class/file?)
def try_to_make_boolean(self, cppcode_object):
if isinstance(cppcode_object, unary_operation.UnaryOperation):
cpparg = arg_utils.to_cpparg(cppcode_object.operand, self._conversion_data)
if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type):
updated_operand = literal.Literal(f"{cpparg.name}.empty()")
return unary_operation.UnaryOperation(cppcode_object.unary_op, updated_operand, cppcode_object.op_position)
if isinstance(cppcode_object, struct_member_access.StructMemberAccess):
cpparg = arg_utils.to_cpparg(cppcode_object.name, self._conversion_data)
if cpparg and self._conversion_data.is_container_type(cpparg.decl_spec.type):
return literal.Literal(f"{cpparg.name}.empty()")
return cppcode_object

View File

@ -17,7 +17,8 @@ class GribAccessorAstCodeConverter(default_ast_code_converter.DefaultAstCodeConv
def create_ccode(self):
cfilename = self._ast_code.cfilename
self._accessor_class_name = cfilename.rstrip(".cc")
assert cfilename.endswith(".cc"), f"Expected filename=[{cfilename}] to have .cc extension"
self._accessor_class_name = cfilename[:-3]
self._accessor_name = self._accessor_class_name.replace("grib_accessor_class", "grib_accessor")
self._ccode = grib_accessor_ccode.GribAccessorCCode(cfilename, self._accessor_name, self._accessor_class_name)

View File

@ -34,9 +34,9 @@ class GribAccessorCCode(default_ccode.DefaultCCode):
def is_member_function(self, cfuncsig):
if not self.is_virtual_member_function(cfuncsig):
# If any arg starts with a "ptr type name", then it's a member function (as we've already extracted virtual functions)
for arg_entry in cfuncsig.args:
if re.search(r"grib_accessor(\w*)?\s*\*", arg_entry.decl_spec.as_string()):
# If first arg starts with a "ptr type name", then it's a member function (as we've already extracted virtual functions)
if len(cfuncsig.args) > 0:
if re.search(r"grib_accessor(\w*)?\s*\*", cfuncsig.args[0].decl_spec.as_string()):
return True
return False

View File

@ -121,7 +121,7 @@ class GribAccessorCCodeConverter(default_ccode_converter.DefaultCCodeConverter):
for mapping in grib_accessor_virtual_member_funcsig_mapping:
conv_data.add_global_virtual_member_funcsig_mapping(mapping)
self._conversion_pack_updates.add_funcsig_mappings_to_conversion_data(conv_data)
self._conversion_pack_updates.add_accessor_wide_conversion_data(conv_data)
all_funcsig_mappings.add_all_funcsig_mappings_to_conversion_data(conv_data)
@ -153,6 +153,7 @@ class GribAccessorCCodeConverter(default_ccode_converter.DefaultCCodeConverter):
conv_pack.conversion_data.info.header_includes.append(inc)
# Source includes
debug.line("SOURCE INCLUDE", f"class_name=[{conv_pack.conversion_data.info.class_name}] Header Entry=[\"{conv_pack.conversion_data.info.class_name}.h\"]")
conv_pack.conversion_data.info.source_includes.append(f"\"{conv_pack.conversion_data.info.class_name}.h\"")
for inc in includes.grib_accessor_source_includes:

View File

@ -6,6 +6,8 @@ from code_object_converter.conversion_pack.funcsig_mapping import FuncSigMapping
from code_object_converter.conversion_pack.arg_indexes import ArgIndexes
from code_object.funcsig import FuncSig
from code_object.code_interface import NONE_VALUE
from code_object.data_member import DataMember
from code_object.struct_member_access import create_struct_member_access_from_tokenstring
class TemplateConversionPackUpdates(base_conversion_pack_updates.BaseConversionPackUpdates):
def __init__(self) -> None:
@ -15,7 +17,11 @@ class TemplateConversionPackUpdates(base_conversion_pack_updates.BaseConversionP
"pack_long": self.apply_updates_for_pack_long
})
self._include_files.extend([
self._header_includes.extend([
"BufrDefs.h",
])
self._source_includes.extend([
"<float.h>",
])
@ -30,5 +36,13 @@ class TemplateConversionPackUpdates(base_conversion_pack_updates.BaseConversionP
Arg("unsigned char*","p") : Arg("AccessorDataPointer","p"),
})
self._data_member_mappings.update({
DataMember("foo*", "bar"): DataMember("Foo", "bar_"),
})
self._all_function_struct_member_access_mappings.update({
create_struct_member_access_from_tokenstring("foo->bar"): create_struct_member_access_from_tokenstring("foo_.bar_"),
})
def apply_updates_for_pack_long(self, conversion_pack):
conversion_pack.conversion_data.add_funcbody_arg_mapping(Arg("unsigned char*","mdata"), Arg("AccessorDataPointer","mdata"))

View File

@ -9,13 +9,28 @@ class BaseConversionPackUpdates:
self._update_funcs = {}
self._funcsig_mappings = []
self._all_function_arg_mappings = {}
self._include_files = []
self._header_includes = []
self._source_includes = []
self._data_member_mappings = {
DataMember("const char*", "cclass->name"): DataMember("std::string", "name_"),
}
self._all_function_struct_member_access_mappings = {}
def add_funcsig_mappings_to_conversion_data(self, conversion_data):
def add_accessor_wide_conversion_data(self, conversion_data):
for mapping in self._funcsig_mappings:
debug.line("add_funcsig_mappings_to_conversion_data", f"Adding funcsig mapping: [{mapping.cfuncsig.name}] -> [{mapping.cppfuncsig.name}]")
conversion_data.add_global_funcsig_mapping(mapping)
for cmember, cppmember in self._data_member_mappings.items():
conversion_data.add_data_member_mapping(cmember, cppmember)
for entry in self._header_includes:
conversion_data.info.add_header_include(entry)
for entry in self._source_includes:
conversion_data.info.add_source_include(entry)
# Use this entry point to call the appropriate derived function
def apply_updates_for_cfunction(self, cfuncname, conversion_pack):
@ -29,13 +44,14 @@ class BaseConversionPackUpdates:
# Override to set the same update for all functions
# NOTE: Doesn't apply to global definition
def apply_updates_for_all_functions(self, conversion_pack):
# Default data member mappings
for cmember, cppmember in {
DataMember("grib_accessor_class**", "cclass->super"): DataMember("AccessorData", conversion_pack.conversion_data.info.super_class_name),
DataMember("const char*", "cclass->name"): DataMember("std::string", "name_"),
}.items():
conversion_pack.conversion_data.add_data_member_mapping(cmember, cppmember)
# Add super class as data member
conversion_pack.conversion_data.add_data_member_mapping(DataMember("grib_accessor_class**", "cclass->super"),
DataMember("AccessorData",
conversion_pack.conversion_data.info.super_class_name))
# All function arg mappings
for carg, cpparg in self._all_function_arg_mappings.items():
conversion_pack.conversion_data.add_funcbody_arg_mapping(carg, cpparg)
for cstruct_member_access, cppstruct_member_access in self._all_function_struct_member_access_mappings.items():
conversion_pack.conversion_data.add_struct_member_access_mapping(cstruct_member_access, cppstruct_member_access)

View File

@ -0,0 +1,29 @@
import utils.debug as debug
import grib_accessor.grib_accessor_conversion_pack.conversion_pack_updates.base_conversion_pack_updates as base_conversion_pack_updates
from code_object.arg import Arg
from code_object_converter.conversion_pack.funcsig_mapping import FuncSigMapping
from code_object_converter.conversion_pack.arg_indexes import ArgIndexes
from code_object.funcsig import FuncSig
from code_object.code_interface import NONE_VALUE
from code_object.data_member import DataMember
from code_object.struct_member_access import struct_member_access_from_string
class BufrDataElementConversionPackUpdates(base_conversion_pack_updates.BaseConversionPackUpdates):
def __init__(self) -> None:
super().__init__()
self._header_includes.extend([
"GribCpp/BufrDefs.h",
])
self._data_member_mappings.update({
DataMember("bufr_descriptors_array*", "descriptors"): DataMember("BufrDescriptorsArray", "descriptors"),
})
self._all_function_struct_member_access_mappings.update({
struct_member_access_from_string("creator.op") : struct_member_access_from_string("creator.op_"),
struct_member_access_from_string("creator.name_space") : struct_member_access_from_string("creator.nameSpace_"),
struct_member_access_from_string("creator.set") : struct_member_access_from_string("creator.set_"),
struct_member_access_from_string("creator.name") : struct_member_access_from_string("creator.name_"),
})

View File

@ -11,6 +11,6 @@ class ClosestDateConversionPackUpdates(base_conversion_pack_updates.BaseConversi
def __init__(self) -> None:
super().__init__()
self._include_files.extend([
self._source_includes.extend([
"<float.h>",
])

View File

@ -7,13 +7,32 @@ from code_object_converter.conversion_pack.arg_indexes import ArgIndexes
from code_object.funcsig import FuncSig
from code_object.code_interface import NONE_VALUE
class ApplyBoustrophedonicConversionPackUpdates(base_conversion_pack_updates.BaseConversionPackUpdates):
class DataApplyBoustrophedonicConversionPackUpdates(base_conversion_pack_updates.BaseConversionPackUpdates):
def __init__(self) -> None:
super().__init__()
self._update_funcs.update({
"unpack_helper": self.apply_updates_for_unpack_helper,
"pack_double": self.apply_updates_for_pack_double,
})
self._funcsig_mappings.extend([
# template<typename T> static int unpack_helper(grib_accessor* a, T* val, size_t* len)
FuncSigMapping(FuncSig("int", "unpack_helper", [Arg("grib_accessor*", "a"), Arg("T*", "val"), Arg("size_t*", "len")]),
FuncSig("GribStatus", "unpackHelper", [NONE_VALUE, Arg("std::vector<T>&", "vecTValues"), NONE_VALUE]),
ArgIndexes(cbuffer=1, clength=2, cpp_container=1)),
])
def apply_updates_for_unpack_helper(self, conversion_pack):
for key,value in {
Arg("double*","pvalues") : Arg("double*","pvalues"),
Arg("T*","pval") : Arg("T*","pval"),
}.items():
conversion_pack.conversion_data.add_funcbody_arg_mapping(key, value)
def apply_updates_for_pack_double(self, conversion_pack):
for key,value in {
Arg("double*","pvalues") : Arg("double*","pvalues"),
Arg("double*","pval") : Arg("const double*","pval"),
}.items():
conversion_pack.conversion_data.add_funcbody_arg_mapping(key, value)

View File

@ -7,6 +7,7 @@ import code_object.code_objects as code_objects
import code_object.compound_statement as compound_statement
import code_object.variable_declaration as variable_declaration
import code_object.binary_operation as binary_operation
import code_object.unary_operation as unary_operation
import code_object.value_declaration_reference as value_declaration_reference
import code_object.if_statement as if_statement
import code_object.virtual_member_function as virtual_member_function
@ -133,14 +134,14 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv
# If we're calling grib_XXX which is a virtual member function, and the first argument is "a", then we're actually calling ourself!
if cfunction_call.name.startswith("grib_"):
updated_cfuncname = cfunction_call.name[5:]
if self._conversion_data.is_virtual_member_function(updated_cfuncname) and \
len(cfunction_call.args) > 0 and cfunction_call.args[0].as_string() == "a":
mapping = self._conversion_data.funcsig_mapping_for_cfuncname(updated_cfuncname)
if mapping:
updated_cppfunction_call = function_call.FunctionCall(mapping.cppfuncsig.name, cppfunction_call.args[1:])
updated_cppfunction_call = self.validate_function_call_args(updated_cppfunction_call, mapping.cppfuncsig)
debug.line("apply_special_function_call_conversions", f"Updated C++ function call=[{debug.as_debug_string(cppfunction_call)}] to [{debug.as_debug_string(updated_cppfunction_call)}]")
return updated_cppfunction_call
if self._conversion_data.is_virtual_member_function(updated_cfuncname):
if len(cfunction_call.args) > 0 and cfunction_call.args[0].as_string() in ["a"]:
mapping = self._conversion_data.funcsig_mapping_for_cfuncname(updated_cfuncname)
if mapping:
updated_cppfunction_call = function_call.FunctionCall(mapping.cppfuncsig.name, cppfunction_call.args[1:])
updated_cppfunction_call = self.validate_function_call_args(updated_cppfunction_call, mapping.cppfuncsig)
debug.line("apply_special_function_call_conversions", f"Updated C++ function call=[{debug.as_debug_string(cppfunction_call)}] to [{debug.as_debug_string(updated_cppfunction_call)}]")
return updated_cppfunction_call
for cfuncname, cppfuncname in special_function_name_mapping.items():
if cfunction_call.name == cfuncname:
@ -152,13 +153,15 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv
return None
def validate_variable_declaration(self, cvariable_declaration, cppvariable_declaration):
if "GribStatus" in cppvariable_declaration.variable.as_string() and \
not isinstance(cppvariable_declaration.value, function_call.FunctionCall) and \
not cppvariable_declaration.value.as_string().startswith("GribStatus"):
updated_cpp_variable_declaration = variable_declaration.VariableDeclaration(
cppvariable_declaration.variable,
literal.Literal(f"GribStatus{{{cppvariable_declaration.value.as_string()}}}"))
return updated_cpp_variable_declaration
if "GribStatus" in cppvariable_declaration.variable.as_string():
if not (isinstance(cppvariable_declaration.value, function_call.FunctionCall) or
cppvariable_declaration.value.as_string().startswith("GribStatus") or
cppvariable_declaration.value.as_string() == "{}"):
debug.line("validate_binary_operation", f"GribStatus variable [{debug.as_debug_string(cppvariable_declaration.variable)}] is assigned incorrect value type [{debug.as_debug_string(cppvariable_declaration.value)}] - updating")
updated_cpp_variable_declaration = variable_declaration.VariableDeclaration(
cppvariable_declaration.variable,
literal.Literal(f"GribStatus{{{cppvariable_declaration.value.as_string()}}}"))
return updated_cpp_variable_declaration
return super().validate_variable_declaration(cvariable_declaration, cppvariable_declaration)
@ -178,9 +181,9 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv
if isinstance(cppright, cast_expression.CastExpression):
cpp_right_expression = cppright.expression
if isinstance(cpp_right_expression, function_call.FunctionCall) and cpp_right_expression.name in ["gribContextMalloc", "gribContextRealloc"]:
if isinstance(cpp_right_expression, function_call.FunctionCall) and cpp_right_expression.name in ["gribContextMalloc", "gribContextMallocClear", "gribContextRealloc"]:
# For now, we'll assume we're allocating a container (may need to revisit)
cpp_alloc = literal.Literal(f"{arg_utils.extract_name(cppleft)}.resize({cpp_right_expression.arg_string});")
cpp_alloc = literal.Literal(f"{arg_utils.extract_name(cppleft)}.resize({strip_semicolon(cpp_right_expression.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
@ -192,7 +195,7 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv
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_expression = literal.Literal(f"GribStatusSuccess({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
@ -274,3 +277,25 @@ class GribAccessorConversionValidation(default_conversion_validation.DefaultConv
return super().is_cppfunction_returning_container(cppfunc_object)
def try_to_make_boolean(self, cppcode_object):
if isinstance(cppcode_object, unary_operation.UnaryOperation):
cpparg = arg_utils.to_cpparg(cppcode_object.operand, self._conversion_data)
if cpparg:
if cpparg.decl_spec.type == "GribStatus":
if cppcode_object.unary_op.value == "!":
updated_expression = literal.Literal(f"GribStatusSuccess({cpparg.name})")
else:
updated_expression = literal.Literal(f"!GribStatusSuccess({cpparg.name})")
debug.line("apply_special_unary_operation_conversion", f"Updating GribStatus error: [{debug.as_debug_string(cppcode_object)}]->[{debug.as_debug_string(updated_expression)}]")
return updated_expression
if isinstance(cppcode_object, function_call.FunctionCall):
cppfuncsig = self._conversion_data.cppfuncsig_for_cppfuncname(cppcode_object.name)
if cppfuncsig:
if cppfuncsig.return_type.type == "GribStatus":
updated_cppcode_object = literal.Literal(f"GribStatusSuccess({cppcode_object.as_string()})")
return updated_cppcode_object
return super().try_to_make_boolean(cppcode_object)

View File

@ -0,0 +1,24 @@
import utils.debug as debug
import grib_accessor.grib_accessor_conversion_pack.grib_accessor_conversion_validation as grib_accessor_conversion_validation
import code_object_converter.conversion_pack.arg_utils as arg_utils
import code_object.literal as literal
from code_object_converter.conversion_utils import as_commented_out_code
class DataShsimplePackingValidation(grib_accessor_conversion_validation.GribAccessorConversionValidation):
def validate_unary_operation(self, cunary_operation, cppunary_operation):
if self._conversion_data.current_cfuncname == "pack_double":
if cppunary_operation.as_string() == "doubleValues++;":
return as_commented_out_code(cppunary_operation, f"Removed invalid unary operation - will handle in next function call")
return super().validate_unary_operation(cunary_operation, cppunary_operation)
def validate_function_call(self, cfunction_call, cppfunction_call):
if self._conversion_data.current_cfuncname == "pack_double":
if cppfunction_call.name == "gribSetDouble":
if cppfunction_call.args[0].as_string() == "codedValues_":
cppfunction_call.args[1] = literal.Literal("doubleValues[1]")
return super().validate_function_call(cfunction_call, cppfunction_call)

View File

@ -0,0 +1,14 @@
import utils.debug as debug
import grib_accessor.grib_accessor_conversion_pack.grib_accessor_conversion_validation as grib_accessor_conversion_validation
import code_object_converter.conversion_pack.arg_utils as arg_utils
class SectionPointerValidation(grib_accessor_conversion_validation.GribAccessorConversionValidation):
def validate_cast_expression(self, ccast_expression, cppcast_expression):
if self._conversion_data.current_cfuncname == "init":
# We don't need either cast expression in the constructor, so remove them!
debug.line("validate_cast_expression", f"[init()] Removing cast expression: [{debug.as_debug_string(cppcast_expression)}]->[{debug.as_debug_string(cppcast_expression.expression)}]")
return cppcast_expression.expression
return super().validate_cast_expression(ccast_expression, cppcast_expression)

View File

@ -12,7 +12,7 @@
{% for i in c.header_file_includes -%}
#include "{{ i }}"
{%- endfor %}
{% endfor %}
namespace {{ c.nested_namespaces }} {

View File

@ -23,8 +23,13 @@ grib_accessor_base_data_members_map = {
DataMember("grib_accessor*","attributes") : DataMember("std::vector<AccessorPtr>","attributes_"),
# grib_handle conversion helpers
DataMember("grib_loader*","loader") : DataMember("AccessorLoaderPtr","loader()"),
DataMember("char*","gts_header") : DataMember("std::string","gtsHeader"),
DataMember("size_t","gts_header_len") : DataMember("std::string","gtsHeader"),
DataMember("int","partial") : DataMember("int","partial_"),
DataMember("int","header_mode") : DataMember("int","headerMode_"),
DataMember("char*","gts_header") : DataMember("std::string","gtsHeader_"),
DataMember("size_t","gts_header_len") : DataMember("std::string","gtsHeader_"),
DataMember("char*","section_offset") : DataMember("std::vector<std::string>","sectionOffsetList_"),
DataMember("char*","section_length") : DataMember("std::vector<std::string>","sectionLengthList_"),
DataMember("int","sections_count") : DataMember("std::vector<std::string>","sectionsCount_"),
}
def add_data_member_mappings_to_conversion_data(conversion_data):

View File

@ -10,7 +10,7 @@ grib_buffer_stub_funcsig_mappings = [
FuncSig("void", "griBufferDelete", [NONE_VALUE, Arg("AccessorDataBuffer&", "b")])),
FuncSigMapping( FuncSig("void", "grib_buffer_replace", [Arg("grib_accessor*", "a"), Arg("const unsigned char*", "data"), Arg("size_t", "newsize"), Arg("int", "update_lengths"), Arg("int", "update_paddings")]),
FuncSig("void", "gribBufferReplace", [NONE_VALUE, Arg("AccessorDataBuffer&", "data"), Arg("size_t", "newsize"), Arg("int", "updateLengths"), Arg("int", "updatePaddings")])),
FuncSig("void", "gribBufferReplace", [NONE_VALUE, Arg("const AccessorDataBuffer&", "data"), Arg("size_t", "newsize"), Arg("int", "updateLengths"), Arg("int", "updatePaddings")])),
FuncSigMapping( FuncSig("void", "grib_buffer_set_ulength_bits", [Arg("const grib_context*", "c"), Arg("grib_buffer*", "b"), Arg("size_t", "length_bits")]),
FuncSig("void", "gribBufferSetUlengthBits", [NONE_VALUE, Arg("AccessorDataBuffer&", "b"), Arg("size_t", "lengthBits")])),

View File

@ -20,5 +20,8 @@ grib_value_stub_funcsig_mappings = [
FuncSigMapping( FuncSig("int", "grib_get_nearest_smaller_value", [Arg("grib_handle*", "h"), Arg("const char*", "name"), Arg("double", "val"), Arg("double*", "nearest")]),
FuncSig("GribStatus", "gribGetNearestSmallerValue", [NONE_VALUE, Arg("AccessorName const&", "name"), Arg("double", "val"), Arg("double&", "nearest")])),
FuncSigMapping( FuncSig("int", "grib_is_missing", [Arg("grib_handle*", "h"), Arg("const char*", "name"), Arg("int*", "err")]),
FuncSig("GribStatus", "gribIsMissing", [NONE_VALUE, Arg("AccessorName", "name"), Arg("int", "err")])),
]

View File

@ -7,6 +7,7 @@ from code_object.code_interface import NONE_VALUE
# ==================== FUNCSIG TYPE MAPPINGS: Begin ====================
common_funcsig_type_mappings = {
#"grib_accessor*" : "AccessorDataPtr",
"char*" : "std::string&",
"char[]" : "std::string&",
}
@ -23,13 +24,14 @@ def add_funcsig_type_mappings_to_conversion_data(conversion_data):
# ==================== FUNCBODY TYPE MAPPINGS: Begin ====================
common_grib_funcbody_type_mappings = {
"grib_accessor*" : "AccessorPtr",
"grib_accessor_class*" : NONE_VALUE,
"grib_handle*" : NONE_VALUE,
"grib_context*" : NONE_VALUE,
"grib_expression*" : "GribExpressionPtr",
"grib_codetable*" : "GribCodeTablePtr",
"grib_action*" : "GribActionPtr"
"grib_accessor*" : "AccessorPtr",
"grib_accessor_class*" : NONE_VALUE,
"grib_handle*" : NONE_VALUE,
"grib_context*" : NONE_VALUE,
"grib_expression*" : "GribExpressionPtr",
"grib_codetable*" : "GribCodeTablePtr",
"grib_action*" : "GribActionPtr",
"bufr_descriptors_array" : "BufrDescriptorsArray",
}
grib_array_funcbody_type_mappings = {

View File

@ -53,6 +53,7 @@ set(accessor_utils_src_files
)
set(accessor_grib_cpp_src_files
${accessor_grib_cpp_dir}/BufrDefs.h
${accessor_grib_cpp_dir}/GribCppIncludes.h
${accessor_grib_cpp_dir}/GribBits.cc
${accessor_grib_cpp_dir}/GribBits.h

View File

@ -96,6 +96,12 @@ protected:
// Conversion helpers...
std::vector<AccessorPtr> attributes_;
int partial_{};
int headerMode_{};
std::string gtsHeader_;
std::vector<std::string> sectionOffsetList_;
std::vector<std::string> sectionLengthList_;
std::vector<std::string> sectionsCount_;
};
template<typename T>

View File

@ -0,0 +1,79 @@
#pragma once
#include "AccessorDefs.h"
#include <string>
#include <vector>
namespace eccodes::accessor {
/* types of BUFR descriptors used in bufr_descriptor->type*/
enum class BufrDescriptorType{
UNKNOWN,
STRING,
DOUBLE,
LONG,
TABLE,
FLAG,
REPLICATION,
OPERATOR,
SEQUENCE,
// Used for conversion routines - keep last!
ENUMSIZE
};
constexpr int toInt(BufrDescriptorType type) {
return static_cast<int>(type);
}
//std::string toString(GribType type);
//GribType toGribType(std::string_view type);
struct BufrDescriptor
{
//grib_context* context;
long code;
int F;
int X;
int Y;
int type;
/*char* name; Not needed: All usage commented out. See ECC-489 */
std::string shortName;
std::string units;
long scale;
double factor;
long reference;
long width;
int nokey; /* set if descriptor does not have an associated key */
AccessorPtr a; //grib_accessor* a;
};
struct BufrDescriptorsArray
{
std::vector<std::vector<BufrDescriptor>> v;
size_t size;
size_t n;
size_t incsize;
size_t number_of_pop_front;
//grib_context* context;
};
struct bufr_descriptors_map_list
{
std::vector<BufrDescriptor> unexpanded;
std::vector<BufrDescriptor> expanded;
bufr_descriptors_map_list* next;
};
/* BUFR: Operator 203YYY: Linked list storing Table B changed reference values */
struct BufrTablebOverride
{
BufrTablebOverride* next;
int code;
long newRefVal;
};
}

View File

@ -3,9 +3,9 @@
namespace eccodes::accessor {
// Helper for the conversion process
bool isError(GribStatus stat)
bool GribStatusSuccess(GribStatus stat)
{
return stat != GribStatus::SUCCESS;
return stat == GribStatus::SUCCESS;
}
}

View File

@ -86,6 +86,6 @@ enum class GribStatus{
};
// Helper for the conversion process
bool isError(GribStatus stat);
bool GribStatusSuccess(GribStatus stat);
}

View File

@ -13,9 +13,9 @@ struct GribAction
std::string op_;
std::string nameSpace_;
unsigned long flags_;
//char* defaultkey; /** name of the key used as default if not found */
std::string defaultkey; /** name of the key used as default if not found */
//grib_arguments* default_value; /** default expression as in .def file */
//char* set;
std::string set;
//char* debug_info; /** purely for debugging and tracing */
};

View File

@ -10,7 +10,7 @@ void griBufferDelete(AccessorDataBuffer& b)
assert(false);
}
void gribBufferReplace(AccessorDataBuffer& data, size_t newsize, int update_lengths, int update_paddings)
void gribBufferReplace(const AccessorDataBuffer& data, size_t newsize, int update_lengths, int update_paddings)
{
assert(false);
}

View File

@ -8,7 +8,7 @@
namespace eccodes::accessor {
void griBufferDelete(AccessorDataBuffer& b);
void gribBufferReplace(AccessorDataBuffer& data, size_t newsize, int updateLengths, int updatePaddings);
void gribBufferReplace(const AccessorDataBuffer& data, size_t newsize, int updateLengths, int updatePaddings);
void gribBufferSetUlengthBits(AccessorDataBuffer& b, size_t lengthBits);
AccessorDataBuffer gribCreateGrowableBuffer();

View File

@ -34,4 +34,10 @@ GribStatus gribGetNearestSmallerValue(AccessorName name, double val, double& nea
return GribStatus::NOT_IMPLEMENTED;
}
GribStatus gribIsMissing(AccessorName name, GribStatus& err)
{
assert(false);
return GribStatus::NOT_IMPLEMENTED;
}
}

View File

@ -16,4 +16,5 @@ GribStatus gribGetDoubleElementSet(AccessorName const& name, const std::vector<s
GribStatus gribGetDoubleElementSetInternal(AccessorName const& name, const std::vector<size_t> indexArray, size_t len, std::vector<double>& valArray);
GribStatus gribGetNearestSmallerValue(AccessorName name, double val, double& nearest);
GribStatus gribIsMissing(AccessorName name, GribStatus& err);
}