Foreign Predicates

Foreign predicates can be defined by Java methods, constructors and fields. Foreign predicates will have retrieved the actual goal arguments by the interpreter and automatically passed to the associated Java method, constructor or field. More details about foreign predicates can be found in the Jekejeke Prolog Programming Interface documentation.

Foreign predicates can be registered by one of the directives foreign/3, foreign_constructor/3 foreign_setter/3 and foreign_getter/3. Foreign evaluable functions can be registered by one of the directives foreign_function/3 or foreign_constant/3. The directives take as arguments a predicate specification, a declaring class specification and a method, constructor or field specification. We can describe the arguments via the following syntax:

directive --> "foreign(" indicator "," module "," signature ")"
| "foreign_constructor(" indicator "," module "," signature ")"
| "foreign_setter(" indicator "," module "," atom ")"
| "foreign_getter(" indicator "," module "," atom ")"
| "foreign_fun(" indicator "," module "," signature ")"
| "foreign_const(" indicator "," module "," atom ")".

signature --> atom [ "(" module { "," module } ")" ].

Example:
:- foreign(hello/0, 'OutHello', hello('Interpreter')).
% is a foreign predicate directive.

Not all declared classes or parameter types have to be fully qualified. The below class names can be directly used without specifying the package name. All formal parameters not of class Term cause a range check and/or conversion of the actual argument. A formal parameter of type BigDecimal or BigInteger causes a widening, whereas a formal parameter of type Integer, Float or Long causes a range check.

The supported primitive datatypes are handled analogously. The Java method, constructor or field might also have one of the above classes or primitive types as a return type. By returning a non-null object the Java method, constructor or field can indicate success and the in-terpreter will unify the object with the last argument of the corresponding predicate. By re-turning a null the Java method or field can indicate a failure.

A Java method might also have a boolean or a void return type. The return type boolean can indicate success or failure without returning an object. The return type void always indicates success without returning an object. For non-static methods or fields an additional argument for the receiving object is added to the front of the foreign predicate.

A formal parameter of type Interpreter is needed for foreign predicate that change variable bindings. A formal parameter of type CallOut is needed for non-deterministic foreign predicates. The API of the CallOut allows fine control of the creation of choice points, of the choice point data, of clean-up handling and barrier handling. For more information one should consult the programming interface documentation.

Table 19: Parameter Type Mapping

Java Type

Prolog Type

java.lang.String

atom

java.lang.CharSequence

atom or reference

java.lang.Boolean, boolean

atom from the set {true, false}

java.lang.Byte, byte

integer between - 2^7 and 2^7-1

java.lang.Char, char

char between 0 and 2^16-1

java.lang.Short, short

integer between - 2^15 and 2^15-1

java.lang.Integer, int

integer between - 2^31 and 2^31-1

java.lang.Long, long

integer between - 2^63 and 2^63-1

java.math.BigInteger

integer

java.lang.Float, float

float32

java.lang.Double, double

float

java.math.BigDecimal

decimal

java.lang.Number

number

jekpro.tools.term.AbstractTerm

term

java.lang.Object

term

non-arrays

reference

arrays

reference

jekpro.tools.call.Interpreter

The current interpreter

jekpro.tools.call.CallOut

The current call-out

The interpreter allows InterpreterException and InterpreterMessage exceptions thrown by the Java method. For InterpreterMessage the Prolog stack trace is determined and a corre-sponding InterpreterException is thrown. A couple of Java exceptions are recognized and wrapped into Prolog errors before throwing. The family of interrupt exceptions is mapped to the signal currently stored in the interpreter and the signal is cleared.

Table 20: Exception Type Mapping

Java Class

Jekejeke Prolog Error

jekpro.tools.call.InterpreterException

As is

jekpro.tools.call.InterpreterMessage

As is plus stack trace

jekpro.tools.term.RuntimeWrap

Mapping of the <cause>

java.net.SocketTimeoutException

resource_error(socket_timeout)

java.io.InterruptedIOException

<signal>

java.nio.channels.FileLockInterruptionException

<signal>

java.nio.channels.ClosedByInterruptException

<signal>

java.io.UnsupportedEncodingException

existence_error(encoding, <msg>)

java.net.MalformedURLException

syntax_error(malformed_url)

java.util.zip.ZipException

resource_error(corrupt_archive)

java.nio.charset.CharacterCodingException

syntax_error(malformed_path)

java.io.FileNotFoundException

existence_error(source_sink, <msg>)

java.net.UnknownHostException

existence_error(host, <msg>)

java.net.SocketException

existence_error(port, <msg>)

java.io.IOException

resource_error(io_exception)

java.lang.InterruptedException

<signal>

java.lang.ArithmeticException

evaluation_error(<msg>)

java.lang.RuntimeException

system_error(<msg>)

java.lang.Error

As is

java.lang.Exception

representation_error(<msg>)

Otherwise

New java.lang.Error

Prolog variables and Prolog compounds are always passed as the Java classes TermVar and TermCompound. A formal parameter or result by the Java class Object does not wrap atomics and these are passed unwrapped. On the other hand a formal parameter or result by the Java class Term, does wrap atomics and these are passed wrapped. The distinction is important for atoms, since atoms also carry call-site information which can only be preserved by representing them through the Java class TermAtomic.

The following foreign predicate predicates are provided:

foreign(I, C, M):
Succeeds with registering the predicate indicator I as a foreign predicate that calls the method M of the class C.
foreign_constructor(I, C, M):
Succeeds with registering the predicate indicator I as a foreign predicate that calls the constructor M of the class C.
foreign_getter(I, C, M):
Succeeds with registering the predicate indicator I as a foreign predicate that gets the field M of the class C.
foreign_setter(I, C, M):
Succeeds with registering the predicate indicator I as a foreign predicate that sets the field M of the class C.
foreign_fun(I, C, M):
Succeeds with registering the predicate indicator I as a foreign evaluable function that calls the method M of the class C.
foreign_const(I, C, M):
Succeeds with registering the predicate indicator I as a foreign evaluable function that gets the field M of the class C.

Comments