When I use JPL (from JavaSE 1.8), Prolog (SWI-Prolog version 8.2.2) can return an error message without throwing an exception. E.g. when using consult and the file has errors:
import org.jpl7.Query;
public class Test {
public static void main(String[] args) {
try {
String t1 = "consult('test.pl')";
Query q1 = new Query(t1);
q1.hasNext();
} catch (Exception e) {
e.printStackTrace();
}
}
}
I get the output at the console:
ERROR: test.pl:1:23: Syntax error: Unexpected end of file
But no exception is thrown. Therefore my Java program cannot know that the consulted file has errors. The file test.pl that I used in this simple example only contains a simple predicate with a syntactical error:
brother(mike, stella)..
Can I do something so that my Java program can catch this error?
Can I use another method to find and return the syntactical errors in the file that I intend to consult?
Compiling does not break at the first error. I think that is also what we want as it makes debugging a bit cumbersome if we can only deal with one error at a time.
What you can do is intercept the errors, e.g.,
:- dynamic error_happened/1.
user:message_hook(Term, error, _Lines) :-
assertz(error_happened(Term)),
fail. % still print the error.
Now, after the load, you can call error_happened/1 to see whether some error happened. Depending on your policies you can do many more things. You can also handle warnings. You can abort the current compilation on the first or after N errors/warnings using abort/0. That probably will get reported by JPL as an exception. Note that breaking out of a compilation is currently unsafe in the sense that it may not clean up all global state associated with the compiler. You should normally terminate and restart the process after breaking out of a compilation using abort/0.
I found this answer great and very useful, even applicable when using swiplserver for Python, same issue, consult does not abort with error.
Just if someone is reading/using jan’s solution, see there is a typo in the error_happend inside the assertz, should be assertz(error_happened(Term)), that’s all Otherwise you will look for the error predicate and won’t be there (but won´t give error either because it has been defined dynamic)
It is still valid. Since come time there are also the commandline options --on-warning and --on-error that control the Prolog flags on_warning an on_error. The values are print (default), halt (halt immediately with status 1) or status, which implies keep running but on halt exit with status 1. See SWI-Prolog -- Manual
You are right @jan , I saw those CLI options and played with them, but your solution above is more general it seems to me; for example I can raise an exception after compilation (but not exit).
My use case is making sure that a term-expansion-based typechecker is throwing the right error during file consultation. In each test case I load a file, collect the error, and then unload the file. The following seems to work well (maybe there are improvements?):