[rkward-cvs] SF.net SVN: rkward:[3161] branches/2010_10_18_backend_restructuring_branch/ rkward/rbackend

tfry at users.sourceforge.net tfry at users.sourceforge.net
Thu Oct 28 16:28:14 UTC 2010


Revision: 3161
          http://rkward.svn.sourceforge.net/rkward/?rev=3161&view=rev
Author:   tfry
Date:     2010-10-28 16:28:13 +0000 (Thu, 28 Oct 2010)

Log Message:
-----------
Handle the strange games that browser()-calls play in R. As a side-effect, we can now identify, when inside a browser().

Modified Paths:
--------------
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp
    branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp	2010-10-28 16:26:32 UTC (rev 3160)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.cpp	2010-10-28 16:28:13 UTC (rev 3161)
@@ -19,7 +19,8 @@
 
 // static
 RThread *RThread::this_pointer = 0;
-RThread::RKReplStatus RThread::repl_status = { QByteArray (), 0, true, 0, 0, RThread::RKReplStatus::NoUserCommand, 0 };
+RThread::RKReplStatus RThread::repl_status = { QByteArray (), 0, true, 0, 0, RThread::RKReplStatus::NoUserCommand, 0, false };
+void* RThread::default_global_context = 0;
 
 #include <qstring.h>
 #include <QStringList>
@@ -124,7 +125,7 @@
 	Q_UNUSED (value);
 	Q_UNUSED (visible);
 
-	if (RThread::repl_status.eval_depth == 0) {
+	if ((RThread::repl_status.eval_depth == 0) && (!RThread::repl_status.in_browser_context)) {		// Yes, toplevel-handlers _do_ get called in a browser context!
 		RK_ASSERT (RThread::repl_status.user_command_status = RThread::RKReplStatus::UserCommandRunning);
 		if (succeeded) {
 			RThread::repl_status.user_command_successful_up_to = RThread::repl_status.user_command_parsed_up_to;
@@ -183,7 +184,15 @@
 
 	RK_ASSERT (buf && buflen);
 	RK_ASSERT (RThread::repl_status.eval_depth >= 0);
-	if (RThread::repl_status.eval_depth == 0) {
+
+	if (RThread::repl_status.in_browser_context) {		// previously we were in a browser context. Check, whether we've left that.
+		if (RThread::default_global_context == R_GlobalContext) {
+			RThread::repl_status.in_browser_context = false;
+			RK_ASSERT (!hist);
+		}
+	}
+	
+	if ((!RThread::repl_status.in_browser_context) && (RThread::repl_status.eval_depth == 0)) {
 		while (1) {
 			if (RThread::repl_status.user_command_status == RThread::RKReplStatus::NoUserCommand) {
 				RCommandProxy *command = RThread::this_pointer->fetchNextCommand ();
@@ -235,17 +244,30 @@
 				RThread::repl_status.user_command_status = RThread::RKReplStatus::NoUserCommand;
 				RThread::this_pointer->commandFinished ();
 			} else if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandRunning) {
-				// it appears, the user command triggered a call to readline.
-				int n_frames = RKRSupport::SEXPToInt (RKRSupport::callSimpleFun0 (Rf_findFun (Rf_install ("sys.nframe"), R_BaseEnv), R_GlobalEnv));
+				// This can mean three different things:
+				// 1) User called readline ()
+				// 2) User called browser ()
+				// 3) R jumped us back to toplevel behind our backs.
+				// Let's find out, which one it is.
+				if (hist && (RThread::default_global_context != R_GlobalContext)) {
+					break;	// this looks like a call to browser(). Will be handled below.
+				}
+
+				int n_frames = 0;
+				RCommandProxy *dummy = RThread::this_pointer->runDirectCommand ("sys.nframe()", RCommand::GetIntVector);
+				if ((dummy->getDataType () == RData::IntVector) && (dummy->getDataLength () == 1)) {
+					n_frames = dummy->getIntVector ()[0];
+				}
+				// What the ??? Why does this simple version always return 0?
+				//int n_frames = RKRSupport::SEXPToInt (RKRSupport::callSimpleFun0 (Rf_install ("sys.nframe"), R_GlobalEnv));
 				if (n_frames < 1) {
-					// No active frames? This is either a browser() call at toplevel, or R jumped us back to toplevel, behind our backs.
+					// No active frames? This can't be a call to readline(), then, so probably R jumped us back to toplevel, behind our backs.
 					// For safety, let's reset and start over.
 					RThread::this_pointer->current_command->status |= RCommand::Failed | RCommand::ErrorOther;
 					RThread::repl_status.user_command_status = RThread::RKReplStatus::ReplIterationKilled;
-#warning TODO: use Rf_error(""), instead?
 					RK_doIntr ();	// to discard the buffer
 				} else {
-					// Handled below
+					// A call to readline(). Will be handled below
 					break;
 				}
 			} else if (RThread::repl_status.user_command_status == RThread::RKReplStatus::UserCommandFailed) {
@@ -261,7 +283,12 @@
 	}
 
 	// here, we handle readline() calls and such, i.e. not the regular prompt for code
-	// browser() also takes us here. TODO: give browser() special handling! May be identifiable due to hist==true
+	// browser() also takes us here.
+	if (hist && (RThread::default_global_context != R_GlobalContext)) {
+		// TODO: give browser() special handling!
+		RThread::repl_status.in_browser_context = true;
+	}
+
 	RBackendRequest request (true, RBackendRequest::ReadLine);
 	request.params["prompt"] = QVariant (prompt);
 	request.params["cancelled"] = QVariant (false);
@@ -272,15 +299,12 @@
 		RK_doIntr();
 		// threoretically, the above should have got us out of the loop, but for good measure:
 		Rf_error ("cancelled");
+		RK_ASSERT (false);	// should not reach this point.
 	}
 
 	QByteArray localres = RThread::this_pointer->current_locale_codec->fromUnicode (request.params["result"].toString ());
 	// need to append a newline, here. TODO: theoretically, RReadConsole comes back for more, if \0 was encountered before \n.
 	qstrncpy ((char *) buf, localres.left (buflen - 2).append ('\n').data (), buflen);
-
-	// we should not ever get here, but still...
-	RK_ASSERT (false);
-	buf[0] = '\0';
 	return 1;
 }
 
@@ -824,6 +848,7 @@
 
 	connectCallbacks();
 	RKInsertToplevelStatementFinishedCallback (0);
+	default_global_context = R_GlobalContext;
 
 	// get info on R runtime version
 	RCommandProxy *dummy = runDirectCommand ("as.numeric (R.version$major) * 1000 + as.numeric (R.version$minor) * 10", RCommand::GetIntVector);

Modified: branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h
===================================================================
--- branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h	2010-10-28 16:26:32 UTC (rev 3160)
+++ branches/2010_10_18_backend_restructuring_branch/rkward/rbackend/rembedinternal.h	2010-10-28 16:28:13 UTC (rev 3161)
@@ -168,7 +168,7 @@
 @param argv Arguments as would be passed on the commandline to R
 @param stack_check C stack checking enabled */
 	bool startR (int argc, char **argv, bool stack_check);
-
+public:
 /** convenience low-level function for running a command, directly
 @param command command to be runCommand
 @returns true if command was run successfully, false in case of an error */
@@ -178,7 +178,6 @@
 @param datatype the data type that should be (attempted to be) returned
 @returns a pointer to the RCommandProxy-instance that was created and used, internally. You can query this pointer for status and data. Be sure to delete it, when done. */
 	RCommandProxy *runDirectCommand (const QString &command, RCommand::CommandTypes datatype); 
-public:
 /** call this periodically to make R's x11 windows process their events */
 	static void processX11Events ();
 
@@ -230,8 +229,11 @@
 			ReplIterationKilled
 		} user_command_status;
 		int eval_depth;		// Number (depth) of non-user commands currently running. User commands can only run at depth 0
+		bool in_browser_context;
 	};
 	static RKReplStatus repl_status;
+/** holds a copy of the default R_GlobalContext. Needed to find out, when a browser context has been left. */
+	static void *default_global_context;
 
 	void commandFinished (bool check_object_updates_needed=true);
 /** thread is killed. Should exit as soon as possible. @see kill */


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.




More information about the rkward-tracker mailing list