CXXR (C++ R)
Frame.hpp
Go to the documentation of this file.
1 /*CXXR $Id: Frame.hpp 1403 2013-09-12 07:46:53Z 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 RFRAME_HPP
42 #define RFRAME_HPP
43 
44 #include <boost/range/any_range.hpp>
45 #include <boost/serialization/access.hpp>
46 #include <boost/serialization/base_object.hpp>
47 #include <boost/serialization/nvp.hpp>
48 
49 #include "CXXR/GCNode.hpp"
50 #include "CXXR/PairList.h"
51 #include "CXXR/Provenance.hpp"
52 #include "CXXR/Symbol.h"
53 
54 namespace CXXR {
55  class Environment;
56  class FunctionBase;
57 
67  class Frame : public GCNode {
68  public:
84  class Binding {
85  public:
88  enum Origin {
89  EXPLICIT = 0,
107  };
108 
115  : m_frame(0), m_symbol(0), m_value(Symbol::missingArgument()),
116 #ifdef PROVENANCE_TRACKING
117  m_provenance(0),
118 #endif
119  m_origin(MISSING), m_active(false),
120  m_locked(false)
121  {}
122 
138  PairList* asPairList(PairList* tail = 0) const;
139 
157  void assign(RObject* new_value, Origin origin = EXPLICIT);
158 
182  std::pair<RObject*, bool> forcedValue();
183 
189  const Frame* frame() const
190  {
191  return m_frame;
192  }
193 
212  void fromPairList(PairList* pl);
213 
214 #ifdef PROVENANCE_TRACKING
215 
221  const Provenance* provenance() const
222  {
223  return m_provenance;
224  }
225 #endif
226 
240  void initialize(Frame* frame, const Symbol* sym);
241 
246  bool isActive() const
247  {
248  return m_active;
249  }
250 
255  bool isLocked() const
256  {
257  return m_locked;
258  }
259 
264  Origin origin() const
265  {
266  return Origin(m_origin);
267  }
268 
279  RObject* rawValue() const
280  {
281  if (m_frame)
282  m_frame->monitorRead(*this);
283  return m_value;
284  }
285 
304  void setFunction(FunctionBase* function,
306 
311  void setLocking(bool on)
312  {
313  m_locked = on;
314  }
315 
316 #ifdef PROVENANCE_TRACKING
317 
322  void setProvenance(Provenance *prov)
323  {
324  m_provenance=prov;
325  }
326 #endif
327 
341  void setValue(RObject* new_value, Origin origin = EXPLICIT,
342  bool quiet = false);
343 
348  const Symbol* symbol() const
349  {
350  return m_symbol;
351  }
352 
361  RObject* value() const;
362 
372  void visitReferents(const_visitor* v) const;
373  private:
374  friend class boost::serialization::access;
375 
376  Frame* m_frame;
377  const Symbol* m_symbol;
378  GCEdge<> m_value;
379 #ifdef PROVENANCE_TRACKING
380  GCEdge<const Provenance> m_provenance;
381 #endif
382  unsigned char m_origin;
383  bool m_active;
384  bool m_locked;
385 
386  // Note that serialisation does not save the m_frame or
387  // m_symbol fields, because deserialisation assumes that a
388  // Binding object will already have been initialised (by
389  // calling initialize()).
390  template<class Archive>
391  void serialize(Archive & ar, const unsigned int version);
392  }; // Frame::Binding
393 
394 
401  typedef boost::any_range<const Binding,
402  boost::forward_traversal_tag,
403  const Binding&,
404  std::ptrdiff_t> BindingRange;
405 
410  typedef void (*monitor)(const Binding&);
411 
412  Frame()
413  : m_cache_count(0), m_locked(false),
414  m_read_monitored(false), m_write_monitored(false)
415  {}
416 
426  Frame(const Frame& source)
427  : m_cache_count(0), m_locked(source.m_locked),
428  m_read_monitored(false), m_write_monitored(false)
429  {}
430 
446  PairList* asPairList() const;
447 
461  Binding* bind(const Symbol* symbol, RObject* value,
463  {
464  Binding* bdg = obtainBinding(symbol);
465  bdg->setValue(value, origin);
466  return bdg;
467  }
468 
481 #ifdef __GNUG__
482  __attribute__((fastcall))
483 #endif
484  virtual Binding* binding(const Symbol* symbol) = 0;
485 
498  virtual const Binding* binding(const Symbol* symbol) const = 0;
499 
505  virtual BindingRange bindingRange() const = 0;
506 
511  void clear();
512 
530  virtual Frame* clone() const = 0;
531 
550  void enableReadMonitoring(bool on) const;
551 
575  void enableWriteMonitoring(bool on) const;
576 
591  bool erase(const Symbol* symbol);
592 
597  bool isLocked() const
598  {
599  return m_locked;
600  }
601 
615  void lock(bool lock_bindings)
616  {
617  m_locked = true;
618  if (lock_bindings)
619  lockBindings();
620  }
621 
630  virtual void lockBindings() = 0;
631 
647  Binding* obtainBinding(const Symbol* symbol);
648 
667  static monitor setReadMonitor(monitor new_monitor)
668  {
669  monitor old = s_read_monitor;
670  s_read_monitor = new_monitor;
671  return old;
672  }
673 
692  static monitor setWriteMonitor(monitor new_monitor)
693  {
694  monitor old = s_write_monitor;
695  s_write_monitor = new_monitor;
696  return old;
697  }
698 
704  virtual std::size_t size() const = 0;
705 
714  std::vector<const Symbol*> symbols(bool include_dotsymbols) const;
715 
716  // Virtual function of GCNode:
717  void visitReferents(const_visitor* v) const;
718  protected:
719  // Declared protected to ensure that Frame objects are created
720  // only using 'new':
721  ~Frame()
722  {
723  statusChanged(0);
724  }
725 
734  void statusChanged(const Symbol* sym)
735  {
736  if (m_cache_count > 0)
737  flush(sym);
738  }
739 
740  // Virtual function of GCNode:
741  void detachReferents();
742  private:
743  friend class Environment;
744  friend class boost::serialization::access;
745 
746  static monitor s_read_monitor, s_write_monitor;
747 
748  unsigned char m_cache_count; // Number of cached Environments
749  // of which this is the Frame. Normally
750  // either 0 or 1.
751  bool m_locked : 1;
752  mutable bool m_read_monitored : 1;
753  mutable bool m_write_monitored : 1;
754 
755  // Not (yet) implemented. Declared to prevent
756  // compiler-generated versions:
757  Frame& operator=(const Frame&);
758 
759  // Monitoring functions:
760  friend class Binding;
761 
762  void decCacheCount()
763  {
764  --m_cache_count;
765  }
766 
767  // Flush symbol(s) from search list cache:
768  void flush(const Symbol* sym);
769 
770  void incCacheCount()
771  {
772  ++m_cache_count;
773  }
774 
775  void monitorRead(const Binding& bdg) const
776  {
777  if (m_read_monitored)
778  s_read_monitor(bdg);
779  }
780 
781  void monitorWrite(const Binding& bdg) const
782  {
783  if (m_write_monitored)
784  s_write_monitor(bdg);
785  }
786 
787  template<class Archive>
788  void serialize (Archive & ar, const unsigned int version);
789 
790  // Implementation dependent auxiliary functions:
791  virtual void v_clear() = 0;
792  virtual bool v_erase(const Symbol* symbol) = 0;
793  virtual Binding* v_obtainBinding(const Symbol* symbol) = 0;
794  };
795 
813  void frameReadPairList(Frame* frame, PairList* bindings);
814 
849  bool isMissingArgument(const Symbol* sym, Frame* frame);
850 
851  // ***** Implementation of non-inlined templated members *****
852 
853  template<class Archive>
854  void Frame::Binding::serialize(Archive & ar, const unsigned int version)
855  {
856  GCNPTR_SERIALIZE(ar, m_value);
857  const Provenance* prov = 0;
858 #ifdef PROVENANCE_TRACKING
859  prov = m_provenance;
860 #endif
861  GCNode::PtrS11n::invoke(ar, prov, "m_provenance");
862 #ifdef PROVENANCE_TRACKING
863  m_provenance = prov;
864 #endif
865  ar & BOOST_SERIALIZATION_NVP(m_origin);
866  ar & BOOST_SERIALIZATION_NVP(m_active);
867  ar & BOOST_SERIALIZATION_NVP(m_locked);
868  }
869 
870  template<class Archive>
871  void Frame::serialize (Archive & ar, const unsigned int version) {
872  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(GCNode);
873  bool locked = m_locked;
874  ar & BOOST_SERIALIZATION_NVP(locked);
875  m_locked = locked;
876  }
877 } // namespace CXXR
878 
879 // This definition is visible only in C++; C code sees instead a
880 // definition (in Environment.h) as an opaque pointer.
882 
883 #endif // RFRAME_HPP