==========
A .NET-base implementation of Prolog based on the Warren Abstract Machine (WAM) architecture.
(Forked Prolog.NET by R. Todd from CodePlex)
Prolog.NET is a CLI-based (ECMA International 2006) Prolog interpreter based on the Warren Abstract Machine (WAM) architecture.
The original paper describing what would become known as the Warren Abstract Machine was published by David H. D. Warren in 1983 (Warren 1983). A book clarifying and expanding on the details in this paper was published by Hassan Aït-Kaci in 1991 (Aït-Kaci 1991).
Prolog.NET deviates from the standard WAM architecture in a few important respects. Most significantly, it relies on the garbage collection support provided by the CLI. No explicit memory management is performed by Prolog.NET. All variables, environments and choice points reside in the CLI heap.1 To ensure objects in the heap can be reclaimed in a timely fashion, Prolog.NET must still respect the context of variables when binding variables to other variables and properly “unwind” variable bindings during backtracking.
In the original WAM architecture, the terms “variable” and “value” in opcode names refer to unbound and bound variables, respectively. Prolog.NET uses the terms “unbound variable” and “bound variable”. Further, the WAM architecture uses the term “constant” to refer to integers, strings and other extra-logical objects.2 Prolog.NET reserves instead the term “value” for this use.
Prolog.NET can be called directly from client applications. A WPF-based IDE is also supplied.
The following code demonstrates the use of Prolog.NET from client code:
CodeSentence codeSentence;
codeSentence = Parser.Parse("hello(world)");
Program program = new Program();
program.Add(codeSentence);
codeSentence = Parser.Parse(":-hello(X)");
Query query = new Query(codeSentence);
PrologMachine machine = PrologMachine.Create(program, query);
ExecutionResults results = machine.Run();
Prolog.NET is available at GitHub.
The following projects are included:
- Prolog: the primary assembly containing the Prolog.NET compiler and interpreter.
- PrologWorkbench: a WPF application used for editing, running and debugging Prolog.NET programs.
- PrologTest: a console application used for testing.
- PrologSchedule: a WPF application demonstrating the use of Prolog.NET from a client C# application.
- PrologLibrary: an assembly containing external functions callable by Prolog.NET programs.
- PrologWorkbenchSetup: a deployment project for PrologWorkbench and other supplemental programs. The parser used by Prolog.NET is implemented using Lingua.NET. The Lingua.NET runtime is distributed as part of the Prolog.NET package. More information about Lingua.NET is available Here.
Prolog.NET consists of a Prolog compiler and interpreter based on the WAM architecture and modified to make use of the Common Language Infrastructure (CLI) (ECMA International 2006). It is written in C# (ECMA International 2006). This section contains additional information about the architecture and design of Prolog.NET.
The code in Prolog.NET can be divided into a set of distinct functional domains.
The Grammar domain contains the terminals and nonterminals that define the Prolog.NET grammar. The classes in this domain rely on the Lingua.NET compiler library. They produce as output a representation of the parsed input using classes in the CodeDOM domain. See “Grammar” on page 22 for a specification of the grammar used by Prolog.NET.
All classes in this domain are in the Prolog.Grammar namespace.
The CodeDOM domain provides a run-time representation of Prolog.NET language elements. All CodeDOM classes are immutable and, with some exceptions, are serializable. CodeDOM structures are created by the grammar and passed as input to the Prolog.NET compiler. They also provide the means to pass data to and from external library functions.
CodeDOM classes implement value equality. There is no semantic distinction between CodeDOM structures that differ based solely on reference equality tests.
All classes in this domain are in the Prolog.Code namespace.
The Compiler domain contains the WAM compiler used by Prolog.NET. The compiler accepts as input a CodeDOM structure representing a rule, fact or query and produces a WAM instruction stream.
A WAM instruction stream is represented as an array of WamInstruction structures. It can also contain attributes – instances of classes that inherit from WamInstructionStreamAttribute – associated with specific instructions within the stream. Attributes are used to associate the names of permanent variables with instruction registers, and specify the entry points of individual procedure clauses within an instruction stream.
Persistence or serialization of WAM instruction streams is not supported at this time.
The Program domain supports the management of Prolog.NET applications. The Program class and related child classes allow programs to be created, modified and persisted. Client applications can create or modify Programs using CodeDOM structures. The Program domain also includes a Query class. As with programs, queries are created using the appropriate CodeDOM structure.
Because CodeDOM structures are immutable, queries and individual procedure clauses can maintain references to user-supplied CodeDOM structures without compromising their integrity.
Programs isolate client applications from the WAM compiler and the WAM instruction streams associated with individual procedures. Programs expose program instruction streams –façades over underlying WAM instruction streams – that provide client applications protected access to the underlying WAM instruction stream. Program instruction streams are represented as lists of program instruction objects and, unlike WAM instruction streams, are better suited to WPF binding. Further, program instruction objects expose properties such as IsCurrentLocation that reflect the current run-time state of the underlying WAM machine.
Programs can reference libraries - collections of externally callable functions. By default, all programs reference the library exposed by the Library.Standard property.
The WAM Machine domain contains the WAM machine and associated run-time support structures. To evaluate a query, a WAM machine is constructed for the query and associated program. When the specified query has been evaluated, the WAM machine becomes obsolete.
All WAM machine classes are declared as internal and are not directly manipulated by client applications.
The Prolog Machine domain provides client access to the underlying WAM machine and associated run-time structures. As with program instruction streams, the PrologMachine class and related child classes provide a protected façade over the underlying WAM machine. Among other things, they implement the concept of a run-time call stack, something that does not have a direct analog in the WAM machine runtime.
Prolog.NET supports a call-level interface that provides access to externally defined methods. Methods are grouped into libraries which in turn are referenced by programs.
Methods are used to define predicates and functions. Predicates can be used within the body of a query or rule instead of a program procedure. For example:
is_liquid_temperature(F) :- greater_equal(F, 32), less_equal(F, 212).
Functions are used within expressions. For example:
celsius_to_farenheit(C,F) :- F is add(multiply(C, 1.8), 32).
Certain methods have associated operators. The above rules can be rewritten using their corresponding operators as follows:
is_liquid_temperature(F) :- F >= 32, F =< 212.
celsius_to_farenheit(C,F) :- F := C * 1.8 + 32.
With some exceptions, a method can be used as both a predicate and a function.