@@ -773,6 +773,48 @@ static SEXP R_GetGlobalCacheLoc(SEXP symbol)
773773}
774774#endif /* USE_GLOBAL_CACHE */
775775
776+
777+ /*----------------------------------------------------------------------
778+ R_GetBindingType
779+ */
780+
781+ R_BindingType R_GetBindingType (SEXP sym , SEXP env ) {
782+ /* We are currently getting the location in the environment twice:
783+ * - In `R_BindingIsActive()`
784+ * - In `Rf_findVarInFrame3()`
785+ * Ideally we'd do it once, which would require manually walking
786+ * over the environment frame / hashtable and get the location to
787+ * inspect. */
788+
789+ if (TYPEOF (sym ) != SYMSXP )
790+ error (_ ("not a symbol" ));
791+ if (TYPEOF (env ) != ENVSXP )
792+ error (_ ("not an environment" ));
793+
794+ /* This check must be before `Rf_findVarInFrame3()` because that
795+ * forces active bindings */
796+ if (R_BindingIsActive (sym , env ))
797+ return R_BindingTypeActive ;
798+
799+ SEXP value = Rf_findVarInFrame3 (env , sym , FALSE);
800+
801+ if (value == R_UnboundValue )
802+ return R_BindingTypeUnbound ;
803+
804+ if (value == R_MissingArg )
805+ return R_BindingTypeMissing ;
806+
807+ if (TYPEOF (value ) == PROMSXP ) {
808+ if (PROMISE_IS_EVALUATED (value ))
809+ return R_BindingTypeForced ;
810+ else
811+ return R_BindingTypeDelayed ;
812+ }
813+
814+ return R_BindingTypeValue ;
815+ }
816+
817+
776818/*----------------------------------------------------------------------
777819
778820 unbindVar
@@ -3457,6 +3499,32 @@ void R_unLockBinding(SEXP sym, SEXP env)
34573499 }
34583500}
34593501
3502+ void R_MakeDelayedBinding (SEXP sym , SEXP expr , SEXP evalEnv , SEXP env ) {
3503+ if (TYPEOF (sym ) != SYMSXP )
3504+ error (_ ("not a symbol" ));
3505+ if (TYPEOF (env ) != ENVSXP )
3506+ error (_ ("not an environment" ));
3507+ if (TYPEOF (evalEnv ) != ENVSXP )
3508+ error (_ ("not an environment" ));
3509+ defineVar (sym , Rf_mkPROMISE (expr , evalEnv ), env );
3510+ }
3511+
3512+ void R_MakeForcedBinding (SEXP sym , SEXP expr , SEXP value , SEXP env ) {
3513+ if (TYPEOF (sym ) != SYMSXP )
3514+ error (_ ("not a symbol" ));
3515+ if (TYPEOF (env ) != ENVSXP )
3516+ error (_ ("not an environment" ));
3517+ defineVar (sym , R_mkEVPROMISE (expr , value ), env );
3518+ }
3519+
3520+ void R_MakeMissingBinding (SEXP sym , SEXP env ) {
3521+ if (TYPEOF (sym ) != SYMSXP )
3522+ error (_ ("not a symbol" ));
3523+ if (TYPEOF (env ) != ENVSXP )
3524+ error (_ ("not an environment" ));
3525+ defineVar (sym , R_MissingArg , env );
3526+ }
3527+
34603528void R_MakeActiveBinding (SEXP sym , SEXP fun , SEXP env )
34613529{
34623530 if (TYPEOF (sym ) != SYMSXP )
@@ -3562,6 +3630,60 @@ attribute_hidden Rboolean R_HasFancyBindings(SEXP rho)
35623630 }
35633631}
35643632
3633+ /* Equivalent to `substitute()`, but only supports promises */
3634+ SEXP R_DelayedBindingExpression (SEXP sym , SEXP env ) {
3635+ if (TYPEOF (sym ) != SYMSXP )
3636+ error (_ ("not a symbol" ));
3637+ if (TYPEOF (env ) != ENVSXP )
3638+ error (_ ("not an environment" ));
3639+
3640+ SEXP value = Rf_findVarInFrame3 (env , sym , FALSE);
3641+
3642+ if (TYPEOF (value ) != PROMSXP )
3643+ error (_ ("not a promise" ));
3644+
3645+ if (PROMISE_IS_EVALUATED (value ))
3646+ error (_ ("not a delayed promise" ));
3647+
3648+ /* This has special handling for bytecode, unlike `PREXPR()` */
3649+ return R_PromiseExpr (value );
3650+ }
3651+
3652+ SEXP R_DelayedBindingEnvironment (SEXP sym , SEXP env ) {
3653+ if (TYPEOF (sym ) != SYMSXP )
3654+ error (_ ("not a symbol" ));
3655+ if (TYPEOF (env ) != ENVSXP )
3656+ error (_ ("not an environment" ));
3657+
3658+ SEXP value = Rf_findVarInFrame3 (env , sym , FALSE);
3659+
3660+ if (TYPEOF (value ) != PROMSXP )
3661+ error (_ ("not a promise" ));
3662+
3663+ if (PROMISE_IS_EVALUATED (value ))
3664+ error (_ ("not a delayed promise" ));
3665+
3666+ return PRENV (value );
3667+ }
3668+
3669+ SEXP R_ForcedBindingExpression (SEXP sym , SEXP env ) {
3670+ if (TYPEOF (sym ) != SYMSXP )
3671+ error (_ ("not a symbol" ));
3672+ if (TYPEOF (env ) != ENVSXP )
3673+ error (_ ("not an environment" ));
3674+
3675+ SEXP value = Rf_findVarInFrame3 (env , sym , FALSE);
3676+
3677+ if (TYPEOF (value ) != PROMSXP )
3678+ error (_ ("not a promise" ));
3679+
3680+ if (!PROMISE_IS_EVALUATED (value ))
3681+ error (_ ("not a forced promise" ));
3682+
3683+ /* This has special handling for bytecode, unlike `PREXPR()` */
3684+ return R_PromiseExpr (value );
3685+ }
3686+
35653687SEXP R_ActiveBindingFunction (SEXP sym , SEXP env )
35663688{
35673689 if (TYPEOF (sym ) != SYMSXP )
@@ -4633,4 +4755,3 @@ attribute_hidden void findFunctionForBody(SEXP body) {
46334755 }
46344756 }
46354757}
4636-
0 commit comments