Changeset: 86acf33216e8 for MonetDB
URL: http://dev.monetdb.org/hg/MonetDB?cmd=changeset;node=86acf33216e8
Modified Files:
        monetdb5/modules/mal/Tests/rapi00.mal
        monetdb5/modules/mal/rapi.c
        monetdb5/modules/mal/rapi.h
Branch: RIntegration
Log Message:

Changed environment and user code handling


diffs (truncated from 388 to 300 lines):

diff --git a/monetdb5/modules/mal/Tests/rapi00.mal 
b/monetdb5/modules/mal/Tests/rapi00.mal
--- a/monetdb5/modules/mal/Tests/rapi00.mal
+++ b/monetdb5/modules/mal/Tests/rapi00.mal
@@ -1,4 +1,4 @@
-# Hannes Muhleissen example
+# Hannes Muehleisen example
 b:= bat.new(:oid,:int);
 bat.append(b,1804289383);
 bat.append(b,846930886);
@@ -13,6 +13,6 @@ bat.append(b,1189641421);
 
 io.print(b);
 
-r:bat[:oid,:dbl] := rapi.eval("ret0 <- Re(fft(arg2));",b);
+r:bat[:oid,:dbl] := rapi.eval("someval <- Re(fft(arg1)); print(someval); 
return(someval);",b);
 
 io.print(r);
diff --git a/monetdb5/modules/mal/rapi.c b/monetdb5/modules/mal/rapi.c
--- a/monetdb5/modules/mal/rapi.c
+++ b/monetdb5/modules/mal/rapi.c
@@ -18,7 +18,7 @@
  */
 
 /*
- * H. Muhleissen, M. Kersten
+ * H. Muehleisen, M. Kersten
  * The R interface
  */
 #include "monetdb_config.h"
@@ -29,40 +29,38 @@ static MT_Lock rapiLock;
 
 char* R_HomeDir(void) {
        // FIXME this won't work in general
-    return "/usr/lib64/R";
+       return "/usr/lib64/R";
 }
 
 void writeConsole(const char * buf, int buflen) {
        (void) buflen;
-       THRprintf(GDKout, "%s",buf);
+       THRprintf(GDKout, "%s", buf);
 }
 void writeConsoleEx(const char * buf, int buflen, int foo) {
        (void) buflen;
        (void) foo;
-       THRprintf(GDKout, "%s",buf);
+       THRprintf(GDKout, "%s", buf);
 }
 
-str
-RAPIprelude(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){
-    char *rargv[] = { "whatever", "--quiet", "--no-save", "--vanilla" };
+str RAPIprelude(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
+       char *rargv[] = { "whatever", "--quiet", "--no-save", "--vanilla" };
 
        (void) cntxt;
        (void) mb;
        (void) stk;
        (void) pci;
 
-       MT_lock_init( &rapiLock,"rapi_lock");
-    Rf_initEmbeddedR(4, rargv);
+       MT_lock_init(&rapiLock, "rapi_lock");
+       Rf_initEmbeddedR(4, rargv);
        // these globals are indicative for non-thread safe R settings.
-    ptr_R_WriteConsole =  writeConsole;
-    ptr_R_WriteConsoleEx = writeConsoleEx;
-    R_Outputfile = NULL;
-    R_Consolefile = NULL;
+       ptr_R_WriteConsole = writeConsole;
+       ptr_R_WriteConsoleEx = writeConsoleEx;
+       R_Outputfile = NULL;
+       R_Consolefile = NULL;
        return MAL_SUCCEED;
 }
 
-str
-RAPIpostlude(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){
+str RAPIpostlude(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
        (void) cntxt;
        (void) mb;
        (void) stk;
@@ -71,164 +69,211 @@ RAPIpostlude(Client cntxt, MalBlkPtr mb,
        return MAL_SUCCEED;
 }
 
-str
-RAPIeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci){
-       str exprStr = *(str*) getArgReference(stk,pci,pci->retc);
-    SEXP x;
-    ParseStatus status;
+str RAPIeval(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr pci) {
+       str exprStr = *(str*) getArgReference(stk, pci, pci->retc);
+       SEXP x, env,retval;
+       ParseStatus status;
        int i;
-       char buf[64]={"rapi"};
+       char buf[64] = "rapi";
+       char argnames[1000] = "";
+       char* rcall;
        str *args;
-       char *msg = createException(MAL,"rapi.eval","NYI");
+       int evalErr;
+       char *msg = createException(MAL, "rapi.eval", "NYI");
        BAT *b;
-    char *rargv[] = { "whatever", "--quiet", "--no-save", "--vanilla" };
-    Rf_initEmbeddedR(4, rargv);
-
+       char *rargv[] = { "whatever", "--quiet", "--no-save", "--vanilla" };
+       Rf_initEmbeddedR(4, rargv);
        (void) mb;
 
+       rcall = malloc(strlen(exprStr) + sizeof(argnames) + 100);
+       if (rcall==NULL) {
+               throw(MAL, "rapi.eval", MAL_MALLOC_FAIL);
+       }
+
        args = (str*) GDKzalloc(sizeof(str) * pci->argc);
-       if ( args == NULL)
-               throw(MAL,"rapi.eval", MAL_MALLOC_FAIL);
-       
-       MT_lock_set(&rapiLock,"rapi.evaluate");
+       if (args == NULL)
+               throw(MAL, "rapi.eval", MAL_MALLOC_FAIL);
+
+       MT_lock_set(&rapiLock, "rapi.evaluate");
        // check R expression for errors
 
 #ifdef _RAPI_DEBUG_
-    mnstr_printf(cntxt->fdout,"#Running R expression %s\n",exprStr);
+       mnstr_printf(cntxt->fdout, "#Running R expression %s\n", exprStr);
 #else
        (void) cntxt;
 #endif
 
+       /* create new, empty environment */
+       /* ugly call required since Rf_NewEnvironment is not in the public 
headers*/
+       env = eval(lang1(install("new.env")),R_GlobalEnv);
+
        // install the MAL variables into the R environment
-       for( i = pci->retc+1; i< pci->argc; i++){
-               SEXP varname;
-               SEXP varvalue;
+       for (i = pci->retc + 1; i < pci->argc; i++) {
+               SEXP varname = R_NilValue;
+               SEXP varvalue = R_NilValue;
 
-               sprintf(buf,"arg%d", i);
+               sprintf(buf, "arg%d", i - 1);
                args[i] = GDKstrdup(buf);
-               varname = Rf_install( args[i]);
+               varname = Rf_install(args[i]);
                // check for BAT or scalar first !!
-               if ( isaBatType(getArgType(mb,pci,i))){
+               if (isaBatType(getArgType(mb,pci,i))) {
                        // hand over a BAT into a vector
-                       b = BATdescriptor(*(int*) getArgReference(stk,pci,i));
-                       if ( b== NULL)
-                               throw(MAL,"rapi.eval", MAL_MALLOC_FAIL);
+                       b = BATdescriptor(*(int*) getArgReference(stk, pci, i));
+                       if (b == NULL)
+                               throw(MAL, "rapi.eval", MAL_MALLOC_FAIL);
 
                        // seems expensive to copy all values 
-                       switch(ATOMstorage(getTailType(getArgType(mb,pci,i)))){
+                       switch (ATOMstorage(getTailType(getArgType(mb,pci,i)))) 
{
                        case TYPE_bte:
                                varvalue = NEW_LOGICAL(BATcount(b));
-                               memcpy((char*)(LOGICAL_POINTER(varvalue)), 
(char*) Tloc(b,BUNfirst(b)), BATcount(b) * sizeof(bte));
+                               memcpy((char*) (LOGICAL_POINTER(varvalue)),
+                                               (char*) Tloc(b, BUNfirst(b)),
+                                               BATcount(b) * sizeof(bte));
                                break;
                        case TYPE_int:
                                varvalue = NEW_INTEGER(BATcount(b));
-                               memcpy((char*)(INTEGER_POINTER(varvalue)), 
(char*) Tloc(b,BUNfirst(b)), BATcount(b) * sizeof(int));
+                               memcpy((char*) (INTEGER_POINTER(varvalue)),
+                                               (char*) Tloc(b, BUNfirst(b)),
+                                               BATcount(b) * sizeof(int));
                                break;
                        case TYPE_dbl:
                                varvalue = NEW_NUMERIC(BATcount(b));
-                               memcpy((char*)(NUMERIC_POINTER(varvalue)), 
(char*) Tloc(b,BUNfirst(b)), BATcount(b) * sizeof(dbl));
+                               memcpy((char*) (NUMERIC_POINTER(varvalue)),
+                                               (char*) Tloc(b, BUNfirst(b)),
+                                               BATcount(b) * sizeof(dbl));
                                break;
                        case TYPE_str:
                                //varvalue = NEW_CHARACTER( strlen(*(str*) 
getArgReference(stk,pci,i)));
                                break;
                        default:
                                // no clue what type to consider
-                               msg = createException(MAL,"rapi.eval","unknown 
argument type");
+                               msg = createException(MAL, "rapi.eval",
+                                               "unknown argument type");
                                goto wrapup;
                        }
                        BBPreleaseref(b->batCacheid);
-               } else 
-               switch(ATOMstorage(getTailType(getArgType(mb,pci,i)))){
-               case TYPE_bte:
-                       varvalue = NEW_LOGICAL(1);
-                       LOGICAL_POINTER(varvalue)[0] = *(int*) 
getArgReference(stk,pci,i);
-                       break;
-               case TYPE_int:
-                       varvalue = NEW_INTEGER(1);
-                       INTEGER_POINTER(varvalue)[0] = *(int*) 
getArgReference(stk,pci,i);
-                       break;
-               case TYPE_dbl:
-                       varvalue = NEW_NUMERIC(1);
-                       NUMERIC_POINTER(varvalue)[0]= *(flt*) 
getArgReference(stk,pci,i);
-                       break;
-               case TYPE_str:
-                       //varvalue = NEW_CHARACTER( strlen(*(str*) 
getArgReference(stk,pci,i)));
-                       break;
-               default:
-                       // no clue what type to consider
-                       msg = createException(MAL,"rapi.eval","unknown argument 
type");
-                       goto wrapup;
-               }
+               } else
+                       switch (ATOMstorage(getTailType(getArgType(mb,pci,i)))) 
{
+                       case TYPE_bte:
+                               varvalue = NEW_LOGICAL(1);
+                               LOGICAL_POINTER(varvalue)[0] = *(int*) 
getArgReference(stk, pci,
+                                               i);
+                               break;
+                       case TYPE_int:
+                               varvalue = NEW_INTEGER(1);
+                               INTEGER_POINTER(varvalue)[0] = *(int*) 
getArgReference(stk, pci,
+                                               i);
+                               break;
+                       case TYPE_dbl:
+                               varvalue = NEW_NUMERIC(1);
+                               NUMERIC_POINTER(varvalue)[0] = *(flt*) 
getArgReference(stk, pci,
+                                               i);
+                               break;
+                       case TYPE_str:
+                               //varvalue = NEW_CHARACTER( strlen(*(str*) 
getArgReference(stk,pci,i)));
+                               break;
+                       default:
+                               // no clue what type to consider
+                               msg = createException(MAL, "rapi.eval",
+                                               "unknown argument type");
+                               goto wrapup;
+                       }
                // TODO: it's probably a good idea to have a different, new 
environment here
                // TODO: also, let's use an anonymous function call to run the 
user code
                // install vector into R environment
-               Rf_defineVar(varname,varvalue, R_GlobalEnv);
+               Rf_defineVar(varname, varvalue, env);
        }
-       
-    x = R_ParseVector(mkString(exprStr), INT_MAX, &status, R_NilValue);
-    if (status != PARSE_OK){
-        msg= createException(MAL,"rapi.eval","%s", exprStr);
+
+       /* we are going to evaluate the user function within a anonymous 
function call:
+        * ret <- (function(arg1){return(arg1*2)})(42)
+        * the user code is put inside the {}, this keeps our environment clean 
(TM) and gives
+        * a clear path for return values, namely using the builtin return() 
function
+        * this is also compatible with PL/R
+        */
+       for (i = pci->retc + 1; i < pci->argc; i++) {
+               sprintf(buf, "arg%d", i - 1);
+               strcat(argnames,buf);
+               if (i < pci->argc-1) {
+                       strcat(argnames,",");
+               }
+       }
+       sprintf(rcall,"ret <- 
function(%s){%s}(%s)\n",argnames,exprStr,argnames);
+
+       x = R_ParseVector(mkString(rcall), INT_MAX, &status, R_NilValue);
+       if (status != PARSE_OK) {
+               msg = createException(MAL, "rapi.eval", "%s", exprStr);
                goto wrapup;
        }
 
-       // why this?
-    for (i = 0; i < LENGTH(x); i++) {
-        eval(VECTOR_ELT(x, i), R_GlobalEnv);
-    }
+       /* parsing creates a separate call for each statement, since our r code 
can consist of multiple statements, we need to evaluate each vector entry */
+       if (LENGTH(x) != 1) {
+               msg = createException(MAL, "rapi.eval", "%s", exprStr);
+                          goto wrapup;
+       }
+       retval = R_tryEval(VECTOR_ELT(x, i), env,&evalErr);
+       if (evalErr != FALSE) {
+               msg = createException(MAL, "rapi.eval", "%s", exprStr);
+          goto wrapup;
+       }
+
+       // ret should be a data frame with exactly as many columns as we need 
from retc
 
        // collect the return values
-       for( i=0; i< pci->retc; i++){
-               SEXP othervar;
-               sprintf(buf, "ret%d",i);
+       for (i = 0; i < pci->retc; i++) {
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list

Reply via email to