% BEGIN LICENSE BLOCK % Version: CMPL 1.1 % % The contents of this file are subject to the Cisco-style Mozilla Public % License Version 1.1 (the "License"); you may not use this file except % in compliance with the License. You may obtain a copy of the License % at www.eclipse-clp.org/license. % % Software distributed under the License is distributed on an "AS IS" % basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See % the License for the specific language governing rights and limitations % under the License. % % The Original Code is The ECLiPSe Constraint Logic Programming System. % The Initial Developer of the Original Code is Cisco Systems, Inc. % Portions created by the Initial Developer are % Copyright (C) 1994 - 2006 Cisco Systems, Inc. All Rights Reserved. % % Contributor(s): % % END LICENSE BLOCK % % @(#)umscompiler.tex 1.9 94/07/15 % % \comment{@(\#)text1.mss 20.4 9/19/88} % % REL DATE BY DESCRIPTION % 3.0.17 10.10.91 Micha Meier Created the file % 6.0 2008 Joachim Schimpf Update for new compiler % %---------------------------------------------------------------------- \chapter{The Compiler} \label{chapcompiler} %HEVEA\cutdef[1]{section} %---------------------------------------------------------------------- %---------------------------------------------------------------------- \section{Summary} %---------------------------------------------------------------------- The {\eclipse} compiler compiles {\eclipse} source (or Prolog source in various dialects) into the instructions of an abstract machine, which are then executed by an emulator. Program source can be read in text form from files, console, strings and general input streams. Alternatively, it can be provided in the form of a data structure (list of clause terms). The smallest program unit the compiler can meaningfully process is a predicate. In practice it is best to compile modules as a whole, since this allows for better consistency checks. Usually, the generated code is immediately loaded into main memory and ready for execution. This method is the most convenient during program development. In addition, compiled code can be output to a file ({\eclipse} object format, or {\it eco}), from which it can later be loaded more quickly. Compiled code optionally contains debugging information, allowing a source-oriented trace of program execution. %---------------------------------------------------------------------- \section{Compiler Invocation} %---------------------------------------------------------------------- The compiler is usually invoked by calling one of the following built-in predicates: \begin{quote} \begin{description} \item[\biptxtref{compile(\pattern{Source})}{compile/1}{../bips/kernel/compiler/compile-1.html}] This is the standard compiler predicate. Source is usually a file name, other forms are detailed below. The contents of the file is compiled with the default compiler options. \item[\biptxtref{compile(\pattern{Source},~\pattern{Options})}{compile/2}{../bips/kernel/compiler/compile-2.html}] This is the standard compiler predicate. Source is usually a file name, other forms are detailed below. Options is a list of options to control the compilation process, see details below. \item[\txtbipref{[\pattern{File1},...,\pattern{FileN}]}{(.)/2}{../bips/kernel/compiler/D-2.html}] This predicate can be used as a shorthand for the \bipref{compile/1}{../bips/kernel/compiler/compile-1.html} predicate. It accepts a list of files, which can be source files or precompiled files. \item[\biptxtref{compile_stream(\pattern{Stream})}{compile_stream/1}{../bips/kernel/compiler/compile_stream-1.html}] This predicate compiles a given, open stream up to its end or to the \notation{end_of_file} clause. It can be used when the input file is already open, e.g., when the beginning of the file does not contain compiler input. \item[\biptxtref{compile_stream(\pattern{Stream},~\pattern{Options})}{compile_stream/2}{../bips/kernel/compiler/compile_stream-2.html}] Like compile_stream/1 but with options list. \item[\biptxtref{compile_term(\pattern{Clauses})}{compile_term/1}{../bips/kernel/compiler/compile_term-1.html}] This predicate is used to compile a given term, usually a list of clauses and directives. Unlike \bipref{assert/1}{../bips/kernel/dynamic/assert-1.html} it compiles a static procedure, and so it can be used to compile a procedure which is dynamically created and then used as a static one. \item[\biptxtref{compile_term(\pattern{Clauses},~\pattern{Options})}{compile_term/2}{../bips/kernel/compiler/compile_term-2.html}] Like \predspec{compile_term/2} but with options list. \end{description} \end{quote} When using a development environment like \index{tkeclipse} \index{Saros} TkEclipse or Saros, the compiler is usually invoked implicitly via menu options or buttons. %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Source Files} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Program source is usually contained in files. The recommended file name \index{extension (file name)}\index{suffix (file name)}\index{file name!extension} suffixes (extensions) are \begin{itemize} \item \notation{.ecl} for {\eclipse} specific source \item \notation{.pl} for Prolog source \end{itemize} To compile a source files solver.ecl, any of the following forms is acceptable: \begin{quote} \begin{verbatim} ?- compile('solver.ecl'). ?- compile("solver.ecl"). ?- compile("/home/joe/solver.ecl"). ?- compile("/home/joe/solver"). ?- compile(solver). \end{verbatim} \end{quote} File names must be single quoted (atom) or double quoted (string) if they contain punctuation, blank space, or start with an upper case letter. The \notation{.ecl} extension can be omitted as long as no file without extension is present. A \notation{.pl} extension can be omitted as long as no file without extension and no file with \notation{.ecl} extension is present. The list of accepted suffixes and their precedence is given by the global flag \notationidx{prolog_suffix}, see \bipref{get_flag/3}{../bips/kernel/compiler/get_flag-3.html}. The following shorthands can be used, but note that the last two forms will load precompiled .eco files by preference, should they be present: \begin{quote} \begin{verbatim} ?- ['solver.ecl']. ?- ["solver.ecl"]. ?- ["/home/joe/solver.ecl"]. ?- ["/home/joe/solver"]. ?- [solver]. \end{verbatim} \end{quote} If the source is given as \notation{library(\pattern{Name})}, the predicates looks for the file in the directories from the global flag \notation{library_path}. If File is the special atom 'user', the source will be taken from the current 'input' stream, i.e., will usually generate a prompt at which clauses can be typed in. In this case, input must be terminated either by typing \notation{CTRL-D} (on Unix), \notation{CTRL-Z} + \notation{RETURN} (on Windows), or with the single atom \notation{end_of_file}, followed by a fullstop (period). \begin{quote} \begin{verbatim} ?- [user]. main :- writeln(hello). ^D tty compiled 72 bytes in 0.01 seconds Yes (0.01 cpu) ?- main. hello Yes (0.00s cpu) \end{verbatim} \end{quote} If File is the special form stream(Stream), then the source is taken from the given stream (which must be already opened). The stream content is compiled until the end of stream (or the \notation{end_of_file} marker). Using this feature, any {\eclipse} stream (file, socket, tty, string, queue, pipe) can be used as the source for program text. %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Main Compiler Options} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The following compiler options affect the generated code: \begin{quote} \begin{description} \item[debug:] This option (\notation{off}/\notation{on}) determines whether the resulting code contains debugging information. If \notation{off}, subgoals of the compiled predicates will not be visible to the debugger, the code will be significantly smaller, and slightly faster. The default value is taken from the global flag \notation{debug_compile}. The setting can be changed via a pragma (\notation{debug}/\notation{nodebug}) in the code. \item[opt_level:] Currently the integer 0 or 1, with 1 the default. Setting this to 0 will disable certain compiler optimizations and usually reduce performance. The setting can be changed via an \notation{opt_level(Level)} pragma in the code. \end{description} \end{quote} The following options determine what is being done with the compilation result: \begin{quote} \begin{description} \item[load:] Determines whether the generated code is immediately loaded into memory, ready for execution. Values for the \notation{load} option are: \begin{description} \item[all] (This is the default.) Load and replace code in memory, create/re-create all modules, interpret pragmas, and execute all directives and queries. \item[none] Do not load any code into memory, do not execute queries, but interpret pragmas and execute directives. Do not re-create modules, but create new ones and erase them again after compilation. \item[new] Do not overwrite any code in memory, but load new predicates. Do not execute queries, but interpret pragmas and execute directives. Do not re-create modules, but create new ones and erase them again after compilation. For existing modules, erase pragmas. \end{description} \item[output:] The abstract machine code which is the result of the compilation can be output in various forms. Possible values are: \begin{description} \item[none] (This is the default). No output (but code may be loaded, see \notation{load} option). \item[eco] output compiled code in \about{eco} format to a file whose suffix is \notation{.eco}. This format can be loaded using \predspec{ensure_loaded/1} or the compiler itself. \item[eco(\pattern{File})] output compiled code in \about{eco} format to \about{File}. \item[asm] output compiled code in \about{asm} format to a file whose suffix is \notation{.asm}. This format represents the code as WAM code that can be loaded back into ECLiPSe using the assembler (\notation{lib(asm)}). \item[asm(\pattern{File})] output compiled code in \notation{asm} format to \about{File}. \end{description} \item[outdir:] Value is the destination directory for all output files. The default is the empty string \notation{""}, meaning that all output files go into the same directory as the corresponding input file. \end{description} \end{quote} For other options see \bipref{compile/2}{../bips/kernel/compiler/compile-2.html}. For example, to compile a program without debugging support directly into memory, use \begin{quote}\begin{verbatim} ?- compile(myprogram, [debug:off]). \end{verbatim} \end{quote} The following command will create a precompiled file myprogram.eco from a source file called myprogram.ecl (or myprogram.pl): \begin{quote}\begin{verbatim} ?- compile(myprogram, [output:eco]). \end{verbatim} \end{quote} %---------------------------------------------------------------------- \section{Source Structure} %---------------------------------------------------------------------- The compiler normally reads files from beginning to end, but the file end can also be simulated with a clause \begin{quote} \begin{verbatim} end_of_file. \end{verbatim} \end{quote} When reading from a terminal/console, the end of the input can be marked by \notation{CTRL-D} (in Unix-like systems) or \notation{CTRL-Z}+\notation{RETURN} on Windows. When reading program source, the compiler distinguishes {\it clauses}, {\it directives} and {\it file queries}. Directives are terms with main functor \predspec{:-/1} while file queries have the main functor \predspec{?-/1}. Everything else is a program clause (see Appendix~\ref{chapsyntax}). The differences between a directive and a file query are as follows: \begin{itemize} \item File queries are general goals, and are executed when the program is loaded, i.e., when compiling with the load-option set to \notation{all}, or when loading a compiled file. When compiling without loading, they are ignored. \item Directives can be general goals, in which case they are executed while the program is being compiled, and also when a compiled program is loaded. \item Some directives are not goals, but are interpreted by the compiler (or other source processing tool), e.g., module-directives or pragmas. These should not be combined with general goals in the same directive. \end{itemize} Directives and file queries should succeed and should only have a single solution. No results are printed by the system, failure leads to a warning, and an error condition will cause compilation to abort. %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Clauses and Predicates} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - All other input terms are interpreted as clauses to be compiled. A sequence of consecutive clauses whose heads have the same functor is interpreted as one predicate. Normally, all clauses for one predicate should be consecutive in the source. If this is not the case, the compiler issues a warning and ignores the new clauses. To change this behaviour, a \bipref{discontiguous/1}{../bips/kernel/compiler/discontiguous-1.html} declaration must be used. The clauses are then collected and compiled as a whole once the end of the source unit (file or module) has been reached. To add clauses for a predicate incrementally though several independent compiler invocations is only possible by declaring the corresponding predicate as \bipref{dynamic/1}{../bips/kernel/dynamic/dynamic-1.html}, see Chapter \ref{chapdynamic}. %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Compilation and Modules} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In the absence of module-directives (\bipref{module/1}{../bips/kernel/modules/module-1.html}, \bipref{module/3}{../bips/kernel/modules/module-3.html}) within the file, the file content is compiled into the module from which \predspec{compile/1,2} itself was called. This context module may be modified using the \notation{@/2} notation, i.e., \notation{compile(File, Options)@Module}. Existing static predicates will be redefined, and clauses for dynamic predicates appended to the existing ones (unless the 'load' option requests otherwise). If the compiled file contains module directives (\predspec{module/1,3}), these specify to which module(s) the subsequent code belongs. Module directives are effective from the point where they occur until the next module directive, or until the end of file. If a module directive refers to a module that already exists, this module is erased and redefined (unless the 'load' option requests otherwise). It is generally recommended to follow the \emph{one file -- one module} convention, and to make the base name of the file identical to the module name. In rare cases, it may make sense to have an auxiliary module in the same file as the main module. This is allowed, and every new module directive terminates the previous module. To spread the code for one module over several files, use a top-level file containing the module directive plus one or more include-directives (section \ref{secinclude}) for the component files. %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Incrementality} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - When it encounters a \bipref{module/1}{../bips/kernel/modules/module-1.html} or \bipref{module/3}{../bips/kernel/modules/module-3.html} directive the compiler first erases previous contents of this module, if there was any, before starting to compile predicates into it. This means that in order to incrementally add predicates to a module, the module directive cannot be used because the previous contents of the module would be destroyed. Instead, the construct \notation{compile(File)@Module} must be used. %---------------------------------------------------------------------- \section{Directives} %---------------------------------------------------------------------- %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Modules and Declarations} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The following is a list of the directives most commonly used in source files: \begin{quote} \begin{description} \item[\biptxtref{:- module(\pattern{Name}).}{module/1}{../bips/kernel/modules/module-1.html}] Beginning of a module. \item[\biptxtref{% :- module(\pattern{Name},~\pattern{Exports},~\pattern{Dialect}).}{module/3}{../bips/kernel/modules/module-3.html}] Beginning of a module in a given dialect. \item[\biptxtref{:- local \pattern{Specs}.}{local/1}{../bips/kernel/modules/local-1.html}] Declaration of local items, e.g., syntax settings, operators, global storage, etc. \item[\biptxtref{:- export \pattern{Specs}.}{export/1}{../bips/kernel/modules/export-1.html}] Declaration of exported items, e.g., predicates, syntax settings, operators, etc. \item[\biptxtref{:- reexport \pattern{Specs}.}{reexport/1}{../bips/kernel/modules/reexport-1.html}] Declaration of reexported items. \item[\biptxtref{:- import \pattern{Specs}.}{import/1}{../bips/kernel/modules/import-1.html}] Declaration of imported modules or predicates. \item[\biptxtref{:- use_module(\pattern{Mods}).}{use_module/1}{../bips/kernel/modules/use_module-1.html}] Loading and importing of modules or libraries. \item[\biptxtref{:- lib(\pattern{Libs}).}{lib/1}{../bips/kernel/compiler/lib-1.html}] Loading and importing of libraries. \item[\biptxtref{:- meta_attribute(\pattern{Name},~\pattern{Handlers})}{meta_attribute/2}{../bips/kernel/termmanip/meta_attribute-2.html}] Declare a variable attribute. \item[\biptxtref{:- comment(\pattern{Type},~\pattern{Info})}{comment/2}{../bips/kernel/directives/comment-2.html}] Structured program documentation. \end{description} \end{quote} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Conditional Compilation} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The compiler and other source-processing tools recognise the conditional compilation directives \bipref{if/1}{../bips/kernel/directives/if-1.html}, \bipref{elif/1}{../bips/kernel/directives/elif-1.html}, \bipref{else/0}{../bips/kernel/directives/else-0.html} and \bipref{endif/0}{../bips/kernel/directives/endif-0.html}. The first two take a goal as their argument, and parts of the program source can be included or excluded depending of the satisfiability of that goal. For example, \begin{quote} \begin{verbatim} :- if(get_flag(hostarch, "i386_nt")). ...Windows-specific code... :- elif( (get_flag(version_as_list,Version), Version @>= [6,0]) ). ...code for version 6.0 and later... :- else. ...alternative code... :- endif. \end{verbatim} \end{quote} Note however, that only complete clauses or directives can be conditionally included. %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Include Directives} \label{secinclude} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Generally, it is best to use the module system to structure {\eclipse} applications, and to use one module per file. The modules then refer to each other via \predspec{use_module/1}, \predspec{lib/1}, or \predspec{import/1} directives. In rare cases it can make sense to split a single module into several files, which can then be pulled together using the following include directives: \begin{quote} \begin{description} \item[\biptxtref{:- include(\pattern{Files}).}{include/1}{../bips/kernel/directives/include-1.html}] The contents of the given Files are treated as if they occurred in place of the include directive. Files is a single file name or a list of them. \item[\biptxtref{:- [\pattern{Files}].}{'.'/2}{../bips/kernel/compiler/D-2.html}] A synonym for the include/1 directive. Note that the semantics of this construct when used as a directive (include semantics) differs slightly from its use as a goal or query (compiler/loader invocation). \end{description} \end{quote} Included files can contain clauses, directives and queries, but should not contain \predspec{module/1,3} directives, since they would be interpreted as occurring within the including file, and the included module would not end at the end of the included file. %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Compiler Pragmas} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \index{pragma}\index{compiler!pragma} Compiler pragmas are compiler directives which instruct the compiler to emit a particular code type, overriding the options given to the compiler. Their syntax is similar to directives: \begin{quote} \predspec{:- pragma(\pattern{Option}).}\indextt{pragma/1} \end{quote} It is not possible to have several pragmas grouped together and separated by commas, every pragma must be specified separately. {\it Option} can be one of the following: \begin{quote} \begin{description} \item[debug] - generate code which can be inspected with the debugger. This overrides the global setting of the \notation{debug_compile} flag, and any debug-option given to the compiler. \item[nodebug] - generate optimized code with no debugger support. This overrides the global setting of the \notation{debug_compile} flag, and any debug-option given to the compiler. \item[expand] - do in-line expansion of built-ins like \bipref{is/2}{../bips/kernel/arithmetic/is-2.html} and user-defined inline predicates. This code can still be inspected with the debugger but the expanded subgoals look differently than in the normal debugged code, or their arguments cannot be seen. This pragma overrides the global setting of the \notation{goal_expansion} flag, and any expand-option given to the compiler. \item[noexpand] - inhibit the in-line goal expansion. This pragma overrides the global setting of the \notation{goal_expansion} flag, and any expand-option given to the compiler. \item[opt_level(\pattern{Level})] - override the \notation{opt_level} option given to the compiler. \about{Level} is an integer greater or equal to 0. A zero setting disables all optional optimization. \item[skip] - set the \notation{skip} flag of all following predicates to \notation{on}. \item[noskip] - set the \notation{skip} flag of all following predicates to \notation{off}. \item[system] - set the \notation{type} flag of all following predicates to \notation{built_in}. Moreover, all following predicates will have unspecified \notation{source_file} and \notation{source_line} flags. \item[warnings] - enable compiler warnings, overriding any warnings-option given to the compiler. \item[nowarnings] - disable compiler warnings, overriding any warnings-option given to the compiler. \end{description} \end{quote} A pragma is active from its specification in the file until the file end or until it is disabled by another pragma. Recursive compilations or calls to other compiling predicates are not affected by the pragma. The pragmas are useful mainly for libraries and other programs that should be always compiled in a particular mode independently of the global flags or compiler option settings. %---------------------------------------------------------------------- \section{Precompiled (ECO) Files} %---------------------------------------------------------------------- %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Making Precompiled Files} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {\eclipse} source files can be compiled into {\eclipse} object files, \index{object code} for subsequent loading. These files have the \notation{.eco} suffix by default. This facility is mainly intended for module files. To create such a file, call the compiler with the appropriate output-option, e.g., \begin{quote} \begin{verbatim} ?- compile(myprogram, [output:eco]). \end{verbatim} \end{quote} This creates a precompiled file myprogram.eco from a source file called \notation{myprogram.ecl} (or \notation{myprogram.pl}). If the source file contained include directives, the result will be a single object file containing the compiled code of all included files. In earlier releases of {\eclipse} this was done using the \bipref{fcompile/1}{../bips/lib/fcompile/fcompile-1.html} predicate from the fcompile library, which is still supported for compatibility. Loading of {\eclipse} object files is significantly faster than compilation from source. In {\eclipse} 6.0, {\eclipse} object files are text files containing a representation of the compiled abstract machine code, and can be used to deploy application code without revealing the source. The precompiled code is hardware and operating system independent. It may however not be portable between different versions of {\eclipse} if details of the abstract machine were modified between releases. The global flag \notationidx{eclipse_object_suffix} determines the file suffix used for {\eclipse} object files. \subsection{Restrictions} Currently, the compiler generates the auxiliary predicates for the do iterator using a module-wide counter to name the predicates. Unfortunately this means that if an object file with auxiliary predicates is loaded into a module that already has existing code that contains auxiliary predicates, naming conflict can occur and the old auxiliaries may be replaced. It is thus strongly recommended that object files should not be loaded into an existing module. This will only be a problem if the file does not contain any module declarations that redefine the module (i.e., \bipref{module/1}{../bips/kernel/modules/module-1.html}), as these redefinition will erase the old copy of the module. %The predicate generates the object code by first compiling the program and %then outputting the object code. Directives, which are executed in a normal %compilation process, will not be executed during the output of the object %code (but the directives themselves will be added to the object code so %that they will be executed when the code is loaded). This can lead to %differences between loading the object code and compiling the program if %the directive affects the compiled code during the compilation %(e.g., determining which files to load by a conditional in a %directive). %If macro transformation is defined (via %\bipref{macro/3}{../bips/kernel/syntax/macro-3.html} %declarations) in the module that is fcompiled, then %the ``protecting functor'' {\tt no_macro_expansion} %\index{no_macro_expansion/1} \index{macro!no_macro_expansion} (see %section~\ref{usingmacros}) should be used to prevent the macro definition %itself from being transformed when the definition is generated by %fcompile. For example: % %\begin{quote}\begin{verbatim} %:- local macro(no_macro_transformation(foo/1), trans_foo/2, []). %\end{verbatim}\end{quote} % %\noindent %the {\tt no_macro_transformation/1} wrapper prevents this instance of {\tt %foo/1} from being transformed when the directive is generated by fcompile. %Note that this is only needed if all terms are transformed, and not for %goals or clause transformation. One restriction does apply between platforms of different word sizes: integers which fit in the word size of one platform but not the other are represented differently internally in {\eclipse}. Specifically, integers which takes between 32 and 64 bits to represent are treated as normal integers on a 64 bit machine, but as bignums (see section~\ref{intrep}) on 32 bit machines. This difference is normally invisible, but if such numbers occur as constants in the program code (i.e., their values appear textually), they can lead to different low-level compiled abstract code on the different platforms. Avoid using such constants if you want the object code to be portable across different word sizes (they can always be computed at run-time, e.g., writing \verb'2^34' instead of \notation{17179869184}). %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Loading Precompiled Files} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The following predicates either invoke the compiler or load precompiled\notation{.eco} files. If the source specification does not specify the file type, precompiled files are preferred if they can be found in the search path: \begin{quote} \begin{description} \item[\txtbipref{[\pattern{File1},...,\pattern{FileN}]}{(.)/2}{../bips/kernel/compiler/D-2.html}] This predicate can be used as a shorthand for the \predspec{compile} predicate, usually in the interactive toplevel. It accepts a list of files, which can be source files or precompiled files. \item[\biptxtref{ensure_loaded(\pattern{Files})}{ensure_loaded/1}{../bips/kernel/compiler/ensure_loaded-1.html}] This predicate compiles the specified file if it has not been compiled yet or if it has been modified since the last compilation. It can be used to load application code or system libraries. \item[\biptxtref{use_module(\pattern{Files})}{use_module/1}{../bips/kernel/modules/use_module-1.html}] A combination of \predspec{ensure_loaded/1} and \predspec{import/1}. \item[\biptxtref{lib(\pattern{Lib})}{lib/1}{../bips/kernel/compiler/lib-1.html}] This predicate is used to ensure that a specified library file is loaded. It is equivalent to \notation{ensure_loaded(library(\pattern{Lib}))}. If this library is not yet compiled or loaded, the system will look in all directories in the \notation{library_path} flag for a file with this name, which is either a source file or a precompiled file, and compile or load it. \item[\biptxtref{make}{make/0}{../bips/kernel/env/make-0.html}] This predicate recompiles or reloads all files that have been modified since their last compilation or loading. \end{description} \end{quote} To implement reloading/recompiling when needed, the system keeps track of when a particular source files was compiled or precompiled file was loaded into memory. This information can be accessed explicitly through \bipref{current_compiled_file/3}{../bips/kernel/compiler/current_compiled_file-3.html}. %\item[\biptxtref{assert(Clause)}{assert/1}{../bips/kernel/dynamic/assert-1.html}] %\index{assert/1} %This predicate compiles the given clause of a dynamic predicate. %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Using the Compiler with a Makefile} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - To generate .eco file from source files, the compiler can be run from the command line using the -e option. To invoke it from a makefile, use the following suffix rule \begin{quote} \begin{verbatim} .SUFFIXES: $(SUFFIXES) .ecl .eco .ecl.eco: eclipse -e "compile(\"$<\",[output:eco])" \end{verbatim} \end{quote} or a pattern rule for Gnu make: \begin{quote} \begin{verbatim} %.eco: %.ecl eclipse -e "compile(\"$<\",[output:eco])" \end{verbatim} \end{quote} %---------------------------------------------------------------------- \section{Special Compiler Features} %---------------------------------------------------------------------- %---------------------------------------------------------------------- \subsection{Compiling Non-Textual Source} %---------------------------------------------------------------------- A characteristic feature of Prolog and {\eclipse} is, that programs can be represented as data structures in a straightforward way. The compiler therefore provides the \bipref{compile_term/1}{../bips/kernel/compiler/compile_term-1.html} and \bipref{compile_term/2}{../bips/kernel/compiler/compile_term-2.html} interface predicates, which allow one to compile a list of terms. The compiler interprets these as clauses, directives and queries, similarly to what happens when the program source is being read from a file. For program generators, it is therefore not necessary to create a textual representation of generated code - the data structures can be compiled directly. There are the following minor differences between compilation from textual sources and term compilation: \begin{itemize} \item Module directives are not supported - to compile code into a certain module, use the construct compile_term(Clauses,Options)@Module, and use \bipref{create_module/1}{../bips/kernel/modules/create_module-1.html} to create modules beforehand if necessary. \item Include directives do not make sense and are not supported. \item No end-of-compilation events are raised---\predspec{compile_term/1} behaves more like the compilation of an included file in this respect. This implies that discontiguous predicates are not supported. \end{itemize} A variant of \predspec{compile_term/2} is \bipref{compile_term_annotated/3}{../bips/kernel/compiler/compile_term_annotated-3.html} which takes source terms with source position annotations. This can be used when compiling auxiliary code within inlining/goal expansions transformations, without losing the source position information which is needed by the debugger. %---------------------------------------------------------------------- \subsection{Mode Declarations} %---------------------------------------------------------------------- \indextt{mode/1} \index{mode declaration} Mode declarations are a way for the user to give some additional information to the compiler, thus enabling it to do a better job. The {\eclipse} compiler makes use of the mode information mainly to improve indexing and to reduce code size. Mode declarations are optional. They specify the argument instantiation patterns that a predicate will be called with at runtime, for example: \begin{quote} \begin{verbatim} :- mode p(+), q(-), r(++, ?). \end{verbatim} \end{quote} The possible argument modes and their meaning are: \newlength{\firstColumn} \newlength{\secondColumn} \settowidth{\firstColumn}{\notation{++}} \setlength{\secondColumn}{\textwidth} \addtolength{\secondColumn}{-\firstColumn} \addtolength{\secondColumn}{-7.5em} \begin{quote} \begin{tabular}[t]{l@{\hspace{1em}}p{\secondColumn}} \notation{+} & the argument is instantiated, i.e., it is not a variable;\\ \notation{++} & the argument is ground;\\ \notation{-} & the argument is not instantiated, it must be a free variable without any constraints, especially it must not occur in any other argument and it cannot be a suspending variable;\\ \notation{?} & the mode is not known or it is neither of the above ones. \end{tabular} \end{quote} Note that, if the actual instantiation of a predicate call violates its mode declaration, the behaviour is undefined. Usually, an unexpected failure occurs in this case. %---------------------------------------------------------------------- \subsection{Inlining} %---------------------------------------------------------------------- \index{inlining} \index{goal expansion} To improve efficiency, calls to user-defined predicates can be preprocessed and transformed at compile time. The directive \bipref{inline/2}{../bips/kernel/compiler/inline-2.html}, e.g., \begin{quote} \begin{verbatim} :- inline(mypred/1, mytranspred/2). \end{verbatim} \end{quote} arranges for \predspec{mytranspred/2} to be invoked at compile time for each call to the predicate \predspec{mypred/1} before this call is being compiled. The transformation predicate receives the original call to \predspec{mypred/1} as its first argument, and is expected to return a replacement goal in its second argument. This replacement goal replaces the original call in the compiled code. Usually, the replacement goal would be semantically equivalent, but more efficient than the original goal. When the transformation predicate fails, the original goal is not replaced. Typically, a predicate would be defined together with the corresponding inlining transformation predicate, e.g., \begin{quote} \begin{verbatim} :- inline(double/2, trans_double/2). double(X, Y) :- Y is 2*X. trans_double(double(X, Y), Y=Result) :- not nonground(X), % if X already known at compile time: Result is 2*X. % do calculation at compile time! \end{verbatim} \end{quote} All compiled calls to \predspec{double/2} will now be preprocessed by being passed to \predspec{trans_double/2}. For example, if we now compile the following predicate involving \predspec{double/2}: \begin{quote} \begin{verbatim} sample :- double(12, Y), ..., double(Y, Z). \end{verbatim} \end{quote} then the first call to double will be replaced by \notation{Y~=~24} while the second one will be unaffected. The code that the compiler sees and compiles is therefore \begin{quote} \begin{verbatim} sample :- Y = 24, ..., double(Y, Z). \end{verbatim} \end{quote} Note that meta-calls (e.g., via \bipref{call/1}{../bips/kernel/control/call-1.html}) are never preprocessed, they always go directly to the definition of \predspec{double/2}. Transformation can be disabled for debugging purposes by adding \begin{quote} \begin{verbatim} :- pragma(noexpand). \end{verbatim} \end{quote} to the compiled file, or by setting the global flag \begin{quote} \begin{verbatim} :- set_flag(goal_expansion, off). \end{verbatim} \end{quote} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \subsection{Clause Expansion} %- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Before compilation, the compiler also performs clause macro expansion (\bipref{macro/3}{../bips/kernel/syntax/macro-3.html}). This includes the DCG grammar rule expansion (section \ref{dcg}). %---------------------------------------------------------------------- \section{Writing Efficient Code} \label{secefficientcode} %---------------------------------------------------------------------- Even with a declarative language, there are certain constructs which can be compiled more efficiently than others. It is however not recommended to write unreadable code with the aim of achieving faster execution - intuition is often wrong about which particular construct will execute more efficiently in the end. The advice is therefore \begin{quotation} \emph{Try the simple and straightforward solution first!} \end{quotation} This will keep code maintainable, and will often be as fast or marginally slower than elaborate tricks. The second rule is to keep this original program even if you try to optimise it. You may find out that the optimisation was not worth the effort. {\eclipse} provides some support for finding those program parts that are worth optimizing. To achieve the maximum speed of your programs, choose the following compiler options: \begin{itemize} \item \notation{debug:off} ; \item \notation{opt_level:1} (the default); \item \notation{expand:on} (the default). \end{itemize} %Setting the flag {\tt variable_names} can also cause slight %performance degradations and it is thus better to have %it off, unless variable names have to be kept. %Unlike in the previous releases, the flag {\tt coroutine} %has now no influence on the execution speed. Some programs spend a lot of time in the garbage collection, collecting the stacks and/or the dictionary. If the space is known to be deallocated anyway, e.g., on failure, the programs can be often sped up considerably by switching the garbage collector off or by increasing the \notation{gc_interval} flag. As the global stack expands automatically, this does not cause any stack overflow, but it may of course exhaust the machine memory. When the program is running and its speed is still not satisfactory, use the profiling tools. The profiler can tell you which predicates are the most expensive ones, and the statistics tool tells you why. A program may spend its time in a predicate because the predicate itself is very time consuming, or because it was frequently executed. The port profiling tool gives you this information. It can also tell whether the predicate was slow because it has created a choice point or because there was too much backtracking due to bad indexing. One of the very important points is the selection of the clause that matches the current call. If there is only one clause that can potentially match, the compiler is expected to recognise this and generate code that will directly execute the right clause instead of trying several subsequent clauses until the matching one is found. Unlike most of the current Prolog compilers, the {\eclipse} compiler tries to base this selection ({\it indexing}) on the most suitable argument of the predicate.\footnote{% The standard approach is to index only on the first argument.} It is therefore not necessary to reorder the predicate arguments so that the first one is the crucial argument for indexing. For example, in a predicate like \begin{quote} \begin{verbatim} p(a, a) :- a. p(b, a) :- b. p(a, b) :- c. p(d, b) :- d. p(b, c) :- e. \end{verbatim} \end{quote} calls where the first argument is instantiated, like \notation{p(d,Y)}, will be indexed on the first argument, while calls where the second argument is instantiated, like \notation{p(X,b)}, will be indexed on the second. However, the decision is still based on only one argument at a time: a call like \notation{p(d,b)} will be indexed on the first argument only (not because it is the first, but because it is more discriminating than the second). If it is crucial that such a procedure is executed as fast as possible with such a calling pattern, it can help to define an auxiliary procedure which will be indexed on the other argument: \begin{quote} \begin{verbatim} p(X, a) :- pa(X). p(X, b) :- pb(X). p(b, c) :- e. pa(a) :- a. pa(b) :- b. pb(a) :- c. pb(d) :- d. \end{verbatim} \end{quote} The compiler also tries to use for indexing all type-testing information that appears at the beginning of the clause body (or beginning of a disjunction): \begin{itemize} \item Type testing predicates, i.e., \bipref{free/1}{../bips/kernel/typetest/free-1.html}, \bipref{var/1}{../bips/kernel/typetest/var-1.html}, \bipref{meta/1}{../bips/kernel/typetest/meta-1.html}, \bipref{atom/1}{../bips/kernel/typetest/atom-1.html}, \bipref{integer/1}{../bips/kernel/typetest/integer-1.html}, \bipref{rational/1}{../bips/kernel/typetest/rational-1.html}, \bipref{float/1}{../bips/kernel/typetest/float-1.html}, \bipref{breal/1}{../bips/kernel/typetest/breal-1.html}, \bipref{real/1}{../bips/kernel/typetest/real-1.html}, \bipref{number/1}{../bips/kernel/typetest/number-1.html}, \bipref{string/1}{../bips/kernel/typetest/string-1.html}, \bipref{atomic/1}{../bips/kernel/typetest/atomic-1.html}, \bipref{compound/1}{../bips/kernel/typetest/compound-1.html}, \bipref{nonvar/1}{../bips/kernel/typetest/nonvar-1.html} and \bipref{nonground/1}{../bips/kernel/typetest/nonground-1.html}. \item Explicit unification and value testing \txtbipref{=/2}{(=)/2}{../bips/kernel/termcomp/E-2.html}, \txtbipref{==/2}{(==)/2}{../bips/kernel/termcomp/EE-2.html}, \biptxtrefni{\bsl==/2}{'\\=='/2}{../bips/kernel/termcomp/REE-2.html}% \index{\bsl==/2@\bsl\notation{==/2}} and \biptxtrefni{\bsl=/2}{'\\='/2}{../bips/kernel/termcomp/RE-2.html}\index{\bsl=/2@\bsl\notation{=/2}}. \item Combinations of tests with \txtbipref{,/2}{','/2}{../bips/kernel/control/C-2.html}, \bipref{;/2}{../bips/kernel/control/O-2.html}, \bipref{not/1}{../bips/kernel/control/not-1.html}, \txtbipref{$->$/2}{->/2}{../bips/kernel/control/-G-2.html}. %\item Arithmetic testing predicates %\txtbipref{$<$/2}{(<)/2}{../bips/kernel/arithmetic/L-2.html}, %\txtbipref{=$<$/2}{(=<)/2}{../bips/kernel/arithmetic/EL-2.html}, %\txtbipref{$>$/2}{(>)/2}{../bips/kernel/arithmetic/G-2.html}, %\txtbipref{$>=$/2}{(>=)/2}{../bips/kernel/arithmetic/GE-2.html} if one argument %is an integer constant and the %other one known to be of the integer type. \item A cut after the type tests. \end{itemize} If the compiler can decide about the clause selection at compile time, the type tests are never executed and thus they incur no overhead. When the clauses are not disjoint because of the type tests, either a cut after the test or more tests into the other clauses can be added. For example, the following procedure will be recognised as deterministic and all tests are optimised away: \begin{verbatim} % a procedure without cuts p(X) :- var(X), ... p(X) :- (atom(X); integer(X)), X \= [], ... p(X) :- nonvar(X), X = [_|_], ... p(X) :- nonvar(X), X = [], ... \end{verbatim} Another example: \begin{verbatim} % A procedure with cuts p(X{_}) ?- !, ... p(X) :- var(X), !, ... p(X) :- integer(X), ... p(X) :- real(X), ... p([H|T]) :- ... p([]) :- ... \end{verbatim} %Integers less than or greater than a constant can also be %recognised by the compiler: %\begin{verbatim} % p(X) :- integer(X), X < 5, ... % p(7) :- ... % p(9) :- ... % p(X) :- integer(X), X >= 15, ... %\end{verbatim} %If the clause contains tests of several head arguments, only the %first one is taken into account for indexing. Here are some more hints for efficient coding with {\eclipse}: \begin{itemize} \item Arguments which are repeated in the clause head and in the first regular goal in the body do not require any data moving and thus they do not cost anything. For example, \begin{quote} \begin{verbatim} p(X, Y, Z, T, U) :- q(X, Y, Z, T, U). \end{verbatim} \end{quote} is just as cheap as \begin{quote} \begin{verbatim} p :- q. \end{verbatim} \end{quote} On the other hand, switching arguments requires data moves and so \begin{quote} \begin{verbatim} p(A, B, C) :- q(B, C, A). \end{verbatim} \end{quote} is somewhat more expensive. \item When accessing an argument of a structure whose functor is known, unification and \bipref{arg/3}{../bips/kernel/termmanip/arg-3.html} are both similarly efficient, so the question of whether to write \notation{Struct = emp(_,~X,~_)} or \notation{arg(2,~Struct,~X)} is just a matter of taste and style. We recommend that the structure notation (see section~\ref{chapstruct}) \index{structures} be used, as it improves readability without adding any overhead. So, for example, use \notation{Struct~=~emp\{salary:X\}} or \notation{arg(salary~of~emp,~Struct,~X)}. \item Tests are generally rather slow unless they can be compiled away (see \about{indexing}). %\item When processing all arguments of a structure, using %\txtbipref{=../2}{(=..)/2}{../bips/kernel/termmanip/EDD-2.html} %and list predicates is always faster, more readable %and easier analyzable by automated tools than using %\bipref{functor/3}{../bips/kernel/termmanip/functor-3.html} %and \bipref{arg/3}{../bips/kernel/termmanip/arg-3.html} loops. %\item Similarly, when adding one new element to a structure, using {\bf =../2} %and \bipref{append/3}{../bips/lib/lists/append-3.html} is faster than %functor/arg. \item Waking is more expensive (due to the priority mechanism) than metacalling which is more expensive than compiled calls. Metacalls however do not carry as heavy a penalty as in some other Prolog systems. \item Sorting using \bipref{sort/2}{../bips/kernel/termcomp/sort-2.html} is very efficient and it does not use much space. Using \bipref{setof/3}{../bips/kernel/allsols/setof-3.html}, \bipref{findall/3}{../bips/kernel/allsols/findall-3.html} etc. is also efficient enough to be used every time a list of all solutions is needed. %\item using {\bf not not Goal} is optimised in the compiler %to use only one choice point. \item \txtbipref{=/2}{=/2}{../bips/kernel/termcomp/E-2.html} and \txtbipref{==/2}{==/2}{../bips/kernel/termcomp/EE-2.html} are faster than \txtbipref{=:=/2}{=:=/2}{../bips/kernel/arithmetic/ENE-2.html}. \item \txtbipref{:/2}{:/2}{../bips/kernel/control/N-2.html} is optimised away by the compiler if both arguments are known. \item Starting from {\eclipse} 6.0, there is no performance difference between using multiple clauses or using disjunction or if-then-else cascades. In fact, the compiler normalises multiple clause predicates into a single-clause representation with inline disjunctions. Disjunctions are indexed. \item Conditionals (i.e., \notation{$\ldots$->$\ldots$;$\ldots$}) are compiled more efficiently if the condition is an indexable built-in test. \end{itemize} %---------------------------------------------------------------------- \section{Implementation Notes} %---------------------------------------------------------------------- The {\eclipse} compiler is actually contained in the eclipse library \notation{lib(ecl_compiler)} which relies on a number of auxiliary modules. It uses \biptxtref{lib(source_processor)}{library(source_processor)}{../bips/lib/source_processor/index.html} to read programs, and produces abstract machine code that is assembled using \biptxtref{lib(asm)}{library(asm)}{../bips/lib/asm/index.html}. The built-in predicate \bipref{als/1}{../bips/kernel/compiler/als-1.html} or \bipref{asm:wam/1}{../bips/lib/asm/wam-1.html} lists the abstract code of the given predicate and it can thus be used by experts to check if the predicate was compiled as expected. %HEVEA\cutend