CXXR (C++ R) API
BuiltInFunction.h
Go to the documentation of this file.
1 /*CXXR $Id: BuiltInFunction.h 1390 2013-06-11 14:41:41Z arr $
2  *CXXR
3  *CXXR This file is part of CXXR, a project to refactor the R interpreter
4  *CXXR into C++. It may consist in whole or in part of program code and
5  *CXXR documentation taken from the R project itself, incorporated into
6  *CXXR CXXR (and possibly MODIFIED) under the terms of the GNU General Public
7  *CXXR Licence.
8  *CXXR
9  *CXXR CXXR is Copyright (C) 2008-13 Andrew R. Runnalls, subject to such other
10  *CXXR copyrights and copyright restrictions as may be stated below.
11  *CXXR
12  *CXXR CXXR is not part of the R project, and bugs and other issues should
13  *CXXR not be reported via r-bugs or other R project channels; instead refer
14  *CXXR to the CXXR website.
15  *CXXR */
16 
17 /*
18  * R : A Computer Language for Statistical Data Analysis
19  * Copyright (C) 1995, 1996 Robert Gentleman and Ross Ihaka
20  * Copyright (C) 1999-2006 The R Development Core Team.
21  * Andrew Runnalls (C) 2007
22  *
23  * This program is free software; you can redistribute it and/or modify
24  * it under the terms of the GNU General Public License as published by
25  * the Free Software Foundation; either version 2.1 of the License, or
26  * (at your option) any later version.
27  *
28  * This program is distributed in the hope that it will be useful,
29  * but WITHOUT ANY WARRANTY; without even the implied warranty of
30  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31  * GNU Lesser General Public License for more details.
32  *
33  * You should have received a copy of the GNU General Public License
34  * along with this program; if not, a copy is available at
35  * http://www.r-project.org/Licenses/
36  */
37 
42 #ifndef BUILTINFUNCTION_H
43 #define BUILTINFUNCTION_H
44 
45 #include "CXXR/FunctionBase.h"
46 
47 #ifdef __cplusplus
48 
49 #include <map>
50 #include <boost/serialization/nvp.hpp>
51 
52 #include "CXXR/ArgList.hpp"
53 #include "CXXR/Environment.h"
54 #include "CXXR/Expression.h"
55 
56 extern "C" {
57 #endif
58 
63  typedef SEXP (*CCODE)(SEXP, SEXP, SEXP, SEXP);
64 
65 #ifdef __cplusplus
66 } // extern "C"
67 
68 namespace CXXR {
82  class BuiltInFunction : public FunctionBase {
83  public:
86  enum Kind {
87  PP_INVALID = 0,
88  PP_ASSIGN = 1,
89  PP_ASSIGN2 = 2,
90  PP_BINARY = 3,
91  PP_BINARY2 = 4,
92  PP_BREAK = 5,
93  PP_CURLY = 6,
94  PP_FOR = 7,
95  PP_FUNCALL = 8,
96  PP_FUNCTION = 9,
97  PP_IF = 10,
98  PP_NEXT = 11,
99  PP_PAREN = 12,
100  PP_RETURN = 13,
101  PP_SUBASS = 14,
102  PP_SUBSET = 15,
103  PP_WHILE = 16,
104  PP_UNARY = 17,
105  PP_DOLLAR = 18,
106  PP_FOREIGN = 19,
107  PP_REPEAT = 20
108  };
109 
112  enum Precedence {
113  PREC_FN = 0,
114  PREC_LEFT = 1,
115  PREC_EQ = 2,
116  PREC_RIGHT = 3,
117  PREC_TILDE = 4,
118  PREC_OR = 5,
119  PREC_AND = 6,
120  PREC_NOT = 7,
121  PREC_COMPARE = 8,
122  PREC_SUM = 9,
123  PREC_PROD = 10,
124  PREC_PERCENT = 11,
125  PREC_COLON = 12,
126  PREC_SIGN = 13,
127  PREC_POWER = 14,
128  PREC_DOLLAR = 15,
129  PREC_NS = 16,
130  PREC_SUBSET = 17
131  };
132 
139  int arity() const
140  {
141  return s_function_table[m_offset].arity;
142  }
143 
157  void checkNumArgs(const PairList* args, const Expression* call) const;
158 
164  CCODE function() const
165  {
166  return m_function;
167  }
168 
175  Kind kind() const
176  {
177  return s_function_table[m_offset].gram.kind;
178  }
179 
184  const char* name() const
185  {
186  return s_function_table[m_offset].name;
187  }
188 
209  static BuiltInFunction* obtain(const std::string& name);
210 
215  unsigned int offset() const
216  {
217  return m_offset;
218  }
219 
225  {
226  return s_function_table[m_offset].gram.precedence;
227  }
228 
238  int printHandling() const
239  {
240  return m_result_printing_mode;
241  }
242 
247  bool rightAssociative() const
248  {
249  return s_function_table[m_offset].gram.rightassoc;
250  }
251 
256  static const char* staticTypeName()
257  {
258  return "(builtin or special)";
259  }
260 
271  unsigned int variant() const
272  {
273  return s_function_table[m_offset].variant;
274  }
275 
281  bool viaDotInternal() const
282  {
283  return (s_function_table[m_offset].flags%100)/10 == 1;
284  }
285 
286  // Virtual function of RObject:
287  const char* typeName() const;
288 
289  // Virtual function of FunctionBase:
290  RObject* apply(ArgList* arglist, Environment* env,
291  const Expression* call) const;
292  private:
293  friend class boost::serialization::access;
294  friend class SchwarzCounter<BuiltInFunction>;
295 
296  // 'Pretty-print' information:
297  struct PPinfo {
298  Kind kind;
300  unsigned int rightassoc;
301  };
302 
303  struct TableEntry {
304  const char* name; // name of function
305  CCODE cfun; // pointer to relevant do_xxx function
306  unsigned int variant; // used to select alternative
307  // behaviours within the do_xxx
308  // function
309  unsigned int flags; // misc flags: see names.cpp
310  int arity; // function arity; -1 means 'any'
311  PPinfo gram; // 'pretty-print' information
312  };
313 
314  // SOFT_ON signifies that result printing should be enabled
315  // before calling m_function, but that if m_function disables
316  // result printing, this should not be overridden.
317  enum ResultPrintingMode {FORCE_ON = 0, FORCE_OFF, SOFT_ON};
318 
319  // Actually an array:
320  static TableEntry* s_function_table;
321 
322  // Mapping from function names to pointers to BuiltInFunction
323  // objects:
324  typedef std::map<std::string, BuiltInFunction*> map;
325  static map* s_cache;
326 
327  int m_offset;
328  CCODE m_function;
329  ResultPrintingMode m_result_printing_mode;
330  bool m_transparent; // if true, do not create a
331  // FunctionContext when this function is
332  // applied.
333 
334  // This default constructor is used only during (boost)
335  // deserialisation, and constructs a bodged-up temporary
336  // object, with m_offset set negative to signify that this is
337  // a deserialisation proxy.
338 
339  // (The argument to the FunctionBase base-class constructor is
340  // arbitrary, but will not be used during the lifetime of this
341  // temporary object.)
342  BuiltInFunction()
343  : FunctionBase(BUILTINSXP), m_offset(-1), m_function(0)
344  {}
345 
353  BuiltInFunction(unsigned int offset);
354 
355  // Declared private to ensure that BuiltInFunction objects are
356  // allocated only using 'new'.
357  ~BuiltInFunction();
358 
359  static void cleanup();
360 
369  static int indexInTable(const char* name);
370 
371  // Put primitive functions into the base environment, and
372  // internal functions into the DotInternalTable:
373  static void initialize();
374 
375  // Invoke the encapsulated function:
376  RObject* invoke(Environment* env, const ArgList* arglist,
377  const Expression* call) const
378  {
379  return m_function(const_cast<Expression*>(call),
380  const_cast<BuiltInFunction*>(this),
381  const_cast<PairList*>(arglist->list()), env);
382  }
383 
384  template<class Archive>
385  void load(Archive & ar, const unsigned int version);
386 
397  static void missingArgumentError(const BuiltInFunction* func,
398  const PairList* args,
399  unsigned int index);
400 
401  template<class Archive>
402  void save(Archive & ar, const unsigned int version) const;
403 
404  // Fields not serialised here are set up by the constructor:
405  template <class Archive>
406  void serialize(Archive& ar, const unsigned int version) {
407  boost::serialization::split_member(ar, *this, version);
408  }
409  };
410 } // namespace CXXR
411 
412 BOOST_CLASS_EXPORT_KEY(CXXR::BuiltInFunction)
413 
414 // Force Environment and Symbol classes to be initialised first:
415 #include "CXXR/Environment.h"
416 
417 namespace {
419 }
420 
421 // ***** Implementation of non-inlined templated members *****
422 
423 template<class Archive>
424 void CXXR::BuiltInFunction::load(Archive& ar, const unsigned int version)
425 {
426  // This will only ever be applied to a 'temporary' BuiltInFunction
427  // created by the default constructor.
428  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(FunctionBase);
429  std::string namestr;
430  ar >> boost::serialization::make_nvp("name", namestr);
431  S11nScope::defineRelocation(this, obtain(namestr));
432 }
433 
434 template<class Archive>
435 void CXXR::BuiltInFunction::save(Archive& ar, const unsigned int version) const
436 {
437  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(FunctionBase);
438  std::string namestr(name());
439  ar << boost::serialization::make_nvp("name", namestr);
440 }
441 
442 // Old-style accessor functions. Get rid of these in due course.
443 
444 inline int PRIMARITY(SEXP x)
445 {
446  using namespace CXXR;
447  BuiltInFunction& bif = *SEXP_downcast<BuiltInFunction*>(x);
448  return bif.arity();
449 }
450 
451 inline CCODE PRIMFUN(SEXP x)
452 {
453  using namespace CXXR;
454  BuiltInFunction& bif = *SEXP_downcast<BuiltInFunction*>(x);
455  return bif.function();
456 }
457 
458 inline int PRIMINTERNAL(SEXP x)
459 {
460  using namespace CXXR;
461  BuiltInFunction& bif = *SEXP_downcast<BuiltInFunction*>(x);
462  return bif.viaDotInternal();
463 }
464 
465 inline int PRIMPRINT(SEXP x)
466 {
467  using namespace CXXR;
468  BuiltInFunction& bif = *SEXP_downcast<BuiltInFunction*>(x);
469  return bif.printHandling();
470 }
471 
472 extern "C" {
473 #endif
474 
475 #ifndef __cplusplus
476  const char* PRIMNAME(SEXP x);
477 #else
478 inline const char* PRIMNAME(SEXP x)
479 {
480  using namespace CXXR;
481  BuiltInFunction& bif = *SEXP_downcast<BuiltInFunction*>(x);
482  return bif.name();
483 }
484 #endif
485 
492 #ifndef __cplusplus
493  int PRIMOFFSET(SEXP x);
494 #else
495  inline int PRIMOFFSET(SEXP x)
496  {
497  using namespace CXXR;
498  BuiltInFunction& bif = *SEXP_downcast<BuiltInFunction*>(x);
499  return bif.offset();
500  }
501 #endif
502 
503 #ifndef __cplusplus
504  unsigned int PRIMVAL(SEXP x);
505 #else
506 inline unsigned int PRIMVAL(SEXP x)
507 {
508  using namespace CXXR;
509  BuiltInFunction& bif = *SEXP_downcast<BuiltInFunction*>(x);
510  return bif.variant();
511 }
512 #endif
513 
514 #ifdef __cplusplus
515 }
516 #endif
517 
518 #endif /* BUILTINFUNCTION_H */