InFact
Interpreter and factory for easily creating C++ objects at run-time
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
environment-impl.h
Go to the documentation of this file.
1 // Copyright 2014, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 // * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 // * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 // -----------------------------------------------------------------------------
30 //
31 //
36 
37 #ifndef INFACT_ENVIRONMENT_IMPL_H_
38 #define INFACT_ENVIRONMENT_IMPL_H_
39 
40 #include <sstream>
41 #include <string>
42 #include <unordered_map>
43 #include <unordered_set>
44 #include <typeinfo>
45 
46 #include "environment.h"
47 #include "error.h"
48 
49 namespace infact {
50 
51 using std::ostringstream;
52 using std::string;
53 using std::unordered_map;
54 using std::unordered_set;
55 
60 class EnvironmentImpl : public Environment {
61  public:
66  EnvironmentImpl(int debug = 0);
67 
69  virtual ~EnvironmentImpl() {
70  for (unordered_map<string, VarMapBase *>::iterator it = var_map_.begin();
71  it != var_map_.end(); ++it) {
72  delete it->second;
73  }
74  }
75 
78  virtual bool Defined(const string &varname) const {
79  unordered_map<string, string>::const_iterator it = types_.find(varname);
80  return it != types_.end();
81  }
82 
85  virtual void ReadAndSet(const string &varname, StreamTokenizer &st,
86  const string type);
87 
88  virtual const string &GetType(const string &varname) const {
89  unordered_map<string, string>::const_iterator type_it =
90  types_.find(varname);
91  if (type_it == types_.end()) {
92  // Error or warning.
93  }
94  return type_it->second;
95  }
96 
97  virtual VarMapBase *GetVarMap(const string &varname) {
98  return GetVarMapForType(GetType(varname));
99  }
100 
102  virtual VarMapBase *GetVarMapForType(const string &type) {
103  string lookup_type = type;
104  // First, check if this is a concrete Factory-constructible type.
105  // If so, map to its abstract type name.
106  unordered_map<string, string>::const_iterator factory_type_it =
107  concrete_to_factory_type_.find(type);
108  if (factory_type_it != concrete_to_factory_type_.end()) {
109  lookup_type = factory_type_it->second;
110  }
111 
112  unordered_map<string, VarMapBase *>::const_iterator var_map_it =
113  var_map_.find(lookup_type);
114  if (var_map_it == var_map_.end()) {
115  return nullptr;
116  }
117  return var_map_it->second;
118  }
119 
121  virtual void Print(ostream &os) const {
122  for (unordered_map<string, VarMapBase *>::const_iterator var_map_it =
123  var_map_.begin();
124  var_map_it != var_map_.end(); ++var_map_it) {
125  var_map_it->second->Print(os);
126  }
127  }
128 
130  virtual void PrintFactories(ostream &os) const;
131 
133  virtual Environment *Copy() const {
134  EnvironmentImpl *new_env = new EnvironmentImpl(*this);
135  // Now go through and create copies of each VarMap.
136  for (unordered_map<string, VarMapBase *>::iterator new_env_var_map_it =
137  new_env->var_map_.begin();
138  new_env_var_map_it != new_env->var_map_.end(); ++new_env_var_map_it) {
139  new_env_var_map_it->second = new_env_var_map_it->second->Copy(new_env);
140  }
141  return new_env;
142  }
143 
152  template<typename T>
153  bool Get(const string &varname, T *value) const;
154 
155  private:
157  string InferType(const string &varname,
158  const StreamTokenizer &st, bool is_vector,
159  bool *is_object_type);
160 
162  unordered_map<string, string> types_;
163 
166  unordered_map<string, VarMapBase *> var_map_;
167 
170  unordered_map<string, string> concrete_to_factory_type_;
171 
172  int debug_;
173 };
174 
175 template<typename T>
176 bool
177 EnvironmentImpl::Get(const string &varname, T *value) const {
178  unordered_map<string, string>::const_iterator type_it =
179  types_.find(varname);
180  if (type_it == types_.end()) {
181  if (debug_ >= 2) {
182  ostringstream err_ss;
183  err_ss << "Environment::Get: error: no value for variable "
184  << varname;
185  cerr << err_ss.str() << endl;
186  }
187  return false;
188  }
189 
190  // Now that we have the type, look up the VarMap.
191  const string &type = type_it->second;
192  unordered_map<string, VarMapBase*>::const_iterator var_map_it =
193  var_map_.find(type);
194 
195  if (var_map_it == var_map_.end()) {
196  ostringstream err_ss;
197  err_ss << "Environment::Get: error: types_ and var_map_ data members "
198  << "are out of sync";
199  Error(err_ss.str());
200  }
201 
202  // Do a dynamic_cast down to the type-specific VarMap.
203  VarMapBase *var_map = var_map_it->second;
204  VarMap<T> *typed_var_map = dynamic_cast<VarMap<T> *>(var_map);
205 
206  if (typed_var_map == nullptr) {
207  ostringstream err_ss;
208  err_ss << "Environment::Get: error: no value for variable "
209  << varname << " of type " << typeid(*value).name()
210  << "; perhaps you meant " << type << "?";
211  cerr << err_ss.str() << endl;
212  return false;
213  }
214  bool success = typed_var_map->Get(varname, value);
215  if (!success) {
216  ostringstream err_ss;
217  err_ss << "Environment::Get: error: no value for variable "
218  << varname << " of type " << typeid(*value).name()
219  << "; types_ and var_map_ data members are out of sync";
220  Error(err_ss.str());
221  }
222  return success;
223  }
224 
225 } // namespace infact
226 
227 #endif
virtual ~EnvironmentImpl()
Destroys this environment.
virtual const string & GetType(const string &varname) const
Retrieves the type name of the specified variable.
bool Get(const string &varname, T *value) const
Retrieves the value of the variable with the specified name and puts into into the object pointed to ...
virtual bool Defined(const string &varname) const
Returns whether the specified variable has been defined in this environment.
Provides an error handling function that optionally throws an exception.
virtual Environment * Copy() const
Returns a copy of this environment.
virtual void ReadAndSet(const string &varname, StreamTokenizer &st, const string type)
Sets the specified variable to the value obtained from the following tokens available from the specif...
EnvironmentImpl(int debug=0)
Constructs a new, empty environment.
virtual void Print(ostream &os) const
Prints a human-readable string of all the variables in this environment, their types and...
bool Get(const string &varname, T *value) const
Assigns the value of the specified variable to the object pointed to by the value parameter...
Definition: environment.h:280
A container to hold the mapping between named variables of a specific type and their values...
Definition: environment.h:384
A simple class for tokenizing a stream of tokens for the formally specified language used to construc...
An interface for an environment in which variables of various types are mapped to their values...
Definition: environment.h:126
virtual void PrintFactories(ostream &os) const
Prints out a human-readable string with the names of all abstract base types and their concrete imple...
Provides an interface for an Environment, which contains a map from variables of a specific type (pri...
void Error(const std::string &message)
Reports an error encountered during parsing and/or construction of an object.
Definition: error.cc:47
Provides a set of named variables and their types, as well as the values for those variables...
virtual VarMapBase * GetVarMap(const string &varname)
Retrieves the VarMap instance for the specified variable.
A base class for a mapping from variables of a specific type to their values.
Definition: environment.h:66
virtual VarMapBase * GetVarMapForType(const string &type)
Retrieves the VarMap instance for the specified type.