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()