def typeck_connections(connection, type_table): """ Once all variable have been type-checked, we can try to type-check connections. :type connection: monasca_analytics.banana.grammar.ast.Connection :param connection: The connection to type-check :type type_table: monasca_analytics.banana.typeck.type_table.TypeTable :param type_table: The table with all variable already type-checked. :raise Raise an exception if there's a type error in connections. """ if connection is not None: for ident_from, ident_to in connection.connections: type_from = type_table.get_type(ident_from) type_to = type_table.get_type(ident_to) if not util.is_comp(type_from): raise exception.BananaTypeError(expected_type=util.Component(), found_type=type_from) if not util.is_comp(type_to): raise exception.BananaTypeError(expected_type=util.Component(), found_type=type_to) if type(type_to) not in valid_connections_types[type(type_from)]: possible_types = map(lambda x: x.__name__, valid_connections_types[type(type_from)]) raise exception.BananaConnectionError(connection.span, ident_from, ident_to, type_from, possible_types)
def typeck_connections(connection, type_table): """ Once all variable have been type-checked, we can try to type-check connections. :type connection: monasca_analytics.banana.grammar.ast.Connection :param connection: The connection to type-check :type type_table: monasca_analytics.banana.typeck.type_table.TypeTable :param type_table: The table with all variable already type-checked. :raise Raise an exception if there's a type error in connections. """ if connection is not None: for ident_from, ident_to in connection.connections: type_from = type_table.get_type(ident_from) type_to = type_table.get_type(ident_to) if not util.is_comp(type_from): raise exception.BananaTypeError( expected_type=util.Component(), found_type=type_from ) if not util.is_comp(type_to): raise exception.BananaTypeError( expected_type=util.Component(), found_type=type_to ) if type(type_to) not in valid_connections_types[type(type_from)]: possible_types = map(lambda x: x.__name__, valid_connections_types[type(type_from)]) raise exception.BananaConnectionError( connection.span, ident_from, ident_to, type_from, possible_types )
def set_type(self, var, _type, statement_index): """ Set the type for the given var to _type. :type var: ast.Ident | ast.DotPath :param var: The var to set a type. :type _type: util.Object | util.Component | util.String | util.Number :param _type: The type for the var. :type statement_index: int :param statement_index: The statement at which this assignment was made. """ if _type is None: raise exception.BananaTypeCheckerBug( "'None' is not a valid banana type" ) if isinstance(var, ast.Ident): self._check_needs_for_snapshot(var, _type, statement_index) self._variables[var] = _type return if isinstance(var, ast.DotPath): if util.is_comp(_type) and len(var.properties) > 0: raise exception.BananaAssignCompError(var.span) if len(var.properties) == 0: self._check_needs_for_snapshot( var.varname, _type, statement_index ) self._variables[var.varname] = _type else: if var.varname in self._variables: var_type = self._variables[var.varname] if isinstance(var_type, util.Object): new_type = util.create_object_tree( var.next_dot_path(), _type) util.attach_to_root(var_type, new_type, var.span, erase_existing=True) elif isinstance(var_type, util.Component): var_type[var.next_dot_path()] = _type else: raise exception.BananaTypeError( expected_type=util.Object, found_type=type(var) ) # Var undeclared, declare its own type else: new_type = util.create_object_tree(var.next_dot_path(), _type) self._variables[var.varname] = new_type return raise exception.BananaTypeCheckerBug("Unreachable code reached.")
def set_type(self, var, _type, statement_index): """ Set the type for the given var to _type. :type var: ast.Ident | ast.DotPath :param var: The var to set a type. :type _type: util.Object | util.Component | util.String | util.Number :param _type: The type for the var. :type statement_index: int :param statement_index: The statement at which this assignment was made. """ if _type is None: raise exception.BananaTypeCheckerBug( "'None' is not a valid banana type" ) if isinstance(var, ast.Ident): self._check_needs_for_snapshot(var, _type, statement_index) self._variables[var] = _type return if isinstance(var, ast.DotPath): if util.is_comp(_type) and len(var.properties) > 0: raise exception.BananaAssignCompError(var.span) if len(var.properties) == 0: self._check_needs_for_snapshot( var.varname, _type, statement_index ) self._variables[var.varname] = _type else: if var.varname in self._variables: var_type = self._variables[var.varname] if isinstance(var_type, util.Object): new_type = util.create_object_tree( var.next_dot_path(), _type) util.attach_to_root(var_type, new_type, var.span, erase_existing=True) elif isinstance(var_type, util.Component): var_type[var.next_dot_path()] = _type else: raise exception.BananaTypeError( expected_type=util.Object, found_type=type(var) ) # Var undeclared, declare its own type else: new_type = util.create_object_tree(var.next_dot_path(), _type) self._variables[var.varname] = new_type return raise exception.BananaTypeCheckerBug("Unreachable code reached.")
def _check_needs_for_snapshot(self, var, _type, statement_index): if var in self._variables: # If we shadow a component, we need to raise an error if util.is_comp(self._variables[var]): raise exception.BananaShadowingComponentError( where=var.span, comp=self._variables[var].class_name) # If we change the type of the variable, we create a new snapshot: # This is very strict but will allow to know exactly how # the type of a variable (or a property) changed. if self._variables[var] != _type: self._create_snapshot(statement_index)
def _check_needs_for_snapshot(self, var, _type, statement_index): if var in self._variables: # If we shadow a component, we need to raise an error if util.is_comp(self._variables[var]): raise exception.BananaShadowingComponentError( where=var.span, comp=self._variables[var].class_name ) # If we change the type of the variable, we create a new snapshot: # This is very strict but will allow to know exactly how # the type of a variable (or a property) changed. if self._variables[var] != _type: self._create_snapshot(statement_index)