Added support for goto and labels

This commit is contained in:
kevstone 2024-02-15 14:01:46 +00:00
parent 123a955e79
commit c147a05199
14 changed files with 154 additions and 13 deletions

View File

@ -16,8 +16,8 @@ grib_accessor_class_long.cc
grib_accessor_class_proj_string.cc
grib_accessor_class_blob.cc
#grib_accessor_class_bufr_data_array.cc
#grib_accessor_class_bufr_data_element.cc
#grib_accessor_class_bufr_elements_table.cc
grib_accessor_class_bufr_data_element.cc
grib_accessor_class_bufr_elements_table.cc
#grib_accessor_class_bufr_extract_area_subsets.cc
#grib_accessor_class_bufr_extract_datetime_subsets.cc
#grib_accessor_class_bufr_extract_subsets.cc

View File

@ -14,10 +14,12 @@ import code_object.conditional_operation as conditional_operation
import code_object.declaration_specifier as declaration_specifier
import code_object.for_statement as for_statement
import code_object.function_call as function_call
import code_object.goto_statement as goto_statement
import code_object.if_statement as if_statement
import code_object.init_list as init_list
import code_object.macro_definition as macro_definition
import code_object.macro_instantation as macro_instantation
import code_object.label_statement as label_statement
import code_object.literal as literal
import code_object.paren_expression as paren_expression
import code_object.return_statement as return_statement
@ -271,6 +273,30 @@ class AstParser:
return stmt_lines
def parse_GOTO_STMT(self, node):
children = list(node.get_children())
child_count = len(children)
assert child_count == 1, f"Expected one child for goto statement, not [{child_count}]"
label = self.parse_ast_node(children[0])
return goto_statement.GotoStatement(label)
def parse_LABEL_STMT(self, node):
children = list(node.get_children())
child_count = len(children)
assert child_count == 1, f"Expected one child for label statement, not [{child_count}]"
label = literal.Literal(node.spelling)
statement = self.parse_ast_node(children[0])
label_stmt = label_statement.LabelStatement(label, statement)
debug.line("parse_LABEL_STMT", f"label_stmt=[{debug.as_debug_string(label_stmt)}]")
#ast_utils.dump_node(node)
#assert False
return label_stmt
def parse_RETURN_STMT(self, node):
children = list(node.get_children())
child_count = len(children)
@ -354,6 +380,9 @@ class AstParser:
def parse_BREAK_STMT(self, node):
return literal.Literal("break;")
def parse_CONTINUE_STMT(self, node):
return literal.Literal("continue;")
def parse_FOR_STMT(self, node):
init_statement = condition = iteration_expression = statement = None
@ -437,12 +466,13 @@ class AstParser:
clang.cindex.CursorKind.CASE_STMT: parse_CASE_STMT,
clang.cindex.CursorKind.DEFAULT_STMT: parse_CASE_STMT,
clang.cindex.CursorKind.IF_STMT: parse_IF_STMT,
clang.cindex.CursorKind.LABEL_STMT: parse_LABEL_STMT,
clang.cindex.CursorKind.SWITCH_STMT: parse_SWITCH_STMT,
clang.cindex.CursorKind.WHILE_STMT: parse_WHILE_STMT,
clang.cindex.CursorKind.DO_STMT: parse_node_not_implemented,
clang.cindex.CursorKind.FOR_STMT: parse_FOR_STMT,
clang.cindex.CursorKind.GOTO_STMT: parse_node_not_implemented,
clang.cindex.CursorKind.CONTINUE_STMT: parse_node_not_implemented,
clang.cindex.CursorKind.GOTO_STMT: parse_GOTO_STMT,
clang.cindex.CursorKind.CONTINUE_STMT: parse_CONTINUE_STMT,
clang.cindex.CursorKind.BREAK_STMT: parse_BREAK_STMT,
clang.cindex.CursorKind.RETURN_STMT: parse_RETURN_STMT,
clang.cindex.CursorKind.NULL_STMT: parse_NULL_STMT,
@ -565,9 +595,11 @@ class AstParser:
func_name = self.parse_ast_node(children[0])
cargs = []
for entry in children [1:]:
if entry.kind == clang.cindex.CursorKind.DECL_REF_EXPR:
carg = self.parse_ast_node(entry)
cargs.append(carg)
'''if entry.kind == clang.cindex.CursorKind.DECL_REF_EXPR:
carg = arg.Arg(entry.type.spelling, entry.spelling)
cargs.append(carg)
cargs.append(carg)'''
func_call = function_call.FunctionCall(func_name.as_string(), cargs)
debug.line("parse_UNEXPOSED_EXPR", f"Extracted func_call=[{debug.as_debug_string(func_call)}]")
return func_call
@ -882,11 +914,15 @@ class AstParser:
ast_utils.dump_node(node)
return literal.Literal("::".join([t.spelling for t in node.get_tokens()]))
def parse_LABEL_REF(self, node):
return literal.Literal(node.spelling)
parse_REF_funcs = {
clang.cindex.CursorKind.TYPE_REF: parse_TYPE_REF,
clang.cindex.CursorKind.TEMPLATE_REF: parse_node_not_implemented,
clang.cindex.CursorKind.MEMBER_REF: parse_node_not_implemented,
clang.cindex.CursorKind.NAMESPACE_REF: parse_NAMESPACE_REF,
clang.cindex.CursorKind.LABEL_REF: parse_LABEL_REF,
}
def parse_REF_node(self, node):

View File

@ -14,8 +14,6 @@ class CaseStatement(code_interface.CodeInterface):
self._statement = statement
assert isinstance(self._statement, code_interface.CodeInterface), f"Statement must be a CodeInterface class"
self._else = None
@property
def constant_expression(self):
return self._constant_expression

View File

@ -33,5 +33,7 @@ class FunctionCall(code_interface.CodeInterface):
def as_lines(self):
return [f"{self._name}({', '.join([arg_utils.extract_function_call_name(a) for a in self._args])});"]
func_call_string = f"{self._name}({', '.join([arg_utils.extract_function_call_name(a) for a in self._args])});"
debug.line("as_lines", f"func_call_string=[{func_call_string}]")
return [func_call_string]
#return [f"{self._name}({', '.join([strip_semicolon(a.as_string()) for a in self._args])});"]

View File

@ -0,0 +1,21 @@
import utils.debug as debug
import code_object.code_interface as code_interface
import code_object.arg as arg
# Represent a goto statement of the form goto LABEL;
#
class GotoStatement(code_interface.CodeInterface):
def __init__(self, label) -> None:
self._label = label
assert isinstance(self._label, code_interface.CodeInterface), f"Label must be a CodeInterface class (or a string)"
@property
def label(self):
return self._label
def as_lines(self):
lines = [f"goto {self._label.as_string()};"]
return lines

View File

@ -0,0 +1,33 @@
import utils.debug as debug
import code_object.code_interface as code_interface
# Represents a label statement in the form: label: statement
#
# For example:
# the_end:
# GRIB_MUTEX_UNLOCK(&mutex1);
#
class LabelStatement(code_interface.CodeInterface):
def __init__(self, label, statement) -> None:
self._label = label
assert isinstance(self._label, code_interface.CodeInterface), f"Label must be a CodeInterface class"
self._statement = statement
assert isinstance(self._statement, code_interface.CodeInterface), f"Statement must be a CodeInterface class"
@property
def label(self):
return self._label
@property
def statement(self):
return self._statement
def as_lines(self):
label_lines = [f"{self._label.as_string()}:"]
statement_lines = []
statement_lines.extend(self._statement.as_lines())
return label_lines + statement_lines

View File

@ -13,6 +13,6 @@ class CaseStatementConverter(code_interface_converter.CodeInterfaceConverter):
cpp_constant_expression = conversion_funcs.convert_ccode_object(self._ccode_object.constant_expression, conversion_pack)
cpp_statement = conversion_funcs.convert_ccode_object(self._ccode_object.statement, conversion_pack)
cpp_while = case_statement.CaseStatement(cpp_constant_expression, cpp_statement)
cpp_case = case_statement.CaseStatement(cpp_constant_expression, cpp_statement)
return conversion_pack.conversion_validation.validate_case_statement(self._ccode_object, cpp_while)
return conversion_pack.conversion_validation.validate_case_statement(self._ccode_object, cpp_case)

View File

@ -18,8 +18,10 @@ import code_object.funcsig as funcsig
import code_object.function as function
import code_object.function_call as function_call
import code_object.global_function as global_function
import code_object.goto_statement as goto_statement
import code_object.if_statement as if_statement
import code_object.init_list as init_list
import code_object.label_statement as label_statement
import code_object.literal as literal
import code_object.macro_definition as macro_definition
import code_object.macro_instantation as macro_instantation
@ -58,8 +60,10 @@ import code_object_converter.funcsig_pointer_converter as funcsig_pointer_conver
import code_object_converter.function_call_converter as function_call_converter
import code_object_converter.function_converter as function_converter
import code_object_converter.global_function_converter as global_function_converter
import code_object_converter.goto_statement_converter as goto_statement_converter
import code_object_converter.if_statement_converter as if_statement_converter
import code_object_converter.init_list_converter as init_list_converter
import code_object_converter.label_statement_converter as label_statement_converter
import code_object_converter.literal_converter as literal_converter
import code_object_converter.macro_definition_converter as macro_definition_converter
import code_object_converter.macro_instantiation_converter as macro_instantiation_converter
@ -104,8 +108,10 @@ CodeInterfaceConverterClasses = {
function_call.FunctionCall : function_call_converter.FunctionCallConverter,
function.Function : function_converter.FunctionConverter,
global_function.GlobalFunction : global_function_converter.GlobalFunctionConverter,
goto_statement.GotoStatement : goto_statement_converter.GotoStatementConverter,
if_statement.IfStatement : if_statement_converter.IfStatementConverter,
init_list.InitList : init_list_converter.InitListConverter,
label_statement.LabelStatement : label_statement_converter.LabelStatementConverter,
literal.Literal : literal_converter.LiteralConverter,
member_function.MemberFunction : member_function_converter.MemberFunctionConverter,
macro_definition.MacroDefinition : macro_definition_converter.MacroDefinitionConverter,

View File

@ -111,6 +111,6 @@ def extract_function_call_name(cpp_obj):
if not cppname:
cppname = strip_semicolon(cpp_obj.as_string())
debug.line("function_call_name", f"Converted cpp_obj: [{debug.as_debug_string(cpp_obj)}] -> [{cppname}] cpp_ob type=[{type(cpp_obj)}]")
debug.line("extract_function_call_name", f"Converted cpp_obj: [{debug.as_debug_string(cpp_obj)}] -> [{cppname}] cpp_ob type=[{type(cpp_obj)}]")
return cppname

View File

@ -75,12 +75,18 @@ class ConversionValidation:
def validate_global_function(self, cglobal_function, cppglobal_function):
return cppglobal_function
def validate_goto_statement(self, cgoto_statement, cppgoto_statement):
return cppgoto_statement
def validate_if_statement(self, cif_statement, cppif_statement):
return cppif_statement
def validate_init_list(self, cinit_list, cppinit_list):
return cppinit_list
def validate_label_statement(self, clabel, cpplabel):
return cpplabel
def validate_literal(self, cliteral, cppliteral):
return cppliteral

View File

@ -0,0 +1,16 @@
import utils.debug as debug
import code_object.goto_statement as goto_statement
import code_object_converter.code_interface_converter as code_interface_converter
import code_object_converter.conversion_funcs as conversion_funcs
class GotoStatementConverter(code_interface_converter.CodeInterfaceConverter):
def __init__(self, ccode_object) -> None:
super().__init__(ccode_object)
assert isinstance(ccode_object, goto_statement.GotoStatement), f"Expected GotoStatement, got type=[{type(ccode_object)}]"
def create_cpp_code_object(self, conversion_pack):
cpp_label = conversion_funcs.convert_ccode_object(self._ccode_object.label, conversion_pack)
cppgoto_statement = goto_statement.GotoStatement(cpp_label)
return conversion_pack.conversion_validation.validate_goto_statement(self._ccode_object, cppgoto_statement)

View File

@ -0,0 +1,18 @@
import utils.debug as debug
import code_object.label_statement as label_statement
import code_object_converter.code_interface_converter as code_interface_converter
import code_object_converter.conversion_funcs as conversion_funcs
class LabelStatementConverter(code_interface_converter.CodeInterfaceConverter):
def __init__(self, ccode_object) -> None:
super().__init__(ccode_object)
assert isinstance(ccode_object, label_statement.LabelStatement), f"Expected LabelStatement, got type=[{type(ccode_object)}]"
def create_cpp_code_object(self, conversion_pack):
cpp_label = conversion_funcs.convert_ccode_object(self._ccode_object.label, conversion_pack)
cpp_statement = conversion_funcs.convert_ccode_object(self._ccode_object.statement, conversion_pack)
cpp_label_stmt = label_statement.LabelStatement(cpp_label, cpp_statement)
return conversion_pack.conversion_validation.validate_label_statement(self._ccode_object, cpp_label_stmt)

View File

@ -4,6 +4,7 @@ import code_object.unary_operation as unary_operation
import code_object_converter.code_interface_converter as code_interface_converter
import code_object_converter.conversion_funcs as conversion_funcs
import code_object.struct_member_access as struct_member_access
from code_object.code_interface import NONE_VALUE
class UnaryOperationConverter(code_interface_converter.CodeInterfaceConverter):
def __init__(self, ccode_object) -> None:
@ -15,5 +16,9 @@ class UnaryOperationConverter(code_interface_converter.CodeInterfaceConverter):
cpp_operand = conversion_funcs.convert_ccode_object(self._ccode_object.operand, conversion_pack)
cpp_op_position = self._ccode_object.op_position
if cpp_operand == NONE_VALUE:
debug.line("create_cpp_code_object", f"cpp_operand is NONE_VALUE for self._ccode_object=[{debug.as_debug_string(self._ccode_object)}] - returning NONE_VALUE")
return NONE_VALUE
cpp_unary_operation = unary_operation.UnaryOperation(cpp_unary_op, cpp_operand, cpp_op_position)
return conversion_pack.conversion_validation.validate_unary_operation(self._ccode_object, cpp_unary_operation)

View File

@ -116,7 +116,7 @@ class DefaultConversionValidation(conversion_validation.ConversionValidation):
# 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)}]")
return cppunary_operation.operand
elif cpparg.decl_spec.pointer == "&":
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)}]")
return cppunary_operation.operand