From ebo at sandien.com  Thu Sep  4 09:58:03 2008
From: ebo at sandien.com (EBo)
Date: Thu, 4 Sep 2008 01:58:03 MDT
Subject: [Rd] suggestion of new API function for embedded programming.
In-Reply-To: <twig.1220458335.76209@swcp.com>
References: <twig.1220449912.10283@swcp.com>,
	<twig.1220449912.10283@swcp.com> <twig.1220454941.83227@swcp.com>,
	<twig.1220454941.83227@swcp.com>,
	<alpine.LFD.1.10.0809031106210.28931@nokomis.stat.uiowa.edu>
Message-ID: <twig.1220515083.62751@swcp.com>


I stumbled onto a near trivial solution... here is some example code:

  EBo --

#include <Rembedded.h>
#include <Rdefines.h>
#include <Rinternals.h>
#include <R_ext/Parse.h>


SEXP
LineEval (char *cmd)
{
    SEXP ans;
    int error;

    ans = R_tryLineEval (cmd, R_GlobalEnv, &error);

    if (error)
    {
        fprintf (stderr, "Error evaluating line \"%s\"\n", cmd);
        return R_NilValue;
    }

    return ans;
}


SEXP
R_tryLineEval (char *cmd, SEXP rho, int *error)
{
    SEXP cmdSexp, cmdexpr, ans = R_NilValue;
    int i;
    ParseStatus status;

    *error = 0;

    // parse the R epression
    PROTECT(cmdSexp = allocVector(STRSXP, 1));
    SET_STRING_ELT(cmdSexp, 0, mkChar(cmd));
    cmdexpr = PROTECT(R_ParseVector(cmdSexp, -1, &status, R_NilValue));
    if (status != PARSE_OK) {
        UNPROTECT(2);
        return R_NilValue;
    }
    // Loop is needed here as EXPSEXP will be of length > 1 
    for(i = 0; i < length(cmdexpr); i++)
    {
        ans = R_tryEval(VECTOR_ELT(cmdexpr, i), R_GlobalEnv, error);
        if (*error) {
            UNPROTECT(2);
            return R_NilValue;
        }
    }
    UNPROTECT(2);

    return ans;
}


int
main (int argc, char *argv[])
{
    char *cmd[] =
        {"t.test(x,conf.level=0.67)",
         "t.test(x,conf.level=0.67)$conf.int[2]",
         "xyz=c(9,8,7,6); xyz=median(x)",
         "print(x)",
         NULL
        };
    SEXP ans;
    int  i;

    char *args[] = {"bla", "--gui=none", "--silent", "--no-save"};
    Rf_initEmbeddedR (4, args);

    // set the variable "x" to the dataset.
    SEXP value;
    value = NEW_NUMERIC(11);
    for (i=10; 0<=i; i--)
        NUMERIC_DATA(value)[i] = i;
    PROTECT(value);
    setVar(install("x"), value, R_GlobalEnv);
 
    
    // spin through several R expressions and evaluate each.
    for (i=0; cmd[i]; i++)
    {
        ans = LineEval (cmd[i]);
        if (R_NilValue != ans)
        {
            printf ("cmd = \"%s\"\n", cmd[i]);
            if (IS_NUMERIC(ans))
                printf ("  ans is %f\n", REAL(ans)[0]);
            else 
                PrintValue(ans);
            printf ("#############\n\n");
        }
    }

    return 0;
}






EBo <ebo at sandien.com> said:

> Luke Tierney <luke at stat.uiowa.edu> said:
> 
> > On Wed, 3 Sep 2008, EBo wrote:
> > 
> > > Luke Tierney <luke at stat.uiowa.edu> said:
> > >
> > >> ...
> > >>> do something like the following:
> > >>>
> > >>>  R_Expr = R_Parse1Buffer(&R_ConsoleIob, 0, &status);
> > >>>  if (PARSE_OK==status) {
> > >>>    ...
> > >>>    value = eval(R_CurrentExpr, rho);
> > >>>    ...
> > >>>  }
> > >>
> > >> We definitely do NOT want this frozen into the public API.
> > >
> > > What is your objection with making something like this a part of the public
> > > API?  I understand that having to use the IOBuffer seems a bit much, but
I do
> > > not understand your concern.
> > 
> > We need the freedom to completely change these internals if doing so
> > proves useful.
> 
> Ah, that makes perfect sense.
> 
> Thanks,
> 
>   EBo --
> 



--



[Rd] suggestion of new API function for embedded programming.
EBo