def endvisit_function(self, node):
     symbol = self.symbol_stack.pop()
     scope = self.scope_stack.pop()
     assert isinstance(symbol, FunctionSymbol), 'Not a function symbol'
     for arg in node.get_parameters():
         # given the fact that the name is not directly equivalent to the one as stated in the model,
         # we have to get it by the sub-visitor
         data_type_visitor = ASTDataTypeVisitor()
         arg.get_data_type().accept(data_type_visitor)
         type_name = data_type_visitor.result
         # first collect the types for the parameters of the function symbol
         symbol.add_parameter_type(PredefinedTypes.get_type(type_name))
         # update the scope of the arg
         arg.update_scope(scope)
         # create the corresponding variable symbol representing the parameter
         var_symbol = VariableSymbol(
             element_reference=arg,
             scope=scope,
             name=arg.get_name(),
             block_type=BlockType.LOCAL,
             is_predefined=False,
             is_function=False,
             is_recordable=False,
             type_symbol=PredefinedTypes.get_type(type_name),
             variable_type=VariableType.VARIABLE)
         assert isinstance(scope, Scope)
         scope.add_symbol(var_symbol)
     if node.has_return_type():
         data_type_visitor = ASTDataTypeVisitor()
         node.get_return_type().accept(data_type_visitor)
         symbol.set_return_type(
             PredefinedTypes.get_type(data_type_visitor.result))
     else:
         symbol.set_return_type(PredefinedTypes.get_void_type())
     self.block_type_stack.pop()  # before leaving update the type
 def visit_ode_function(self, node):
     """
     Private method: Used to visit a single ode-function, create the corresponding symbol and update the scope.
     :param node: a single ode-function.
     :type node: ast_ode_function
     """
     data_type_visitor = ASTDataTypeVisitor()
     node.get_data_type().accept(data_type_visitor)
     type_symbol = PredefinedTypes.get_type(data_type_visitor.result)
     # now a new symbol
     symbol = VariableSymbol(element_reference=node,
                             scope=node.get_scope(),
                             name=node.get_variable_name(),
                             block_type=BlockType.EQUATION,
                             declaring_expression=node.get_expression(),
                             is_predefined=False,
                             is_function=True,
                             is_recordable=node.is_recordable,
                             type_symbol=type_symbol,
                             variable_type=VariableType.VARIABLE)
     symbol.set_comment(node.get_comment())
     # now update the scopes
     node.get_scope().add_symbol(symbol)
     node.get_data_type().update_scope(node.get_scope())
     node.get_expression().update_scope(node.get_scope())
    def visit_declaration(self, node: ASTDeclaration) -> None:
        """
        Private method: Used to visit a single declaration, update its scope and return the corresponding set of symbols
        :param node: a declaration AST node
        :return: the scope is updated without a return value.
        """
        expression = node.get_expression() if node.has_expression() else None
        visitor = ASTDataTypeVisitor()
        node.get_data_type().accept(visitor)
        type_name = visitor.result
        # all declarations in the state block are recordable
        is_recordable = (node.is_recordable
                         or self.block_type_stack.top() == BlockType.STATE)
        init_value = node.get_expression() if self.block_type_stack.top(
        ) == BlockType.STATE else None

        # split the decorators in the AST up into namespace decorators and other decorators
        decorators = []
        namespace_decorators = {}
        for d in node.get_decorators():
            if isinstance(d, ASTNamespaceDecorator):
                namespace_decorators[str(d.get_namespace())] = str(
                    d.get_name())
            else:
                decorators.append(d)

        # now for each variable create a symbol and update the scope
        block_type = None
        if not self.block_type_stack.is_empty():
            block_type = self.block_type_stack.top()
        for var in node.get_variables(
        ):  # for all variables declared create a new symbol
            var.update_scope(node.get_scope())
            type_symbol = PredefinedTypes.get_type(type_name)
            vector_parameter = var.get_vector_parameter()
            symbol = VariableSymbol(element_reference=node,
                                    scope=node.get_scope(),
                                    name=var.get_complete_name(),
                                    block_type=block_type,
                                    declaring_expression=expression,
                                    is_predefined=False,
                                    is_inline_expression=False,
                                    is_recordable=is_recordable,
                                    type_symbol=type_symbol,
                                    initial_value=init_value,
                                    vector_parameter=vector_parameter,
                                    variable_type=VariableType.VARIABLE,
                                    decorators=decorators,
                                    namespace_decorators=namespace_decorators)
            symbol.set_comment(node.get_comment())
            node.get_scope().add_symbol(symbol)
            var.set_type_symbol(Either.value(type_symbol))
        # the data type
        node.get_data_type().update_scope(node.get_scope())
        # the rhs update
        if node.has_expression():
            node.get_expression().update_scope(node.get_scope())
        # the invariant update
        if node.has_invariant():
            node.get_invariant().update_scope(node.get_scope())
 def visit_declaration(self, node):
     """
     Private method: Used to visit a single declaration, update its scope and return the corresponding set of
     symbols
     :param node: a declaration object.
     :type node: ast_declaration
     :return: the scope is update without a return value.
     :rtype: void
     """
     expression = node.get_expression() if node.has_expression() else None
     visitor = ASTDataTypeVisitor()
     node.get_data_type().accept(visitor)
     type_name = visitor.result
     # all declarations in the state block are recordable
     is_recordable = (node.is_recordable
                      or self.block_type_stack.top() == BlockType.STATE
                      or self.block_type_stack.top()
                      == BlockType.INITIAL_VALUES)
     init_value = node.get_expression() if self.block_type_stack.top(
     ) == BlockType.INITIAL_VALUES else None
     vector_parameter = node.get_size_parameter()
     # now for each variable create a symbol and update the scope
     for var in node.get_variables(
     ):  # for all variables declared create a new symbol
         var.update_scope(node.get_scope())
         type_symbol = PredefinedTypes.get_type(type_name)
         symbol = VariableSymbol(element_reference=node,
                                 scope=node.get_scope(),
                                 name=var.get_complete_name(),
                                 block_type=self.block_type_stack.top(),
                                 declaring_expression=expression,
                                 is_predefined=False,
                                 is_function=node.is_function,
                                 is_recordable=is_recordable,
                                 type_symbol=type_symbol,
                                 initial_value=init_value,
                                 vector_parameter=vector_parameter,
                                 variable_type=VariableType.VARIABLE)
         symbol.set_comment(node.get_comment())
         node.get_scope().add_symbol(symbol)
         var.set_type_symbol(Either.value(type_symbol))
     # the data type
     node.get_data_type().update_scope(node.get_scope())
     # the rhs update
     if node.has_expression():
         node.get_expression().update_scope(node.get_scope())
     # the invariant update
     if node.has_invariant():
         node.get_invariant().update_scope(node.get_scope())
     return
 def visitDataType(self, ctx):
     is_int = (True if ctx.isInt is not None else False)
     is_real = (True if ctx.isReal is not None else False)
     is_string = (True if ctx.isString is not None else False)
     is_bool = (True if ctx.isBool is not None else False)
     is_void = (True if ctx.isVoid is not None else False)
     unit = self.visit(ctx.unitType()) if ctx.unitType() is not None else None
     ret = ASTNodeFactory.create_ast_data_type(is_integer=is_int, is_boolean=is_bool,
                                               is_real=is_real, is_string=is_string, is_void=is_void,
                                               is_unit_type=unit, source_position=create_source_pos(ctx))
     # now update the type
     ret.accept(ASTDataTypeVisitor())
     # self.data_type_visitor.visit_datatype(ret)
     return ret
 def __init__(self, tokens):
     self.__comments = CommentCollectorVisitor(tokens)
     self.data_type_visitor = ASTDataTypeVisitor()