[education/rkward/releases/0.8.3] rkward/rbackend: Make do without SET_PRx functions

Thomas Friedrichsmeier null at kde.org
Fri Apr 17 16:32:41 BST 2026


Git commit 63bf8a9bae8588b87f55af7eaea73f9c4410e782 by Thomas Friedrichsmeier.
Committed on 17/04/2026 at 13:37.
Pushed by tfry into branch 'releases/0.8.3'.

Make do without SET_PRx functions

M  +0    -2    rkward/rbackend/rkrapi.h
M  +5    -8    rkward/rbackend/rkstructuregetter.cpp
M  +1    -1    rkward/rbackend/rkstructuregetter.h

https://invent.kde.org/education/rkward/-/commit/63bf8a9bae8588b87f55af7eaea73f9c4410e782

diff --git a/rkward/rbackend/rkrapi.h b/rkward/rbackend/rkrapi.h
index f8b8831c8..c3b144934 100644
--- a/rkward/rbackend/rkrapi.h
+++ b/rkward/rbackend/rkrapi.h
@@ -297,8 +297,6 @@ class RFn : public QObject {
 	IMPORT_R_API(STRING_ELT);
 	IMPORT_R_API(SET_STRING_ELT);
 	IMPORT_R_API(SET_VECTOR_ELT);
-	IMPORT_R_API(SET_PRENV);
-	IMPORT_R_API(SET_PRVALUE);
 	IMPORT_R_API(TYPEOF);
 	IMPORT_R_API(VECTOR_ELT);
 	IMPORT_R_API(run_Rmainloop);
diff --git a/rkward/rbackend/rkstructuregetter.cpp b/rkward/rbackend/rkstructuregetter.cpp
index 2fcd18f77..d1f079431 100644
--- a/rkward/rbackend/rkstructuregetter.cpp
+++ b/rkward/rbackend/rkstructuregetter.cpp
@@ -130,11 +130,14 @@ void RKStructureGetter::getStructureSafe(SEXP value, const QString &name, int ad
  *
  *  @note This is is not quite perfect, however. E.g. if we have two promises a and b, where b takes a slice out of a, then
  *        evaluating b will force a, permanently. */
-SEXP RKStructureGetter::resolvePromise(SEXP from) {
+SEXP RKStructureGetter::resolvePromise(SEXP from, SEXP env) {
 	RK_TRACE(RBACKEND);
 
 	SEXP ret = from;
 	if (RFn::TYPEOF(from) == PROMSXP) {
+		if (keep_evalled_promises) {
+			return RFn::Rf_eval(ret, env);
+		}
 		ret = RFn::PRVALUE(from);
 		if (ret == ROb(R_UnboundValue)) {
 			RK_DEBUG(RBACKEND, DL_TRACE, "temporarily resolving unbound promise");
@@ -144,10 +147,6 @@ SEXP RKStructureGetter::resolvePromise(SEXP from) {
 			//        Not setting it from here, only means, any recursion will be detected one level later.
 			ret = RFn::Rf_eval(RFn::PRCODE(from), RFn::PRENV(from));
 			// SET_PRSEEN(from, 0);
-			if (keep_evalled_promises) {
-				RFn::SET_PRVALUE(from, ret);
-				RFn::SET_PRENV(from, ROb(R_NilValue));
-			}
 			RFn::Rf_unprotect(1);
 
 			RK_DEBUG(RBACKEND, DL_TRACE, "resolved type is %d", RFn::TYPEOF(ret));
@@ -174,8 +173,6 @@ void RKStructureGetter::getStructureWorker(SEXP val, const QString &name, int ad
 	SEXP value = val;
 	PROTECT_INDEX value_index;
 	RFn::R_ProtectWithIndex(value, &value_index);
-	// manually resolve any promises
-	RFn::R_Reprotect(value = resolvePromise(value), value_index);
 
 	bool is_s4 = RFn::Rf_isS4(value);
 	SEXP baseenv = ROb(R_BaseEnv);
@@ -372,7 +369,7 @@ void RKStructureGetter::getStructureWorker(SEXP val, const QString &name, int ad
 			for (int i = 0; i < childcount; ++i) {
 				SEXP current_childname = RFn::Rf_install(RFn::R_CHAR(RFn::STRING_ELT(childnames_s, i))); // ??? Why does simply using RFn::STRING_ELT(childnames_i, i) crash?
 				RFn::Rf_protect(current_childname);
-				SEXP child = RFn::Rf_findVar(current_childname, value);
+				SEXP child = resolvePromise(RFn::Rf_findVar(current_childname, value), value);
 				RFn::Rf_protect(child);
 
 				getStructureSafe(child, childnames[i], 0, children[i], nesting_depth + 1);
diff --git a/rkward/rbackend/rkstructuregetter.h b/rkward/rbackend/rkstructuregetter.h
index 4951eee17..9b92bffa8 100644
--- a/rkward/rbackend/rkstructuregetter.h
+++ b/rkward/rbackend/rkstructuregetter.h
@@ -36,7 +36,7 @@ class RKStructureGetter {
 	/** needed to wrap things inside an R_ToplevelExec */
 	static void getStructureWrapper(GetStructureWorkerArgs *data);
 	void getStructureSafe(SEXP value, const QString &name, int add_type_flags, RData *storage, int nesting_depth);
-	SEXP resolvePromise(SEXP from);
+	SEXP resolvePromise(SEXP from, SEXP env);
 
 	SEXP prefetch_fun(const char *name, bool from_base = true);
 



More information about the rkward-tracker mailing list