Rob Anderson
2011-Nov-07 10:24 UTC
[Rd] Accessing ENVSXP and CLOSXP while processing parsed R code
Hello Guys, Following up my earlier mail where I am trying to write an alternative front-end for R, I had a question about accessing the closures and environments in R code. Here's the function taken and modified a little from "*Lexical Scope and Statistical Computing*" ====================================================================f<-function(){ Rmlfun<-function(x){ sumx <- sum(x) n <- length(x) function(mu) n*log(mu)-mu*sumx } efun <-Rmlfun(1:10) y1 <- efun(3) print(y1) efun2 <- Rmlfun(20:30) y2 <- efun2(3) print(y2) } ==================================================================== Now assignment efun <-Rmlfun(1:10) creates a closure where *function(mu) n*log(mu)-mu*sumx *is returned and *sumx* and *n *are added to the existing environment. I can parse the code using *PROTECT(e R_ParseVector(tmp,1,&status,R_NilValue));* where tmp is the buffer containing the same source. I can walk the resultant parser output and build and alternative Abstract syntax tree(AST). I would like to include the information about closure/environments in my AST so that I can possibly do some optimizations. My question is, how can I get hold of this information? One thing I noticed while 'walking' through the parser output, I never encounter a CLOSXP (which I check using TYPEOF()) , even though in the above code, closure is created. Is it the case that this information is meant just for the internal "eval*" function and not exposed application writers? Thanks, Rob [[alternative HTML version deleted]]
Duncan Murdoch
2011-Nov-07 11:49 UTC
[Rd] Accessing ENVSXP and CLOSXP while processing parsed R code
On 11-11-07 5:24 AM, Rob Anderson wrote:> Hello Guys, > > Following up my earlier mail where I am trying to write an alternative > front-end for R, I had a question about accessing the closures and > environments in R code. > > Here's the function taken and modified a little from "*Lexical Scope and > Statistical Computing*" > > ====================================================================> f<-function(){ > Rmlfun<-function(x){ > sumx<- sum(x) > n<- length(x) > function(mu) > n*log(mu)-mu*sumx > } > efun<-Rmlfun(1:10) > y1<- efun(3) > print(y1) > efun2<- Rmlfun(20:30) > y2<- efun2(3) > print(y2) > } > ====================================================================> > Now assignment efun<-Rmlfun(1:10) creates a closure where > *function(mu) n*log(mu)-mu*sumx *is returned and *sumx* and *n *are added > to the existing environment.That's not correct. When you call Rmlfun, an evaluation frame (environment) is created. It contains the argument x. Then sumx and n are added to it. Then the anonymous closure is created, with body n*log(mu)-mu*sumx, and the closure's environment is the evaluation frame from the call to Rmlfun.> > I can parse the code using *PROTECT(e > R_ParseVector(tmp,1,&status,R_NilValue));* where tmp is the buffer > containing the same source. I can walk the resultant parser output and > build and alternative Abstract syntax tree(AST). > > I would like to include the information about closure/environments in my > AST so that I can possibly do some optimizations.It's not there, except potentially. When you call the function "function" to create the closure, that's when the closure is created. That doesn't happen at parse time. Rmlfun is created when you evaluate f() and then the anonymous function is created when you call Rmlfun() within it.> > My question is, how can I get hold of this information? > > One thing I noticed while 'walking' through the parser output, I never > encounter a CLOSXP (which I check using TYPEOF()) , even though in the > above code, closure is created. Is it the case that this information is > meant just for the internal "eval*" function and not exposed application > writers?No, there's nothing hidden, it just didn't exist at the time you were looking for it. Duncan Murdoch