Ejemplo n.º 1
0
  private static SEXP R_loadMethod(Context context, SEXP def, String fname, Environment ev) {

    /* since this is called every time a method is dispatched with a
    definition that has a class, it should be as efficient as
    possible => we build in knowledge of the standard
    MethodDefinition and MethodWithNext slots.  If these (+ the
    class slot) don't account for all the attributes, regular
    dispatch is done. */
    int found = 1; /* we "know" the class attribute is there */

    found++; // we also have our fake __S4_BIt for renjin

    PairList attrib = def.getAttributes().asPairList();
    for (PairList.Node s : attrib.nodes()) {
      SEXP t = s.getTag();
      if (t == R_target) {
        ev.setVariable(R_dot_target, s.getValue());
        found++;
      } else if (t == R_defined) {
        ev.setVariable(R_dot_defined, s.getValue());
        found++;
      } else if (t == R_nextMethod) {
        ev.setVariable(R_dot_nextMethod, s.getValue());
        found++;
      } else if (t == Symbols.SOURCE) {
        /* ignore */ found++;
      }
    }
    ev.setVariable(R_dot_Method, def);

    /* this shouldn't be needed but check the generic being
    "loadMethod", which would produce a recursive loop */
    if (fname.equals("loadMethod")) {
      return def;
    }
    if (found < attrib.length()) {
      FunctionCall call =
          FunctionCall.newCall(R_loadMethod_name, def, StringArrayVector.valueOf(fname), ev);
      return context.evaluate(call, ev);

      //      SEXP e, val;
      //      PROTECT(e = allocVector(LANGSXP, 4));
      //      SETCAR(e, R_loadMethod_name); val = CDR(e);
      //      SETCAR(val, def); val = CDR(val);
      //      SETCAR(val, fname); val = CDR(val);
      //      SETCAR(val, ev);
      //      val = eval(e, ev);
      //      return val;
    } else {
      return def;
    }
  }
Ejemplo n.º 2
0
  public static SEXP R_execMethod(Context context, Closure op, Environment rho) {

    /* create a new environment frame enclosed by the lexical
    environment of the method */
    Environment newrho = Environment.createChildEnvironment(op.getEnclosingEnvironment());

    /* copy the bindings for the formal environment from the top frame
    of the internal environment of the generic call to the new
    frame.  need to make sure missingness information is preserved
    and the environments for any default expression promises are
    set to the new environment.  should move this to envir.c where
    it can be done more efficiently. */
    for (PairList.Node next : op.getFormals().nodes()) {
      // R_varloc_t loc;
      // int missing;
      // TODO(alex): redo missingness handling
      //      loc = R_findVarLocInFrame(rho,symbol);
      //      if(loc == NULL)
      //       throw new EvalException("could not find symbol \"%s\" in environment of the generic
      // function"),
      //            CHAR(PRINTNAME(symbol)));
      //      missing = R_GetVarLocMISSING(loc);
      //      val = R_GetVarLocValue(loc);

      if (!next.hasTag()) {
        throw new EvalException("closure formal has no tag! op = " + op);
      }

      Symbol symbol = next.getTag();
      SEXP val = rho.findVariable(symbol);
      if (val == Symbol.UNBOUND_VALUE) {
        throw new EvalException(
            "could not find symbol \"%s\" in the environment of the generic function",
            symbol.getPrintName());
      }

      //      SET_FRAME(newrho, CONS(val, FRAME(newrho)));
      //      SET_TAG(FRAME(newrho), symbol);

      newrho.setVariable(symbol, val);

      //      if (missing) {
      //        SET_MISSING(FRAME(newrho), missing);
      //        if (TYPEOF(val) == PROMSXP && PRENV(val) == rho) {
      //          SEXP deflt;
      //          SET_PRENV(val, newrho);
      //          /* find the symbol in the method, copy its expression
      //           * to the promise */
      //          for(deflt = CAR(op); deflt != R_NilValue; deflt = CDR(deflt)) {
      //            if(TAG(deflt) == symbol)
      //              break;
      //          }
      //          if(deflt == R_NilValue)
      //            error(_("symbol \"%s\" not in environment of method"),
      //                CHAR(PRINTNAME(symbol)));
      //          SET_PRCODE(val, CAR(deflt));
      //        }
      //      }
    }

    /* copy the bindings of the spacial dispatch variables in the top
    frame of the generic call to the new frame */
    newrho.setVariable(DOT_DEFINED, rho.getVariable(DOT_DEFINED));
    newrho.setVariable(DOT_METHOD, rho.getVariable(DOT_METHOD));
    newrho.setVariable(DOT_TARGET, rho.getVariable(DOT_TARGET));

    /* copy the bindings for .Generic and .Methods.  We know (I think)
    that they are in the second frame, so we could use that. */
    newrho.setVariable(Symbols.GENERIC, newrho.getVariable(".Generic"));
    newrho.setVariable(DOT_METHODS, newrho.getVariable(DOT_METHODS));

    /* Find the calling context.  Should be R_GlobalContext unless
    profiling has inserted a CTXT_BUILTIN frame. */
    Context cptr = context;
    //    cptr = R_GlobalContext;
    //    if (cptr->callflag & CTXT_BUILTIN)
    //      cptr = cptr->nextcontext;

    /* The calling environment should either be the environment of the
    generic, rho, or the environment of the caller of the generic,
    the current sysparent. */
    Environment callerenv = cptr.getCallingEnvironment(); /* or rho? */

    /* get the rest of the stuff we need from the current context,
    execute the method, and return the result */
    FunctionCall call = cptr.getCall();
    PairList arglist = cptr.getArguments();
    SEXP val = R_execClosure(context, call, op, arglist, callerenv, newrho);
    return val;
  }