[Rcpp-devel] Catching parse errors with RInside::parseEval()
Theodore Lytras
thlytras at gmail.com
Wed Oct 10 23:39:42 CEST 2012
Στις Τετ 10 Οκτ 2012, ο/η Dirk Eddelbuettel έγραψε:
> There is a boolean in RInside.cpp that you need to flip. Eventually, we
> could (if it is useful) support a flag at instantiation of the RObject.
[snip]
> | I browsed the code, and a few lines down I see:
> |
> | case PARSE_ERROR:
> | Rf_error("Parse Error: \"%s\"\n", line.c_str());
> | UNPROTECT(2);
> | return 1;
> | break;
> |
> | thus it appears that parse errors are already handled. Even better:
> | handled with a return code (I don't like exceptions that much). So I
> | guess the only problem is that we're not in interactive mode, correct?
>
> In theory. In practice, I think, it just doesn't get there.
>
> | What kind of work/extensions do you suggest this code needs? (I could
> | try to work a little on that, and learn a little about the insides of
> | R in the process).
>
> I think it is pretty much this switch block we need to get to work
> properly.
>
> Dirk
Hi Dirk,
I studied RInside.cpp, made a few trial-and-error tests, and it appears to
work for me now - parseEval() doesn't crash when fed with syntactically
incorrect R code.
I am attaching a patch I made with quilt (interactive.diff), so you can see
what I did.
Turns out, that boolean you were talking about (on line 152) did no good.
Leaving it to false results in a crash ("Execution halted"), switching it to
true results in a crash plus a segmentation fault!
Turns out also that the switch statement is indeed evaluated. It gets there.
What halts execution is indeed the Rf_error() function; changing that to
Rf_warning() solves the problem, and allows parseEval() to return 1 and
parseEvalQ() to throw its exception.
One also needs to call mb_m.rewind() afterwards, or the MemBuf is not cleared
and subsequent calls to parseEval() fail as well.
As a result I added a boolean to RInside.h (interactiveMode) along with a
setter function (setInteractive(bool)), in order to enable this behaviour
instead of the old one.
Now it works perfectly for me!
As an alternative, we could get rid of the boolean altogether and also get rid
of the Rf_error() or Rf_warning(). I don't think it can ever be good to "halt
execution" when dealing with syntactically incorrect R code. Returning an
error code or throwing an exception is better. And the Rf_warning() is also
unnecessary, if case PARSE_NULL: and case PARSE_ERROR: return their own error
code (eg. 2 and 3). No code using RInside should be affected by this, since
until now the error code was not returned and execution was halted at
Rf_error().
So if you aggree with that, you can apply instead the other patch I'm
attaching (simplified.diff). I guess that's the best solution.
Hope this helps a bit! It sure solved my problem.
Regards,
Theodore
-------------- next part --------------
A non-text attachment was scrubbed...
Name: interactive.diff
Type: text/x-patch
Size: 2527 bytes
Desc: not available
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20121011/2d9e41e2/attachment-0002.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: simplified.diff
Type: text/x-patch
Size: 767 bytes
Desc: not available
URL: <http://lists.r-forge.r-project.org/pipermail/rcpp-devel/attachments/20121011/2d9e41e2/attachment-0003.bin>
More information about the Rcpp-devel
mailing list