CXXR (C++ R)
Symbol.h
Go to the documentation of this file.
1 /*CXXR $Id: Symbol.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  *
22  * This program is free software; you can redistribute it and/or modify
23  * it under the terms of the GNU General Public License as published by
24  * the Free Software Foundation; either version 2.1 of the License, or
25  * (at your option) any later version.
26  *
27  * This program is distributed in the hope that it will be useful,
28  * but WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30  * GNU Lesser General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, a copy is available at
34  * http://www.r-project.org/Licenses/
35  */
36 
41 #ifndef RSYMBOL_H
42 #define RSYMBOL_H
43 
44 #include "CXXR/RObject.h"
45 
46 #ifdef __cplusplus
47 
48 #include "CXXR/GCRoot.h"
49 #include "CXXR/SEXP_downcast.hpp"
50 #include "CXXR/String.h"
51 
52 namespace CXXR {
94  class Symbol : public RObject {
95  private:
96  typedef std::vector<GCRoot<Symbol> > Table;
97  public:
105  public:
106  const_iterator(Table::const_iterator tblit)
107  : m_tblit(tblit)
108  {}
109 
110  const Symbol* operator*() {
111  return *m_tblit;
112  }
113 
114  const_iterator& operator++() {
115  ++m_tblit;
116  return *this;
117  }
118 
119  bool operator!=(const_iterator other) const
120  {
121  return (m_tblit != other.m_tblit);
122  }
123  private:
124  Table::const_iterator m_tblit;
125  };
126 
127  static const_iterator begin()
128  {
129  return const_iterator(s_table->begin());
130  }
131 
132  static const_iterator end()
133  {
134  return const_iterator(s_table->end());
135  }
136 
146  unsigned int dotDotIndex() const
147  {
148  return m_dd_index;
149  }
150 
156  bool isDotDotSymbol() const
157  {
158  return m_dd_index != 0;
159  }
160 
165  static size_t maxLength()
166  {
167  return s_max_length;
168  }
169 
175  {
176  return s_missing_arg;
177  }
178 
183  const String* name() const
184  {
185  if (m_name)
186  return m_name;
187  return String::blank();
188  }
189 
201  static Symbol* obtain(const String* name)
202  {
203  return (name->m_symbol ? name->m_symbol : make(name));
204  }
205 
219  static Symbol* obtain(const std::string& name);
220 
229  static Symbol* obtainDotDotSymbol(unsigned int n);
230 
235  static const char* staticTypeName()
236  {
237  return "symbol";
238  }
239 
248  {
249  return s_unbound_value;
250  }
251 
252  // Virtual functions of RObject:
254  const char* typeName() const;
255 
256  // Virtual function of GCNode:
257  void visitReferents(const_visitor* v) const;
258  protected:
259  // Virtual function of GCNode:
260  void detachReferents();
261  private:
262  friend class boost::serialization::access;
263  friend class SchwarzCounter<Symbol>;
264 
265  static const size_t s_max_length = 256;
266  static Table* s_table; // Vector of
267  // pointers to all Symbol objects in existence, other than
268  // special Symbols and deserialization temporaries, used to
269  // protect them against garbage collection.
270  static Symbol* s_missing_arg;
271  static Symbol* s_unbound_value;
272 
273  GCEdge<const String> m_name;
274 
275  unsigned int m_dd_index;
276 
277  enum S11nType {NORMAL = 0, MISSINGARG, UNBOUNDVALUE};
278 
289  explicit Symbol(const String* name = 0);
290 
291  // Declared private to ensure that Symbol objects are
292  // allocated only using 'new':
293  ~Symbol()
294  {}
295 
296  // Not (yet) implemented. Declared to prevent
297  // compiler-generated versions:
298  Symbol(const Symbol&);
299  Symbol& operator=(const Symbol&);
300 
301  static void cleanup();
302 
303  // Initialize the static data members:
304  static void initialize();
305 
306  template<class Archive>
307  void load(Archive & ar, const unsigned int version);
308 
309  // Precondition: there is not already a Symbol identified by
310  // 'name'.
311  //
312  // Creates a new Symbol identified by 'name', enters it into
313  // the table of standard Symbols, and returns a pointer to it.
314  static Symbol* make(const String* name);
315 
316  template<class Archive>
317  void save(Archive & ar, const unsigned int version) const;
318 
319  // Fields not serialised here are set up by the constructor:
320  template <class Archive>
321  void serialize(Archive& ar, const unsigned int version)
322  {
323  boost::serialization::split_member(ar, *this, version);
324  }
325  };
326 
334  inline bool isDotSymbol(const Symbol* symbol)
335  {
336  return symbol && symbol->name()->c_str()[0] == '.';
337  }
338 
346  inline bool isDotDotSymbol(const Symbol* symbol)
347  {
348  return symbol && symbol->isDotDotSymbol();
349  }
350 
351  // Predefined Symbols visible in 'namespace CXXR':
352  extern Symbol* const Bracket2Symbol; // "[["
353  extern Symbol* const BracketSymbol; // "["
354  extern Symbol* const BraceSymbol; // "{"
355  extern Symbol* const ClassSymbol; // "class"
356  extern Symbol* const ConnIdSymbol; // "conn_id"
357  extern Symbol* const DimNamesSymbol; // "dimnames"
358  extern Symbol* const DimSymbol; // "dim"
359  extern Symbol* const DollarSymbol; // "$"
360  extern Symbol* const DotClassSymbol; // ".Class"
361  extern Symbol* const DotDeviceSymbol; // ".Device"
362  extern Symbol* const DotDevicesSymbol; // ".Devices"
363  extern Symbol* const DotGenericSymbol; // ".Generic"
364  extern Symbol* const DotGenericCallEnvSymbol; // ".GenericCallEnv"
365  extern Symbol* const DotGenericDefEnvSymbol; // ".GenericDefEnv"
366  extern Symbol* const DotGroupSymbol; // ".Group"
367  extern Symbol* const DotMethodSymbol; // ".Method"
368  extern Symbol* const DotMethodsSymbol; // ".Methods"
369  extern Symbol* const DotdefinedSymbol; // ".defined"
370  extern Symbol* const DotsSymbol; // "..."
371  extern Symbol* const DottargetSymbol; // ".target"
372  extern Symbol* const DoubleColonSymbol; // "::"
373  extern Symbol* const DropSymbol; // "drop"
374  extern Symbol* const ExactSymbol; // "exact"
375  extern Symbol* const LastvalueSymbol; // ".Last.value"
376  extern Symbol* const LevelsSymbol; // "levels"
377  extern Symbol* const ModeSymbol; // "mode"
378  extern Symbol* const NameSymbol; // "name"
379  extern Symbol* const NamesSymbol; // "names"
380  extern Symbol* const NaRmSymbol; // "na.rm"
381  extern Symbol* const PackageSymbol; // "package"
382  extern Symbol* const PreviousSymbol; // "previous"
383  extern Symbol* const QuoteSymbol; // "quote"
384  extern Symbol* const RowNamesSymbol; // "row.names"
385  extern Symbol* const S3MethodsTableSymbol; // ".__S3MethodsTable__."
386  extern Symbol* const SeedsSymbol; // ".Random.seed"
387  extern Symbol* const LastvalueSymbol; // ".Last.value"
388  extern Symbol* const TripleColonSymbol; // ":::"
389  extern Symbol* const TspSymbol; // "tsp"
390  extern Symbol* const CommentSymbol; // "comment"
391  extern Symbol* const SourceSymbol; // "source"
392  extern Symbol* const DotEnvSymbol; // ".Environment"
393  extern Symbol* const RecursiveSymbol; // "recursive"
394  extern Symbol* const SrcfileSymbol; // "srcfile"
395  extern Symbol* const SrcrefSymbol; // "srcref"
396  extern Symbol* const WholeSrcrefSymbol; // "wholeSrcref"
397  extern Symbol* const TmpvalSymbol; // "*tmp*"
398  extern Symbol* const UseNamesSymbol; // "use.names"
399 } // namespace CXXR
400 
401 BOOST_CLASS_EXPORT_KEY(CXXR::Symbol)
402 
403 namespace {
404  CXXR::SchwarzCounter<CXXR::Symbol> symbol_schwarz_ctr;
405 }
406 
407 // ***** Implementation of non-inlined templated members *****
408 
409 template<class Archive>
410 void CXXR::Symbol::load(Archive& ar, const unsigned int version)
411 {
412  // This will only ever be applied to a 'temporary' Symbol created
413  // by the default constructor.
414  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(RObject);
415  S11nType symtype;
416  ar >> BOOST_SERIALIZATION_NVP(symtype);
417  Symbol* reloc;
418  switch(symtype) {
419  case NORMAL:
420  {
421  std::string name;
422  ar >> BOOST_SERIALIZATION_NVP(name);
423  reloc = obtain(name);
424  }
425  break;
426  case MISSINGARG:
427  reloc = s_missing_arg;
428  break;
429  case UNBOUNDVALUE:
430  reloc = s_unbound_value;
431  break;
432  }
433  S11nScope::defineRelocation(this, reloc);
434 }
435 
436 template<class Archive>
437 void CXXR::Symbol::save(Archive& ar, const unsigned int version) const
438 {
439  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(RObject);
440  S11nType symtype = NORMAL;
441  if (this == s_missing_arg)
442  symtype = MISSINGARG;
443  else if (this == s_unbound_value)
444  symtype = UNBOUNDVALUE;
445  ar << BOOST_SERIALIZATION_NVP(symtype);
446  if (symtype == NORMAL) {
447  // We deliberately don't serialise the CachedString pointed to
448  // by m_name, because this would make us hostage to the
449  // current implementation. Instead we serialise the
450  // std::string represented by that CachedString.
451  std::string name = m_name->stdstring();
452  ar << BOOST_SERIALIZATION_NVP(name);
453  }
454 }
455 
456 extern "C" {
457 #endif /* __cplusplus */
458 
459  /* Pseudo-objects */
460  extern SEXP R_MissingArg;
461  extern SEXP R_UnboundValue;
462 
463  /* Symbol Table Shortcuts */
464  extern SEXP R_Bracket2Symbol; /* "[[" */
465  extern SEXP R_BracketSymbol; /* "[" */
466  extern SEXP R_BraceSymbol; /* "{" */
467  extern SEXP R_ClassSymbol; /* "class" */
468  extern SEXP R_ConnIdSymbol; /* "conn_id" */
469  extern SEXP R_DeviceSymbol; /* ".Device" */
470  extern SEXP R_DevicesSymbol; /* ".Devices" */
471  extern SEXP R_DimNamesSymbol; /* "dimnames" */
472  extern SEXP R_DimSymbol; /* "dim" */
473  extern SEXP R_DollarSymbol; /* "$" */
474  extern SEXP R_DotsSymbol; /* "..." */
475  extern SEXP R_DoubleColonSymbol; /* "::" */
476  extern SEXP R_DropSymbol; /* "drop" */
477  extern SEXP R_LastvalueSymbol; /* ".Last.value" */
478  extern SEXP R_LevelsSymbol; /* "levels" */
479  extern SEXP R_ModeSymbol; /* "mode" */
480  extern SEXP R_NameSymbol; /* "name" */
481  extern SEXP R_NamesSymbol; /* "names" */
482  extern SEXP R_NaRmSymbol; /* "na.rm" */
483  extern SEXP R_PackageSymbol; /* "package" */
484  extern SEXP R_QuoteSymbol; /* "quote" */
485  extern SEXP R_RowNamesSymbol; /* "row.names" */
486  extern SEXP R_SeedsSymbol; /* ".Random.seed" */
487  extern SEXP R_SourceSymbol; /* "source" */
488  extern SEXP R_TripleColonSymbol; /* ":::" */
489  extern SEXP R_TspSymbol; /* "tsp" */
490 
491  extern SEXP R_dot_Generic; /* ".Generic" */
492  extern SEXP R_dot_Method; /* ".Method" */
493  extern SEXP R_dot_defined; /* ".defined" */
494  extern SEXP R_dot_target; /* ".target" */
495 
503 #ifndef __cplusplus
504  Rboolean DDVAL(SEXP x);
505 #else
506  inline Rboolean DDVAL(SEXP x)
507  {
508  using namespace CXXR;
509  const Symbol& sym = *SEXP_downcast<Symbol*>(x);
510  return Rboolean(sym.isDotDotSymbol());
511  }
512 #endif
513 
527  SEXP Rf_ddfindVar(SEXP symbol, SEXP rho);
528 
541 #ifndef __cplusplus
542  SEXP Rf_install(const char *name);
543 #else
544  inline SEXP Rf_install(const char *name)
545  {
546  return CXXR::Symbol::obtain(name);
547  }
548 #endif
549 
557 #ifndef __cplusplus
558  Rboolean Rf_isSymbol(SEXP s);
559 #else
560  inline Rboolean Rf_isSymbol(SEXP s)
561  {
562  return Rboolean(s && TYPEOF(s) == SYMSXP);
563  }
564 #endif
565 
572 #ifndef __cplusplus
573  SEXP PRINTNAME(SEXP x);
574 #else
575  inline SEXP PRINTNAME(SEXP x)
576  {
577  using namespace CXXR;
578  const Symbol& sym = *SEXP_downcast<Symbol*>(x);
579  return const_cast<String*>(sym.name());
580  }
581 #endif
582 
583 #ifdef __cplusplus
584 }
585 #endif
586 
587 #endif /* RSYMBOL_H */