pyccel.parser.scope module#

Module containing the Scope class

class pyccel.parser.scope.Scope(*, name=None, decorators=(), is_loop=False, parent_scope=None, used_symbols=None, original_symbols=None, symbolic_aliases=None)[source]#

Bases: object

Class representing all objects defined within a given scope.

This class provides all necessary functionalities for creating new object names without causing name clashes. It also stores all objects defined within the scope. This allows us to search for variables only in relevant scopes.

Parameters:
  • name (str, optional) – The name of the scope. The value needs to be provided when it is not a loop.

  • decorators (dict, default: ()) – A dictionary of any decorators which operate on objects in this scope.

  • is_loop (bool, default: False) – Indicates if the scope represents a loop (in Python variables declared in loops are not scoped to the loop).

  • parent_scope (Scope, default: None) – The enclosing scope.

  • used_symbols (dict, default: None) – A dictionary mapping all the names which we know will appear in the scope and which we therefore want to avoid when creating new names to their collisionless name.

  • original_symbols (dict, default: None) – A dictionary which maps names used in the code to the original name used in the Python code.

  • symbolic_aliases (dict, optional) – A dictionary which maps indexed tuple elements to variables representing those elements. This argument should only be used after the semantic stage.

add_loop(loop)[source]#

Make parent aware of new child loop

add_son(name, son)[source]#

Make parent aware of new child

property all_used_symbols#

Get all symbols which already exist in this scope

allow_loop_scoping = False#
categories = ('functions', 'variables', 'classes', 'imports', 'symbolic_functions', 'symbolic_aliases', 'decorators', 'cls_constructs')#
property classes#

A dictionary of classes defined in this scope

property cls_constructs#

A dictionary of datatypes for the classes defined in this scope

collect_all_imports()[source]#

Collect the names of all modules necessary to understand this scope

collect_all_tuple_elements(tuple_var)[source]#

Create a tuple of variables from a variable representing an inhomogeneous object.

Create a tuple of variables that can be printed in a low-level language. An inhomogeneous object cannot be represented as is in a low-level language so it must be unpacked into a PythonTuple. This function is recursive so that variables with a type such as tuple[tuple[int,bool],float] generate PythonTuple(PythonTuple(var_0_0, var_0_1), var_1).

Parameters:

tuple_var (Variable | FunctionAddress) – A variable which may or may not be an inhomogeneous tuple.

Returns:

All variables that should be printed in a low-level language to represent the Variable.

Return type:

list[Variable]

collect_all_type_vars()[source]#

Collect all TypeVar objects which are available in this scope.

Collect all TypeVar objects which are available in this scope. This includes TypeVars declared in parent scopes.

Returns:

A list of TypeVars in the scope.

Return type:

list[TypeVar]

collect_tuple_element(tuple_elem)[source]#

Get an element of a tuple.

This function is mainly designed to handle inhomogeneous tuples. Such tuples cannot be directly represented in low-level languages. Instead they are replaced by multiple variables representing each of the elements of the tuple. This function maps tuple elements (e.g. var[0]) to the variable representing that element in the low-level language (e.g. var_0).

Parameters:

tuple_elem (PyccelAstNode) – The element of the tuple obtained via the __getitem__ function.

Returns:

The variable which represents the tuple element in a low-level language.

Return type:

Variable

Raises:

PyccelError – An error is raised if the tuple element has not yet been added to the scope.

create_new_loop_scope()[source]#

Create a new Scope within the current scope describing a loop (For/While/etc)

create_product_loop_scope(inner_scope, n_loops)[source]#

Create a n_loops loop scopes such that the innermost loop has the scope inner_scope

Parameters:
  • inner_scope (Namespace) – Namespace describing the innermost scope

  • n_loops (The number of loop scopes required)

property decorators#

Dictionary of Pyccel decorators which may be applied to a function definition in this scope.

property dotted_symbols#

Return all dotted symbols that were inserted into the scope.

Return all dotted symbols that were inserted into the scope. This is useful to ensure that class variable names are in the class scope.

find(name, category=None, local_only=False, raise_if_missing=False)[source]#

Find and return the specified object in the scope.

Find a specified object in the scope and return it. The object is identified by a string containing its name. If the object cannot be found then None is returned unless an error is requested.

Parameters:
  • name (str) – The Python name of the object we are searching for.

  • category (str, optional) – The type of object we are searching for. This must be one of the strings in Scope.categories. If no value is provided then we look in all categories.

  • local_only (bool, default=False) – Indicates whether we should look for variables in the entire scope or whether we should limit ourselves to the local scope.

  • raise_if_missing (bool, default=False) – Indicates whether an error should be raised if the object cannot be found.

Returns:

The object stored in the scope.

Return type:

pyccel.ast.basic.PyccelAstNode

find_all(category)[source]#

Find and return all objects from the specified category in the scope.

Find and return all objects from the specified category in the scope.

Parameters:

category (str) – The type of object we are searching for. This must be one of the strings in Scope.categories.

Returns:

A dictionary containing all the objects of the specified category found in the scope.

Return type:

dict

property functions#

A dictionary of functions defined in this scope

get_expected_name(start_name)[source]#

Get a name with no collisions.

Get a name with no collisions, ideally the provided name. The provided name should already exist in the symbols.

Parameters:

start_name (str) – The name which was used in the Python code.

Returns:

The name which will be used in the generated code.

Return type:

PyccelSymbol

get_new_incremented_symbol(prefix, counter)[source]#

Create a new name by adding a numbered suffix to the provided prefix.

Create a new name which does not clash with any existing names by adding a numbered suffix to the provided prefix.

Parameters:
  • prefix (str) – The prefix from which the new name will be created.

  • counter (int) – The starting point for the incrementation.

Returns:

The newly created name.

Return type:

pyccel.ast.internals.PyccelSymbol

get_new_name(current_name=None, is_temp=None)[source]#

Get a new name which does not clash with any names in the current context.

Creates a new name. A current_name can be provided indicating the name the user would like to use if possible. If this name is not available then it will be used as a prefix for the new name. If no current_name is provided, then the standard prefix is used, and the dummy counter is used and updated to facilitate finding the next value of this common case.

Parameters:
  • current_name (str, default: None) – The name the user would like to use if possible.

  • is_temp (bool, optional) – Indicates if the generated symbol should be a temporary (i.e. an extra temporary object generated by Pyccel). This is always the case if no current_name is provided.

Returns:

The new name which will be printed in the code.

Return type:

PyccelSymbol

get_python_name(name)[source]#

Get the name used in the original Python code.

Get the name used in the original Python code from the name used by the variable that was created in the parser.

Parameters:

name (PyccelSymbol | str) – The name of the Variable in the generated code.

Returns:

The name of the Variable in the original code.

Return type:

str

get_temporary_variable(dtype_or_var, name=None, *, clone_scope=None, **kwargs)[source]#

Get a temporary variable.

Get a temporary variable.

Parameters:
  • dtype_or_var (str, DataType, Variable) – In the case of a string of DataType: The type of the Variable to be created In the case of a Variable: a Variable which will be cloned to set all the Variable properties.

  • name (str, optional) – The requested name for the new variable.

  • clone_scope (Scope, optional) – A scope which can be used to look for tuple elements when cloning a Variable.

  • **kwargs (dict) – See Variable keyword arguments.

Returns:

The temporary variable.

Return type:

Variable

property imports#

A dictionary of objects imported in this scope

insert_class(cls, name=None)[source]#

Add a class to the current scope.

Add the definition of a class to the current scope to make it discoverable when used.

Parameters:
  • cls (ClassDef) – The class to be inserted into the current scope.

  • name (str, optional) – The name under which the classes should be indexed in the scope. This defaults to the name of the class.

insert_symbol(symbol)[source]#

Add a new symbol to the scope.

Add a new symbol to the scope in the syntactic stage. This should be used to declare symbols defined by the user. Once the symbol is declared the Scope generates a collisionless name if necessary which can be used in the target language without causing problems by being a keyword or being confused with other symbols (e.g. in Fortran which is not case-sensitive). This new name can be retrieved later using Scope.get_expected_name.

Parameters:

symbol (PyccelSymbol | AnnotatedPyccelSymbol | DottedName) – The symbol to be added to the scope.

insert_symbolic_alias(symbol, alias)[source]#

Add a new symbolic alias to the scope.

A symbolic alias is a symbol declared in the scope which is mapped to a constant object. E.g. a symbol which represents a type.

Parameters:
  • symbol (PyccelSymbol) – The symbol which will represent the object in the code.

  • alias (pyccel.ast.basic.Basic) – The object which will be represented by the symbol.

insert_symbols(symbols)[source]#

Add multiple new symbols to the scope

insert_variable(var, name=None, tuple_recursive=True)[source]#

Add a variable to the current scope.

Add a variable to the current scope.

Parameters:
  • var (Variable) – The variable to be inserted into the current scope.

  • name (str, default=var.name) – The name of the variable in the Python code.

  • tuple_recursive (bool, default=True) – Indicate whether inhomogeneous tuples should be inserted recursively. Generally this should be the case, but occasionally inhomogeneous tuples are created with pre-existent elements. In this case trying to insert these elements would create an error.

property is_loop#

Indicates whether this scope describes a loop

property local_used_symbols#

Get all symbols which already exist in this scope excluding enclosing scopes

property loops#

Returns the scopes associated with any loops within this scope

property name#

The name of the scope.

The name of the scope.

name_clash_checker = <pyccel.naming.pythonnameclashchecker.PythonNameClashChecker object>#
new_child_scope(name, **kwargs)[source]#

Create a new child Scope object which has the current object as parent.

The parent scope can access the child scope through the ‘_sons_scopes’ dictionary, using the provided name as key. Conversely, the child scope can access the parent scope through the ‘parent_scope’ attribute.

Parameters:
  • name (str) – Name of the new scope, used as a key to retrieve the new scope.

  • **kwargs (dict) – Keyword arguments passed to __init__() for object initialization.

Returns:

New child scope, which has the current object as parent.

Return type:

Scope

property parent_scope#

Return the enclosing scope

property python_names#

Get map of new names to original python names

remove_loop(loop)[source]#

Remove a loop from the scope

remove_son(son)[source]#

Remove a sub-scope from the scope

remove_symbol(symbol)[source]#

Remove symbol from the scope.

Remove symbol from the scope.

Parameters:

symbol (PyccelSymbol) – The symbol to be removed from the scope.

remove_variable(var, name=None)[source]#

Remove a variable from anywhere in scope.

Remove a variable from anywhere in scope.

Parameters:
  • var (Variable) – The variable to be removed.

  • name (str, optional) – The name of the variable in the python code Default : var.name.

rename_function(o, name)[source]#

Rename a function that exists in the scope.

Rename a function that exists in the scope. This is done by finding a new collisionless name, renaming the FunctionDef instance, and updating the dictionary of symbols.

Parameters:
  • o (FunctionDef) – The object that should be renamed.

  • name (str) – The suggested name for the new function.

property sons_scopes#

A dictionary of all the scopes contained within the current scope

symbol_in_use(name)[source]#

Determine if a name is already in use in this scope.

Determine if a name is already in use in this scope.

Parameters:

name (PyccelSymbol) – The name we are searching for.

Returns:

True if the name has already been inserted into this scope, False otherwise.

Return type:

bool

property symbolic_aliases#

A dictionary of symbolic alias defined in this scope.

A symbolic alias is a symbol declared in the scope which is mapped to a constant object. E.g. a symbol which represents a type.

property symbolic_functions#

A dictionary of symbolic functions defined in this scope

update_class(cls)[source]#

Update a class which is in scope.

Search for a class in the current scope and its parents. Once it has been found, replace it with the updated ClassDef passed as argument.

Parameters:

cls (ClassDef) – The class to be inserted into the current scope.

update_parent_scope(new_parent, is_loop, name=None)[source]#

Change the parent scope

property variables#

A dictionary of variables defined in this scope