Coverage Report

Created: 2026-10-16 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/r-source/src/main/objects.c
Line
Count
Source
1
/*
2
 *  R : A Computer Language for Statistical Data Analysis
3
 *  Copyright (C) 1999-2026  The R Core Team.
4
 *  Copyright (C) 2002-2023  The R Foundation
5
 *  Copyright (C) 1995, 1996  Robert Gentleman and Ross Ihaka
6
 *
7
 *  This program is free software; you can redistribute it and/or modify
8
 *  it under the terms of the GNU General Public License as published by
9
 *  the Free Software Foundation; either version 2, or (at your option)
10
 *  any later version.
11
 *
12
 *  This program is distributed in the hope that it will be useful,
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 *  GNU General Public License for more details.
16
 *
17
 *  You should have received a copy of the GNU General Public License
18
 *  along with this program; if not, a copy is available at
19
 *  https://www.R-project.org/Licenses/
20
 */
21
22
/*  This module contains support for S-style generic */
23
/*  functions and "class" support.  Gag, barf ...  */
24
25
#ifdef HAVE_CONFIG_H
26
#include <config.h>
27
#endif
28
29
#define R_USE_SIGNALS 1
30
#include <Defn.h>
31
#include <Internal.h>
32
#include <R_ext/RS.h> /* for R_Calloc, R_Realloc and for S4 object bit, R_allocObject() */
33
34
static SEXP GetObject(RCNTXT *cptr)
35
821k
{
36
821k
    SEXP s, b, formals, tag;
37
38
821k
    b = cptr->callfun;
39
821k
    if (TYPEOF(b) != CLOSXP) error(_("generic 'function' is not a function"));
40
821k
    formals = FORMALS(b);
41
42
821k
    tag = TAG(formals);
43
821k
    if (tag != R_NilValue && tag != R_DotsSymbol) {
44
820k
  s = NULL;
45
  /** exact matches **/
46
3.00M
  for (b = cptr->promargs ; b != R_NilValue ; b = CDR(b))
47
2.18M
      if (TAG(b) != R_NilValue && pmatch(tag, TAG(b), 1)) {
48
0
    if (s != NULL)
49
0
        error(_("formal argument \"%s\" matched by multiple actual arguments"),
50
0
              CHAR(PRINTNAME(tag)));
51
0
    else
52
0
        s = CAR(b);
53
0
      }
54
55
820k
  if (s == NULL)
56
      /** partial matches **/
57
3.00M
      for (b = cptr->promargs ; b != R_NilValue ; b = CDR(b))
58
2.18M
    if (TAG(b) != R_NilValue && pmatch(tag, TAG(b), 0)) {
59
0
        if ( s != NULL)
60
0
      error(_("formal argument \"%s\" matched by multiple actual arguments"),
61
0
            CHAR(PRINTNAME(tag)));
62
0
        else
63
0
      s = CAR(b);
64
0
    }
65
820k
  if (s == NULL)
66
      /** first untagged argument **/
67
820k
      for (b = cptr->promargs ; b != R_NilValue ; b = CDR(b))
68
820k
    if (TAG(b) == R_NilValue )
69
820k
    {
70
820k
        s = CAR(b);
71
820k
        break;
72
820k
    }
73
820k
  if (s == NULL)
74
0
      s = CAR(cptr->promargs);
75
/*
76
      error("failed to match argument for dispatch");
77
*/
78
820k
    }
79
436
    else
80
436
  s = CAR(cptr->promargs);
81
82
821k
    if (TYPEOF(s) == PROMSXP) {
83
821k
  if (! PROMISE_IS_EVALUATED(s))
84
480k
      s = eval(s, R_BaseEnv);
85
341k
  else
86
341k
      s = PRVALUE(s);
87
821k
    }
88
821k
    return(s);
89
821k
}
90
91
static SEXP applyMethod(SEXP call, SEXP op, SEXP args, SEXP rho, SEXP newvars)
92
1.36M
{
93
1.36M
    SEXP ans;
94
1.36M
    if (TYPEOF(op) == SPECIALSXP) {
95
4.53k
  int save = R_PPStackTop, flag = PRIMPRINT(op);
96
4.53k
  const void *vmax = vmaxget();
97
4.53k
  R_Visible = flag != 1;
98
4.53k
  ans = PRIMFUN(op) (call, op, args, rho);
99
4.53k
  if (flag < 2) R_Visible = flag != 1;
100
4.53k
  check_stack_balance(op, save);
101
4.53k
  vmaxset(vmax);
102
4.53k
    }
103
    /* In other places we add a context to builtins when profiling,
104
       but we have not bothered here (as there seem to be no primitives
105
       used as methods, and this would have to be a primitive to be
106
       found).
107
     */
108
1.36M
    else if (TYPEOF(op) == BUILTINSXP) {
109
0
  int save = R_PPStackTop, flag = PRIMPRINT(op);
110
0
  const void *vmax = vmaxget();
111
0
  PROTECT(args = evalList(args, rho, call, 0));
112
0
  R_Visible = flag != 1;
113
0
  ans = PRIMFUN(op) (call, op, args, rho);
114
0
  if (flag < 2) R_Visible = flag != 1;
115
0
  UNPROTECT(1);
116
0
  check_stack_balance(op, save);
117
0
  vmaxset(vmax);
118
0
    }
119
1.36M
    else if (TYPEOF(op) == CLOSXP) {
120
1.36M
  ans = applyClosure(call, op, args, rho, newvars, FALSE);
121
1.36M
    }
122
0
    else
123
0
  ans = R_NilValue;  /* for -Wall */
124
1.36M
    return ans;
125
1.36M
}
126
127
128
/* "newintoold" -  a destructive matching of arguments; */
129
/* newargs comes first; any element of oldargs with */
130
/* a name that matches a named newarg is deleted; the */
131
/* two resulting lists are appended and returned. */
132
/* S claims to do this (white book) but doesn't seem to. */
133
134
static SEXP newintoold(SEXP _new, SEXP old)
135
872
{
136
872
    if (_new == R_NilValue) return R_NilValue;
137
436
    SETCDR(_new, newintoold(CDR(_new),old));
138
872
    while (old != R_NilValue) {
139
872
  if (TAG(old) != R_NilValue && TAG(old) == TAG(_new)) {
140
436
      SETCAR(old, CAR(_new));
141
436
      return CDR(_new);
142
436
  }
143
436
  old = CDR(old);
144
436
    }
145
0
    return _new;
146
436
}
147
148
static SEXP matchmethargs(SEXP oldargs, SEXP newargs)
149
436
{
150
436
    newargs = newintoold(newargs, oldargs);
151
436
    return listAppend(oldargs, newargs);
152
436
}
153
154
/* R_MethodsNamespace is initialized to R_GlobalEnv when R is
155
   initialized.  If it set to the methods namespace when the latter is
156
   loaded, and back to R_GlobalEnv when it is unloaded. */
157
158
#ifdef S3_for_S4_warn /* not currently used */
159
static SEXP s_check_S3_for_S4 = NULL;
160
void R_warn_S3_for_S4(SEXP method) {
161
  SEXP call;
162
  if(!s_check_S3_for_S4)
163
    s_check_S3_for_S4 = install(".checkS3forS4");
164
  PROTECT(call = lang2(s_check_S3_for_S4, method));
165
  eval(call, R_MethodsNamespace);
166
  UNPROTECT(1);
167
}
168
#endif
169
170
static SEXP findFunInEnvRange(SEXP symbol, SEXP rho, SEXP target)
171
12.9M
{
172
12.9M
    SEXP vl;
173
28.7M
    while(rho != R_EmptyEnv) {
174
28.7M
  vl = R_findVarInFrame(rho, symbol);
175
28.7M
  if (vl != R_UnboundValue) {
176
1.40M
      if (TYPEOF(vl) == PROMSXP) {
177
1.40M
    PROTECT(vl);
178
1.40M
    vl = eval(vl, rho);
179
1.40M
    UNPROTECT(1);
180
1.40M
      }
181
1.40M
      if ((TYPEOF(vl) == CLOSXP ||
182
0
     TYPEOF(vl) == BUILTINSXP ||
183
0
     TYPEOF(vl) == SPECIALSXP))
184
1.40M
    return (vl);
185
1.40M
  }
186
27.3M
  if(rho == target)
187
11.5M
      return (R_UnboundValue);
188
15.8M
  else
189
15.8M
      rho = ENCLOS(rho);
190
27.3M
    }
191
0
    return (R_UnboundValue);
192
12.9M
}
193
194
static SEXP findFunWithBaseEnvAfterGlobalEnv(SEXP symbol, SEXP rho)
195
11.5M
{
196
11.5M
    SEXP vl;
197
34.5M
    while(rho != R_EmptyEnv) {
198
23.0M
  vl = R_findVarInFrame(rho, symbol);
199
23.0M
  if (vl != R_UnboundValue) {
200
0
      if (TYPEOF(vl) == PROMSXP) {
201
0
    PROTECT(vl);
202
0
    vl = eval(vl, rho);
203
0
    UNPROTECT(1);
204
0
      }
205
0
      if ((TYPEOF(vl) == CLOSXP ||
206
0
     TYPEOF(vl) == BUILTINSXP ||
207
0
     TYPEOF(vl) == SPECIALSXP))
208
0
    return (vl);
209
0
  }
210
23.0M
  if(rho == R_GlobalEnv)
211
11.4M
      rho = R_BaseEnv;
212
11.5M
  else
213
11.5M
      rho = ENCLOS(rho);
214
23.0M
    }
215
11.5M
    return (R_UnboundValue);
216
11.5M
}
217
218
/*  usemethod  -  calling functions need to evaluate the object
219
 *  (== 2nd argument).  They also need to ensure that the
220
 *  argument list is set up in the correct manner.
221
 *
222
 *    1. find the context for the calling function (i.e. the generic)
223
 *   this gives us the unevaluated arguments for the original call
224
 *
225
 *    2. create an environment for evaluating the method and insert
226
 *   a handful of variables (.Generic, .Class and .Method) into
227
 *   that environment. Also copy any variables in the env of the
228
 *   generic that are not formal (or actual) arguments.
229
 *
230
 *    3. fix up the argument list; it should be the arguments to the
231
 *   generic matched to the formals of the method to be invoked */
232
233
attribute_hidden
234
SEXP R_LookupMethod(SEXP method, SEXP rho, SEXP callrho, SEXP defrho)
235
12.9M
{
236
12.9M
    SEXP val, top = R_NilValue; /* -Wall */
237
12.9M
    static SEXP s_S3MethodsTable = NULL;
238
12.9M
    PROTECT_INDEX validx;
239
240
12.9M
    if (TYPEOF(callrho) != ENVSXP) {
241
0
  if (TYPEOF(callrho) == NILSXP)
242
0
      error(_("use of NULL environment is defunct"));
243
0
  else
244
0
      error(_("bad generic call environment"));
245
0
    }
246
12.9M
    if (defrho == R_BaseEnv)
247
11.0M
  defrho = R_BaseNamespace;
248
1.93M
    else if (TYPEOF(defrho) != ENVSXP) {
249
0
  if (TYPEOF(defrho) == NILSXP)
250
0
      error(_("use of NULL environment is defunct"));
251
0
  else
252
0
      error(_("bad generic definition environment"));
253
0
    }
254
255
    /* This evaluates promises */
256
12.9M
    PROTECT(top = topenv(R_NilValue, callrho));
257
12.9M
    val = findFunInEnvRange(method, callrho, top);
258
12.9M
    if(val != R_UnboundValue) {
259
1.40M
  UNPROTECT(1); /* top */
260
1.40M
  return val;
261
1.40M
    }
262
263
11.5M
    PROTECT_WITH_INDEX(val, &validx);
264
    /* We assume here that no one registered a non-function */
265
11.5M
    if (!s_S3MethodsTable)
266
32
  s_S3MethodsTable = install(".__S3MethodsTable__.");
267
11.5M
    SEXP table = R_findVarInFrame(defrho, s_S3MethodsTable);
268
11.5M
    if (TYPEOF(table) == PROMSXP) {
269
11.5M
  PROTECT(table);
270
11.5M
  table = eval(table, R_BaseEnv);
271
11.5M
  UNPROTECT(1); /* table */
272
11.5M
    }
273
11.5M
    if (TYPEOF(table) == ENVSXP) {
274
11.5M
  PROTECT(table);
275
11.5M
  REPROTECT(val = R_findVarInFrame(table, method), validx);
276
11.5M
  UNPROTECT(1); /* table */
277
11.5M
  if (TYPEOF(val) == PROMSXP)
278
8.87k
      REPROTECT(val = eval(val, rho), validx);
279
11.5M
  if(val != R_UnboundValue) {
280
8.87k
      UNPROTECT(2); /* top, val */
281
8.87k
      return val;
282
8.87k
  }
283
11.5M
    }
284
285
11.5M
    if (top == R_GlobalEnv)
286
2.00k
  top = R_BaseEnv;
287
11.5M
    else
288
11.5M
  top = ENCLOS(top);
289
11.5M
    REPROTECT(val = findFunWithBaseEnvAfterGlobalEnv(method, top),
290
11.5M
        validx);
291
292
11.5M
    UNPROTECT(2); /* top, val */
293
11.5M
    return val;
294
11.5M
}
295
296
#ifdef UNUSED
297
static int match_to_obj(SEXP arg, SEXP obj) {
298
  return (arg == obj) ||
299
    (TYPEOF(arg) == PROMSXP && PRVALUE(arg) == obj);
300
}
301
#endif
302
303
/* look up the class name in the methods package table of S3 classes
304
   which should be explicitly converted when an S3 method is applied
305
   to an object from an S4 subclass.
306
*/
307
0
attribute_hidden int isBasicClass(const char *ss) {
308
0
    static SEXP s_S3table = NULL;
309
0
    if(!s_S3table) {
310
0
      s_S3table = R_findVarInFrame(R_MethodsNamespace,
311
0
           install(".S3MethodsClasses"));
312
0
      if(s_S3table == R_UnboundValue)
313
0
  error(_("no '.S3MethodsClass' table, cannot use S4 objects with S3 methods ('methods' package not attached?)"));
314
0
      if (TYPEOF(s_S3table) == PROMSXP)  /* findVar... ignores lazy data */
315
0
  s_S3table = eval(s_S3table, R_MethodsNamespace);
316
0
    }
317
0
    if(s_S3table == R_UnboundValue)
318
0
      return FALSE; /* too screwed up to do conversions */
319
0
    return R_existsVarInFrame(s_S3table, install(ss));
320
0
}
321
322
/* Note that ./attrib.c 's S4_extends() has an alternative
323
   'sanity check for methods package available' */
324
0
attribute_hidden Rboolean R_has_methods_attached(void) {
325
0
    return(
326
0
  isMethodsDispatchOn() &&
327
  // based on unlockBinding() in ../library/methods/R/zzz.R  {since 2003}:
328
0
  !R_BindingIsLocked(install(".BasicFunsList"), R_MethodsNamespace));
329
0
}
330
331
static R_INLINE
332
8.48M
SEXP addS3Var(SEXP vars, SEXP name, SEXP value) {
333
334
8.48M
    SEXP res = CONS(value, vars);
335
8.48M
    SET_TAG(res, name);
336
8.48M
    return res;
337
8.48M
}
338
339
attribute_hidden
340
SEXP createS3Vars(SEXP dotGeneric, SEXP dotGroup, SEXP dotClass, SEXP dotMethod,
341
1.41M
      SEXP dotGenericCallEnv, SEXP dotGenericDefEnv) {
342
343
1.41M
    SEXP v = R_NilValue;
344
1.41M
    v = addS3Var(v, R_dot_GenericDefEnv, dotGenericDefEnv);
345
1.41M
    v = addS3Var(v, R_dot_GenericCallEnv, dotGenericCallEnv);
346
1.41M
    v = addS3Var(v, R_dot_Group, dotGroup);
347
1.41M
    v = addS3Var(v, R_dot_Method, dotMethod);
348
1.41M
    v = addS3Var(v, R_dot_Class, dotClass);
349
1.41M
    v = addS3Var(v, R_dot_Generic, dotGeneric);
350
351
1.41M
    return v;
352
1.41M
}
353
354
355
static
356
SEXP dispatchMethod(SEXP op, SEXP sxp, SEXP dotClass, RCNTXT *cptr, SEXP method,
357
1.36M
        const char *generic, SEXP rho, SEXP callrho, SEXP defrho) {
358
359
1.36M
    SEXP newvars = PROTECT(createS3Vars(
360
1.36M
  PROTECT(mkString(generic)),
361
1.36M
  R_BlankScalarString,
362
1.36M
  dotClass,
363
1.36M
  PROTECT(ScalarString(PRINTNAME(method))),
364
1.36M
  callrho,
365
1.36M
  defrho
366
1.36M
    ));
367
368
    /* Create a new environment without any */
369
    /* of the formals to the generic in it. */
370
371
1.36M
    if (TYPEOF(op) == CLOSXP) {
372
821k
  SEXP formals = FORMALS(op);
373
821k
  SEXP s, t;
374
821k
  int matched;
375
376
2.34M
  for (s = FRAME(cptr->cloenv); s != R_NilValue; s = CDR(s)) {
377
1.52M
      matched = 0;
378
2.51M
      for (t = formals; t != R_NilValue; t = CDR(t))
379
2.51M
    if (TAG(t) == TAG(s)) {
380
1.52M
        matched = 1;
381
1.52M
        break;
382
1.52M
    }
383
1.52M
      if (!matched) {
384
#ifdef USEMETHOD_FORWARD_LOCALS
385
    UNPROTECT(1); /* newvars */
386
    newvars = PROTECT(CONS(CAR(s), newvars));
387
    SET_TAG(newvars, TAG(s));
388
#else
389
0
    static int option = -1;
390
0
    if (option == -1) {
391
0
        option = 2; // none: the default
392
0
        const char *val = getenv("R_USEMETHOD_FORWARD_LOCALS");
393
0
        if (val != NULL) {
394
0
      if (strcmp(val, "all") == 0)
395
0
          option = 0;
396
0
      else if (strcmp(val, "S4") == 0)
397
0
          option = 1;
398
0
      else if (strcmp(val, "none") == 0)
399
0
          option = 2;
400
0
      else if (strcmp(val, "error") == 0)
401
0
          option = 3;
402
0
      else if (strcmp(val, "warning") == 0)
403
0
          option = 4;
404
0
      else
405
0
          warning("bad value for R_USEMETHOD_FORWARD_LOCALS");
406
0
        }
407
0
    }
408
0
    SEXP val;
409
0
    char buf[8192];
410
0
    switch(option) {
411
0
    case 0: // forward all, as in the past before R 4.4.0
412
0
        UNPROTECT(1); /* newvars */
413
0
        newvars = PROTECT(CONS(CAR(s), newvars));
414
0
        SET_TAG(newvars, TAG(s));
415
0
        break;
416
0
    case 1: // forward only S4 variables
417
0
        if (TAG(s) == R_dot_defined ||
418
0
      TAG(s) == R_dot_Method ||
419
0
      TAG(s) == R_dot_target ||
420
0
      TAG(s) == R_dot_Generic ||
421
0
      TAG(s) == R_dot_Methods) {
422
0
      UNPROTECT(1); /* newvars */
423
0
      newvars = PROTECT(CONS(CAR(s), newvars));
424
0
      SET_TAG(newvars, TAG(s));
425
0
        }
426
0
        break;
427
0
    case 2: // don't forward any variables
428
0
        break;
429
0
    case 3: // forward all, with an error when used
430
#ifdef WARN_ON_FORWARDING
431
        if (TAG(s) != R_dot_defined &&
432
      TAG(s) != R_dot_Method &&
433
      TAG(s) != R_dot_target &&
434
      TAG(s) != R_dot_Generic &&
435
      TAG(s) != R_dot_Methods)
436
      warningcall_immediate(R_NilValue,
437
                "UseMethod forwarding '%s' "
438
                "in generic '%s'",
439
        CHAR(PRINTNAME(TAG(s))),
440
        generic);
441
#endif
442
0
        snprintf(buf, sizeof(buf),
443
0
           "stop(\"getting UseMethod variable '%s' "
444
0
           "from generic '%s'; "
445
0
           "this is no longer supported\")",
446
0
           CHAR(PRINTNAME(TAG(s))),
447
0
           generic);
448
0
        val = mkPROMISE(R_ParseString(buf), R_GlobalEnv);
449
0
        UNPROTECT(1); /* newvars */
450
0
        newvars = PROTECT(CONS(val, newvars));
451
0
        SET_TAG(newvars, TAG(s));
452
0
        break;
453
0
    default:
454
0
        option = 0;
455
0
        warning("bad value for R_USEMETHOD_FORWARD_LOCALS");
456
0
    }
457
0
#endif
458
0
      }
459
1.52M
  }
460
821k
    }
461
462
    /* Debug a method when debugging the generic. When called via UseMethod or
463
       NextMethod, RSTEP(op) will always be zero because the bit is cleared by
464
       applyClosure. We thus approximate and enter the debugger also when
465
       RDEBUG(rho) is set. */
466
1.36M
    if ((RDEBUG(op) && R_current_debug_state()) || RSTEP(op) || RDEBUG(rho))
467
0
  SET_RSTEP(sxp, 1);
468
469
1.36M
    SEXP newcall =  PROTECT(shallow_duplicate(cptr->call));
470
1.36M
    SETCAR(newcall, method);
471
1.36M
    R_GlobalContext->callflag = CTXT_GENERIC;
472
1.36M
    SEXP matchedarg = PROTECT(cptr->promargs); /* ? is this PROTECT needed ? */
473
1.36M
    SEXP ans = applyMethod(newcall, sxp, matchedarg, rho, newvars);
474
1.36M
    R_GlobalContext->callflag = CTXT_RETURN;
475
1.36M
    UNPROTECT(5); /* "generic,method", newvars, newcall, matchedarg */
476
477
1.36M
    return ans;
478
1.36M
}
479
480
attribute_hidden
481
int usemethod(const char *generic, SEXP obj, SEXP call, SEXP args,
482
        SEXP rho, SEXP callrho, SEXP defrho, SEXP *ans)
483
5.90M
{
484
5.90M
    SEXP klass, method, sxp;
485
5.90M
    SEXP op;
486
5.90M
    int i, nclass;
487
5.90M
    RCNTXT *cptr;
488
489
    /* Get the context which UseMethod was called from. */
490
491
5.90M
    cptr = R_GlobalContext;
492
5.90M
    op = cptr->callfun;
493
5.90M
    PROTECT(klass = R_data_class2(obj));
494
495
5.90M
    nclass = length(klass);
496
12.8M
    for (i = 0; i < nclass; i++) {
497
7.57M
  const void *vmax = vmaxget();
498
7.57M
  const char *ss = translateChar(STRING_ELT(klass, i));
499
7.57M
  method = installS3Signature(generic, ss);
500
7.57M
  vmaxset(vmax);
501
7.57M
  sxp = R_LookupMethod(method, rho, callrho, defrho);
502
7.57M
  if (isFunction(sxp)) {
503
621k
      if(method == R_SortListSymbol && CLOENV(sxp) == R_BaseNamespace)
504
0
    continue; /* kludge because sort.list is not a method */
505
621k
      PROTECT(sxp);
506
621k
      if (i > 0) {
507
63.3k
    SEXP dotClass = PROTECT(stringSuffix(klass, i));
508
63.3k
    setAttrib(dotClass, R_PreviousSymbol, klass);
509
63.3k
    *ans = dispatchMethod(op, sxp, dotClass, cptr, method, generic,
510
63.3k
              rho, callrho, defrho);
511
63.3k
    UNPROTECT(1); /* dotClass */
512
558k
      } else {
513
558k
    *ans = dispatchMethod(op, sxp, klass, cptr, method, generic,
514
558k
              rho, callrho, defrho);
515
558k
      }
516
621k
      UNPROTECT(2); /* klass, sxp */
517
621k
      return 1;
518
621k
  }
519
7.57M
    }
520
5.28M
    method = installS3Signature(generic, "default");
521
5.28M
    PROTECT(sxp = R_LookupMethod(method, rho, callrho, defrho));
522
5.28M
    if (isFunction(sxp)) {
523
739k
  *ans = dispatchMethod(op, sxp, R_NilValue, cptr, method, generic,
524
739k
            rho, callrho, defrho);
525
739k
  UNPROTECT(2); /* klass, sxp */
526
739k
  return 1;
527
739k
    }
528
4.54M
    UNPROTECT(2); /* klass, sxp */
529
4.54M
    cptr->callflag = CTXT_RETURN;
530
4.54M
    return 0;
531
5.28M
}
532
533
/* Note: "do_usemethod" is not the only entry point to
534
   "usemethod". Things like [ and [[ call usemethod directly,
535
   hence do_usemethod should just be an interface to usemethod.
536
*/
537
538
/* This is a primitive SPECIALSXP */
539
NORET attribute_hidden
540
SEXP do_usemethod(SEXP call, SEXP op, SEXP args, SEXP env)
541
821k
{
542
821k
    static SEXP do_usemethod_formals = NULL;
543
821k
    if (do_usemethod_formals == NULL)
544
32
  do_usemethod_formals = allocFormalsList2(install("generic"),
545
32
             install("object"));
546
547
821k
    SEXP argList = PROTECT(matchArgs_NR(do_usemethod_formals, args, call));
548
821k
    if (CAR(argList) == R_MissingArg)
549
0
  errorcall(call, _("there must be a 'generic' argument"));
550
    // else
551
821k
    SEXP generic = PROTECT(eval(CAR(argList), env));
552
821k
    if(!isString(generic) || LENGTH(generic) != 1)
553
0
  errorcall(call, _("'generic' argument must be a character string"));
554
555
    /* get environments needed for dispatching.
556
       callenv = environment from which the generic was called
557
       defenv = environment where the generic was defined */
558
821k
    RCNTXT *cptr = R_GlobalContext;
559
821k
    if ( !(cptr->callflag & CTXT_FUNCTION) || cptr->cloenv != env)
560
0
  errorcall(call, _("'UseMethod' used in an inappropriate fashion"));
561
821k
    SEXP callenv = cptr->sysparent;
562
    /* We need to find the generic to find out where it is defined.
563
       This is set up to avoid getting caught by things like
564
565
  mycoef <- function(x)
566
       {
567
     mycoef <- function(x) stop("not this one")
568
     UseMethod("mycoef")
569
       }
570
571
  The generic need not be a closure (Henrik Bengtsson writes
572
  UseMethod("$"), although only functions are documented.)
573
    */
574
821k
    SEXP defenv = topenv(R_NilValue, env);
575
821k
    SEXP obj = PROTECT((CADR(argList) != R_MissingArg)
576
821k
           ? eval(CADR(argList), env)
577
821k
           : GetObject(cptr));
578
821k
    SEXP ans;
579
821k
    if (usemethod(translateChar(STRING_ELT(generic, 0)), obj, call, CDR(args),
580
821k
      env, callenv, defenv, &ans) == 1) {
581
820k
  UNPROTECT(3); /* obj, generic, argList */
582
820k
  findcontext(CTXT_RETURN, env, ans); /* does not return */
583
820k
    }
584
731
    else { // no method found
585
1.46k
#define CLLEN 1024
586
731
  char cl[CLLEN] = {0};
587
731
  SEXP klass = PROTECT(R_data_class2(obj));
588
731
  int nclass = length(klass);
589
731
  if(!nclass)
590
0
      errorcall(call, _("illegal class of length 0 when using method for '%s'"),
591
0
          translateChar(STRING_ELT(generic, 0)));
592
731
  const char *c_name = translateChar(STRING_ELT(klass, 0));
593
731
  if (nclass == 1) {
594
0
      strncpy(cl, c_name, CLLEN-1); cl[CLLEN-1] = '\0';
595
731
  } else { // nclass >= 2
596
731
      size_t cl_count = 3; // 3 : "c(" + \0
597
731
      strcpy(cl, "c('");
598
731
      for (int i = 0; i < nclass; i++) {
599
0
    if(i > 0) {
600
0
        c_name = translateChar(STRING_ELT(klass, i));
601
0
        cl_count += 4; // "', '"
602
0
        if (cl_count < CLLEN) strcat(cl, "', '");
603
0
    }
604
0
    size_t len_nm = strlen(c_name);
605
0
    if (cl_count + len_nm >= CLLEN) {
606
0
        cl_count += 2;
607
0
        if(cl_count < CLLEN) strcat(cl, "..");
608
0
        break;
609
0
    }
610
    // else
611
0
    cl_count += len_nm;
612
0
    strcat(cl, c_name);
613
0
      }
614
731
      if (++cl_count < CLLEN) strcat(cl, "'");
615
731
      if (++cl_count < CLLEN) strcat(cl, ")");
616
731
  }
617
731
  errorcall(call, _("no applicable method for '%s' applied to an object of class \"%s\""),
618
731
      translateChar(STRING_ELT(generic, 0)), cl);
619
731
    }
620
821k
}
621
622
/*
623
   fixcall: fixes up the call when arguments to the function may
624
   have changed; for now we only worry about tagged args, appending
625
   them if they are not already there
626
*/
627
628
static SEXP fixcall(SEXP call, SEXP args)
629
436
{
630
436
    SEXP s, t;
631
436
    int found;
632
633
1.74k
    for(t = args; t != R_NilValue; t = CDR(t)) {
634
1.30k
  if(TAG(t) != R_NilValue) {
635
872
    found = 0;
636
2.18k
    for(s = call; CDR(s) != R_NilValue; s = CDR(s))
637
2.18k
        if(TAG(CDR(s)) == TAG(t)) {
638
872
      found = 1;
639
872
      break;
640
872
        }
641
872
    if( !found ) {
642
0
      SETCDR(s, allocList(1));
643
0
      SET_TAG(CDR(s), TAG(t));
644
0
      SETCAR(CDR(s), lazy_duplicate(CAR(t)));
645
0
    }
646
872
  }
647
1.30k
    }
648
436
    return call;
649
436
}
650
651
/*
652
   equalS3Signature: compares "signature" and "left.right"
653
   all arguments must be non-null
654
*/
655
static
656
Rboolean equalS3Signature(const char *signature, const char *left,
657
5.40k
       const char *right) {
658
659
5.40k
    const char *s = signature;
660
5.40k
    const char *a;
661
662
14.8k
    for(a = left; *a; s++, a++) {
663
9.40k
  if (*s != *a)
664
0
      return FALSE;
665
9.40k
    }
666
5.40k
    if (*s++ != '.')
667
0
  return FALSE;
668
44.6k
    for(a = right; *a; s++, a++) {
669
39.2k
  if (*s != *a)
670
0
      return FALSE;
671
39.2k
    }
672
5.40k
    return (*s == 0) ? TRUE : FALSE;
673
5.40k
}
674
675
676
static R_INLINE SEXP getPrimitive(SEXP symbol)
677
0
{
678
0
    SEXP value = SYMVALUE(symbol);
679
0
    if (TYPEOF(value) == PROMSXP) {
680
0
  PROTECT(value);
681
0
  value = eval(value, R_GlobalEnv);
682
0
  UNPROTECT(1);
683
0
  ENSURE_NAMEDMAX(value);
684
0
    }
685
0
    if (TYPEOF(value) == BUILTINSXP || TYPEOF(value) == SPECIALSXP)
686
0
        return value;
687
688
0
    if (TYPEOF(value) == CLOSXP) {
689
  /* probably means a package redefined the base function so
690
     try to get the real thing from the internal table of
691
     primitives */
692
0
  value = R_Primitive(CHAR(PRINTNAME(symbol)));
693
0
    } else
694
0
  value = R_NilValue;
695
696
0
    return value;
697
0
}
698
699
/* If NextMethod has any arguments the first must be the generic */
700
/* the second the object and any remaining are matched with the */
701
/* formals of the chosen method. */
702
703
704
/* This is a special .Internal */
705
attribute_hidden SEXP do_nextmethod(SEXP call, SEXP op, SEXP args, SEXP env)
706
5.40k
{
707
5.40k
    const char *sb, *sg, *sk;
708
5.40k
    SEXP ans, s, t, klass, method, matchedarg, generic;
709
5.40k
    SEXP nextfun, nextfunSignature;
710
5.40k
    SEXP sysp, formals, newcall;
711
5.40k
    SEXP group, basename;
712
5.40k
    SEXP callenv, defenv;
713
5.40k
    RCNTXT *cptr;
714
5.40k
    int i, j;
715
716
5.40k
    cptr = R_GlobalContext;
717
5.40k
    cptr->callflag = CTXT_GENERIC;
718
719
    /* get the env NextMethod was called from */
720
5.40k
    sysp = R_GlobalContext->sysparent;
721
11.0k
    while (cptr != NULL) {
722
11.0k
  if (cptr->callflag & CTXT_FUNCTION && cptr->cloenv == sysp) break;
723
5.66k
  cptr = cptr->nextcontext;
724
5.66k
    }
725
5.40k
    if (cptr == NULL)
726
0
  error(_("'NextMethod' called from outside a function"));
727
728
5.40k
    PROTECT(newcall = shallow_duplicate(cptr->call));
729
730
    /* eg get("print.ts")(1) or do.call() */
731
5.40k
    if (TYPEOF(CAR(cptr->call)) != SYMSXP)
732
0
       error(_("'NextMethod' called from an anonymous function"));
733
734
5.40k
    readS3VarsFromFrame(sysp, &generic, &group, &klass, &method,
735
5.40k
      &callenv, &defenv);
736
737
    /* Find dispatching environments. Promises shouldn't occur, but
738
       check to be on the safe side.  If the variables are not in the
739
       environment (the method was called outside a method dispatch)
740
       then chose reasonable defaults. */
741
5.40k
    if (TYPEOF(callenv) == PROMSXP)
742
0
  callenv = eval(callenv, R_BaseEnv);
743
5.40k
    else if (callenv == R_UnboundValue)
744
0
  callenv = env;
745
5.40k
    if (TYPEOF(defenv) == PROMSXP) defenv = eval(defenv, R_BaseEnv);
746
5.40k
    else if (defenv == R_UnboundValue) defenv = R_GlobalEnv;
747
748
    /* set up the arglist */
749
5.40k
    s = cptr->callfun;
750
751
5.40k
    if (TYPEOF(s) != CLOSXP){ /* R_LookupMethod looked for a function */
752
0
  if (s == R_UnboundValue)
753
0
      error(_("no calling generic was found: was a method called directly?"));
754
0
  else
755
0
      errorcall(R_NilValue,
756
0
      _("'function' is not a function, but of type %d"),
757
0
      TYPEOF(s));
758
0
    }
759
    /* get formals and actuals; attach the names of the formals to
760
       the actuals, expanding any ... that occurs */
761
5.40k
    formals = FORMALS(s);
762
5.40k
    PROTECT(matchedarg = patchArgsByActuals(formals, cptr->promargs, cptr->cloenv));
763
764
    /*
765
      Now see if there were any other arguments passed in
766
      Currently we seem to only allow named args to change
767
      or to be added, this is at variance with p. 470 of the
768
      White Book
769
    */
770
771
5.40k
    s = CADDR(args); /* this is ... and we need to see if it's bound */
772
5.40k
    if (s == R_DotsSymbol) {
773
5.40k
  t = R_findVarInFrame(env, s);
774
5.40k
  if (t != R_NilValue && t != R_MissingArg) {
775
436
      SET_TYPEOF(t, LISTSXP); /* a safe mutation */
776
436
      s = matchmethargs(matchedarg, t);
777
436
      UNPROTECT(1);
778
436
      PROTECT(matchedarg = s);
779
436
      newcall = fixcall(newcall, matchedarg);
780
436
  }
781
5.40k
    }
782
0
    else
783
0
  error(_("wrong argument ..."));
784
785
    /*
786
      .Class is used to determine the next method; if it doesn't
787
      exist the first argument to the current method is used
788
      the second argument to NextMethod is another option but
789
      isn't currently used).
790
    */
791
5.40k
    if (klass == R_UnboundValue) {
792
  /* we can get the object from actuals directly, but this
793
     branch seems to be very cold if not dead */
794
0
  s = GetObject(cptr);
795
0
  if (!isObject(s)) error(_("object not specified"));
796
0
  klass = getAttrib(s, R_ClassSymbol);
797
0
    }
798
799
    /* the generic comes from either the sysparent or it's named */
800
5.40k
    if (generic == R_UnboundValue)
801
0
  generic = eval(CAR(args), env);
802
5.40k
    if (generic == R_NilValue)
803
0
  error(_("generic function not specified"));
804
5.40k
    PROTECT(generic);
805
806
5.40k
    if (!isString(generic) || LENGTH(generic) != 1)
807
0
  error(_("invalid generic argument to 'NextMethod'"));
808
809
5.40k
    if (CHAR(STRING_ELT(generic, 0))[0] == '\0')
810
0
  error(_("generic function not specified"));
811
812
    /* determine whether we are in a Group dispatch */
813
    /* determine the root: either the group or the generic will be it */
814
5.40k
    if (group == R_UnboundValue) {
815
0
  group = R_BlankScalarString;
816
0
  basename = generic;
817
5.40k
    } else {
818
5.40k
  if (!isString(group) || LENGTH(group) != 1)
819
0
      error(_("invalid 'group' argument found in 'NextMethod'"));
820
5.40k
  if (CHAR(STRING_ELT(group, 0))[0] == '\0') basename = generic;
821
0
  else basename = group;
822
5.40k
    }
823
5.40k
    PROTECT(group);
824
825
5.40k
    nextfun = R_NilValue;
826
5.40k
    nextfunSignature = R_NilValue;
827
828
    /*
829
       Find the method currently being invoked and jump over the current call
830
       If t is R_UnboundValue then we called the current method directly
831
    */
832
5.40k
    const void *vmax = vmaxget(); /* needed for translateChar */
833
5.40k
    const char *b = NULL;
834
5.40k
    if (method != R_UnboundValue) {
835
5.40k
  if (!isString(method))
836
0
      error(_("wrong value for .Method"));
837
5.40k
  for(i = 0; i < LENGTH(method); i++) {
838
5.40k
      b = translateChar(STRING_ELT(method, i));
839
5.40k
      if (strlen(b)) break;
840
5.40k
  }
841
  /* for binary operators check that the second argument's method
842
     is the same or absent */
843
10.8k
  for(j = i; j < LENGTH(method); j++) {
844
5.40k
      const char *bb = translateChar(STRING_ELT(method, j));
845
5.40k
      if (strlen(bb) && strcmp(b,bb))
846
0
    warning(_("Incompatible methods ignored"));
847
5.40k
  }
848
5.40k
    }
849
0
    else {
850
0
  b = CHAR(PRINTNAME(CAR(cptr->call)));
851
0
    }
852
853
5.40k
    sb = translateChar(STRING_ELT(basename, 0));
854
5.40k
    Rboolean foundSignature = FALSE;
855
5.40k
    for (j = 0; j < LENGTH(klass); j++) {
856
5.40k
  sk = translateChar(STRING_ELT(klass, j));
857
5.40k
  if (equalS3Signature(b, sb, sk)) { /* b == sb.sk */
858
5.40k
      foundSignature = TRUE;
859
5.40k
      break;
860
5.40k
  }
861
5.40k
    }
862
863
5.40k
    if (foundSignature) /* we found a match and start from there */
864
5.40k
      j++;
865
0
    else
866
0
      j = 0;  /* no match so start with the first element of .Class */
867
868
    /* we need the value of i on exit from the for loop to figure out
869
     how many classes to drop. */
870
871
5.40k
    sg = translateChar(STRING_ELT(generic, 0));
872
5.88k
    for (i = j ; i < LENGTH(klass); i++) {
873
909
  sk = translateChar(STRING_ELT(klass, i));
874
909
  nextfunSignature = installS3Signature(sg, sk);
875
909
  nextfun = R_LookupMethod(nextfunSignature, env, callenv, defenv);
876
909
  if (isFunction(nextfun)) break;
877
473
  if (group != R_UnboundValue) {
878
      /* if not Generic.foo, look for Group.foo */
879
473
      nextfunSignature = installS3Signature(sb, sk);
880
473
      nextfun = R_LookupMethod(nextfunSignature, env, callenv, defenv);
881
473
      if(isFunction(nextfun))
882
0
    break;
883
473
  }
884
473
  if (isFunction(nextfun))
885
0
      break;
886
473
    }
887
5.40k
    if (!isFunction(nextfun)) {
888
4.97k
  nextfunSignature = installS3Signature(sg, "default");
889
4.97k
  nextfun = R_LookupMethod(nextfunSignature, env, callenv, defenv);
890
  /* If there is no default method, try the generic itself,
891
     provided it is primitive or a wrapper for a .Internal
892
     function of the same name.
893
   */
894
4.97k
  if (!isFunction(nextfun)) {
895
4.53k
      t = install(sg);
896
4.53k
      nextfun = R_findVar(t, env);
897
4.53k
      if (TYPEOF(nextfun) == PROMSXP) {
898
0
    PROTECT(nextfun);
899
0
    nextfun = eval(nextfun, env);
900
0
    UNPROTECT(1);
901
0
      }
902
4.53k
      if (!isFunction(nextfun))
903
0
    error(_("no method to invoke"));
904
4.53k
      if (TYPEOF(nextfun) == CLOSXP) {
905
0
    if (INTERNAL(t) != R_NilValue)
906
0
        nextfun = INTERNAL(t);
907
0
    else {
908
0
        nextfun = getPrimitive(t);
909
0
        if (nextfun == R_NilValue)
910
0
            error(_("no method to invoke"));
911
0
    }
912
0
      }
913
4.53k
  }
914
4.97k
    }
915
5.40k
    PROTECT(nextfun);
916
5.40k
    PROTECT(s = stringSuffix(klass, i));
917
5.40k
    setAttrib(s, R_PreviousSymbol, klass);
918
    /* It is possible that if a method was called directly that
919
  'method' is unset */
920
5.40k
    if (method != R_UnboundValue) {
921
  /* for Ops we need `method' to be a vector */
922
5.40k
  PROTECT(method = duplicate(method));
923
10.8k
  for(j = 0; j < LENGTH(method); j++) {
924
5.40k
      if (strlen(CHAR(STRING_ELT(method,j))))
925
5.40k
    SET_STRING_ELT(method, j,  PRINTNAME(nextfunSignature));
926
5.40k
  }
927
5.40k
    } else
928
0
  PROTECT(method = PRINTNAME(nextfunSignature));
929
930
5.40k
    SEXP newvars = PROTECT(createS3Vars(
931
5.40k
  generic,
932
5.40k
  group,
933
5.40k
  s,
934
5.40k
  method,
935
5.40k
  callenv,
936
5.40k
  defenv
937
5.40k
    ));
938
939
5.40k
    SETCAR(newcall, nextfunSignature);
940
941
    /* applyMethod expects that the parent of the caller is the caller
942
       of the generic, so fixup by brute force. This should fix
943
       PR#15267 --pd */
944
5.40k
    R_GlobalContext->sysparent = callenv;
945
946
5.40k
    ans = applyMethod(newcall, nextfun, matchedarg, env, newvars);
947
5.40k
    vmaxset(vmax);
948
5.40k
    UNPROTECT(8);
949
5.40k
    return(ans);
950
5.40k
}
951
952
/* primitive */
953
attribute_hidden SEXP do_unclass(SEXP call, SEXP op, SEXP args, SEXP env)
954
14.1k
{
955
14.1k
    checkArity(op, args);
956
14.1k
    check1arg(args, call, "x");
957
958
14.1k
    if (isObject(CAR(args))) {
959
2.47k
  switch(TYPEOF(CAR(args))) {
960
0
  case ENVSXP:
961
0
      errorcall(call, _("cannot unclass an environment"));
962
0
      break;
963
0
  case EXTPTRSXP:
964
0
      errorcall(call, _("cannot unclass an external pointer"));
965
0
      break;
966
2.47k
  default:
967
2.47k
      break;
968
2.47k
  }
969
2.47k
  if (MAYBE_REFERENCED(CAR(args)))
970
1.82k
      SETCAR(args, R_shallow_duplicate_attr(CAR(args)));
971
2.47k
  setAttrib(CAR(args), R_ClassSymbol, R_NilValue);
972
2.47k
    }
973
14.1k
    return CAR(args);
974
14.1k
}
975
976
/** Version of inherits() that supports S4 inheritance and implicit
977
    classes.  The inlined inherits() does not have access to private
978
    entry points R_data_class() and R_data_class2(). The semantics of
979
    inherits2() are identical to that of the R-level inherits(),
980
    except there is no translation.
981
*/
982
983
2.75k
attribute_hidden Rboolean inherits2(SEXP x, const char *what) {
984
2.75k
    if (OBJECT(x)) {
985
2.75k
  SEXP klass;
986
987
2.75k
  if(IS_S4_OBJECT(x))
988
0
      PROTECT(klass = R_data_class2(x));
989
2.75k
  else
990
2.75k
      PROTECT(klass = R_data_class(x, FALSE));
991
2.75k
  int nclass = length(klass);
992
2.75k
  for (int i = 0; i < nclass; i++) {
993
2.75k
      if (!strcmp(CHAR(STRING_ELT(klass, i)), what)) {
994
2.75k
    UNPROTECT(1);
995
2.75k
    return TRUE;
996
2.75k
      }
997
2.75k
  }
998
0
  UNPROTECT(1);
999
0
    }
1000
0
    return FALSE;
1001
2.75k
}
1002
1003
/* NOTE: Fast  inherits(x, what)    in ../include/Rinlinedfuns.h
1004
 * ----        ----------------- */
1005
/** C API for  R  inherits(x, what, which)
1006
 *
1007
 * @param x any R object
1008
 * @param what character vector
1009
 * @param which logical: "want vector result" ?
1010
 *
1011
 * @return if which is false, logical TRUE or FALSE
1012
 *     if which is true, integer vector of length(what) ..
1013
 */
1014
static SEXP inherits3(SEXP x, SEXP what, SEXP which)
1015
2.38M
{
1016
2.38M
    const void *vmax = vmaxget();
1017
2.38M
    SEXP klass, rval = R_NilValue /* -Wall */;
1018
1019
2.38M
    if(IS_S4_OBJECT(x))
1020
0
  PROTECT(klass = R_data_class2(x)); // -> := S4_extends( "class(x)" )
1021
2.38M
    else
1022
2.38M
  PROTECT(klass = R_data_class(x, FALSE));
1023
1024
2.38M
    if(!isString(what))
1025
0
  error(_("'what' must be a character vector "
1026
0
    "or an object with a nameOfClass() method"));
1027
2.38M
    int j, nwhat = LENGTH(what);
1028
1029
2.38M
    if( !isLogical(which) || (LENGTH(which) != 1) )
1030
0
  error(_("'which' must be a length 1 logical vector"));
1031
2.38M
    bool isvec = asRbool(which, R_NilValue);
1032
1033
2.38M
    if(isvec)
1034
0
  PROTECT(rval = allocVector(INTSXP, nwhat));
1035
1036
3.55M
    for(j = 0; j < nwhat; j++) {
1037
2.38M
  const char *ss = translateChar(STRING_ELT(what, j));
1038
2.38M
  int i = stringPositionTr(klass, ss);
1039
2.38M
  if (isvec)
1040
0
      INTEGER(rval)[j] = i+1; /* 0 when ss is not in klass */
1041
2.38M
  else if (i >= 0) {
1042
1.21M
      vmaxset(vmax);
1043
1.21M
      UNPROTECT(1);
1044
1.21M
      return mkTrue();
1045
1.21M
  }
1046
2.38M
    }
1047
1.16M
    vmaxset(vmax);
1048
1.16M
    if(!isvec) {
1049
1.16M
  UNPROTECT(1);
1050
1.16M
  return mkFalse();
1051
1.16M
    }
1052
0
    UNPROTECT(2);
1053
0
    return rval;
1054
1.16M
}
1055
1056
static R_INLINE SEXP nameOfClass(SEXP what, SEXP env)
1057
0
{
1058
0
    static SEXP call = NULL;
1059
0
    static SEXP Xsym = NULL;
1060
0
    if (call == NULL) {
1061
0
  Xsym = install("X");
1062
0
  call = R_ParseString("base::nameOfClass(X)");
1063
0
  R_PreserveObject(call);
1064
0
    }
1065
1066
0
    SEXP callenv = PROTECT(R_NewEnv(env, FALSE, 0));
1067
0
    defineVar(Xsym, what, callenv);
1068
0
    INCREMENT_NAMED(what);
1069
0
    SEXP name = eval(call, callenv);
1070
    /* could remove 'what' from callenv to drop REFCNT */
1071
0
    UNPROTECT(1); /* callenv */
1072
1073
0
    return name;
1074
0
}
1075
1076
attribute_hidden SEXP do_inherits(SEXP call, SEXP op, SEXP args, SEXP env)
1077
2.38M
{
1078
2.38M
    checkArity(op, args);
1079
1080
2.38M
    SEXP x = CAR(args);
1081
2.38M
    SEXP what = CADR(args);
1082
2.38M
    SEXP which = CADDR(args);
1083
1084
2.38M
    if (OBJECT(what) && TYPEOF(what) != STRSXP) {
1085
0
  SEXP name = nameOfClass(what, env);
1086
0
  if (name != R_NilValue) {
1087
0
      PROTECT(name);
1088
0
      SEXP val = inherits3(x, name, which);
1089
0
      UNPROTECT(1); /* name */
1090
0
      return val;
1091
0
  }
1092
  /* fall through */
1093
0
    }
1094
1095
2.38M
    return inherits3(x, what, which);
1096
2.38M
}
1097
1098
1099
/*
1100
   ==============================================================
1101
1102
     code from here on down is support for the methods package
1103
1104
   ==============================================================
1105
*/
1106
1107
/**
1108
 * Return the 0-based index of an is() match in a vector of class-name
1109
 * strings terminated by an empty string.  Returns -1 for no match.
1110
 *
1111
 * @param x  an R object, about which we want is(x, .) information.
1112
 * @param valid vector of possible matches terminated by an empty string.
1113
 * @param rho  the environment in which the class definitions exist.
1114
 *
1115
 * @return index of match or -1 for no match
1116
 */
1117
attribute_hidden
1118
int R_check_class_and_super(SEXP x, const char **valid, SEXP rho)
1119
0
{
1120
0
  if(isObject(x)) {
1121
0
    int ans;
1122
0
    SEXP clattr = getAttrib(x, R_ClassSymbol);
1123
0
    SEXP cl = PROTECT(asChar(clattr));
1124
0
    const char *class = CHAR(cl);
1125
0
    for (ans = 0; strlen(valid[ans]); ans++)
1126
0
  if (!strcmp(class, valid[ans])) {
1127
0
      UNPROTECT(1); /* cl */
1128
0
      return ans;
1129
0
  }
1130
    /* if not found directly, then look for a match among the nonvirtual
1131
       superclasses, possibly after finding the environment 'rho' in which
1132
       class(x) is defined */
1133
0
    if(IS_S4_OBJECT(x)) {
1134
0
  if (rho == NULL) {
1135
0
      SEXP pkg = getAttrib(clattr, R_PackageSymbol);
1136
0
      if (!isNull(pkg)) {
1137
0
    static SEXP meth_classEnv = NULL;
1138
0
    if(!meth_classEnv)
1139
0
        meth_classEnv = install(".classEnv");
1140
    /* FIXME: fails if 'methods' is not loaded */
1141
0
    SEXP clEnvCall = PROTECT(lang2(meth_classEnv, clattr));
1142
0
    rho = eval(clEnvCall, R_MethodsNamespace);
1143
0
    UNPROTECT(1); /* clEnvCall */
1144
0
    if(!isEnvironment(rho))
1145
0
        error(_("could not find correct environment; "
1146
0
          "please report!"));
1147
0
      } else
1148
0
    rho = R_GlobalEnv;
1149
0
  }
1150
0
  PROTECT(rho);
1151
0
  SEXP classExts, superCl, _call;
1152
0
  static SEXP s_contains = NULL, s_selectSuperCl = NULL;
1153
0
  if(!s_contains) {
1154
0
      s_contains      = install("contains");
1155
0
      s_selectSuperCl = install(".selectSuperClasses");
1156
0
  }
1157
0
  SEXP classDef = PROTECT(R_getClassDef(class));
1158
0
  PROTECT(classExts = R_do_slot(classDef, s_contains));
1159
  /* .selectSuperClasses(getClassDef(class)@contains,
1160
   *                     dropVirtual = TRUE, namesOnly = TRUE,
1161
   *                     directOnly = FALSE, simpleOnly = TRUE):
1162
   */
1163
0
  PROTECT(_call = lang6(s_selectSuperCl, classExts,
1164
0
            ScalarLogical(1), ScalarLogical(1),
1165
0
            ScalarLogical(0), ScalarLogical(1)));
1166
0
  superCl = eval(_call, rho);
1167
0
  UNPROTECT(3); /* _call, classExts, classDef */
1168
0
  PROTECT(superCl);
1169
0
  for(int i = 0; i < LENGTH(superCl); i++) {
1170
0
      const char *s_class = CHAR(STRING_ELT(superCl, i));
1171
0
      for (ans = 0; strlen(valid[ans]); ans++)
1172
0
    if (!strcmp(s_class, valid[ans])) {
1173
0
        UNPROTECT(3); /* superCl, rho, cl */
1174
0
        return ans;
1175
0
    }
1176
0
  }
1177
0
  UNPROTECT(2); /* superCl, rho */
1178
0
    }
1179
0
    UNPROTECT(1); /* cl */
1180
0
  } // only if isObject(x)
1181
0
  return -1;
1182
0
}
1183
1184
/**
1185
 * Return the 0-based index of an is() match in a vector of class-name
1186
 * strings terminated by an empty string.  Returns -1 for no match.
1187
 * Strives to find the correct environment() for is(), using .classEnv()
1188
 * (from \pkg{methods}).
1189
 *
1190
 * @param x  an R object, about which we want is(x, .) information.
1191
 * @param valid vector of possible matches terminated by an empty string.
1192
 *
1193
 * @return index of match or -1 for no match
1194
 */
1195
int R_check_class_etc(SEXP x, const char **valid)
1196
0
{
1197
0
    return R_check_class_and_super(x, valid, NULL);
1198
0
}
1199
1200
/* standardGeneric:  uses a pointer to R_standardGeneric, to be
1201
   initialized when the methods namespace is loaded,
1202
   via R_initMethodDispatch.
1203
*/
1204
static R_stdGen_ptr_t R_standardGeneric_ptr = 0;
1205
static SEXP dispatchNonGeneric(SEXP name, SEXP env, SEXP fdef);
1206
1.99M
#define NOT_METHODS_DISPATCH_PTR(ptr) (ptr == 0 || ptr == dispatchNonGeneric)
1207
1208
static
1209
R_stdGen_ptr_t R_get_standardGeneric_ptr(void)
1210
1.95M
{
1211
1.95M
    return R_standardGeneric_ptr;
1212
1.95M
}
1213
1214
/* Also called from R_initMethodDispatch in methods C code, which is
1215
   called when the methods namespace is loaded. */
1216
R_stdGen_ptr_t R_set_standardGeneric_ptr(R_stdGen_ptr_t val, SEXP envir)
1217
32
{
1218
32
    R_stdGen_ptr_t old = R_standardGeneric_ptr;
1219
32
    R_standardGeneric_ptr = val;
1220
32
    if(envir && !isNull(envir))
1221
32
  R_MethodsNamespace = envir;
1222
    /* just in case ... */
1223
32
    if(!R_MethodsNamespace)
1224
0
  R_MethodsNamespace = R_GlobalEnv;
1225
32
    return old;
1226
32
}
1227
1228
// R's .isMethodsDispatchOn() -> do_S4on() ->
1229
static SEXP R_isMethodsDispatchOn(SEXP onOff)
1230
0
{
1231
0
    R_stdGen_ptr_t old = R_get_standardGeneric_ptr();
1232
0
    int ival =  !NOT_METHODS_DISPATCH_PTR(old);
1233
0
    if(length(onOff) > 0) {
1234
0
  bool onOffValue = asRbool(onOff, R_NilValue);
1235
0
  if(onOffValue == NA_INTEGER)
1236
0
      error(_("'onOff' must be TRUE or FALSE"));
1237
0
  else if(onOffValue == FALSE)
1238
0
      R_set_standardGeneric_ptr(NULL, R_GlobalEnv);
1239
  // TRUE is not currently used
1240
0
  else if(NOT_METHODS_DISPATCH_PTR(old)) {
1241
      // so not already on
1242
      // This may not work correctly: the default arg is incorrect.
1243
0
      warning("R_isMethodsDispatchOn(TRUE) called -- may not work correctly");
1244
0
      SEXP call = PROTECT(lang1(install("initMethodDispatch")));
1245
0
      eval(call, R_MethodsNamespace); // only works with methods loaded
1246
0
      UNPROTECT(1);
1247
0
  }
1248
0
    }
1249
0
    return ScalarLogical(ival);
1250
0
}
1251
1252
/* simpler version for internal use, in attrib.c and print.c */
1253
attribute_hidden
1254
Rboolean isMethodsDispatchOn(void)
1255
41.8k
{
1256
41.8k
    return !NOT_METHODS_DISPATCH_PTR(R_standardGeneric_ptr);
1257
41.8k
}
1258
1259
1260
/* primitive for .isMethodsDispatchOn
1261
   This is generally called without an arg, but is call with
1262
   onOff=FALSE when package methods is detached/unloaded.
1263
1264
   It seems it is not currently called with onOff = TRUE (and would
1265
   not have worked prior to 3.0.2).
1266
*/
1267
attribute_hidden
1268
SEXP do_S4on(SEXP call, SEXP op, SEXP args, SEXP env)
1269
3.32k
{
1270
3.32k
    if(length(args) == 0) return ScalarLogical(isMethodsDispatchOn());
1271
0
    return R_isMethodsDispatchOn(CAR(args));
1272
3.32k
}
1273
1274
1275
static SEXP dispatchNonGeneric(SEXP name, SEXP env, SEXP fdef)
1276
0
{
1277
    /* dispatch the non-generic definition of `name'.  Used to trap
1278
       calls to standardGeneric during the loading of the methods package */
1279
0
    SEXP e, value, rho, fun, symbol;
1280
0
    RCNTXT *cptr;
1281
1282
    /* find a non-generic function */
1283
0
    symbol = installTrChar(asChar(name));
1284
0
    for(rho = ENCLOS(env); rho != R_EmptyEnv;
1285
0
  rho = ENCLOS(rho)) {
1286
0
  fun = R_findVarInFrame(rho, symbol);
1287
0
  if(fun == R_UnboundValue) continue;
1288
0
  switch(TYPEOF(fun)) {
1289
0
  case CLOSXP:
1290
0
      value = R_findVarInFrame(CLOENV(fun), R_dot_Generic);
1291
0
      if(value == R_UnboundValue) break;
1292
0
  case BUILTINSXP:  case SPECIALSXP:
1293
0
  default:
1294
      /* in all other cases, go on to the parent environment */
1295
0
      break;
1296
0
  }
1297
0
  fun = R_UnboundValue;
1298
0
    }
1299
0
    fun = SYMVALUE(symbol);
1300
0
    if(fun == R_UnboundValue)
1301
0
  error(_("unable to find a non-generic version of function \"%s\""),
1302
0
        translateChar(asChar(name)));
1303
0
    cptr = R_GlobalContext;
1304
    /* check this is the right context */
1305
0
    while (cptr != R_ToplevelContext) {
1306
0
  if (cptr->callflag & CTXT_FUNCTION )
1307
0
      if (cptr->cloenv == env)
1308
0
    break;
1309
0
  cptr = cptr->nextcontext;
1310
0
    }
1311
1312
0
    PROTECT(e = shallow_duplicate(R_syscall(0, cptr)));
1313
0
    SETCAR(e, fun);
1314
    /* evaluate a call the non-generic with the same arguments and from
1315
       the same environment as the call to the generic version */
1316
0
    value = eval(e, cptr->sysparent);
1317
0
    UNPROTECT(1);
1318
0
    return value;
1319
0
}
1320
1321
1322
static SEXP get_this_generic(SEXP args);
1323
1324
attribute_hidden SEXP do_standardGeneric(SEXP call, SEXP op, SEXP args, SEXP env)
1325
0
{
1326
0
    SEXP arg, value, fdef; R_stdGen_ptr_t ptr = R_get_standardGeneric_ptr();
1327
1328
0
    checkArity(op, args); /* set to -1 */
1329
0
    check1arg(args, call, "f");
1330
1331
0
    if(!ptr) {
1332
0
  warningcall(call,
1333
0
        _("'standardGeneric' called without 'methods' dispatch enabled (will be ignored)"));
1334
0
  R_set_standardGeneric_ptr(dispatchNonGeneric, NULL);
1335
0
  ptr = R_get_standardGeneric_ptr();
1336
0
    }
1337
1338
0
    arg = CAR(args);
1339
0
    if(!isValidStringF(arg))
1340
0
  errorcall(call,
1341
0
      _("argument to 'standardGeneric' must be a non-empty character string"));
1342
1343
0
    PROTECT(fdef = get_this_generic(args));
1344
1345
0
    if(isNull(fdef))
1346
0
  error(_("call to standardGeneric(\"%s\") apparently not from the body of that generic function"), translateChar(STRING_ELT(arg, 0)));
1347
1348
0
    value = (*ptr)(arg, env, fdef);
1349
1350
0
    UNPROTECT(1);
1351
0
    return value;
1352
0
}
1353
1354
static int maxMethodsOffset = 0, curMaxOffset;
1355
static Rboolean allowPrimitiveMethods = TRUE;
1356
typedef enum {NO_METHODS, NEEDS_RESET, HAS_METHODS, SUPPRESSED} prim_methods_t;
1357
1358
static prim_methods_t *prim_methods;
1359
static SEXP *prim_generics;
1360
static SEXP *prim_mlist;
1361
64
#define DEFAULT_N_PRIM_METHODS 100
1362
1363
// Called from methods package, ../library/methods/src/methods_list_dispatch.c
1364
SEXP R_set_prim_method(SEXP fname, SEXP op, SEXP code_vec, SEXP fundef,
1365
           SEXP mlist)
1366
32
{
1367
32
    const char *code_string;
1368
32
    const void *vmax = vmaxget();
1369
32
    if(!isValidString(code_vec))
1370
0
  error(_("argument '%s' must be a character string"), "code");
1371
32
    code_string = translateChar(asChar(code_vec));
1372
    /* with a NULL op, turns all primitive matching off or on (used to avoid possible infinite
1373
     recursion in methods computations*/
1374
32
    if(op == R_NilValue) {
1375
0
  SEXP value = allowPrimitiveMethods ? mkTrue() : mkFalse();
1376
0
  switch(code_string[0]) {
1377
0
  case 'c': case 'C':/* clear */
1378
0
      allowPrimitiveMethods = FALSE; break;
1379
0
  case 's': case 'S': /* set */
1380
0
      allowPrimitiveMethods = TRUE; break;
1381
0
  default: /* just report the current state */
1382
0
      break;
1383
0
  }
1384
0
  return value;
1385
0
    }
1386
32
    if (!isPrimitive(op)) {
1387
0
        SEXP internal = R_do_slot(op, install("internal"));
1388
0
        op = INTERNAL(installTrChar(asChar(internal)));
1389
0
        if (op == R_NilValue) {
1390
0
          error("'internal' slot does not name an internal function: %s",
1391
0
                CHAR(asChar(internal)));
1392
0
        }
1393
0
    }
1394
32
    do_set_prim_method(op, code_string, fundef, mlist);
1395
32
    vmaxset(vmax);
1396
32
    return fname;
1397
32
}
1398
1399
SEXP R_primitive_methods(SEXP op)
1400
0
{
1401
0
    int offset = PRIMOFFSET(op);
1402
0
    if(offset < 0 || offset > curMaxOffset)
1403
0
  return R_NilValue;
1404
0
    else {
1405
0
  SEXP value = prim_mlist[offset];
1406
0
  return value ? value : R_NilValue;
1407
0
    }
1408
0
}
1409
1410
SEXP R_primitive_generic(SEXP op)
1411
0
{
1412
0
    int offset = PRIMOFFSET(op);
1413
0
    if(offset < 0 || offset > curMaxOffset)
1414
0
  return R_NilValue;
1415
0
    else {
1416
0
  SEXP value = prim_generics[offset];
1417
0
  return value ? value : R_NilValue;
1418
0
    }
1419
0
}
1420
1421
// used in the methods package, but also here
1422
SEXP do_set_prim_method(SEXP op, const char *code_string, SEXP fundef,
1423
      SEXP mlist)
1424
32
{
1425
32
    int offset = 0;
1426
32
    prim_methods_t code = NO_METHODS; /* -Wall */
1427
32
    SEXP value;
1428
32
    Rboolean errorcase = FALSE;
1429
32
    switch(code_string[0]) {
1430
0
    case 'c': /* clear */
1431
0
  code = NO_METHODS; break;
1432
32
    case 'r': /* reset */
1433
32
  code = NEEDS_RESET; break;
1434
0
    case 's': /* set or suppress */
1435
0
  switch(code_string[1]) {
1436
0
  case 'e': code = HAS_METHODS; break;
1437
0
  case 'u': code = SUPPRESSED; break;
1438
0
  default: errorcase = TRUE;
1439
0
  }
1440
0
  break;
1441
0
    default:
1442
0
  errorcase = TRUE;
1443
32
    }
1444
32
    if(errorcase) {
1445
0
  error(_("invalid primitive methods code (\"%s\"): should be \"clear\", \"reset\", \"set\", or \"suppress\""), code_string);
1446
0
  return R_NilValue;
1447
0
    }
1448
32
    switch(TYPEOF(op)) {
1449
32
    case BUILTINSXP: case SPECIALSXP:
1450
32
  offset = PRIMOFFSET(op);
1451
32
  break;
1452
0
    default:
1453
0
  error(_("invalid object: must be a primitive function"));
1454
32
    }
1455
32
    if(offset >= maxMethodsOffset) {
1456
32
  int n;
1457
32
  n = offset + 1;
1458
32
  if(n < DEFAULT_N_PRIM_METHODS)
1459
32
      n = DEFAULT_N_PRIM_METHODS;
1460
32
  if(n < 2*maxMethodsOffset)
1461
0
      n = 2 * maxMethodsOffset;
1462
32
  if(prim_methods) {
1463
0
      int i;
1464
1465
0
      prim_methods  = R_Realloc(prim_methods,  n, prim_methods_t);
1466
0
      prim_generics = R_Realloc(prim_generics, n, SEXP);
1467
0
      prim_mlist    = R_Realloc(prim_mlist,     n, SEXP);
1468
1469
      /* R_Realloc does not clear the added memory, hence: */
1470
0
      for (i = maxMethodsOffset ; i < n ; i++) {
1471
0
    prim_methods[i]  = NO_METHODS;
1472
0
    prim_generics[i] = NULL;
1473
0
    prim_mlist[i]  = NULL;
1474
0
      }
1475
0
  }
1476
32
  else {
1477
32
      prim_methods  = R_Calloc(n, prim_methods_t);
1478
32
      prim_generics = R_Calloc(n, SEXP);
1479
32
      prim_mlist    = R_Calloc(n, SEXP);
1480
32
  }
1481
32
  maxMethodsOffset = n;
1482
32
    }
1483
32
    if(offset > curMaxOffset)
1484
32
  curMaxOffset = offset;
1485
32
    prim_methods[offset] = code;
1486
    /* store a preserved pointer to the generic function if there is not
1487
       one there currently.  Unpreserve it if no more methods, but don't
1488
       replace it otherwise:  the generic definition is not allowed to
1489
       change while it's still defined! (the stored methods list can,
1490
       however) */
1491
32
    value = prim_generics[offset];
1492
32
    if(code == SUPPRESSED) {} /* leave the structure alone */
1493
32
    else if(code == NO_METHODS && prim_generics[offset]) {
1494
0
  R_ReleaseObject(prim_generics[offset]);
1495
0
  prim_generics[offset] = 0;
1496
0
  prim_mlist[offset] = 0;
1497
0
    }
1498
32
    else if(fundef && !isNull(fundef) && !prim_generics[offset]) {
1499
32
  if(TYPEOF(fundef) != CLOSXP)
1500
0
      error(_("the formal definition of a primitive generic must be a function object (got type '%s')"),
1501
0
      R_typeToChar(fundef));
1502
32
  R_PreserveObject(fundef);
1503
32
  prim_generics[offset] = fundef;
1504
32
    }
1505
32
    if(code == HAS_METHODS) {
1506
0
  if(!mlist  || isNull(mlist)) {
1507
      /* turning methods back on after a SUPPRESSED */
1508
0
  } else {
1509
0
      if(prim_mlist[offset])
1510
0
    R_ReleaseObject(prim_mlist[offset]);
1511
0
      R_PreserveObject(mlist);
1512
0
      prim_mlist[offset] = mlist;
1513
0
  }
1514
0
    }
1515
32
    return value;
1516
32
}
1517
1518
static SEXP get_primitive_methods(SEXP op, SEXP rho)
1519
0
{
1520
0
    SEXP f, e, val;
1521
0
    int nprotect = 0;
1522
0
    f = PROTECT(allocVector(STRSXP, 1));  nprotect++;
1523
0
    SET_STRING_ELT(f, 0, mkChar(PRIMNAME(op)));
1524
0
    PROTECT(e = allocVector(LANGSXP, 2)); nprotect++;
1525
0
    SETCAR(e, install("getGeneric"));
1526
0
    val = CDR(e); SETCAR(val, f);
1527
0
    val = eval(e, rho);
1528
    /* a rough sanity check that this looks like a generic function */
1529
0
    if(TYPEOF(val) != CLOSXP || !IS_S4_OBJECT(val))
1530
0
  error(_("object returned as generic function \"%s\" does not appear to be one"), PRIMNAME(op));
1531
0
    UNPROTECT(nprotect);
1532
0
    return CLOENV(val);
1533
0
}
1534
1535
1536
/* get the generic function, defined to be the function definition for
1537
the call to standardGeneric(), or for primitives, passed as the second
1538
argument to standardGeneric.
1539
*/
1540
static SEXP get_this_generic(SEXP args)
1541
0
{
1542
0
    static SEXP gen_name = NULL;
1543
0
    RCNTXT *cptr;
1544
0
    SEXP fname;
1545
1546
    /* a second argument to the call, if any, is taken as the function */
1547
0
    if(CDR(args) != R_NilValue)
1548
0
  return CAR(CDR(args));
1549
0
    if(!gen_name)
1550
0
  gen_name = install("generic");
1551
0
    fname = STRING_ELT(CAR(args), 0); /* type and length checked by caller */
1552
1553
    /* check for a matching "generic" slot */
1554
0
    for(cptr = R_GlobalContext; cptr != NULL; cptr = cptr->nextcontext)
1555
0
  if((cptr->callflag & CTXT_FUNCTION) && isObject(cptr->callfun)) {
1556
0
      SEXP generic = getAttrib(cptr->callfun, gen_name);
1557
0
      if(isValidString(generic) && Seql(fname, STRING_ELT(generic, 0)))
1558
    /* not duplicating/marking immutable, used read-only */
1559
0
    return cptr->callfun;
1560
0
  }
1561
0
    return R_NilValue;
1562
0
}
1563
1564
/* Could there be methods for this op?  Checks
1565
   only whether methods are currently being dispatched and, if so,
1566
   whether methods are currently defined for this op. */
1567
attribute_hidden
1568
Rboolean R_has_methods(SEXP op)
1569
1.95M
{
1570
1.95M
    R_stdGen_ptr_t ptr = R_get_standardGeneric_ptr(); int offset;
1571
1.95M
    if(NOT_METHODS_DISPATCH_PTR(ptr))
1572
2.97k
  return(FALSE);
1573
1.94M
    if(!op || TYPEOF(op) == CLOSXP) /* except for primitives, just test for the package */
1574
0
  return(TRUE);
1575
1.94M
    if(!allowPrimitiveMethods) /* all primitives turned off by a call to R_set_prim */
1576
0
  return FALSE;
1577
1.94M
    offset = PRIMOFFSET(op);
1578
1.94M
    if(offset > curMaxOffset || prim_methods[offset] == NO_METHODS
1579
0
       || prim_methods[offset] == SUPPRESSED)
1580
1.94M
  return(FALSE);
1581
0
    return(TRUE);
1582
1.94M
}
1583
1584
static SEXP deferred_default_object;
1585
1586
SEXP R_deferred_default_method(void)
1587
0
{
1588
0
    if(!deferred_default_object)
1589
0
  deferred_default_object = install("__Deferred_Default_Marker__");
1590
0
    return(deferred_default_object);
1591
0
}
1592
1593
1594
static R_stdGen_ptr_t quick_method_check_ptr = NULL;
1595
void R_set_quick_method_check(R_stdGen_ptr_t value)
1596
32
{
1597
32
    quick_method_check_ptr = value;
1598
32
}
1599
1600
/* try to dispatch the formal method for this primitive op, by calling
1601
   the stored generic function corresponding to the op.  Requires that
1602
   the methods be set up to return a special object rather than trying
1603
   to evaluate the default (which would get us into a loop). */
1604
1605
/* called from DispatchOrEval, DispatchGroup, do_matprod
1606
   When called from the first the arguments have been enclosed in
1607
   promises, but not from the other two: there all the arguments have
1608
   already been evaluated.
1609
 */
1610
attribute_hidden SEXP
1611
R_possible_dispatch(SEXP call, SEXP op, SEXP args, SEXP rho,
1612
        Rboolean promisedArgs)
1613
0
{
1614
0
    SEXP fundef, value, mlist=R_NilValue, s, a, b, suppliedvars;
1615
0
    int offset;
1616
0
    prim_methods_t current;
1617
0
    offset = PRIMOFFSET(op);
1618
0
    if(offset < 0 || offset > curMaxOffset)
1619
0
  error(_("invalid primitive operation given for dispatch"));
1620
0
    current = prim_methods[offset];
1621
0
    if(current == NO_METHODS || current == SUPPRESSED)
1622
0
  return(NULL);
1623
    /* check that the methods for this function have been set */
1624
0
    if(current == NEEDS_RESET) {
1625
  /* get the methods and store them in the in-core primitive
1626
     method table.  The entries will be preserved via
1627
     R_preserveobject, so later we can just grab mlist from
1628
     prim_mlist */
1629
0
  do_set_prim_method(op, "suppressed", R_NilValue, mlist);
1630
0
  PROTECT(mlist = get_primitive_methods(op, rho));
1631
0
  do_set_prim_method(op, "set", R_NilValue, mlist);
1632
0
  current = prim_methods[offset]; /* as revised by do_set_prim_method */
1633
0
  UNPROTECT(1);
1634
0
    }
1635
0
    mlist = prim_mlist[offset];
1636
0
    if(mlist && !isNull(mlist)
1637
0
       && quick_method_check_ptr) {
1638
0
  value = (*quick_method_check_ptr)(args, mlist, op);
1639
0
  if(isPrimitive(value))
1640
0
      return(NULL);
1641
0
  if(isFunction(value)) {
1642
0
            if (inherits(value, "internalDispatchMethod")) {
1643
0
                return(NULL);
1644
0
            }
1645
0
            PROTECT(suppliedvars = list1(mkString(PRIMNAME(op))));
1646
0
            SET_TAG(suppliedvars, R_dot_Generic);
1647
      /* found a method, call it with promised args */
1648
0
      if(!promisedArgs) {
1649
0
    PROTECT(s = promiseArgs(CDR(call), rho));
1650
0
    if (length(s) != length(args)) error(_("dispatch error"));
1651
0
    for (a = args, b = s; a != R_NilValue; a = CDR(a), b = CDR(b))
1652
0
        IF_PROMSXP_SET_PRVALUE(CAR(b), CAR(a));
1653
0
    value =  applyClosure(call, value, s, rho, suppliedvars, TRUE);
1654
0
    UNPROTECT(2);
1655
0
    return value;
1656
0
      } else {
1657
    /* INC/DEC of REFCNT needed for non-tracking args */
1658
0
    for (SEXP a = args; a != R_NilValue; a = CDR(a))
1659
0
        INCREMENT_REFCNT(CAR(a));
1660
0
    value = applyClosure(call, value, args, rho,
1661
0
             suppliedvars, FALSE);
1662
0
    for (SEXP a = args; a != R_NilValue; a = CDR(a))
1663
0
        DECREMENT_REFCNT(CAR(a));
1664
0
                UNPROTECT(1);
1665
0
                return value;
1666
0
            }
1667
0
  }
1668
  /* else, need to perform full method search */
1669
0
    }
1670
0
    fundef = prim_generics[offset];
1671
0
    if(!fundef || TYPEOF(fundef) != CLOSXP)
1672
0
  error(_("primitive function \"%s\" has been set for methods but no generic function supplied"),
1673
0
        PRIMNAME(op));
1674
    /* To do:  arrange for the setting to be restored in case of an
1675
       error in method search */
1676
0
    if(!promisedArgs) {
1677
0
  PROTECT(s = promiseArgs(CDR(call), rho));
1678
0
  if (length(s) != length(args)) error(_("dispatch error"));
1679
0
  for (a = args, b = s; a != R_NilValue; a = CDR(a), b = CDR(b))
1680
0
      IF_PROMSXP_SET_PRVALUE(CAR(b), CAR(a));
1681
0
  value = applyClosure(call, fundef, s, rho, R_NilValue, TRUE);
1682
0
  UNPROTECT(1);
1683
0
    } else {
1684
  /* INC/DEC of REFCNT needed for non-tracking args */
1685
0
  for (SEXP a = args; a != R_NilValue; a = CDR(a))
1686
0
      INCREMENT_REFCNT(CAR(a));
1687
0
  value = applyClosure(call, fundef, args, rho, R_NilValue, FALSE);
1688
0
  for (SEXP a = args; a != R_NilValue; a = CDR(a))
1689
0
      DECREMENT_REFCNT(CAR(a));
1690
0
    }
1691
0
    prim_methods[offset] = current;
1692
0
    if(value == deferred_default_object)
1693
0
  return NULL;
1694
0
    else
1695
0
  return value;
1696
0
}
1697
1698
SEXP R_do_MAKE_CLASS(const char *what)
1699
0
{
1700
0
    static SEXP s_getClass = NULL;
1701
0
    SEXP e, call;
1702
0
    if(!what)
1703
0
  error(_("C level MAKE_CLASS macro called with NULL string pointer"));
1704
0
    if(!s_getClass) s_getClass = install("getClass");
1705
0
    PROTECT(call = allocVector(LANGSXP, 2));
1706
0
    SETCAR(call, s_getClass);
1707
0
    SETCAR(CDR(call), mkString(what));
1708
0
    e = eval(call, R_MethodsNamespace);
1709
0
    UNPROTECT(1);
1710
0
    return(e);
1711
0
}
1712
1713
// similar, but gives NULL instead of an error for a non-existing class
1714
// and 'what' is never checked
1715
attribute_hidden SEXP R_getClassDef_R(SEXP what)
1716
0
{
1717
0
    static SEXP s_getClassDef = NULL;
1718
0
    if(!s_getClassDef) s_getClassDef = install("getClassDef");
1719
0
    if(!isMethodsDispatchOn()) error(_("'methods' package not yet loaded"));
1720
0
    SEXP call = PROTECT(lang2(s_getClassDef, what));
1721
0
    SEXP e = eval(call, R_MethodsNamespace);
1722
0
    UNPROTECT(1);
1723
0
    return(e);
1724
0
}
1725
1726
SEXP R_getClassDef(const char *what)
1727
0
{
1728
0
    if(!what)
1729
0
  error(_("R_getClassDef(.) called with NULL string pointer"));
1730
0
    SEXP s = PROTECT(mkString(what));
1731
0
    SEXP ans = R_getClassDef_R(s);
1732
0
    UNPROTECT(1); /* s */
1733
0
    return ans;
1734
0
}
1735
1736
attribute_hidden Rboolean R_isVirtualClass(SEXP class_def, SEXP env)
1737
0
{
1738
0
    if(!isMethodsDispatchOn()) return(FALSE);
1739
0
    static SEXP isVCl_sym = NULL;
1740
0
    if(!isVCl_sym) isVCl_sym = install("isVirtualClass");
1741
0
    SEXP call = PROTECT(lang2(isVCl_sym, class_def));
1742
0
    SEXP e = PROTECT(eval(call, env));
1743
    // return(LOGICAL(e)[0]);
1744
    // more cautious:
1745
0
    Rboolean ans = (asLogical(e) == TRUE);
1746
0
    UNPROTECT(2); /* call, e */
1747
0
    return ans;
1748
0
}
1749
1750
attribute_hidden Rboolean R_extends(SEXP class1, SEXP class2, SEXP env)
1751
0
{
1752
0
    if(!isMethodsDispatchOn()) return(FALSE);
1753
0
    static SEXP extends_sym = NULL;
1754
0
    if(!extends_sym) extends_sym = install("extends");
1755
0
    SEXP call = PROTECT(lang3(extends_sym, class1, class2));
1756
0
    SEXP e = PROTECT(eval(call, env));
1757
    // return(LOGICAL(e)[0]);
1758
    // more cautious:
1759
0
    Rboolean ans = (asLogical(e) == TRUE);
1760
0
    UNPROTECT(2); /* call, e */
1761
0
    return ans;
1762
0
}
1763
1764
/* in Rinternals.h */
1765
SEXP R_do_new_object(SEXP class_def)
1766
0
{
1767
0
    static SEXP s_virtual = NULL, s_prototype, s_className;
1768
0
    SEXP e, value;
1769
0
    const void *vmax = vmaxget();
1770
0
    if(!s_virtual) {
1771
0
  s_virtual = install("virtual");
1772
0
  s_prototype = install("prototype");
1773
0
  s_className = install("className");
1774
0
    }
1775
0
    if(!class_def)
1776
0
  error(_("C level NEW macro called with null class definition pointer"));
1777
0
    e = R_do_slot(class_def, s_virtual);
1778
0
    if(asLogical(e) != 0)  { /* includes NA, TRUE, or anything other than FALSE */
1779
0
  e = R_do_slot(class_def, s_className);
1780
0
  error(_("trying to generate an object from a virtual class (\"%s\")"),
1781
0
        translateChar(asChar(e)));
1782
0
    }
1783
0
    PROTECT(e = R_do_slot(class_def, s_className));
1784
0
    PROTECT(value = duplicate(R_do_slot(class_def, s_prototype)));
1785
0
    bool xDataType = TYPEOF(value) == ENVSXP || TYPEOF(value) == SYMSXP ||
1786
0
  TYPEOF(value) == EXTPTRSXP;
1787
0
    if((TYPEOF(value) == OBJSXP || getAttrib(e, R_PackageSymbol) != R_NilValue) &&
1788
0
       !xDataType)
1789
0
    {
1790
0
  setAttrib(value, R_ClassSymbol, e);
1791
0
  SET_S4_OBJECT(value);
1792
0
    }
1793
0
    UNPROTECT(2); /* value, e */
1794
0
    vmaxset(vmax);
1795
0
    return value;
1796
0
}
1797
1798
attribute_hidden Rboolean R_seemsOldStyleS4Object(SEXP object)
1799
42
{
1800
42
    SEXP klass;
1801
42
    if(!isObject(object) || IS_S4_OBJECT(object)) return FALSE;
1802
    /* We want to know about S4SXPs with no S4 bit */
1803
    /* if(TYPEOF(object) == S4SXP) return FALSE; */
1804
0
    klass = getAttrib(object, R_ClassSymbol);
1805
0
    return (klass != R_NilValue && LENGTH(klass) == 1 &&
1806
0
      getAttrib(klass, R_PackageSymbol) != R_NilValue) ? TRUE: FALSE;
1807
42
}
1808
1809
// a bare object of type "object" (OBJSXP without the S4 bit), as used e.g. by S7
1810
attribute_hidden SEXP do_objsxp(SEXP call, SEXP op, SEXP args, SEXP env)
1811
0
{
1812
0
    checkArity(op, args);
1813
0
    return R_allocObject();
1814
0
}
1815
1816
attribute_hidden SEXP do_setS4Object(SEXP call, SEXP op, SEXP args, SEXP env)
1817
0
{
1818
0
    checkArity(op, args);
1819
0
    SEXP object = CAR(args);
1820
0
    Rboolean flag = asRbool(CADR(args), call);
1821
0
    int complete = asInteger(CADDR(args));
1822
0
    if(length(CADR(args)) != 1 || flag == NA_INTEGER)
1823
0
  error("invalid '%s' argument", "flag");
1824
0
    if(complete == NA_INTEGER)
1825
0
  error("invalid '%s' argument", "complete");
1826
0
    if(flag == IS_S4_OBJECT(object))
1827
0
  return object;
1828
0
    else
1829
0
      return asS4(object, flag, complete);
1830
0
}
1831
1832
#ifdef UNUSED
1833
SEXP R_get_primname(SEXP object)
1834
{
1835
    SEXP f;
1836
    if(TYPEOF(object) != BUILTINSXP && TYPEOF(object) != SPECIALSXP)
1837
  error("'R_get_primname' called on a non-primitive");
1838
    PROTECT(f = allocVector(STRSXP, 1));
1839
    SET_STRING_ELT(f, 0, mkChar(PRIMNAME(object)));
1840
    UNPROTECT(1);
1841
    return f;
1842
}
1843
#endif
1844
1845
// in Rinternals.h
1846
Rboolean isS4(SEXP s)
1847
6.53k
{
1848
6.53k
    return IS_S4_OBJECT(s);
1849
6.53k
}
1850
1851
// in Rinternals.h
1852
SEXP asS4(SEXP s, Rboolean flag, int complete)
1853
0
{
1854
0
    if(flag == IS_S4_OBJECT(s))
1855
0
  return s;
1856
0
    PROTECT(s);
1857
0
    if(MAYBE_SHARED(s)) {
1858
0
  s = shallow_duplicate(s);
1859
0
  UNPROTECT(1);
1860
0
  PROTECT(s);
1861
0
    }
1862
0
    if(flag) SET_S4_OBJECT(s);
1863
0
    else {
1864
0
  if(complete) {
1865
0
      SEXP value;
1866
      /* TENTATIVE:  how much does this change? */
1867
0
      if((value = R_getS4DataSlot(s, ANYSXP))
1868
0
         != R_NilValue && !IS_S4_OBJECT(value)) {
1869
0
        UNPROTECT(1);
1870
0
        return value;
1871
0
      }
1872
      /* else no plausible S3 object*/
1873
0
      else if(complete == 1) /* ordinary case (2, for conditional) */
1874
0
        error(_("object of class \"%s\" does not correspond to a valid S3 object"),
1875
0
          CHAR(STRING_ELT(R_data_class(s, FALSE), 0)));
1876
0
      else {
1877
0
    UNPROTECT(1);
1878
0
    return s; /*  unchanged */
1879
0
      }
1880
0
  }
1881
0
  UNSET_S4_OBJECT(s);
1882
0
    }
1883
0
    UNPROTECT(1);
1884
0
    return s;
1885
0
}