[top] [up] [next]

Returning a value


If the type of an argument is T_ARG_VAR_EMPTY then it is possible to assign a value to it. The _VarValue attribute of TPARGUMENT can be be assigned a block of memory. The _VarValue attribute is a pointer to an array of TPCHAR characters, such a memory block can be allocated with the function TP_MEMALLOC. Do not use another function or operator to allocate memory. Any value can be copied to this character array with C string functions like strcpy (StrCopy in Delphi).

It is also necessary to fill the _VarValueType attribute of the same TPARGUMENT structure to indicate to Trinc-Prolog the type of the returned value. The possible return value types are:

T_VARVALUE_CLAUSE a Prolog clause that must be compiled
T_VARVALUE_INTEGER an integer
T_VARVALUE_FLOAT a floating point value
T_VARVALUE_ATOM an atom
T_VARVALUE_ATOM_QUOTED an atom enclosed by single quotes

Returning a clause

If _VarValueType is T_VARVALUE_CLAUSE the _VarValue string is compiled by the Trinc-Prolog compiler so it is necessary to create a valid prolog fact, this is done by creating a string like 'value( <my-value-here> ).'. The constant TP_VALUE_FUNCTOR is defined as the string which must be used for creating the prolog fact.

Return value Prolog fact which must be send to Trinc-Prolog
a value(a).
[1,2,3] value([1,2,3]).

If the return value is the atom 'a' then a Prolog fact that looks like 'value(a).' must be created, Trinc-Prolog checks that the functor of the returned Prolog fact is 'value' and that the arity of 'value' is 1.

In the example below two parameters are multiplied and the result is assigned to or compared with the third parameter, this depends on the type of the third parameter. The example implements a multiply/3 predicate.

/* Multiply the first and second argument */
double Mul = atof(First->_Lexeme) * atof(Second->_Lexeme);

/* Check what to do with the result */
if( Third->_Type == T_ARG_VAR_EMPTY ) {

    /* Convert value to a string and assign it to a variable */
    char Tmp[128];
    gcvt(Mul, 7, Tmp);

    /* Allocate memory to store the result in, this memory will be deleted by Trinc-Prolog if it is
     * no longer necessary, the allocated block is already filled with zero's */
    TPCHAR *PC = TP_MEMALLOC( strlen(Tmp) + strlen(TP_VALUE_FUNCTOR) + strlen("().") + 1 );

    /*Copy string to the buffer, a predicate like 'value(16).' is created */
    strcat(PC, TP_VALUE_FUNCTOR);
    strcat(PC, "(");
    strcat(PC, Tmp);
    strcat(PC, ").");

    /* Assign address of buffer and the type of the returned value to the argument structure */
    Third->_VarValue = PC;
    Third->_VarValueType = T_VARVALUE_CLAUSE;
    return TP_EXIT;
    }
else {
    /* Compare value of third argument with the result of multiplication */
    double Val3 = atof(Third->_Lexeme);
    if( Val3 == Mul ) {
        /* The values are the same, exit the predicate */
        return TP_EXIT;
        }
    else {
        /* Different results, so start failing */
        return TP_FAIL;
        }
    }
Delphi example

Returning an integer

If only an integer must be returned then it is faster to use this method then creating a valid Prolog clause that will be compiled like in the section above. Trinc-Prolog does check if the returned string is a valid integer. A buffer for the string representation of the integer must be allocated, the integer must be converted to a string and then copied to the buffer. This buffer must be assigned to _VarValue and the constant T_VARVALUE_INTEGER must be assigned to _VarValueType.

if( Minimum->_Type & T_ARG_VAR_EMPTY ) {
    /* Empty variable -> assign the minimum value, convert the value to a
    * string. First allocate a buffer to put the converted result in.
    */
    TPCHAR *Value = TP_MEMALLOC(64);
    if( Value ) {
        /* Convert value to string (precision of 10 digits) */
        itoa(Min, Value, 10);

        /* Store buffer in argument structure */
        Minimum->_VarValue = Value;
        /* Set the type of the returned value, so Trinc-Prolog knows that
        * it does not have to compile a Prolog clause but just a single
        * number to its internal representation.
        */
        Minimum->_VarValueType = T_VARVALUE_INTEGER;
       }
}

Returning a floating-point value

If a floating-point value must be returned then it is faster to use this method then creating a valid Prolog clause. A buffer for the string representation of the floating-point value must be allocated, the value must be converted to a string and then copied to the buffer. This buffer must be assigned to _VarValue and the constant T_VARVALUE_FLOAT must be assigned to _VarValueType. Trinc-Prolog does check if the returned string is a valid floating-point value.

if( Minimum->_Type & T_ARG_VAR_EMPTY ) {
    /* Empty variable -> assign the minimum value, convert the value to a
    * string. First allocate a buffer to put the converted result in.
    */
    TPCHAR *Value = TP_MEMALLOC(64);
    if( Value ) {
        /* Convert value to string (precision of 10 digits) */
        gcvt(Min, 10, Value);

        /* Store buffer in argument structure */
        Minimum->_VarValue = Value;
        /* Set the type of the returned value, so Trinc-Prolog knows that
        * it does not have to compile a Prolog clause but just a single
        * number to its internal representation.
        */
        Minimum->_VarValueType = T_VARVALUE_FLOAT;
       }
}

Returning an atom

A buffer for the atom must be allocated, the atom must then be copied to the buffer. This buffer must be assigned to _VarValue and the constant T_VARVALUE_ATOM or T_VARVALUE_ATOM_QUOTED must be assigned to _VarValueType. Trinc-Prolog does check if the returned string is a valid atom. If the atom must be treated as an atom enclosed by single quotes then the return value type T_VARVALUE_ATOM_QUOTED must be assigned to _VarValueType.

if( Arg1->_Type & T_ARG_VAR_EMPTY ) {

    /* Empty variable -> assign atom.
    */
    TPCHAR *Value = TP_MEMALLOC(64);
    if( Value ) {
        /* Copy string to "Value" buffer */
        strcpy(Value, First->_Lexeme);

        /* Store buffer in argument structure */
        Arg1->_VarValue = Value;
        /* Set the type of the returned value, so Trinc-Prolog knows that
        * it does not have to compile a Prolog clause but just convert
        * an atom to its internal representation.
        */
        if( First->_Type & T_ARG_SINGLE_QUOTED )
            Arg1->_VarValueType = T_VARVALUE_ATOM_QUOTED;
        else
            Arg1->_VarValueType = T_VARVALUE_ATOM;
        }
}

[top] [up] [next]

 

info@trinc-prolog.com