mirror of https://github.com/ecmwf/eccodes.git
Added support for goto and labels
This commit is contained in:
parent
123a955e79
commit
c147a05199
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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])});"]
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue