CXXR (C++ R)
ArgMatcher.hpp
Go to the documentation of this file.
1 /*CXXR $Id: ArgMatcher.hpp 1348 2013-02-25 17:49:03Z 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  *
20  * This program is free software; you can redistribute it and/or modify
21  * it under the terms of the GNU General Public License as published by
22  * the Free Software Foundation; either version 2.1 of the License, or
23  * (at your option) any later version.
24  *
25  * This program is distributed in the hope that it will be useful,
26  * but WITHOUT ANY WARRANTY; without even the implied warranty of
27  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28  * GNU Lesser General Public License for more details.
29  *
30  * You should have received a copy of the GNU General Public License
31  * along with this program; if not, a copy is available at
32  * http://www.r-project.org/Licenses/
33  */
34 
39 #ifndef ARGMATCHER_HPP
40 #define ARGMATCHER_HPP 1
41 
42 #include <list>
43 #include <map>
44 #include <vector>
45 #include "CXXR/GCEdge.hpp"
46 #include "CXXR/String.h"
47 
48 namespace CXXR {
49  class ArgList;
50  class Environment;
51  class Frame;
52  class PairList;
53  class RObject;
54  class Symbol;
55 
67  class ArgMatcher : public GCNode {
68  public:
76  explicit ArgMatcher(const PairList* formals);
77 
85  static void enableWarnOnPartialMatch(bool on)
86  {
87  s_warn_on_partial_match = on;
88  }
89 
95  const PairList* formalArgs() const
96  {
97  return m_formals;
98  }
99 
104  bool has3Dots() const
105  {
106  return m_has_dots;
107  }
108 
143  static ArgMatcher* make(Symbol* fml1, Symbol* fml2 = 0,
144  Symbol* fml3 = 0, Symbol* fml4 = 0,
145  Symbol* fml5 = 0, Symbol* fml6 = 0);
146 
185  void match(Environment* target_env, const ArgList* supplied) const;
186 
192  size_t numFormals() const
193  {
194  return m_formal_data.size() + m_has_dots;
195  }
196 
234  void propagateFormalBindings(const Environment* fromenv,
235  Environment* toenv) const;
236 
247  void stripFormals(Frame* input_frame) const;
248 
255  static bool warnOnPartialMatch()
256  {
257  return s_warn_on_partial_match;
258  }
259 
260  // Virtual function of GCNode:
261  void visitReferents(const_visitor* v) const;
262  protected:
263  // Virtual function of GCNode:
264  void detachReferents();
265  private:
266  static bool s_warn_on_partial_match;
267 
268  struct FormalData {
269  const Symbol* symbol;
270  bool follows_dots; // true if ... occurs earlier in the
271  // formals list.
272  RObject* value;
273  };
274 
275  enum MatchStatus {UNMATCHED = 0, EXACT_TAG, PARTIAL_TAG, POSITIONAL};
276 
277  GCEdge<const PairList> m_formals;
278 
279  // Data on formals (other than "...") in order of occurrence:
280  typedef std::vector<FormalData, Allocator<FormalData> > FormalVector;
281  FormalVector m_formal_data;
282 
283  struct Comparator {
284  bool operator()(const String* l, const String* r) const
285  {
286  return l->stdstring() < r->stdstring();
287  }
288  };
289 
290  // Mapping from tag names to index within m_formal_data:
291  typedef std::map<const String*, unsigned int, Comparator,
292  Allocator<std::pair<const String*,
293  unsigned int> > > FormalMap;
294  FormalMap m_formal_index;
295 
296  bool m_has_dots; // True if formals include "..."
297 
298  struct SuppliedData {
299  const Symbol* tag;
300  RObject* value;
301  FormalMap::const_iterator fm_iter;
302  unsigned int index;
303  };
304 
305  // Data relating to supplied arguments that have not yet been
306  // matched.
307  typedef std::list<SuppliedData, Allocator<SuppliedData> > SuppliedList;
308 
309  // Turn remaining arguments, if any, into a DottedArgs object
310  // bound to '...'. Leave supplied_list empty.
311  static void handleDots(Frame* frame, SuppliedList* supplied_list);
312 
313  // Return true if 'shorter' is a prefix of 'longer', or is
314  // identical to 'longer':
315  static bool isPrefix(const String* shorter, const String* longer);
316 
317  // Create a Binding in the Frame of target_env for the Symbol
318  // in fdata, setting its Origin and applying default value
319  // appropriately. Default values are wrapped in Promises
320  // keyed to target_env.
321  static void makeBinding(Environment* target_env, const FormalData& fdata,
322  RObject* supplied_value);
323 
324  // Raise an error because there are unused supplied arguments,
325  // as indicated in supplied_list.
326  static void unusedArgsError(const SuppliedList& supplied_list);
327  };
328 }
329 
330 #endif // ARGMATCHER_HPP