Commit d10576e3 authored by Radford Neal's avatar Radford Neal

reorg of var result, new VARIANT_PASS_ON macro

parent 4e01554f
Modifications to the variant result mechanism.
Defines a VARIANT_PASS_ON macro to isolate the part of
a variant that should be passed on by "{", "if", etc.
......@@ -483,9 +483,14 @@ typedef struct {
NONVEC_SXPINFO(x).var2 = (v2); \
} while (0)
/* Symbols for eval variants. The symbols with values less than 16 may be
OR'd with zero or more symbols with values 16, 32, 64, or 128. The result
will fit in one unsigned char.
/* Symbols for eval variants. Variant 0 indicates the standard result.
Variants with numbers from 0x01, 0x02, ..., 0x0f are passed on for
the evaluaton of arguments of "{", "(", "if" (except conditon), etc.
Variants with numbers 0x10, 0x20, ..., 0xf0 are not passed on. There
are no variants of the form 0xNM with N!=0 and M!=0. These variant
numbers may be OR'd with flags 0x100, 0x200, 0x400, 0x800, ... in
order to indicate additional aspects of variation. Such additional
flags up to 0x8000 are passed on, but flags from 0x10000 up are not.
Return of a variant result is indicated either by the nature of the
returned value, or by R_variant_result being set to a non-zero value
......@@ -497,10 +502,6 @@ typedef struct {
return will not appear to have a variant result (unless that is what
should happen).
Variants that set R_variant_return may not make sense for arguments of
fast primitives (ie, for ARG1VAR or ARG2VAR), since evalv does not
record R_variant_result for use by the primitive.
A caller of evalv need not set R_variant_result to zero before a call,
since that is done inside evalv.
......@@ -509,42 +510,61 @@ typedef struct {
However, when VARIANT_NULL is combined with VARIANT_DIRECT_RETURN, a
direct value for "return" will not be replaced by R_NilValue. */
#define VARIANT_SEQ 2 /* May return a sequence spec, rather than a vector.
Sets R_variant_result to 1 if so. */
/* Macros isolating part of a variant. */
#define VARIANT_PASS_ON(v) ((v)&0xff0f) /* Isolate part of variant to be passed
on by "{", "(", "if", etc. */
#define VARIANT_KIND(v) ((v)&0xff) /* Isolate low 8 bits to compare with symbols
defined below (excludes flag bits) */
/* Variant kinds that are passed on. */
#define VARIANT_SEQ 0x01 /* May return a sequence spec, rather than a vector.
Sets R_variant_result to 1 if so. */
#define VARIANT_AND 0x02 /* May return AND of a logical vec rather than vec.
Does not set R_variant_result. */
#define VARIANT_OR 0x03 /* May return OR of a logical vec rather than vec.
Does not set R_variant_result. */
#define VARIANT_SUM 0x04 /* May return sum of vec elements rather than vec.
Does not set R_variant_result. */
#define VARIANT_TRANS 0x05 /* May return the transpose of the result.
Sets R_variant_result to 1 if so. */
#define VARIANT_ONE_NAMED 0x06 /* When the result is a vector list with exactly
one named element, may return a one-element
pairlist with this element (used for $).
Does not set R_variant_result. */
#define VARIANT_AND 3 /* May return AND of a logical vec rather than vec.
Does not set R_variant_result. */
/* Variant kinds that are not passed on. */
#define VARIANT_OR 4 /* May return OR of a logical vec rather than vec.
Does not set R_variant_result. */
/* none so far */
#define VARIANT_SUM 5 /* May return sum of vec elements rather than vec.
Does not set R_variant_result. */
/* Variant flags that are passed on. */
#define VARIANT_TRANS 6 /* May return the transpose of the result.
Sets R_variant_result to 1 if so. */
#define VARIANT_PENDING_OK 0x100 /* Computation may be deferred pending
completion of a task (in a helper or the
master). Does not set R_variant_result. */
#define VARIANT_ONE_NAMED 7 /* When the result is a vector list with exactly
one named element, may return a one-element
pairlist with this element (used for $).
Does not set R_variant_result. */
#define VARIANT_NULL 0x200 /* May just return R_NilValue, while doing side
effects, unless the value is for a direct return.
Should usually be OR'd with VARIANT_PENDING_OK.
Does not set R_variant_result. */
#define VARIANT_KIND(v) ((v)&15) /* Isolate low 4 bits to compare with symbols
defined above */
#define VARIANT_DIRECT_RETURN 0x400 /* A "return" statement may simply return
the return value, without a non-local
jump. Usually OR with VARIANT_PENDING_OK.
ORs R_variant_result with VARIANT_RTN. */
#define VARIANT_PENDING_OK 16 /* Computation may be deferred pending completion
of a task (in a helper or the master).
Does not set R_variant_result. */
/* Variant flags that are not passed on. */
#define VARIANT_DIRECT_RETURN 32 /* A "return" statement may simply return the
return value, without a non-local jump.
Should be OR'd with VARIANT_PENDING_OK.
ORs R_variant_result with VARIANT_RTN */
/* none so far */
#define VARIANT_NULL 64 /* May just return R_NilValue, while doing side
effects, unless the value is for a direct return.
Should usually be OR'd with VARIANT_PENDING_OK.
Does not set R_variant_result. */
/* Flags in R_variant_result. */
#define VARIANT_RTN_FLAG 0x80000000 /* Bit flagging a direct return */
......
......@@ -1417,7 +1417,7 @@ static SEXP do_if (SEXP call, SEXP op, SEXP args, SEXP rho, int variant)
return R_NilValue;
}
return evalv (Stmt, rho, variant);
return evalv (Stmt, rho, VARIANT_PASS_ON(variant));
}
......@@ -1668,7 +1668,7 @@ static SEXP do_paren (SEXP call, SEXP op, SEXP args, SEXP rho, int variant)
if (args == R_NilValue || CDR(args) != R_NilValue)
checkArity(op, args);
return evalv (CAR(args), rho, variant);
return evalv (CAR(args), rho, VARIANT_PASS_ON(variant));
}
/* Curly brackets. Passes on the eval variant to the last expression. For
......@@ -1684,6 +1684,7 @@ static SEXP do_begin (SEXP call, SEXP op, SEXP args, SEXP rho, int variant)
SEXP arg, s, srcrefs = getBlockSrcrefs(call);
int vrnt = VARIANT_NULL | VARIANT_PENDING_OK;
variant = VARIANT_PASS_ON(variant);
if (variant & VARIANT_DIRECT_RETURN)
vrnt |= variant;
......@@ -1720,7 +1721,7 @@ static SEXP do_return(SEXP call, SEXP op, SEXP args, SEXP rho, int variant)
v = R_NilValue;
else if (CDR(args) == R_NilValue) /* one argument */
v = evalv (CAR(args), rho, ! (variant & VARIANT_DIRECT_RETURN) ? 0
: variant & ~ VARIANT_NULL);
: VARIANT_PASS_ON(variant) & ~ VARIANT_NULL);
else
errorcall(call, _("multi-argument returns are not permitted"));
......@@ -2421,7 +2422,7 @@ static SEXP do_eval (SEXP call, SEXP op, SEXP args, SEXP rho, int variant)
if (TYPEOF(expr) == LANGSXP || TYPEOF(expr) == SYMSXP || isByteCode(expr)) {
begincontext(&cntxt, CTXT_RETURN, call, env, rho, args, op);
if (!SETJMP(cntxt.cjmpbuf))
expr = evalv (expr, env, variant);
expr = evalv (expr, env, VARIANT_PASS_ON(variant));
else {
expr = R_ReturnedValue;
if (expr == R_RestartToken) {
......@@ -2443,7 +2444,8 @@ static SEXP do_eval (SEXP call, SEXP op, SEXP args, SEXP rho, int variant)
for (i = 0 ; i < n ; i++) {
R_Srcref = getSrcref(srcrefs, i);
tmp = evalv (VECTOR_ELT(expr, i), env,
i==n-1 ? variant : VARIANT_NULL | VARIANT_PENDING_OK);
i==n-1 ? VARIANT_PASS_ON(variant)
: VARIANT_NULL | VARIANT_PENDING_OK);
}
}
else {
......@@ -2459,7 +2461,7 @@ static SEXP do_eval (SEXP call, SEXP op, SEXP args, SEXP rho, int variant)
expr = tmp;
}
else if( TYPEOF(expr) == PROMSXP ) {
expr = evalv (expr, rho, variant);
expr = forcePromise(expr);
}
else
; /* expr is returned unchanged */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment