Language Reference/Directives

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


 * #include, #bininclude  - file inclusion.
 * #if, #then, #else, #elseif, #endif - conditional statements.
 * #export</vp>, #externally</vp> - exporting and importing classes.
 * #message</vp>, #error</vp>, #requires</vp>, #orrequires</vp> - compilation time information.
 * #options</vp> - compiler options.

Source File Inclusion
The #include</vp> 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 should specify an existing filename.


 * 1) include "pfc\\exception\\exception.ph" % Includes pfc\exception\exception.ph file


 * 1) 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</vp> 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.

Text File Inclusion
The #stringinclude</vp> compiler directive is used to include (during compilation) the contents of a file (specified by the string) as a :: constant into your program source code. It has the following syntax:

<Pp_dir_bininclude> : #stringinclude( <String_literal> )

This directive can be used in any places where constants are allowed. The should specify an existing filename. The syntax is the same as in the #include</vp> compiler directive described in the previous paragraph. The compiler tries to find the specified file in the same way as for #include</vp> compiler directive. If the file has a byte-order-mark it will be treated accordingly, if the file does not have byte order mark and does not appear to be in utf-16 it will be read with the current codepage (it is recommended to use files with byte-order-mark utf-8 or utf-16).

Binary File Inclusion
The #bininclude</vp> compiler directive is used to include (during compilation) the contents of a file (specified by the string) as a :: constant into your program source code. It has the following syntax:

<Pp_dir_bininclude> : #bininclude( <String_literal> )

This directive can be used in any places where constants are allowed. The should specify an existing filename. The syntax is the same as in the #include</vp> compiler directive described in the previous paragraph. The compiler tries to find the specified file in the same way as for #include</vp> compiler directive.

When creating a binary constant the compiler adds the EOS symbol immediately after this constant.

Exporting and Importing Classes
Compiler directives #export</vp> and <vp>#externally</vp> 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 <vp>#export</vp> 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 <vp>#export</vp> directive) become accessible while runtime from other executed modules.

Usually, an <vp>#export</vp> 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 <vp>#export</vp> compiler directives can be used to specify expressions for <vp>#if</vp> compiler directives.

For example, let us suppose that somewhere in the beginning of a compilation unit the compiler has met the <vp>#export</vp> compiler directive like this:


 * 1) export className

Then the compiler, if in the subsequent code it meets an <vp>#if</vp> compiler directive with the same <vp>#export</vp> compiler directive used as the condition expression, for example like this:


 * 1) if #export className #then ...  #endif

Then the compiler evaluates the <vp>#export</vp> condition expression as <vp>true</vp> and, hence, the compiler executes the <vp>#then</vp> branch of the conditional compilation directive.

For example, the following <vp>#export</vp> compiler directive with the subsequent <vp>#if</vp> conditional compilation compiler directive:

...
 * 1) export className
 * 1) if #export className #then #requires "some.pack" #endif

guaranty that the <vp>"some.pack"</vp> package will be included into the compilation unit.

From the other hand, if an <vp>#export</vp> compiler directive is not met by the compiler (somewhere in the compilation unit before the <vp>#if</vp> compiler directive, which uses the same <vp>#export</vp> compiler directive as the conditional expression), then the compiler evaluates this <vp>#export</vp> condition expression as <vp>false</vp>. Hence, the compiler will not execute the <vp>#then</vp> branch of the <vp>#if</vp> conditional compilation directive. That is, the single <vp>#if</vp> compiler directive without previous <vp>#export</vp> directive


 * 1) if #export className #then #requires "some.pack" #endif

does not requires to include the <vp>"some.pack"</vp> package.

An <vp>#externally</vp> compiler directive is counterpart to an <vp>#export</vp> compiler directive. An <vp>#externally</vp> compiler directive can be used instead of (and concurrently with) an <vp>IMPORTS</vp> directive in definition files. An <vp>#externally</vp> 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 <vp>#export</vp> and <vp>#externally</vp> compiler directives can be used as <Condition> boolean expressions in.

For example, like this:


 * 1) if #export className #then #include "Some package.pack" #endif

Compile Time Information
Compiler directives <vp>#message</vp>, <vp>#requires</vp>, <vp>#orrequires</vp>, and <vp>#error</vp> can be used to issue user-defined messages into a listing file while compilation of project modules and to interrupt compilation.

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:

Notice that no empty spaces can be used between the colon <vp>:</vp> (after <vp>/listinglile</vp>) and <vp>"FileName"</vp>.

By default the compiler does NOT generate informative messages for the <vp>#message</vp>, <vp>#requires</vp>, and <vp>#orrequires</vp> directives. You can switch generation of these informative messages ON specifying the compiler options:

The directive <vp>#requires</vp> (<vp>#orrequires</vp>) issues arbitrary user-defined messages about the needed source (object) files into a listing file. The <vp>#orrequires</vp> directive cannot be used alone: the <vp>#requires</vp> directive should immediately (separated with white spaces or comments only) precede it.

The directive <vp>#error</vp> always terminates the compilation and issues the user-defined error message like the following into a listing file:

You can parse and analyze these messages and accept the required actions. For example, the VDE analyzes information printed by the <vp>#requires</vp> and <vp>#orrequires</vp> directives and automatically adds all needed PFC packages and standard libraries to the compiled project (See also the Handling Project Modules topic).

Compiler options directive
Compiler directive <vp>#options <string_literal></vp> 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 <vp><string_literal></vp> can only contain the following compiler options:

"/Warning" "/Check" "/NOCheck" "/Optimize" "/DEBug" "/GOAL" "/MAXErrors" "/MAXWarnings" "/profile"

Otherwise the compiler generates the error message for invalid option. If there are several <vp>#options</vp> 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 <vp>#if</vp>, <vp>#then</vp>, <vp>#elseif</vp> and <vp>#else</vp> (if present), <vp>#endif</vp> 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.

class aaa constants x = 3 end class aaa class aaa constants x = 23 end class aaa
 * 1) if aaa::x > 7 #then % ERROR!
 * 1) else
 * 1) endif