CON-PROLOG 7.0 - Details

CON-PROLOG 7.0 is both the latest version of LPA's true 32-bit Prolog compiler, and also the first version of LPA's brand new 64-bit Prolog compiler. The 32-bit version is available for all versions of Microsoft Windows, from Windows 98SE right up to Windows 8, and everything in-between, while the 64-bit version has been built for Windows 7 and later. Key features of CON-PROLOG include:

  • Source and Object Code Compatibility: CON-PROLOG is fully compatible with th esource and object code files of WIN-PROLOG, and either system can be used to compile and build applications for the other as well as for itself.
  • Unlimited Memory (X64): Gone forever is the pain of trying to squeeze large data sets or huge structures into just 2Gb of memory. With the 64-bit version of WIN-PROLOG, the only limit to directly addressable memory is how much is installed on a given computer
  • Huge File Support: Gone is the old 2Gb limit on individual file sizes, WIN-PROLOG now directly supports data files of up to 2^53-1 (X86) or 2^64-1 (X64) bytes in size, up to 64 of which can be open at any one time. This new feature gives WIN-PROLOG the capability to access vast file-based datasets, as well as perform more mundane tasks such as managing large video and other media files
  • Native x87 Floating Point Package: A brand new high-precision, floating point maths package has been written to replace the previously-used emulation library that was used since the earliest days of 386-PROLOG. The new package is faster, more accurate, and has been extensively tested for over a year prior to public release
  • XML Support: Extended Markup Language (XML) import and export is supported through a collection of special predicates, which allow XML files or streams to be read as tokens or nested terms, and written with or without indented formatting, to support web-centric and other data processing applications
  • JSON Support: JavaScript Object Notation (JSON) import and export is supported through a collection of special predicates, which allow JSON files or streams to be read and written as nested terms, to support AJAX and web-based technologies
  • Soft Meta-Predicate Definitions: the meta_system/2 predicate can now be modified by the user, in order to produce improved program listings, debugging, call-graph and cross-referencing behaviour where user-defined meta-predicates are employed
  • Windows 10 Support: CON-PROLOG is now fully compatible with Windows 10, while still working great on all versions of the operating system since Windows 98SE
  • Musical Instrument Digital Interface (MIDI): comprehensive support for the Musical Instrument Digital Interface (MIDI) opens up a whole new world of experimental research and analysis of music, as well real-time recording and playback
  • Windows Sockets (WinSock) Support: a set of predicates and special system events makes the programming of client and server TCP/IP applications easy, giving CON-PROLOG programs full access to the Internet
  • Dynamic Memory Reallocation: all heaps, stacks and major memory buffers can be reconfigured at runtime, during execution of any query, to allow flexible use of resources during large, complex computations
  • Easy Installation: the entire CON-PROLOG system comes as a simple download, together with all documentation and associated toolkits (flex, Prolog++, Intelligence Server, etc)
  • Full Unicode Support: CON-PROLOG supports the full Unicode 3.1 character set in files, in addition to the byte-oriented ASCII and ISO/IEC 8859-1 character sets, as well as an arbitrary 32-bit character set
  • True Hashed Compilation: CON-PROLOG includes a special mode of compilation, in which hash tables can be produced for huge Prolog databases to provide highly efficient execution of applications such as WordNet
  • Automatic Configuration: the same files run on Win_10, Win_8, Win_7, Vista, WinXP, Win2k, WinNT, WinME and Win98, and fully support features of each version of the platform
  • Source Level and Box Model Debuggers: these make full use of windows and other GUI features to make program testing and debugging as easy as possible
  • Efficient Runtime System: CON-PROLOG is implemented in 32-bit assembler language (MASM), and employs advanced techniques to achieve outstanding runtime performance, easily attaining speeds of around 10 megalips on faster Celeron and Pentium II machines
  • Dynamic Link Libraries: CON-PROLOG can load and access code in DLLs written using standard Windows development languages, including Visual C/C++, Visual Basic and Delphi
  • Direct Windows API interface: virtually any Windows API function, or third-party DLL function, can be directly called from CON-PROLOG, without the need to resort to C/C++ programming
  • True 32-bit Implementation: a genuine Win32 application makes up to 4Gb (4096Mb) of memory is directly addressable, without complex internal segmented addressing schemes
  • Small Memory Requirements: needs as little as 4Mb of memory: as much space as possible is made available for use by user's applications code
  • Edinburgh Standard Syntax: fully conforms to the industry standard syntax, including support for DCGs, term expansion and other advanced features
  • Quintus Prolog Compatibility: the system was designed from the outset with QP compatibility as a key objective
  • 64-bit Arithmetic: full-featured, efficient double precision built-in floating point maths library complements the 32-bit integer arithmetic
  • Incremental and Optimised Compilation: all the flexibility of a traditional interpreter is combined with the runtime speed of fully compiled code
  • Operating System Control: full featured access to the operating system gives Prolog programs full control of files, directories, environment variables, time and date, and allows other applications to be executed
  • User-definable System Hooks: many events, such as errors, spypoints, timers and messages can be directly programmed in Prolog
  • Special Data Types: efficient text manipulation is supported by a true string data type, and four linked data types efficiently support compound terms
  • Sophisticated Data Compression: Lempel/Ziv data compression and decompression routines are built in, and are used both for saving/loading system files, and for general user-specified applications
  • Powerful Data Encryption: data can be encrypted or decrypted with a unique and uncrackable algorithm, using a comb-filtered Marsaglia/Zaman random number generator whose key size is an amazing 1185 bits
  • Secure Hashing and Message Digests: full support is given for a number of industry standard data integrity checks, including the CRC-32 Cyclic Redundancy Check, MD5 Message Digest and SHA-256 Secure Hash Algorithm
  • Stand-alone Applications: the Developer edition of CON-PROLOG allows self-contained, stand-alone applications to be built and distributed; end users need never know that their systems are implemented in Prolog

CON-PROLOG: Easy to Install and Use!

The entire CON-PROLOG 7.0 system comes as a simple download, ready to unzip and use, without any special installation. If you know Prolog, just fire it up and go; otherwise, you can download and read details of all its predicates in the WIN-PROLOG documentation. Just remember that the Window and Graphics features are omitted in CON-PROLOG!

CON-PROLOG: for Windows 10, 8, 7, Vista, XP, 2000, NT, ME and 98SE

In this section we will look a little more closely at some of the special features of CON-PROLOG. The system is a true 32-bit application, which nonetheless runs under the older Windows systems (98SE onwards). It is totally integrated with the Windows operating system, and utilises a standard input and output (STDIO) console for debugging and running programs.

A full source-level debugger utilises a special dialog in which you can scroll through program source code, variable bindings, and other information. A multi-level break facility allows you to escape from the debugger to run supplementary queries before returning. A traditional box model debugger, together with a collection of small, special purpose debuggers, complements the source-level debugger to provide unprecedented flexibility in program testing.

Direct Windows API Interface

As well as providing high-level access to around 100 Windows API (Application Programming Interface) functions, not to mention numerous subfunctions, CON-PROLOG includes a special interface which allows your programs to call virtually any C function directly, whether defined in the Windows API or in a DLL or other module. The winapi/3 predicate allows any function, defined in any 32-bit module, to be called with any number of parameters. The parameters may be integers, string pointers, or arbitrary structures, and facilities exist for defining named "memory files". All memory allocation and stack frame creation is carried out automatically, so your only job as a programmer is to provide the relevant data and call the function.

Memory Files

As well as creating or opening files on disk, CON-PROLOG has the powerful ability to open "virtual" files in memory: these have no disk image, and can be of any size within available resources. Ideal as temporary scratchpads during complex data operations, they are both extremely fast (no need to bother the hard disk) and avoid the usual worries about how best to name a temporary file: they don't have external names!

Modelled on the original buffers that implemented to provide storage for use in conjunction with the winapi/3 predicate, these new memory files can be used with any and all of the standard Prolog input/output predicates, as well as to store virtually any data directly. Applications which require the storage of large numbers of small data items (such as bit tables) are especially helped by this feature.

True 32-bit Assembler-coded Implementation

The CON-PROLOG kernel is implemented entirely in 32-bit assembler to provide the best overall performance possible on 386, 486, Pentium or Pentium Pro platforms, with just enough 32-bit C to interface it to the Win32 API of Windows Vista, XP, 2000, NT, ME and 98. Thanks to its tight implementation, the entire CON-PROLOG system requires under 2Mb of disk space, and can be installed without having to modify any Windows or System directories, although two Microsoft files, RICHED20.DLL and MSLS31.DLL are updated with later versions on older versions of Windows.

32-bit Memory Access: the 4 Gigabyte "Limit"

A significant advantage of the true 32-bit implementation is that all pointers and integers are 32 bits wide, giving CON-PROLOG the ability directly to address up to 4 gigabytes (4096 megabytes) of memory. You can divide memory in any way you like between program, text and dynamic data: there are no built-in limits or restrictions. CON-PROLOG can directly use every single byte of memory on your computer.

Huge File Support

CON-PROLOG uses special "floating integer" numbers to provide direct access to files up to 10^53-1 bytes in size: that's 9,007,199,254,740,991 bytes, or if you prefer, about 9 million gigabytes, or 9 thousand terabytes, in size. And moreover, it can open and handle up to 64 such files simultaneously, with full random access for both reading and writing. Such massive files greatly exceed the size of storage available today, so effective provide no upper limit to file size. On a more practical note, this means that items such as large video files can be processed easily.

Thorough Quintus Prolog Compatibility

CON-PROLOG has been designed from scratch for Quintus Prolog (QP) compatibility. This extends well beyond the obvious requirement of duplicating the built in predicates of QP, as it includes special features such as logical file names, background housekeeping of predicates/file relationships, and much more. Most applications will port directly from QP to CON-PROLOG, as the file management support isolates user programs from the intricacies of the host operating system.

Linear Garbage Collection

With all the memory available to the designers, it would have been tempting to skimp on garbage collection features. However, the garbage collection and memory management within CON-PROLOG is more complete and advanced than in any other commercial Prolog system.

The evaluation stacks and heap are managed by a linear garbage collector: doubling the size of evaluation space roughly doubles the time taken to collect garbage on any one occasion, but garbage collection occurs only half as often. The result is that there is no degradation of performance, when even vastly different sizes of evaluation space are used. A fixed size cell allocation scheme avoids any risk of memory fragmentation.

Text space is used to store the bodies of atoms and strings, and is managed as a special heap. It too is fully garbage collectable. Program space is used to store clauses and optimised programs, and is totally reclaimable when these programs are abolished. Both text and program spaces use a special segmented heap format which guarantees that every last byte of memory can be used, with no fragmentation or degradation problems, however many times items have been added or removed.

The Incremental Compiler

CON-PROLOG is based on an incremental compiler, whereby all clauses in a program are compiled at all times. Because the compiler is incremental, individual clauses can be added by programs - just as in a conventional interpreter. In fact, assert/1 is implemented as a call to the compiler. But CON-PROLOG goes beyond simple clause level compilation, maintaining dynamic first argument indexing (even into compound terms), which can result in considerable runtime performance improvements over previous LPA Prologs.

Programs can be incrementally decompiled too, allowing predicates like clause/1 and retract/1 (and even listing/1) to be implemented. Both the incremental compilation and decompilation routines are written in assembler code, and are very fast, matching the speed of their interpreter equivalents - but the clauses they manage run some 3-4 times faster than they would in an interpreter.

The Optimising Compiler

The incremental compiler/decompiler does not perform multi-argument indexing, or the space-saving last clause and other optimisations - they would simply be too complex to change on the fly during assert/1 or retract/1. With this in mind, CON-PROLOG provides an alternative optimising compiler.

The optimising compiler can perform all the optimisations just mentioned, and more. There is full support for multiple-argument indexing, which enable the very fast matching of clauses on any arbitrary argument (as opposed to the single first-argument indexing the incremental compiler and other Prolog systems), and a complete analysis of variable usage is performed on relations. Any variables which can be left in situ between calls are left so, substantially reducing the data traffic in most programs.

Optimised programs can run some 2-3 or more times faster than incrementally compiled ones, and use less space during execution. Decompilation of these programs is not possible, so your source code will remain completely hidden in applications.

64-bit Floating Point and 32-bit Integer Arithmetic

A fully-featured, 64-bit double precision floating point arithmetic library is built in to CON-PROLOG. This is accessed directly by the is/2 predicate, which in turn is implemented entirely in 32-bit assembler. The library provides high-speed, high-precision arithmetic computations, and includes support for standard "calculator" functions, trigonometric and logarithmic functions, floating point to integer conversion and truncation functions, maximum and minimum functions, and pseudo random numbers. Direct support is also provided for 32-bit integer style shift, rotate and bitwise logical functions. The most common use of the is/2 predicate is for the simple adding or subtracting of two integers, and this case is specially optimised, being handled entirely in the integer domain wherever possible.

For special systems applications, a 32-bit integer, reverse polish notation evaluator is provided, once again implemented in 32-bit assembler. This evaluator provides very high speed computation of integer expressions, and supports the standard "calculator" functions, bitwise logical functions, and pseudo random numbers.

The carefully researched, pseudo random number generator is useful in a variety of applications, including games, simulations and data encryption. For speed, it is implemented in integer arithmetic, and uses a very high potency linear congruential algorithm, with a period of 2^64. The single, seedable generator is shared between the floating point and integer evaluators, so switching portions of code between these two domains will not violate the integrity of a pseudo random sequence.

Powerful Input and Output Features

One of CON-PROLOG's great strengths is its powerful collection input and output subsystems. As well as the standard see/1, tell/1, read/1 and write/1 style predicates, support is given for formatted I/O, binary I/O, and the manipulation of a number of special I/O streams, including device and string streams as well as disk files.

Formatted I/O primitives provide complete control of the output of atoms, strings, numbers and other items. Fixed field display, with left or right justification, optional truncation, and free field formats are all supported. Numbers can be output in fixed point, signed or unsigned integer, and even non-decimal base formats (anything from base 2 (binary), through base 16 (hexadecimal) right up to base 36).

Matching formatted input allows structured records to be read in with automatic type checking. As well as the obvious applications such as writing or reading data in tabular formats, the formatted I/O predicates make it easy to build interfaces to ASCII files from other applications.

Text String Data Type

While the traditional Prolog "string", namely a list of 8-bit integers, is a powerful means by which to manipulate small pieces of text, it is extremely inefficient as a way of storing text. This inefficiency would be compounded in a 32-bit Prolog system, where each one-character element of the list would need 10 bytes of storage on the dynamic heap. To enable bulk text handling applications, CON-PROLOG includes a true text string type. Any number of such strings may exist in Prolog terms, and each may contain up to 64Kb of text. Because of the way these strings are stored, garbage collection is still quick and efficient, and even string space cannot become fragmented.

Many built in predicates use strings as a means of passing large amounts of text or binary data around, for example between a window buffer and a disk file. In addition, strings may be used as input and output streams: for example, the call:

?- listing ~> String.

would bind the variable String to a string containing the entire text of a program listing. This string could be manipulated, displayed in a window, and processed in virtually any fashion.

Strings provide a data type with a high bandwidth for communications between CON-PROLOG and low-level data types, such as files and screen buffers. They are of particular importance as parameters in CON-PROLOG's extensive library of Windows GUI predicates.

LZSS Data Compression

An interesting feature in CON-PROLOG is the provision of a pair of routines for LZSS data compression and decompression. These are used internally by the system state save and restore predicates, but are also available for general use in user programs through two special I/O predicates. A modified version of the original LZ77 algorithm, LZSS uses a sliding window to hold processed data, while a look-ahead buffer peeks into the stream of data yet to be compressed. Depending upon the sizes of sliding window and look-ahead buffer, compression ratios of up to 64:1 are theoretically possible for highly patterned data; in practice, ratios of 2:1 to 4:1 are more usual.

There are many potential applications of LZSS compression: these include the creation of stuffed archive files, which contain an accumulation of compressed files with their names, creation dates/times and attributes, the simple stuffing of individual files, such as bitmaps, which normally use large amounts of disk space, or the compacting of data which needs to be transmitted by modem or some other slow device. More advanced uses might include the creation of mixed database files consisting of uncompressed index information, and compressed data records.

MZSS Data Encryption

As its name suggests, MZSS encryption makes use of a Marsaglia/Zaman pseudo random number generator (PRANG), which has the primary benefit of offering a very large key size (1185 bits, compared with just 64 bits in CON-PROLOG's existing linear-congruential PRANG!). The MZ/PRANG is seeded by a user-specified password of up to 148 characters, and successive numbers are then combined (XOR) with the plaintext in order to encrypt it, or with the cyphertext in order to decrypt it. Two special features of MZSS encryption make it especially secure: "comb filtering" and "sequence variation".

Although having excellent random properties, and a massively long cycle (well over 2^1180 numbers in the sequence), there is a weakness in the pure MZ/PRANG. If a history of the previous 37 numbers is visible, it is possible to guess the next one +/- 1 bit: if the first 37 characters of a document's plaintext are known, this is quite sufficient for an intelligent attack to decrypt the rest of the document. MZSS encryption prevents such an attack with the help of "comb filtering", in which only a random sample of numbers from the MZ/PRANG sequence are actually used.

Another common attack on simple cyphertext is to find some other document to which both the encrypted and decrypted version are available. Suppose that a document, VULNERABLE, is to be attacked, and the attacker has access to the PLAINTEXT and CYPHERTEXT versions of another document: on the (fairly reasonable) assumption that same password has been used to encode both VULNERABLE and CYPHERTEXT, it is possible to decode the former, at least as far as length of the PLAINTEXT document, by combinding PLAINTTEXT and CYPHERTEXT to obtain an intermediate KEYSEQUENCE, then combining this with VULNERABLE to generate the desired DISCOVERED document. MZSS encryption prevents such an attack by adding additional data to the user's password: this results in "sequence variation", so that even if the same password is used on more than one occasion, the random sequence it generates is completely different each time.

Term and Data Management

There are many special features in CON-PROLOG geared towards term and data management. An assembler-coded, high speed list/merge sort algorithm gives truly stunning performance. Displaying ln2(X) performance characteristics, it is capable of sorting lists of 10,000 elements in around two seconds on a 25MHz 386. The sort/3 predicate goes beyond the functionality sort/2, by allowing you to define a sort key of arbitrary depth: if the elements in the list you are sorting are complex compound terms, you can uniquely identify which subterm you want to use for sorting. This powerful feature allows you, for example, to sort a given list of names and addresses by surname, street name, town or post code, simply by changing the search key parameter.

The Operating System Interface

As you would expect from LPA's Prolog implementations, CON-PROLOG has a huge library of operating system interface functions, providing for disk file and directory management, program execution, the reading of environment variable strings, and time and date functions.

Predicates allow you to create, rename and remove files or directories, and you can test and modify file attributes and timestamps. File directories can be read according to file name and attribute matching, returning information about each file's size, time and date.

For specialist time and date applications, a built in predicate allows you to compute absolute day numbers for any given date, or vice versa, allowing days between dates, lunar phases, and other such calculations to be made.

Programmable Interrupt Timers

For special purposes, up to 64 completely independent, programmable timers may be set or tested. When a timer expires, it interrupts the execution of CON-PROLOG, and calls a specially defined user "hook" predicate. This predicate can perform various operations, before resetting the timer. Because of the design of the timers, real-time synchronisation is maintained, even if an individual hook is delayed in its operation. Uses for timers include timeouts on user input, periodic updating of clock or calendar displays, the writing of sophisticated profile tools, and so on.