You are on page 1of 167

Visual Prolog 7.

5
Language Reference
Prolog Development Center
www.visual-prolog.com

This document describes the syntax and semantics of the Visual Prolog programming language.
Visual Prolog is a strongly typed object oriented programming language based on the logical
programming language Prolog.
A Visual Prolog program consists of a goal and a number of:
l
l
l

Interfaces
Class declarations and
Class implementations

Which contain declarations and definitions of Prolog entities:


l
l
l
l
l

Domains
Constants
Predicates
Properties
Fact databases

The "actual" code of a Visual Prolog is the clauses, which are located in class implementations and
which implements predicates.

Language Reference

Page 1 / 167

Visual Prolog 7.5 - Language Reference


Basic Concepts
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 and 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 represents tree structures.
Subtypes
Types are organized in a subtype hierarchy. Subtypes are used to introduce subsumptionpolymorphism: Any context that expects a value of some type will equally well accept a value of any
subtype. Or if we turn it around, we can say, that values of a certain type are automatically
converted to any super-type where needed and can thus be used as having the super-type without
explicit type conversion.
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 are the same type rather
than a subtype.
The notion of subtypes relates closely to the notion of subsets. But it is important to notice that
even though a type is "mathematically" a subset of another type it need not be a subtype. A type is
only subtype of another type if it is declared to be so.
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 (both 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. On the
other hand, 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, but otherwise subtype relations are explicitly
stated 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 defined by means of stating that one
interface supports another. If an object has an interface/object type that supports a certain other
interface, then the object also has that type and can without further interference be used as such
an object.
See also: Universal and Root Types

Object System
Language Reference

Page 2 / 167

Visual Prolog 7.5 - Language Reference


External View
The description in this section is not supposed to be an introduction to classes; it is intended as a
clarification of the class notions in Visual Prolog. The reader is expected to be familiar with common
class notions. The description is purely conceptual in the sense that it does not refer to any syntax,
implementation, etc. Moreover, this description does not consider any operational or programmatic
aspects. While the reasons for introducing classes, objects, etc are mostly of programmatic nature,
we find it valuable to describe the underlying concepts without reference to these programmatic
reasons.
The class concept of Visual Prolog is based on the following three semantic entities:
l
l
l

objects
interfaces
classes

Object
An object is set of named object member predicates and a set of supported interfaces. Objects
actually also have a state, but this state can only be changed and observed through the member
predicates. We say that the state is encapsulated in the object.
Here encapsulation means the ability of an object to hide its internal data and methods, making only
the intended parts of the object programmatically accessible. The importance of encapsulation and
modularity is well known. Encapsulation helps building more structured and readable programs,
because objects are treated like black boxes. Look at a complex problem, find a part, which you can
declare and describe. Encapsulate it into an object, construct an interface and continue so, until you
have declared all the sub-problems. When you have encapsulated the objects of the problem, and
ensured, that they work correctly, you can abstract from them.
Interface
An interface is an object type. It has a name and defines a set of named object predicates.
Interfaces are structured in a supports hierarchy (the structure is a semi-lattice rooted in the
interface object). If an object has a type denoted by an interface, then it also has the type of any
supported interfaces. Therefore, the supports hierarchy is also a type hierarchy. An interface is a
subtype of all its supported interfaces. We also say that the object supports the interface. If the
interface is named X, then we say that the object is an X, or an X object.
Class
A class is a named object factory; it can create objects corresponding to a certain interface. Any
object is created by a class, if an object was created by the class, which uses the interface C to
construct objects then we call it a "C object".
All objects that are constructed by a certain class share the same definition of the object member
predicates, but each object has its own state. Thus, the object member predicates is actually part of
the class, whereas the state of the object is part of the object itself.
A class also contains another set of named predicates and an encapsulated state, known as the
class members and class state, respectively. The class members and the class state exist on a per
class basis, whereas the object members and object state exist on a per object basis. The class
state can be accessed both by class members and by object members.
Language Reference

Page 3 / 167

Visual Prolog 7.5 - Language Reference


Notice! The set of object member predicates that a class defines is the union of the predicates
declared (transitively) in the interfaces of that class. More specifically this means that, if the same
predicate is declared in two different interfaces then the class will only provide one definition of that
predicate. So the class only sounds if that makes sense, i.e. if the intended semantics of these two
inherited predicates are the same.
Notice that interface support must be specified explicitly. The fact that some class provides the
predicates corresponding to some interface does not imply that the class supports the interface.
Module
In fact a class need not be able to manufacture objects at all. Such class may have only class
members and the class state. And therefore, such class can be considered to be a module rather
than a class.
Identity
Every object is unique: objects have a changeable state and since the state of the objects can be
observed by means of their member predicates an object is only identical to itself. I.e. even if the
states of two objects are identical, the objects are not identical, because we can change the state
of one object without changing the state of the other object.
We never have direct access to an object state, we always access an object state by means of a
reference to the object and while an object is only identical to itself, we can have many references
to the same object. Thus, the same object can be accessed through many different references.
Classes and interfaces are also unique; they are identified by their names. Two interfaces or classes
cannot have the same name in the same program. A class and an interface can only have the same
name if the class constructs objects of that interface.
The essence is that structural equality does not imply identity for objects, classes nor interfaces.
Internal View
Where the previous section described objects, classes, and interfaces in terms of their external
behavior, this section will extend this description with internal issues. These internal issues have more
programmatically nature; they are concerned with splitting of classes onto the declaration part and
the implementation part.
From a programmatic point of view, classes are the central item: the code is contained in the
classes.
Interfaces mainly have static importance. In fact, interfaces only exist in the textual representation
of a program; there is no (direct) runtime representation of an interface.
Objects, on the other hand, have mainly dynamic importance. Objects are not directly visible in the
program; they do not exist until the program actually runs.
A class consists of a declaration and an implementation. The declaration declares the public
accessible parts of the class and the objects it generates. The implementation on the other hand
defines the entities declared in the class declaration. The basic implementation of predicates is of
course clauses, but predicates can also be defined by means of inheritance, or resolved to external
libraries.

Language Reference

Page 4 / 167

Visual Prolog 7.5 - Language Reference


A class declaration in Visual Prolog is purely declarative. It only states which entities you can access:
not how or where they are implemented.
A class implementation can declare and define further entities (i.e. domains, predicates, etc), which
are only visible inside the class itself. I.e. they are private.
The state of an object is stored in the object as its facts. These facts are declared as normal facts
(database) sections in the implementation of the class. Facts are local to each object (like other
object entities), whereas class facts are shared among all objects of the class.
Facts can only be declared in the implementation of a class and, therefore, cannot be accessed
(directly) from outside the class.
The implementation of a class can also declare that it supports more interfaces than mentioned in the
declaration. This information is, however, only visible in the implementation itself and is, therefore,
private.
Code Inheritance
In Visual Prolog code inheritance only takes place in the implementation of a class. Visual Prolog has
multiple inheritance. You inherit from a class by mentioning the class in a special inherits section of
the implementation. The classes you inherit from are called parent classes or super-classes. Childclass or sub-class is the dual to parent class, we also say that the child classes inherit from the
parent classes. A child class can only access its parent classes through its public interface, i.e. it
does not receive any extra privileges than anybody else that use the parent class.

Scoping & Visibility


Name Categories
All names (identifiers) in Visual Prolog are syntactically divided into two major groups:
l
l

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:


l
l
l

l
l

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 nullaryfunctors).
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.
Packages
The basic units of code organization accepted in Visual Prolog are packages. We use packages in
Language Reference

Page 5 / 167

Visual Prolog 7.5 - Language Reference


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 and
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:
l
l

Local
Super-class & opened scopes

Opened scopes have the same status as super-classes, so in the sequel we will just say superclasses.
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.
Example Assume the interface aa and the class aa_class:
interface aa
predicates
p1 : () procedure ().
p2 : () procedure ().
Language Reference

Page 6 / 167

Visual Prolog 7.5 - Language Reference


p3 : () procedure ().
end interface
class aa_class : a a
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 ambiguous 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

Language Reference

Page 7 / 167

Visual Prolog 7.5 - Language Reference


Lexical Elements
The Visual Prolog Compiler is applied to a source file. This source file may include other source files,
which are (conceptually) inserted into the original source file to constitute one compilation unit.
The compilation of a compilation unit is done in two conceptual steps:
l
l

first the input is transformed into a sequence of tokens;


and then these tokens are syntactically analyzed and transformed into executable code.

The lexical analysis of the program will break the compilation unit CompilationUnit into a list of input
elements InputElement
CompilationUnit:
InputElement-list

InputElement:
Comment
WhiteSpace
Token

Only tokens are significant to the subsequent syntax analysis.

Comments
A Visual Prolog comment is written in one of the following ways:
l

The /* (slash, asterisk) characters, followed by any sequence of characters (including new
lines), terminated by the */ (asterisk, slash) characters. These comments can be multi-lined.
They can also be nested.
The % (percent sign) character, followed by any sequence of characters. Comments that
begin with character % (percent sign) continue until the end of the line. Therefore, they are
commonly called single-line comments.

Notice the following comment example:

/* Begin of Comment1
%NestedComment2*/Comment1isnotterminated(single-line comment)
This is the real termination of Comment1 */

Whitespace
WhiteSpace:
Space
Tab
NewLine

Here Space is a space character, Tab is a tabulation character and NewLine is a new line character.

Tokens

Language Reference

Page 8 / 167

Visual Prolog 7.5 - Language Reference


Token:
Identifier
Keyword
Punctuator
Operator
Literal

Identifiers
Identifier:
LowercaseIdentifier
UppercaseIdentifier
AnonymousIdentifier
Ellipsis

A LowercaseIdentifier is a sequence of letters, digits, and underscores that starts with a small
letter. An UppercaseIdentifier is a sequence of letters, digits, and underscores that starts either
with a capital letter or with an underscore.
AnonymousIdentifier :

Ellipsis :
...

Keywords
Keywords are divided into major and minor keywords, this division is only cosmetic however, there is
no formal difference between major and minor keywords. In the sequel we will however use different
coloring for them.
Keyword :
MajorKeyword
MinorKeyword

MajorKeyword : one of
class clauses constants constructors
delegate domains
end
facts
goal
implement inherits interface
monitor
namespace
open
predicates
properties
resolve
supports

MinorKeyword : one of
align and anyflow a s
bitsize
catch
determ digits div d o
Language Reference

Page 9 / 167

Visual Prolog 7.5 - Language Reference


else elseif erroneous externally
failure finally foreach from
guard
if in
language
mod multi
nondeterm
or orelse
procedure
quot
rem
single
then to try

All keywords except as and language are reserved words.


end is always combined with another key word:
end
end
end
end
end
end

class
implement
interface
if
foreach
try

Punctuation Marks
Punctuation marks in Visual Prolog have syntactic and semantic meaning to the compiler, but do not
specify by themselves an operation that yields a value. Some punctuation marks, either alone or in
combinations, can also be Visual Prolog operators.
Punctuation marks are:
PunctuationMarks: one of
! , . # [ ] |

:-

::

Operators
Operators specify an evaluation to be performed on involved operands.
Operators: one of
^
/ * div mod quot rem
+ = < > <> >< <=

>=

:=

All operators are binary, but - and + also exist as unary operators.
div, mod, quot and rem are reserved words.

Literals
Literals fall into following categories: integer, character, floating-point, string, binary and list.

Language Reference

Page 10 / 167

Visual Prolog 7.5 - Language Reference


Literal:
IntegerLiteral
RealLiteral
CharacterLiteral
StringLiteral
BinaryLiteral
ListLiteral
CompoundDomainLiteral

Integral Literals
IntegerLiteral:
UnaryPlus-opt DecimalDigit-list
UnaryMinus-opt DecimalDigit-list
UnaryPlus-opt OctalPrefix OctalDigit-list
UnaryMinus-opt OctalPrefix OctalDigit-list
UnaryPlus-opt HexadecimalPrefix HexadecimalDigit-list
UnaryMinus-opt HexadecimalPrefix HexadecimalDigit-list

UnaryPlus:
+

UnaryMinus:

OctalPrefix:
0o

OctalDigit: one of
01234567

DecimalDigit: one of
0123456789

HexadecimalPrefix:
0x

HexadecimalDigit: one of
0123456789AaBbCcDdEeFf

An integral literal can belong to integer or unsigned domains and it should not exceed maximum and
minimum integer or unsigned values.
Real Literal
RealLiteral:
UnaryMinus-opt DecimalDigit-list FractionOfFloat-opt Exponent-opt

FractionOfFloat:
. DecimalDigit-list

Exponent:
ExponentSymbol ExponentSign-opt DecimalDigit-list

ExponentSymbol: one of
eE

ExponentSign: one of
-+

A floating literal should not exceed maximum and minimum real values.

Language Reference

Page 11 / 167

Visual Prolog 7.5 - Language Reference


Character Literals
CharacterLiteral:
' <CharacterValue> '

CharacterValue can be any printable character or an escape sequence:


l
l
l
l
l
l
l

\\ representing \
\t representing Tab character
\n representing New Line character
\r representing carriage return
\' representing single quote
\" representing double quote
\uXXXX, here XXXX should be exactly four HexadecimalDigit's representing the Unicode
character corresponding to the digits.

String Literals
StringLiteral:
StringLiteralPart-list

StringLiteralPart:
' <CharacterValue>-list-opt '
" <CharacterValue>-list-opt "
@AtOpenChar AnyCharacter-list-opt AtCloseChar

A string literal consists of one or more StringLiteralPart's, which are concatenated.


The first two forms (the ' and " forms) uses escape sequences to express certain characters
l
l
l
l
l
l
l

\\ representing \
\t representing Tab character
\n representing New Line character
\r representing carriage return
\" representing double quote
\" representing single quote
\uXXXX, here XXXX should be exactly four HexadecimalDigit's representing the Unicode
character corresponding to the digits.

In single quoted strings it is optional to escape double quotes, and likewise it is optional to escape
single quotes in double quoted strings.
Single quoted strings must contain at least two characters otherwise they will be assumed to be a
character literal.
The @-literals can be used to avoid obscuring the string literals with escape characters. The literals
starts with @ followed by some non-letter character AtOpenChar. And it terminates when the close
character AtCloseChar is met. For most characters the close character is the same as the opening
character, but for diverse paranthesis charactes the close character is the corresponding opposite
paranthesis.
Open Close Open Close
Language Reference

Page 12 / 167

Visual Prolog 7.5 - Language Reference


@(

@)

@[

@]

@{

@}

@<

>

@>

<

For all non-paranthesis opening character the close character is the same as the open character, for
example @" is closed by ".
For all @-strings it is the case the twice the closing character does not close the string, but means
one occurence of the closing character in the string.
Example
This example uses @[ as opening and ] as closing, inside the string literal both " and ' can be used
unescaped:
Binary Literals
BinaryLiteral:
$[ ElementValue-comma-sep-list-opt ]
ElementValue:
IntegerLiteral

ElementValue should be any integral arithmetic expression (for example, constant), which should be
calculated while compilation-time and be in the range from 0 till 255.
List Literals
All elements in a list literal must belong to the same domain (or to compatible domains). This domain
can be any built-in or user defined domain, for example, it can be integral, character, binary,
compound domain, etc.
ListLiteral:
[ SimpleLiteral-comma-sep-list-opt ]
[ SimpleLiteral-comma-sep-list | ListLiteral ]

Here SimpleLiteral can be:


SimpleLiteral:
IntegerLiteral
RealLiteral
CharacterLiteral
StringLiteral
BinaryLiteral
ListLiteral
CompoundDomainLiteral

Example These are all valid list literals:


[]

% empty list

Language Reference

Page 13 / 167

Visual Prolog 7.5 - Language Reference


[1,2,3]
% list of integers
["abc", "defg"]
% list of strings

Example This is invalid because the elements in a list must all have same type:
[1,"abc"]

% this is INVALID list

Compound Domain Literals


Terms of user defined compound domains can be treated as literals if all their arguments are literals.

Language Reference

Page 14 / 167

Visual Prolog 7.5 - Language Reference


Compilation Units
A program consists of a number of compilation units. The compiler compiles each of these compilation
units separately. The result of a compilation is an object file. These object files (and perhaps other
files) are linked together to produce the project target. A program must contain exactly one
goalSection, which is the entry point to the program.
A compilation unit has to be self-contained in the sense that all referenced names have to be either
declared or defined in the unit. Interface definitions and class declarations can be included in several
compilation units (the definitions/declarations must be identical in all units where they are included),
whereas class implementations (definitions) may only be defined in a single unit. Every declared item
must also be defined in the project, but some items can be defined in libraries, meaning that they do
not need a textual definition.
A compilation unit (which is perhaps composed by using #include directives) is a sequence of
compilation items.
CompilationUnit :
CompilationItem-list-opt

A compilation item is an interface, a class declaration, a class implementation, the goal section or it
can be a conditional compilation item, which are described in Conditional Compilation.
CompilationItem :
Directive
NamespaceEntrance
ConditionalItem
InterfaceDefinition
ClassDeclaration
ClassImplementation
GoalSection

See also
l
l
l
l
l
l
l

Interfaces
Classes
Implementations
Namespaces
Goal Section
Directives
Conditional Item

Language Reference

Page 15 / 167

Visual Prolog 7.5 - Language Reference


Interfaces
An interface definition defines a named object type. Interfaces can support other interfaces. See
Supports Qualification for further details.
All predicates declared in an interface are object members in objects of the interface type.
An interface is also a global scope, in which constants and domains can be defined. Thus constants
and domains defined in an interface are not part of the type that the interface denotes (or of objects
having this type).
Such domains and constants can be referenced from other scopes by qualification with the interface
name: interfaceName::constant, or by using an open qualification. (See Open Qualification.)
InterfaceDefinition :
interface InterfaceName
ScopeQualifications
Sections
end interface IinterfaceName-opt

InterfaceName :
LowerCaseIdentifier

See also Generic Interfaces and Classes and Monitors.


The InterfaceName in the end of the construction must (if present) be identical to the one in the
beginning of the construction.
The ScopeQualifications must be of the kinds:
l
l

Supports Qualification
Open Qualification

The Sections must be of the kinds:


l
l
l
l
l
l

ConstantsSection
DomainsSection
PredicatesSection
PredicatesFromInterface
PropertiesSection
ConditionalSection

All sections contained (transitively) in conditional sections must also be of those kinds.

The interface: object


If an interface does not explicitly support any interfaces, then it implicitly supports the build-in
interface object.
The object is an empty interface, i.e. it contains no predicates etc.
The purpose of object is to be a universal base-type of all objects.
Language Reference

Page 16 / 167

Visual Prolog 7.5 - Language Reference


Open Qualification
Open qualifications are used to make references to class level entities more convenient. The open
section brings the names of one scope into another scope, so that these can be referenced without
qualification.
Open has no effect on the names of object members as these can only be accessed by means of an
object anyway. But names of class members, domains, functors and constants can be accessed
without qualification.
When names are brought into a scope in this way it may happen that some names becomes
ambiguous (see Scoping).
Open sections have only effect in the scope in which they occur. Especially this means that an open
section in a class declaration has no effect on the class implementation.
OpenQualification :
open ScopeName-comma-sep-list

Supports Qualification
Supports qualifications can only be used in InterfaceDefinition and ClassImplementation.
Supports qualifications are used for two things:
l

specifying that one interface A extends another interface B and, thereby, that the object type
A is a subtype of the object type B
declaring that the objects of a certain class "privately" have more object types, than the one
specified as construction type.

supports is a transitive relation: if an interface A supports an interface B and B in turn supports


C, then A also supports C.
If an interface does not explicitly support any interfaces, then it implicitly supports the predefined
interface object.
Functionally, it makes no difference whether an interface supports a certain interface more that once
(directly and/or indirectly), but it might make a representational difference for the objects.
When supports is used in the implementation of a class, the result is that "This" not only can be
used with the construction type, but also with any privately supported object type.
SupportsQualification :
supports InterfaceName-comma-sep-list

SupportsQualification can only be used in InterfaceDefinition and ClassImplementation.


Notice interfaces cannot be used together in a supports qualification, if they have conflicting
predicates.
Predicates are conflicting if they have the same name and the arity but different origin interfaces.
Language Reference

Page 17 / 167

Visual Prolog 7.5 - Language Reference


The origin interface of a predicate is the interface in which the predicate is literally declared, as
opposed to interfaces where it is indirectly declared by a supports qualification.
So it does not give conflicts, if the same interface is met twice or more in the supports chains.
Example Consider the following definitions and declarations:
interface aaa
predicates
insert : (integer X).
end interface

interface bbb
supports aaa
predicates
insert : (integer X, string Comment).
end interface

interface cc
supports aaa
predicates
extract : () -> integer.
end interface

interface dd
supports aaa, bbb, cc
predicates
extract : (string Comment) -> integer.
end interface

Here is a list of all predicates found in dd (found by a depth traversal):


predicates
insert : (integer).
% dd -> aaa
insert : (integer).
% dd -> bbb -> aaa
insert : (integer, string).
% dd -> bbb
insert : (integer).
% dd -> cc -> aaa
extract : () -> integer.
% dd -> cc
extract: : (string) -> integer.
% dd

Some of the predicates are the same, so all in all, dd will contain the following members:
predicates
insert : (integer).
% origin interface: aaa
insert : (integer, string).
% origin interface: bbb
extract : () -> integer.
% origin interface: cc
extract : (string) -> integer.
% origin interface: dd

Example Consider the following interfaces:


interface aaa
predicates
insert : (integer X).
end interface

interface bbb
predicates
insert : (integer X).
Language Reference

Page 18 / 167

Visual Prolog 7.5 - Language Reference


end interface

interface cc
supports aaa, bbb
end interface

% conflicting interfaces

The interface cc is illegal, because insert/1 supported in aaa has aaa as origin, whereas insert/1
supported in bbb has bbb as origin.

Language Reference

Page 19 / 167

Visual Prolog 7.5 - Language Reference


Classes
A class declaration defines the appearance of the class to the surroundings: the surroundings can
see and use exactly those entities mentioned in the class declaration. We say that the declaration of
a class specifies the public part of the class.
A class declaration can contain constant and domain definitions and predicate declarations.
If the class states a construction type ConstructionType, then it constructs objects of that type.
Object constructing classes have at least one constructor, but more can be declared. Classes that
do not explicitly declare any constructors are automatically equipped with the default constructors
(i.e. new/0).
Objects are constructed by invoking one of constructors of the class.
Constructors are also used when initializing inherited classes.
Everything mentioned in a class declaration belongs to the class, rather than to objects it constructs.
Everything that relates to the objects must be declared in the construction type of the objects
constructed by the class.
Any class declaration ClassDeclaration must have an accompanying class implementation
ClassImplementation. The definition/implementation of predicates declared in the class declaration
is provided by the class implementation. Likewise the definition of the predicates supported by the
objects constructed by the class is provided by the class implementation. Both kinds of predicates
can be implemented by clauses, but object predicates can also be inherited from other classes.
It is important to notice that a class declaration does not state anything about code inheritance.
Code inheritance is a completely private matter that can only be stated in the class implementation.
(This is unlike many other object oriented programming languages, and serves to hide all
implementation details in the implementation).
If the class does not state a construction type ConstructionType, then the class cannot
manufacture any objects; it therefore plays the role of a module rather than a "real" class.
ClassDeclaration :
class ClassName ConstructionType-opt
ScopeQualifications
Sections
end class ClassName-opt

ConstructionType :
: InterfaceName

ClassName :
LowerCaseIdentifier

See also Generic Interfaces and Classes and Monitors.


The ClassName in the end of the class declaration must (if present) be identical to the one in the
beginning of the class declaration.

Language Reference

Page 20 / 167

Visual Prolog 7.5 - Language Reference


Notice that you can use the same class name ClassName as the interface name ConstructionType
specified as the construction type to this class. That is you can write:
class interfaceAndClassName : interfaceAndClassName

Notice that both the class and the interface can declare domains and constants and these must not
conflict with each other since they end up in the same name space (because they can be qualified
only with the same name of the interface or the class).
The ScopeQualifications must be of the kind OpenQualification.
The Sections must be of the kinds:
l
l
l
l
l
l

constantsSection
domainsSection
predicatesSection
constructorsSection
PropertiesSection
conditionalSection

constructorsSections are only legal if the class states a ConstructionType.


All sections contained (transitively) in conditional sections must also be of those kinds.

Language Reference

Page 21 / 167

Visual Prolog 7.5 - Language Reference


Implementations
A class implementation is used to provide the definitions of the predicates and constructors declared
in the class declaration, as well as the definitions of any predicates supported by its constructed
objects.
A class can privately (i.e. inside the implementation) declare and define more entities than those
mentioned in the declaration. Especially, an implementation can declare fact databases that can be
used to carry class and object state.
An implementation is a mixed scope, in the sense that it both contains the implementation of the
class and of the objects produced by the class. The class part of a class is shared among all objects
of the class, as opposed to the object part, which is individual for each object. Both the class part
and the object part can contain facts and predicates, whereas domains, functors and constants
always belong to the class part, i.e. they do not belong to individual objects.
By default all predicate and fact members declared in the implementation of a class are object
members. To declare class members the section keyword (i.e. predicates and facts) must be
prefixed with the keyword class. All members declared in such sections are class members.
Class members can reference the class part of a class, but not the object part.
Object members, on the other hand, can access both the class part and the object part of the class.
In the code in the implementation, the owner object is subsumed by all object predicates. The
subsumed owner object can also be accessed directly through the special variable "This".
ClassImplementation :
implement ClassName
ScopeQualifications
Sections
end implement ClassName-opt

See also Generic Interfaces and Classes.


The ClassName in the end of the class implementation must (if present) be identical to the one in
the beginning of the class implementation.
The ScopeQualifications must be of the kinds:
l
l
l
l

SupportsQualification
OpenQualification
InheritQualification
DelegateQualification

A Supports qualification states the list of interfaces, which are supported privately by the class
implementation.
A Delegate qualification delegates functionality of (object) predicates from interfaces to predicates
from objects, which can be stored as fact variables.
The Sections must be of the kinds:
l

ConstantsSection

Language Reference

Page 22 / 167

Visual Prolog 7.5 - Language Reference


l
l
l
l
l
l
l
l

ResolveQualification
DelegateQualification
DomainsSection
PredicatesSection
PropertiesSection
FactsSection
ClausesSection
ConditionalSection

constructorsSections are only legal if the class ClassName states a ConstructionType. Classes
that states a ConstructionType are also object constructors, which construct objects of the stated
construction type.
Example
This example illustrates how class facts are shared among the objects of the class and how object
facts are not shared.
Consider the interface aa and class aa_class:
interface aa
predicates
setClassFact : (integer Value).
getClassFact : () -> integer.
setObjectFact : (integer Value).
getObjectFact : () -> integer.
end interface
class aa_class : a a
end class

The point of the predicates is that they store and fetches values from respectively class and object
facts:
implement aa_class
class facts
classFact : integer := 0.
facts
objectFact : integer := 0.
clauses
setClassFact(Value) :classFact := Value.
getClassFact() = classFact.
clauses
setObjectFact(Value) :objectFact := Value.
getObjectFact() = objectFact.
end implement aa_class

Given this class consider the goal:


goal
A1 = aa_class::n e w(),
A2 = aa_class::n e w(),
A1:setClassFact(1),
A1:setObjectFact(2),
ClassFact = A2:getClassFact(),
ObjectFact = A2:getObjectFact().

Language Reference

Page 23 / 167

Visual Prolog 7.5 - Language Reference


The class fact is shared among all objects, so setting the class fact via A1 also affects the value
obtained via A2. Hence, the value of ClassFact will be one, the value set via A1.
On the other hand, object facts belong to each object. Therefore setting the object fact in A1 will
not affect the value stored in A2. Hence value of ObjectFact is zero, the value that the fact was
initialized to in A2.

Construction
This section describes object construction and, as such, it only deals with classes that produce
objects.
Objects are constructed by calling a constructor.
Constructors are explicitly declared in constructors sections in class declarations and
implementations (see also Default Constructor).
A constructor actually has two associated predicates:
l
l

A class function, which returns a new constructed object.


An object predicate, which is used when initializing inherited objects.

The associated object predicate is used to perform initialization the object. This predicate can only
be called from a constructor in the class itself and from a constructor in a class, which inherits from
the class (i.e. base class initialization).
The associated class function is defined implicitly, i.e. there are no clauses for it anywhere.
The class function allocates memory to hold the object, perform internal initialization of the object
and then invokes the object constructor on the created object. Finally, the constructed object is
returned as the result of the constructor execution.
So before the clauses of the constructor are invoked:
l
l

All object facts variables that have an initialization expression are initialized.
All object facts that have clauses are initialized from these clauses.

This initialization is also performed on all (transitively) inherited sub-objects, before the clauses of the
constructor are invoked.
The constructor clauses must:
l

Initialize all those single object facts and object fact variables that are not initialized before
entrance.
Initialize all sub-objects.

The constructor clauses can do other things as well, but it must perform the initialization mentioned
here to ensure that the object is valid after construction.
Note. During construction objects might not be valid and care must be taken not to access uninitialized parts of the object (see Rules for Constructing Objects).
Default Constructor
Language Reference

Page 24 / 167

Visual Prolog 7.5 - Language Reference


A default constructor is a null-ary constructor with the name new/0. If a class that constructs
objects does not declare any constructors in the class declaration, then the default constructor (i.e.
new/0) is implicitly declared (in the class declaration). This means that each class has at least one
constructor. So writing:
class aaa
end class aaa

is exactly the same as writing


class aaa
constructors
new : ().
end class aaa

It is legal to re-declare the default constructor explicitly.


It is not necessary to define (i.e. implement) the default constructor; if it is not defined then an
effect-less definition is implicitly assumed. So writing
implement aaa
end implement aaa

is exactly the same as writing:


implement aaa
clauses
new().
end implement aaa

(Given that aaa has a default constructor).


Notice that a class has a default constructor if and only if:
l
l

it does not (publicly) declare any constructors at all;


or it declares new/0 as a constructor.

Which is the same (negated) as: A class does not have a default constructor if:
l
l

It publicly declares constructors;


and it does not publicly declare new/0 as a constructor.

Example
Given an interface aa, consider the following code:
class aa_class : a a
end class

Language Reference

Page 25 / 167

Visual Prolog 7.5 - Language Reference


The class aa_class declares no constructors; therefore, it implicitly declares the default constructor.
Thus you can create an aa_class object like:
goal
_A = aa_class::n e w(). % implicitly declared default constructor

Example
It is legal to implement the implicitly declared default constructor of aa_class:
implement aa_class
clauses
new() :...
end implement

Example
The bb_class class explicitly declares a constructor, which is not the default constructor;
subsequently the class does not have the default constructor
class bb_class : a a
constructors
newFromFile : (file File).
end class

Example
The cc_class class declares the newFromFile/1 constructor, but it also declares the default
new/0 constructor; so obviously, it has the default new/0 constructor
class cc_class : a a
constructors
new : ().
newFromFile : (file File).
end class

% default constructor

Private Constructors
You also can declare "private" constructors in class implementations. This can be reasonable, for
example, in the following situations:
1. When some predicate returns an object of construction type, then in a class implementation
can be declared, implemented and called a "private" constructor to create such objects.
2. When some class declares several "public" constructors having a "same big part", then it can be
reasonable to define in the class implementation a "private" constructor, which implements this
"same big part". Then clauses of all these "public" constructors can simply call this "private"
constructor to implement this "same big part".
Notice that if a class, which can construct objects, does not declare any constructors in the class
declaration, then the default constructor (i.e. new/0) will be declared implicitly independently of
whether the class implementation declares or not "private" constructors. That is, it is possible to
Language Reference

Page 26 / 167

Visual Prolog 7.5 - Language Reference


write:
interface aa
end interface

class aa : a a
end class

implement aa
constructors
myCreate : ().
clauses
myCreate() :...
end implement

% program code
...
Obj = aa::n e w(),
% This is the declared IMPLICIT default class constructor
...

Sub-object Construction
All constructors are responsible for initializing constructed objects to valid states. In order to obtain
such a valid state all sub-objects (i.e. inherited classes) must be initialized as well.
The sub-objects can be initialized in one of two ways, either the programmer calls a constructor of
the inherited class or the default constructor is automatically invoked. The latter requires that the
inherited class actually has the default constructor, but this is no difference whether this default
constructor is declared explicitly or implicitly - it will be called in both cases!
If the inherited class does not have a default constructor, then another constructor must be invoked
explicitly. The default invocation of constructors of inherited classes takes place immediately after
initialization of fact variables and facts with clauses and before entrance to the clauses of the
constructor.
Constructors of inherited classes are invoked by the versions that does not return a value. If you call
the version that returns a value then you are actually creating a new object, rather than invoking the
constructor on "This" (see the example below).
Example
This implementation of the class bb_class inherits from the class aa_class and the default
constructor of bb_class call a constructor of aa_class with a newly created cc_class object
implement bb_class inherits aa_class
clauses
new() :C = cc_class::n e w(), % create a cc_class object
aa_class::newC(C). % invoke constructor on inherited sub-object
...
end implement

Example 2
If a base class is not explicitly constructed, then it is implicitly constructed using the default
constructor. So writing:
Language Reference

Page 27 / 167

Visual Prolog 7.5 - Language Reference


implement bbb
inherits aaa
clauses
myNew() :doSomething().
end implement bbb

is exactly the same as writing:


implement bbb
inherits aaa
clauses
myNew() :aaa::n e w(),
doSomething().
end implement bbb

If aaa does not have a default constructor then this will, of course, give an error.
Notice that this rule (of course) can be combined with the rule discussed in the first paragraph of
Default Constructor. So writing:
implement bbb
inherits aaa
end implement bbb

Is exactly the same as writing (according to the rule discussed in the first paragraph of Default
Constructor):
implement bbb
inherits aaa
clauses
new().
end implement bbb

Which is exactly the same as writing (the rule discussed above):


implement bbb
inherits aaa
clauses
new() :aaa::n e w().
end implement bbb

Single (Object) Fact Initialization


Just like all constructors have to initialize/construct sub-objects, they also have to initialize all single
facts of an object, before they are referenced the first time.
Notice that single class facts can only be initialized with clauses, since they are not related to an
object. A class fact can be accessed before the first object is created.

Language Reference

Page 28 / 167

Visual Prolog 7.5 - Language Reference


Example
This example shows (1) how to initialize a fact variable by means of an expression; (2) how to
initialize a single fact (point) by means of a clause; (3) how to initialize a single fact in the
constructor and (4) where the default constructor of an inherited class is invoked:
implement bb_class inherits aa_class
facts
counter : integer := 0.
point : (integer X, integer Y) single.
c : (cc C) single.
clauses
point(0, 1).
% The object is created and counter and point are initialized before entrance,
% the default constructor aa_class::new/0 is also invoked before entrance
new() :C = cc_class::n e w(),
assert(c(C)).
...
end implement

Construction by Delegation
As an alternative to construct the object directly in a constructor the job can be delegated to
another constructor of the same class. This is done simply by invoking the other constructor (i.e. the
version that does not return a value). When delegating construction we have to be sure that the
object is actually constructed and that it is not "over-constructed". Single facts can be assigned a
value as many times as one likes so they cannot be "over-constructed". Inherited classes, on the
other hand, may only be initialized once during object construction.
Example
This example shows a typical use of construction by means of delegation. A constructor (new/0)
invokes another constructor (newFromC/1) with a default value.
implement aa_class
facts
c : (cc C) single.
clauses
new() :C = cc_class::n e w(),
newFromC(C).
newFromC(C) :assert(c(C)).
...
end implement

Rules for Constructing Objects


The programmer must ensure that:
l
l
l
l

All sub-objects are initialized/constructed exactly once each.


All single facts are initialized (at least once).
That no sub-object is referenced before it is initialized/constructed.
That no single fact is used before it is initialized.

There is no guarantee about how clever the compiler is in detecting such problems at compile time.
Language Reference

Page 29 / 167

Visual Prolog 7.5 - Language Reference


The compiler may offer to generate runtime validation, it may also offer to non-safely omit such
runtime validations.

"This"
An object predicate is always invoked on an object. This object carries the object facts and is
subsumed by the implementation of object predicates. The object predicate has access to this
implicit object. We shall call the object "This". There are two kinds of access to "This" implicit and
explicit.
Explicit "This"
In every clause of every object predicate the variable This is implicitly defined and bound to "This",
i.e. the object whose member predicate is executing.
Implicit "This"
In the clause of an object member predicate other object member predicates can be called directly,
because "This" is implicitly assumed for the operation. Members of super-classes can also be invoked
directly, as long as it is unambiguous which method is called (see Scoping & Visibility). Likewise the
object facts (which are stored in "This") can be accessed.
"This" and Inheritance
[Notice this particular section is subject to change, as it is decided to change the language
semantics in this matter.]
"This" always refer to an object belonging to the class in which "This" is used, also if that class is
inherited by another class.
Assume the interface aa declared as follows:
interface aa
predicates
action : ().
doAction : ().
end interface

also assume the class aa_class declared as follows:


class aa_class : a a
end class

And implemented as follows:


implement aa_class
clauses
action() :doAction(),
This:doAction().
doAction() :write("aa_class::doAction"), nl.
end implement
Language Reference

Page 30 / 167

Visual Prolog 7.5 - Language Reference


The following goal:
goal
A = aa_class::n e w(),
A:action().

Will write:
aa_class::doAction
aa_class::doAction

Now also consider class bb_class declared as follows:


class bb_class : a a
end class

And implemented as follows


implement bb_class inherits aa_class
clauses
doAction() :write("bb_class::doAction"), nl.
end implement

The following goal:


goal
B = bb_class::n e w(),
B:action().

Will also write:


aa_class::doAction
aa_class::doAction

because (both implicit and explicit) "This" in aa_class refers to the object of class aa_class.
Now consider else one example:
interface iName
predicates
className : () -> string Class.
name: () -> string Class.
nameThis: () -> string Class.
end interface iName

class aaa : iName


end class aaa

implement aaa
Language Reference

Page 31 / 167

Visual Prolog 7.5 - Language Reference


clauses
className() = "aaa".
clauses
name() = className().
clauses
nameThis() = This:className().
end implement aaa

class bbb : iName


end class bbb

implement bbb
inherits aaa
clauses
className() = "bbb".
end implement bbb

goal
OOO = bbb::n e w(),
Class1 = OOO:name(),
Class2 = OOO:nameThis().

Class bbb inherits the definition of name and nameThis from aaa, but it re-implements className.
In the goal we create a bbb object and on this we call name and nameThis.
The name predicate calls className directly, while nameThis calls This:className. The effects
are different. The name predicate calls className, which is defined in aaa. But nameThis call the
className that is defined on This and that is actually bbb::className, since This is a bbb object.
All in all Class1 is bound to the value "aaa", whereas Class2 is bound to "bbb".
Calling from a parent class to a child class like in nameThis is very often used to implement general
functionality in a shared parent class. The general functionality relies on the refinements of the child
classes for the non-generalized functionality.
Also consider this class:
interface iTest
predicates
test : () -> string Name.
end interface iTest

class ccc : iTest


end class ccc

implement ccc
inherits aaa
clauses
test() = aaa::nameThis().
end implement ccc

ccc also inherits from aaa. Since ccc inherits from aaa it also implicitly supports the iName interface
(i.e. privately). So when aaa calls This:className it call the one that ccc provides, which happens
to be the one inherited from aaa.
Also consider this example:
class ddd : name
end class ddd

Language Reference

Page 32 / 167

Visual Prolog 7.5 - Language Reference


implement ddd
inherits bbb
clauses
className() = "ddd".
end implement ddd
goal
OOO = ddd::n e w(),
Class1 = OOO:name(),
Class2 = OOO:nameThis().

ddd inherits from bbb which we know inherits from aaa. When calling nameThis we actually call
aaa::nameThis, which calls This:className. In this case This is the ddd object and therefore the
effective call will go to ddd::className.
All in all a call to This:className goes to last child that supports an interface containing
className.

Inherits Qualification
Inherits qualifications are used to state that an implementation inherits from one or more classes.
Inheritance has only influence on the object part of a class.
The purpose of inheriting from other classes is to inherit behavior from these classes.
When a class cc inherits from a class aa, this means that the implementation of the cc class
automatically implicitly (privately) supports the construction type (interface) of the aa class. (If the
class aa implementation already support the cc construction type explicitly then there is of course no
difference.)
Therefore, notice that the same predicate, for example p, cannot be declared in the construction
type interface of a cc class and in the construction type interface of an inherited aa class. (The
compiler will detect this and generates an error that a predicate is declared in 2 places.) Let us
discuss this in some details. Let us suppose that a cc class has a construction type interface cci and
some other aa class has a construction type interface aai. Let both aai and cci interfaces declare
the same predicate p. Till the aa and cc classes are independent, the compiler does not detect any
problems. But as soon as we declare that the cc class inherits from the aa class, then cc class starts
to support also the aai interfaces. Therefore, the cc class starts to see both declarations of the
predicate p, which will be reported as a compiling time error. The only possibility to avoid such
ambiguity in the predicate p declaration is using of the Predicates from Interface section in the cci
interface declaration. For example like:
interface cci
predicates from aai
p(), ...
end interface cci

Object predicates can be inherited: If the class does not implement a certain of its object predicates,
but one of the classes it inherits from does implement this predicate, then that predicate will be used
for the current class.
The class that inherits from another class does not have any special privileges towards the inherited
class: It can only access the embedded object through its construction type interface.
Inheritance must be unambiguous. If the class defines the predicate itself then there is no ambiguity,
because then it is this predicate definition that is exposed. If only one inherited class supports the
Language Reference

Page 33 / 167

Visual Prolog 7.5 - Language Reference


predicate then it is also unambiguous. But if two or more classes supports the predicate then it is
ambiguous which class provides the definition. In that case the ambiguity must be resolved by means
of a resolve qualification (see Resolve Qualification).
Object predicates from inherited classes can be called directly from object predicates in the current
class, since the embedded sub-object is implicitly used as predicate owner. Class qualification can be
used to resolve calling ambiguities for object predicates from inherited classes.
InheritsQualification :
inherits ClassName-comma-sep-list

Resolve Qualification
As mentioned elsewhere all ambiguities related to calling predicates can be avoided by using qualified
names.
But when it comes to inheritance this is not the case. Consider the following example:
interface aa
predicates
p : () procedure ().
...
end interface

class bb_class : a a
end class

class cc_class : a a
end class

class dd_class : a a
end class

implement dd_class inherits bb_class, cc_class


end implement

In this case it is ambiguous which of the classes bb_class and cc_class that would provide the
implementation of aa for dd_class. (Notice that when we say that a class implements an interface,
it means that it provide definitions for the predicates declared in the interface.)
It would of course be possible to add clauses to the implementation of dd_class, which would
effectively solve the job. Consider, for example, the following clause, which would "export" the
predicate p from bb_class:
clauses
p() :- bb_class::p().

But, with this code we have not really inherited the behavior from bb, we have actually delegated
the job to the bb_class part of our class.
So to resolve this kind of ambiguities (and use real inheritance rather than delegation) we use a
resolve section. A resolve section contains a number of resolutions:
ResolveQualification :
Language Reference

Page 34 / 167

Visual Prolog 7.5 - Language Reference


resolve Resolution-comma-sep-list

Resolution :
InterfaceResolution
PredicateFromClassResolution
PredicateRenameResolution
PredicateExternallyResolution

A resolve qualification is used to resolve an implementation from the specified source.


Predicate Resolution
PredicateFromClassResolution :
PredicateNameWithArity from ClassName

A predicate from class resolution states that the predicate is implemented by the specified class.
To resolve a predicate to a class:
l

the class must implement the predicate to be resolved, this implies that the predicate must
origin in the same interface as the one that should be inherited
the class must be mentioned in the inherits section

Predicate Rename Resolution


A predicate rename resolution states that the predicate is implemented as predicate with another
name. The predicate must come from an inherited class and its type, mode and flow must match
exactly.
PredicateRenameResolution :
PredicateNameWithArity from ClassName :: PredicateName

Interface Resolution
An interface resolution is used to resolve a complete interface from one of the inherited classes. Thus
an interface resolution is a short way of stating that all the predicates in the interface should be
resolved from the same class.
InterfaceResolution :
interface InterfaceName from ClassName

The class must publicly support the resolved interface.


If both a predicate resolution and an interface resolution cover some predicate name, then the
predicate resolution is used. I.e. the specific resolution overrides the less specific ones.
It is valid for a predicate to be covered by several interface resolutions, as long as these all resolve
the predicate to the same class. If on the other hand a predicate is resolved to different classes by
interface resolutions, then the resulting ambiguity must be resolved by a predicate resolution.

Language Reference

Page 35 / 167

Visual Prolog 7.5 - Language Reference


Note: The syntax of resolutions is not capable of resolving different overloading of a predicate to
different classes.
Example
We can solve the ambiguity from the example above by providing an interface resolution. In this case
we have chosen to inherit the implementation of aa_class from cc_class, except that we will inherit
p from bb_class
implement dd_class
inherits bb_class, cc_class
resolve
interface aa from cc_class
p from bb_class
end implement

External Resolution
A predicate externally resolution states that the predicate is not at all implemented in the class itself,
but in an external library. External resolutions can only be used for class predicates. I.e. object
predicates cannot be resolved externally.
It is important that the calling convention, link name and argument types correspond to the
implementation in the library.
Both private and public predicates can be resolved externally.
PredicateExternallyResolution : PredicateNameWithArity externally

Dynamic External Resolution


A predicate externally resolution also provide syntax for dynamic loading of private and public class
predicates from DLLs.
The syntax is:
PredicateExternallyResolutionFromDLL :
PredicateNameWithArity externally from DllNameWithPath

DllNameWithPath :
StringLiteral

If the predicate predicateNameWithArity is missed in the DLL DllNameWithPath, then the dynamic
loading provides the possibility to run a program until it actually invokes the missed predicate. The
runtime error will occur on such invocation. The DllNameWithPath is the path to the DLL on the
machine where the program should run. One can absolute or relative. For example if the required dll is
situated in the one level up from directory which the application loaded, then the DllNameWithPath
should be like "../DllName". See also Dynamic Library Search Order in MSDN.

Finalization
Language Reference

Page 36 / 167

Visual Prolog 7.5 - Language Reference


Once an object cannot be reached by the program it can be finalized, the semantics of the language
does not say exactly when the object will be finalized. The only thing that is guaranteed is that it is
not finalized as long as it can be reached from the program. In practice the object is finalized, when
it is wasted by the garbage collector. Finalization is the opposite of construction and will remove the
object from memory.
Classes can also implement a finalizer, which is a predicate that is invoked when the object is
finalized (before it is removed from memory).
A finalizer is a procedure with no arguments and no return value, which has the name finalize. The
predicate is implicitly declared and cannot be invoked directly from the program.
The main purpose of finalizers is to be able to release external resources, but there are no restrictions
on what it can do. Finalizers should however be used with caution, recall that the time of their
invocation is not completely known and, therefore, it might also be difficult to predict the overall
program state at the time where they are invoked.
Notice that there is no reason to retract object facts from an object in the finalizer, because this is
automatically done in the finalization process.
All objects are finalized before the program can terminate (unless an abnormal situation like power
failure prevents this).
Example
This example uses a finalizer to ensure that a database connection is closed properly.
implement aa_class
facts
connection : databaseConnection.
clauses
finalize() :connection:close().
...
end implement aa_class

Delegate Qualification
A delegate section contains a number of delegations:
DelegateQualification :
delegate Delegation-comma-sep-list

Delegation :
PredicateDelegation
InterfaceDelegation

The delegate qualifications are used to delegate implementations of object predicates to the specified
source.
There are two kinds of the delegate qualifications. The Predicate Delegation and the Interface
Delegation. The Interface Delegation is used to delegate implementations of a complete set of object
predicates declared in an interface to an implementation of another object, stored as fact variable.
Language Reference

Page 37 / 167

Visual Prolog 7.5 - Language Reference


Thus an interface delegation is a short way of stating that implementations of all predicates in the
interface should be delegated to an implementation of the object, stored in fact variable.
The delegate sections look like a correspondent (predicate/interface) resolve sections, except that
you delegate to fact variables keeping constructed objects of classes, rather than to inherited
classes.
Predicate Delegation
A object predicate delegation states that the predicate functionality is delegated to the predicate in
the object specified with the fact variable FactVariable_of_InterfaceType.
PredicateDelegation :
PredicateNameWithArity to FactVariable_of_InterfaceType

To delegate a predicate to an object passed with the fact variable:


l

The fact variable FactVariable_of_InterfaceType must have a type of an interface (or of its
sub-type), which declares the predicate predicateNameWithArity.
The object supporting the interface must be constructed and be assigned to the fact variable
FactVariable_of_InterfaceType.

Consider the following example:


interface a
predicates
p1 : ().
p2 : ().
end interface

interface aa
supports a
end interface

class bb_class : a
end class

class cc_class : a
end class

class dd_class : a a
constructors
new : (a First, a Second).
end class

implement dd_class
delegate p1/0 to fv1, p2/0 to fv2
facts
fv1 : a.
fv2 : a.
clauses
new(I,J):fv1 := I,
fv2 := J.
end implement

Later it will be possible to construct objects of the type a and assign them to fact variables fv1 and
fv2 to define to objects of which class we really delegate definitions of p1 and p2 functionality.
Consider, for example,
Language Reference

Page 38 / 167

Visual Prolog 7.5 - Language Reference


goal
O_bb = bb_class::n e w(),
O_cc = cc_class::n e w(),
O_dd = dd_class::n e w(O_bb, O_cc),
O_dd : p1(), % This p1 from O_bb object
O_dd : p2(). % This p2 from O_cc object

Actually in Visual Prolog delegation has the same effect as if you add clauses to the implementation
of dd_class that explicitly specify, from object of which class the predicate functionality is
"exported". That is for example, as if the following clause is determined in the implementation of
dd_class:
clauses
p1() :- fv1:p1().

Interface Delegation
When you need to specify that functionality of all predicates declared in an interface InterfaceName
are delegated to predicates from objects of the same inherited class, you can use the Interface
Delegation specification:
InterfaceDelegation :
interface InterfaceName to FactVariable_of_InterfaceType

Thus an interface delegation is a short way of stating that functionality of all predicates declared in
the interface InterfaceName should be delegated to objects stored as the fact variable
FactVariable_of_InterfaceType. Objects should be assigned to the fact variable
FactVariable_of_InterfaceType, which should be of the InterfaceName type (or its sub-type).
To delegate an interface to an object passed with the fact variable:
l

The fact variable FactVariable_of_InterfaceType must have a type of an interface


InterfaceName or of its sub-type.
The object supporting the interface must be constructed and be assigned to the fact variable
FactVariable_of_InterfaceType.

The predicate delegation has higher priority than the interface delegation. If to a predicate both
delegations are specified. That is, the predicate delegation is specified to the predicate and it is
declared in an interface, which has the interface delegation. Then the higher priority predicate
delegation will be implemented.

Language Reference

Page 39 / 167

Visual Prolog 7.5 - Language Reference


Generic Interfaces and Classes
Interfaces and classes can be parametrized with type parameters so that they can be used in
different instantiations in different contexts.
This section must be considered as an extension to the individual sections about:
l
l
l

Interfaces
Classes
Implementations

The pragmatic reason to use generic classes and interfaces is to declare parametrized object facts
and implement operations on these facts. As illustrated in the Queue example below.

Example: Queue
Consider this interface
interface queue_integer
predicates
insert : (integer Value).
tryGet : () -> integer Value.
end interface queue_integer

An object of this type is a queue of integers, if you replace "integer" with "string" you would have a
type describing queues of strings.
A generic interface can be used to describe all such interfaces in a single interface definition:
interface queue{@Elem}
predicates
insert : (@Elem Value).
tryGet : () -> @Elem Value determ.
end interface queue

@Elem is a scope type variable (distinguished from local type variables by the @).
queue{integer} represents integer-queues; queue{string} represents string-queues; and so forth.
We can declare a generic queue class like this:
class queueClass{@Elem} : queue{@Elem}
end class queueClass

queueClass{@Elem} constructs objects type queue{@Elem} for any instantiation of @Elem.


The implementation can look like this:
implement queueClass{@Elem}
facts
queue_fact : (@Elem Value).
clauses
Language Reference

Page 40 / 167

Visual Prolog 7.5 - Language Reference


insert(Value) :assert(queue_fact(Value)).
clauses
tryGet() = Value :retract(queue_fact(Value)),
!.
end implement queueClass

This piece of code illustrates how to create an integer queue and insert an element in it:
..., Q = queueClass{integer}::n e w(), Q:insert(17), ...

It is not necessary to apply the type explicitly, instead the compiler can infer it from the context:
..., Q = queueClass::n e w(), Q:insert(17), ...

The compiler sees that Q must be an integer queue, because we insert 17 into it.

Generic Interfaces
Syntax
Generic interfaces have a list of type parameters:
InterfaceDeclaration :
interface InterfaceName { ScopeTypeVariable-comma-sep-list-opt }
ScopeQualifications
Sections
end interface InterfaceName-opt

ScopeTypeVariable :
@ UppercaseName

The scope type parameters can be used in any declaration/definition in the interface.
Semantics
A generic interface defines all the interfaces that can be obtained by instantiating the type
parameters with actual types. The scope type parameters from the opening are bound in the entire
interface.
Restrictions
Then closing name should not have parameters:
interface xxx{@A}
...
end interface xxx % no parameters here

It is illegal to use same interface name for interfaces with different arity (in the same namespace):

Language Reference

Page 41 / 167

Visual Prolog 7.5 - Language Reference


interface xxx % xxx/0
...
end interface xxx

interface xxx{@A, @B} % error: Several classes, interfaces and/or namespaces have the same name 'xxx'
...
end interface xxx

Parameters can be used in supported interfaces:


interface xxx{@P} supports yyy{@P} % legal: @P is bound
...
end interface xxx

interface xxx supports yyy{@P} % illegal: @P must be bound


...
end interface xxx

Supported interfaces can be instantiated with any type expressions (as long as parameters are
bound):
interface xxx{@A} supports yyy{integer, @A*}
...

Generic Classes
Syntax
Generic classes have a list of type parameters, and constructs objects of an interface type uses the
these parameters.
ClassDeclaration :
class ClassName { ScopeTypeVariable-comma-sep-list-opt } ConstructionType
ScopeQualifications
Sections
end class ClassName-opt

ScopeTypeVariable :
@ UppercaseName

ConstructionType :
: TypeExpression

The construction type must be generic (i.e. a generic interface).


Semantics
A generic class declares a class with a generic constructor. The type of the constructed object will
be inferred from the usage of the constructor.
Restrictions
Then closing name should not have parameters:

Language Reference

Page 42 / 167

Visual Prolog 7.5 - Language Reference


class xxx{@A} : xxx{@AAA}
...
end class xxx % no parameters here

It is illegal to use same class name for class with different arity (in the same namespace):
class xxx % xxx/0
...
end class xxx

class xxx{@A} : yyy{@A} % error: Several classes, interfaces and/or namespaces have the same name 'xxx'
...
end class xxx

If a class and interface can have the same name, the class must construct objects of that interface.
interface xxx{@A}
...
end interface xxx

class xxx{@Q, @P} : object % error: Several classes, interfaces and/or namespaces have the same name 'xxx'
...
end class xxx

Parameters in the construction type, etc must be bound:


class bbb : xxx{@Q} % error: Free parameter '@Q' is used in type expression
...

All the parameters from the class must be used in the construction type:
class xxx{@P} : object % error: Unused type parameter '@P'
...

In class declarations scope parameter can only be used in constructors, domains and constants.
class xxx{@P} : xxx{@P}
domains
list = @P*. % legal
constants
empty : @P* = []. % legal
constructors
new : (@P Init). % legal
predicates
p : (@P X). % error: Scope parameter '@P' used in a class entity
end class xxx

Generic Implmentations
Syntax
Generic implementations have a list of type parameters.
Language Reference

Page 43 / 167

Visual Prolog 7.5 - Language Reference


ClassImplementation :
implement ClassName { ScopeTypeVariable-comma-sep-list-opt }
ScopeQualifications
Sections
end implement ClassName-opt

ScopeTypeVariable :
@ UppercaseName

Semantics
A generic class declares a class with a generic constructor. The type of the constructed object will
be inferred from the usage of the constructor.
Restrictions
Then closing name should not have parameters:
implement xxx{@A}
...
end implement xxx % no parameters here

The parameters must be the same as in the corresponding class declaration and have same order.
class xxx{@A} : aaa{@A}
...
end class xxx

implement xxx{@B} % error: The parameter '@B' is not the same as in the declaration '@A'
...
end implement xxx

In class implementations scope parameter can be used in constructors, domains, constants and in
object entities (i.e. object facts, object predicates and object properties).
implement xxx{@P}
domains
list = @P*. % legal
constants
empty : @P* = []. % legal
constructors
new : (@P Init). % legal
predicates
op : (@P X). % legal
class predicates
cp : (@P X). % error: Scope parameter '@P' used in a class entity
facts
ofct : (@P). % legal
class facts
cfct : (@P). % error: Scope parameter '@P' used in a class entity
...
end implement xxx

Language Reference

Page 44 / 167

Visual Prolog 7.5 - Language Reference


Monitors
A monitor is a language construction to synchronize two or more threads that use a shared resource,
usually a hardware device or a set of variables. The compiler transparently inserts locking and
unlocking code to appropriately designated procedures, instead of the programmer having to access
concurrency primitives explicitly.
Visual Prolog monitor entrances can be controlled by guard predicates (conditions).

Syntax
Monitor interfaces and monitor classes are scopes:
Scope : one of
...
MonitorInterface
MonitorClass
...

A monitor interface is defined by writing the keyword monitor in front of a regular interface
definition:
MonitorInterface :
monitor IntertfaceDefinition

A monitor class is declared by writing the keyword monitor in front of a regular class declaration:
MonitorClass :
monitor ClassDeclaration

Monitor classes and interfaces cannot declare multi and nondeterm predicate members.

Restrictions
l
l
l

A regular interface cannot support a monitor interface


A monitor class cannot construct objects.
It is not legal to inherit from a monitor (i.e. from a class that implements a monitor interface).

Semantics
The predicates and properties declared in a monitor are the entrances to the monitor. A thread
enters the monitor through an entrance and is in the monitor until it leaves that entrance again. Only
one thread is allowed to be in the monitor at the time. So each entry is protected as a critical region.
The semantics is simplest to understand as a program transformation (which is how it is
implemented). Consider this academic example:
monitor class mmmm
predicates
e1 : (a1 A1).
e2 : (a2 A2).
Language Reference

Page 45 / 167

Visual Prolog 7.5 - Language Reference


...
en : (an An).
end class mmmm

%----------------------------------------implement mmmm
clauses
e1(A1) :- <B1>.

clauses
e2(A2) :- <B2>.

...
clauses
en(An) :- <Bn>.
end implement mmmm

Where <B1>, <B2>, ..., <Bn> are clause bodies. This code corresponds to the following "normal"
code:
class mmmm
predicates
e1 : (a1 A1).
e2 : (a2 A2).
...
en : (an An).
end class mmmm

%----------------------------------------implement mmmm
class facts
monitorRegion : mutex := mutex::create(false).

clauses
e1(A1) :_ W = monitorRegion:wait(),
try
<B1>
finally
monitorRegion:release()
end try.

clauses
e2(A2) :_ W = monitorRegion:wait(),
try
<B2>
finally
monitorRegion:release()
end try.
...
clauses
en(An) :_ W = monitorRegion:wait(),
try
<Bn>
finally
monitorRegion:release()
end try.
end implement mmmm

So each monitor class is extended with a mutex, which is used to create a critical region around each
entry body.
The code for monitor objects is similar, except that the mutex object is owned by the object.
Language Reference

Page 46 / 167

Visual Prolog 7.5 - Language Reference


Guards
Consider a monitor protected queue: some threads (producers) inserts elements in the queue and
others (consumers) pick-out elements. However, you cannot pick-out elements if the queue is
empty.
If we implement the queue using a monitor, the "pick-out" entry could be determ, failing if the queue
is empty. But then the consumers would have to "poll" the queue until an element can be obtained.
Such polling uses system resources, and normally it is desirable to avoid polling. This problem can be
solved by guard predicates.
Each entry can have a guard associated in the implementation. The guard is added as a special
guard-clause before the other clauses of the entry.
Clause : one of
...
GuardClause.

GuardClause : one of
LowerCaseIdentifier guard LowerCaseIdentifier .
LowerCaseIdentifier guard AnonymousPredicate .

Example The guard can be the name of a predicate


clauses
remove guard remove_guard.
remove() = ...

Example The guard can also be an anonymous predicate


clauses
remove guard { :- element_fact(_), ! }.
remove() = ...

The guard predicates are evaluated when the monitor is created. For monitor classes this means at
program start, for object predicates this is immediately after the construction of the object. The
guard predicates are also evaluated whenever a tread leaves the monitor. But they are not evaluated
at any other time.
If a certain guard succeeds the corresponding entry is open, if it fails the entry is closed.
It is only possible to enter open entries.
Example Here is a queue class that solves the pick-out problem using a guard predicate on the
remove operation:
monitor class queue
predicates
insert : (integer Element).
Language Reference

Page 47 / 167

Visual Prolog 7.5 - Language Reference


predicates
remove : () -> integer Element.
end class queue

%----------------------------------------implement queue
class facts
element_fact : (integer Element) nondeterm.

clauses
insert(Element) :assert(element_fact(Element)).

clauses
remove guard remove_guard.
remove() = Element :retract(element_fact(Element)),
!;
exception::raise_error("The guard should have ensured that the queue is not empty").

predicates
remove_quard : () determ.
clauses
remove_guard() :element_fact(_),
!.
end implement queue

Notice that remove is a procedure, because threads that call remove will wait until there is an
element for them. The guard predicate remove_guard succeeds if there is an element in the queue.
So remove_guard is evaluated each time a thread leaves the monitor, and the element_fact fact
database can only be changed by a thread that is inside the monitor. Therefore the guard value
stays sensible all the time (i.e. when there are no threads in the monitor). It is important to ensure
such "stays sensible" condition for guards.
Guard predicates are handled in the transformation mentioned above.
Example The queue example is effectively the same as this "monitor-free" code:
class queue
predicates
insert : (integer Element).
predicates
remove : () -> integer Element.
end class queue

%----------------------------------------implement queue
class facts
monitorRegion : mutex := mutex::create(false).
remove_guard_event : event := event::create(true, toBoolean(remove_guard())).
element_fact : (integer Element) nondeterm.

clauses
insert(Element) :_ W = monitorRegion:wait(),
try
assert(element_fact(Element))
finally
setGuardEvents(),
monitorRegion:release()
end try.

clauses
Language Reference

Page 48 / 167

Visual Prolog 7.5 - Language Reference


remove() = Element :_ W = syncObject::waitAll([monitorRegion, remove_guard_event]),
try
retract(element_fact(Element)),
!;
common_exception::raise_error(common_exception::classInfo, predicate_name(),
"The guard should have ensured that the queue is not empty")
finally
setGuardEvents(),
monitorRegion:release()
end try.

class predicates
remove_guard : () determ.
clauses
remove_guard() :element_fact(_),
!.

class predicates
setGuardEvents : ().
clauses
setGuardEvents() :remove_guard_event:setSignaled(toBoolean(remove_guard())).
end implement queue

An event is created for each guard predicate; this event is set to signaled if the guard predicate
succeeds. As mentioned it is set during the creation of the monitor and each time a predicate leaves
the monitor (before it leaves the critical region).
When entering an entry the threads waits both for the monitorRegion and for the guard event to
be in signalled state.
In the code above the initialization of the class itself and the guard events are done in an
undetermined order. But actually it is ensured that the guard events are initialized after all other
class/object initialization is performed.

Examples of practical usage


This section shows a few cases where monitors are handy.
Writing to a log file
Several threads needs to log information to a single log file.
monitor class log
properties
logStream : outputStream.
predicates
write : (...).
end class log

%----------------------------------------implement log
class facts
logStream : outputStream := erroneous.
clauses
write(...) :logStream:write(time::n e w():formatShortDate(), ": "),
logStream:write(...),
logStream:nl().
end implement log
Language Reference

Page 49 / 167

Visual Prolog 7.5 - Language Reference


The monitor ensures that writing of a log lines are not mixed with each other, and that stream
changes only takes place between writing of log lines.
Shared output streams
This monitor can be used to thread protect the operations of an output stream:
monitor interface outputStream_sync
supports outputStream
end interface outputStream_sync

%----------------------------------------class outputStream_sync : outputStream_sync


constructors
new : (outputStream Stream).
end class outputStream_sync

%----------------------------------------implement outputStream_sync
delegate interface outputStream to stream

facts
stream : outputStream.

clauses
new(Stream) :- stream := Stream.
end implement outputStream_sync

You should realize however that with code like this:


clauses
write(...) :logStream:write(time::n e w():formatShortDate(), ": "),
logStream:write(...),
logStream:nl().

consists of three separate operations, so it can still be the case (fx) that two threads first write
the time and then one writes the "...", etc.
Queue
The queue above is fine, but actually it may be better to create queue objects. Using generic
interfaces we can create a very general queue:
monitor interface queue{@Elem}
predicates
enqueue : (@Elem Value).
predicates
dequeue : () -> @Elem Value.
end interface queue

%----------------------------------------class queue{@Elem} : queue{@Elem}


end class queue

%----------------------------------------implement queue{@Elem}
facts
Language Reference

Page 50 / 167

Visual Prolog 7.5 - Language Reference


value_fact : (@Elem Value).

clauses
enqueue(V) :assert(value_fact(V)).

clauses
dequeue guard { value_fact(_), ! }.
dequeue() = V :retract(value_fact(V)),
!.
dequeue() = V :common_exception::raise_error(....).
end implement queue

Notice that PFC contains a similar class monitorQueue already.

References
l

wikipedia:Monitor (synchronization)

Language Reference

Page 51 / 167

Visual Prolog 7.5 - Language Reference


Namespaces
Namespaces can be used to avoid name clashes, without having to use long strange names. The
names in two different namespaces will never clash, but it may be necessary to qualify references
with the namespace (or part of it) to resolve ambiguities.
A namespaces are declared and defined implicitly using NamespaceEntrance'es:
NamespaceEntrance:
namespace NamespaceIdentifier

NamespaceIdentifier: one of
LowercaseIdentifier
LowercaseIdentifier \ NamespaceIdentifier

In short a NamespaceIdentifier is a sequence of lowercase identifiers separated by backslashes.

Namespace Entrances and Regions


Namespace entrances divide source files into namespace regions.
A namespace entrance marks the beginning of a namespace region, which ends at the next
namespace entrance or the end of the file.
Every file starts in the root namespace.
Namespace regions are not influenced by #include directives, meaning:
l

Namespace entrances in an #include-file does not change the namespace region in the
including file
Any file starts in the root namespace (also if it is included inside a namespace region in another
file).

Any interface, class and implementation that is meet inside a namespace region belongs to that
namespace.
Example
class aaa
end class aaa

namespace xxx

class bbb
end class bbb

namespace xxx\yyy

class ccc
end class ccc

This file is divided in three regions (assuming that it is a complete file). The first region is in the root
namespace (\), the second region belongs to the xxx namespace and the third region belongs to the
Language Reference

Page 52 / 167

Visual Prolog 7.5 - Language Reference


xxx\yyy namespace.
Subsequently, the class aaa belongs to the root namespace, the class bbb belongs to the
namespace xxx and finally the class ccc belongs to the namespace xxx\yyy.

Referencing names in namespaces


If ccc is a class in the namespace xxx\yyy, then the full name of ccc is \xxx\yyy\ccc.
The leading backslash indicates that we start from the root namespace.
A class/interface can always be uniquely referenced using its full name.
Open namespaces
The full names are not always convenient and therefore it is possible to use shorter names by
opening namespaces.
ScopeQualification: one of
OpenQualification
...

OpenQualification: one of
open NamespaceIdentifier\
...

Opening a namespace is distinguished from opening a class/interface by a trailing backslash.


Example
class aaa
open xxx\yyy\
...
end class aaa

The namespace xxx\yyy is opened inside aaa.


When a namespace is open that part of a full name can be left out.
Example A domains with the full name \xxx\yyy\zzz\ccc::ddd can be as referenced zzz\ccc::ddd
inside aaa because xxx\yyy is open.
Notice that the short name does not start with a backslash; A name starting with a backslash is
always a full name.
The namespace that a certain scope (i.e. interface/class/implementation) belongs to is (implicitly)
open inside that scope.

Language Reference

Page 53 / 167

Visual Prolog 7.5 - Language Reference


Program Sections
Sections are used to declare and define entities in scopes.
Section :
ConstantsSection
DomainsSection
PredicatesSection
ConstructorsSection
PropertiesSection
FactsSection
ClausesSection
ConditionalSection

Section: ConstantsSection, DomainsSection, PredicatesSection, ConstructorsSection, FactsSection,


ClausesSection, PropertiesSection, ConditionalSection
Not all sections can occur in all kinds of scopes, please refer to the description of Interfaces, Class
Declarations, and Class Implementations for further details.
Conditional sections are described in Conditional Compilation.

Language Reference

Page 54 / 167

Visual Prolog 7.5 - Language Reference


Domains
Domains Sections
A domain section defines a set of domains in the current scope (see Interface, Class Declaration, and
Class Implementation).
DomainsSection:
domains DomainDefinition-dot-term-list-opt

Domain Definitions
A domain definition defines a named domain in the current scope.
DomainDefinition:
DomainName FormalTypeParameterList-opt = DomainExpression

If the domain on the right hand side denotes an interface or a compound domain, then the defined
domain is synonym (i.e. identical) to the type expression. Otherwise the defined domain becomes a
subtype of the domain denoted by the type expression. Here a domain name DomainName should be
a lower case identifier.
There are certain places where you must use a domain name rather than a type expression:
l
l
l

as a declaration of a formal argument type;


as a type of a constant or a fact variable;
as a type in a list domain.

Domain Expressions
A domain expression denotes a type in a domain definition:
DomainExpression:
TypeName
CompoundDomain
ListDomain
PredicateDomain
IntegralDomain
RealDomain
TypeVariable
ScopeTypeVariable
TypeApplication

Type Expressions
The full range of DomainExpressions can only be used in a domain definition. TypeExpression is a
subset of these expressions that are used in other many other contexts.
TypeExpression:
TypeName
ListDomain
TypeVariable
ScopeTypeVariable
Language Reference

Page 55 / 167

Visual Prolog 7.5 - Language Reference


TypeApplication

Type Names
A type name is either an interface name or the name of a value domain. We use the term value
domain to specify domains whose elements are immutable (unchangeable). Here we can say that
objects, belonging to domains correspondent to interface names, have mutable state and terms of
any other domains are immutable. So actually value types are everything except object types. A type
name (obviously) denotes the type corresponding to the name of an existing domain.
TypeName:
InterfaceName
DomainName
ClassQualifiedDomainName

InterfaceName:
LowercaseIdentifier

DomainName:
LowercaseIdentifier

ClassQualifiedDomainName:
ClassName::DomainName

ClassName:
LowercaseIdentifier

Here InterfaceName is an interface name, DomainName is a value domain name, and ClassName
is a class name.
Example
domains
newDomain1 = existingDomain.
newDomain2 = myInterface.

In this example the domain name existingDomain and the interface name myInterface are used to
define new domains.
Compound Domains
Compound domains (also known as algebraic data types) are used to represent lists, trees, and other
tree structured values. In its simple forms compound domains are used to represent structures and
enumeration values. Compound domains can have a recursive definition. They can also be
mutually/indirectly recursive.
CompoundDomain:
Alignment-opt FunctorAlternative-semicolon-sep-list
Language Reference

Page 56 / 167

Visual Prolog 7.5 - Language Reference

Alignment:
align IntegralConstantExpression

Here IntegralConstantExpression is an expression, which must be compile time evaluated to an


integral value.
A compound domain declaration declares a list of functor alternatives with optional alignment.
Alignment must be 1, 2 or 4.
If a compound domain consists of one functor alternative, then it is considered as structure and has
representation, which is binary compatible with the appropriate structure in language C.
FunctorAlternative:
FunctorName FunctorName ( FormalArgument-comma-sep-list-opt )

Here FunctorName is the name of a functor alternative it should be a lower case identifier.
FormalArgument:
TypeExpression ArgumentName-opt

Here ArgumentName can be any upper case identifier. The compiler ignores it.
Compound domains have no subtype relations to any other domains.
If a domain is defined as being equal to a compound domain, then these two domains are synonym
types rather than subtypes. Meaning that they are just two different names for the same type.
Example
domains
t1 = ff(); gg(integer, t1).

t1 is a compound domain with two alternatives. The first alternative is the null-ary functor ff, while
the second alternative is the two-ary functor gg, which takes an integer and a term of the domain t1
itself as arguments. So the domain t1 is recursively defined.
The following expressions are terms of the domain t1:
ff()
gg(77, ff())
gg(33, gg(44, gg(55, ff())))

Example
domains
t1 = ff(); gg(t2).
t2 = hh(t1, t1).

Language Reference

Page 57 / 167

Visual Prolog 7.5 - Language Reference


t1 is a compound domain with two alternatives. The first alternative is the null-ary functor ff, while
the second alternative is the unary functor gg, which takes a term of the domain t2 as argument. t2
is a compound domain with one alternative the functor hh, which takes two t1 terms as argument.
So the domains t1 and t2 are mutually recursive.
The following are terms in the domain t1:
ff()
gg(hh(ff(), ff()))
gg(hh(gg(hh(ff(), ff())), ff()))
ggg(hh(ff(), g(hh(ff(), ff()))))
gg(hh(gg(hh(ff(), ff())), gg(hh(ff(), ff()))))

Example
In this example t1 and t2 are synonym types.
domains
t1 = f(); g(integer).
t2 = t1.

Normally, it is not necessary to use empty parenthesis after null-ary functors. But in a domain
definition consisting only of a single null-ary functor, empty parenthesis are required to distinguish it
from a synonym/subtype definition.
Example
t1 is a compound domain with a single null-ary functor, whereas t2 is defined to be synonym to t1.
domains
t1 = f().
t2 = t1.

List Domains
List domains represent sequences of values of a certain domain. Thus, all elements in a T list must be
of type T.
ListDomain:
TypeExpression *

T* is the type of lists of T elements.


The following syntax is used for lists:
ListExpression:
[ Term-comma-sep-list-opt ]
[ Term-comma-sep-list | Tail ]

Tail:
Language Reference

Page 58 / 167

Visual Prolog 7.5 - Language Reference


Term

Here Tail is a term which should have a value of the ListDomain type. Each Term should be of
typeName type.
Actually, lists are just compound domains with two functors: [] denoting the empty list and the mixfix functor [HD|TL] denoting the list with head HD and tail TL. The head must be of the underlying
element type, whereas the tail must be a list of relevant type.
Lists are however syntactically sugared.
[E1, E2, E3, ..., En | L ] is shorthand for [E1 |[ E2 |[ ...[ En | L ]...}}]
[E1, E2, E3, ..., En] is shorthand for [E1, E2, E3, ..., En |[}}, which in turn is shorthand for [E1 |
[ E2 |[ ...[ En | [] ]...}}]
Predicate Domains
Values of a predicate domain are predicates with the same "signature", i.e. the same argument and
return types, the same flow pattern and the same (or stronger) predicate mode.
A predicate that returns a value is called a function, whereas a predicate that does not return a
value is sometimes called an ordinary predicate, to stress that it is not a function.
PredicateDomain:
( FormalArgument-comma-sep-list-opt ) ReturnArgument-opt
PredicateModeAndFlow-list-opt CallingConvention-opt

FormalArgument:
TypeExpression VariableName-opt
Ellipsis

ReturnArgument:
-> FormalArgument

VariableName:
UpperCaseIdentifier

Predicate domains can have Ellipsis argument as the last FormalArgument in the
FormalArgument-comma-sep-list.
Predicate domains can have AnonymousIdentifier as a predicateArgumentType to specify that the
argument can be of any type.
Currently, predicate domains with ellipsis can only be used in predicate declarations.
Predicate domains that are used in domain definitions can at most state one flow.
PredicateModeAndFlow:
PredicateMode-opt
Language Reference

Page 59 / 167

Visual Prolog 7.5 - Language Reference


FlowPattern-list-opt

Predicate Mode
The specified predicate mode applies for each member of a flow pattern list following it.
PredicateMode: one of
erroneous
failure
procedure
determ
multi
nondeterm

Predicate modes can be described by the following sets:


erroneous = {}
failure = {Fail}
procedure = {Succeed}
determ = {Fail, Succeed}
multi = {Succeed, BacktrackPoint}
nondeterm = {Fail, Succeed, BacktrackPoint}

If Fail is in the set it means that the predicate can fail. If succeed is in the set it means that the
predicate can succeed. If BacktrackPoint is in the set it means that the predicate can return with an
active backtrack point in it.
If such a set, say failure, is a subset of another set, say nondeterm, then we say that the mode is
stronger than the other, i.e. failure is stronger than nondeterm.

A predicate domain actually contain all predicates (with correct type and flow), which have the mode
specified or a stronger mode.
It is illegal to state a predicate mode for constructors, they always have the procedure mode.
Omitting of a predicate mode means procedure.
Flow Pattern
The flow pattern defines the input/output direction of the arguments, which in combination with
functor domains can be structures with parts of a single argument being input and other parts of the
same argument being output.
A flow pattern consists of a sequence of flows, each flow corresponds to an argument (fist flow to
first argument, etc).
FlowPattern:
( Flow-comma-sep-list-opt ) AnyFlow

Flow: one of
i
Language Reference

Page 60 / 167

Visual Prolog 7.5 - Language Reference


o
FunctorFlow
ListFlow
Ellipsis

Ellipsis flow must match an ellipsis argument and can therefore be only the last flow in the flow
pattern.
Ellipsis:
...

A functor flow FunctorFlow states a functor and flows of each of the components of that flow. The
functor must of course be in the domain of the corresponding argument.
FunctorFlow:
FunctorName ( Flow-comma-sep-list-opt )

A functor flow declaration cannot contain ellipsis flow.


List flows are just like functor flows, but with the same syntactic sugaring as the list domain.
ListFlow:
[ Flow-comma-sep-list-opt ListFlowTail-opt]

ListFlowTail:
| Flow

A list flow cannot contain ellipsis flow.


When declaring a predicate the flow can be omitted. Inside an implementation (i.e. for a local
predicate) the needed flows are derived from the usages of the predicate. Inside an interface or a
class declaration (i.e. for a public predicate) omitting flows means that all arguments are input.
The special flow pattern anyflow can be stated only in declarations of local predicates (i.e. in
predicate declarations inside the implementation of a class). It means that the exact flow pattern(s)
will be evaluated during the compilation.
Example
domains
pp1 = (integer Argument1).

pp1 is a predicate domain. The predicates that have type pp1 takes one integer argument. Since no
flow-pattern is stated the argument is input, and since no predicate mode is mentioned the
predicates are procedure.
Example
domains
Language Reference

Page 61 / 167

Visual Prolog 7.5 - Language Reference


pp2 = (integer Argument1) -> integer ReturnType.

Predicates of type pp2 take one integer argument and returns a value of type integer. Therefore,
pp2 is actually a function domain and the predicates that have type pp2 are actually functions.
Since no flow-pattern is stated the argument is input and since no predicate mode is mentioned the
predicates are procedure.
Example
predicates
ppp : (integer Argument1, integer Argument2) determ (o,i) (i,o) nondeterm (o,o).

The predicate ppp takes two integer arguments. It exists in three flow variants: (o,i) and (i,o),
which are determ, and (o,o), which is nondeterm.
Calling Convention
The calling convention determines how arguments, etc. are passed to the predicate, it also
determines how the link name is derived from a predicate name.
CallingConvention:
language CallingConventionKind

CallingConventionKind: one of
c thiscall stdcall apicall prolog

If a calling convention is not stated, then the prolog convention is assumed. The prolog calling
convention is the standard convention used for Prolog predicates.
The calling convention c follows the C/C++ standard calling convention. The link name of a predicate
is created from the predicate name by adding a leading underscore (_).
The calling convention thiscall follows the C++ standard calling convention for virtual functions. This
calling convention uses the c link name strategy but sometimes it may use the different argument and
stack handling rules. Calling convention thiscall can be applied to the object predicates only.
The calling convention stdcall uses the c link name strategy but it uses the different argument and
stack handling rules. The following table shows the implementation of stdcall calling convention:
Feature

Implementation

Argument-passing
order

Right to left.

Argument-passing
convention

By value, unless a compound domain term is passed. So it cannot be used


to predicates with variable number of arguments.

Stack-maintenance
responsibility

Called predicate pops its own arguments from the stack.

Name-decoration
convention

An underscore (_) is prefixed to the predicate name.

Language Reference

Page 62 / 167

Visual Prolog 7.5 - Language Reference


Case-translation
convention

No case translation of the predicate name is performed.

The calling convention apicall uses the same argument and stack handling rules as stdcall, but for
convenience to call MS Windows API functions apicall uses the naming conventions that are used by
most MS Windows API functions. According to apicall naming conventions the link name of a
predicate is constructed as follows:
l
l
l

l
l

an leading underscore (_) is prefixed to the predicate name;


the predicate name in which the first letter is changed in to a capital letter;
the 'A', the 'W' or nothing is suffixed, if the arguments and the return type indicate an ANSI,
Unicode or neutral predicate, respectively;
the '@' is suffixed;
the number of bytes pushed on the call stack is suffixed.

Example
predicates
predicateName : (integer, string) language apicall

The argument types of this predicate indicates that it is a Unicode predicate (as string is the domain
of Unicode strings). An integer and a string each occupies 4 bytes on the call stack and, therefore,
the link name becomes:

_PredicateNameW@8

If apicall is used together with the "as" construction the name stated in the "as" construction is
decorated in the same manner.
apicall can only be used directly in a predicate declaration, not in a predicate domain definition. In
predicate domain definitions stdcall, must be used instead. A predicate declared with apicall calling
convention cannot have clauses and it also cannot be resolved externally without explicit DLL name.
The following table compares implementations of c, apicall, and stdcall calling conventions (the
prolog calling convention has the special implementation, which is not discussed here):

Keyword

Stack cleanup

Predicate name
case-translation

Link predicate name decoration


convention

Calling predicate pops


the arguments from the
stack.

None.

An underscore (_) is prefixed to the


predicate name.

thiscall

Calling predicate pops


the arguments from the
stack except the implicit
This argument which is
passed in the register.

None.

c link name strategy is used.

stdcall

Called predicate pops its


own arguments from the None.
stack.

An underscore (_) is prefixed to the


predicate name.
An underscore (_) is prefixed to the

Language Reference

Page 63 / 167

Visual Prolog 7.5 - Language Reference


apicall

The first letter of


Called predicate pops its
the predicate name
own arguments from the
is changed to the
stack.
capital letter.

name. The first letter is changed to the


upper case. The 'A', the 'W' or nothing
is suffixed. The sign @ is suffixed. The
(decimal) number of bytes in the
argument list is suffixed.

Visual Prolog notion of predicate domains covers both class and object members. Class members are
handled straight forward, but the handling of object members requires attention. The invocation of an
object predicate will get "back" in the context of the object to which the member belongs.
Example Assume the following declarations:
interface actionEventSource
domains
actionListener = (actionEventSource Source) procedure (i).
predicates
addActionListener : (actionListener Listener) procedure (i).
... end interface

Also assume a class button_class which supports the actionEventSource. The event is sent when
the button is pressed. In myDialog_class class, which implements a dialog, I create a button and I
want to listen to its action events, so that I can react on button presses:
implement myDialog_class
clauses
new() :OkButton = button_class::n e w(...),
OkButton:addActionListener(onOk),
...
facts
okPressed : () determ.
predicates
onOk : actionListener.
clauses
onOk(Source) :assert(okPressed()).
end implement

The important thing about the example is that onOk is an object member and that, when the button
is pressed, the invocation of the registered onOk will bring us back in the object that owns onOk.
This means that we have access to the object fact okPressed, so that we can assert it.
Format Strings
A formal parameter to a predicate can be marked as format string using the attribute formatString.
The format string can contain ordinary characters which are printed without modification, and format
fields,that%beginswiththepercent'%'sign.Ifthepercentsignisfollowed%bysomeunknown
character (not the format specifier) -then%thischaracterwill be printed without modifications.
predicates
writef : (string Format [formatstring], ...).

The format fields specification is:


[-][0][width][.precision][type]
Language Reference

Page 64 / 167

Visual Prolog 7.5 - Language Reference


All fields are optional.
[-] Hyphen indicates that the field is to be left justified; right justified is the default. Having no effect
when width value is not set, or the number of characters in the actual value is greater than width
value.
[0] Zero before width means for values that zeros will be added until the minimum width is reached. If
0(zero) and -(hyphen) appear, the 0 is ignored
[width] Positive decimal number specifying a minimum field size. If the number of characters in the
actual value is less than width value - then the required number of space ' ' characters will be added
before the value (or after it, if '-' field was set). No changes occurs if number of characters in the
actual value is greater than the width value.
[.precision] The point '.' with the following unsigned decimal number can specify either the precision
of a floating-point image or the maximum number of characters to be printed from a string.
[type] Specifies other format then the default for the given. For example, in the type field, you can
give a specifier that says an integer will be formatted as an unsigned. The possible values are:

Format real's in fixed-decimal notation (such as 123.4 or 0.004321). This is the default
for real's.

Format real's in exponential notation (such as 1.234e+002 or 4.321e-003).

Format real's in the shortest of f and e format, but always in e format if exponent of
the value is less than -4 or greater than or equal to the precision. Trailing zeros are
truncated.

d or
Format as a signed decimal number.
D
u or
Format as an unsigned integer.
U
x or
Format as a hexadecimal number.
X
o or
Format as an octal number.
O
c

Format as a char.

Format as the Visual Prolog binary type.

Format as a database reference number.

Format as a procedure parameter.

Format as a string.

Integral Domains
Integral domains are used for representing integral numbers. They are divided in two main categories
for signed and unsigned numbers. Integral domains can also have different representation size. The
predefined domains integer and unsigned represent signed and unsigned numbers with natural
representation length for the processor architecture (i.e. 32bit on a 32bit machine, etc).
IntegralDomain:
DomainName-opt IntegralDomainProperties
Language Reference

Page 65 / 167

Visual Prolog 7.5 - Language Reference


If a DomainName is stated in front of the IntegralDomainProperties, then this domain must itself
be an integral domain and the resulting domain will be child-type (i.e. subtype) of this domain. In that
case IntegralDomainProperties may not violate the possibility of being a subtype, i.e. the range
cannot be extended and the size cannot be changed.
IntegralDomainProperties:
IntegralSizeDescription IntegralRangeDescription-opt
IntegralRangeDescription IntegralSizeDescription-opt

IntegralSizeDescription:
bitsize DomainSize

DomainSize:
IntegralConstantExpression

An integral size description declares the size DomainSize of the integral domain, measured in bits.
The compiler implement such representation to the integral domain, which has no less than the
specified number of bits. The value of DomainSize should be positive and no greater than the
maximal value supported by the compiler.
If integral size description is omitted, then it will become the same as the parent domain. If there is
no parent domain, it will become the natural size for the processor.
IntegralRangeDescription:
[ MinimalBoundary-opt .. MaximalBoundary-opt ]

MinimalBoundary:
IntegralConstantExpression

MaximalBoundary:
IntegralConstantExpression

An integral range description declares the minimal MinimalBoundary and the maximal
MaximalBoundary limits for the integral domain. If a limit is omitted, then the range of the parent
domain is used. If there is no parent domain, then the DomainSize is used to determine respectively
maximum or minimum value.
Notice that the specified minimum value should not exceed the specified maximum value. That is:
MinimalBoundary <= MaximalBoundary

Also the minimal MinimalBoundary and the maximal MaximalBoundary limits should satisfy the
limits implied by the specified bit size bitsize.
The domain bit size DomainSize value and values of the minimal MinimalBoundary and the maximal
MaximalBoundary limits must be calculated while compiling time.
Real Domains
Real domains are used to represent numbers with fractional parts (i.e. floating point numbers). Real
domains can be used to represent very large and very small numbers. The built-in domain real have
the natural precision for the processor architecture (or the precision given by the compiler).

Language Reference

Page 66 / 167

Visual Prolog 7.5 - Language Reference


RealDomain:
DomainName-opt RealDomainProperties

If a DomainName is stated in front of the RealDomainProperties, then this domain must itself be
a real domain and the resulting domain will be a subtype of this domain. In that case
RealDomainProperties may not violate the possibility of being a subtype, i.e. the range cannot be
extended and the precision cannot be increased.
RealDomainProperties: one of
RealPrecisionDescription RealRangeDescription-opt
RealRangeDescription RealPrecisionDescription

RealPrecisionDescription:
digits IntegralConstantExpression

The real precision description declares precision of the real domain, measured in number of decimal
digits. If precision is omitted then it will become the same as for the parent domain. If there is no
parent domain, then it will be the natural precision for the processor or given by the compiler (in
Visual Prolog v.6 the compiler limit is 15 digits). Precision have an upper and a lower limits given by
the compiler, if the precisions larger than that limit is used the numbers will only obtain the processor
(compiler) specified precision anyway.
RealRangeDescription:
[ MinimalRealBoundary-opt .. MaximalRealBoundary-opt ]

MinimalRealBoundary:
RealConstantExpression

MaximalRealBoundary:
RealConstantExpression

Here RealConstantExpression is an expression, which must be compile time evaluated to a floating


point value. That is the real domain precision and limits must be calculated while compiling time.
The real range description declares minimal and maximal limits for the real domain. If a limit is omitted
then it will be the same as for the parent domain. If there is no parent domain then the largest
possible range for the precision will be used.
Notice that the specified minimum value should not exceed the specified maximum value. That is:
MinimalBoundary <= MaximalBoundary

Generic Domains
This section contains the formal syntax for generic domains, for a more complete introduction to
generics please see the section Generics.
FormalTypeParameterList:
TypeVariable-comma-sep-list-opt

Language Reference

Page 67 / 167

Visual Prolog 7.5 - Language Reference


A formalTypeParameterList is a list of typeVariables
TypeVariable:
UpperCaseIdentifier

A TypeVariable is an upper case identifier. In a domain declaration the type variable must be bound
in the FormalTypeParameterList on the left hand side of the domain definition. In a predicate
declaration all free type variables are implicitly bound and scoped to that predicate declaration.
TypeApplication:
TypeName {TypeExpression-comma-sep-list-opt }

A TypeApplication is the application of a typeName to a list of types. The type name must be
generic and the number of formal type parameters must match the number of type expressions.

Universal and Root Types


Visual Prolog uses some internal types, called root types and universal types.
Universal Types
A number literal like 1 does not have any particular type, it can be used as a value of any type that
contains 1, including real types.
We say that 1 have a universal type. Having a universal type means that it have any type, which
can represent its value.
Arithmetic operations also return universal types.
Root Types
Arithmetic operations are very liberal with their operand requirements: You can add integers of any
integer domain with each other.
We say that arithmetic operands takes root types as arguments. The integer root type is super-type
of any integer type (regardless that it is not mentioned in their declarations). Hence any integer type
can be converted to the integer root type, and, since the arithmetic operations exist for the root
types, it means one of them will work on any integer domains.
The actual number of root types and which operands exist is a matter of library facilities, and outside
the scope of this document to describe.

Language Reference

Page 68 / 167

Visual Prolog 7.5 - Language Reference


Constants
Constants Sections
A constants section defines a set of constants in the current scope.
ConstantsSection :
constants ConstantDefinition-dot-term-list-opt

Constant Definitions
A constant definition defines a named constant, its type, and its value.
ConstantDefinition: one of
ConstantName = ConstantValue
ConstantName : TypeName = ConstantValue

ConstantName:
LowerCaseIdentifier

The ConstantValue should be an expression, which can be evaluated at compile time and it should
have the type of the correspondent domain. The ConstantName should be a lower case identifier.
The TypeName can be omitted only for the following built-in domains:
1. Numerical (i.e. integral or real) constants. In this case, the corresponding anonymous numerical
domain is adopted for a constant (see the numerical domains for details).
2. Binary constants.
3. String constants.
4. Character constants.
Example
constants
my_char = 'a'.
true_const : boolean = true.
binaryFileName = "mybin".
myBinary = #bininclude(binaryFileName).

Language Reference

Page 69 / 167

Visual Prolog 7.5 - Language Reference


Predicates
Predicates Sections
A predicates section declares a set of object or class predicates in the current scope.
PredicatesSection :
class-opt predicates PredicateDeclaration-dot-term-list-opt

The keyword class can be used only inside class implementations, since:
l
l

predicates declared in an interface are always object predicates and


predicates declared in a class declaration are always class predicates.

Predicate Declarations
The predicate declaration is used to declare the predicate in scopes in which the predicate
declaration can be seen. When predicates are declared in an interface definition, this means that
objects of the corresponding type must support these predicates. When predicates are declared in a
class declaration, this means that the class publicly provides the declared predicates. And if
predicates are declared in a class implementation, this means that the predicates are available
locally. In all cases a corresponding definitions of the predicates must exist.
PredicateDeclaration :
PredicateName : PredicateDomain LinkName-opt
PredicateName : PredicateDomainName LinkName-opt

LinkName :
a s StringLiteral

PredicateName :
LowerCaseIdentifier

Here predicateDomainName is the name of a predicate domain declared in the domains section.
A predicate declaration states the name of the predicate, its type, mode, flow (see predicate
domains), and optionally a link name.
Only class predicates can have link names. If the link name is not stated then a link name is derived
from the predicate name, the way this name is derived depends on the calling convention.
If the calling convention is apicall then the link name stated in the as clause is decorated anyway. If
this decoration is unintended, use stdcall instead.
Decorated
Sometimes a name must have the _...@N decoration, but the default from apicall is wrong. In such
cases decorated, decoratedA and decoratedW can be used to control the decoration:

Language Reference

Page 70 / 167

Visual Prolog 7.5 - Language Reference


predicates
myPredicate : (string X) language stdcall a s decorated.

In this case the link name will be "_MyPredicate@4", where apicall would make it
"_MyPredicateW@4".

predicates
myPredicate : (pointer X) language stdcall a s decoratedA.

In this case the link name will be "_MyPredicateA@4", where apicall would make it
"_MyPredicate@4".

predicates
myPredicate : (pointer X) language stdcall a s decoratedW.

In this case the link name will be "_MyPredicateW@4", where apicall would make it
"_MyPredicate@4".
All of them change the start of the name from xxxx to _Xxxx and all of them put @N behind. The first
never uses a suffix; the second always uses A and the third always uses W. This means that the
programmer is responsible for deciding which suffix is needed. But he needs not to worry about
calculating argument size and initial "_X".

Constructors Sections
A constructors section declares a set of constructors. The constructors belong to the scope in
which the constructors section occurs (see class declaration and class implementation).
ConstructorsSection :
constructors ConstructorDeclaration-dot-term-list-opt

Constructor sections can only occur in declarations and implementations of classes that construct
objects.

Constructor Declarations
A constructor declaration declares a named constructor of a class.
A constructor actually has two associated predicates:
l
l

A class function, which returns a new constructed object.


An object predicate, which is used when initializing inherited objects.

An associated constructor object predicate is used to perform an object initialization. This predicate
can only be called from the constructor in the class itself and from a constructor in a class that
inherits from the class (i.e. base class initialization).
ConstructorDeclaration :
Language Reference

Page 71 / 167

Visual Prolog 7.5 - Language Reference


ConstructorName : PredicateDomain

It is illegal to state a predicate mode for constructors, constructors always have procedure mode.
Example Consider the following class:
class test_class : test
constructors
new : (integer Argument).
end class test_class

The associated class level predicate has the following signature:


class predicates
new : (integer) -> test.

Whereas the associated object level predicate has the following signature:
predicates
new : (integer).

Also consider the following implementation:


implement test2_class inherits test_class
clauses
new() :test_class::n e w(7), % invoke the base class constructor on "This"
p(test_class::n e w(8)). % create a new object of the base class and pass it to p(...)
...

The first call to test_class::new does not return a value, therefore it is a call to the non-function
object version of the constructor. I.e. it is an invocation of the base class constructor on "This".
The second call on the other hand does return a value, therefore it is a call to the class function
version of the constructor. I.e. we are creating a new object.

Predicates from Interface


An interface can support a subset of another interface by stating the predicates in a predicates from
section. The predicates from section names the interface and all supported predicates. The
predicates are stated by name or by name and arity.
If an interface supports a subset of another interface it is neither subtype or super-type related to
the other interface.
The important thing about the predicates from section is that the mentioned predicates retain their
origin interface. Therefore:
l
l

there will be no support conflict with any predicates from the origin interface;
they can be inherited as the predicates from the origin interface.

Language Reference

Page 72 / 167

Visual Prolog 7.5 - Language Reference

PredicatesFromInterface :
predicates from InterfaceName PredicateNameWithArity-comma-sep-list-opt

PredicatesFromInterface can only be used in interface definitions.


Example
interface aaa
predicates
ppp : ().
qqq : ().
end interface aaa

interface bbb
predicates from aaa
ppp
predicates
rrr : ().
end interface bbb

interface ccc supports aaa, bbb


end interface ccc

Even though aaa and bbb both declare a predicate ppp, ccc can support them both without any
conflicts, because ppp has aaa as an origin interface in all cases.
Example
interface aaa
predicates
ppp : ().
qqq : ().
end interface aaa

interface bbb
predicates from aaa
ppp
predicates
rrr : ().
end interface bbb

class aaa_class : aaa


end class aaa_class

class bbb_class : bbb


end class bbb_class

implement aaa_class inherits bbb_class


clauses
qqq().
end implement aaa_class

aaa_class can inherit ppp from bbb_class, because ppp in both classes has aaa as origin
interface.

Arity
A predicate that takes N arguments are said to be N-ary, or to have arity N. Predicates with different
Language Reference

Page 73 / 167

Visual Prolog 7.5 - Language Reference


arity are always different predicates, even if they have the same name.
In most situations the arity of a predicate is obvious from the context in which the predicate is
mentioned. But in, for example, predicatesFromInterface sections and resolve qualifications the arity
is not obvious.
In order to distinguish between different arities of predicates in predicates from sections and in
resolve qualifications, predicate names can (optionally) be stated with arity.
The following arities are possible:
l
l
l

Name/N meaning an ordinary predicate (i.e. not a function) Name of arity N.


Name/N-> meaning a function Name of arity N.
Name/N... meaning an ordinary predicate Name with N arguments followed by an Ellipsis
argument (i.e. a varying number of arguments). (Ellipsis "..." can be used in predicate and
predicate domain declarations as the last formal argument. In this case it means that the
declared predicate (predicate domain) can have a variable number of arguments. Ellipsis flow
must match an ellipsis argument and can therefore be only the last flow in the flow pattern.)
Name/N...-> meaning a function Name with N arguments followed by an ellipsis argument.
PredicateNameWithArity :
PredicateName Arity-opt

Arity : one of
/ IntegerLiteral Ellipsis-opt
/ IntegerLiteral Ellipsis-opt ->

In Name/0... and Name/0...->. the zero is optional and can thus be written as Name/... and
Name/...->, respectively.

programPoint
A programPoint is a value that represents a specific point in a clause. The programPoint contains
the class name, the predicate name, the line number and position on the line. The programPoint
domain is defined in the core class
programPoint's are used by the exception mechanism to indicate where exceptions are raised and
continued, but the usage is not limited to that purpose.
The compiler suppors programPoint's in a special way by means of the attribute programPoint,
which can be added to a predicate declaration like this:
predicates
raiseAnException : (integer X) [programPoint].

Adding this attribute actually means that two predicates are declared, the one you have mentioned
and an another one with name raiseAnException_explicit which in addition to the arguemnts of
raiseAnException takes a programPoint as first argument:
predicates
raiseAnException : (integer X).

Language Reference

Page 74 / 167

Visual Prolog 7.5 - Language Reference


predicates
raiseAnException_explicit : (programPoint ProgramPoint, integer X).

When you call raiseAnException the compiler will actually create a program point ans call
raiseAnException_explicit instead.
Example
clauses
test() :raiseAnException(17).

will actually correspond to:


clauses
test() :raiseAnException_explicit(programPoint(...), 17).

where the program point corresponds to the point where raiseAnException is called in the test
predicate.
If you have a programPoint you can directly call the explicit predicate with it.
Example
clauses
raiseAnExceptio17_explicit(ProgramPoint) :raiseAnException_explicit(ProgramPoint, 17).

Typically, as in this example, explicit predicates will call other explicit predicates with the
programPoint they receive in order to use an "original" call point in a nested explicit predicate.
Such code is treated in the usual way. I.e. when calling raiseAnException or
raiseAnException_explicit will in both cases result in calling raiseAnException_explicit, so this is
the only predicate that needs an implementation. In fact, it is illegal to state clauses for the nonexplicit predicate that will never be called.
There is also a built-in predicate, programPoint/0->, which returns a programPoint corresponding
to the place where it is called.
To summarize:
l

A predicate declaration with programPoint attribute actually declares two predicates. A nonexplicit and an explicit predicate.
Calling the non-explicite predicate actually results in calling the explicit predicate with the call
point as aditina argument.
Only the explicit predicate should be implemented.

The introduction of the the programPoint feature simplifies the exception mechanism as known in
Visual Prolog 7.3 and before. For example classInfo predicates are no longer needed (though they in
Visual Prolog 7.4 are still legal but deprecated to ease transition).
Language Reference

Page 75 / 167

Visual Prolog 7.5 - Language Reference

Language Reference

Page 76 / 167

Visual Prolog 7.5 - Language Reference


Properties
Properties are named values associated with classes and objects. Actually they are syntactic sugar
for get/set predicates for the property value. And in that sense they are a language incarnation of a
frequently used programming pattern.

Properties Sections
A properties section declares a set of object or class properties in the current scope.
PropertiesSection :
class-opt properties PropertyDeclaration-dot-term-list-opt

The keyword class can be used only inside class implementations, since:
l
l

properties declared in an interface are always object properties and


properties declared in a class declaration are always class properties.

Property Declaration
PropertyDeclaration :
PropertyName : PropertyType FlowPattern-list-opt

FlowPattern: one of
(i)
(o)

It is possible to get the value of a property that has the (o) flow, and it is possible to set the value
of a property that has the (i) flow. If the flow patterns are not stated, both (i) and (o) are assumed,
so it is possible bot to set and get the value of such properties.
Though it is legal to state (i) and (o) simultaneously, it is considered better practice to omit them in
the get+set case.
Example Assume we declare them with an i/o pattern as:
properties
durationO : real (o). % a get only property
durationI : real (i). % a set only property
durationIO : real (i) (o). % a "full" property, which can both be set and get.
duration : real. % equivalent to the declaration above and preferred.

In the sequel we will use the use the following example:


Example
interface ip
properties
duration : real.
initialized : boolean (o).
scale : real.
Language Reference

Page 77 / 167

Visual Prolog 7.5 - Language Reference


end interface

duration and scale are get+set properties, and initialized is a get-only property.
Properties are used like fact variables. It is possible to qualify properties for with a scope name or an
object.
Example X is an object that supports the interface ip
X:duration := 5,
if true = X:initialized then ... else ... end if,
X:scale := 2.56,
....

Inside an implementation of a class that supports ip you access the properties as if they were facts.
duration := 5,
if true = initialized then ... else ... end if,
scale := 2.56,
....

Implementation
A property is implemented by defining a function for getting the value and a predicate to set it.
Example
clauses
% implementation of the get function of the duration property
duration() = duration_fact.

clauses
% implementation of the set predicate of the duration property
duration(D) :duration_fact := D / scale.

Alternatively the property can be implemented as a fact variable with the same name as the
property.
Example
facts
% the initialized property is implemented by a fact variable
initialized : boolean := false.
% the scale property is implemented by a fact variable
scale : real := 1.2

In this case the compiler will implicitly provide clauses that implement the get and set predicates.
Example For the two fact variable implementations above the compiler will provide clauses
corresponding to this

Language Reference

Page 78 / 167

Visual Prolog 7.5 - Language Reference


clauses
% implicit get clause for the initialized property
initialized() = initialized.

clauses
% implicit get clause for the scale property
scale() = scale.

clauses
% implicit get clause for the scale property
scale(V) :scale := V.

As mentioned below it would not be legal to state these clauses in a program.


It is illegal to have set and get predicates and a fact with the same name, meaning that a property is
either implemented by programmer provided clauses or by a fact; mixed implementation is not
possible.
Example We want to send a changed event when the duration property changes value. Therefore
we have to implement the property by predicates, and use a fact variable with an other name for
storing the value.
properties
duration : integer.
facts
duration_fact : integer.
clauses
duration() = duration_fact.
clauses
duration(D) :OldDuration = duration_fact,
duration_fact := D,
OldDuration <> D,
!,
sendChanged().
duration(_D).

It is not possible to use the duration predicates as predicates (they are not declared as predicates,
but as a property; it is just the way the get and set of the property are implemented).
But in the predicate names are "used" - so you cannot declare predicates duration\1 or
duration\0->.
As mentioned above properties are always implemented by get/set predicates even when the program
implement them by a fact variable.

Properties from Interface


An interface can support a subset of another interface by stating the properties in a properties from
section. The properties from section names the interface and all supported properties.
If an interface supports a subset of another interface it is neither subtype or super-type related to
the other interface.
The important thing about the properties from section is that the mentioned properties retain their
origin interface. Therefore:
Language Reference

Page 79 / 167

Visual Prolog 7.5 - Language Reference


l
l

there will be no support conflict with any properties from the origin interface;
they can be inherited as the properties from the origin interface.
PropertiesFromInterface :
properties from InterfaceName PpropertyName-comma-sep-list-opt

PropertiesFromInterface can only be used in interface definitions.


Example
interface aaa
properties
pp : integer.
qq : boolean.
end interface aaa

interface bbb
properties from aaa
pp
properties
rr : string.
end interface bbb

interface ccc supports aaa, bbb


end interface ccc

Even though aaa and bbb both declare a property pp, ccc can support them both without any
conflicts, because pp has aaa as an origin interface in all cases.
Example
interface aaa
properties
pp : integer.
qq : boolean.
end interface aaa

interface bbb
properties from aaa
pp
properties
rr : string.
end interface bbb

class aaa_class : aaa


end class aaa_class

class bbb_class : bbb


end class bbb_class

implement aaa_class inherits bbb_class


facts
pp_fact(): integer.
clauses
pp()= pp_fact-3.
clauses
pp(D):- pp_fact:=D+3.
end implement aaa_class

aaa_class can inherit pp from bbb_class, because pp in both classes has aaa as origin interface.
Language Reference

Page 80 / 167

Visual Prolog 7.5 - Language Reference

Language Reference

Page 81 / 167

Visual Prolog 7.5 - Language Reference


Facts
Facts Sections
A facts section declares a fact database, consisting of a number of facts. The fact database and the
facts belong to the current scope.
Fact databases can exist on a class level as well as on an object level.
Facts sections can be declared only in class implementations.
If the fact database is named, an additional compound domain is implicitly defined. This domain has
the same name as the fact section and has functors corresponding to the facts in the fact section.
If the facts section is named, the name denotes a value of the build-in domain factDB. The save
and consult predicates accept values of this domain.
FactsSection :
class-opt facts FactsSectionName-opt FactDeclaration-dot-term-list-opt

FactsSectionName :
- LowerCaseIdentifier

Fact Declarations
A fact declaration declares a fact of a fact database. A fact declaration is either a fact variable, or a
functor fact.
FactDeclaration :
FactVariableDeclaration
FactFunctorDeclaration

FactFunctorDeclaration :
FactName : ( Argument-comma-sep-list-opt ) FfactMode-opt

FactName :
LowerCaseIdentifier

A fact functor declaration has nondeterm fact mode by default.


A fact functor can have initialization via clauses section. In such case values in the clauses should be
expressions, which can be evaluated at compile time.
FactMode : one of
determ nondeterm single

If mode is single, then a fact always has one and only one value and the assert predicate
overwrites old value with a new one. Predicate retract cannot be applied to single facts.
Language Reference

Page 82 / 167

Visual Prolog 7.5 - Language Reference


If mode is nondeterm, then the fact can have zero, one, or any other number of values. If mode is
determ, then the fact can have zero or one value. If fact has zero values, then any read access to
it gives fail.

Fact Variable Declarations


A fact variable is similar to a one-argument single functor fact. However, syntactically it is used as a
mutable variable (i.e. with assignment).
FactVariableDeclaration :
FactVariableName : Domain InitialValue-opt

InitialValue :
:= ConstantValue
:= erroneous

FactVariableName :
LowerCaseIdentifier

A constant value ConstantValue should be a term (of the Domain type), which can be evaluated at
compile time.
The constant value can be omitted only if the fact variable is initialized in a constructor. Class fact
variables should always have an initial constant value.
Notice that the keyword erroneous can be used as value to be assigned to fact variables. That is
both lines below are valid:
facts
thisWin : vpiDomains::windowHandle := erroneous.
clauses
p() :- thisWin := erroneous.

The idea of assigning erroneous value is to give clear runtime error if some code uses uninitialized
fact variable by mistake.

Facts
Facts can only be declared in a class implementation and subsequently they can only be referenced
from this implementation. So the scope of facts is the implementation in which they are declared. But
the lifetime of object facts is the lifetime of the object to which they belong. Likewise the lifetime of
class facts are from program start to program termination.
Example The following class declares an object fact objectFact and a class fact classFact:
implement aaa_class
facts
objectFact : (integer Value) determ.
class facts
classFact : (integer Value) determ.
Language Reference

Page 83 / 167

Visual Prolog 7.5 - Language Reference


...
end implement aaa_class

Language Reference

Page 84 / 167

Visual Prolog 7.5 - Language Reference


Clauses
Clauses Sections
A clauses section consists of a set of clauses. The clauses section contains implementations of
predicates or initial values of facts.
A single clause section can have clauses for several predicates and facts. On the other hand, all
clauses for one predicate/fact (the same name and arity) must be grouped together in one clauses
section and without intervening clauses of other predicates/facts.
ClausesSection :
clauses Clause-dot-term-list-opt

See also Guards in Monitors.

Clauses
Clauses are used to define predicates. A single predicate is defined by a set of clauses. Each clause
is executed in turn until one of them succeeds, or there is no more clauses left to execute. If no
clause succeeds the predicate fails.
If a clause succeeds and there are more relevant clauses in a predicate left, the program control can
later backtrack to the clauses of this predicate to search for other solutions.
Thus, a predicate can fail, succeed, and even succeed multiple times.
Each clause has a head and optionally a body.
When a predicate is called the clauses are tried in turn (from top to bottom). For each clause the
head is unified with the arguments from the call. If this unification succeeds then the body of the
clause (if such one exist) is executed. The clause succeeds if the match of the head succeeds and
the body succeeds. Otherwise it fails.
A clause consists of a head and an optional body.
Clause :
ClauseHead ReturnValue-opt ClauseBody-opt .

ClauseHead :
LowercaseIdentifier ( Term-comma-sep-list-opt )

ReturnValue :
= Term

ClauseBody :
:- Term

See also Guards in Monitors.


Language Reference

Page 85 / 167

Visual Prolog 7.5 - Language Reference


Goal Section
The goal section is the entry to a program. When the program starts it executes the goal, when the
goal is executed, the program exits.
GoalSection :
goal Term.

The goal section consists of a clause body. The goal section defines its own scope, therefore all
invocations should contain class qualifications.
The goal must have procedure mode.

Language Reference

Page 86 / 167

Visual Prolog 7.5 - Language Reference


Terms
This section describes terms and how execution/evaluation of terms and clauses proceeds.
Semantically, there are two kinds of terms: formulas and expressions.
l
l

Expressions represent values, like the number 7.


Formulas represent logical statements, like "the number 7 is greater than the number 3".

Syntactically the two kinds have a huge overlap and therefore the syntax unites the two kinds into
terms.
The following definition of Term is simplified, in the sense that it includes syntactic constructions
that are not legal. For example, one cannot legally write ! + !. We do however believe that using this
simple syntax description in combination with intuitive understanding of language concepts, the type
system, and the operator hierarchy described below is better for most purposes.
Term:
( Term )
Literal
Variable
Identifier
MemberAccess
PredicateCall
PredicateExpression
UnaryOperator Term
Term Operator Term
Cut
Ellipsis
FactvariableAssignment

Backtracking
The evaluation of a Prolog program is a search for a "solution" to the goal. Each step in the search for
a solution can either succeed or fail. At certain points in the program execution there are more than
one possible choices for finding a solution. When such a choice point is met a so called backtrack
point is created. A backtrack point is a recording of the program state plus a pointer to the choice
that was not executed. If it turn out that the original choice could not provide the solution (i.e. if it
fails), then the program will backtrack to the recorded backtrack point. Thereby restoring the
program state and pursuing the other choice. The mechanism will be described and exemplified in
details in the following sections.

Literals
Literals have universal type.
Literal:
IntegerLiteral
RealLiteral
CharacterLiteral
StringLiteral
BinaryLiteral
ListLiteral
CompoundDomainLiteral

See also Literals (in Lexical Elements)


Language Reference

Page 87 / 167

Visual Prolog 7.5 - Language Reference


Variables
Variables in Visual Prolog are immutable: once they are bound to a value they retain that value, but
backtracking can unbind the variable again during the process of restoring a previous program state.
A variable can thus be bound (during unification and matching), if it is already bound then it
evaluates to the value that it is bound to.
Variables are names starting with an upper-case letter or with an underscore (_), followed by a
sequence of letters (both uppercase and lowercase), digits, and underscore characters (all in all
called an UppercaseIdentifier):
Variable:
UppercaseIdentifer

The following are examples of valid variable names:


My_first_correct_variable_name
_
_Sales_10_11_86

while the next two are invalid:


1stattempt
second_attempt

The variable consisting of single underscore character (i.e. _) is known as the anonymous variable.
The anonymous variable is used in patterns and bindings where the corresponding value is of no
interest and should be ignored. Every occurrence of the anonymous variable is an independent
anonymous variable, i.e. even though the anonymous variable is used several times in a single clause
they have no relation to each other.
If variables that starts with an underscore are not anonymous, but they are still intended for values
of no interest that should be ignored. The compiler will issue a warning if the value of such a warning
is actually not ignored.
Prolog variables are local to the clause in which it occurs. That is, if two clauses each contain a
variable called X, these X-s are two distinct variables.
A variable is said to be free when it is not yet associated with a term and to be bound or instantiated
when it is unified with a term.
The Visual Prolog compiler does not make a distinction between upper and lower case letters in
names, except for the first letter. This means that the two variables SourceCode and SOURCECODE
are the same.

Identifier
Identifier:
MemberName
Language Reference

Page 88 / 167

Visual Prolog 7.5 - Language Reference


GlobalScopeMembername
ScopeQualifiedMemberName

MemberName:
LowerCaseIdentifier

Identifiers are used to refer to named entities (i.e. classes, interfaces, constants, domains,
predicates, facts, ...).
An identifier can just be a lower case identifier (i.e. a lowercase letter followed by a sequence of
letters, numbers and underscore characters).
Many entities can have the same name. So it may be necessary or desirable to qualify the lowercase
identifier the name of the particular scope of interest, or to state that the name is in the global
namespace.
Example These are examples of unqualified identifiers:
integer
mainExe
myPredicate

Global Entities Access


The only global entities, which exist in Visual Prolog, are built-in domains, predicates, and constants.
Global names are directly accessible in any scope. There might however exist situations where a
global name is shadowed by a local or imported name. In that case the global entity can be qualified
with a double colon '::' (without a prefixed class/interface name). The double colon can be used
everywhere, but the most important place is where an interface name is used as formal parameter
type specifier.
GlobalScopeMemberName:
:: MemberName

Example The built-in domain integer is defined in the global scope, to avoid ambiguity or stress that
it is this particular domains you can use the global scope member name:
::integer

Class/Interface Member Access


Static members of classes and interfaces are accessed by means of qualification with the class name
(and optionally a namespace prefix):
ScopeQualifiedMemberName
NamespacePrefix-opt ScopeName :: MemberName

NamespacePrefix:
NamespaceIdentifier-opt \

ScopeName:
LowercaseIdentifier

Language Reference

Page 89 / 167

Visual Prolog 7.5 - Language Reference


The ScopeName is the name of the class or interface that defines/declares the name.
Namespace prefixing is explained in: Referencing names in namespaces.
Some names can be accessed without qualification, see scoping & visibility.

Predicate Call
A predicate call have the form
PredicateCall:
Term ( Term-comma-sep-list-opt )

The first term must be an expression that evaluates to a value with predicate type. Typically, it is
either the name of a predicate in a class, or an expression that evaluates to a predicate member of
an object.
Notice that some predicates return values, whereas other predicates do not. A predicate that returns
a value is an expression, and the predicate call is often referred to as a function call. A predicate
that does return a value is a formula.
A predicate is invoked by applying arguments to the predicate. The predicate must have a flowpattern that matches the free/bound state of the arguments.
Most predicates are defined by a set of clauses, but some predicates are built into the language and
some are defined externally in a DLL (perhaps in a foreign programming language).
When a predicate is invoked by a predicate call, each clause is executed in turn until one of them
succeeds, or there are no more clauses left to execute. If no clause succeeds the predicate fails.
If a clause succeeds and there are more relevant clauses left, a backtrackpoint is created to the
next relevant clause.
Thus, a predicate can fail, succeed, and even succeed multiple times.
Each clause has a head and optionally a body.
When a predicate is called the clauses are tried in turn (from top to bottom). For each clause the
arguments in the head is unified with the arguments from the call. If this unification succeeds then
the body of the clause (if present) is executed. The clause succeeds, if the match of the head
succeeds and the body succeeds. Otherwise it fails.
Example
clauses
ppp() :- qqq(X), write(X), fail.

qqq(1).
qqq(2).
qqq(3).

When ppp is called it in turn calls qqq. When qqq is called, it first creates a backtrack point pointing
Language Reference

Page 90 / 167

Visual Prolog 7.5 - Language Reference


to the second clause. Then the first clause is executed. Hereby the free variable X from ppp is
matched against the number 1, whereby X is bound to 1.
In ppp X (i.e. 1) is written and then fail cause backtracking to the backtrackpoint. Hereby program
control is set to the second clause in qqq and the program state is set back to the state it was in
when qqq was first entered, i.e. X in ppp is unbound again.
Before the actual execution of the second clause in qqq begins a backtrack point to the third clause
is created. The execution then proceeds as it did for 1

Unification
When a predicate is called the arguments from the call is unified with the terms in the head of each
clause.
Unification is the process of binding variables in such a way that two terms become equal, making as
few bindings as possible (i.e. leaving as much as possible open for further binding).
Variables can be bound to any kind of terms, including variables or terms containing variables.
Unification is either possible or impossible, i.e. it can succeed or fail.
Variables and terms to which they are unified have types, a variable can only be bound to a term of
the same type as the variable, or a subtype. When two variables are bound to each other they must
therefore have exactly the same type.
Unification takes place (as mentioned) between a predicate call and the clause head. It also takes
place when two terms are compared for equality.
Example Consider two terms (of the same type):
T1 = f1(g(), X, 17, Y, 17)
T2 = f1(Z, Z, V, U, 43)

We will attempt to unify these two terms from left to right (i.e. a left-to-right pre-traversal).
Both T1 and T2 are f1/5 terms, this match. Therefore we attempt to unify each of the arguments
from T1 with each correspondent argument of T2. First we must unify Z and g(), this can be unified
if we bind Z to g(). So far everything is fine and we have the first binding in our unifier:
Z = g()

The next two arguments are X and Z, which already has been bound to g(). These two arguments
can also be unified if we also bind X to g(). So we now have the following contributions to our
unifier:
X = Z = g()

Next we must bind V to 17 and then we must bind Y to U. So far everything unifies with the following
unifier:
Language Reference

Page 91 / 167

Visual Prolog 7.5 - Language Reference


X = Z = g()
V = 17
Y=U

The two unified terms are now equivalent to these terms:


T1 = f1(g(), g(), 17, Y, 17)
T2 = f1(g(), g(), 17, Y, 43)

But we have not yet unified the two last arguments, which are 17 and 43. No variable binding can
make these terms equal, so all in all the unification fails.
T1 and T2 cannot be unified.
In the example above T1 could have been a predicate call and T2 a clause head. But they could also
have been two terms that were compared with equal "=".

Matching
Matching is the same as unification except that variables can only be bound to grounded terms. A
grounded term is a term that does not contain any unbound variables.
It is the flow-patterns that are stated for predicates, that make it possible to use matching rather
than full-blown unification.
Example
clauses
ppp(Z, Z, 17).
qqq() :ppp(g(), X, 17).

Unification of the ppp-call with the ppp-clause is possible with the following unifier:
Z = X = g()

If ppp have the flow (i,o,i) then the unification is just a match:
l
l

g() is input as the first argument, this is bound to Z


The second argument in the clause is therefore bound and can thus be output to X, which
therefore becomes bound to g().
finally the third argument is 17 used as input this number is simply compared to the third
argument in the clause.

It is the flow-pattern that makes it possible to predict that the clause does not need real unification.

Nested Function Calls


Terms that have to be unified or matched with each other are allowed to contain sub-terms that are
actually expressions or function calls that have to be evaluated before the unification/matching can
Language Reference

Page 92 / 167

Visual Prolog 7.5 - Language Reference


be completed.
The evaluation of such sub-terms is done on a by-need basis.
In a predicate call all input arguments are evaluated before the predicate is called, all output
arguments are variables, which does not need evaluation.
Clause heads can also contain terms that have to be evaluated, before matching/unification can be
determined.
l

l
l
l

all matching/unification that does not require any evaluation is performed before any evaluation
is performed;
then evaluation corresponding to input arguments is performed one by one left-to-right.
Comparing each value to the corresponding input after each evaluation;
then the clause body is evaluated;
then the output arguments are evaluated (left-to-right);
then the return value (if the predicate is a function) is evaluated.

If any of these fail then the rest of the evaluation is not carried out.
All in all the base principles are:
l
l
l

input after other match, before body evaluation


output after body evaluation
left-to-right

Anonymous Predicates
An anonymous predicate is an expression that evaluates to a predicate value. The predicate value
can be bound to a variable, passed as arguments or returned as result, but the value does not have
a name in any class, interface or implementation.
Anonymous predicates have the ability to capture values from the context in which the expression
occurs, this is a rather powerful ability that can be used to avoid rather excessive amount of
strange/unpleasant code.
Syntax
Anonymous predicates are terms:
Term : one of
...
AnonymousPredicate
...

An anonymous predicate is a nameless clause in curly brackets. Certain parts are optional, giving
these forms:
AnonymousPredicate : one of
{ ( Arg-comma-sep-list ) = Term }
{ ( Arg-comma-sep-list ) = Term :- Term }
{ ( Arg-comma-sep-list ) :- Term }
{ = Term }
{ = Term :- Term }
Language Reference

Page 93 / 167

Visual Prolog 7.5 - Language Reference


{ :- Term }

Leaving out the argument list means "the required number of arguments" and can be used whenever
the arguments are not used.
Semantics
An anonymous predicate expression evaluates to a predicate value. Consider this code:
clauses
run() :Inc = { (X) = X+1 },
A = Inc(4),
B = Inc(23),
stdio::writef("A=%,B=%", A, B).

Inc becomes an increment predicate, so the program will write:

A = 5, B = 24

The code in this example corresponds to this code:


clauses
run() :Inc = inc,
A = Inc(4),
B = Inc(23),
stdio::writef("A=%,B=%", A, B).

class predicates
inc : (integer X) -> integer R.
clauses
inc(X) = X+1.

Where the clause (X) = X+1 can be found in the last line. I.e. this time in a named predicate.
Variables that are bound outside (i.e. before the occurrence of) an anonymous predicate can be used
inside the anonymous predicate. The value of variable will be captured by the anonymous predicate.
Variables that are bound in an anonymous predicate are local variables in the anonymous predicate.
Capturing context
An anonymous predicate can capture context, which means that it can refer to things that are
defined in its context, especially facts and variables from the clause.
Capturing Variables
Anonymous predicate occurs in a clause, and this clause may contain variables. Those variables that
are bound before the anonymous predicate is met can be used inside the anonymous predicate. This
code illustrates how a variable is captured:

Language Reference

Page 94 / 167

Visual Prolog 7.5 - Language Reference


domains
pred = (integer) -> integer.

class predicates
createAdder : (integer A) -> pred Adder.
clauses
createAdder(A) = { (X) = X+A }.

clauses
run() :Add17 = createAdder(17),
A = Add17(4),
B = Add17(20),
stdio::writef("A=%,B=%", A, B).

We call createAdder with 17 as argument. So in the createAdder clause A is 17, and therefore the
result is { (X) = X+17 }. We say that the anonymous predicate has captured the variable A.
Since Add17 is a predicate that adds 17 to its argument, the output of the code will be:

A = 21, B = 37

Capturing ellipsis (...)


An anonymous predicate can capture the ellipsis variable (i.e. ...):
clauses
ppp(...) :W = { () :- stdio::write(...) },
qqq(W).

W captures the ellipsis variable. qqq receives a zero-arity predicate, when this predicate is invoked
the captured ellipsis variable will be written to the standard output device.
Capturing Facts
An anonymous predicate can access facts. If it is created by a class predicate it can access class
facts. If it is created by an object predicate it can access both object and class facts. Consider this
code that captures a class fact:
class facts
count : integer := 0.
clauses
seq() = { () = count :- count := count+1 }.
clauses
run() :A = seq(),
B = seq(),
stdio::writef("A1=%,", A()),
stdio::writef("B1=%,", B()),
stdio::writef("A2=%,", A()),
stdio::writef("B2=%", B()).

Both A and B increment the class fact count, so the result is

Language Reference

Page 95 / 167

Visual Prolog 7.5 - Language Reference


A1 = 1, B1 = 2, A2 = 3, B2 = 4

In object predicates we can capture object facts. So assuming that seq is an object predicate in
myClass, this code illustrates the capture of an object fact:
facts
count : integer := 0.
clauses
seq() = { () = count :- count := count+1 }.
clauses
run() :A = myClass::n e w():seq(),
B = myClass::n e w():seq(),
stdio::writef("A1=%,", A()),
stdio::writef("B1=%,", B()),
stdio::writef("A2=%,", A()),
stdio::writef("B2=%", B()).

In this case A and B comes from two different objects, which each have a count fact, so the output
will be:

A1 = 1, B1 = 1, A2 = 2, B2 = 2

Technically, the class version actually doesn't capture anything, it merely have access to the fact.
Likewise, the object version doesn't actually capture the fact, instead it captures This and through
This it obtains access to the object facts.
Capturing This
As described above it is possible to capture This and thereby gaining access to objects facts. The
same mechanism gives access to calling object predicates.
clauses
seq() = { () = count :- inc() }.

clauses
inc() :- count := count+1.

This can also be used directly:


clauses
ppp() = { () = aaa::rrr(This) }.

Nesting
Anonymous predicates can be nested:
clauses
run() :P = { (A) = { (B) = A+B } },
Q = P(3300),
R = P(2200),
stdio::writef("Q(11)=%,", Q(11)),
Language Reference

Page 96 / 167

Visual Prolog 7.5 - Language Reference


stdio::writef("R(11)=%", R(11)).

To obtain Q we call P with 3300, so A is 3300 and Q therefore becomes { (B) = 3300+B } },
likewise R becomes { (B) = 2200+B } }. So, the output is:

Q(11) = 3311, R(11) = 2211

Syntactic Sugar
If you don't need the arguments they can be skipped. So this code-fragment:
P = { (_) :- succeed },
Q = { (_, _) = 0 },
R = { (_, _, _) = _ :- fail }
Can be shortened down to this:
P = { :- succeed },
Q = { = 0 },
R = { = _ :- fail }

Notice that the arguments are completely skipped. If you write () it means zero arguments, whereas
skipping the arguments means "a suitable amount" of arguments.
Examples of practical usage
This section shows some cases where anonymous predicates are very handy. The examples assume
that the PFC scopes core, std, stdio, list and string are open.
Dummy predicates
Anonymous predicates are good for creating dummy predicate values:
ppp( { = true } ), % don't filter (boolean)
qqq( { :- succeed } ), % don't filter (determ)
rrr( { = 17 } ), % all rows must have height 17

Adaptation
In cases where you need a predicate and have one that is almost suitable, you can make the
adaptation using an anonymous predicate.
Index adaptation
Consider the predicate write3:
class predicates
write3 : (function{integer, string} Indexer).
clauses
write3(Indexer) :foreach I = std::fromTo(0,2) d o
write(Indexer(I), "\n")
end foreach.
Language Reference

Page 97 / 167

Visual Prolog 7.5 - Language Reference


Indexer implements an "array" of strings, write3 will write the three strings found at the indexes 0, 1
and 2. So write3 assumes that the "array" index is zero-based. However, the "array" we have uses a
one-based index:
class predicates
myArray : (integer N) -> string Value.
clauses
myArray(1) = "First" :- !.
myArray(2) = "Second" :- !.
myArray(3) = "Third" :- !.
myArray(_) = _ :raiseError().

But using an anonymous predicate we can easily adapt the one-based array to the zero-based
usage:
% myArray is 0-based, write3 requires 1-based
Arr = { (N) = myArray(N+1) },
write3(Arr)

So we get the expected output:

First
Second
Third

Parameter adaptation
In this code listChildren will call a ChildWriter predicate for each "C is the child of P"-pair:
class predicates
listChildren :
(predicate{string,string} ChildWriter).
clauses
listChildren(C W) :C W("Son1", "Father"),
C W("Son2", "Father").

We will however prefer to list the "P is the parent of C" using the predicate wParent:
class predicates
wParent : (string Parent, string Child).
clauses
wParent(P, C) :writef("%istheparentof%\n", P, C).

wParent takes the arguments in the opposite order, but we can easily adapt using an anonymous
predicate:
Swap = { (A,B) :- wParent(B,A) },
listChildren(Swap)
Language Reference

Page 98 / 167

Visual Prolog 7.5 - Language Reference


And then the out becomes the expected:

Father is the parent of Son1


Father is the parent of Son2

We can also throw away arguments, for example when calling this predicate that only needs a Child:
class predicates
wKnowParent : (string Child).
clauses
wKnowParent(C) :writef("Weknowaparentof%\n", C).

The adaptation looks like this:


Fewer = { (C,P) :- wKnowParent(C) },
listChildren(Fewer)

The output will be:

We know a parent of Son1


We know a parent of Son2

We can also supply dummy arguments:


More = { (_,P) :- addChildren(P, 1) }
listChildren(More)

Here addChildren will "add a count of children to P". Since each invocation corresponds to one child
we will call addChild supplying 1 as a "dummy" argument. The More is thus an adaptor that both
throws away an argument and supplies a dummy argument.
Filters
Assume this predicate:
class predicates
writeFiltered :
(string L, filterPredicate{integer} Filter).
clauses
writeFiltered(Label, Filter) :List = [1,2,3,4,5,6,7,8,9],
FilteredList = filter(List, Filter),
writef("%\t%\n", Label, FilteredList).

Filter is used to filter the list [1,2,3,4,5,6,7,8,9]; the filtered list and the Label are written to the
standard output.
First we use the allow-all filter:
Language Reference

Page 99 / 167

Visual Prolog 7.5 - Language Reference


All = { :- succeed },
writeFiltered("All", All)

This filter simply succeeds for any element, so the output is the entire list:

All

[1,2,3,4,5,6,7,8,9]

It is just as easy to create a filter that fails for all elements and thus allow-none:
None = { :- fail },
writeFiltered("None", None)

The output from this is the empty list:

None

[]

We can also create filters for elements greater than 3 and elements dividable by 3:
GreaterThan3 = { (X) :- X > 3 },
writeFiltered("> 3", GreaterThan3),
Rem3 = { (X) :- 0 = X rem 3 },
writeFiltered("Rem3", Rem3)

The output from this is:

> 3
Rem3

[4,5,6,7,8,9]
[3,6,9]

Sorting
The list package has a sort predicate. But sometimes the default order is not what you need.
Therefore the list package also has a predicate sortBy, which sorts the elements using a programmer
defined compare operation. Let us first consider string sorting, using this predicate:
class predicates
writeStringsSorted :
(string Label, comparator{string} Comp).
clauses
writeStringsSorted(Label, C) :List = ["John Wayne", "Uma Thurman",
"Harrison Ford", "Nicolas Cage",
"Elizabeth Taylor", "Cary Grant",
"Jerry Lewis", "Robert De Niro"],
Sorted = sortBy(C, List),
write(Label, "\n"),
foreach S = list::getMember_nd(Sorted) d o
writef("%\n", S)
end foreach.

Language Reference

Page 100 / 167

Visual Prolog 7.5 - Language Reference


We can call the predicate with the "normal" comparator, and using an anonymous predicate we can
easily sort it descending as well:
Normal = compare,
writeStringsSorted("Normal", Normal),
Descending = { (A,B) = compare(B,A) },
writeStringsSorted("Descending", Descending)

The output looks like this:

Normal
Cary Grant
Elizabeth Taylor
Harrison Ford
Jerry Lewis
John Wayne
Nicolas Cage
Robert De Niro
Uma Thurman
Descending
Uma Thurman
Robert De Niro
Nicolas Cage
John Wayne
Jerry Lewis
Harrison Ford
Elizabeth Taylor
Cary Grant

Let us also sort some more complex elements. Here a person has a first name and a last name, using
this domain:
domains
person = p(string First, string Last).

For the demonstration we will use this test predicate:


class predicates
writePersonsSorted :
(string Label, comparator{person} Comparator).
clauses
writePersonsSorted(Label, C) :List = [p("John","Wayne"),
p("Uma","Thurman"),
p("Harrison","Ford"),
p("Nicolas","Cage"),
p("Elizabeth","Taylor"),
p("Cary","Grant"),
p("Jerry","Lewis"),
p("Robert","De Niro")],
Sorted = sortBy(C, List),
write(Label, "\n"),
foreach p(F,L) = list::getMember_nd(Sorted) d o
writef("%%\n", F, L)
end foreach.

Again we can sort using the normal and a descending comparator:

Language Reference

Page 101 / 167

Visual Prolog 7.5 - Language Reference


Normal = compare,
writePersonsSorted("Normal", Normal),
Descending = { (A,B) = compare(B,A) },
writePersonsSorted("Descending", Descending)

Since the compare predicate uses left-to-right lexicographic order on the p-functor, the result is the
same as before:

Normal
Cary Grant
Elizabeth Taylor
Harrison Ford
Jerry Lewis
John Wayne
Nicolas Cage
Robert De Niro
Uma Thurman
Descending
Uma Thurman
Robert De Niro
Nicolas Cage
John Wayne
Jerry Lewis
Harrison Ford
Elizabeth Taylor
Cary Grant

But with the more complex domain we can create a comparator that will sort on last name:
LN = { (p(_,L1), p(_, L2)) = compare(L1,L2) },
writePersonsSorted("LastName", LN)

The result is what we expect:

LastName
Nicolas Cage
Robert De Niro
Harrison Ford
Cary Grant
Jerry Lewis
Elizabeth Taylor
Uma Thurman
John Wayne

Capturing context
As mentioned a very powerful feature of anonymous predicates is the ability to capture context. The
examples in this section show some ways you can use this.
Background threads
The routine for starting a thread takes a null-ary predicate and run it in the new thread. But you
nearly always need to pass some input data to the job in the new thread. This is possible in several
ways, but the absolutely simplest way is to use anonymous predicates. The project bgDemo from
the Visual Prolog example collection (that can be installed from the IDE) use this method. The project
has a form that can start background job and display status information from the job in a jobControl
Language Reference

Page 102 / 167

Visual Prolog 7.5 - Language Reference


that is added to the form. A background job is a predicate that will receive a jobLog, which it can
use to report status and completion degree:
domains
job = (jobLog Log).

A jobLog looks like this:


interface jobLog

properties
completion : real (i).

properties
status : string (i).

end interface jobLog

The job can report completion degree by setting the completion property (range 0 to 1). Likewise,
the status property can be used to reflect the current status of the job.
The status and completion will be shown in the form together with a job name. A job is started by
calling the form's addJob predicate:
clauses
addJob(JobName, Job) :JobCtrl = jobControl::n e w(This),
JobCtrl:name := JobName,
JobCtrl:show(),
assert(jobCtrl_fact(JobCtrl)),
arrange(),
JobLog = jobLog::n e w(JobCtrl),
Action = { :- Job(JobLog) },
_ = thread::start(Action).

In this context it is the last three lines that are interesting. thread::start takes a null-ary predicate
as argument, but a job is a predicate that takes a jobLog as argument. Therefore we create an
anonymous predicate Action, which takes no arguments but invokes Job on the JobLog. The
anonymous predicate has captured both Job and JobLog from the context, and subsequently both
these values are transferred to the new thread even though this thread only receives a null-ary
predicate. The jobs in the bgDemo project are merely dummy jobs that only manipulate their
jobLog. One of them looks like this:
clauses
job(Log, From, To) :Log:status := "Step 1",
foreach N1 = std::fromTo(From, To) d o
Log:completion :=
(N1-From) / (To-From) / 2,
programControl::sleep(3)
end foreach,
Log:status := "Step 2",
foreach N2 = std::fromTo(From, To) d o
Log:completion :=
(N2-From) / (To-From) / 2 + 0.5,
programControl::sleep(3)
end foreach,
Log:status := "finished".
Language Reference

Page 103 / 167

Visual Prolog 7.5 - Language Reference

It has two loops which run from From to To and calculates the completion and sets it on the Log. It
also sets the status text before, between and after the loops. You may notice that the job does not
have the proper job type, because a proper job only has one argument (the jobLog), this job has
three arguments. Again it is anonymous predicates that help us. The code that adds the jobs to the
form looks like this:
predicates
onFileNew : window::menuItemListener.
clauses
onFileNew(_Source, _MenuTag) :JF = jobForm::display(This),
Job11 = {(L) :- job1::job(L, 1, 1000)},
Job12 = {(L) :- job1::job(L, 200, 600)},
Job13 = {(L) :- job1::job(L, 1200, 3000)},
Job14 = {(L) :- job1::job(L, 1, 1000)},
JF:addJob("job1.1", Job11),
JF:addJob("job1.2", Job12),
JF:addJob("job1.3", Job13),
JF:addJob("job1.4", Job14),
...

In a more realistic program, it is most likely that From and To would not be constants, but rather
parameters passed from some outer place. In that case these anonymous predicates would also
capture variables from the context. The jobLog in the bgDemo illustrates one more usage of
anonymous predicates. The jobLog pass the completion and the status information to a jobControl.
The jobControl is a GUI control on the jobForm capable of doing a suitable rendering of the
information. This however gives a synchronization problem, because GUI controls are not thread safe
and here we want to update some controls from a background thread. This can lead to conflicts,
because it is the main thread that draws the controls. The solution is to make transfer the the
update of the control to the GUI thread. We do this by posting actions to the control. The
implementation of the status update looks like this:
clauses
status(Status) :Action = { :- jobCtrl:status := Status },
jobCtrl:postAction(Action).

Action is a null-ary predicate that will set the status in the jobCtrl. We post this action to the
jobCtrl. When the jobCtrl receives the action it invokes it and is thus updated. This way that actual
update of the control will be performed by the GUI thread. This anonymous predicate not only
captures the Status variable it also captures the jobCtrl fact.
Asynchronous callbacks
Assume that we send commands to a remote service. The command execution is asynchronous, so
when we execute a command we also give a callback action which will be invoked when the
execution of the command is finished. To execute a command we must call this predicate:
predicates
executeCommand :
(command Cmd, predicate{} OnDone).

Based on this predicate we want to create a similar predicate that can execute a list of commands. A
certain command should be executed when the previous command completes. We will also make our
Language Reference

Page 104 / 167

Visual Prolog 7.5 - Language Reference


list executor asynchronous, so we supply an action that will be invoked when the entire script of
commands are finished. Our script executer will have the form:
predicates
executeScript :
(command* Script, predicate{} OnDone).

If the script is empty we simply invoke the OnDone action. If the script has a command H and a rest
script T, we must first execute H, and when it is finished we must execute the rest of the script T.
So the OnDone action we supply when executing H must execute T. All in all, the implementation
can look like this:
clauses
executeScript([], OnDone) :OnDone().
executeScript([H|T], OnDone) :DoneH = { :- executeScript(T, OnDone) },
executeCommand(H, DoneH).

We have used an anonymous predicate to perform the execution of the rest of the script. This
anonymous predicate captures T and OnDone.

Fact Variable Assignment


Assign operator := is used to assign a new value for a fact variable FactVariable. The Term must be
evaluated to a value of suitable type (i.e. the same type as the fact variable, or a subtype).
FactVariableAssignment:
FactVariable := Term

Facts
A fact database contains a number of fully instantiated (grounded) predicate heads corresponding to
the facts from the facts section declaration. The facts can be accessed by a predicate call, using
the fact name as the predicate name. The predicate call is matched against each fact in turn;
succeeding with a possible backtrack point to the next fact each time the predicate call match the
fact. When there are no more facts in the fact database then the predicate call fails.
New facts can be asserted using the predicates assert/1, asserta/1, and assertz/1. assert/1 is the
same as assertz/1 and it asserts a new fact to the end of the list of facts, whereas asserta/1
asserts a new fact to the start of the list.
Existing facts can be retracted with the predicate retract/1 and retractAll/1. retract/1 retracts the
first fact that match the argument binding variables in the argument and leaving a backtrack point so
that more facts will potentially be retracted when backtracking.
retractAll/1 retracts all facts that matches the arguments and succeeds without any binding.

Operators
Operators are organized in a precedence hierarchy. In the rule below operators in each group have
same precedence, which is higher than those below. I.e. the power operator has higher precedence
Language Reference

Page 105 / 167

Visual Prolog 7.5 - Language Reference


than unary minus and plus, which in turn has higher precedence than the multiplication operators,
etc. Parenthesis can be used to circumvent the precedence (and for clarification).
Operator: one of
PowerOperator
UnaryOperator
MultiplicationOperator
AdditionOperator
RelationOperator
MustUnifyOperator
InOperator
AndOperator
OrOperator

UnaryOperator: one of
-+

All operators except the UnaryOperator's are binary. The power operator is right associative, all
other operators are left associative.
RelationOperator, MustUnifyOperator and InOperator have same precedence.
Notice that the placement UnaryOperator is not consistent with mathematics, where these
operators are at the same level as the AdditionalOperator's. The difference has no influence of the
calculated value, but it allows writing 2*-2, where mathematics would require a parenthesis around
the second operator 2*(-2). It also means that -2*2 is mmeans (-2)*2 where it would be -(2*2) in
mathematics (the resulting value is the same).
Example
-2^2 is the same as -(2^2) because ^ has higher precedence than unary minus.
Example
3^2^2 is the same as 3^(2^2) because ^ is right associative.
Example
-2*-3^-4+5 is the same as ((-2) * (-(3 ^ (-4)))) + 5.
Example The following term:
7 + 3 * 5 * 13 + 4 + 3 = X / 6A < 7, p(X)

has the same meaning as this term:


((((7 + ((3 * 5) * 13)) + 4) + 3) = (X / 6))((A < 7) , p(X))

I.e. at outermost level the term is an "or" of two terms, the first of these is a relational (=) term, the
second is an "and" term, etc.

Language Reference

Page 106 / 167

Visual Prolog 7.5 - Language Reference


Arithmetic Operators
The arithmetic operators are used for arithmetic operations on numbers. They are expressions, which
takes expressions as arguments. They have root types as arguments and return universal types as
result. (See Universal and Root types.)
PowerOperator:
^

MultiplicationOperator: one of
* / div mod quot rem

AdditionOperator: one of
+ -

Relational Operators
The relational operators are formulas, which takes expressions as arguments. Given this nature they
are non-associative.
RelationOperator: one of
= > < >= <= <> ><

First the left term is evaluated, then the right term is evaluated and then the results are compared.
Notice that <> (different) is not the dual operation of = (equal). <> compares two values, whereas
= tries to unify two terms (in the general case at least).
The dual to expression A = B is not (A = B).
Must Unify Operator
The must unify operator is a procedure, which takes expressions as arguments. It is non-associative.
MustUnifyOperator:
==

A == B unifies A and B; if the unification fails an exception is raised, otherwise the predicate
succeeds. Therefore A == B always succeeds.
Example
clauses
p(L) :[H|T] == L,
...

p is a procedure. An exception will be raised if it is called with an empty list, because [H|T] and L
Language Reference

Page 107 / 167

Visual Prolog 7.5 - Language Reference


cannot unify.
in
in
InOperator:
in

The in operator is used to test for member ship of a collection (e.g. a list) and to nondeterministically
generate the members of a collection.
Example
predicates
p : (Type X, Type* L).
clauses
p(X, L) :if X in L then
write("X is in L\n")
end if.

p is a procedure that takes a value X and a list L as arguments. If X is in the list L then it will write
"X is in L". In this case in is used as an in-test (membership test).

Example
predicates
q : (Type* L).
clauses
q(L) :foreach X in L d o
writef("% is in L\n", X)
end foreach.

q is a procedure that takes a list L as argument. The "in" operator is used to nondeterministically
return the members of L, so that they can be written.
The in operator can be defined for any domain and interface using the in_test and in_iterate
attributes.
The in_test(<predicate name>) attribute defines the predicate that is used as in-test for a
certain domain or interface. Likewise the in_iterate attribute defines the predicate that is used as
in-ieratorfor the domain/interface.
Example
domains
tree{E} = empty; node(tree{E} Left, E Value, tree{E} Right) [in_test(isMemberTree), in_iterate(getAll_nd

When the program contains A in B where A is bound B is a tree{E} then isMemberTree is actually
Language Reference

Page 108 / 167

Visual Prolog 7.5 - Language Reference


called.
In that case A in B corresponds to isMemberTree(A, B).
If A is free the call corresponds to A = getAll_nd(B).
For a domain <collection> the predicate must have the type:
predicates
<predicate> : (<some-type> Elem, <collection> Collection) determ.

Example
interface collection [in_test(contains), in_test(getAll_nd)]
...
end interface collection

When the program contains A in B where A is bound B is a collection then contains is actually
called.
In that case A in B corresponds to B:contains(A).
If A is free the call corresponds to A = B:getAll_nd().
For a domain <collection> the in_test and in_iterate predicate must fulfill these schematic
declarations:
domains
<collection> = ... [in_test(<in_test>), in_iterate(<in_iterate>)].
class predicates
<in_test> : (<some-type> Elem, <collection> Collection) determ.
<in_iterate : (<collection> Collection) -> <some-type> Elem nondeterm.

For an interface <collection> the in_test and in_iterate predicate must fulfill these schematic
declarations:
interface <collection> [in_test(<in_test>), in_iterate(<in_iterate>)].
predicates
<in_test> : (<some-type> Elem) determ.
<in_iterate : () -> <some-type> Elem nondeterm.
...
end interface <collection>

The in operator is predefined on list domains, and in PFC the collections have suitable attributes.
Example
clauses
p() :foreach X in [1, 2, 3, 4] d o % in_iterate
if X in [2, 4] then % in_test
...
Language Reference

Page 109 / 167

Visual Prolog 7.5 - Language Reference


end if
end foreach.

The first in is the predefined in_iterate for the list domain, and the second one is the predefined
in_iterate.
clauses
q() :M1 = setM_redBlack::n e w(),
M1:inset("a"),
M1:inset("b"),
M2 = setM_redBlack::n e w(),
M2:inset("b"),
foreach X in M1 d o % in_iterate
if X in M2 then % in_test
...
end if
end foreach.

For collections the in operators resolve to contains and getAll_nd:


interface collection{@Type}
[in_test(contains), in_iterate(getAll_nd)]

predicates
contains : (@Type Value) determ.
% @short Succeeds if the collection contains the value @Type
% @end

predicates
getAll_nd : () -> @Type Value nondeterm.
% @short @Type is nondeterministic iteration of the elements in the collection.
% @end

...

end interface collection

Logical Operators
The AndOperator(s) and OrOperator(s) are formulas, which takes formulas as arguments. They are
all left associative. The , and and are synonyms and so are ; and or.
AndOperator: one of
, and

OrOperator: one of
or orelse

and (,)
The evaluation of an and term A, B proceeds as follows. First the left sub-term A is evaluated. If this
evaluation fails, the whole and term fails. If A succeeds then the right sub-term B is evaluated. If
this evaluation fails, the whole and term fails, otherwise the and term succeeds.

Language Reference

Page 110 / 167

Visual Prolog 7.5 - Language Reference


Thus the second sub-term B is only evaluated, if the first sub-term A succeeds.
Example
clauses
ppp() :qqq(), rrr().

When ppp is called it will first call qqq and if qqq succeeds, then it will call rrr. If rrr succeeds, then
the and term and subsequently the whole clause succeeds.
or (;)
The evaluation of an or term A; B proceeds as follows. First a backtrack point to the second term B
is created and then the first term A is evaluated. If the evaluation of the first term succeeds, then
the whole or term succeeds and is left with a backtrack to the second term B. If the evaluation of
the first term fails, the backtrack point to the second term is activated.
If the backtrack point to the second term B is activated (either because the first term fails, or
because something later in the execution invokes the backtrack point), then the second term B is
evaluated and the whole or term will succeed if B succeeds.
Thus an or term can succeed with a backtrack point and the second sub-term B is only evaluated on
backtrack.
Example
clauses
ppp() :(V = 3 or V = 7), write(V), fail.

Here we have used the keyword or, but you can also use semi-colon ;.
When ppp is called we first create a backtrack point to the term V = 7 and then we evaluate V = 3.
Thereby V will be bound to 3 we then continue to the write(V) after 3 has been written fail is met.
fail always fails so we effectuate the backtrack point leading us to the term V = 7.
Backtracking also undo all bindings made since the backtrack point was created. In this case it means
that V is unbound.
Then V = 7 is evaluated and V becomes bound to 7 and er continue to the term write(V), and then
fail is met again, this time there are no more backtrack points ppp fails.
Using parentheses or can be nested deeply in clauses.
clauses
p(X) = Y :(X = 1, !, Z = 3 or Z = 7), Y = 2*Z.

We recommend careful usage of or. It is mainly intended for usage in test-conditions:

Language Reference

Page 111 / 167

Visual Prolog 7.5 - Language Reference


clauses
isOutside(X) :(X < 10 or X > 90), !.

or is a nondeterministic construction, but orelse can be used as a deterministic pendand:


clauses
isOutside(X) :X < 10 orelse X > 90.

orelse
orelse is a deterministic pendant to the nondeterministic or. A orelse B will succed if A succeds or if
B succeds, but it will not leave a backtrack point to B if A succeeds.
The evaluation of an orelse term A orelse B proceeds as follows: First a backtrack point to the
second term B is created and then the first term A is evaluated. If the evaluation of the first term
succeeds then the backtrack to the second term (and any backtrack point within it) B are removed
again and the whole orelse term succeeds. If the evaluation of the first term A fails, the backtrack
point to the second term B is evaluated.
So an orelse term does not leave a backtrack point.
Example
clauses
ppp(V) :(V = 3 orelse V = 7), write(V).

Whenever ppp is called we first create a backtrack point to the term V = 7 and then we evaluate
the term V = 3, if V = 3 succeds we remove the backtrack point to V = 7 again and then continue to
write(V). If V = 3 fails the backtrack point to V = 7 is effectuated. If V = 7 succeds we continue to
write(V), if V = 7 fails the entire ppp predicate will fail.
not
The not/1 takes a term as the argument. The evaluation of not(A) first evaluates A. If A succeeds,
then not(A) fails, if A fails, then not(A) succeeds.
Notice that not(A) will never bind any variables, because if not(A) succeeds then A has failed, and
a failed term does not bind anything. If not(A) on the other hand fails, it cannot bind any variables
either, because then the term itself failed.
Also notice that not(A) can never succeed with backtrack points, because if not(A) succeeds then
A have failed, and a failed term cannot contain any backtrack points. This in turn means that all
possibilities of success in A have been exhausted.

fail/0 and succeed/0


fail/0 and succeed/0 are two built-in nullary predicates. fail/0 always fails and succeed/0 always
succeeds, besides this the predicates have no effect.

Language Reference

Page 112 / 167

Visual Prolog 7.5 - Language Reference


Cut
Cut "!" removes all backtrack points created since the entrance to the current predicate, this means
all backtrack points to subsequent clauses, plus backtrack points in predicate calls made in the
current clause before the "!".
Cut:
!

Example
clauses
ppp(X) :X > 7,
!,
write("Greater than seven").
ppp(_X) :write("Not greater than seven").

When ppp is executed, there is first created a backtrack point to the second clause, and then the
first clause is executed. If the test "X > 7" succeeds then the cut "!" is reached. This cut "!" will
remove the backtrack point to the second clause.
Example
clauses
ppp() :qqq(X),
X > 7,
!,
write("Found one").
ppp() :write("Did not find one").
clauses
qqq(3).
qqq(12).
qqq(13).

When ppp is executed it first creates a backtrack point to the second ppp clause and then qqq is
called. The qqq will create a backtrack point to the second qqq clause and execute the first clause,
thereby returning the value 3. In ppp variable X is bound to this value and then compared to 7. This
test fails and, therefore, the control backtracks to the second clause of qqq.
Before executing the second clause a new backtrack point to the third clause of qqq is created and
then the second clause returns 12.
This time the test against 7 succeeds and, therefore, the cut is executed. This cut will remove both
the backtrack point left in qqq as well as the backtrack point to the second clause of ppp.
Cut Scopes
A cut scope is a scope to which the effect of a cut is limited. Meaning that if a cut is met within a
cut scope then only backtrack points within that scope are discarded, while backtrack points outside
(i.e. prior to) the cut scope remains.
Language Reference

Page 113 / 167

Visual Prolog 7.5 - Language Reference


The clauses of a predicate is a cut scope. Meeting a cut will (at most) discard the backtrack points
that was created after entrance to the predicate. Backtrack points created before entrance to the
predicate will remain.
Example
clauses
aaa() :- p1_nd(), qqq().
qqq() :- p2_nd(), !.

aaa calls p1_nd, which leaves a backtrack point, and then it calls qqq. qqq calls p2_nd, which also
leaves a backtrack point. Then we meet a cut. This cut is in the cut-scope of the qqq predicate, so
it is only the backtrack point in p2_nd which is discarded, the one in p1_nd remains.
Several terms introduce cut scopes (see the respective terms: list comprehension, if-then-else,
foreach). Here we will use if-then-else to illustrate the effect of cut scopes. Consider the schematic
if-then-else term:
if Cond then T1 else T2 end if

The condition Cond is a cut-scope, meaning that a cut inside Cond will only have effect inside
Cond. Cuts inside T1 and T2, on the other hand, have effect outside the if-then-else statement.
Consider this code fragment:
X = getMember_nd([3,1,2]),
if X = getMember_nd([3,3]), ! then
write(X)
else
!
end if,
fail

getMember_nd is a nondeterministic predicate. The evaluation of this code will go as follows. First X
is bound to 3 and getMember_nd leaves a backtrack point (so that X can later become 1 and then
even 2).
Then we evaluate the condition in the if-then-else term. The first part of this condition succeeds as
3 is a member of [3,3]. The first part also leaves a backtrack point, so that it can be examined
whether X is a member several times.
Now we meet a cut. This cut is inside the condition part of an if-then-else statement, so it only has
local effect, meaning that it only discards the backtrack point in the second getMember_nd, but
leaves the backtrack point in the first getMember_nd predicate.
The whole condition succeeds and we enter the then-part and write out "3".
After the if-then-else we meet fail, which backtracks us to the first getMember_nd.
getMember_nd then binds X to 1, and leaves a backtrack point (so that X can later become 2).
Then we evaluate the condition in the if-then-else term. The first part of this condition fails as 1 is
Language Reference

Page 114 / 167

Visual Prolog 7.5 - Language Reference


not a member of [3,3]. So we enter the else-part.
Here we meet a cut. This cut is in the else-part of a conditional term so it has effect outside the ifthen-else term and subsequently it discards the backtrack point in the first getMember_nd.
When we meet the fail after the if-then-else term there are no more backtrack points in the code
and it will fail. So all in all X never becomes 2.

List Comprehension
ListComprehensionTerm :
[ Term || Term ]

The list comprehension term is a list expression. Consider this schematic term:
[ Exp || Gen ]

Gen is (typically) a nondeterm term. Exp is evaluated for each solution of Gen, and the resulting
Exp's are collected in a list. The Exp corresponding to the first solution of Gen is the first element in
the list, etc. This list is the result of the list comprehension term. Exp must be procedure (or
erroneous). Both Exp and Gen are cut scopes.
The list comprehension (normally) reads: The list of Exp's such that Gen.
Example
[ X || X = getMember_nd(L), X mod 2 = 0 ]

This reads the list of X's such that X is in L and X is even. So this expression is the even numbers of
L.
Example
[ X + 1 || X = getMember_nd(L), X mod 2 = 0 ]

Here the collected expression is more complex. This makes say the term more awkward:
"the list of (X+1)'s such that ..."
This expression again finds the even elements in L, but the resulting list contains all these values
incremented.
This term is completely equivalent to this term:
[ Y || X = getMember_nd(L), X mod 2 = 0 , Y = X+1 ]

This term is easier to say:

Language Reference

Page 115 / 167

Visual Prolog 7.5 - Language Reference


"The list of Y's such that (there exists an) X which is member of L, and which is even, and Y is
X+1."

Object Member Access


Whenever we have a reference to an object, we can access the object member predicates of that
object.
MemberAccess:
Term : Identifier

(Currently, the term must be a variable or a fact variable).


The identifier must have the type of the term.
Inside an implementation object member predicates can be invoked without reference to an object,
because "This" is subsumed, see Scoping.

Domain, Functor, and Constant Access


Domains, functors, and constants are all accessed as if they are class members. Even if they are
declared in an interface. This means that when they are qualified, then they are always qualified with
class/interface name and a double colon.

foreach
ForeachTerm :
foreach Term d o Term end foreach

Consider the schematic foreach term:


foreach Gen d o Body end foreach

Gen is (typically) a nondeterm term. Body is evaluated for each solution of Gen. If/when Gen fails
the foreach-term succeeds without evaluating Body. Body must be procedure (or erroneous).
Gen and Body are both cut scopes.
The schematic foreach term resembles a fail loop:
Gen,
Body,
fail

The main (and important) difference is that a foreach-term succeeds after the iteration, whereas a
fail loop fails. As a result foreach-terms can be followed by other terms and they can be properly
nested.
Example

Language Reference

Page 116 / 167

Visual Prolog 7.5 - Language Reference


foreach L = list::getMember_nd(LL) d o
write("<< "),
foreach X = list::getMember_nd(L) d o
write(" ", X)
end foreach,
write(" >>\n")
end foreach.

LL is supposed to be a list of lists. The outer foreach-loop iterates L through this list, so each L is a
list. The inner foreach-loop iterates X through the elements of L.
There are a number of things to notice:
l
l

There is no comma before the keywords "do" and "end foreach".


The Body of a foreach-term is a cut scope, so a cut meet in the body will not influence the
iteration.
A foreach-term always succeeds (or raises an exception), and no extra variables are bound
after the evaluation of a foreach-term. Therefore, a foreach-term can only be used for its
side effects.

Example
clauses
p(L) :foreach X = list::getMember_nd(L) d o
stdio::write(X, "\n")
end foreach,
stdio::write("Finished\n").

Foreach can be used instead of traditional "fail-loops":


clauses
p(L) :X = list::getMember_nd(L),
stdio::write(X, "\n"),
fail.
p(_L) :stdio::write("Finished\n").

In this context it is advantageous that Body must be a procedure, because in a "fail-loop" the body
may accidentally fail before reaching the fail in the loop. Another advantage is that a foreach loop
succeeds when the loop is finished, whereas a fail loop fails, so that execution can continue in the
same clause. Also notice that foreach can be properly nested:
clauses
p(LL) :foreach L = list::getMember_nd(LL) d o
foreach X = list::getMember_nd(L) d o
stdio::write(X, "\n")
end foreach,
stdio::write("Finished a list\n")
end foreach,
stdio::write("Finished all lists\n").

if-then-else
Language Reference

Page 117 / 167

Visual Prolog 7.5 - Language Reference


if-then-else can be used both as a statement and as an expression.
if-then-else (statement)
The if-then-eslse statement conditionally executes a group of statements.
IfThenElseTerm:
if Condition then Term Elseif-list-opt Else-opt end if

Elseif:
elseif Condition then Term

Else:
else Term

The following two terms are equivalents.


if Cond1 then T1 elseif Cond2 then T2 else T3 end if

if Cond1 then T1 else


if Cond2 then T2 else T3 end if
end if

Consider the schematic if then else term:


if Cond then T1 else T2 end if

First Cond is evaluated, if it succeeds then T1 is evaluated otherwise T2 is evaluated.


Cond is followed by an implicit cut, which turns:
l
l

a nondeterm condition into a determ condition and


a multi condition into a procedure.

Cond is a cut-scope (see Cut Scopes).


Example
clauses
w(X) :if X div 2 = 0 and X > 3 then
write("X is good")
else
write("X is bad"),
nl
end if,
nl.

There are several things to notice about this example:


l

You can use "and" and "or" logical operators and other "complex" terms in all three sub-terms.

Language Reference

Page 118 / 167

Visual Prolog 7.5 - Language Reference


l

There is no comma before the keywords "then", "elseif", "else", and "end if".

For readability sake, we always recommend using "or" instead of ";". Likewise we also recommend
using "and" (instead of ",") when it (as in the condition above) represents a logical "condition" rather
than a "sequentation".
Leaving out the else-part is just shorthand for writing that else succeed, i.e.
if Cond then Term end if

is short-hand for
if Cond then Term else succeed end if

if-then-else (expression)
The if-then-else expression conditionaly evaluates excressions.
Syntactically it is same as the if-then-else statement, but and the terms in the branches must be
expressions and the entire if-then-else expression will itself evaluate to a value.
The shorhand writings that leave out the else-part does not make sense for the expression.
Example
clauses
w(X, Y) :Min = if X < Y then X else Y end if,
writef("Theminimumis:%\n", Min).

The if-then-else expression above evaluates to X if X is less than Y else it evaluates to Y. Min is
bound to the resulting value.

try-catch-finally
The try-catch-finally statement provides means for dealing with exceptions that may occur in a given
block of code.
TryCatchTerm:
try Term CatchFinally-list end try

CatchFinally: one of
catch Variable d o Trap-Handler
finally Finally-Handler

Handler:
Term

A try-construction thus have a Term and a list of catch and finally handlers.

Language Reference

Page 119 / 167

Visual Prolog 7.5 - Language Reference


The Term and the handlers are not allowed to leave backtrack points (i.e. they cannot have mode
multi or nondeterm).
A try-construction with more than one handler is equivalent to nesting several try-constructions with
one handler each. I.e. the following term:
try
Body
catch Var1 d o
Handler1
finally
Handler2
catch Var2 d o
Handler3
end try

Is equivalent to these nested terms:


try
try
try
Body
catch Var1 d o
Handler1
end try
finally
Handler2
end try
catch Var2 d o
Handler3
end try

try-catch
Consider the try-catch construction
try
Body
catch Var d o
Handler
end try

First Body is evaluated.


If Body fails or succeeds the whole try construction fails or succeeds, respectively. I.e. if Body does
not terminate with an exception the try construction corresponds to evaluating Body.
If Body terminates with an exception, then the exception is caught by the catch handler. Meaning
that first Var is bound to the exception (in PFC context the exception will be a traceId) and then
Handler is evaluated. In this case the construction behaves as if Handler is evaluated with Var
bound to the caught exception.
Notice, that no bindings are made by Body if it terminates with an exception.
Example Handle the situation where a file cannot be read:

Language Reference

Page 120 / 167

Visual Prolog 7.5 - Language Reference


clauses
read(Filename) = Contents :try
Contents = file::readFile(Filename)
catch TraceId d o
stdio::writef("Couldnotreadthefile:%\n", Filename),
exceptionDump::dumpToStdio(TraceId),
Contents = ""
end try.

First Contents = file::readFile(Filename) is evaluated, if that does not terminate with an


exception read returns the contents of the file.
If it raises an exception the handler is evaluated with TraceId bound to the exception. So in this
case a message is written to stdio and then the exception is dumped to stdio, and finally Contents
is set to the empty string which is returned as result.
try-finally
Consider the try-finally construction:
try
Body
finally
Handler
end try

The purpose of the construction is to evaluate the Handler after the Body no matter how the Body
terminates, i.e. whether it succeeds, fails or terminates with an exception (it cannot leave backtrack
points).
The evaluation is like this
First Body is evaluated.
l
l
l

If Body succeeds: Handler is executed and the try-finally construction succeeds.


If Body fails: Handler is executed and the try-finally construction fails.
If Body terminates with an exception Exn: Handler is executed and the try-finally
construction terminates with the exception Exn.

Example Ensure that an odbcStatement is free'd after use:


clauses
tryGetName(Connection, PersonId) = Name :Stmt = odbcStatement::n e w(Connection),
try
Stmt:setParameterValue(1, core::integer(PersonId)),
Stmt:execDirect("select name from person where id=?"),
Stmt:fetch(),
Name = Stmt:getParameterValue_string(1)
finally
Stmt:free()
end try.

The Stmt is free'd also if fetch fails, or if something terminates with an exception.
Language Reference

Page 121 / 167

Visual Prolog 7.5 - Language Reference

Language Reference

Page 122 / 167

Visual Prolog 7.5 - Language Reference


Conversion
View and Construction Types
An interface defines a type of objects, all objects that supports the interface have that type. In the
sequel we shall use the term the object type as synonym for the term the type defined by the
interface.
Since interfaces define types, these types can be used as formal type specifiers in predicate and fact
declarations and in domain definitions.
Since an object have the object type of any interface it supports, it can be used as an object of any
of these types. I.e. the type of objects is converted to any supported object type. As described
below the conversion is in many cases performed automatically.
So the same object can be viewed as having different types in different contexts. The type with
which an object is viewed is called its view type, whereas the type of the class that constructed
the object is called the construction type or definition type. The construction type is also a view
type.
Type Conversion
As mentioned above objects can be used as having the type of any supported interface. This section
describes how conversions between various supported types is handled.
Conversion Upwards
If some term is statically typed to some type T1 and T1 is declared to support T2 then it is obvious
that any object referenced by the variable will indeed support T2. So upward support information is
statically known. Subsequently all conversions upwards in the support hierarchy is performed
automatically.
Example Assume the existence of the interface bb which supports an interface aa and the class
bb_class with construction type bb. Consider the following code:
implement ...
predicates
ppp : (aa AA).
clauses
... :BB = bb_class::n e w(), % (1)
ppp(B). % (2)
clauses
ppp(AA) :- % (3)
...
BB = convert(bb,AA), % Conversion possible since definition type of AA is bb
...

In the line marked (1) we create a bb_class object: the object has construction type bb. The
variable BB is a reference to this new object. BB provides the view type bb on the object. In the
line marked (2) the object is passed to ppp as an aa object. The conversion from view type bb to
view type aa is performed implicitly. When the object reaches the line marked (3) it has view-type
aa, though the construction type is still bb.

Explicit Conversion
Language Reference

Page 123 / 167

Visual Prolog 7.5 - Language Reference


Explicit conversion is performed by calling a conversion predicate.
Several conversion predicates are available.
Checked Conversion
The predicates convert/2-> and tryConvert/2-> are used to perform safe conversion from one type
to another type.
Neither predicate can be given a real declaration, but here are pseudo declarations for them
predicates
convert : ("type" Type, _ Value) -> Type ConvertedValue.
tryConvert : ("type" Type, _ Value) -> Type ConvertedValue determ.

Both convert/2-> and tryConvert/2-> take a "type" as the first argument and a value of any type as
the second argument and will then return the converted value as the result.
convert/2-> will raise an exception if the conversion is impossible, while tryConvert/2-> simply fails in
that case.
Notice that the use of convert/2-> and tryConvert/2-> is always superfluous, if the source type is a
subtype of the target type, because then the conversion will be performed implicitly.
convert/2-> and tryConvert/2-> can be used in the following situations:
l
l

converting from one number domain to another number domain


converting an object to another type

The compiler may complain (but does not have to) if it can determine that a conversion can never
succeed, for example if attempting to convert between number domains that does not have
overlapping ranges.
Conversion Downwards
When an object is converted to a super type (i.e. to a supported interface), then information about
the object is "forgotten". Notice that the capabilities are not really lost they are just not visible in the
context where the object is seen with a less capable interface.
In many situations it is necessary to restore the actual capabilities of the objects. Therefore, we
need to be able to convert them downward as well as upwards.
Downward conversion cannot (in general) be validated statically. Therefore, it is necessary to use
explicit conversion when restoring "lost" interfaces.
Example
While it is extremely simple to make sensible illustration of type conversions up in the supportshierarchy, it requires a "real" example to illustrate sensible use of downward conversion. Therefore we
shall present a more "real" example here.
Assume that we want to implement "sets of homogeneously typed objects". I.e. sets of objects which
Language Reference

Page 124 / 167

Visual Prolog 7.5 - Language Reference


all supports a certain view type. We know that we will need such sets for several types of objects.
Therefore we want to make our implementation in a way, which can easily be adopted to many
different types of objects, but yet preserve the homogeneity of the contained objects.
Our approach is fairly standard: we make the actual implementation of the "set" based on the object
type, which any object supports. And then construct the more specific versions of "sets" by means of
a thin layer, which will convert between the actual type and object. We shall not show the actual
implementation of object sets, we shall merely assume that it exists in the shape of the following
class and interface:
interface objectSet
predicates
insert : (object Elem).
getSomeElem : () -> object determ.
...
end interface
class objectSet_class : objectSet
end class

Now assume that we have some object type myObject and that we want to create the
corresponding "set" class myObjectSet_class. We declare myObjectSet_class as following:
interface myObjectSet
predicates
insert : (myObject Elem).
getSomeElem : () -> myObject determ.
...
end interface
class myObjectSet_class : myObjectSet
end class

I.e. myObjectSet has all the predicates of objectSet but every occurrence of object is replaced
with myObject. The implementation of myObjectSet_class inherits from objectSet_class, this
embedded/inherited objectSet will carry the members of the set. The implementation will fulfill the
following invariant: The embedded objectSet will only contain objects of type myObject (even
though they "technically" have type object).
The implementation looks as follows:
implement myObjectSet_class
inherit objectSet_class
clauses
insert(Elem) :objectSet_class::insert(Elem). % (1)
getSomeElem() = Some :SomeObject = objectSet_class::getSomeElem(), % (2)
Some = convert(myObject, SomeObject). % (3)
...
end implement

In the line marked (1) Elem is automatically converted from type myObject to object. In the line
marked (2) we retrieve an object from the embedded object set. Technically this object has type
object. But from our invariant we know that the object also supports myObject. Subsequently, we
know that we can safely restore the myObject interface. This is explicitly done in the line marked
(3).

Language Reference

Page 125 / 167

Visual Prolog 7.5 - Language Reference


Private and Public Types
When an object is created with a constructor it is returned with the construction type. Such an
object can automatically be converted to any supported interface and explicitly back again.
Even if the class that implements the object have stated further supported interfaces privately it is
impossible to convert the "public" object to any of these private types.
In the implementation however the object can be accessed with any privately supported type.
Furthermore "This" can be handed outside the implementation with any of these privately supported
types.
Such a "private" version of an object can also be converted implicitly upwards in its hierarchy and
explicitly downwards again. In fact such a "private" object can be converted explicitly to any publicly
or privately supported interface.
So an object have two views the public view and the private view. The private view includes the
public type. The object cannot be converted from one view to another, but since the private view
includes the public type, the private view can be converted to any supported type whatsoever.
Unchecked Conversion
The predicate uncheckedConvert/2-> is used to perform unsafe conversions based on memory
representation. The predicate does not modify memory in any way, it simply forces the compiler to
interpret that piece of storage with another type.
Notice this predicate is highly unsafe and should be used with maximum precautions.
The predicate is intended to be used when interfacing to foreign languages, in order to interpret the
memory images these foreign languages uses.
uncheckedConvert/2-> can only be used on pieces of memory that have exactly the same bit-size.
However many kinds of data are represented by a pointer and such data have the same bit-size.
predicates
uncheckedConvert : ("type" Type, _ Value) -> Type ConvertedValue.

Example
predicates
interpretBufferAsString : (pointer BufferPointer) -> string Value.
clauses
interpretBufferAsString(BufferPointer) = uncheckedConvert(string, BufferPointer).

This predicate will interpret (convert) a buffer represented by a pointer as a string.


This is only sound if the memory block has the correct representation to be a string.

Language Reference

Page 126 / 167

Visual Prolog 7.5 - Language Reference


Exception Handling
This section describes the low level constructions for dealing with exceptions in Visual Prolog. PFC
does however put a higher level layer on top of this low level mechanisms (see the tutorial Exception
Handling).
The basic part of the exception handling system is based on the built-in predicate errorExit/1 and the
try-catch language construction.
l
l

errorExit/1 raises an exception


try-catch sets an exception handler for a certain computation.

When errorExit/1 is called the currently active exception handler is invoked. This exception handler is
executed in its original context, i.e. in the context where it was set rather than in the context where
the exception is raised.
The argument that errorExit/1 is invoked on is transferred to the exception handler. This argument
must somehow provide the needed description of the exception.
Together with additional runtime routines, it is possible to build high-level exception mechanisms on
top of this system.
It is however out of the scope of this document to describe runtime system access routines.
It is likewise out of the scope of this document to describe how the runtime system deals with
exceptions occurring inside the runtime system.
The first argument of try-catch is the term to execute with new exception handler. The second
argument must be a variable. This variable will be bound to the value errorExit/1 is invoked on, if it is
invoked while this exception handler is active. The third argument is the exception handler, which will
be invoked if errorExit/1 is called while this exception handler is active.
The exception handler can access the variable stated in the second argument thereby examining the
exception that was raised.
Example
clauses
p(X) :try
dangerous(X)
catch Exception d o
handleDangerous(Exception)
end try.

If an exception is raised while executing dangerous, then Exception will be bound to the exception
value, and control will be transferred to the third argument of try-catch. In this case Exception is
passed to handleDangerous.

Language Reference

Page 127 / 167

Visual Prolog 7.5 - Language Reference


Built-in entities
Visual Prolog contains an embedded hidden class, which provides declarations and implementations to
all built-in constants, domains, and predicates.
These built-in constants, domains, and predicates can be used both during compilation (for example,
in #if ... constructions) and in implementations (which are supported for runtime).
Each compilation unit implicitly contains the declaration of this embedded hidden class. To
disambiguate from other entities with the same name you can use "::" before names of built-in items.
Notice that the clause variable This is automatically defined in the clauses for object predicates.

Operators
See also Operators.
Operator

Description

Remark
Not defined for 64 bit
integral numbers

Power operation

- (unary)

Unary minus

*, /

Multiplication and division

div, mod

The quotient and remainder of an integral division


rounded towards minus infinity

Not defined for real's

quot,
rem

The quotient and remainder of an integral division


rounded towards zero

Not defined for real's

+, -

Addition and subtraction

l
l
l
l

The operators are listed from highest to lowest precedence


All division and multiplication operators have same precedence.
The the power operator is right associative
All other operators are left associative.

All binary operators takes two arguments of same base type and returns a value of that base type.
Operands and result may be converted using ordinary subtype rules.
Integral division
div and quot are different integral division operators.
l
l

div rounds towards minus infinite. mod is the remainder corresponding to div.
quot rounds towards zero. rem is the remainder corresponding to quot.

For positive results div and quot have same functionality.


The difference can be seen in this table:
A
15

B A div B A mod B A quot B A rem B


7

-15 7

-3

-2

-1

Language Reference

Page 128 / 167

Visual Prolog 7.5 - Language Reference


15 -7

-3

-6

-2

-15 -7

-1

-1

Constants
compilation_date

Compilation date.

compilation_time

Compilation time.

compiler_buildDate Build date of a compiler.


compiler_version

A compiler version.

maxFloatDigits

Defines the maximal value of "digits", which is supported by the compiler.

null

The default NULL pointer.

nullHandle

A special constant of a handle type with the zero value.

invalidHandle

A special constant of a handle type with the invalid (-1) value.

platform_bits

Defines the digital capacity of compilation platform.

platform_name

Defines the target platform name.

compilation_date
Compilation date. Here Y Y Y Y means the number of a year, MM means a month number, and DD means
a day number.
compilation_date : string = "YYYY-MM-DD".

compilation_time
Compilation time. Here HH means hours, MM means minutes, and SS means seconds.
compilation_time : string = "HH-MM-SS".

compiler_buildDate
Build date of the compiler.
compiler_buildDate : string = "YYYY-MM-DD HH-MM-SS".

compiler_version
A compiler version. This value depends upon the compiler version.
compiler_version = 6003.

maxFloatDigits
Defines the maximal value of "digits", which is supported by the compiler.
Language Reference

Page 129 / 167

Visual Prolog 7.5 - Language Reference


maxFloatDigits = 16.

null
A special constant of a pointer type with the zero value.
null : pointer = uncheckedConvert(pointer, 0).

nullHandle
A special constant of a handle type with the zero value.
nullHandle : handle = uncheckedConvert(handle, 0).

invalidHandle
A special constant of a handle type with the invalid (-1) value.
invalidHandle : handle = uncheckedConvert(handle, -1).

platform_bits
Defines the digital capacity of compilation platform.
platform_bits = 32.
or
platform_bits = 64.

platform_name
Defines the target platform name.
platform_name : string = "Windows 32bits".
or
platform_name : string = "Windows 64bits".

Domains
any

Universal term type.

char

Wide (two-bytes) character.

string

Wide zero-terminated sequence of wide characters.

string8

Zero-terminated sequence of ASCII (one-byte) characters.

symbol

Wide zero-terminated sequence of wide characters.

binary

Sequence of bytes.

Language Reference

Page 130 / 167

Visual Prolog 7.5 - Language Reference


binaryNonAtomic Sequence of bytes.
integer

Integral signed integer number.

integer64

Integral signed integer number.

integerNative

Integral signed integer number.

unsigned

Integral unsigned integer number.

unsigned64

Integral unsigned integer number.

unsignedNative

Integral unsigned integer number.

real

Float-pointing number.

real32

Float-pointing number.

pointer

pointer to a memory address.

handle

a handle (e.g. native file and windows handles).

boolean

Boolean values.

factDB

Descriptors of named internal databases.

compareResult

Values of comparison result.

any
Universal term type.
any

The values of this domain are any terms. Such a value contains the reference to the term type library
and a term itself.
char
Wide character.
char

The values of this domain are UNICODE characters. Implemented as 2 unsigned bytes.
Only assignment and comparison (in the lexicographical sense) operations are applied to the values of
this domain. The image of a character has the following syntax:
Char_image :
' Char_value '
Char_value :
Letter
Digit
Graphical_symbol
\ Escape_seq
Escape_seq:
t
n
r
\
'
"
Language Reference

Page 131 / 167

Visual Prolog 7.5 - Language Reference


u <HHHH>

In the syntax above HHHH correspond to 4 hexadecimal digits. Also, the backslash symbol and the
single quote can be represented by an escape-sequence only.
compareResult
The compareResult is a built-in domain. It is used to define a comparison result. The built-in
compare/2-> predicate's result is compareResult domain.
domains
compareResult = less; equal; greater.

string
Wide zero terminated sequence of wide characters.
string

A string is a sequence of UNICODE characters. It's implemented as a pointer to the wide zeroterminated array of wide characters. Only assignment and comparison (in the lexicographical sense)
operations are applied to values of this domain.
In source code a string literal can be specified as a set of sequences of characters surrounded by the
double quotes.
StringLiteral:
StringLiteralPart-list

StringLiteralPart :
@" AnyCharacter-list-opt "
" CharacterValue-list-opt "

A string literal consists of one or more StringLiteralPart's, which are concatenated.


StringLiteralPart's starting with @ does not use escape sequences, whereas StringLiteralPart's
without @ uses the following escape sequences:
l
l
l
l
l
l
l

\\ representing \
\t representing Tab-character
\n representing newline-character
\r representing carriage return
\' representing single quote
\" representing double quote
\u followed by exactly four HexadecimalDigit's representing the Unicode character
corresponding to the digits.

The double quotes in the string can be represented by the escape-sequence only (the single quote
can be represented both with an escape-sequence and a graphical symbol).
string8
Language Reference

Page 132 / 167

Visual Prolog 7.5 - Language Reference


A term of the built-in string8 domain is a sequence of ASCII (one-byte) characters. It is implemented
as a pointer to the zero terminated array of ASCII characters. Only assignment and comparison for
equality (in the lexicographical sense) operations are applied to the values of this domain. Currently
no literals are allowed for this domain.
symbol
Wide zero terminated sequence of wide characters.
symbol

Similar to a string, a symbol is also a sequence of the UNICODE characters. It's implemented as a
pointer to an entry in a symbol table that contains strings. The operations that can be applied to
symbols are the same as for strings.
The image of a symbol is represented with a <string_literal> (any string surrounded by the double
quotes).
Symbols and strings are largely interchangeable but they are stored differently. Symbols are kept in a
look-up table and their addresses, rather than the symbols themselves, are stored to represent
objects. This means that symbols can be matched very quickly and, if a symbol occurs repeatedly in
a program, it can be stored very compactly. Strings are not kept in a look-up table. Visual Prolog
examines strings character-by-character whenever they are to be matched.
binary
Sequence of N bytes.
binary

Values of this domain are used for holding binary data. A binary value is implemented as a pointer to
the sequence of bytes that represents the contents of a binary term.
The length of a binary term is situated in the 4 bytes immediately preceding this sequence of bytes.
The 4 bytes contains:
TotalNumberOfBytesOccupiedByBinary = ByteLen + 4

where ByteLen - is the length of the binary term and 4 is number of bytes occupied by size field.
Only assignment and comparison operations are applied to values of binary domain.
Two binary terms are compared in the following way:
l
l

If they are of different sizes, the bigger is considered larger.


Otherwise, they are compared byte by byte, as unsigned values. Comparison stops when two
differing bytes are found and the result of their comparison is the result of the comparison of
the binary terms. Two binary terms are equal if they have the same sizes and all bytes are
equal.

Language Reference

Page 133 / 167

Visual Prolog 7.5 - Language Reference


The text syntax for binary images is determined by the Binary rules:
Binary :
$ [ Byte_value-comma-sep-list-opt ]
Byte_value :
Expression

Each expression should be calculate on compiling time and its value should be in the range from 0 to
255.
binaryNonAtomic
Sequence of N bytes.
binaryNonAtomic

Same as binary, but can contain pointer.


integer
Integral signed number.
integer

Values of this domain occupy 4 bytes. Arithmetic operations (+, -, /, *, ^), comparison, assignment,
div/2->, mod/2->, quot/2->, and rem/2-> operations are applied to values of this domain.
The permitted number range is from -2147483648 to 2147483647.
The syntax for the integer literal is determined by the Integer rule:
Integer :
Add_operation-opt
Add_operation-opt
Add_operation-opt
Add_operation :
+
Oct_number :
Oct_digit-list
Oct_digit : one of
01234567
Dec_number :
Dec_digit-list
Dec_digit : one of
Oct_digit 8 9
Hex_number :
Hex_digit-list
Hex_digit : one of
Dec_digit a b c d e

0o Oct_number
Dec_number
0x Hex_number

fABCDEF

integer64
Integral signed number.
Language Reference

Page 134 / 167

Visual Prolog 7.5 - Language Reference

integer64

Values of this domain occupy 8 bytes.


The permitted number range is from -2^63 = -9,223,372,036,854,775,808 to 2^63-1 =
9,223,372,036,854,775,807.
The syntax for integer64 literal is the same as Integer rule.
The set of operations for integer64 is similar to the one for Integer.
integerNative
Integral signed number.
integerNative

unsigned
Integral unsigned number.
unsigned

Values of this domain occupy 4 bytes. Arithmetic operations (+, -, /, *, ^), comparison, assignment,
div/2->, mod/2->, rem/2->, and quot/2-> operations are applied to values of this domain.
The permitted number range is from 0 to 4294967295.
The syntax for unsigned number images is the same as for integer numbers. The usage of minus
sign (UnaryMinus) is not allowed for an image of an unsigned number.
unsigned64
Integral unsigned number.
unsigned64

Values of this domain occupy 8 bytes.


The permitted number range is from 0 to 2^64-1 = 18,446,744,073,709,551,615.
The syntax for unsigned64 number images is the same as for integer64 numbers. The usage of
minus sign (UnaryMinus) is not allowed for an image of an unsigned64 number.
The set of operations for unsigned64 is similar to the one for Unsigned.
unsignedNative
Language Reference

Page 135 / 167

Visual Prolog 7.5 - Language Reference


Integral unsigned number.
unsignedNative

real
Float-pointing number.
real

Values of this domain occupy 8 bytes. This numerical real domain is introduced for the user's
convenience only. All arithmetic, comparison, and assignment operations are applied to values of real
domain.
The permitted number range is -1.7e+308 to 1.7e+308. Values from integral domains are
automatically converted to real numbers when necessary.
The syntax for the floating-point number literal is determined by the Real rule:
Real :
Add_operation-opt Fraction Exponent-opt
Fraction :
Dec_number Fractional_part-opt
Fractional_part :
. Dec_number
Exponent :
Exp Add_operation-opt Dec_number
Exp :
e
E
Add_operation :
+
Dec_number :
Dec_digit-list
Dec_digit : one of
0123456789

real32
Float-pointing number.
real32

Values of this domain occupy 4 bytes. This numerical real32 domain is introduced for the user's
convenience only. All arithmetic, comparison, and assignment operations can be applied to values of
real32 domain.
The permitted number range is -3.4e+38 to 3.4e+38.
The syntax of real32 literals is the same as real lietrals.
pointer
Language Reference

Page 136 / 167

Visual Prolog 7.5 - Language Reference


A pointer to a memory address.
pointer

A pointer directly corresponds to memory addresses. Only the equality operation can be applied to
the values of this domain. There is a built-in null constant for this type
handle
A handle is used for Windows API function call. Values of this domain has the same size as a pointer
(i.e. 4 on 32bit platfor and 8 on 64bit platform).
There are no operations for this domain and cannot be converted (except uncheckedConvert) to/from
other domains.
There is a built-in nullHandle and invalidHandle constant for this type
boolean
Boolean values.
boolean

This domain is introduced for the user convenience only. It is treated as usual compound domain with
the following definition:
domains
boolean = false(); true().

factDB
Descriptors of named internal databases.
factDB

This domain has the following hidden meta-declaration:


domains
factDB = struct @factdb( named_internal_database_domain, object ).

All user-defined names of facts sections are the constants of this domain. The compiler automatically
builds the corresponding compound terms from such constants whenever it's in need. At the runtime
the 1st field of this structure contains the address of the corresponding domain descriptor and the
2nd field contains either zero (for class facts sections) or pointer to an object (i.e. This, for object
facts sections).

Predicates
Language Reference

Page 137 / 167

Visual Prolog 7.5 - Language Reference


and/2
,/2

Term "and"

assert/1

Insert the specified fact at the end of the matched internal facts
database.

asserta/1

Insert a fact at the beginning of the matched internal facts database.

assertz/1

Insert a fact at the end of the matched internal facts database.

bound/1 determ

Test whether the specified variable is bound to a value.

class_name/0->

This compile time predicate returns the string ClassName that represents
the name of the current interface or class.

compare/2->

Returns the result of the variables' comparison.

convert/2->

Checked term conversion.

digitsOf/1->

Returns precision of the specified floating-point domain.

errorExit/1 erroneous

Performs a run-time error with the specified return code ErrorNumber


and sets the internal error information.

fail/0 failure

Invoke backtracking.

free/1 determ

Check whether a variable is free.

fromEllipsis/1->

Creates the list of terms of the universal type any from the EllipsisBlock.

hasDomain/2
hasDomain/2->

Declares/restricts the type of a variable or value.

in/2 determ
in/2 nondeterm

Infix operator "in" (in-test and in-iterator).

isErroneous/1 determ

Returns the lower bound value of the specified numeric domain.

lowerBound/1->

Returns the lower bound value of the specified numeric domain.

maxDigits/1->

Retrieves the value of digits (precision) of the basic domain


corresponding to the specified floating-point domain domainName.

not/1 determ

Negate the result (success/fail) of subgoal.

or/2
;/2

Nondeterministic term "or"

orelse

Deterministic term "or"

predicate_fullname/1->

This compile time predicate returns the string PredicateFullName that


represent the name of the predicate in which clause body
predicate_name is called. The returned predicate name is qualified with
a scope name.

predicate_name/1->

This compile time predicate returns the string PredicateName that


represent the name of the predicate in which clause body
predicate_name is called. The returned predicate name is not qualified
with a scope name.

programPoint/0->

This compile time predicate returns the programPoint corresponding to


the place where it is called.

retract/1 nondeterm

Remove a matched fact from the matched internal facts database.

retractall/1

Remove all matching facts from the matched internal facts database.

retractFactDb/1

Remove all facts from the specified named internal facts database.

sizeBitsOf/1->

Retrieves the number of bits occupied in memory by an entity of the


specified domain DomainName.

Language Reference

Page 138 / 167

Visual Prolog 7.5 - Language Reference


sizeOf/1->

Retrieves the number of bytes occupied in memory by the specified term.

sizeOfDomain/1->

Retrieves the number of bytes occupied in memory by the entity of the


specified domain DomainName.

sourcefile_lineno/0->

Returns the current line number in the source file processed by the
compiler .

sourcefile_name/0->

Returns the name of the source file processed by the compiler.

sourcefile_timestamp/0- Returns the string representing the date and time of the source file
>
processed by the compiler.
succeed/0

The predicate succeed/0 will always succeed.

toAny/1->

Converts the specified Term to the value of the universal term type
any.

toBinary/1->

Converts the specified Term to the binary representation.

toBoolean/1->

The purpose of this meta-predicate is to convert the deterministic call


(to a predicate or fact) to the procedure that returns the value of
boolean domain.

toEllipsis/1->

Creates the EllipsisBlock from the list of any type values.

toString/1->

Converts the specified Term to the string representation.

toTerm/1->
toTerm/2->

Converts the string/binary representation of the specified term SrcTerm


into representation corresponding to the domain of PrologTerm variable
of the return value.

Converts the string/binary representation of the specified term SrcTerm


tryToTerm/1-> determ
into representation corresponding to the domain of PrologTerm variable
tryToTerm/2-> determ
of the return value.
Checks whether the input term InputTerm can be strictly converted into
tryConvert/2-> determ the specified domain returnDomain and returns the converted term
ReturnTerm.
uncheckedConvert/2->

Unchecked conversion of domains.

upperBound/1->

Returns the upper bound value of the specified numeric domain.

The following predicates are deprecated:


finally/2

Use try ... finally ... end try instead.

findall/3

Use list comprehension [...||...] instead

trap/3 determ Use try ... catch V do ... end try instead
and
See and (,).
assert
assert : (<fact-term> FactTerm).

Insert the specified fact at the end of the matched internal facts database
assert(Fact) inserts Fact in the matched internal facts database after any other stored facts for
Language Reference

Page 139 / 167

Visual Prolog 7.5 - Language Reference


the corresponding database predicate. Fact must be a term belonging to the domain of an internal
facts database. assert/1 applied to a single fact changes the existing instance of a fact to the
specified one. assert/1 has the same effect as assertz/1. See also asserta/1.
Notice that the combination of retract/1 and assert/1 like the following can lead to endless loop:
loop() :retract(fct(X)),
...
% creating Y from X
assert(fct(Y)),
fail.

The problem is that the retract in first line will eventually retract the fact asserted in the last line,
because that fact is inserted last in the fact chain.
Exceptions:
l

Attempt to assert a second instance to a fact declared as determ.

asserta
asserta : (<fact-term> FactTerm).

Insert a fact at the beginning of the matched internal facts database.


The asserta(Fact) predicate inserts a Fact in the matched internal facts database before any other
stored facts for the corresponding predicate. The Fact must be a term belonging to the domain of an
internal facts database. The asserta/1 applied to a single fact changes the existing instance of a
fact to the specified one. See also assert/1 and assertz/1.
Exceptions:
l

Attempt to a fact declared as determ, but the fact instance already exists.

assertz
assertz : (<fact-term> FactTerm).

assertz does exactly the same as the assert/1 predicate.


bound
bound : (<variable> Variable) determ.

Test whether the specified variable is bound to a value.


The bound(Variable) succeeds if Variable is bound and fails if it is free. The bound predicate is
used to control flow patterns and to check the binding of reference variables. The bound predicate
treats the specified Variable as bound if any of it's part is instantiated.

Language Reference

Page 140 / 167

Visual Prolog 7.5 - Language Reference


See also free/1.
class_name
class_Name : () -> string ClassName.

This compile time predicate returns the string ClassName that represents the name of the current
interface or class.
compare
compare : (A Left, A Right) -> compareResult CompareResult.

Comparison of two terms of the same domain, resturns the value of compareResult domain.
CompareResult = compare("bar", "foo")
convert
convert : (<type> Type, Term) -> <type> Converted.

Checked term conversion.


Call-template for this function is:
ReturnTerm = convert(returnDomain, InputTerm)
l

returnDomain: Specifies a domain to which function convert/2-> converts InputTerm. Here


returnDomain must be a name of built-in Visual Prolog domain, an interface domain, a name of
such user defined domain that is synonym to one of built-in Visual Prolog domains, a numeric
domain, binary and pointer domains. The domain name returnDomain must be specified at
compile-time, i.e. it cannot come from a variable.

InputTerm: Specifies the value that must be converted. InputTerm may be any Prolog term
or an expression. If InputTerm is an expression, then it will be evaluated before the
conversion.

ReturnTerm: Returned parameter ReturnTerm will be of returnDomain type.

The convert predicate performs a clean and genuine conversion of the given InputTerm, returning a
new term ReturnTerm of the specified new domain returnDomain. If convert cannot perform the
required conversion, it rises errors. The similar functionality is provided by the tryConvert/2->
predicate, but tryConvert-> fails and does not produce any runtime errors if it cannot perform the
conversion.
Allowed conversions
l
l
l

Between numerical domains.


Between interface types.
Between string and symbol domains.

Language Reference

Page 141 / 167

Visual Prolog 7.5 - Language Reference


l
l
l

From binary to pointer.


For synonyms of mentioned domains.
Between reference domains and corresponding non-reference domains.

The contrast to these is uncheckedConvert/2-> predicate, which performs an unchecked conversion


between terms from any domains, which have the same bit-size.
The convert/2-> (or tryConvert/2->) predicate accomplishes a checked explicit conversion, when
the source and target domains are statically known during the compilation. The result of an explicit
conversion can be one of the following:
l
l

ok the successful conversion to the target domain;


run-time-check the conversion to the target domain with generation of run-time checking for
compatibility;
error the conversion is impossible, error output.

Rules of Checked Explicit Conversions


l

l
l
l

l
l
l

Synonyms of domains are converted using the same rules that are applied to the domains
themselves.
Numerical domains can be converted to the numerical domains only.
Integral constants are the representatives of the anonymous integral domain: [const .. const].
Real constants are the representatives of the anonymous real domain: digits dig [const ..
const], where dig is the number of the digits in mantissa without insignificant zeroes.
A value of the symbol domain can be converted to the string domain and vice versa.
A value of binary domain can be converted to the pointer domain.
The domains that are implicitly introduced for interfaces can be converted only to the interface
domains according to the rules specified below.
All other domains cannot be converted.

Conversions of Numerical Domains


l

The range is considered first during such conversion. If the ranges of source and target do not
intersect, then an error is produced. If the ranges of source and target only partially intersect,
then run-time checking is generated. Also, if one of domains is real and another is an integral
one, then the integer range is converted to the real range before the comparison.
When input term in real and output is integer, then convert/2-> and tryConvert/2->
predicates truncate the input value to the nearest integer value, which is nearer to zero.

Conversions of Interface Types


Predicate convert/2-> allow to convert any object to any interface type. The actual correctness of
such conversion is checked at runtime. When object is created, its type is internally stored, therefore
when the object is passed as argument it still remember about its original type. This original type is
used for checking allowed conversions. The example:
interface x
supports a, b
end interface x

If object is created by class, which implements x interface, and then object is passed as parameter
of type a to some predicate, then it is allowed to convert the object to b type.
Exceptions:
Language Reference

Page 142 / 167

Visual Prolog 7.5 - Language Reference


l
l

Check range error.


Unsupported interface type.

digitsOf
digitsOf : (<real-domain> Domain) -> unsigned.

Returns precision of the specified floating-point domain.


Call-template for this function is:
Precision = digitsof(domainName)

The input parameter domainName of this compiling-time predicate is a floating-point domain, it should
be explicitly specified at compile-time (that is, domainName cannot come from a variable). The
predicate returns the number Precision that was determined by the digits attribute in the domain
declaration.
The compiler guarantees that values of the domain domainName will have at least Precision number
of significant decimal digits.
errorExit
errorExit : (unsigned ErrorNumber) erroneous.

Performs a run-time error with the specified return code ErrorNumber, which can be used in the trycatch-finally.
fail
fail : () failure.

The fail predicate forces failure and, hence, always causes backtracking. A clause that fails (with fail
or for some other reason) cannot bind output arguments.
free
free : (<variableName> Variable) determ.

Check whether a variable is free.


Call-template for this predicate is:
free(Variable)

The free predicate succeeds if the specified Variable is free and fails if Variable is bound. The free
Language Reference

Page 143 / 167

Visual Prolog 7.5 - Language Reference


predicate treats the specified Variable as bound if any of it's part are instantiated.
See also bound/1.
fromEllipsis
fromEllipsis : (...) -> any* AnyTermList.

This predicate creates the list of terms of the universal type any from the EllipsisBlock ... (i.e. from
the special varying parameters block).
Call-template for this function is:
AnyTermList = fromEllipsis(EllipsisBlock )

See also toEllipsis/1->.


hasDomain
hasDomain is not really a predicate, but more a type declaration/restriction. It has two forms a nonfunction for declaring/restricting the type of a variable and a function form for declaring/restricting
the type of a value.
The non-function form is called with a type as first parmeter and a variable as second parameter.
hasDomain : (<type> Type, Type Variable).

The only effect of the call is that the Variable will be restricted to the type Type.
The variable can be free, bound or of some mixed flow and the binding of the variable will not change
in any way.
The function form is called with a type as first argument and a value as second argument, and it
returns the same value.
hasDomain : (<type> Type, Type Value) -> Type Value.

The only effect of the call is to ensure that the Value will be restricted to the type Type.
lowerBound
lowerBound : (<numeric-domain> NumericDomain) -> <numeric-domain> LowerBound.

Returns the lower bound of the specified NumericDomain.


Call-template for this function is:

Language Reference

Page 144 / 167

Visual Prolog 7.5 - Language Reference


LowerBoundValue = lowerBound(domainName)

The lowerBound is a compiling-time predicate. The lowerBound returns the lower bound value
LowerBoundValue of the specified numeric domain domainName. The return value
LowerBoundValue belongs to the same domain domainName. The domainName parameter should be
the name of any numerical domain; this domain name should be explicitly specified at compile-time
(that is, domainName cannot come from a variable). See also upperBound/1->.
It will give a compile time error if the specified domain domainName is not numeric domain.
in
See in/2.
isErroneous
isErroneous : (<fact-variable> FactVariable) determ.

The predicate succeeds if the specified fact variable is erroneous.


Call-template for this predicate is:
isErroneous(factVariableName)

The predicate succeeds if the specified fact variable factVariableName has the erroneous value,
otherwise it fails.
maxDigits
maxDigits : (<real-domain> RealDomain) -> unsigned MaxDigits

Retrieves the value of digits (precision) of the basic domain corresponding to the specified floatingpoint domain domainName.
Call-template for this function is:
MaxDigitsNumber = maxdigits(domainName)

The return maximal number of digits MaxDigitsNumber for the domainName parameter, which should
be the name of a real domain.
not
See not.
or
See or (;).
Language Reference

Page 145 / 167

Visual Prolog 7.5 - Language Reference


orelse
See orelse.
predicate_fullname
predicate_fullname : () -> string PredicateFullName.

This predicate returns the name PredicateFullName of the predicate in which it is invoked. The
returned predicate name is qualified with a scope name.
predicate_fullname can only be used inside a clause. Use of predicate_fullname in other places
causes a compile time error. See also predicate_name.
predicate_name
predicate_name : () -> string PredicateName.

This predicate returns the name PredicateName of the predicate in which it is invoked.
predicate_name can only be used inside a clause. Use of predicate_name in other places causes
a compile time error. See also predicate_fullname
programPoint
programPoint : () -> core::programPoint ProgramPoint.

This predicate returns the name programPoint corresponding to the place where it is invoked.
retract
retract : (<fact-term> FactTerm) nondeterm anyflow.

Successively removes the first matching fact from the facts database. Fails when no more facts
match.
Call-template for this predicate is:
retract(FactTemplate)

Here FactTemplate should be a fact term. The retract/1 predicate deletes the first fact that
matches the FactTemplate in the appropriated facts database. During backtracking, the rest of the
matching facts will be deleted.
Notice that FactTemplate can have any level of instantiation. The FactTemplate is matched with
the facts in the facts database, which means that any free variables will be bound in the call to
retract/1.
Language Reference

Page 146 / 167

Visual Prolog 7.5 - Language Reference


The FactTemplate can contain any anonymous variables. That is, variables with names consisting
from the single underscore _ or a variable with a name starting with an underscore _AnyValue if the
variable occurs only once in the clause. For example.
retract(person("Hans", _Age)),

will retract the first matched person fact that has "Hans" as the first argument and anything as the
second argument.
When retracting a fact, which is declared to be determ, the call to retract/1 will be deterministic.
See also retractall/1 and retractFactDb.
The retract/1 predicate cannot be applied to single facts or fact variables.
Be careful calling retract/1 with free FactTemplate variable if any single fact is declared in the
project current scope. If you retract a single fact, then the run-time error is generated. The
retract/1 predicate fails when there are no more matches.
retractall
retractall : (<fact-term> FactTerm) .

Remove all matching facts from the facts database.


Call-template for this predicate is:
retractall(FactTemplate)

Here FactTemplate should be a fact term.


The retractall/1 retracts all facts which match the given FactTemplate. It always succeeds, even if
no facts were retracted.
Attempting to retract a single fact will cause a compile time error.
It is not possible to obtain any output values from retractall/1. For this reason, the variables in the
call must be bound or be a single underscores (anonymous). Notice that FactTemplate can have any
level of instantiation, but free variables must be single underscores ("unconditionally anonymous"). In
difference to retract/1 "conditionally" anonymous variables with names starting from the underscore
(like _AnyValue) cannot be used in retractall/1.
See also retract/1 and retractFactDb/1.
retractFactDb
retractFactDb : (factDB FactDB).

Language Reference

Page 147 / 167

Visual Prolog 7.5 - Language Reference


Remove all facts from the named internal facts database FactDB.
Call-template for this predicate is:
retractFactDb(FactDB)

The retractFactDb/1 removes all facts from the named facts database FactDB.
Notice, it is impossible to retract single facts and fact variables, so the predicate leaves such ones
as they are.
See also retractall/1 and retract/1.
retractAll/2
Obsolete predicate! Use retractFactDb/1 instead.
sizeBitsOf
sizeBitsOf : (<domain> DomainName) -> unsigned BitSize.

Retrieves the number of bits occupied in memory by an entity of the specified domain DomainName.
Call-template for this function is:
BitSize = sizeBitsOf(DomainName)

This compiling-time predicate receives the domain DomainName as input parameter and return the
size of memory that is occupied by the entity of the given domain. The result is measured in bits. For
the integer domains sizeBitsOf/1-> predicate returns the value that was defined for the size-field in
a domain's declaration.
The following is always true for the integral domains:
sizeOfDomain(domain)*8 - 7 <= sizeBitsOf(domain) <= sizeOfDomain(domain)*8

See also sizeOfDomain/1->.


sizeOf
sizeOf : (<term> Term) -> integer ByteSize.

Retrieves the number of bytes occupied in memory by the specified term Term.
Call-template for this function is:
ByteSize = sizeOf(Term)
Language Reference

Page 148 / 167

Visual Prolog 7.5 - Language Reference

The sizeOf/1-> function receives a term as input parameter and returns value ByteSize that
specifies the number of bytes occupied in memory by this term Term.
sizeOfDomain
sizeOfDomain : (<domain> Domain) -> integer ByteSize.

Retrieves the number of bytes occupied in memory by the entity of the specified domain
DomainName.
Call-template for this function is:
ByteSize = sizeOfDomain(DomainName)

This compiling-time predicate receives the domain DomainName as input parameter and return the
size of memory that is occupied by the entity of the given domain. The result is measured in bytes.
The returned value ByteSize belongs to the integer domain. Compare with sizeBitsOf/1->, which
returns size of a domain measured in bits.
sourcefile_lineno
sourcefile_lineno : () -> unsigned LineNumber.

Returns the current line number in the source file processed by the compiler.
sourcefile_name
sourcefile_name : () -> string FileName.

Returns the name of the source file processed by the compiler.


sourcefile_timestamp
sourcefile_timestamp : () -> string TimeStamp..

Returns a string that represents the date and time of the currently compiled source file in format
YYYY-MM-DD HH:MM:SS. Where:
l
l
l
l
l
l

YYYY - Year.
MM - Month.
DD - Day.
HH - Hour.
MM - Minute.
SS - Second.

succeed
Language Reference

Page 149 / 167

Visual Prolog 7.5 - Language Reference


succeed : ().

The predicate succeed/0 will always succeed.


toAny
toAny : (Term) -> any UniversalTypeValue.

Converts the specified Term to the value of universal term type any.
Call-template for this function is:
UniversalTypeValue = toAny(Term)

toBinary
toBinary : (Term) -> binary Serialized.

Converts the specified Term to binary representation.


Call-template for this function is:
Serialized = toBinary(Term)

When a Term (of some domain domainName) is converted into a binary, it can safely be stored in a
file or sent over a network to another program. Later the obtained binary value Serialized can be
converted back to a Visual Prolog term, using toTerm/1-> function (the domain for the reversed term
should be adequate to domainName) for the reverse conversion.
toBoolean
toBoolean : (<term> SubGoal) -> boolean Succeed.

The purpose of this meta-predicate is to convert the deterministic call (to a predicate or fact) to the
procedure that returns the value of boolean domain.
Call-template for this meta-predicate is:
True_or_False = toBoolean(deterministic_call)

The toBoolean/1-> meta-predicate returns boolean value. The result is true if deterministic_call
succeeds. The result is false if deterministic_call fails.
toEllipsis

Language Reference

Page 150 / 167

Visual Prolog 7.5 - Language Reference


toEllipsis : (any* AnyTermList) -> ....

This predicate creates EllipsisBlock ... (i.e. the special varying parameters block) from the list of
terms of the universal type any. Such EllipsisBlock can be later passed to a predicate which expects
the varying number of arguments (i.e. is declared with the ellipsis (...)), like write/..., at the position
of the ellipsis (...).
Call-template for this function is:
EllipsisBlock = toEllipsis(<any_term_list>), write(EllipsisBlock )

See also fromEllipsis/1->.


toString
toString : (Term) -> string Serialized.

Converts the specified Term to string representation.


Call-template for this function is:
Serialized = toString(Term)

When a Term (of some domain domainName) is converted into a string, it can safely be stored in a
file or sent over a network to another program. Later the obtained string value can be converted
back to a Visual Prolog term, using toTerm/1-> function (the domain of the return value should be
adequate to domainName) for the reverse conversion.
toTerm
toTerm
toTerm
toTerm
toTerm
toTerm
toTerm

: (string Serialized) -> Term.


: (binary Serialized) -> Term.
: (any Serialized) -> Term.
: (<domain> Type, string Serialized) -> Term.
: (<domain> Type, binary Serialized) -> Term.
: (<domain> Type, any Serialized) -> Term.

Converts the string/binary/any representation of the specified term Serialized into representation
corresponding to the domain of Term variable of the return value. The domain can be stated
explicitly or it can be left to the compiler to determine a suitable domain.
Call-template for this function is:
Term = toTerm(Serialized) % with implicit domain
Term = toTerm(domainName, Serialized) % with explicit domain, domainName

If the domain is not specified the compiler must be able to determine the domain for the returned
value Term at compile-time. Notice that binary version of toTerm predicate performs almost byte to
byte conversion and only checking general compatibility of Serialized data with the domain required
Language Reference

Page 151 / 167

Visual Prolog 7.5 - Language Reference


to the return value Term. The programmer is wholly responsible for providing binary data of
Serialized that can be correctly converted to the term of the desired domain. The toTerm
predicates are counterparts to predicates toBinary/1-> and toString/1->. When a Term (of some
domain domainName) is converted into a binary or string representation Serialized (by toBinary/1->
or toString/1-> or toAny/1-> correspondingly), it can safely be stored in a file or sent over a network
to another program. Later the corresponding toTerm/1-> function can convert the obtained
string/binary value Serialized back to a Visual Prolog term Term. For correctness of the reverse
conversion the domain of the clause variable Term should be adequate to the initial domain
domainName.
See also tryToTerm.
It gives a compile time error if the compiler cannot determine the return domain.
Exceptions
l

Run time errors are generated when the toTerm predicate cannot convert the string or binary
into a term of the specified domain.

tryToTerm
tryToTerm
tryToTerm
tryToTerm
tryToTerm
tryToTerm
tryToTerm

: (string Serialized) -> Term.


: (binary Serialized) -> Term.
: (any Serialized) -> Term.
: (<domain> Type, string Serialized) -> Term.
: (<domain> Type, binary Serialized) -> Term.
: (<domain> Type, any Serialized) -> Term.

Converts the string/binary/any representation Serialized into a term Term like toTerm. The only
difference between the predicates is that tryToTerm fails if it cannot convert the string or binary or
any into a term of the specified domain whereas toTerm raises an exception.
See also toTerm.
tryConvert
tryConvert : (<type> Type, Value) -> <type> Converted determ.

Checks whether the input term InputTerm can be strictly converted into the specified domain Type
and returns the converted term Converted.
Call-template for this function is:
ReturnTerm = tryConvert(returnDomain, InputTerm)

Arguments:
l

returnDomain: Specifies a domain to which tryConvert/2-> predicate tries to convert the


specified InputTerm. Here returnDomain can be any domain accessible in the current scope.
The domain name returnDomain must be specified at compile-time, i.e. it cannot come from a
variable.

Language Reference

Page 152 / 167

Visual Prolog 7.5 - Language Reference


l

InputTerm: Specifies the term that must be converted. InputTerm may be any Prolog term or
an expression. If InputTerm is an expression, then it will be evaluated before conversion.
ReturnTerm: Returned term ReturnTerm will be of returnDomain domain.

The conversion rules are the same as of the embedded predicate convert/2->, but tryConvert/2->
fails when convert/2-> generates conversion errors.
This predicate succeeds if the corresponding conversion succeeds. Otherwise it fails. The
tryConvert/2-> predicate tries to perform a clean and genuine conversion of the given InputTerm
into a value of the specified domain returnDomain. The tryConvert/2-> predicate will fail if the
required conversion cannot be performed. When tryConvert/2-> predicate succeeds, it returns the
term ReturnTerm converted to the specified domain returnDomain.
For allowed conversions and rules of checked explicit conversions see convert/2-> predicate.
See also uncheckedConvert/2->.
uncheckedConvert
uncheckedConvert : (<type> Type, Value) -> <type> Converted.

Unchecked conversion of a value to another type.


Call-template for this function is:
ReturnTerm = uncheckedConvert(returnDomain, InputTerm)

Arguments:
l

returnDomain: Specifies a domain to which uncheckedConvert predicate unsafely converts


the specified InputTerm. Here returnDomain can be any domain accessible in the current
scope, the ReturnTerm should has the same bit-size as the InputTerm. The domain name
returnDomain must be specified at compile-time, i.e. it cannot come from a variable.
InputTerm: Specifies the value that must be converted. InputTerm may be any Prolog term
or an expression. If InputTerm is an expression, then it will be evaluated before conversion.
ReturnTerm: Returned parameter ReturnTerm will be of returnDomain type.

uncheckedConvert evaluates InputTerm, change the type to returnDomain without any


modification of the memory pattern and unifies with ReturnTerm. The uncheckedConvert predicate
performs no runtime checks. It makes only compile time checking of bit-size equality of the converted
domains. So almost any term may be quite recklessly converted to any other term. So quite
disastrous results may occur if you try to use variables incorrectly converted by uncheckedConvert.
Be extremely careful implementing uncheckedConvert; we strongly recommend you always, when it
is possible, using of convert/2-> and tryConvert/2->. But notice that, when an object is returned by
COM system it is necessary to convert it by uncheckedConvert, as Prolog program does not have
information about its actual type.
upperBound
upperBound : (<numeric-domain> NumericDomain) -> <number-domain> UpperBound.

Language Reference

Page 153 / 167

Visual Prolog 7.5 - Language Reference


Returns the upper bound value of the specified numeric domain.
Call-template for this function is:
UpperBound = upperBound(domainName)

The upperBound is a compiling-time predicate. The upperBound returns the upper bound value of
the specified numeric domain domainName. The return value UpperBound belongs to the same
domain domainName. The domainName parameter should be the name of any numerical domain; this
domain name should be explicitly specified at compile-time (that is, domainName cannot come from a
variable).
See also lowerBound/1->.
Will cause a compile time error if the specified domain domainName is not numeric domain.

Language Reference

Page 154 / 167

Visual Prolog 7.5 - Language Reference


Directives
Each compiler directive starts from the # character. The following directives are supported:
l
l
l
l
l

#include, #bininclude - file inclusion.


#if, #then, #else, #elseif, #endif - conditional statements.
#export, #externally - exporting and importing classes.
#message, #error, #requires, #orrequires - compilation time information.
#options - compiler options.

Source File Inclusion


The #include compiler directive is used to include the contents of another file into your program
source code during compilation. It has the following syntax:
Pp_dir_include :
#include String_literal

The String_literal should specify an existing filename.


#include "pfc\\exception\\exception.ph" % Includes pfc\exception\exception.ph file

#include @"pfc\vpi\vpimessage\vpimessage.ph" % Includes pfc\vpi\vpimessage\vpimessage.ph

This compiler directive uses "include the first file occurrence only" semantics. That is, if a compilation
unit contains several include directives for the same file, it will be included only one time with the first
include directive.
Each included file must contain several accomplished scopes; an included file cannot contain
uncompleted scopes. That is, it should contain several accomplished interface declarations, class
declarations, class implementations or/and several compiler directives.
The compiler tries to find the specified include source file in the following way:
1. If the filename contains an absolute path, then this file should be included.
2. Otherwise, the compiler searches for the specified include filename among the paths that had
been defined by the /Include command line option. These paths are handled consequently as
they are specified in the option. In the IDE you can set these paths in the Include Directories
in the Directories tab of the Project Settings dialog.
If the compiler does not find the specified file a compiling time error is generated.

Binary File Inclusion


The #bininclude compiler directive is used to include (during compilation) the contents of a file
(specified by the string_literalstring)asa::binary type constant into your program source code. It
has the following syntax:
Pp_dir_bininclude :
Language Reference

Page 155 / 167

Visual Prolog 7.5 - Language Reference


#bininclude ( String_literal )

This directive can be used in any places where binary constants are allowed. The string_literal should
specify an existing filename. The syntax is the same as in the #include compiler directive described
in the previous paragraph Source File Inclusions. The compiler tries to find the specified file in the
same way as for #include compiler directive.
The typical usage is like this:
constants
myBin : binary = #bininclude("Bin.bin").
% Creates value of binary constant from "Bin.bin" file

When creating a binary constant the compiler adds the EOS symbol immediately after this constant,
which makes safe the directive usages like this:
constants
text : string = uncheckedConvert(string, #bininclude("text.txt")).
% Here text.txt is a text file, which is normally not text zero terminated

Exporting and Importing Classes


Compiler directives #export and #externally are used to determine lists of exported and imported
classes, respectively. They have the following syntax:
Pp_dir_export :
#export ClassNames-comma-sep-list
Pp_dir_export :
#externally ClassNames-comma-sep-list

These compiler directives are applied only to classes classNames, which do not construct objects.
They can be used only outside scopes; that is, they cannot be used inside declarations of interfaces
and classes and they cannot be used inside implementations of classes.
By default, predicates within one executed module are hidden at runtime for all other executed
modules. An #export compiler directive makes names of specified classes public outside the module
in which they are declared (and implemented). Therefore, all predicates from this module declared in
the classes (specified in an #export directive) become accessible while runtime from other executed
modules.
Usually, an #export compiler directives can be used in projects, which target modules are DLLs. It
enumerates classes declared in a DLL, which should be accessible to other modules that use this DLL.
If a compilation unit export some class, then this compilation unit should contain this class
implementation.
Also an #export compiler directives can be used to specify condition expressions for #if compiler
directives.
For example, let us suppose that somewhere in the beginning of a compilation unit the compiler has
Language Reference

Page 156 / 167

Visual Prolog 7.5 - Language Reference


met the #export compiler directive like this:
#export className

Then the compiler, if in the subsequent code it meets an #if compiler directive with the same
#export compiler directive used as the condition expression, for example like this:
#if #export className #then ... #endif

Then the compiler evaluates the #export condition expression as true and, hence, the compiler
executes the #then branch of the conditional compilation directive.
For example, the following #export compiler directive with the subsequent #if conditional compilation
compiler directive:
#export className
...
#if #export className #then #requires "some.pack" #endif

guaranty that the "some.pack" package will be included into the compilation unit.
From the other hand, if an #export compiler directive is not met by the compiler (somewhere in the
compilation unit before the #if compiler directive, which uses the same #export compiler directive as
the conditional expression), then the compiler evaluates this #export condition expression as false.
Hence, the compiler will not execute the #then branch of the #if conditional compilation directive.
That is, the single #if compiler directive without previous #export directive
#if #export className #then #requires "some.pack" #endif

does not requires to include the "some.pack" package.


An #externally compiler directive is counterpart to an #export compiler directive. An #externally
compiler directive can be used instead of (and concurrently with) an IMPORTS directive in definition
files. An #externally compiler directive enumerates classes, which are declared in a module but
implemented in other modules. Therefore, the compiler will not produce errors when it detects such
classes. The referenced classes can be implemented (and exported) in DLLs, which can be linked to
the module at runtime.
The #export and #externally compiler directives can be used as Condition boolean expressions in
Conditional Compilation.
For example, like this:
#if #export className #then #include "Some package.pack" #endif

Compile Time Information


Compiler directives #message, #requires, #orrequires, and #error can be used to issue userdefined messages into a listing file while compilation of project modules and to interrupt compilation.
Language Reference

Page 157 / 167

Visual Prolog 7.5 - Language Reference


These directives can be used either outside scopes (interface declaration, class declaration or class
implementation), or inside scopes but outside sections. They have the following syntax:
Pp_dir_message: one of
#message String_literal
#error String_literal
#requires String_literal Pp_dir_orrequires-list-opt
#orrequires String_literal

When the compiler meets any of these directives, it generates the correspondent warning message
and place the directive text into a listing file.
A listing file name can be specified with the compiler directive:

/listingfile:"FileName"

Notice that no empty spaces can be used between the colon : (after /listinglile) and "FileName".
By default the compiler does NOT generate informative messages for the #message, #requires, and
#orrequires directives. You can switch generation of these informative messages ON specifying the
compiler options:

/listing:message
/listing:requires
/listing:ALL

Example In this case, when the compiler meets a directive like:


#message "Some message"

it will place the following text into the listing file:

C:\Tests\test\test.pro(14,10):informationc062:#message"Somemessage"

The directive #requires (#orrequires) issues arbitrary user-defined messages about the needed
source (object) files into a listing file. The #orrequires directive cannot be used alone: the
#requires directive should immediately (separated with white spaces or comments only) precede it.
The directive #error always terminates the compilation and issues the user-defined error message
like the following into a listing file:

C:\Tests\test\test.pro(14,10):errorc080:#error"Compilationisinterrupted"

You can parse and analyze these messages and accept the required actions. For example, the VDE
analyzes information printed by the #requires and #orrequires directives and automatically adds all
needed PFC packages and standard libraries to the compiled project (See also the Handling Project
Modules topic).
Language Reference

Page 158 / 167

Visual Prolog 7.5 - Language Reference


Example The directives #requires and #orrequires can be used like this:
#requires @"\Common\Sources\CommonTypes.pack"
#orrequires @"\Common\Lib\CommonTypes.lib"
#orrequires @"\Common\Obj\Foreign.obj"
#if someClass::debugLevel > 0 #then
#requires @"\Sources\Debug\Tools.pack"
#orrequires @"\Lib\Debug\Tools.lib"
#else
#requires @"\Sources\Release\Tools.pack"
#orrequires @"\Lib\Release\Tools.lib"
#endif
#orrequires "SomeLibrary.lib"
#requires "SomePackage.pack"
#if someClass::debugLevel > 0 #then
#orrequires @"\Debug\SomePackage.lib"
#else
#orrequires @"\Release\SomePackage.lib"
#endif

Example The #message directive can be used like this:


#message "Some text"
#if someClass::someConstant > 0 #then
#message "someClass::someConstant > 0"
#else
#message "someClass::someConstant <= 0"
#endif
class someClass
#if ::compiler_version > 600 #then
#message "New compiler"
constants
someConstant = 1.
#else
#message "Old compiler"
constants
someConstant = 0.
#endif
end class someClass

Example The #error can be used like this:


#if someClass::debugLevel > 0 #then
#error "Debug version is not yet implemented"
#endif

Compiler options directive


Compiler directive #options <string_literal> affects the whole compilation unit. This directive
should be used outside scopes and conditional compilation statements in the main source file for a
compilation unit (i.e. in the source file which is passed to the compiler). Otherwise the compiler
generates a warning message and ignores the directive.
The <string_literal> can only contain the following compiler options:
"/Warning"
"/Check"
"/NOCheck"
Language Reference

Page 159 / 167

Visual Prolog 7.5 - Language Reference


"/Optimize"
"/DEBug"
"/GOAL"
"/MAXErrors"
"/MAXWarnings"

Otherwise the compiler generates the error message for invalid option. If there are several #options
directives they are handled in the textual order.

Conditional Compilation
The conditional programming constructions are part of the Visual Prolog language. Only other compiler
directives, Compilation Units, and Program Sections (including empty) can be conditional. The
following syntax is used:
ConditionalItem :
#if Condition #then CompilationItem-list-opt ElseIfItem-list-opt ElseItem-opt #endif

ElseIfItem :
#elseif Condition #then CompilationItem

ElseItem :
#else CompilationItem

Here Condition can be any expression, which can be evaluated to fail or succeed during compilation
time.
Each one conditional compilation statement must be in one file, that is, the compiler directives #if,
#then, #elseif and #else (if present), #endif of the same level of nesting must be in one file.
During compilation the compiler evaluates the conditions, in order to determine which parts to include
in the final program. Parts that are excluded from the final program are called the dead branches.
All branches of conditional compilation items are syntax checked and must be syntactically correct.
That is, also the dead branches must be syntactically correct.
The compiler only calculates conditions on a need to know basis, i.e. it does not calculate conditions
in dead branches.
A condition may not depend on any code, which is located textually inside the conditional statement.
The example below is illegal because the condition depends on the scope (and constant) which is
declared inside the condition branch.
#if aaa::x > 7 #then % ERROR!
class aaa
constants
x=3
end class aaa
#else
class aaa
constants
x = 23
Language Reference

Page 160 / 167

Visual Prolog 7.5 - Language Reference


end class aaa
#endif

Language Reference

Page 161 / 167

Visual Prolog 7.5 - Language Reference


Attributes
Various definitions and declarations can be annotated with attributes. This section describes the
general syntax of attributes and where they can be placed. It also describes the meaning of the
specific attributes.

Syntax
Attributes :
[ Attribute-comma-sep-list ]

Attribute : one of
LowerCaseIdentifier
LowerCaseIdentifier ( Literal-comma-sep-list )

where the literals must either be numbers or string literals.

Insertion Points
The attributes of interfaces, classes and implementations are right after the scope qualifications.
InterfaceDeclaration :
interface IinterfaceName
ScopeQualifications
Attributes-opt
Sections
end interface IinterfaceName-opt

ClassDeclaration :
class ClassName ConstructionType-opt
ScopeQualifications
Attributes-opt
Sections
end class ClassName-opt

ClassImplementation :
implement ClassName
ScopeQualifications
Attributes-opt
Sections
end implement ClassName-opt

The attributes of constants, domains, predicates, properties and facts are at the end (i.e. right
before the terminating dot).
ConstantDefinition: one of
ConstantName = ConstantValue Attributes-opt
ConstantName : TypeName = ConstantValue Attributes-opt

DomainDefinition:
DomainName FormalTypeParameterList-opt = TypeExpression Attributes-opt
Language Reference

Page 162 / 167

Visual Prolog 7.5 - Language Reference

PredicateDeclaration :
PredicateName : PredicateDomain LinkName-opt Attributes-opt
PredicateName : PredicateDomainName LinkName-opt Attributes-opt

PropertyDeclaration :
PropertyName : PropertyType FlowPattern-list-opt Attributes-opt

FactDeclaration :
FactVariableDeclaration Attributes-opt
FactFunctorDeclaration Attributes-opt

The attributes of formal arguments are at the end.


FormalArgument :
TypeExpression ArgumentName-opt Attributes-opt

Specific Attributes
byVal
An argument is transferred directly on the stack rather than using a pointer. Valid for formal predicate
arguments provided the language is stdcall, apicall or c.
Example
predicates
externalP : (point Point [byVal]) language apicall.

deprecated
The declared entity is deprecated. The string literal describes how to migrate from it. The entity still
exist, but usage will cause a warning. The entity will not exist in future versions of Visual Prolog. Valid
for member declarations and scopes.
Example
predicates
oldFasioned : (string Arg) [deprecated("Use newFasion instead")].

formatString
The argument is a format string for a subsequent ellipsis argument (i.e. ...). Valid for one string
argument of a predicate with an ellipsis argument. The use of formatString will make the compiler
check the validity of actual arguments with respect to actual format strings (where possible).
Example
Language Reference

Page 163 / 167

Visual Prolog 7.5 - Language Reference


predicates
writef : (string Format [formatString], ...).

in
The argument is an input argument. Valid for a formal predicate argument.
Example
predicates
pred : (string InputArg [in]).

inline
inline alters the memory layout of a struct (i.e. a single alternative functor domain with an align
qualification). The purpose of the attribute is to ease interfacing to foreign languages and should
normally not be used for pure Visual Prolog.
inline can be used in three cases:
l
l
l

inlining a struct rather than having a pointer to the struct


inlining a fixed size string
inlining a fixed number of bytes

When using inline on struct field in another struct its data will be inlined instead of having a pointer
to the struct
Example
domains
point =p(integer X, integer Y).

domains
rectangle =
r(
point UpperLeft [inline],
point LowerRight [inline]
).

Since UpperLeft and LowerRight are inlined the struct have the same memory layout as this one:
domains
rectangle2 =
r2(
integer UpperLeft_X,
integer UpperLeft_Y,
integer LowerRight_X,
integer LowerRight_Y
).

When using inline(<size>) on a string or a string8 field in a struct, the struct will contain a fixed
size string with <size> characters (i.e. char or char8, respectively). The strings will be zero
Language Reference

Page 164 / 167

Visual Prolog 7.5 - Language Reference


terminated if they are shorter than <size>, but not if they have <size> characters.
Example
domains
device =
device(
integer Id,
string DeviceName [inline(12)]
).

DeviceName is an inlined Unicode string of length 12. The struct have the same layout as:
domains
device =
device(
integer Id,
char DeviceName_01,
char DeviceName_02,
char DeviceName_03,
char DeviceName_04,
char DeviceName_05,
char DeviceName_06,
char DeviceName_07,
char DeviceName_08,
char DeviceName_09,
char DeviceName_10,
char DeviceName_11,
char DeviceName_12
).

When using inline(<size>) on the pointer type the struct will contain <size> bytes, and the
pointer will become a pointer to that field:
Example
domains
mark =
mark(
integer Position,
pointer Data [8]
).

Data is pointer to 8 inlined bytes The struct have the same layout as:
domains
mark2 =
mark2(
integer Position,
byte Data_1,
byte Data_2,
byte Data_3,
byte Data_4,
byte Data_5,
byte Data_6,
byte Data_7,
byte Data_8
).
Language Reference

Page 165 / 167

Visual Prolog 7.5 - Language Reference

And Data will point to Data_1.


noDefaultConstructor
Used for a class to indicate that it should not have an implicit default constructor, and can thus be
used to a class that does not have any public constructors at all. Valid for an object creating class
declaration.
Example
class classWithoutPublicConstructors : myInterface
[noDefaultConstructor]
...
end class classWithoutPublicConstructors

out
The argument is an output argument. Valid for a formal predicate argument.
Example
predicates
pred : (string OutputArg [out]).

programPoint
Used for a predicate or constructor declaration to indicate that it recieves an extra input argument
which describes the place in a program (program point) where this predicate was called. This
additional argument has programPoint type which is declared in the PFC core class like:
domains
programPoint = programPoint(hScopeDescriptor ClassDescriptor, string PredicateName, sourceCursor

The clause name of such predicate or constructor should have suffix "_explicit". Valid for a predicate
or constructor declaration.
Example
predicates
pred : (string String) [programPoint].
clauses
pred_explicit(ProgramPoint, String) :...

The programPoint attribute is described in more details in the description of Predicates, and it is a
vital part of the exception system, see Exception Handling.
retired

Language Reference

Page 166 / 167

Visual Prolog 7.5 - Language Reference


The declared entity is retired. The string literal describes how to migrate from it. The entity does not
exist anymore.
Example
predicates
veryOldFasioned : (string Arg) [retired("Use newFasion instead")].

sealed
Used for an interface to indicate that it cannot be supported by any other interface. This allows to
create more efficient codes, because the compiler provides some optimization when using the objects
of such type. Valid for an object creating class declaration as a construction interface.
Example
interface myInterface
[sealed]
...
end interface myInterface

class myClass : myInterface


...
end class myClass

union
Used for creating functor domains with several alternatives but no real functors. This should only be
used to mimic C/C++ union structs in low-level interfacing. Valid for functor domain with several
alternatives and alignment.
Example
domains
u64var = align 4
u64(unsigned64 Value64);
u64_struct(unsigned Low32, unsigned High32)
[union].

used
An unused local member can be marked used to prevent the compiler to issue a warning and remove
the corresponding code. Valid for members.
Example
predicates
seeminglyUnused : () [used].

Language Reference

Page 167 / 167

You might also like