R-alpha: Source Fix

Ross Ihaka (ihaka@stat.auckland.ac.nz)
Tue, 26 Mar 1996 14:54:16 +1200


Date: Tue, 26 Mar 1996 14:54:16 +1200
From: Ross Ihaka <ihaka@stat.auckland.ac.nz>
Message-Id: <199603260254.OAA05293@stat.auckland.ac.nz>
To: R-testers@stat.math.ethz.ch
Subject: R-alpha: Source Fix

Ack!  Fix one thing break another (we made a change to support some
debugging code for Martin Maechler).

There is actually quite a deep problem here.  Namely, how eval should
work.  Consider:

	i <- expression(1 + 1)
	eval(i)

I think that we would all agree that eval(i) should produce 2.
But what about eval(i + 1)?  The traditional evaluation rule is

    (1)	Evaluate the operator		(here +)
    (2) Evaluate the arguments		(or promise to evaluate them)
    (3)	Apply the operator to the arguments.

In any consistent universe, this algorithm produces 3.  In S, an error
message is generated.

	> i <- expression(1+1)
	> eval(i)
	[1] 2
	> eval(i+1)
	Error in i + 1: Non-numeric first operand
	Dumped

It seems that "i" on its own can be evaluated, but in an expression it
can't.  This is rather curious behavior and seems to happen because
names are treated as a special case by "eval".  I hate special cases,
but I will hold my nose and do it this way.

To fix the problem change the function do_eval at the bottom of the
file R/src/main/eval.c to the following:


SEXP do_eval(SEXP call, SEXP op, SEXP args, SEXP rho)
{
        SEXP tmp, expr, env;
	checkArity(op, args);

	expr = CAR(args);
	env=CADR(args);

	switch(TYPEOF(env)) {
	case NILSXP:
		PROTECT(env = sysparent(1));
		break;
	case LISTSXP:
	case FRAMESXP:
		PROTECT(env = allocSExp(ENVSXP));
		FRAME(env) = duplicate(env);
		ENCLOS(env) = R_GlobalEnv;
		break;
	case ENVSXP:
		PROTECT(env); /* so we can unprotect 2 at the end */
		break;
	default:
		errorcall(call, "invalid second argument\n");
	}

	if(isSymbol(expr)) {
		PROTECT(expr);
		expr = eval(expr, sysparent(1));
		UNPROTECT(1);
		PROTECT(expr);
		expr = eval(expr, env);
		UNPROTECT(1);
	}
	else if(isLanguage(expr)) {
		PROTECT(expr);
		expr = eval(expr, env);
		UNPROTECT(1);
	}
	UNPROTECT(1);
	return expr;
}
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
r-testers mailing list -- To (un)subscribe, send
subscribe	or	unsubscribe
(in the "body", not the subject !)  To: r-testers-request@stat.math.ethz.ch
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-