Language Reference/Basic Concepts/Scoping and Visibility
Scoping & Visibility
All names (identifiers) in Visual Prolog are syntactically divided into two major groups:
- Constant names (starting with a lowercase letter)
- Variable names (starting with an uppercase letter or an underscore)
Constant names (identifiers) are divided into the following categories:
- Type names (i.e. domains and interfaces).
- Domain carriers (i.e. classes and interfaces).
- Names without parentheses (i.e. constants, fact variables of non-function type, and nullary-functors).
- Value returning names of arity N (i.e. functions, functors, and fact-variables of function type).
- Non-value-returning names of arity N (i.e. predicates, facts, and fact variables of predicate type).
Visual Prolog demands that names do not conflict at the point of declaration, because then it would be impossible to solve the conflict at point of usage. Declarations can only conflict if they are in the same scope, because qualification with scope can be used to solve the conflict. A name in one category can never be in conflict with a name in another category, but as we shall see a single declaration might place a name in several categories.
The basic units of code organization accepted in Visual Prolog are packages. We use packages in Visual Prolog to organize and structuring things. The use of packages ensures homogeneity in structuring principles among different projects. Packages define the standard for tool structuring, they ease sharing source code among projects.
The package is a collection of several grouped together interfaces and classes. The package provides some common name to all these interfaces and classes. Each declaration or implementation of each interface or class from a package is placed in a separate file. Each filename (of these files) coincides with the name of a class or an interface that is declared or implemented in this file. All package files are stored in the same separate package directory. (If a package contains sub-packages, then they are placed in subdirectories of the package directory.)
The concept of packages is used for grouping together several linked interfaces and classes. Packages can play a role of some class library. Packages can be used in your program instead of direct placing all used interfaces and classes into your program.
The accepted in Visual Prolog structure of packages and how packages should be included into projects are described in the VDE part of this help. (See Creating a Package in Creating New Project Items.)
Visibility, Shadowing, and Qualification
Most of the scoping rules are already mentioned above. This section will complete the picture.
An interface definition, a class declaration and a class implementation are scopes (scopes cannot be nested). An implementation (privately) extends the scope of the corresponding class declaration. The visibility is the same everywhere in a scope. This does especially mean that no matter where in a scope something is declared, it is visible in the whole scope.
Public names from supported interfaces and super-classes are directly (i.e. without qualification) available inside a scope, if it is unambiguous where they come from. It is illegal to use a name whose origin is ambiguous. All ambiguities in predicate calls can be removed by qualifying the predicate name with the class name (e.g. cc::p).
This qualification is also used to qualify calls of object member predicates of super-classes on the current object.
Visual Prolog has the following shadowing hierarchy:
- Super-class & opened scopes
Opened scopes have the same status as super-classes, so in the sequel we will just say super-classes.
The hierarchy means that a local declaration will shadow a super-class declaration. But there is no shadowing between super-classes; all super-classes have equal preference. If two or more super classes contain conflicting declarations then these declarations can only be accessed by means of qualification.
Assume the interface aa and the class aa_class:
interface aa predicates p1 : () procedure (). p2 : () procedure (). p3 : () procedure (). end interface class aa_class : aa end class
Also assume the class bb_class:
class bb_class predicates p3 : () procedure (). p4 : () procedure (). end class bb_class
In the context of these classes consider the implementation of a class cc_class
implement cc_class inherits aa_class open bb_class predicates p2 : () procedure (). p5 : () procedure (). clauses new() :- p1(), % aa_class::p1 p2(), % cc::p2 (shadows aa_class::p2) aa_class::p2(), % aa_class::p2 p3(), % Illegal ambigious call: aa_class::p3 or bb_class::p3 aa_class::p3(), % aa_class::p3 bb_class::p3(), % bb_class::p3 p4(), % bb_class::p4 p5(), % cc::p5 end implement cc_class