Language Reference/Basic Concepts

From wiki.visual-prolog.com

Types and Subtypes

Types

Visual Prolog types are divided into object types and value types. Objects have mutable state, whereas values are immutable.

Object types are defined by interface definitions.

The value types include numerical types, strings, character types, and compound domains (also known as algebraic data types). Simpler forms of compound domains are structure and enumeration types, whereas more complex forms represent tree structures.

Subtypes

Types are organized in a subtype hierarchy. Subtypes provide subsumption polymorphism: any context that expects a value of some type will also accept a value of any subtype. Equivalently, values of a given type are implicitly converted to any super-type where needed; no explicit cast is required.

Subtypes can be derived from any value type, except from algebraic data types. Types derived from algebraic data types are synonym types rather than subtypes (i.e., they denote the same type).

The notion of subtypes relates to the notion of subsets. However, even if a type is "mathematically" a subset of another type, it is not a subtype unless declared as such.

domains
    t1 = [1..17].
    t2 = [5..13].
    t3 = t1 [5..13].

t1 is an integral type whose values are the integers from 1 to 17 (inclusive). Likewise, t2 contains the values from 5 to 13. So t2 is a subset of t1, but t2 is not a subtype of t1. By contrast, t3 (which contains the same values as t2) is a subtype of t1, because it is declared to be so.

The language contains a few implicit subtype relations; otherwise, subtype relations are stated explicitly in type definitions.

Object types are organized in a subtype hierarchy rooted in the predefined object type object, i.e., any object type is a subtype of object. Object subtypes are formed by stating that one interface supports another. If an object has an interface/object type that supports another interface, the object also has that type and can be used as such without further changes.

See also: Universal and Root Types

Object System

External View

This section clarifies the class-related notions in Visual Prolog at a conceptual level. It does not discuss syntax or implementation details.

The class concept in Visual Prolog is based on three semantic entities:

  • objects
  • interfaces
  • classes
Object

An object is a set of named object member predicates together with a set of supported interfaces. Objects also have state, but this state can only be observed and changed through member predicates; the state is therefore encapsulated in the object.

Interface

An interface is an object type. It has a name and defines a set of named object predicates.

Interfaces form a supports hierarchy (a semi-lattice) rooted at the object interface. If an object has a type denoted by some interface, it also has the types of all supported interfaces. Thus the supports hierarchy is a type hierarchy: an interface is a subtype of each interface it supports.

Class

A class is a named object factory; it constructs objects that correspond to a given interface. If a class constructs objects of interface iii, then its objects are "iii objects". All objects constructed by the same class share the same definitions of the object member predicates, but each object has its own state; the predicate definitions belong to the class, while the state belongs to each object.

The set of object member predicates a class defines is the union of the predicates declared (transitively) in its interfaces. If the same predicate is declared in multiple interfaces, the class provides one common definition; this is only valid if the intended semantics coincide. Interface support must be specified explicitly.

Module

A class need not construct objects. A class without a construction type acts as a module: it may have only class members and class state.

Identity

Every object is unique. Even if two objects currently have identical state, they are not identical: one can be changed without affecting the other. We never access object state directly; we access it through references, and many references may denote the same object. Classes and interfaces are also unique and identified by name (with namespace); duplicate names are not allowed within a program. Structural equality does not imply identity for objects, classes, or interfaces.

Internal View

This section complements the external view with internal aspects: how declarations and implementations are organized. From a programmatic point of view, classes are central (they contain the code). Interfaces have mainly static importance and have no direct runtime representation; objects are dynamic and exist only when the program runs.

A class has a declaration and an implementation. The declaration states the public accessible parts of the class and of the objects it constructs; the implementation defines what the declaration introduces (predicates are implemented by clauses, by inheritance, or resolved to external libraries). A class declaration is purely declarative.

An implementation can declare additional private entities (domains, predicates, etc.). Object state is stored as facts in the implementation; such facts are per-object, while class facts are shared across all objects of the class. Facts are declared only in implementations and are not directly accessible from outside. Implementations may also (privately) support more interfaces than stated in the declaration.

Code Inheritance

Code inheritance occurs only in class implementations. Visual Prolog supports multiple inheritance via an inherits section in the implementation. The classes you inherit from are parent (super) classes; the inheriting class is the child (sub) class. A child class can only access its parent classes through their public interfaces; it receives no special privileges.


Scoping & Visibility

Name Categories

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 requires that names do not conflict at the point of declaration; otherwise, conflicts cannot be resolved at the point of use. Declarations can only conflict if they are in the same scope, because scope qualification can resolve conflicts. A name in one category can never conflict with a name in another category, but a single declaration can place a name in several categories.

Packages

Packages are the basic units of code organization in Visual Prolog. They group related interfaces and classes.

Each declaration or implementation of an interface or class in a package is placed in a separate file. Each filename matches the interface or class that it declares or implements. All package files are stored in the package directory; subpackages are stored in subdirectories of that directory.

Packages can act as class libraries. You can include packages in your program instead of placing all used interfaces and classes directly in the program.

How packages are structured and included in projects is described in the IDE documentation (see Creating a Package in Creating New Project Items).

Visibility, Shadowing, and Qualification

Most scoping rules were introduced above; this section completes 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. Visibility is the same everywhere in a scope; i.e., no matter where something is declared in the scope, 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 when their origin is unambiguous. It is illegal to use a name whose origin is ambiguous. 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 to object member predicates of super-classes on the current object.

Visual Prolog has the following shadowing hierarchy:

  • Local
  • Opened scopes and super-classes

Opened scopes have the same status as super-classes. Local declarations shadow declarations in opened scopes. If two or more opened scopes contain conflicting declarations, you can only access them by using qualification.

Example Assume the interface ixx and the classes aa and bb:
interface ixx
 
predicates
    p1 : ().
    p2 : ().
    p3 : ().
 
end interface ixx
 
%========================
 
class aa : ixx
end class aa
 
%========================
 
class bb
 
predicates
    p3 : ().
    p4 : ().
    p5 : ().
 
end class bb

The class aa creates objects of type ixx, whereas the class bb does not create objects at all.

In this context consider the implementation of a class cc:

implement cc inherits aa
    open bb
 
clauses
    p2(). % reimplementation of ixx::p2
 
predicates
    p5 : ().
clauses
    p5().
 
clauses
    new() :-
        p1(), % aa::p1
        p2(), % cc::p2 (shadows aa::p2)
        aa::p2(), % aa::p2
        p3(), % Illegal ambiguous call: aa::p3 or bb::p3
        aa::p3(), % aa::p3
        bb::p3(), % bb::p3
        p4(), % bb::p4
        p5(). % cc::p5 (shadows bb::p5)
 
end implement cc
Since cc inherits aa, all predicates in the interface ixx are visible in cc. Likewise, the open bb directive makes all predicates in bb visible in cc.