CXXR (C++ R)
ConsCell.h
Go to the documentation of this file.
1 /*CXXR $Id: ConsCell.h 1353 2013-03-18 16:59:38Z 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 
49 #ifndef CONSCELL_H
50 #define CONSCELL_H
51 
52 #include "CXXR/RObject.h"
53 
54 #ifdef __cplusplus
55 
56 #include <stdexcept>
57 #include <boost/serialization/access.hpp>
58 #include <boost/serialization/base_object.hpp>
59 #include <boost/serialization/nvp.hpp>
60 
61 #include "CXXR/GCRoot.h"
62 #include "CXXR/SEXP_downcast.hpp"
63 
64 namespace CXXR {
65  class PairList;
66 
98  class ConsCell : public RObject {
99  public:
102  class iterator
103  : public std::iterator<std::forward_iterator_tag, ConsCell> {
104  public:
110  explicit iterator(ConsCell* cc = 0)
111  : m_cc(cc)
112  {}
113 
114  ConsCell& operator*() const
115  {
116  return *m_cc;
117  }
118 
119  ConsCell* operator->() const
120  {
121  return m_cc;
122  }
123 
124  ConsCell& operator++()
125  {
126  advance();
127  return *m_cc;
128  }
129 
130  ConsCell& operator++(int)
131  {
132  ConsCell& ans = *m_cc;
133  advance();
134  return ans;
135  }
136  private:
137  ConsCell* m_cc;
138 
139  void advance();
140  };
141 
145  : public std::iterator<std::forward_iterator_tag, const ConsCell> {
146  public:
152  explicit const_iterator(const ConsCell* cc = 0)
153  : m_cc(cc)
154  {}
155 
156  const ConsCell& operator*() const
157  {
158  return *m_cc;
159  }
160 
161  const ConsCell* operator->() const
162  {
163  return m_cc;
164  }
165 
166  const ConsCell& operator++()
167  {
168  advance();
169  return *m_cc;
170  }
171 
172  const ConsCell& operator++(int)
173  {
174  const ConsCell& ans = *m_cc;
175  advance();
176  return ans;
177  }
178  private:
179  const ConsCell* m_cc;
180 
181  void advance();
182  };
183 
184  iterator begin()
185  {
186  return iterator(this);
187  }
188 
189  const_iterator begin() const
190  {
191  return const_iterator(this);
192  }
193 
198  RObject* car() const
199  {
200  return m_car;
201  }
202 
217  template <class T>
218  static T* convert(ConsCell* cc)
219  {
220  if (!cc)
221  return 0;
222  if (T* ccc = dynamic_cast<T*>(cc))
223  return ccc;
224  T* ans = new T(cc->car(), cc->tail(), cc->tag());
225  ans->setAttributes(cc->attributes());
226  return expose(ans);
227  }
228 
229  iterator end()
230  {
231  return iterator();
232  }
233 
234  const_iterator end() const
235  {
236  return const_iterator();
237  }
238 
244  void setCar(RObject* cr)
245  {
246  m_car = cr;
247  }
248 
254  void setTag(const RObject* tg)
255  {
256  m_tag = tg;
257  }
258 
264  void setTail(PairList* tl);
265  // Implemented inline in CXXR/PairList.h
266 
271  static const char* staticTypeName()
272  {
273  return "(pairlist type)";
274  }
275 
279  const RObject* tag() const
280  {
281  return m_tag;
282  }
283 
288  const PairList* tail() const;
289 
293  PairList* tail();
294 
295  // Virtual function of GCNode:
296  void visitReferents(const_visitor* v) const;
297  protected:
311  explicit ConsCell(SEXPTYPE st,
312  RObject* cr = 0, PairList* tl = 0,
313  const RObject* tg = 0);
314 
322  ConsCell(const ConsCell& pattern);
323 
338  ConsCell(const ConsCell& pattern, int dummy);
339 
345 
346  // Virtual function of GCNode:
347  void detachReferents();
348  private:
349  friend class boost::serialization::access;
350  friend class PairList;
351 
352  RHandle<> m_car;
353  GCEdge<PairList> m_tail;
354  GCEdge<const RObject> m_tag;
355 
356  // Not implemented yet. Declared to prevent
357  // compiler-generated version:
358  ConsCell& operator=(const ConsCell&);
359 
360  // Check that st is a legal SEXPTYPE for a ConsCell:
361  static void checkST(SEXPTYPE st);
362 
363  template<class Archive>
364  void serialize(Archive & ar, const unsigned int version);
365  };
366 
367  template<class Archive>
368  void CXXR::ConsCell::serialize(Archive & ar, const unsigned int version) {
369  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(RObject);
370  GCNPTR_SERIALIZE(ar, m_tag);
371  GCNPTR_SERIALIZE(ar, m_car);
372  GCNPTR_SERIALIZE(ar, m_tail);
373  }
374 
375  inline bool operator==(ConsCell::iterator l, ConsCell::iterator r)
376  {
377  return &(*l) == &(*r);
378  }
379 
380  inline bool operator!=(ConsCell::iterator l, ConsCell::iterator r)
381  {
382  return !(l == r);
383  }
384 
385  inline bool operator==(ConsCell::const_iterator l,
386  ConsCell::const_iterator r)
387  {
388  return &(*l) == &(*r);
389  }
390 
391  inline bool operator!=(ConsCell::const_iterator l,
392  ConsCell::const_iterator r)
393  {
394  return !(l == r);
395  }
396 
409  inline RObject* car0(ConsCell* cc)
410  {
411  return cc ? cc->car() : 0;
412  }
413 
418  void ccdump(std::ostream& os, const ConsCell& cc, size_t margin = 0);
419 
428  inline size_t listLength(const ConsCell* start)
429  {
430  return (start ? std::distance(start->begin(), start->end()) : 0);
431  }
432 
445  inline PairList* tail0(ConsCell* cc)
446  {
447  return cc ? cc->tail() : 0;
448  }
449 
459  class PairList : public ConsCell {
460  public:
470  explicit PairList(RObject* cr = 0, PairList* tl = 0,
471  const RObject* tg = 0)
472  : ConsCell(LISTSXP, cr, tl, tg)
473  {}
474 
479  PairList(const PairList& pattern);
480 
497  static PairList* cons(RObject* cr, PairList* tl=0,
498  const RObject* tag = 0)
499  {
500  // We call MemoryBank::allocate() directly here, rather
501  // than GCNode::operator new(), to avoid giving rise to
502  // any garbage collection, and thus avoiding (a) the need
503  // to protect the arguments from GC, and (b) the
504  // possibility of reentrant calls to this function (from
505  // object destructors). However, calling code should not
506  // rely on the fact that no GC will occur, because the
507  // implementation may change in the future.
508  void* pad = MemoryBank::allocate(sizeof(PairList));
509  return expose(new (pad) PairList(cr, tl, tag));
510  }
511 
521  static PairList* make(size_t sz) throw (std::bad_alloc);
522 
527  static const char* staticTypeName()
528  {
529  return "pairlist";
530  }
531 
532  // Virtual functions of RObject:
533  PairList* clone() const;
534  unsigned int packGPBits() const;
535  const char* typeName() const;
536  void unpackGPBits(unsigned int gpbits);
537  private:
538  friend class boost::serialization::access;
539 
540  // Tailless copy constructor. Copies the node without copying
541  // its tail. Used in implementing the copy constructor
542  // proper. The second parameter is simply to provide a
543  // distinct signature, and its value is ignored.
544  PairList(const PairList& pattern, int)
545  : ConsCell(pattern, 0)
546  {}
547 
548  // Declared private to ensure that PairList objects are
549  // allocated only using 'new':
550 #ifdef __GNUG__
551  __attribute__((hot))
552 #endif
553  ~PairList();
554 
555  // Not implemented yet. Declared to prevent
556  // compiler-generated version:
557  PairList& operator=(const PairList&);
558 
559  template<class Archive>
560  void serialize(Archive & ar, const unsigned int version) {
561  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(ConsCell);
562  }
563  };
564 
565  inline void ConsCell::iterator::advance()
566  {
567  m_cc = m_cc->tail();
568  }
569 
570  inline void ConsCell::const_iterator::advance()
571  {
572  m_cc = m_cc->tail();
573  }
574 
576  PairList* tl, const RObject* tg)
577  : RObject(st), m_car(cr), m_tail(tl), m_tag(tg)
578  {
579  // checkST(st);
580  }
581 
582  inline ConsCell::ConsCell(const ConsCell& pattern)
583  : RObject(pattern), m_car(pattern.m_car),
584  m_tail(clone(pattern.tail())), m_tag(pattern.tag())
585  {}
586 
587  inline ConsCell::ConsCell(const ConsCell& pattern, int)
588  : RObject(pattern), m_car(pattern.m_car), m_tail(0),
589  m_tag(pattern.tag())
590  {}
591 
592  inline void ConsCell::setTail(PairList* tl)
593  {
594  m_tail = tl;
595  }
596 
597  inline const PairList* ConsCell::tail() const
598  {
599  return m_tail;
600  }
601 
603  {
604  return m_tail;
605  }
606 } // namespace CXXR
607 
608 BOOST_CLASS_EXPORT_KEY(CXXR::PairList)
609 
610 extern "C" {
611 
618 #ifndef __cplusplus
619  SEXP CAR(SEXP e);
620 #else
621  inline SEXP CAR(SEXP e)
622  {
623  using namespace CXXR;
624  return car0(SEXP_downcast<ConsCell*>(e));
625  }
626 #endif
627 
631 #ifndef __cplusplus
632  SEXP CAAR(SEXP e);
633 #else
634  inline SEXP CAAR(SEXP e) {return CAR(CAR(e));}
635 #endif
636 
637  // Used in argument handling (within envir.cpp, eval.cpp and
638  // match.cpp). Note comments in the 'R Internals' document.
639  inline int MISSING(SEXP x)
640  {
641  using namespace CXXR;
642  return SEXP_downcast<ConsCell*>(x)->m_missing;
643  }
644 
653  SEXP SETCAR(SEXP x, SEXP y);
654 
655  // Used in argument handling (within envir.cpp, eval.cpp and
656  // match.cpp). Note comments in the 'R Internals' document.
657  inline void SET_MISSING(SEXP x, int v)
658  {
659  using namespace CXXR;
660  SEXP_downcast<ConsCell*>(x)->m_missing = v;
661  }
662 #endif /* __cplusplus */
663 
670 #ifndef __cplusplus
671  SEXP TAG(SEXP e);
672 #else
673  inline SEXP TAG(SEXP e)
674  {
675  using namespace CXXR;
676  if (!e) return 0;
677  ConsCell& cc = *SEXP_downcast<ConsCell*>(e);
678  return const_cast<RObject*>(cc.tag());
679  }
680 #endif
681 
689  void SET_TAG(SEXP x, SEXP y);
690 
701 
702 #ifdef __cplusplus
703 }
704 #endif
705 
706 #endif /* CONSCELL_H */