Re: Redirecting error messages

Thomas Russ <[email protected]> Mon, 14 Jan 2008 11:08:15 -0800
Newsgroups gmane.comp.ai.powerloom
Message-ID <[email protected]>
General note:  This reply is specific to the Common Lisp version of  
PowerLoom.

On Jan 12, 2008, at 12:29 PM, Magnus Malm wrote:

> Hello
>
> I do not understand how the error messages are generated. They  
> appear to go through some other stream than *standard-output*. (I  
> have tried to bind both *standard-output* and *error-output* to a  
> file but nothing is streamed to the file, the error messages are  
> still printed to the REPL.)

The issue is that PowerLoom uses Stella to implement the language.    
And Stella has its own streams for writing standard output, error  
output, etc.  These are mapped (in the Common Lisp implementation) to  
*standard-output* and *error-output*, but the mapping isn't dynamic.   
If you change the values of the Lisp special variables, their original  
values have already been captured by Stella.

Possible solutions below.

> What I want to do is to capture all error (And warning) messages and  
> redirect them to a string (for futher processing) but I do not  
> understand the underlying code that generates these messages.  
> Apparently, a stream is created with MAKE-STRING-OUTPUT-STREAM, but  
> I have no idea when, or where, this stream is created, let alone the  
> name of it. (It might be worth mentioning that I use the struct  
> version of powerloom)

The exception mechanism should be the same in both versions of Common  
Lisp, since we use the native exception mechanism.  It is good to  
mention the struct item, though, since other things are often different.

I think that you have two options:

1.  Redirect the the output of cl:*error-output* (and perhaps also  
cl:*standard-output*) BEFORE loading PowerLoom.  In that case, the  
initialization when PowerLoom loads should get the values existing at  
the time of loading.  If you don't want to do the re-direction  
globally, you should be able to bind the values around the loading and  
initialization of PowerLoom.

    (let ((*error-output*  your-stream-here))
       (load ".../load-powerloom"))

2.  You could redirect the output when running PowerLoom by binding  
the global variables stella::standard-output, stella::warning-output  
and stella::error-output.  These require objects of type  
stella::output-stream.  Constructing such objects involves invoking  
the stella:new-output-stream function and then setting the native- 
stream slot.  The native-stream slot accessor differs between the CLOS  
and struct versions of Stella.

     (let ((my-stella-stream (stella::make-output-stream)))

        ;; CLOS
        (setf (stella::%native-stream my-stella-stream)  my-lisp-stream)
        ;; STRUCT
        (setf (stella::%output-stream.native-stream my-stella-stream)  
my-lisp-stream)

        (let ((stella::error-output my-stella-stream)))
           ... PowerLoom API functions here ...
           ))



> Perhaps I am going the wrong way here but I have not found any  
> documentation on how to handle exceptions, and wether or not  
> exceptions are thrown when there's a parse error in a query for  
> instance.

Exceptions are implemented as sub-types of native exceptions.  They  
are thrown by the code and handled by the powerloom listener.  If you  
aren't running through the listener, then the exceptions should be  
thrown normally.

> I use LISP and only the API functions, s-retrieve, s-ask, etc. It is  
> s-retrieve I use the most and would really like to be able to handle  
> parse errors and make my own error handling for this (quite simply  
> just send the entire error message to the user (who does not have  
> the REPL infront of him/her :))).

Well, the interface functions should throw the errors themselves, for  
example, using SBCL:

 > (pli:s-retrieve "all (fred ?x)" null-string null)

ERROR: Undeclared predicate or function reference: `FRED'.
    Error occurred while parsing the proposition:
    (KAPPA (?X) (FRED ?X))

    [Condition of type PROPOSITION-ERROR]


The full exception hierarchy is shown below.  These are all defined in  
the Common Lisp STELLA package.  The most interesting for general use  
are CLASH, READ-EXCEPTION, PARSING-EXCEPTION and PROPOSITION- 
EXCEPTION.  The READ-EXCEPTION is what you will get if there is, for  
example, not enough parentheses in the form, since that is detected at  
low-level in the code, before any attempt is made to parse the results  
as a PowerLoom form.  Most PowerLoom exceptions will be subtypes of  
LOGIC-EXCEPTION.

NATIVE-EXCEPTION
   STELLA-EXCEPTION
   INPUT-OUTPUT-EXCEPTION
     READ-EXCEPTION
     END-OF-FILE-EXCEPTION
     NO-SUCH-FILE-EXCEPTION
     FILE-ALREADY-EXISTS-EXCEPTION
   UNHANDLED-EXCEPTION
   EVALUATION-EXCEPTION
   NO-SUCH-OBJECT-EXCEPTION
     NO-SUCH-CONTEXT-EXCEPTION
     UNDEFINED-CLASS-EXCEPTION
   BAD-ARGUMENT-EXCEPTION
     OBJECT-NOT-CLASS-EXCEPTION
   INCOMPATIBLE-QUANTITY-EXCEPTION

   OBJECT-ALREADY-EXISTS-EXCEPTION
   LOGIC-EXCEPTION
     EXPLAIN-EXCEPTION
       EXPLAIN-NO-QUERY-EXCEPTION
       EXPLAIN-NO-SOLUTION-EXCEPTION
       EXPLAIN-NO-MORE-SOLUTIONS-EXCEPTION
       EXPLAIN-NOT-ENABLED-EXCEPTION
       EXPLAIN-NO-SUCH-LABEL-EXCEPTION
       EXPLAIN-QUERY-TRUE-EXCEPTION
     TERM-GENERATION-EXCEPTION
     PROPOSITION-ERROR
     PARSING-ERROR
     CLASH
     FAIL-EXCEPTION
     QUERY-THREAD-LIMIT-VIOLATION



Is there some particular parsing error you are running into that isn't  
generating a real error?

Note that warnings will not throw exceptions, but will only print  
information, though.