Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

manipulate output streams (esp. errout) in libgap #2874

Open
dimpase opened this issue Sep 27, 2018 · 11 comments
Open

manipulate output streams (esp. errout) in libgap #2874

dimpase opened this issue Sep 27, 2018 · 11 comments
Labels
kind: discussion discussions, questions, requests for comments, and so on kind: support request topic: libgap things related to libgap

Comments

@dimpase
Copy link
Member

dimpase commented Sep 27, 2018

At the moment, asking libgap to compute something like 1/0 results in an error message printed:

Error, Rational operations: <divisor> must not be zero

It is often necessary to be able to capture this output for further processing
(something what current libGAP in Sage does by changing source code in GAP kernel)
Thus it would be great to able to have more control over it in libgap.

Perhaps #2824 is relevant here, I don't know.

@markuspf
Copy link
Member

Have you tried using the variable introduced in #2824?

@dimpase
Copy link
Member Author

dimpase commented Sep 28, 2018

I don't really know how. Suppose I call GAP_EvalString and it produces an error. I can check that this was the case from inspecting its output.
Is it already too late to inspect ERROR_OUTPUT at this moment?

I tried, and only say that ERROR_OUTPUT equals *errout* after a run of GAP_EvalString. I'd actually have the latter, instead of just True/False as the status,
returning the actual error message (in some way).

Am I supposed to manipulate ERROR_OUTPUT in the error_callback function?

@dimpase
Copy link
Member Author

dimpase commented Sep 28, 2018

I tried printing ERROR_OUTPUT in an error callback function, and it still was
*errout*. Could it be that the error message goes there after the callback invocation, and not before?
If so, could this be changed?


OK, I'm getting there, sorry for noise; I'm doing something like

libgap_errout := "";
ERROR_OUTPUT := OutputTextString(libgap_errout, true);
1/0; # boom...
     #  now I can inspect/reset libgap_errout in the callback

@dimpase
Copy link
Member Author

dimpase commented Oct 1, 2018

Here is something that appears to work.

  1. I have not found a way to clear the error stream, currently the callback closes and reopens it. Is there a better way?
  2. Should I call ClearError() in the callback, and if yes, where exactly?
    (I am not sure what exactly ClearError() does)
int main(int argc, char ** argv)
{
    Int a = 42;
    Obj b, str, out;
    char *buf;
    printf("# Initializing GAP...\n");
    GAP_Initialize(argc, argv, environ, 0L, &err_callback);
    b = INTOBJ_INT(a);
    b = INV(b);
    GAP_EvalString("libgap_errout := \"\"; ERROR_OUTPUT := OutputTextString(libgap_errout, false);");
    str = NEW_STRING(0);
    out = CALL_2ARGS(
       GAP_ValueGlobalVariable("OutputTextString"), str, True);
    CALL_2ARGS(GAP_ValueGlobalVariable("PrintTo"), out, b);
    CALL_1ARGS(GAP_ValueGlobalVariable("CloseStream"), out);
    buf =  CSTR_STRING(str);
    printf("\n its C part: %s\n", buf);
    printf("# error processing\n");
    GAP_EvalString("_rich_repr_;"); /* or whatever */
    GAP_EvalString("1/0;");
    printf("# done\n");
    return 0;
}

void err_callback(void) {
        Obj r;
        int len;
        printf(" err_callback!\n");
        r = GAP_ValueGlobalVariable("libgap_errout");
        len = GET_LEN_STRING(r);
        printf("  got: %.*s\n", len, CSTR_STRING(r));
        GAP_EvalString("CloseStream(ERROR_OUTPUT);");
        GAP_EvalString("libgap_errout := \"\"; ERROR_OUTPUT := OutputTextString(libgap_errout, false);");
        return;
}

PS. Would it be a good idea to add this to my PR with tests for libgap?

@dimpase dimpase removed topic: libgap things related to libgap labels Oct 31, 2018
@embray
Copy link
Contributor

embray commented Nov 19, 2018

Per my comments here it would be much easier from a third-party integration perspective if it were possible to prevent error messages from being printed to I/O streams at all, as doing so results in a lot of overhead (e.g. unnecessary copying) and other complications. Likewise, going into ErrorInner as currently implemented is mostly useful for the REPL and other interactive use, less so for library integration. Rather than having to capture error messages to an I/O stream and read them from that stream, it would be easier if the latest error message were made available as a string that could be simply read/copied. It could even perhaps live in the MainGAPState, or at least some other global variable. That's an implementation detail.

Not relying strictly on I/O (even in-memory I/O streams) would also help avoid problems like #3028

@embray
Copy link
Contributor

embray commented Nov 22, 2018

And now, as I wrote about here, the GAP kernel state already has an effectively unused "ThrownObject" member that, with some relatively minor patching, could be made useful again by using it to store error messages and other error information.

@ssiccha
Copy link
Contributor

ssiccha commented Nov 28, 2018

Per my comments here it would be much easier from a third-party integration perspective if it were possible to prevent error messages from being printed to I/O streams at all, as doing so results in a lot of overhead (e.g. unnecessary copying) and other complications.

it would be easier if the latest error message were made available as a string that could be simply read/copied.

@embray Atm there is no code to get the string of e.g. an expression directly. Ofc there is the kernel function PrintExpr which could be redirected into an OutputTextString. If #2858 is sensible that could be used to build strings that contain the error message without doing lots of redirection.

@embray
Copy link
Contributor

embray commented Nov 29, 2018

I think I've brought this up elsewhere, but something like #2858 is very necessary--there are far too many objects in GAP whose string representation is made available only by printing (and thus having to capture output), which is exactly backwards :)

@embray
Copy link
Contributor

embray commented Nov 29, 2018

Are there cases of error messages (e.g. as passed to ErrorQuit and the like) where one of the arguments is something that can't otherwise be easily string-ified, such as an expression? If so, if nothing else, I'm fine replacing the actual text in those cases with a placeholder. It's better than nothing.

@ssiccha
Copy link
Contributor

ssiccha commented Nov 29, 2018

Note that I'm not speaking on behalf of the actual GAP devs:

there are far too many objects in GAP whose string representation is made available only by printing

Improving this with the kernel may be possible but doing that for the whole library and all packages at once doesn't sound realistic to me. IIRC there have been attempts to do something like that with the DisplayString or ViewString methods in the library.

Are there cases of error messages (e.g. as passed to ErrorQuit and the like) where one of the arguments is something that can't otherwise be easily string-ified, such as an expression?

Expression are printed when printing the traceback. I don't know much about the actual error messages like "No method found".

If so, if nothing else, I'm fine replacing the actual text in those cases with a placeholder. It's better than nothing.

Do you mean in this repository or in the version you use for sage?

@fingolfin fingolfin added kind: discussion discussions, questions, requests for comments, and so on and removed kind: discussion discussions, questions, requests for comments, and so on kind: question labels Mar 21, 2019
@embray
Copy link
Contributor

embray commented Mar 3, 2021

I'm working on a possible solution to this, and possibly #2822 at least from the libgap API perspective.

@fingolfin fingolfin added the topic: libgap things related to libgap label Apr 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: discussion discussions, questions, requests for comments, and so on kind: support request topic: libgap things related to libgap
Projects
None yet
Development

No branches or pull requests

5 participants