Skip to content

Commit 8f30a31

Browse files
committed
Implement dots interface
1 parent 3006cdb commit 8f30a31

File tree

2 files changed

+92
-6
lines changed

2 files changed

+92
-6
lines changed

src/include/Rinternals.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,22 @@ Rboolean R_BindingIsActive(SEXP sym, SEXP env); // envir.c
708708
SEXP R_ActiveBindingFunction(SEXP sym, SEXP env);
709709
Rboolean R_HasFancyBindings(SEXP rho); // envir.c
710710

711+
/* Dots interface */
712+
typedef enum {
713+
R_DotTypeValue = 0,
714+
R_DotTypeMissing = 1,
715+
R_DotTypeDelayed = 2,
716+
R_DotTypeForced = 3
717+
} R_DotType;
718+
719+
Rboolean R_DotsExist(SEXP env); // envir.c
720+
int R_DotsLength(SEXP env);
721+
SEXP R_DotsNames(SEXP env);
722+
SEXP R_DotsElt(int i, SEXP env);
723+
724+
SEXP R_DotDelayedExpression(int i, SEXP env); // envir.c
725+
SEXP R_DotDelayedEnvironment(int i, SEXP env);
726+
SEXP R_DotForcedExpression(int i, SEXP env);
711727

712728
/* ../main/errors.c : */
713729
/* needed for R_load/savehistory handling in front ends */

src/main/envir.c

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
14281433
SEXP 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+
14561466
attribute_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

Comments
 (0)