<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"><html><head><meta name="qrichtext" content="1" /><style type="text/css">p, li { white-space: pre-wrap; }</style></head><body style=" font-family:'Bitstream Vera Sans'; font-size:10pt; font-weight:400; font-style:normal;">Hi,<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>as I'm posting to rkward-devel, I'm leaving in all the context for others to pick up reading. <br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>On Tuesday 26 May 2009, you wrote:<br>
> Thomas Friedrichsmeier wrote:http://dirk.eddelbuettel.com/code/rinside.htm<br>
> > Hi,<br>
> ><br>
> > On Tuesday 26 May 2009, you wrote:<br>
> > > I am interested in developping a front-end to R debugging abilities<br>
> > > (browser, debug, ...), and rkward is a candidate host. This was a<br>
> > > google summer of code idea for R this year, but was not retained<br>
> > > eventually, so I will probably end up doing it on my own.<br>
> ><br>
> > I saw your mail on r-devel, and marked it as "I may want to look into<br>
> > this some time", but I have to admit, I have not read the thread, yet.<br>
> > Decent debugging support is certainly a much wanted feature in rkward.<br>
> > If you would like to work on that, I'll try to be of help as much as I<br>
> > can.<br>
><br>
> Good. The more helpful you are, the more likely rkward is to be chosen<br>
> as the first host for the feature, the more marketing you can do about<br>
> it ;-)<br>
><br>
> Although, I've already started to look into adding the feature to<br>
> biocep, but this is not the first time I make proposal to the biocep<br>
> team (karim) which are simply not taken care of, so ...<br>
><br>
> > > Now, as it happens, the REPL implementation in rkward does not treat<br>
> > > input from within the browser the same way as regular top level input,<br>
> > > but rather brings a dialog box. This might be related to the use of<br>
> > > R_ReplDLLdo1, instead of the usual REPL mechanism, but I am not sure (I<br>
> > > have just been looking at the code today).<br>
> ><br>
> > The REPL-implementation in rkward is quite a mess. Not all of that is<br>
> > the fault of R (some is simply bad code that I did not find the time<br>
> > to improve, yet), but the basic problem is that the rkward-concept<br>
> > just doesn't map well to a REPL-loop. The R REPL loop is basically<br>
> > assuming one single channel of user input (namely a terminal).<br>
><br>
> Yes, but if this leaves in its on thread, with a bit of care, this can<br>
> survive without being the main thread. As an example JGR uses the REPL<br>
> (through JRI). The relevant part of the readConsole callback is this:<br>
><br>
>         output.append(prompt, JGRPrefs.CMD);<br>
>             output.setCaretPosition(outputDoc.getLength());<br>
>             String s = JGR.rSync.waitForNotification();<br>
>             try {<br>
>                 outputDoc.insertString(outputDoc.getLength(), s + "\n",<br>
>                         JGRPrefs.CMD);<br>
>             } catch (Exception e) {<br>
>             }<br>
>             return (s == null || s.length() == 0) ? "\n" : s + "\n";<br>
><br>
> ... and most of the magic is in the JGR.rSync.waitForNotification()<br>
> call, which basically sleeps until there is actually something to do. I<br>
> am pretty sure this could be done in rkward as well.<br>
><br>
> > In rkward, commands may originate from a number of different sources,<br>
> > and may not necessarily be executed in the order that they are<br>
> > generated (see RCommandStack, and the doxygen page "Using the<br>
> > interface to R" (defined in rinterface.h), if you're interested in<br>
> > some details).<br>
><br>
> I'll have a look. This probably can survive alongside a proper REPL.<br>
><br>
> > In much older versions of RKWard we did not use R's REPLs at all, but<br>
> > basically relied on R_tryEval(). However, this approach has important<br>
> > drawbacks as well. In rembedinternal.cpp around line 1000 you find a<br>
> > rough explanation of how we try to tame the R REPL loop, and why. Also<br>
> > see https://stat.ethz.ch/pipermail/r-devel/2007-January/044336.html<br>
> > for some desiderata, if you like. I never got any feedback on that,<br>
> > and did not pursue this any further.<br>
> ><br>
> ><br>
> > (BTW, the reason we don't use the main REPL is that this never<br>
> > returns. So that assumes that R is in charge of all event handling,<br>
> > but unfortunately in rkward it's just the other way around.)<br>
><br>
> again, not necessarily true, R just needs to believe it controls, but we<br>
> can fool it.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Now that you mention it, I think you're right, and in fact I've played with that idea a bit in the past. techdocs/r_eventloops picks it up in the context of another long-term project (which is to split out the R backend into a separate process, which could even run on a remote machine).<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>It's simply been a while since I last thought about these issues.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>That said, while restructuring the backend to run the regular R REPL, may be worth-while, I don't think it really makes much of a difference, in this context, or if so, I still fail to see, how.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>> > In a nutshell, the issue with the REPL is that R_ReadConsole is used<br>
> > for several quite distinct purposes:<br>
> > 1) Waiting for toplevel - parsable/command - input.<br>
> > 2) Fetching more of the toplevel input, if it was too long to fit in<br>
> > the buffer.<br>
> > 3) Requests for generic user input -> readline().<br>
> > 4) The browser.<br>
> > In rkward we need to spend quite some effort on finding out whether<br>
> > R_ReadConsole is doing 1, 2 or 3/4, as that info is not readily<br>
> > available. 3 and 4 are not yet differentiated, and both treated the<br>
> > same in rkward (try readline("test"); to see it's actually the same<br>
> > dialog).<br>
> ><br>
> ><br>
> > So the first task would be to find out, when exactly a call to<br>
> > R_ReadConsole signifies we are in a debugging-context (4) instead of a<br>
> > generic input request (3). Probably this is not too hard to do, but I<br>
> > simply haven't looked into that, yet.<br>
><br>
> The prompt argument of the readConsole callback gives you a clue I<br>
> suppose, but the key I think (from what simon urbanek told me on the<br>
> R-devel thread) is that if you use the REPL, you don't have to care so<br>
> much.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>If I understood that correctly, he's basically just saying that R_ReadConsole gets called from inside the REPL when in the browser(). The same thing is true in our version of the loop.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>In fact, as long as we don't return from the toplevel statement, there should be (almost) no difference between running the full loop and R_ReplDLLdo1. The main difference is that Rf_mainloop continues after returning from a toplevel statement, while R_ReplDLLdo1 does not. When debugging we stay inside a statement all the time. Note that I'm not oppossed to switching to the full REPL, at all. Just saying that perhaps it's not a requirement, here.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Yes, probably the prompt argument is all the cues we need to find out were in the browser(). So we can just go and feed it the commands we want it to run...<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>> > The second task would be to signal that to the main/GUI thread.<br>
> > RThread::handleStandardCallback() or RThread::handleSubstackCall()<br>
> > could be used for that. This would then allow a specialized debugger<br>
> > widget/window (task number three) to run further R commands in the<br>
> > current context to gather relevant information such as the call stack<br>
> > / code of the function we're in, .... (Here we have another small -<br>
> > but solvable - issue that currently rkward evaluates all statements in<br>
> > the globalenv()).<br>
> ><br>
> ><br>
> > So all in all, adding a nice debugger should be possible without<br>
> > having to change the whole application design, but of course it's not<br>
> > exactly trivial, either.<br>
> ><br>
> ><br>
> > Let me know, what I can do to help you with this.<br>
><br>
> My guesss is that the first step is going to be to set up an actual<br>
> REPL, with all the pain this can cause. I can look into it although I am<br>
> not so familiar with Qt and KDE, but the code looks alright with enough<br>
> comments to pick things up.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Some more technical comments on this:<br>
- Historically we could not bring Qt-includes and R-includes together in the same source file. This is the reason, why rthread.cpp and rembedinternal.cpp are separated the way they are. It may - or may not - be helpful to merge the two.<br>
- Partially for the same reason, some of the data formats are quite strange. I'm quite embarassed of RCallbackArgs, for example, and hope to change it one day.<br>
- We have a lot of legacy support for ancient versions of R. I intend to drop everything before R 2.7.x in trunk. This might simplify the backend code quite a bit in a few places.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Regarding this, how do you think you will proceed? If you're going to start playing with the backend code right away, I'll simply refrain from doing any non-needed changes for the time being. In contrast, if you're going to spend a few more weeks on the conceptual level, it might be quite helpful if I start working on some cleanups as soon as possible.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>> Have you looked into Dirk's Rinside:<br>
> http://dirk.eddelbuettel.com/code/rinside.html<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>No, not yet, and ATM the server just gives me an error.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>> Do you think this discussion should be broadcast to one of your mailing<br>
> list ? which one ?<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Yes, in fact. I'm taking this to rkward-devel.<br>
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; -qt-user-state:0;"><br></p>Regards<br>
Thomas</p></body></html>