[rkward-cvs] SF.net SVN: rkward: [782] branches/environment_objects/rkward/rkward

tfry at users.sourceforge.net tfry at users.sourceforge.net
Sun Oct 1 19:03:51 UTC 2006


Revision: 782
          http://svn.sourceforge.net/rkward/?rev=782&view=rev
Author:   tfry
Date:     2006-10-01 12:03:29 -0700 (Sun, 01 Oct 2006)

Log Message:
-----------
Committing current (buggy) REnvironmentObject implementation to separate branch

Modified Paths:
--------------
    branches/environment_objects/rkward/rkward/core/Makefile.am
    branches/environment_objects/rkward/rkward/core/rcontainerobject.cpp
    branches/environment_objects/rkward/rkward/core/renvironmentobject.cpp
    branches/environment_objects/rkward/rkward/core/renvironmentobject.h
    branches/environment_objects/rkward/rkward/core/robject.cpp
    branches/environment_objects/rkward/rkward/core/robject.h
    branches/environment_objects/rkward/rkward/core/robjectlist.cpp
    branches/environment_objects/rkward/rkward/core/robjectlist.h
    branches/environment_objects/rkward/rkward/rbackend/rpackages/rkward/R/internal.R

Modified: branches/environment_objects/rkward/rkward/core/Makefile.am
===================================================================
--- branches/environment_objects/rkward/rkward/core/Makefile.am	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/core/Makefile.am	2006-10-01 19:03:29 UTC (rev 782)
@@ -2,6 +2,6 @@
 METASOURCES = AUTO
 noinst_LIBRARIES =  libcore.a
 libcore_a_SOURCES = rkvariable.cpp robjectlist.cpp robject.cpp rcontainerobject.cpp rkmodificationtracker.cpp \
-	rfunctionobject.cpp
+	rfunctionobject.cpp renvironmentobject.cpp
 noinst_HEADERS = rkvariable.h robjectlist.h robject.h rcontainerobject.h rkmodificationtracker.h \
-	rfunctionobject.h
+	rfunctionobject.h renvironmentobject.h

Modified: branches/environment_objects/rkward/rkward/core/rcontainerobject.cpp
===================================================================
--- branches/environment_objects/rkward/rkward/core/rcontainerobject.cpp	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/core/rcontainerobject.cpp	2006-10-01 19:03:29 UTC (rev 782)
@@ -171,8 +171,7 @@
 
 	QString canonified = name;
 	if (!is_canonified) {
-		// yeah, ok, this could be made more efficient relatively easily ...
-		canonified = canonified.replace ("[\"", "$").replace ('[', "").replace ("\"]", "").replace (']', "");
+		canonified = RObject::canonifyName (name);
 	}
 
 	// TODO: there could be objects with "$" in their names!

Modified: branches/environment_objects/rkward/rkward/core/renvironmentobject.cpp
===================================================================
--- branches/environment_objects/rkward/rkward/core/renvironmentobject.cpp	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/core/renvironmentobject.cpp	2006-10-01 19:03:29 UTC (rev 782)
@@ -17,18 +17,21 @@
 
 #include "renvironmentobject.h"
 
+#include "../rkglobals.h"
+#include "../rbackend/rinterface.h"
+#include "robjectlist.h"
+
 #include "../debug.h"
 
 REnvironmentObject::REnvironmentObject (RContainerObject *parent, const QString &name) : RContainerObject (parent, name) {
 	RK_TRACE (OBJECTS);
 
 	type = Environment;
-	if (name == ".GlobalEnv") {
-		type |= GlobalEnv;
+
+	if (parent != RKGlobals::rObjectList ()) {
+		type |= EnvironmentVar;
 	}
-
 	// TODO: determine namespace_name
-	// TODO: determine if this is an environment var (or maybe this is done from the parent)
 }
 
 REnvironmentObject::~REnvironmentObject () {
@@ -47,7 +50,7 @@
 
 	if (type & GlobalEnv) return (short_child_name);
 	if (type & EnvironmentVar) return (name + "$" + short_child_name);
-	return (namespace_name + "::" + short_child_name);
+	return (namespace_name + "::" + RObject::rQuote (short_child_name));
 }
 
 void REnvironmentObject::writeMetaData (RCommandChain *chain) {
@@ -56,10 +59,17 @@
 	if (type & EnvironmentVar) RContainerObject::writeMetaData (chain);
 }
 
+bool REnvironmentObject::handleClassifyCommand (RCommand *command, bool *dims_changed) {
+	RK_TRACE (OBJECTS);
+
+	if (type & EnvironmentVar) return RContainerObject::handleClassifyCommand (command, dims_changed);
+	return true;
+}
+
 QString REnvironmentObject::listChildrenCommand () {
 	RK_TRACE (OBJECTS);
 
-	return ("ls (as.environment (" + getFullName () + ", all.names=TRUE)");
+	return ("ls (" + getFullName () + ", all.names=TRUE)");
 }
 
 void REnvironmentObject::renameChild (RObject *object, const QString &new_name) {

Modified: branches/environment_objects/rkward/rkward/core/renvironmentobject.h
===================================================================
--- branches/environment_objects/rkward/rkward/core/renvironmentobject.h	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/core/renvironmentobject.h	2006-10-01 19:03:29 UTC (rev 782)
@@ -39,6 +39,9 @@
 
 	bool isGlobalEnv () { return (type & GlobalEnv); };
 
+/** reimplemented from RObject: Check type only for EnvironmentVars. Toplevel-environments are hard to classify from R space, and don't simply change their type */
+	bool handleClassifyCommand (RCommand *command, bool *dims_changed);
+
 	QString listChildrenCommand ();
 /** 
 # search ()
@@ -64,6 +67,7 @@
 RContainerObject::canonifyName
 */
 protected:
+	friend class RObjectList;
 /** reimplemented from RContainerObject to raise an assert if this is not the isGlobalEnv (). Otherwise calls "remove (objectname)" instead of objectname <- NULL" */
 	void renameChild (RObject *object, const QString &new_name);
 /** reimplemented from RContainerObject to raise an assert if this is not the isGlobalEnv (). Otherwise calls "remove (objectname)" instead of objectname <- NULL" */

Modified: branches/environment_objects/rkward/rkward/core/robject.cpp
===================================================================
--- branches/environment_objects/rkward/rkward/core/robject.cpp	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/core/robject.cpp	2006-10-01 19:03:29 UTC (rev 782)
@@ -72,6 +72,15 @@
 	return 0;
 }
 
+// static
+QString RObject::canonifyName (const QString &name) {
+	RK_TRACE (OBJECTS);
+
+	QString canonified = name;
+	// yeah, ok, this could be made more efficient relatively easily ...
+	return (canonified.replace ("[\"", "$").replace ('[', "").replace ("\"]", "").replace (']', ""));
+}
+
 QString RObject::getMetaProperty (const QString &id) {
 	RK_TRACE (OBJECTS);
 	if (meta_map) {

Modified: branches/environment_objects/rkward/rkward/core/robject.h
===================================================================
--- branches/environment_objects/rkward/rkward/core/robject.h	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/core/robject.h	2006-10-01 19:03:29 UTC (rev 782)
@@ -134,10 +134,12 @@
 @param is_canonified the object name may usually have to be canonified. Since this function may be called recursively, canonification may already have occured on a higher level. In this case the argument is set to true to avoid some duplicate work. When calling from outside always leave the default false.
 @returns a pointer to the object (if found) or 0 if not found */
 	virtual RObject *findObject (const QString &name, bool is_canonified=false);
+	static QString canonifyName (const QString &name);
 protected:
 // why do I need those to compile? I thought they were derived classes!
 	friend class RContainerObject;
 	friend class RObjectList;
+	friend class REnvironmentObject;
 	RContainerObject *parent;
 	QString name;
 	int type;
@@ -165,7 +167,7 @@
 @param command The command. Make sure it really is a  .rk.classify command *before* calling this function!
 @param dims_changed If the dimensions changed, this bool is set to true. If the dimensions did not change, it is left untouched (i.e. even if it already was true)
 @returns false if there was a type mismatch. In this case you *must* return! */
-	bool handleClassifyCommand (RCommand *command, bool *dims_changed);
+	virtual bool handleClassifyCommand (RCommand *command, bool *dims_changed);
 
 /** an instance of this struct is created, when the object is opened for editing. For one thing, it keeps track of which editor(s) are working on the object.
 In subclasses like RKVariable, the struct is extended to additionally hold the data of the object, etc. */

Modified: branches/environment_objects/rkward/rkward/core/robjectlist.cpp
===================================================================
--- branches/environment_objects/rkward/rkward/core/robjectlist.cpp	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/core/robjectlist.cpp	2006-10-01 19:03:29 UTC (rev 782)
@@ -30,6 +30,7 @@
 
 #include "rkvariable.h"
 #include "rfunctionobject.h"
+#include "renvironmentobject.h"
 
 #include "../rbackend/rinterface.h"
 #include "rkmodificationtracker.h"
@@ -49,6 +50,8 @@
 	type = RObject::Workspace;
 	
 	update_chain = 0;
+	toplevel_environments = 0;
+	num_toplevel_environments = 0;
 }
 
 
@@ -73,6 +76,8 @@
 			childUpdateComplete ();
 			return;
 		}
+		REnvironmentObject **new_toplevel_envs = new REnvironmentObject*[command->stringVectorLength ()];
+		int num_new_toplevel_envs = 0;
 		for (int i = 0; i < command->stringVectorLength (); ++i) {
 			QString cname = command->getStringVector ()[i];		// for easier typing
 			/*if (cname == (".rk.meta")) {
@@ -82,13 +87,22 @@
 			if (childmap.find (cname) != childmap.end ()) {
 				childmap[cname]->updateFromR ();
 			} else {
-				createFromR (this, cname);
+				createToplevelEnvironment (cname);
 				changed = true;
 			}
+
+			RObject *object = childmap[cname];
+			RK_ASSERT (object);
+			RK_ASSERT (object->isType (Environment));
+			new_toplevel_envs[num_new_toplevel_envs++] = static_cast<REnvironmentObject *> (object);
 		}
+		delete [] toplevel_environments;
+		toplevel_environments = new_toplevel_envs;
+		num_toplevel_environments = num_new_toplevel_envs;
 	} else if (command->getFlags () == CHILD_GET_TYPE_COMMAND) {
 		if (command->intVectorLength () != 1) {
 			RK_ASSERT (false);
+			qDebug (command->command ().latin1());
 		}
 
 		PendingObject *pobj = pending_objects[command];
@@ -114,7 +128,7 @@
 QString RObjectList::listChildrenCommand () {
 	RK_TRACE (OBJECTS);
 
-	return ("ls (all.names=TRUE)");
+	return ("search ()");
 }
 
 void RObjectList::updateFromR () {
@@ -133,12 +147,12 @@
 	RKGlobals::rInterface ()->issueCommand (command, update_chain);
 }
 
- void RObjectList::createFromR (RContainerObject *parent, const QString &cname) {
+void RObjectList::createFromR (RContainerObject *parent, const QString &cname) {
 	RK_TRACE (OBJECTS);
- 	PendingObject *obj = new PendingObject;
+	PendingObject *obj = new PendingObject;
 	obj->name = cname;
 	obj->parent = parent;
-	
+
 	QString fullname = parent->makeChildName (cname);
 
 	RCommand *command = new RCommand (".rk.get.type (" + fullname + ")", RCommand::App | RCommand::Sync | RCommand::GetIntVector, QString::null, this, CHILD_GET_TYPE_COMMAND);
@@ -146,6 +160,24 @@
 	RKGlobals::rInterface ()->issueCommand (command, update_chain);
 }
 
+void RObjectList::createToplevelEnvironment (const QString &name) {
+	RK_TRACE (OBJECTS);
+	RK_ASSERT (childmap.find (name) == childmap.end ());
+
+	REnvironmentObject *envobj = new REnvironmentObject (this, name);
+	if (name == ".GlobalEnv") {
+		envobj->type |= GlobalEnv;
+	} else if (name.contains (':')) {
+		envobj->namespace_name = name.section (':', 1);
+	} else if (name == "Autoloads") {
+		envobj->type |= GlobalEnv;		// this is wrong! but it's a temporary HACK to get things to work
+	}
+
+	addChild (envobj, name);
+	RKGlobals::tracker ()->addObject (envobj, 0);
+	envobj->updateFromR ();
+}
+
 void RObjectList::childUpdateComplete () {
 	RK_TRACE (OBJECTS);
 	RK_ASSERT (num_children_updating);
@@ -161,41 +193,75 @@
 	}
 }
 
+RObject *RObjectList::findObject (const QString &name, bool is_canonified) {
+	RK_TRACE (OBJECTS);
+
+	QString canonified = name;
+	if (!is_canonified) {
+		canonified = RObject::canonifyName (name);
+	}
+
+	// TODO: there could be objects with "::" in their names!
+	if (canonified.contains ("::")) {
+		QString env = canonified.section ("::", 0, 0);
+		QString remainder = canonified.section ("::", 1);
+
+		RObjectMap::iterator it = childmap.find (env);
+		if (it == childmap.end ()) return 0;
+
+		RObject *found = it.data ();
+		return (found->findObject (remainder, true));
+	}
+
+	// no environment specified, do regular search:
+	// TODO: there could be objects with "$" in their names!
+	QString current_level = canonified.section (QChar ('$'), 0, 0);
+	QString remainder = canonified.section (QChar ('$'), 1);
+
+	for (int i = 0; i < num_toplevel_environments; ++i) {
+		RObject *found = toplevel_environments[i]->findChild (current_level);
+		if (found) {
+			if (remainder.isEmpty ()) return (found);
+			return (found->findObject (remainder, true));
+		}
+	}
+	return 0;
+}
+
 void RObjectList::timeout () {
 	RK_TRACE (OBJECTS);
 	updateFromR ();
 }
 
-void RObjectList::renameChild (RObject *object, const QString &new_name) {
+void RObjectList::renameChild (RObject *, const QString &) {
 	RK_TRACE (OBJECTS);
 
-	RObjectMap::iterator it = childmap.find (object->getShortName ());
-	RK_ASSERT (it.data () == object);
-	
-	RCommand *command = new RCommand (makeChildName (new_name) + " <- " + object->getFullName ());
-	RKGlobals::rInterface ()->issueCommand (command, 0);
-	command = new RCommand ("remove (" + object->getFullName () + ")", RCommand::App | RCommand::Sync);
-	RKGlobals::rInterface ()->issueCommand (command, 0);
-	
-	childmap.remove (it);
-	childmap.insert (new_name, object);
-
-	object->name = new_name;
+	RK_ASSERT (false);
 }
 
 void RObjectList::removeChild (RObject *object, bool removed_in_workspace) {
 	RK_TRACE (OBJECTS);
 
-	RObjectMap::iterator it = childmap.find (object->getShortName ());
-	RK_ASSERT (it.data () == object);
-	
-	if (!removed_in_workspace) {
-		RCommand *command = new RCommand ("remove (" + object->getFullName () + ")", RCommand::App | RCommand::Sync);
-		RKGlobals::rInterface ()->issueCommand (command, 0);
+	if (removed_in_workspace) {
+		RObjectMap::iterator it = childmap.find (object->getShortName ());
+		RK_ASSERT (it.data () == object);
+		childmap.remove (it);
+
+		// remove from list of toplevel environments
+		REnvironmentObject **new_toplevel_envs = new REnvironmentObject*[num_toplevel_environments];
+		int num_new_toplevel_envs = 0;
+		for (int i=0; i < num_toplevel_environments; ++i) {
+			if (toplevel_environments[i] != object) new_toplevel_envs[num_new_toplevel_envs++] = toplevel_environments[i];
+		}
+		RK_ASSERT ((num_toplevel_environments - 1) == num_new_toplevel_envs); 
+		delete [] toplevel_environments;
+		toplevel_environments = new_toplevel_envs;
+		num_toplevel_environments = num_new_toplevel_envs;
+
+		delete object;
+	} else {
+		RK_ASSERT (false);
 	}
-	
-	childmap.remove (it);
-	delete object;
 }
 
 #include "robjectlist.moc"

Modified: branches/environment_objects/rkward/rkward/core/robjectlist.h
===================================================================
--- branches/environment_objects/rkward/rkward/core/robjectlist.h	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/core/robjectlist.h	2006-10-01 19:03:29 UTC (rev 782)
@@ -30,6 +30,7 @@
 class RCommand;
 class RCommandChain;
 class RKEditor;
+class REnvironmentObject;
 
 /**
 This class is responsible for keeping and updating a list of objects in the R-workspace.
@@ -47,7 +48,7 @@
 	void updateFromR ();
 	
 	void createFromR (RContainerObject *parent, const QString &cname);
-	
+
 	QString getFullName () { return QString::null; };
 	QString makeChildName (const QString &short_child_name) { return short_child_name; };
 	/** reimplemented from RContainerObject: do nothing. The object-list has no meta data. */
@@ -58,6 +59,9 @@
 	void childUpdateComplete ();
 	QString listChildrenCommand ();
 
+	/** reimplemented from RcontainterObject, as we need to deal with search order in different environments */
+	RObject *findObject (const QString &name, bool is_canonified=false);
+
 	KURL getWorkspaceURL () { return current_url; };
 public slots:
 	void timeout ();
@@ -68,13 +72,15 @@
 	void updateComplete ();
 protected:
 	void rCommandDone (RCommand *command);
-/// reimplemented from RContainerObject to call "remove (objectname)" instead of "objectname <- NULL"
+/// reimplemented from RContainerObject to do nothing, as all children are top-level environments (raises an assert)
 	void renameChild (RObject *object, const QString &new_name);
-/// reimplemented from RContainerObject to call "remove (objectname)" instead of "objectname <- NULL"
+/// reimplemented from RContainerObject to do nothing, as all children are top-level environments (raises an assert)
 	void removeChild (RObject *object, bool removed_in_workspace);
 /// reimplemented from RContainerObject to emit a change signal
 	void objectsChanged ();
 private:
+	void createToplevelEnvironment (const QString &name);
+
 	friend class RKLoadAgent;
 	friend class RKSaveAgent;
 	void setWorkspaceURL (const KURL &url) { current_url = url; };
@@ -90,14 +96,21 @@
 	RCommandChain *update_chain;
 
 	KURL current_url;
+
+	REnvironmentObject **toplevel_environments;
+	int num_toplevel_environments;
 };
 
 /**
 \page RepresentationOfRObjectsInRKWard Representation of R objects in RKWard
 \brief How objects in R space are represented in RKWard
 
-This page has not been written, yet.
+Due to primarily two reasons, RKWard needs to keep it's own list of objects in the R workspace. The first, and most important reason is threading: R objects might be modified or even removed in the R backend, while the GUI thread is trying to access them. Since we have no control over what's going on inside R, this cannot be solved with a simple mutex. So rather, we copy a representation into memory accessed by the GUI thread only (in the future, maybe the backend thread will get access to this representation for more efficient updating, but still a representation separate from that kept in R itself is needed).
 
+The second reason is that R and Qt includes clash, and we cannot easily use R SEXPs directly in Qt code.
+
+RKWard then uses an own specialized description of R objects. This is slightly more abstracted than objects in R, but stores the most important information about each object, and of course the hierarchical organization of objects.
+
 TODO: write me!
 	
 @see RObject

Modified: branches/environment_objects/rkward/rkward/rbackend/rpackages/rkward/R/internal.R
===================================================================
--- branches/environment_objects/rkward/rkward/rbackend/rpackages/rkward/R/internal.R	2006-10-01 19:01:37 UTC (rev 781)
+++ branches/environment_objects/rkward/rkward/rbackend/rpackages/rkward/R/internal.R	2006-10-01 19:03:29 UTC (rev 782)
@@ -23,14 +23,15 @@
 	if (is.list (x)) type = type + 8
 	if (type != 0) type = type + 16 else type = 32
 	if (is.function (x)) type = 128
-	if (!is.null (attr (x, ".rk.meta"))) type = type + 256
+	if (is.environment (x)) type = type + 256 + 1024	# Environment variable
+	if (!is.null (attr (x, ".rk.meta"))) type = type + 2048
 	d <- dim (x)
 	if (length (d) < 1) d <- length (x);	# handling for objects that according to R do not have a dimension (such as vectors, functions, etc.)
 	c (type, d)
 }
 
 ".rk.get.type" <- function (x) {
-	if (is.data.frame (x) || is.matrix (x) || is.array (x) || is.list (x)) return (1)		# container
+	if (is.data.frame (x) || is.matrix (x) || is.array (x) || is.list (x) || is.environment (x)) return (1)		# container
 	if (is.function (x)) return (2)		# function
 	if (is.vector (x)) return (3)		# a vector/variable
 	return (4)		# something else


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