| TPINT TP_API myClause( TPINT32 Version, TPCALL *Call, TPARGUMENT *First, TPEXCEPTION *Exc ) |
The First parameter of a clause function is a TPARGUMENT structure. The type of the argument (variable, atom, number, integer, list, etc.) and the name of the argument are stored inside this structure. Trinc-Prolog creates a single linked list of argument structures for predicates that have more than 1 parameter. For instance: for a call to test/2 a linked list of two TPARGUMENT structures is created.
| if( Call->_Arity == 3 ) { //Arity of 3, get the second parameter TPARGUMENT *SecondArg = First->_Next; //Get the third parameter TPARGUMENT *ThirdArg = Second->_Next; } Delphi example |
| It is not necessary to delete the memory occupied by TPARGUMENT structures, these structures are managed by Trinc-Prolog. |
The next step is to check the type of the arguments and if these are of the incorrect type throw an exception. The possible argument types are:
| T_ARG_VAR_EMPTY | an empty variable |
| T_ARG_ATOM | atom |
| T_ARG_INTEGER | an integer number |
| T_ARG_FLOAT | a floating point number |
| T_ARG_LIST | a list |
| T_ARG_EMPTY_LIST | an empty list |
| T_ARG_OP | an operator |
| T_ARG_SINGLE_QUOTED | an atom enclosed by single quotes |
| T_ARG_VARIOUS | all remaining possible types |
Suppose that the second argument may not be an empty variable and that the third argument must be an atom.
| if( SecondArg->_Type & T_ARG_VAR_EMPTY ) { //Create an exception goal and copy it to the exception parameter Exc->_Str = TP_MEMALLOC( 32 ); strcpy(Exc->_Str, "instantiation_error."); //Return the exception result code return TP_EXCEPTION; } if( (ThirdArg->_Type & T_ARG_ATOM) == 0 ) { |
| If memory must be allocated for a value to return to Trinc-Prolog then the function TP_MEMALLOC must always be used. The block of memory will be deleted by Trinc-Prolog. | |
| Never change the lexeme string of an argument structure. |
As can be seen from the example above the bit operator & is used to check the type of an argument. This is necessary because it is possible that several type flags are present for a single clause argument.
If a list or a Prolog structure is an argument for an external Prolog clause then the _Child attribute of TPARGUMENT is used. The _Child attribute points to the first child argument.
| void IterateArgs( TPARGUMENT *First, <other-parameters>
) { //Check if the current argument structure has a subexpression, if so examine it if( First->_Child ) { IterateArgs( First->_Child, <other-parameters> ); } //Check if there is a next argument structure, if so examine it if( First->_Next ) { IterateArgs( First->_Next, <other-parameters> ); } } Delphi example |
For instance: if 'a(b, c)' is the value of a parameter for a Prolog clause then three TPARGUMENT structures are created, one for 'a' and the 'a' argument structure has two child arguments, these are 'b' and 'c'.