CXXR (C++ R) API
Promise.h
Go to the documentation of this file.
1 /*CXXR $Id: Promise.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 
41 #ifndef RPROMISE_H
42 #define RPROMISE_H
43 
44 #include "CXXR/RObject.h"
45 // Just to pick up define of BYTECODE:
46 #include "CXXR/Evaluator.h"
47 
48 #ifdef __cplusplus
49 
50 #include <boost/serialization/access.hpp>
51 #include <boost/serialization/base_object.hpp>
52 #include <boost/serialization/nvp.hpp>
53 
54 #include "CXXR/Expression.h"
55 #include "CXXR/Environment.h"
56 #include "CXXR/Symbol.h"
57 
58 namespace CXXR {
83  class Promise : public RObject {
84  public:
94  Promise(RObject* valgen, Environment* env)
95  : RObject(PROMSXP), m_value(env ? Symbol::unboundValue() : valgen),
96  m_valgen(valgen), m_environment(env), m_under_evaluation(false),
97  m_interrupted(false)
98  {}
99 
107  {
108  return m_environment;
109  }
110 
125  {
126  return evaluate(0);
127  }
128 
137  bool isMissingSymbol() const;
138 
150  void setValue(RObject* val);
151 
156  static const char* staticTypeName()
157  {
158  return "promise";
159  }
160 
167  {
168  return m_value;
169  }
170 
176  const RObject* valueGenerator() const
177  {
178  return m_valgen;
179  }
180 
182  const char* typeName() const;
183 
184  // Virtual function of GCNode:
185  void visitReferents(const_visitor* v) const;
186  protected:
187  // Virtual function of GCNode:
188  void detachReferents();
189  private:
190  friend class boost::serialization::access;
191 
192  GCEdge<> m_value;
193  GCEdge<RObject> m_valgen;
194  GCEdge<Environment> m_environment;
195  mutable bool m_under_evaluation;
196  mutable bool m_interrupted;
197 
198  // Declared private to ensure that Environment objects are
199  // created only using 'new':
200  ~Promise() {}
201 
202  // Not (yet) implemented. Declared to prevent
203  // compiler-generated versions:
204  Promise(const Promise&);
205  Promise& operator=(const Promise&);
206 
207  // Fields not serialised here are set up by the constructor:
208  template <class Archive>
209  void serialize(Archive& ar, const unsigned int version)
210  {
211  ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(RObject);
212  GCNPTR_SERIALIZE(ar, m_value);
213  }
214  };
215 
224  inline RObject* forceIfPromise(RObject* object)
225  {
226  if (object && object->sexptype() == PROMSXP)
227  object = static_cast<Promise*>(object)->force();
228  return object;
229  }
230 } // namespace CXXR
231 
232 BOOST_CLASS_EXPORT_KEY(CXXR::Promise)
233 
234 namespace boost {
235  namespace serialization {
253  template<class Archive>
254  void load_construct_data(Archive& ar, CXXR::Promise* t,
255  const unsigned int version)
256  {
257  using namespace CXXR;
258  GCStackRoot<> valgen;
259  GCNPTR_SERIALIZE(ar, valgen);
261  GCNPTR_SERIALIZE(ar, env);
262  new (t) Promise(valgen, env);
263  }
264 
285  template<class Archive>
286  void save_construct_data(Archive& ar, const CXXR::Promise* t,
287  const unsigned int version)
288  {
289  using namespace CXXR;
290  const RObject* valgen = t->valueGenerator();
291  GCNPTR_SERIALIZE(ar, valgen);
292  const Environment* env = t->environment();
293  GCNPTR_SERIALIZE(ar, env);
294  }
295  } // namespace serialization
296 } // namespace boost
297 
298 extern "C" {
299 #endif
300 
308  SEXP Rf_mkPROMISE(SEXP expr, SEXP env);
309 
317 #ifndef __cplusplus
318  SEXP PRCODE(SEXP x);
319 #else
320  inline SEXP PRCODE(SEXP x)
321  {
322  using namespace CXXR;
323  const Promise& prom = *SEXP_downcast<Promise*>(x);
324  return const_cast<RObject*>(prom.valueGenerator());
325  }
326 #endif
327 
336 #ifndef __cplusplus
337  SEXP PRENV(SEXP x);
338 #else
339  inline SEXP PRENV(SEXP x)
340  {
341  using namespace CXXR;
342  const Promise& prom = *SEXP_downcast<Promise*>(x);
343  return prom.environment();
344  }
345 #endif
346 
354 #ifndef __cplusplus
355  SEXP PRVALUE(SEXP x);
356 #else
357  inline SEXP PRVALUE(SEXP x)
358  {
359  using namespace CXXR;
360  Promise& prom = *SEXP_downcast<Promise*>(x);
361  return prom.value();
362  }
363 #endif
364 
376  void SET_PRVALUE(SEXP x, SEXP v);
377 
378  // PREXPR() behaves similarly to valueGenerator(), but has special
379  // (but apparently undocumented) behaviour if m_valgen (PRCODE) is
380  // bytecode. My guess is that if the bytecode evaluates to a
381  // symbol, PREXPR returns that symbol, otherwise R_NilValue.
382 #ifdef BYTECODE
383  SEXP R_PromiseExpr(SEXP);
384 #define PREXPR(e) R_PromiseExpr(e)
385 #else
386 #define PREXPR(e) PRCODE(e)
387 #endif
388 
389 #ifdef __cplusplus
390 }
391 #endif
392 
393 #endif /* RPROMISE_H */