@Override
 public void visit(ListVector list) {
   ListVector.Builder builder = ListVector.newBuilder();
   for (SEXP exp : list) {
     builder.add(substitute(exp));
   }
   builder.copyAttributesFrom(list);
   result = builder.build();
 }
  public SEXP R_dispatchGeneric(Context context, Symbol fname, Environment ev, SEXP fdef) {
    SEXP method;
    SEXP f;
    SEXP val = Null.INSTANCE;
    // char *buf, *bufptr;
    int lwidth = 0;
    boolean prim_case = false;

    Environment f_env;
    if (fdef instanceof Closure) {
      f_env = ((Closure) fdef).getEnclosingEnvironment();
    } else if (fdef instanceof PrimitiveFunction) {
      fdef = R_primitive_generic(fdef);
      if (!(fdef instanceof Closure)) {
        throw new EvalException(
            "Failed to get the generic for the primitive \"%s\"", fname.asString());
      }
      f_env = ((Closure) fdef).getEnclosingEnvironment();
      prim_case = true;
    } else {
      throw new EvalException(
          "Expected a generic function or a primitive for dispatch, "
              + "got an object of class \"%s\"",
          fdef.getImplicitClass());
    }
    SEXP mtable = f_env.getVariable(R_allmtable);
    if (mtable == Symbol.UNBOUND_VALUE) {
      do_mtable(fdef, ev); /* Should initialize the generic */
      mtable = f_env.getVariable(R_allmtable);
    }
    SEXP sigargs = f_env.getVariable(R_sigargs);
    SEXP siglength = f_env.getVariable(R_siglength);

    if (sigargs == Symbol.UNBOUND_VALUE
        || siglength == Symbol.UNBOUND_VALUE
        || mtable == Symbol.UNBOUND_VALUE) {
      throw new EvalException(
          "Generic \"%s\" seems not to have been initialized for table dispatch---need to have .SigArgs and .AllMtable assigned in its environment",
          fname.asString());
    }
    int nargs = (int) siglength.asReal();
    ListVector.Builder classListBuilder = ListVector.newBuilder();
    StringVector thisClass;
    StringBuilder buf = new StringBuilder();

    for (int i = 0; i < nargs; i++) {
      Symbol arg_sym = sigargs.getElementAsSEXP(i);
      if (is_missing_arg(context, arg_sym, ev)) {
        thisClass = s_missing;
      } else {
        /*  get its class */
        SEXP arg;
        try {
          arg = context.evaluate(arg_sym, ev);
        } catch (EvalException e) {
          throw new EvalException(
              String.format(
                  "error in evaluating the argument '%s' in selecting a "
                      + "method for function '%s'",
                  arg_sym.getPrintName(), fname.asString()),
              e);
        }
        thisClass = Methods.R_data_class(arg, true);
      }
      classListBuilder.set(i, thisClass);
      if (i > 0) {
        buf.append("#");
      }
      buf.append(thisClass.asString());
    }
    ListVector classes = classListBuilder.build();
    method = ((Environment) mtable).getVariable(buf.toString());
    if (method == Symbol.UNBOUND_VALUE) {
      method = do_inherited_table(context, classes, fdef, mtable, (Environment) ev);
    }
    /* the rest of this is identical to R_standardGeneric;
    hence the f=method to remind us  */
    f = method;
    if (f.isObject()) f = R_loadMethod(context, f, fname.getPrintName(), ev);

    if (f instanceof Closure) {
      val = R_execMethod(context, (Closure) f, ev);
    } else if (f instanceof PrimitiveFunction) {
      /* primitives  can't be methods; they arise only as the
      default method when a primitive is made generic.  In this
      case, return a special marker telling the C code to go on
      with the internal computations. */
      // val = R_deferred_default_method();
      throw new UnsupportedOperationException();
    } else {
      throw new EvalException("invalid object (non-function) used as method");
    }
    return val;
  }