@@ -1425,6 +1425,11 @@ static int ddVal(SEXP symbol)
14251425
14261426#define length_DOTS (_v_ ) (TYPEOF(_v_) == DOTSXP ? length(_v_) : 0)
14271427
1428+ Rboolean R_DotsExist (SEXP env )
1429+ {
1430+ return R_findVar (R_DotsSymbol , env ) != R_UnboundValue ;
1431+ }
1432+
14281433SEXP ddfind (int i , SEXP rho )
14291434{
14301435 if (i <= 0 )
@@ -1453,6 +1458,11 @@ SEXP ddfindVar(SEXP symbol, SEXP rho)
14531458 return ddfind (i , rho );
14541459}
14551460
1461+ SEXP R_DotsElt (int i , SEXP env )
1462+ {
1463+ return eval (ddfind (i , env ), env );
1464+ }
1465+
14561466attribute_hidden SEXP do_dotsElt (SEXP call , SEXP op , SEXP args , SEXP env )
14571467{
14581468 checkArity (op , args );
@@ -1465,23 +1475,26 @@ attribute_hidden SEXP do_dotsElt(SEXP call, SEXP op, SEXP args, SEXP env)
14651475 return eval (ddfind (i , env ), env );
14661476}
14671477
1468- attribute_hidden SEXP do_dotsLength ( SEXP call , SEXP op , SEXP args , SEXP env )
1478+ int R_DotsLength ( SEXP env )
14691479{
1470- checkArity (op , args );
14711480 SEXP vl = R_findVar (R_DotsSymbol , env );
14721481 if (vl == R_UnboundValue )
1473- error (_ ("incorrect context: the current call has no '...' to look in" ));
1482+ error (_ ("incorrect context: the current call has no '...' to look in" ));
14741483 // else
1475- return ScalarInteger ( length_DOTS (vl ) );
1484+ return length_DOTS (vl );
14761485}
14771486
1478- attribute_hidden SEXP do_dotsNames (SEXP call , SEXP op , SEXP args , SEXP env )
1487+ attribute_hidden SEXP do_dotsLength (SEXP call , SEXP op , SEXP args , SEXP env )
14791488{
14801489 checkArity (op , args );
1490+ return ScalarInteger (R_DotsLength (env ));
1491+ }
1492+
1493+ SEXP R_DotsNames (SEXP env ) {
14811494 SEXP vl = R_findVar (R_DotsSymbol , env );
14821495 PROTECT (vl );
14831496 if (vl == R_UnboundValue )
1484- error (_ ("incorrect context: the current call has no '...' to look in" ));
1497+ error (_ ("incorrect context: the current call has no '...' to look in" ));
14851498 // else
14861499 SEXP out ;
14871500 int n = length_DOTS (vl );
@@ -1504,6 +1517,63 @@ attribute_hidden SEXP do_dotsNames(SEXP call, SEXP op, SEXP args, SEXP env)
15041517 return out ;
15051518}
15061519
1520+ attribute_hidden SEXP do_dotsNames (SEXP call , SEXP op , SEXP args , SEXP env )
1521+ {
1522+ checkArity (op , args );
1523+ return R_DotsNames (env );
1524+ }
1525+
1526+ // Dot helpers
1527+ // For all helpers:
1528+ // - If dots don't exist, should error, as you should use `R_DotsExist()` first
1529+ // - OOB indexing should error, as you should use `R_DotsLength()` first
1530+
1531+ R_DotType R_GetDotType (int i , SEXP env )
1532+ {
1533+ SEXP value = ddfind (i , env );
1534+
1535+ if (value == R_MissingArg )
1536+ return R_DotTypeMissing ;
1537+
1538+ if (TYPEOF (value ) == PROMSXP ) {
1539+ if (PROMISE_IS_EVALUATED (value ))
1540+ return R_DotTypeForced ;
1541+ else
1542+ return R_DotTypeDelayed ;
1543+ }
1544+
1545+ return R_DotTypeValue ;
1546+ }
1547+
1548+ // For `R_DotTypeDelayed`
1549+ SEXP R_DotDelayedExpression (int i , SEXP env )
1550+ {
1551+ SEXP value = ddfind (i , env );
1552+ if (TYPEOF (value ) != PROMSXP || PROMISE_IS_EVALUATED (value ))
1553+ error (_ ("not a delayed promise" ));
1554+
1555+ return R_PromiseExpr (value );
1556+ }
1557+
1558+ SEXP R_DotDelayedEnvironment (int i , SEXP env )
1559+ {
1560+ SEXP value = ddfind (i , env );
1561+ if (TYPEOF (value ) != PROMSXP || PROMISE_IS_EVALUATED (value ))
1562+ error (_ ("not a delayed promise" ));
1563+
1564+ return PRENV (value );
1565+ }
1566+
1567+ // For `R_DotTypeForced`
1568+ SEXP R_DotForcedExpression (int i , SEXP env )
1569+ {
1570+ SEXP value = ddfind (i , env );
1571+ if (TYPEOF (value ) != PROMSXP || !PROMISE_IS_EVALUATED (value ))
1572+ error (_ ("not a forced promise" ));
1573+
1574+ return R_PromiseExpr (value );
1575+ }
1576+
15071577#undef length_DOTS
15081578
15091579/*----------------------------------------------------------------------
0 commit comments