Identify and remove (or comment out as appropriate) invalid types

This commit is contained in:
kevstone 2024-01-23 12:43:48 +00:00
parent 58f88b4b0e
commit 64b24dee6c
11 changed files with 121 additions and 32 deletions

View File

@ -12,8 +12,11 @@ class Arg(code_interface.CodeInterface):
def __init__(self, decl_spec, name="", is_func_arg=False) -> None:
if isinstance(decl_spec, DeclSpec):
self._decl_spec = DeclSpec.from_instance(decl_spec)
else:
elif isinstance(decl_spec, str):
self._decl_spec = DeclSpec.from_decl_specifier_seq(decl_spec)
else:
assert False, f"Unexpected decl_spec=[{decl_spec}]"
self._name = name
self._is_func_arg = is_func_arg # Support for processing function sig args differently to other args

View File

@ -16,9 +16,34 @@ class DeclSpec(code_interface.CodeInterface):
self._type = type
self._pointer = pointer
# ---------- Support for NoneDeclSpec: Begin ----------
# NoneDeclSpec is used when a C DeclSpec doesn't have a C++ equivalent (i.e. we don't want to convert it!)
class _NoneDeclSpec:
def __repr__(self):
return "<NoneDeclSpec>"
def __eq__(self, other):
# This version is required for testing DeclSpec.NONE = <VAR>
# As the DeclSpec.__eq__ version won't be called when self=DeclSpec.NONE !!!
return isinstance(other, DeclSpec._NoneDeclSpec)
def __ne__(self, other):
return not self.__eq__(other)
NONE = _NoneDeclSpec() # The singleton instance to represent "None"
# ---------- Support for NoneDeclSpec: End ----------
# Create a DeclSpec from a string representing the sequence, e.g. "const char*"
# Pass None (or empty string) to return DeclSpec.NONE
@classmethod
def from_decl_specifier_seq(cls, decl_specifier_seq):
assert decl_specifier_seq, f"Unexpected decl_specifier_seq=[{decl_specifier_seq}]"
if not decl_specifier_seq:
return DeclSpec.NONE
assert isinstance(decl_specifier_seq, str), f"Expected str, got [{decl_specifier_seq}]"
decl_specifier_seq = decl_specifier_seq.strip()
storage_class = ""
const_qualifier = ""
@ -97,15 +122,19 @@ class DeclSpec(code_interface.CodeInterface):
def is_array_type(self):
return self.pointer == "[]"
# Support for DeclSpec as a dict key
# ---------- Support for DeclSpec as a dict key: Begin ----------
def __hash__(self):
return hash((self._storage_class, self._const_qualifier, self.type, self._pointer))
# Support for DeclSpec as a dict key
def __eq__(self, other):
if isinstance(other, DeclSpec):
return self.storage_class == other.storage_class and self.const_qualifier == other.const_qualifier and self.pointer == other.pointer and self.type == other.type
return False
if self is DeclSpec.NONE or other is DeclSpec.NONE:
return self is other
return self.storage_class == other.storage_class and self.const_qualifier == other.const_qualifier and self.pointer == other.pointer and self.type == other.type
def __ne__(self, other):
return not self.__eq__(other)
# ---------- Support for DeclSpec as a dict key: End ----------
# Return the full decl-specifier-seq as a (parsed) string (i.e. consistent spacing etc, not just what was passed in!)
def as_lines(self):

View File

@ -13,7 +13,8 @@ class VariableDeclaration(code_interface.CodeInterface):
self._variable = variable
self._value = value
assert isinstance(self._variable, arg.Arg), f"Variable must be an Arg class"
assert self._variable != arg.Arg.NONE, f"Variable can't be NoneArg!"
assert isinstance(self._variable, arg.Arg), f"Variable must be an Arg class, not=[{variable}]"
assert isinstance(self._value, code_interface.CodeInterface), f"Value must be a CodeInterface class (or a string)"
@property

View File

@ -28,10 +28,13 @@ class ArgConverter(code_interface_converter.CodeInterfaceConverter):
conversion_data.add_type_mapping(carg.decl_spec, cpp_decl_spec)
debug.line("create_cpp_code_object", f"Arg conversion type mapping: carg.decl_spec=[{debug.as_debug_string(carg.decl_spec)}] cpp_decl_spec=[{debug.as_debug_string(cpp_decl_spec)}]")
cpp_name = standard_transforms.transform_variable_name(carg.name)
cpp_is_func_arg = carg.is_func_arg
if cpp_decl_spec == declaration_specifier.DeclSpec.NONE:
cpp_arg = arg.Arg.NONE
else:
cpp_name = standard_transforms.transform_variable_name(carg.name)
cpp_is_func_arg = carg.is_func_arg
cpp_arg = arg.Arg(cpp_decl_spec, cpp_name, cpp_is_func_arg)
cpp_arg = arg.Arg(cpp_decl_spec, cpp_name, cpp_is_func_arg)
conversion_data.add_arg_mapping(carg, cpp_arg)
debug.line("create_cpp_code_object", f"Arg conversion arg mapping: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpp_arg)}]")

View File

@ -102,15 +102,9 @@ CodeInterfaceConverterClasses = {
virtual_member_function.VirtualMemberFunction : virtual_member_function_converter.VirtualMemberFunctionConverter,
}
def get_debug_string(code_obj):
if code_obj:
return f"{code_obj if type(code_obj) is str else code_obj.as_string()}"
else:
return "None"
# Convert a code_object into a C++ code_object
def convert_ccode_object(ccode_object, conversion_data):
debug.line("convert_ccode_object", f"[IN] [{type(ccode_object).__name__}] {get_debug_string(ccode_object)}")
debug.line("convert_ccode_object", f"[IN] [{type(ccode_object).__name__}] {debug.as_debug_string(ccode_object)}")
if ccode_object is None:
cpp_obj = None
@ -121,6 +115,14 @@ def convert_ccode_object(ccode_object, conversion_data):
converter = converter_class(ccode_object)
cpp_obj = converter.to_cpp_code_object(conversion_data)
debug.line("convert_ccode_object", f"[OUT][{type(cpp_obj).__name__}] {get_debug_string(cpp_obj)}")
debug.line("convert_ccode_object", f"[OUT][{type(cpp_obj).__name__}] {debug.as_debug_string(cpp_obj)}")
return cpp_obj
def as_commented_out_code(ccode_object, prefix=""):
comment_string = "// "
if prefix:
comment_string += f"[{prefix}] "
comment_string += debug.as_debug_string(ccode_object)
return literal.Literal(comment_string)

View File

@ -43,10 +43,10 @@ class ConversionData:
def add_type_mapping(self, cdecl_spec, cppdecl_spec):
if cdecl_spec in self.active_map.type_mappings:
assert self.active_map.type_mappings[cdecl_spec] == cppdecl_spec, f"Updating an existing arg: [{cdecl_spec.as_string()}] -> [{cppdecl_spec.as_string()}] Previous arg=[{self.active_map.type_mappings[cdecl_spec]}]"
assert self.active_map.type_mappings[cdecl_spec] == cppdecl_spec, f"Updating an existing arg: [{debug.as_debug_string(cdecl_spec)}] -> [{debug.as_debug_string(cppdecl_spec)}] Previous arg=[{self.active_map.type_mappings[cdecl_spec]}]"
else:
self.active_map.type_mappings[cdecl_spec] = cppdecl_spec
debug.line("add_type_mapping", f"Adding decl_spec: [{cdecl_spec.as_string()}] -> [{cppdecl_spec.as_string()}]")
debug.line("add_type_mapping", f"Adding decl_spec: [{debug.as_debug_string(cdecl_spec)}] -> [{debug.as_debug_string(cppdecl_spec)}]")
def add_arg_mapping(self, carg, cpparg):
if not carg.name:
@ -54,17 +54,17 @@ class ConversionData:
return
if carg in self.active_map.arg_mappings:
assert self.active_map.arg_mappings[carg] == cpparg, f"Updating an existing arg: [{carg.as_string()}] -> [{cpparg.as_string()}] Previous arg=[{self.active_map.arg_mappings[carg]}]"
assert self.active_map.arg_mappings[carg] == cpparg, f"Updating an existing arg: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpparg)}] Previous arg=[{self.active_map.arg_mappings[carg]}]"
else:
self.active_map.arg_mappings[carg] = cpparg
debug.line("add_arg_mapping", f"Adding arg: [{carg.as_string()}] -> [{cpparg.as_string()}]")
debug.line("add_arg_mapping", f"Adding arg: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpparg)}]")
def add_function_arg_mapping(self, carg, cpparg):
if carg in self.active_map.function_arg_mappings:
assert self.active_map.function_arg_mappings[carg] == cpparg, f"Updating an existing function arg: [{carg.as_string()}] -> [{cpparg.as_string()}] Previous function arg=[{self.active_map.function_arg_mappings[carg]}]"
assert self.active_map.function_arg_mappings[carg] == cpparg, f"Updating an existing function arg: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpparg)}] Previous function arg=[{self.active_map.function_arg_mappings[carg]}]"
else:
self.active_map.function_arg_mappings[carg] = cpparg
debug.line("add_function_arg_mappings", f"Adding function arg: [{carg.as_string()}] -> [{cpparg.as_string()}]")
debug.line("add_function_arg_mappings", f"Adding function arg: [{debug.as_debug_string(carg)}] -> [{debug.as_debug_string(cpparg)}]")
def add_funcsig_mapping(self, mapping):
assert isinstance(mapping, funcsig_mapping.FuncSigMapping), f"Expected FuncSigMapping, got type=[{type(mapping).__name__}]"

View File

@ -1,6 +1,7 @@
import utils.debug as debug
import code_object.value_declaration_reference as value_declaration_reference
import code_object.arg as arg
import code_object_converter.code_interface_converter as code_interface_converter
import code_object_converter.conversion_funcs as conversion_funcs
@ -19,7 +20,7 @@ class ValueDeclarationReferenceConverter(code_interface_converter.CodeInterfaceC
# 2. Check if it is an arg
cpparg = conversion_data.cpparg_for_carg_name(cdecl_ref_expr_value)
if cpparg:
if cpparg and cpparg != arg.Arg.NONE:
return value_declaration_reference.ValueDeclarationReference(cpparg.name)
# 3. Perform a default conversion

View File

@ -1,6 +1,7 @@
import utils.debug as debug
import code_object.variable_declaration as variable_declaration
import code_object.arg as arg
import code_object_converter.code_interface_converter as code_interface_converter
import code_object_converter.conversion_funcs as conversion_funcs
@ -10,10 +11,16 @@ class VariableDeclarationConverter(code_interface_converter.CodeInterfaceConvert
assert isinstance(ccode_object, variable_declaration.VariableDeclaration), f"Expected VariableDeclaration, got type=[{type(ccode_object)}]"
def create_cpp_code_object(self, conversion_data):
cpp_variable = conversion_funcs.convert_ccode_object(self._ccode_object.variable, conversion_data)
if cpp_variable == arg.Arg.NONE:
return conversion_funcs.as_commented_out_code(self._ccode_object, f"Removed invalid variable")
cpp_value = conversion_funcs.convert_ccode_object(self._ccode_object.value, conversion_data)
cpp_variable_declaration = variable_declaration.VariableDeclaration(cpp_variable, cpp_value)
return cpp_variable_declaration

View File

@ -9,6 +9,7 @@ from grib_accessor.supporting.member_functions import grib_accessor_member_funcs
import grib_accessor.supporting.member_functions as member_functions
import grib_accessor.supporting.virtual_member_functions as virtual_member_functions
import grib_accessor.supporting.includes as includes
import grib_accessor.supporting.grib_types as grib_types
prefix = "grib_accessor_class_"
rename = {
@ -52,6 +53,8 @@ class GribAccessorCCodeConverter(default_ccode_converter.DefaultCCodeConverter):
for mapping in grib_accessor_virtual_member_funcsig_mapping:
self._conversion_data.add_virtual_member_funcsig_mapping(mapping)
grib_types.add_grib_types_to_conversion_data(self._conversion_data)
def set_function_specific_conversion_data(self, function_name):
pass

View File

@ -0,0 +1,37 @@
from code_object.arg import Arg
from code_object.declaration_specifier import DeclSpec
import code_object_converter.supporting.conversion_data as conversion_data
common_grib_type_transforms = {
"grib_accessor*" : "AccessorPtr",
"grib_handle*" : None,
"grib_context*" : None,
}
grib_array_type_transforms = {
"grib_darray*" : "std::vector<double>",
"grib_iarray*" : "std::vector<long>",
"grib_sarray*" : "std::string",
"grib_vdarray*" : "std::vector<std::vector<double>>",
"grib_viarray*" : "std::vector<std::vector<long>>",
"grib_vsarray*" : "std::vector<std::string>",
}
grib_array_function_transforms = {
"grib_darray" : "std::vector<double>",
"grib_iarray" : "std::vector<long>",
"grib_sarray" : "std::string",
"grib_vdarray" : "std::vector<std::vector<double>>",
"grib_viarray" : "std::vector<std::vector<long>>",
"grib_vsarray" : "std::vector<std::string>",
}
def add_grib_types_to_conversion_data(conversion_data):
for type_transforms in [common_grib_type_transforms, grib_array_type_transforms]:
for key, value in type_transforms.items():
cdecl_spec = DeclSpec.from_decl_specifier_seq(key)
cppdecl_spec = DeclSpec.from_decl_specifier_seq(value)
conversion_data.add_type_mapping(cdecl_spec, cppdecl_spec)
# TODO - Add Function Transforms...

View File

@ -1,5 +1,6 @@
from datetime import datetime
from code_object.code_interface import CodeInterface
func_pad = 40
debug_enabled = True
@ -57,13 +58,15 @@ def line(func, text):
else:
print(f"{func:{func_pad}}:{elapsed_time_str} {text}")
# Safe way to print a CodeInterface object even if it is None - useful for
# debug output
def as_debug_string(code_interface_inst):
if code_interface_inst is not None:
if isinstance(code_interface_inst, str):
return code_interface_inst
# Safe way to print a value even if it is None - useful for
# CodeInstance classes etc
def as_debug_string(value):
if value is not None:
if isinstance(value, str):
return value
elif isinstance(value, CodeInterface):
return value.as_string()
else:
return code_interface_inst.as_string()
return f"[{value}]"
else:
return "None"