Scope rules

Identifiers are valid from the point of their declaration until the end of the block in which the declaration occurred. The range where the identifier is known is the scope of the identifier. The exact scope of an identifier depends on the way it was declared.

Block scope

The scope of a variable declared in the declaration part of a block is valid from the point of declaration until the end of the block. If a block contains a second block, in which the identifier is redeclared, then inside this block, the second declaration will be valid. Upon leaving the inner block, the first declaration is valid again. An identifier cannot be redefined in the same block, except if valid for procedure or iterator overloading purposes.

Tuple or object scope

The field identifiers inside a tuple or object definition are valid in the following places:

  • To the end of the tuple/object definition.
  • Field designators of a variable of the given tuple/object type.
  • In all descendant types of the object type.

Module scope

All identifiers of a module are valid from the point of declaration until the end of the module. Identifiers from indirectly dependent modules are not available. The system module is automatically imported in every module.

If a module imports an identifier by two different modules, each occurrence of the identifier has to be qualified, unless it is an overloaded procedure or iterator in which case the overloading resolution takes place:

  1. # Module A
  2. var x*: string
  1. # Module B
  2. var x*: int
  1. # Module C
  2. import A, B
  3. write(stdout, x) # error: x is ambiguous
  4. write(stdout, A.x) # no error: qualifier used
  5. var x = 4
  6. write(stdout, x) # not ambiguous: uses the module C's x