Communication between prolog and an external process5274821Abstract An improved architecture for a list processing language interpreter/compiler is described to facilitate two-way communication between list processing programs and other external processes. The new architecture employs a table driven approach to translate arguments from the list processing language to arguments that other external processes expect. Additional capability for accessing list processing programs from external processes is also provided. Claims What is claimed is: Description FIELD OF THE INVENTION
______________________________________
get.sub.-- structure `*`/2,A1
% d(*/2(
unify.sub.-- variable A1
% U,
unify.sub.-- variable Y1
% V),
get.sub.-- variable Y2,A2
% X,
get.sub.-- structure `+`/2,A3
% +/2(
unify.sub.-- variable A4
% SS1,
unify.sub.-- variable A5
% SS2),
get.sub.-- structure `*`/2,A4
% SS1 = */2(
unify.sub.-- variable A3
% DU,
unify.sub.-- value Y1
% V),
get.sub.-- structure `*`/2,A5
% SS2 = */2(
unify.sub.-- value A1
% U,
unify.sub.-- variable Y3
% DU)
______________________________________
Can be replaced with the inventive coding scheme by adding two new instructions shown below. unify.sub.-- stack Unify.sub.-- stack works like unify.sub.-- varible, but instead of storing the argument in a stack, it stores the argument in a register. pop.sub.-- structure F Pop.sub.-- structure F works like get.sub.-- structure F, Ai excepts that it pops a word from the stack and uses this word instead of Ai. With these instructions the prior art code shown above can be rewritten as shown below.
______________________________________
get.sub.-- structure `*`/2,A1
% d(*/2(
unify.sub.-- variable A1
% U,
unify.sub.-- variable Y1
% V),
get.sub.-- variable Y2,A2
% X,
get.sub.-- structure `+`/2,A3
% +/2(
unify.sub.-- stack %
unify.sub.-- stack %
get.sub.-- structure `*`/2
% = */2(
unify.sub.-- value A1
% U,
unify.sub.-- variable Y3
% DU)
pop.sub.-- structure `*`/2
% = */2(
unify.sub.-- variable A3
% DU,
unify.sub.-- value Y1
% V),
______________________________________
Now, in the above code, the first get.sub.-- . . . instruction always uses A1 and the next get.sub.-- . . . instructions of indice i use Ai. It is possible to add a new register S0 which is reset by instructions like try.sub.-- . . . (before beginning the processing of a predicate) and which is incremented by one each time a get.sub.-- . . . instruction is executed. Thus, each get.sub.-- . . . uses as register argument, the register of index S0, so this argument does not need to be explicitly coded as part of the instruction. The same steps are equally effective for the put.sub.-- . . . instructions. The first argument of the predicate of a tail of a clause for the Prolog instruction b(hello) is put.sub.-- constant hello, A1, and the classical encoding of the first argument is shown in FIG. 11. The code.sub.-- op of the instruction 560 is a value indicative of the put.sub.-- constant instruction. The code.sub.-- op 560 is followed by a reference to the register that is used for the operation 570, and an index to the constant 580. Each of the fields must be separately parsed to verify the correct information was provided. Also, an index field, like 580, requires the value contained in the index field be added to the appropriate offset register to obtain the address of the constant. These operations are time consuming and account for much of the degradation of execution speed associated with an interpreter. An alternative is to put the full constant in the instruction instead of coding it as an offset or an address. This technique makes fetching of the constant a little faster, but generates a larger instruction. FIG. 12 shows the encoding of the first argument in accordance with the subject invention. Since the address of the constant "hello" is all that is required for the instruction, a word of information with the sign bit set to zero is sufficient to completely convey the information required for the first argument. Once again, no explicit recitation of an argument value is necessary for the interpreter to execute the instruction. Further, no processing time for indirect indexing is required to obtain the address of the constant. Alternatively, as all abstract instructions begin with an op code of one byte and a Prolog object is a tagged word, where the first byte is the tag, it is possible to choose for op code of the unify.sub.-- constant instructions, the value of the type atom. Thus, the unify.sub.-- constant "hello" instructions can be replaced by the representation of the atom "hello". It is also possible to do that for get.sub.-- constant, put.sub.-- constant, put.sub.-- structure and get.sub.-- structure with the type skeletons. Now if this transformation is applied to both unify.sub.-- constant, put.sub.-- constant and get.sub.-- constant, the problem is that each of these instructions have exactly the same representation. This problem is overcome by employing a finite automata processor as shown in FIGS. 13A-13C. The separate instructions are distinguished by using a 4 main state automata. The states are arg, built, read, and write. The automata avoids the step of performing an explicit test of the execution mode (read/write) during the processing of any of the unify.sub.-- . . . instructions. In some cases, the context is not sufficient to allow the automata to predict the mode of the next instruction. For example, if an atom, which has to be interpreted has an unify.sub.-- constant, is followed by a get.sub.-- variable, the automata knows that the get.sub.-- variable has to be executed in an arg mode. However, if an atom, which has to be interpreted as a unify.sub.-- constant, is followed by another atom, this is fine if the second atom has to be interpreted as an unify.sub.-- constant, but if it has to be interpreted as a get.sub.-- constant, then the code generator must insert a pop.sub.-- head instruction between these instructions. Pop.sub.-- head implies emulation has to go further in arg mode. Prolog instructions generally have a format containing an opcode and a plurality of fields similar to the get.sub.-- constant and put.sub.-- constant instructions provided above. Any instruction that previously required an explicit register recitation and/or an implicit address calculation realize significant improvements in execution by suppressing the need to decode arguments that are displaced by the invention. FIG. 13A-13C is a flowchart graphically depicting the logic associated with instruction processing in accordance with the invention. Interrupt Processing One of the inventive features of the Prolog system is the new motion of interrupts in Prolog. Some multi-tasking capability is necessary in Prolog, but adding interrupt processing is extremely difficult because Prolog uses pre-allocated linear stacks. Thus, a copy of the entire stack is required for each Prolog task to assure system integrity is maintained. Interrupt processing is easier to implement because all of the interrupted programs can share the same stacks. Interrupt processing is possible by setting a flag registering the occurrence of an interrupt. Then, each time that a new predicate is fired, the flag tracking interrupts is checked to determine if an interrupt has occurred and to initiate processing of the interrupt. This architecture restricts interrupt processing to a single location within Prolog system processing thus exploiting standard Prolog predicate processing mechanisms. Allowing the execution of a predicate to be preempted at any time by the execution of another predicate makes the writing of an optimizing complier for Prolog very difficult. The introduction of two kinds of interrupts is used to diffuse this problem. The first, TYPE 1, alters execution so that when an interrupt, such as predicate p(X), is activated instead of the current predicate c(. . . ), the executed goal is: p(X) & c (. . . ). NOTE: the execution of p(X) may fail or create some backtrack nodes. The second, TYPE 2, alters execution so that when an interrupt, such as a predicate p(X), is activated instead of the current predicate c(. . . ), the executed goal is: (p(X) & fail; true) & c(. . . ). NOTE: the execution of (p(X) & fail; true) will never create a backtrack or modify the instantiation state of the Prolog variables. TYPE 1 interrupts introduce backtrack nodes in a rather random way and their use in fully compiled code is limited to a small subset of specific interrupts. The content of the Prolog stack is exactly the same before and after the execution of TYPE 2 interrupts, so Prolog can ignore TYPE 2 interrupts when it performs long range optimization of the compiled program. Thus, a TYPE 2 interrupt can be activated before the activation of any predicate of a compiled Prolog code. Interrupts are useful in Prolog for: 1. activating frozen predicates; 2. debugging step-by-step; 3. activating the garbage collector; and 4. allowing users to process asynchronous events. Non-Polling Techniques For Interrupt Processing The PROLOG system must avoid software polling for interrupts during execution to optimize execution. Logical interrupts and daemons are used to provide non-polling interrupt processing. Logical interrupts are software concoctions that register the occurrence of asynchronous events occurring during the execution of a PROLOG program. The event eventually initiates another PROLOG program called a Daemon defined by PROLOG or customized by a user Prolog program. The best analogy to a Daemon in classical computer processing is a task. A task is a set of instructions often for a single purpose that often requires specific inputs to execute. Tasks can be suspended while they await completion of other tasks that may feed information to a suspended task. A Prolog Daemon is initiated to process the interrupt during the designated time between predicates. Some examples of logical interrupt processing are provided below. Delayed Evaluation Predefined PROLOG logical interrupts include delayed evaluation. Delayed evaluation is the instantiation of a frozen variable. A frozen variable is a variable awaiting the completion of another goal to complete its processing. The Daemon is the waiting predicate in this example. A frozen variable is a special unbound variable. When a value is given to this variable, a user defined Prolog predicate is triggered. GARBAGE COLLECTION The logical interrupt is the global of trail stack overflow, and the Daemon is the garbage collector. When a stack overflow occurs, the size of the stack is incremented by a small amount to allow the Prolog process to continue until the next Type 1 interrupt is detected. Then, the garbage collector processes the stack to reclaim space. The small incremental areas, one for the trail stack and one for the global stack, are preallocated when the stacks are initialized. The garbage collection cannot be done when the stack overflow occurs, but occurs at the activation of the next predicate. This is due to the uncertainty of leaving elements in the middle of a computation. STEP BY STEP DEBUGGER The logical interrupt is the step from one predicate to the next, and the Daemon is the Debugger itself. EXTERNAL TERMINAL INTERRUPT The logical interrupt is the action of the user via terminal entry, and the Daemon is the PROLOG user code that is discussed above as the handler of the terminal interrupt. INTERRUPT PROCESSING LOGIC The interrupt events are captured asynchronously from normal PROLOG execution via logical interrupt processing. However, the events are analyzed and processed at execution "safe points" only. The "safe points" occur at the switch from one predicate to the next predicate. At that moment, PROLOG must check to determine whether any pending interrupts require attention. This determination requires only a test of a memory location (flag), approximately two instructions: 1. test Flag for pending interrupt, and 2. branch on Flag to the logical interrupt handling routines. PROLOG clearly needs a better way to handle pending logical Interrupts without testing for them explicitly. The invention exploits the common invocation mechanism of predicate processing used in all Prolog systems. All predicates whether interpreted, incrementally compiled, or fully compiled, use the same (short) sequence of instructions commonly located in a permanent read-write area named "CSINT". At location "EXEC" in "CSINT" the predicate invocation sequence starts. When no logical interrupt is pending, the sequence locates the next predicate execution address and branches to the predicate for normal execution. This is standard Prolog predicate processing. However, when a logical interrupt is pending, the first instruction of that sequence is replaced by a branch to the logical interrupt handler routine. The replacement occurs when the asynchronous event occurred, that is, when the logical interrupt was recorded. In addition to setting the interrupt trap in the "EXEC" instruction, the logical interrupt enqueues on an external logical interrupt queue. When branched to from "EXEC", the logical interrupt handler transfers the contents of the external queue, to the internal logical interrupt queue, and the external queue is emptied. Careful use of the external queue is necessary to assure that its modification in the logical interrupt recording routine, and the logical interrupt handling routine, employ a "CS" instruction (Compare and Swap). During the transfer from the external queue to the internal queue, the logical interrupts are ordered by priority. Then the pending logical interrupt with the highest priority is dequeued and its associated daemon is scheduled for execution. If the internal queue is emptied by the dequeuing, then the interrupt trap reverts to its normal value and executes the normal, next predicate. Detailed Interrupt Logic When an interrupt associated with a predicate p(X,Y,k(0)) is detected, the control block shown in FIG. 14 is constructed in the heap stack to process the logical interrupt. IT.sub.-- BLOCK 800 is the address of the predicate descriptor of p(*,*,*). .rarw.ITNEXT 805 is a pointer to the address of the next interrupt control block, or zero if there are no other interrupts that require processing. X 810 is a pointer to the globalization information for X. Y 815 is a pointer to the globalization information for Y. k(0) 820 is a pointer to the globalization information for k(0). Two global words in common storage, WAITITS and WAITITU are used to flag the occurrence of an interrupt. WAITITS is used to flag interrupts sensitive to backtracking, while WAITITU is used to flag interrupts insensitive to backtracking. The word WAITITU/WAITITS contains a zero if no interrupt has occurred or the address of the first interrupt control block if an interrupt has occurred. The interrupt trap is set when WAITITU or WAITITS is non-zero. There is use for both interrupts sensitive to backtrack and insensitive to backtrack. For example, if there is a Prolog interrupt associated with system command Stop Predicate (SP), and if the predicate Prolog associated to the interrupt is defined as `stop the execution of the current command`, then after someone has entered the SP command, the associated Prolog interrupt will be activated and will stop the execution. Even if backtrack is activated between the entering of the SP command and the execution of the associated interrupt, the program is stopped. Thus, this kind of interrupt is insensitive to backtrack processing. An example of an interrupt that must be sensitive to backtracking is shown below. a(4,0). a(.sub.--,.sub.--). :-ge(X,0) when not var(X), a(X,1). `ge(X,0) when not var(X)` activates the interrupt associated with ge(X,0) as soon as X receives a value. In the example, the execution is the goal:-a(X,1) tries unify a(X,1) with a(4,0). To do that it binds X to 4. This triggers the interrupt associated with ge(X,0). Now ge(4,0)), so ge(4,0) will be added to the list of active interrupts. Then, Prolog attempts to unify 1 and 0. This step fails, so the backtrack activates. This backtrack restores X to the free state. As the interrupt ge(X,0) is related to the fact that X is not a variable, ge(X,0) must be removed from the list of active interrupts to avoid error. This kind of interrupt needs clearly to be sensitive to backtrack. Following the update of the WAITITU/WAITITS word, an interrupt control block similar to FIG. 14 is added at the end of the linked list of interrupt control blocks anchored by the address contained in WAITITU/WAITITS. If an initial interrupt control block is already present, then the chain of next interrupt pointers 805 is traversed until a next interrupt pointer 805 equal to zero is found. The zeroed next interrupt pointer 805 is updated with the address of the new interrupt control block. Then, if backtracking is necessary to restore processing following the interrupt, information for backtracking is pushed onto the trail stack so backtrack will restore the proper values after interrupt processing. The Prolog EXEC predicate processor is modified to check the contents of WAITITS/WAITITU before executing the next predicate. If a non-zero value is detected, then the first interrupt control block is activated and the associated WAITITS/WAITITU word is updated with the next interrupt control block found in ITNEXT 805. If the update is on the WAITITS, then the trail stack is also updated. Next, a new frame is created by executing an allocate instruction and pushing the predicate descriptor of Proc and the arguments of Proc into the local frame. The arguments of p(*,*,*) are loaded in the Ai registers from the interrupt control block 810, 815 and 820. Then, the continuation pointer is set to the system address ITRET and the clauses associated with the interrupt are activated. When interrupt processing is completed, Prolog returns to the address at ITRET and preforms the following operations. First, the Ai registers are reloaded from the previous frame by employing the continuations pointer. Then, the predicate descriptor, E and P pointers are reloaded from the frame. Finally, execution commences from the address specified by the predicate descriptor. FIGS. 15A-15F is a block diagram showing the logic associated with adding interrupt processing to Prolog in accordance with the subject invention. The stacks and other elements of Prolog are described in detail in the preceding text. FIG. 15A shows the state of Prolog when the test for interrupt is done before the execution of an example predicate a(V,b) when no interrupt is active. FIG. 15B shows Prolog's state before the test for interrupt execution just before the execution of the predicate a(V,b) when a Type 2 interrupt associated with predicate p(X,Y,k(O)) is waiting. FIG. 15C shows Prolog's state when a Type 2 interrupt associated with the predicate p(X,Y,k(O)) has been processed before the execution of the predicate a(V,b). FIG. 15D shows Prolog's state before testing for interrupt prior to the execution of predicate a(V,b). There is a Type 1 interrupt associated with the predicate q(3) waiting. FIG. 15E shows Prolog's state when a Type 1 interrupt associated with the predicate q(3) has been processed before the execution of the predicate a(V,b). FIG. 15F shows Prolog's state when a Type 1 interrupt associated with the predicate q(3) was processed just before the execution of the predicate a(V,b). Rerouting the first instruction of the common invocation sequence facilitates PROLOG's logical interrupt processing without any polling overhead. General Language Interface The details of the data structures used by Prolog to interface to other programming languates are presented below. The data structures are employed in the conversion of data arguments from Prolog to other languages. The data structures and other processing described herein provide capability heretofore unknown in Prolog. Argument Descriptor Prolog is able to call procedures written in C, Cobol, Fortran and PL/1. Prolog may transmit arguments to the procedures, formatted as the language requires. To convert the data arguments from the Prolog format to the format expected by the procedures, Prolog uses a descriptor table employing processing that macro-expands the Prolog information to the format that the target language expects to receive. The descriptor table enables Prolog to convert arguments to another language in a language independent manner. The technique also accommodates new releases with increased flexibility. Prolog actually becomes language independent because the variations for individual languages are placed in the data structures. No modification to user programs is necessary when a new release of a language becomes available. Changes are only required in the associated tables. Thus, source code modifications are minimized. Also, generalization of the descriptor table's design supports all data formats, arrays and structures. General Background For Prolog, an external extension is a separately compiled program module. It is recognizable as a Prolog external extension because it contains an external extension header. The header serves as an identifier for an external predicate set type of external extension. Every external predicate or external computable expression is described in turn with its name, arity, and in the case of an external extension in another language, with its expected arguments. Whereas external extensions written in assembler may directly process Prolog data structures, external extensions written in another language must receive their data in the appropriate form for the particular language. This requirement implies that the interface to the languages external extensions must convert Prolog data structures into a form suitable for processing by the complied external extensions. Further, the interface must convert back to Prolog the results returned by the external extensions. A language external predicate or external computable expression is a subprogram. In Cobol this implies an entry, in Fortran a subroutine or function, in PL/1 a procedure and a function in C. The parameters expected by the subprogram are declared in name, and type in other language statements that open the subprogram in the external extension source files. As part of a general external predicate or external computable expression external extension header, PRODECE macro instructions describe every external extension-external computable expression in turn. If the external extension is described as a language type external extension, then the ARGS=Descriptor.sub.-- Label in the PRODECE macro points to the PROARGS macro instruction of the particular external predicate or external computable expression. Description Of The PROARGS Macro The PROARGS macro instruction has the following format ##STR1## where every descriptor describes in turn one parameter of the language subprogram, or, in the case of the C programming language, nesting and fields in structs. One descriptor may have one of the four following formats: 1) (C only) Open a level of C struct; 2) (C only) Close a level of C struct; 3) (DATA.sub.-- TYPE IO.sub.-- TYPE) Describe one scalar parameter or (C only) one scalar field of a struct, 4) (DATA.sub.-- TYPE IO.sub.-- TYPE DIMENSIONS) Describe one array parameter or (C only) one array field of a struct. Data.sub.-- Type specifies the possible conversion target types. It belongs to the standard/XA data types. FIG. 16 shows the correspondence between Data.sub.-- Type 900 and the standard data types of 370/XA Assembler 905, C 910, Cobol 915, Fortran 920, and PL/I 925. IO.sub.-- Type specifies whether the argument is an input to or result from the language subprogram. When used in a C struct, all IO.sub.-- Type of the struct must take the same value. IO.sub.-- Type may take the following values: I Member of the Parameter list, Input to the subprogram. In C, argument passed by pointer--to be used as a * parameter. O Member of the Parameter list, Result of the subprogram. In C, argument passed by pointer--to be used as a * parameter. IO Member of the Parameter list, Input to the subprogram, modified by the subprogram, and the result of the subprogram. In C, argument passed by pointer--to be used as a * parameter. R Register return argument (Fortran functions, PL/1 procedure . . . RETURNS(. . .), and C functions). Result of the subprogram. In C, argument returned by value--not to be used as a * parameter. V (C only) Member of the Parameter list. Input to the subprogram, argument passed by value--not be used as a * parameter. A (C only) Register return argument (C functions). Result of the subprogram returned by pointer--to be used as a * parameter. The subprogram, argument passed by value--not to be used as a * parameter. Finally, dimensions, if specified, indicate that the argument or C struct field, is an array. Dimensions may be one or more of N that describe the exact dimension of the array, or ARGN (Refer Dimension) that specifies that another Descriptor--the one of rank n in the increasing sequence of argument/ struct fields is to contain the actual dimension. Referring to FIG. 17, a C subprogram is presented for an example of the inventive interface. FIG. 18 presents the Prolog Proargs interface information for the C subprogram. In FIG. 17, Uc 950 is input, SI 955 is input, Dv 957 is input, Dp 959 is input and output, where Cp 961 is input, Fa 963 is output, Ip 965 is input and output, and where SI 955 contains the actual dimension of the array Ip 965. The corresponding PROARGS macro instruction is illustrated in FIG. 18. Argument Descriptor Format The PROARGS macro instruction is translated into a set of binary descriptors that the Prolog language interface uses to convert the Prolog data to another language format. The interface is a general interpreter of these binary descriptors. The binary descriptor format is shown in FIG. 19. The conversion processes are descriptor driven, and take six steps to complete. Step One Copy into Read-Write storage of the descriptors; Relocate the "FORCDIM1" Refer fields; Setup the "FORFDIM, FORFDEF" flags; Setup the "FORDAL2, FORDAL4, FORDAL8" flags, according to the field alignment rules of C; Computation of the arity "FORDSKE" for every level of C struct nesting, to the fields alignment rules of C, Check the arity of the external predicate or external computable expression. STEP Two Conversion of every I/IO/V argument. STEP 3 Storage Allocation for every O argument. STEP 4 If there are V arguments, copy the Parameter list and the V arguments together. STEP 5 Actual language call STEP 6 Conversion back of every IO/O/R/A argument. The interface between Prolog and other languages relies extensively on the information provided by the PROARGS macro to build the data in the formats expected by the compiled program. This format is rich enough, and the conversion routines powerful enough to handle all known types of data (binary, floating point, character); any number of array dimensions and any array dimension; dimensions that are fixed once and for all or dimensions that the compiled program expects in another argument, parameter passing as by value, by address, or by register, parameters passed as input, or returned as output or both, any kind of C structure, including nested struct, along with the automatic alignment checking. Details of the Interface The Prolog system of the subject invention provides a general interface to routines written in a compiled language. One of the values of this interface is to subsidize Prolog's shortcoming in support for intensive computation. A programmer can reserve the numerically intensive parts of an application for implementation in a more suitable language. The interface allows a Prolog application to employ Fortran subroutines or functions, PL/1 Non-MAIN Procedures, and similar facilities in other languages as deterministic Prolog predicates or as Prolog expressions. The Prolog interface also manages the operating system dependent portions of a compiled program, and converts Prolog data types towards and from their equivalents in the compiled languages. Fortran Example A basic VS/FORTRAN example is provided in Z1FORT1 FORTRAN. A similar capability is provided for other programming languages such as COBOL, PLI, PASCAL, C, and Assembler. The differences between the interfaces for the other languages are discussed in a separate section. Organization Of An External Predicate 1. Write one or more Function/Subroutine in a compiled language. For example, the sources could be placed in MYFORT1 FORTRAN. It is useful to gather into the same source file all Subroutines and Functions that are used by a Prolog program, to optimize the time devoted to environmental setup. Further, the FORTRAN and COBOL languages allow only a single active program at any time. This restriction does not apply to "Block Structure Compiled Languages" like PASCAL or PL/1. 2. Add the information shown in FIG. 20 following the Main program statement in the source code. In other languages, name the main program Z1MAIN, and let the main program only call Z1COMH without arguments. These names are fixed. NOTE: The main program must contain any global declarations and initialization. In FORTRAN, this implies declaration and initialization of the COMMON areas. This processing must take place before the call to Z1COMH. Global cleanup, if needed, must also take place in the main program, after the call to Z1COMH. 3. Prepare an ASSEMBLE descriptor file named MYFORT0 ASSEMBLE, according to the instructions of the next chapter. 4. Compile the FORTRAN source file, generating MYFORT1 TEXT. 5. Assemble the ASSEMBLE descriptor file with MACLIB: Prolog, which generating MYFORT0 TEXT. 6. Concatenate as one TEXT file, say MYFORT TEXT, the following three files in order. a. A TEXT file obtained from the compiled descriptor file (MYFORT0 TEXT); b. A Z1COMP1 TEXT file provided by Prolog; and c. A TEXT file generated by compiling the FORTRAN source file, (MYFORT1 TEXT). 7. Provide linkage to a GLOBAL TXTLIB to the compiled language lubraries (for VS/FORTRAN V2, it is named VSF2FORT TXTLIB). 8. LOAD the concatenated TEXT file with options NOAUTO CLEAR RLDSAVE. 9. GENMOD the concatenated Text file. 10. Add an entry into the file Prolog NAMES, of the form: ##STR2## 11. Do not forget to keep a GLOBAL LOADLIB or GLOBAL TXTLIB, if it is necessary for the compiled language (GLOBAL LOADLIB VSF2LOAD in VS/FORTRAN V2) 12. Use the predicates and expressions as indicated below. 13. Upon completion of execution, expect some log of the errors caught by the compiled language. Parameter Passing The Prolog interface is designed to accommodate the majority of data types used by the various programming languages. Thus, all data types that FORTRAN recognizes, can be exchanged in both directions between Prolong and Fortran. No restrictions are placed on the type of instructions that the FORTRAN program may perform. This means that COMMON management, File or Terminal IOs, FORTRAN recovered errors, . . . , are all allowed. However, the Fortran program cam only access the data areas assigned to Fortran. Thus, access to the Prolog areas directly from the Fortran application is not permitted except via the call interface. Example Code Some examples are provided in FIG. 21, 22, and 23. FIG. 21 illustrates the source code for the function called STUPID. The function STUPID is used to test the interface and the FORTRAN Error Recovery. FIG. 22 illustrates the declaration of the STUPID function with a source listing of Z1FORT0 ASSEMBLE. FIG. 23 illustrates the information displayed when the STUPID is called during a Prolog program execution. To declare arrays, place the dimension information in the descriptor of the argument in addition to its type and IO control. For each dimension of the array, place a number, if that dimension is fixed, or a reference like ARGn where n is positive integer, describing the position of the Fortran argument containing the dimension. The following rules govern array definition. If the dimension is a reference, the corresponding argument type must be Integer on 4 bytes (I4). An array is converted from a Prolog list, a bi-dimensional array is converted from a Prolog list of lists. If the array has IO Control I or IO, then the interface is able to computer the dimensions of the array from the Prolog list. Thus, the Fortran arguments that contain the dimensions are built by the interface and cannot appear in the predicate. If the array has IO Control O or R, then the interface must allocate the storage for the result array, and the Fortran arguments that contain the dimensions are built by the interface and must appear in the predicated. The descriptors of the dimensions are placed left to right in row major order--the standard way to sweep a multi-dimensional array. Thus, the C, FORTRAN, PASCAL, PL/1 and COBOL interfaces the dimensions appear in the program in the reverse order as compared to the Prolog description as depicted in FIG. 24. Sample Generic Declarations Instead of using a predicate name for each FORTRAN Subroutine and Function, the Prolog application only uses one predicate, for all calls to FORTRAN. This is called the GENERIC format. To use it, there must exist special PRODECE macros inside the ASSEMBLE descriptor file. Say for example, that the Prolog application would like wants to employ all FORTRAN Subroutines and Functions via one predicate name, and one expression. The descriptor file then contains the information shown in FIG. 25. To use the generic descriptor files, the application uses the interface: goals ext.sub.-- pred(pred.sub.-- generic(* . . . ), myfort pgeneric); and ext.sub.-- func(func.sub.-- generic(* . . . ),myfort,fgeneric). Then, where a goal like .rarw.*:=my.sub.-- stupid(2) is used, it is replaced by .rarw.*:=func.sub.-- generic(stupide,2).. Further, where .rarw.testtabl([100,101,102,103],[[200,201],[300,301],[400,401]], [`Chaine1`,`Chaine2`]) is used, it may be replaced by .rarw.-pred.sub.-- generic(testtabl,[100,101,102,103],[[200,201],[300,301],[400,401]],[`Chain e1`,`Chaine2`]).. The generic predicates and expressions use an extra first argument, that defines the Subroutine or Function that the application employs. It contains an atom or a character string that is compared with the NAME fields of the PRODECE macros of the external Module where the Generic PRODECE appears. Compiled Predicate v. Functional There is not a one-to-one relationship that enforces a FORTRAN subroutine to be used as a predicate, and a FORTRAN function to be used as an expression. Indeed, both a subroutine and a function may be used as Prolog predicates. The only difference is in the PROARGS declaration, where a function will use the IO Control R, and the declaration must appear first in the PROARGS list. When the function is used as a Prolog predicate, the result returned by the function will be unified with the first argument of the predicate. In that sense, a predicate invoking a function uses one argument more than what the function expects, to receive the result. In the same logic, both a subroutine and function may be used as expressions, provided they obey the following rules. 1. One argument is either declared with IO Control O, IO, R (for function only), to provide the result of the expression. 2. All other arguments are declared with IO Control I. The differences between compiled predicates and compiled expressions include the following list. a. Compiled predicates receive their arguments simply converted from Prolog, whereas compiled expressions receive their arguments evaluated, then converted from Prolog, b. Management of the Global Stack with compiled expressions is more economical than compiled predicates, which means that a global stack overflow is less likely to occur. As an example of point one above, one writes expressions as shown in FIG. 26. The examples show the use of compiled expressions like 0+0, which demonstrates the automatic internal evaluation of the arguments of the expression. Differences COBOL 1. Main program must be a separate Procedure Division; 2. Subroutines must be gathered in one Procedure Division, where every subroutine uses a separate ENTRY statement. Have a look to Z1COBOL1 COBOL; and 3. No conversion is possible to data types using the Decimal Format, (PACKED or ZONED). In Cobol, this implies that non-BINARY integer types. PASCAL 1. No conversion is possible to Pascal structures, or pointers; and 2. Due to the organization of the data, parameter passing in Pascal forces a COPY of the Plist in the Pascal Stack. This is done in Z1PASC0 ASSEMBLE from line 52 on. PL/1 1. No conversion is possible to PL/1 Structures, or Pointers; 2. Because PL/1 expects Descriptors instead of arguments in the Plist for aggregates. Thus, all aggregates must be declares as BIN FIXED(31) with the BASED attribute and the ADDR Builtin. Prolog TO C Prolog provides a powerful interface to the C programming language. Everything described previously in the interface information is equally applicable to the C interface. An example of a C interface is provided in Z1C1 C illustrated in FIG. 27. Organization of C 1. Write one or more C functions into a C source file, for example MYC1 C; 2. In that same source file, add the #INCLUDE declaration shown in FIG. 28; 3. Add into that same source file the MAIN function of the C code as shown in FIG. 29. It must contain the call Prolog.sub.-- INIT. Before the Prolog.sub.-- INIT, you may add C code that initialize the global data of the C code. After the Prolog.sub.-- INIT, you may add the global clean-up code; 4. Prepare an ASSEMBLE descriptor file named MYC0 ASSEMBLE according to the instructions that follow; 5. Compile the C source file, with compiler option RENT, which produces MYC1 TEXT; 6. Assemble the ASSEMBLE descriptor file with MACLIB: Prolog, which generates MYC1 TEXT; 7. Build One TEXT file as illustrated in FIG. 30, say MYC TEXT, with the CPLINK utility of the C Compiler, out of the following four in that order; a. The TEXT file obtained from the ASSEMBLE descriptor file (MYC0 TEXT); b. The Z1COMP1 TEXT file provided by Prolog; c. The Z1COMP2 TEXT file provided by Prolog; and d. The TEXT file obtained from the C source file, (MYC1 TEXT); 8. Assign a GLOBAL TXTLIB to the C language libraries, LIB and CBASE; 9. LOAD the CPLINK produced TEXT file with options NOAUTO CLEAR RLDSAVE; 10. GENMOD the program; 11. Add an entry into the file Prolog NAMES, of the form: ##STR3## 12. Link GLOBAL LOADLIB CLINK, and the GLOBAL TXTLIB CBASE during the C code execution; 13.Use an EXEC DLIB LOAD before using any C code. Use an EXEC DLIB UNLOAD when C and Prolog have completed; 14.Use the predicates and expressions as indicated below; and 15.Upon execution of the function call by .rarw.fin., expect some log of the errors caught by the compiled language. Parameter Passing and Declarations The Fortran sample for the function Stupid shown in FIG. 21, is translated into C and shown in FIG. 31. Note that arguments IO Control I, O or IO are received by C as pointers, this explains that TSI in that example is always used with the C * dereferencing operator. An execution of the C Stupid function gives the information displayed in FIG. 32. Support Functions For C For external predicates only, the interface provides support functions that may be classified in three areas: 1. Storage Management; 2. Control of Backtracking and/or Error handling; and 3. Analysis of Prolog Data Objects. STORAGE MANAGEMENT The interface provides access to the COMAREA as defined by the PROINI macro. Also, it provides a special data type A, which locates a working storage area that is kept across backtracks. Prolog.sub.-- GET.sub.-- COMAREA() This function returns a pointer to the COMAREA that was permanently allocated as part of the storage loading of the external extension. This COMAREA is zeroed by the interface at loading time, and never modified thereafter. It is freely used by the C code and common to all C functions of the external extension. PROARGS . . . (AN,I) . . . The interface allocates on demand a working storage area, for use by a C function. The storage area is described in the PROARGS macro, by the data type A, with data length n user defined (say for example (A256,I) for a 256 bytes working area), and IO Control I. The corresponding C function may receive this argument with a char * parameter. The working storage area is for exclusive use of the particular C function that defines it in the PROARGS macro. It is zeroed when the C function is normally called, and preserved across backtrack calls of that same function. It may be used to keep data across backtrack calls of a C function. Backtracking/Error Management A C function is defined to Prolog by default as a deterministic predicate. The C function call may change that behavior, with some functions provided by the interface. A first set is used to determine return processing characteristics. This information is used by Prolog to determine if the C function shall succeed, fail or make an error when it returns to the interface. Prolog.sub.-- SET.sub.-- SUCCESS() This function reverts to the normal Success state. Thus, Prolog execution proceeds normally after the C return statement of the C function. Prolog.sub.-- SET.sub.-- BACK() This function causes Prolog execution to Fail immediately after the C return statement of the C function. Prolog.sub.-- SET.sub.-- ERROR(ERROR.sub.-- CODE) This function causes Prolog execution to stop with an Error of type Error.sub.-- Code, after the C return statement of the C function. Some predefined Error.sub.-- Codes are provided by the Prolog.H include file. Prolog.sub.-- ERR.sub.-- GLOBAL Global Stack Overflow Prolog.sub.-- ERR.sub.-- LOCAL Local Stack Overflow Prolog.sub.-- ERR.sub.-- TRAIL Trail Stack Overflow Prolog.sub.-- ERR.sub.-- SYNTAX Syntax Error Also, some of the support function that analyze Prolog Objects set the Error.sub.-- Codes previously discussed. Prolog.sub.-- TEST.sub.-- ERROR() This function determines whether there is an Error.sub.-- Code set. It returns a non-zero value equal to the error code if an Error.sub.-- Code is detected. A second set is used to decide whether the C function may be called again in the future as part of the backtracking process. We say that the C function has created a choice point. Note that the decision whether the function creates a choice point is independent, of its return status (success, failure or error) as managed by the first set of support functions. However if a function fails and has created a choice point, it will be recalled immediately because that choice point is the most recent. Prolog.sub.-- RESET.sub.-- CHOICE() This function reverts to the normal no-choice point state. Prolog.sub.-- SET.sub.-- CHOICE() This function creates an active choice point. If back tracking occurs, then the C function is called again with the same arguments. Prolog.sub.-- TEST.sub.-- CHOICE() This function determines whether the C function was called normally or as part of the backtracking process. It returns a non-zero value if the latter is true. When a C function is called, normally or as part of the backtracking process, it has no active choice point any more. If the function called by the backtrack is recursive, it must recreate a choice point. Analysis of Prolog Data Objects This set of functions describes a Prolog object, selects sub-objects inside a Prolog object, translates Prolog objects into C and C variables into Prolog objects, and unifies a plurality of Prolog objects. Prolog.sub.-- TYPE(Prolog.sub.-- OBJECT) This function returns the type of a Prolog.sub.-- OBJECT. The complete list of Prolog types as understood by Prolog.sub.-- TYPE returns a value associated with Prolog.sub.-- TYP.sub.-- OTHER. An unknown type, returns a value associated with Prolog.sub.-- TYP.sub.-- VARIABLE. A normal Prolog variable, returns a value associated with Prolog.sub.-- TYP.sub.-- NIL. The NIL atom returns a value associated with Prolog.sub.-- TYP.sub.-- ATOM. An atom other than NIL returns a value associated with Prolog.sub.-- TYP.sub.-- STRING. A character string, returns a value associated with Prolog.sub.-- TYP.sub.-- INT. A floating point number returns a value associated with Prolog.sub.-- TYP.sub.-- LONGINT. A rational number returns a value associated with Prolog.sub.-- TYP.sub.-- RATIONAL. A skeleton returns a value associated with Prolog.sub.-- TYP.sub.-- SKELETON. An extended skeleton returns a value associated with Prolog.sub.-- TYP.sub.-- EXTENDEDSKELETON. A list pair returns a value associated with Prolog.sub.-- TYP.sub.-- LIST. Prolog.sub.-- FUNCTOR(Prolog.sub.-- OBJECT) This function returns a Functor of a Prolog.sub.-- Object in Prolog.sub.-- Object format. If the Object is of type Prolog.sub.-- TYP.sub.-- SKELETON or of type Prolog.sub.-- TYP.sub.-- EXTENDEDSKELETON, the function returns the Term Functor. If the Object is of type Prolog.sub.-- TYP.sub.-- LIST, the function returns the atom "." If the Object is the NULL pointer, the function returns the Functor of the external predicate that was used to call the C function. Else the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns the NULL pointer. Prolog.sub.-- ARITY(Prolog.sub.-- OBJECT) This function returns the arity of a Prolog.sub.-- Object, in C int format. If the Object is of type Prolog.sub.-- TYP.sub.-- SKELETON or of type Prolog.sub.-- TYP.sub.-- EXTENDEDSKELETON, the function returns the Term's Arity. If the Object is of type Prolog.sub.-- TYP.sub.-- LIST, the function returns the number two. If the Object is the NULL pointer, the function returns the Arity of the external predicate that was used to call the C function. Else the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns a -1 value. Prolog.sub.-- PREFIX(Prolog.sub.-- OBJECT) This function returns the prefix of a Prolog.sub.-- Object in Prolog.sub.-- Object format. If the Object is the NULL pointer, it returns the Prefix of the external predicate that was used to call the C function. Else the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns the NULL pointer. Prolog.sub.-- ARG(Prolog.sub.-- OBJECT,RANK) This function returns the Rankth subobject of a Prolog.sub.-- Object, in Prolog.sub.-- Object format. The first subobject has Rank 0. If the Object is type Prolog.sub.-- TYP.sub.-- SKELETON or of type Prolog.sub.-- TYP.sub.-- EXTENDEDSKELETON, it returns the Rankth subobject. If the Object is of type Prolog.sub.-- TYP.sub.-- LIST and Rank is either 0 or 1, the function returns the Rankth subobject. Else the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns the NULL pointer. Prolog.sub.-- LIST(Prolog.sub.-- OBJECT,RANK,SELECTION) This function returns the Rankth element of a List Prolog.sub.-- Object, in Prolog.sub.-- Object format. The first element has Rank 0. If the Object is of type Prolog.sub.-- TYP.sub.-- LIST and Selection is Prolog.sub.-- LST.sub.-- VALUE, the function returns the Rankth element of the List. If the Object is of type Prolog.sub.-- TYP.sub.-- LIST and Selection is Prolog.sub.-- LST.sub.-- NEXT, the function returns the Rank+1th List pair. If the Object is of type Prolog.sub.-- TYP.sub.-- LIST and Selection is Prolog.sub.-- LST.sub.-- CURRENT, the function returns the Rankth List pair. Else the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns the NULL pointer. Prolog.sub.-- LIST.sub.-- LENGTH(Prolog.sub.-- OBJECT) This function counts and returns the number of list pairs that are chained to form a list. The count is zero if the Prolog.sub.-- Object is not a list pair. The count concludes whenever the function is presented with a non list pair as the second field of a list pair (the terminating nil of a normal List, or any other Prolog type except list pair). Prolog.sub.-- COMP.sub.-- FLOAT (FLOATING.sub.-- POINT,FLOATING.sub.-- POINT) This function returns a non zero value, if the two floating point numbers in C double format are closer together than the current Prolog fuzz value. Prolog.sub.-- CONSTANT(RANK) This function returns the Rankth Constant Object defined in the set of PROCONS macros. The first Constant Object has Rank 0. If the Constant is a PROCONS LIST or a PROCONS SKEL, a new List pair filled with Prolog variables or a new Prolog Term with the right Functor and Arity and Prolog variables as arguments, is allocated into the Global Stack. This function also provides the Constant Objects with predefined values of Rank: Prolog.sub.-- CST.sub.-- NIL The special Prolog atom nil, Prolog.sub.-- CST.sub.-- LIST A newly allocated list pair, with variable arguments, Prolog.sub.-- CST.sub.-- EMPTY empty Prolog character string. If the Global Stack overflows, it sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- GLOBAL, and returns the NULL pointer. Prolog.sub.-- CONVERT.sub.-- INT(Prolog.sub.-- OBJECT) This function converts the Object into C integer format, and returns the integer. If the Object is of type Prolog.sub.-- TYP.sub.-- INT it returns the integer format value of the Object. Else the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns a zero value. Prolog.sub.-- CONVERT.sub.-- FLOAT(Prolog.sub.-- OBJECT) This function converts the object into C double format, and returns that double. If the Object is of type Prolog.sub.-- TYP.sub.-- FLOAT it returns the double format value of the Object. If the Object is of type Prolog.sub.-- TYP.sub.-- LONGINT or Prolog.sub.-- TYP.sub.-- RATIONAL, it returns the double format converted value of the Object. Else it sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns a zero value. Prolog.sub.-- CONVERT.sub.-- STRING(Prolog.sub.-- OBJECT) This function converts the object into C char * format, and returns that char *. If the Object is of type Prolog.sub.-- TYP.sub.-- STRING, the function returns the char * format converted value of the Object. If the Object is of type Prolog.sub.-- TYP.sub.-- ATOM or Prolog.sub.-- TYP.sub.-- NIL, it returns the char * format converted value of the Print-Name of the Object. If the Local Stack overflows, it sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- LOCAL, and returns the NULL pointer. Else it sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns a NULL pointer. Prolog.sub.-- CONVERT.sub.-- Prolog(TYPE.sub.-- ORG,Prolog.sub.-- OBJECT OR C OBJECT,TYPE.sub.-- DEST) This function converts the Object into Prolog.sub.-- Object of type Type.sub.-- Dest and returns the converted Prolog.sub.-- Object. Type.sub.-- Org is the Prolog.sub.-- Type of the Prolog.sub.-- Object or may be specified as Prolog.sub.-- TYP.sub.-- OTHER. However, if the Object is a C object, Type.sub.-- Org must be specified and must belong to the following set. Prolog.sub.-- TYP.sub.-- BINARYSTRING A character string in C char * format, Prolog.sub.-- TYP.sub.-- BINARYINT An integer number in C int format, and Prolog.sub.-- TYP.sub.-- BINARYFLOAT A floating point number in C double format. The supported conversions are listed below. Prolog.sub.-- TYP.sub.-- BINARYSTRING to Prolog.sub.-- TYP.sub.-- STRING, Prolog.sub.-- TYP.sub.-- BINARYSTRING to Prolog.sub.-- TYP.sub.-- ATOM, Prolog.sub.-- TYP.sub.-- BINARYSTRING to Prolog.sub.-- TYP.sub.-- NIL, Prolog.sub.-- TYP.sub.-- STRING to Prolog.sub.-- TYP.sub.-- STRING, Prolog.sub.-- TYP.sub.-- STRING to Prolog TYP.sub.-- ATOM, Prolog.sub.-- TYP.sub.-- STRING to Prolog.sub.-- TYP.sub.-- NIL, Prolog.sub.-- TYP.sub.-- ATOM to Prolog.sub.-- TYP.sub.-- ATOM, Prolog.sub.-- TYP.sub.-- ATOM to Prolog.sub.-- TYP.sub.-- STRING, Prolog.sub.-- TYP.sub.-- NIL to Prolog.sub.-- TYP.sub.-- NIL, Prolog.sub.-- TYP.sub.-- NIL to Prolog.sub.-- TYP.sub.-- STRING, Prolog.sub.-- TYP.sub.-- INT to Prolog.sub.-- TYP.sub.-- INT, Prolog.sub.-- TYP.sub.-- BINARYINT to Prolog.sub.-- TYP.sub.-- INT, Prolog.sub.-- TYP.sub.-- FLOAT to Prolog.sub.-- TYP.sub.-- FLOAT, and Prolog.sub.-- TYP.sub.-- BINARYFLOAT to Prolog.sub.-- TYP.sub.-- FLOAT. If the Global Stack overflows, the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- GLOBAL, and returns the NULL pointer. Else the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- SYNTAX, and returns a NULL pointer. Prolog.sub.-- UNIFY(Prolog.sub.-- OBJECT,Prolog.sub.-- OBJECT) This function unifies the two Objects. If it succeeds, it returns the unified version or the first Prolog.sub.-- Object. If it fails, backtracking takes place. For performance reasons, Prolog simple non-frozen variables, Prolog integers, atoms, and strings are handled dynamically. However, other types can cause a context switch from C to Prolog, and invoke the full Prolog unifier, before a context switch back to C. If the Trail Stack overflows, the function sets the Error.sub.-- Code to Prolog.sub.-- ERR.sub.-- TRAIL, and returns the NULL pointer. Existing Applications For existing applications that require communication to Prolog, there is also an interface from such applications to Prolog. As seen from FORTRAN, the interface is a TEXT file, Z1COMPF TEXT shown in FIG. 33. The interface provides an "INTEGER function" named Prolog. The INTEGER result is the Return Code of the request. ##STR4## NOTE: Because Fortran does not support empty character strings, one has to replace empty character strings with strings of one space character. C Interface to Prolog The C interface is illustrated in a TEXT file named Z1COMPC TEXT shown in FIG. 33. This interface provides an "int function" called Prolog. The int result is the Return Code of the request. ##STR5## COBOL The interface from Cobol to Prolog is illustrated in the source listing for Z1COMPB TEXT shown in FIG. 35. The return code of the request, is returned as the first argument of the CALL "Prolog" statement. Also, where C and Fortran may use character strings, COBOL has to supply the length of the character string along with the character string itself. ##STR6## The concluding discussion uses C syntax as a communication medium. The language interface to Prolog provides four basic commands: START Initialize Prolog, and if not already loaded, loads a new workspace in a new session, and activates the workspace initial goal. STOP Completes a Prolog session, and frees the associated storage. CALL Runs a Prolog predicate with data converted from the calling program, and if the predicate succeeds, converts results back to the calling program, RECALL Requests the next solution of the latest CALL command, and if the predicate succeeds, converts results back from the calling program into the data supplied by the original CALL command. START COMMAND The command START requires 5 arguments, all character strings. The syntax is provided below. ##STR7## where TOKEN is a session token of eight characters or less, that is used to identify the Prolog session where the program submits the CALL, RECALL and STOP commands. WORKSPACE is a workspace name of eight characters or less, identifying an existing file of filetype Prolog WS. If the application is the original initial workspace supplied by Prolog, use the name Prolog WS. SHARE is a selection string of 8 characters or less, that must take the value NEW or REUSE. If the string is empty, the default (NEW) is taken. OPTIONS is a character string that contains options to be supplied to the LProlog EXEC by the START command. If the NEW Share selection is in use, the START command STOPs any Session with the Session name Token. Then START issues a CMS command of the form LProlog NAME Token WS Workspace Options. During the processing of the LProlog EXEC, Prolog is initialized. If not already done, then the command builds a session of name token with a workspace read from the Prolog WS, with any options that may be required. The START command returns the return code of the LProlog command as its own return code, or a Prolog error code indicating the command syntax was invalid, or a Prolog external storage failure if the Storage allocation request necessary to build the LProlog command failed. STOP The command STOP requires two character arguments. The syntax is ##STR8## where TOKEN is the Session Token of eight characters or less, that identifies the Prolog session at the START command. The STOP command issues a CMS command of the form NUCXDROP Token. Then, during the processing of the NUCXDROP command, the session of name token is finished and its storage reclaimed. If there is no more any Prolog active session, the Prolog itself is removed from the memory. The STOP command returns the return code of the NUCXDROP command as its own return code, or a Prolog Syntax Error if the command was invalid. CALL Command The command CALL requires at least five character arguments, the first five being character strings. The syntax is illustrated below. ##STR9## where TOKEN is the eight character Session Token that uniquely identifies the Prolog session at the START command. PREFIX is the Prefix of the predicate that is called. If supplied as an empty string, the predicate is not given a prefix. In that case, the priority predicate of the predicate name is called, predicate is the Name of the predicate that is to be called, a character string, case sensitive. DESCRIPTOR is the Descriptor character string of the conversion of the input and output arguments. It may be empty, in the case of the zero-arity predicate, and in that case, there must be no Arguments behind the Descriptor in the Prolog call. ARGUMENTS are zero or more data arguments that must be converted into Prolog Data Structures before invoking the predicate, and must be passed as arguments of that predicate. For results arguments, the predicate receives variables in the corresponding positions and if the predicate succeeds, the Prolog data that has been put into these variables is converted back to the format of the calling program. The CALL command runs the Prolog predicate or Prefix:predicate with input arguments converted from the calling program, and output arguments supplied as variables. If a Prolog Error is encountered, then the CALL command returns the Error Code as a Return Code. If the predicate fails, then the CALL command returns its own return code. If the predicate succeeds, then the CALL command converts back the output arguments from the Prolog data unified with the variables, and returns zero as its return code. If the CALL command is invalid, it returns a Prolog Syntax Error as its own return code. RECALL Command The command RECALL requires two character arguments. The syntax is shown below: ##STR10## where TOKEN is the eight character session identifier. The RECALL command requests the Next solution from the latest CALL command. It returns the same Return Codes as the CALL command. It returns the results of the solution if the predicate succeeds another time, into the output arguments supplied by the CALL command. Call Descriptor Descriptor is a character string of zero or more arguments. It uses a subset of the PROARGS syntax. The following cases of the PROARGS syntax may not be used in the CALL Descriptor: Data Types 04, AN, and IO Controls V, R, A. Also, IO Controls Input and Output are relative to the called Prolog predicate, not to the called compiled language external predicate. Two formats (Normal Descriptor and C struct Descriptor) of the PROARGS macro are valid. Data Types B1, B2, B4, I1, I2, I4, E4, E8, J4, J8, CN, C0, I, O, IO; and Dimension Descriptors N, ARGN. When a Dimension is described as an ARGN then the N corresponding argument must be Data Type I4, must be IO Control I, and must be supplied with is correct value as a program data. The predicate receives both the Array in a form of a List; or a List of Lists, for multi-dimensioned arrays, and the dimensions as scalar numbers. The dimension numbers are passed to the predicate; whereas, in the Prolog to compiled language interface, the calling Prolog predicate does not have to supply them for Input Arrays. In the compiled language to Prolog interface, the dimension numbers are given to the predicate, whether the Arrays are input and then provided as lists, or are output and provided as variables. The predicate is required to construct output arrays of exactly the size supplied by the dimension numbers. If it does not, the back conversion fails with an error. From Prolog to External Process The logic of the communication from Prolog to an external process is shown in FIGS. 36A to 36C. Execution begins at 970 where the predicate my.sub.-- stupid with one argument shown in the function block becomes defined as an External Non-Connected. Its execution address points to ATTACHF in Prolog's system area. In function block 971 Prolog first encounters a reference to my.sub.-- stupide(3). Control is passed to ATTACHF for processing the reference to an external process. The file containing the file name where the external process has been built is searched at function block 972 for the particular external process that Prolog desires to execute. The file containing the file name where the external process is user defined. It contains a predicate list created by a plurality of MACRO PRODECE in MYFORT0 ASSEMBLE. Information necessary to execute the external process is stored in the list. This information includes the execution address of the external process. At function block 973, the external process is brought into memory if it has not previously been loaded. Then, in function block 974 the head of the external process, which was created by MACRO PROINI in MYFORT0 ASSEMBLE (discussed previously), is examined. The header contains a banner and Prolog's version number. The banner is tested for correct identification information for the external process, and the version number is interrogated to assure the current Prolog version is active. In function block 975 predicate list is searched to obtain the address information for the external process. The predicate list was previously created by one or more MACRO PRODECE in MYFORT0 ASSEMBLE. STUPID is the external fortran name, while STUPIDE is the name used as the third argument of the ext.sub.-- func. Then, in function block 976, the predicate my.sub.-- stupide(*) is defined as external connected, its connection address is replaced by linkage code in the predicate list and ATTACHF branches to the connection address. This completes the ATTACHF processing. At function block 977 the linkage code stores the entry point address of the external process, the Main fortran address and the address of the PROARGS table into a set of predefined registers. Then, control is returned to Prolog at a predefined address ITFFORT2. The conversion of the Prolog arguments to the format the external process expects is managed by the PROARGS table. At function block 980, an integrity check is performed on the PROARGS table. Then, the predicate call is checked to verify argument count. In function block 982, each argument is passed through the conversion loop 983 to convert arguments from Prolog into the format the external process expects. Then, every output argument is allocated memory in function block 984 and processing loop 985. The information in the PROARGS table manages this processing. In decision block 986, the status of the external process environment is queried and initiated if it is not already active as shown in function block 987. Once the external environment is active, the specific external process is activated with the converted parameter list it expects. When the external process completes execution, the output arguments are converted back to Prolog format as shown in function block 992. Finally, control is returned to Prolog and the predicate succeeds as shown in function block 993. From External Process to Prolog The logic of the communication from Prolog to an external process is shown in FIGS. 37A-37C. Referring to FIG. 37A, execution begins at 1000 where the application wants to start Prolog under the name APPL with a workspace named APPL. The Prolog linkage routine scans the command, recognizes START and extracts the application name and workspace name. The linkage routine starts Prolog by issuing the command shown at function block 1010 to the operating system and returns control to the application. The application wants to run the predicate `prefix:predicate` and wants to give it the converted arguments as shown in function block 1012. The conversion is based on the information in the descriptor tables and the format in the PROARGS MACRO. The linkage routine scans commands and recognizes a CALL. The linkage routine formats a system call to Prolog as shown in function block 1016 via a supervisor call employing the command APPL HLL and the arguments prefix, predicate, descriptor, and arguments. The Prolog system call APPL HLL invokes the conversion processing to convert the arguments from the external process into Prolog's internal format as shown in function block 1018. Function block 1020 loops back to the conversion processing to facilitate conversion of each of the arguments. Once the input arguments are converted, then the predicate is executed as shown in function block 1025. Then, if the predicate succeeds, each output argument is converted back to the external process format as shown in function block 1034 and the loop at 1036 and control is returned to the external process. The conversion back to the external process employs the descriptor table for correct formatting. If the predicate fails, then the Prolog system call terminates at 1032 and returns control to the external process with an error code. The external process gets the next solution of the previous call via the processing shown in function block 1040. The linkage code issues a Prolog system call as shown in function block 1042. The previous set of linkage information is used to communicate with Prolog. Thus, the Prolog system reruns the previous predicate as shown in function block 1044. Then, if the predicate succeeds as tested in decision block 1046, the output arguments are converted back to the external process format in function block 1052, and the Prolog system returns control to the external process. If the predicate fails, then the Prolog system call terminates and returns an error code. When the external process wants to complete Prolog processing and cleanup the session, it issues a STOP command as shown in function block 1056. The Prolog linkage routine recognizes the STOP and extracts the session name APPL. The linkage routine terminates the session named APPL by issuing the command shown in function block 1058 to the operating system. While the invention has been described in terms of a preferred embodiment in a specific system environment, those skilled in the art recognize that the invention can be practiced, with modification, in other and different operating systems within the spirit and scope of the appended claims.
|
Same subclass Same class Consider this |
||||||||||
