Delphi Component

The Delphi Logic Server Component provides a wrapper on the Logic Server DLL that presents the Logic Server in a manner more consistent with Delphi use. It includes: The sections of this document are:

Installation

The Logic Server Component, TLSEngine, is implemented in the Object Pascal unit amzi.pas for 32-bit Delphi. You can use it as an Object Pascal unit by simply including a reference to it in the USES section of your application, or you can install it in the Delphi component library.

It is important to follow the directions carefully when installing amzi.pas as a Delphi component. Delphi must be able to find both amzi.pas and amzi.dll. The directions assume that you set your environment variable PATH to include amzi\bin. Replace N in the directions with the version of Delphi you are using.

  1. Open Delphi.
  2. Select from the menu 'Component/Install Component…'
  3. Select the 'Into existing package' tab which will by default install into the "Borland User Components" package in the file \borland\delphiN\Lib\dclusr.dpk.
  4. Press the button marked 'Browse' next to the 'Unit file name' box.
  5. Select \amzi\lsapis\delphi\amzi.pas
  6. Note the search path should now include amzi\lsapis\delphi.
  7. Select 'OK' on the Install Component dialog box.
  8. Select 'Yes' on the 'Package dclusr.dpk will be rebuilt' confirmation box.
  9. Select 'OK' on the dialog box informing you that TLSEngine has been added to the package.
  10. You should now see the Amzi! flying squirrel logo in the Additional components.

Note: When embedding Prolog code in Delphi, make give your XPL file a different name than your Delphi EXE file. This is necessary so that Amzi! Prolog does not try to use Delphi's CFG file and vice versa.

Hello Prolog

To build the Hello program from Delphi, first install the Logic Server Component as described above. (You can skip this step if you want, see note at end of this section.)

You can run the existing sample by opening the project hellop.dpr in the directory samples\delphi\hello, and running it. To build your own version, start a new project and save the unit as hello.pas (Hello Delphi Source Code) and the project as hellop.dpr. Select the Logic Server Component from the Additions page of the components palette, and place it on the form. Change its name to ls.

Select a button and put it on the form. Change its name to Hello. Add a click event handler. In the event handler, add the code from the sample program and run it.

(If you don't want to install the Logic Server Component, amzi.pas, on the component palette, you can still use it. Simply add 'amzi5' to the 'uses' list for the unit, and define a variable which is an instance of the Logic Server. Use the same code as before, but, if the object is not a part of your form you must remember to 'create' and 'destroy' the object as well.)

Overview

The Amzi! Logic Server Delphi component (TLSEngine) is designed to give the Delphi programmer easy access to the services provided by the Logic Server DLL.

The Logic Server Component is distributed in source form in the file amzi.pas. You can build your own components on top of it, or derive your own version from a copy.

When you compare the methods of the component, you'll find they extend, and in some cases, modify, the native LSAPI functions. The differences are:

Philosophically, the component preserves as much of the flavor of the LSAPI as possible, and augments it to provide a more Delphi-like interface.

Using the Component

To include the Logic Server in an application, simply place the Logic Server component, from the Additions page of the component palette, on a form. Typically it will become part of the main form.

You can also do this manually, by including 'Amzi' in the uses section of a unit and creating a variable for the Logic Server, such as LSEng: TLSEngine. If you do that, make sure you create and destroy the instance of the Logic Server.

To call the Logic Server, simply embed the API calls in the methods of your application. You will need to open and close the Logic Server as well.

Implementing Extended Predicates

Delphi, like C/C++, Java and VB 5.0 (and later), can be used to implement custom extended predicates to the Prolog language. These custom extensions give the Prolog code the ability to directly access anything Delphi can access.

The Delphi functions that implement extended predicates, must be declared as returning type TTFi, and as export. They can be added one at a time, avoiding pointers to arrays, using the API function AddPred, which adds a single predicate at a time.

Note: Extended predicate definitions must always be added after calling InitLS and before calling LoadXPL.

Note: The 32-bit Logic Server DLL uses the stdcall calling convention, so that must be specified in the extended predicate definitions.

The sample in directory \samples\delphi\deltest includes examples of a number of Logic Server capabilities, including extended predicate definitions. \samples\delphi\delgui contains a toolkit of a number of extended predicates that provide various GUI services to Prolog.

Reference

This section contains the interface portion of the unit amzi.pas, which defines the Logic Server Component. You can browse the source code for full details.
  • Logic Server Types
  • Functions to Set Up Logic Server
  • Functions for Extended Predicates
  • Functions for Calling Prolog
  • Functions for Dynamic Clauses in Logicbase
  • Functions for String/Term Conversion
  • Functions for Making/Getting Prolog Types
  • Functions for Manipulating Structures
  • Functions for Manipulating Lists
  • Functions for Prolog Stream I/O
  • Delphi Miscellaneous Functions
  • Logic Server Types

    These are the simple type definitions used by the Logic Server. They are mapped to the API types when calling the DLL. See \AMZI5\INCLUDE\amzi.pas for details.

    Logic Server Set-Up

    These functions provide the basic API services. They are used to initialize and close down the Prolog environment. The function, Main, runs the main/0 predicate of a load Prolog file.

    InitLS, LoadXPL and CloseLS are preferred forms for Delphi to avoid name conflicts with other components with similar names.

    They are based on the API functions Init, InitLSX, AddLSX, AddPred, InitPreds, Load, Main, Reset, and Close.

    Extended Predicates

    When you write an extended predicate, you can directly manipulate the Prolog parameters to that function. These predicates provide that service. The Get family retrieves the nth parameter that was used in the call, and the Unify family unifies some computed result with the nth parameter.

    The Delphi interface contains a number of type-specific additions to the basic API. Functions such as GetLongParm and UnifyPStrParm are examples.

    These functions are based on the API functions GetParm, GetParmType, UnifyParm, and StrParmLen.

    Calling Prolog

    These are the functions that actually call predicates in a Prolog logicbase/program. The query term can be represented as a string or a Prolog term. The first argument, a term, is always unified with the result of the call. The Redo function initiates backtracking, which reunifies the term with the next result.

    ClearCall is only useful if you start a Redo loop and don't finish. It clears the stack.

    The 'PStr' versions of the function calls use Pascal strings.

    These functions are based on the API functions Exec, ExecStr, Call, CallStr, Redo, and ClearCall.

    Dynamic Clauses in Logicbase

    These functions make it easy to assert and retract dynamic clauses to and from Prolog's logicbase. The 'Pstr' versions use Pascal strings. These functions are based on the API functions Asserta, AssertaStr, Assertz, AssertzStr, and Retract.

    Converting Strings/Terms

    These functions convert strings to terms and terms to strings. The 'PStr' versions use Pascal strings. The 'Q' versions create quoted strings, when necessary for atoms and strings that require delimiter symbols. The 'Q' versions are necessary for those cases where you want to use the resulting string in another query. These functions are based on the API functions TermToStr, TermToStrQ, and StrToTerm.

    Making/Getting Prolog Types

    These functions map Prolog types to Delphi types. The type-specific Get functions are Delphi additions. These functions are based on the API functions MakeAtom, MakeStr, MakeInt, MakeFloat, MakeAddr, GetTermType, and GetTerm.

    Manipulating Structures

    These Prolog structure-manipulating functions let you create structures, and take apart terms that represent structures. This is especially useful for getting at various arguments in a query. In the sample code, there is a query 'sibling(mary, X)'. The GetPStrArg function can be used to get the second argument of this structure, after a CallPStr has caused the variable to be bound. (See sample code.) These functions are based on the API functions GetFA, MakeFA, UnifyArg, GetArg, GetArgType, StrArgLen, and Unify.

    Manipulating Lists

    These list manipulation functions let you create Prolog lists, add items to lists, and retrieve items from lists. The PopList family of functions can be used in loops to get all the items in a list. Note that, because PopList doesn't invoke the Prolog engine or unification, it does not return a Boolean. It returns a normal function return code, in which 0 means success and anything else indicates the end of the list has been reached. (See sample code.) These functions are based on the API functions MakeList, PushList, and PopList.

    Prolog Stream I/O

    These functions let you capture and redirect Prolog I/O. These functions are based on the API functions SetStream, GetStream, SetInput, and SetOutput.

    Miscellaneous Functions

    These miscellaneous functions are used to change the Prolog streams, get the version number, and work with Prolog error codes.

    These functions are based on the API functions SetStream, GetStream, GetVersion, ErrMsg, ErrRaise, and ErrReadBuf.

    Copyright ©1987-2011 Amzi! inc. All Rights Reserved. Amzi! is a registered trademark and Logic Server is a trademark of Amzi! inc.