| David Reiss | ea2cba8 | 2009-03-30 21:35:00 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * Licensed to the Apache Software Foundation (ASF) under one | 
 | 3 |  * or more contributor license agreements. See the NOTICE file | 
 | 4 |  * distributed with this work for additional information | 
 | 5 |  * regarding copyright ownership. The ASF licenses this file | 
 | 6 |  * to you under the Apache License, Version 2.0 (the | 
 | 7 |  * "License"); you may not use this file except in compliance | 
 | 8 |  * with the License. You may obtain a copy of the License at | 
 | 9 |  * | 
 | 10 |  *   http://www.apache.org/licenses/LICENSE-2.0 | 
 | 11 |  * | 
 | 12 |  * Unless required by applicable law or agreed to in writing, | 
 | 13 |  * software distributed under the License is distributed on an | 
 | 14 |  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
 | 15 |  * KIND, either express or implied. See the License for the | 
 | 16 |  * specific language governing permissions and limitations | 
 | 17 |  * under the License. | 
 | 18 |  */ | 
| Mark Slee | e9ce01c | 2007-05-16 02:29:53 +0000 | [diff] [blame] | 19 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 20 | #ifndef T_SCOPE_H | 
 | 21 | #define T_SCOPE_H | 
 | 22 |  | 
 | 23 | #include <map> | 
 | 24 | #include <string> | 
| David Reiss | aca320d | 2010-08-31 16:51:26 +0000 | [diff] [blame] | 25 | #include <sstream> | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 26 |  | 
 | 27 | #include "t_type.h" | 
 | 28 | #include "t_service.h" | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 29 | #include "t_const.h" | 
 | 30 | #include "t_const_value.h" | 
 | 31 | #include "t_base_type.h" | 
 | 32 | #include "t_map.h" | 
 | 33 | #include "t_list.h" | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 34 |  | 
 | 35 | /** | 
 | 36 |  * This represents a variable scope used for looking up predefined types and | 
 | 37 |  * services. Typically, a scope is associated with a t_program. Scopes are not | 
 | 38 |  * used to determine code generation, but rather to resolve identifiers at | 
 | 39 |  * parse time. | 
 | 40 |  * | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 41 |  */ | 
 | 42 | class t_scope { | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 43 |  public: | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 44 |   t_scope() {} | 
 | 45 |  | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 46 |   void add_type(std::string name, t_type* type) { | 
 | 47 |     types_[name] = type; | 
 | 48 |   } | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 49 |  | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 50 |   t_type* get_type(std::string name) { | 
 | 51 |     return types_[name]; | 
 | 52 |   } | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 53 |  | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 54 |   void add_service(std::string name, t_service* service) { | 
 | 55 |     services_[name] = service; | 
 | 56 |   } | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 57 |  | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 58 |   t_service* get_service(std::string name) { | 
 | 59 |     return services_[name]; | 
 | 60 |   } | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 61 |  | 
| Mark Slee | d0767c5 | 2007-07-27 22:14:41 +0000 | [diff] [blame] | 62 |   void add_constant(std::string name, t_const* constant) { | 
| Bryan Duxbury | 8fc413f | 2010-08-05 23:23:04 +0000 | [diff] [blame] | 63 |     if (constants_.find(name) != constants_.end()) { | 
 | 64 |       throw "Enum " + name + " is already defined!"; | 
 | 65 |     } else { | 
 | 66 |       constants_[name] = constant; | 
 | 67 |     } | 
| Mark Slee | d0767c5 | 2007-07-27 22:14:41 +0000 | [diff] [blame] | 68 |   } | 
 | 69 |  | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 70 |   t_const* get_constant(std::string name) { | 
 | 71 |     return constants_[name]; | 
 | 72 |   } | 
| Mark Slee | d0767c5 | 2007-07-27 22:14:41 +0000 | [diff] [blame] | 73 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 74 |   void print() { | 
 | 75 |     std::map<std::string, t_type*>::iterator iter; | 
 | 76 |     for (iter = types_.begin(); iter != types_.end(); ++iter) { | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 77 |       printf("%s => %s\n", | 
 | 78 |              iter->first.c_str(), | 
 | 79 |              iter->second->get_name().c_str()); | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 80 |     } | 
 | 81 |   } | 
 | 82 |  | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 83 |   void resolve_const_value(t_const_value* const_val, t_type* ttype) { | 
 | 84 |     if (ttype->is_map()) { | 
 | 85 |       const std::map<t_const_value*, t_const_value*>& map = const_val->get_map(); | 
 | 86 |       std::map<t_const_value*, t_const_value*>::const_iterator v_iter; | 
 | 87 |       for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { | 
 | 88 |         resolve_const_value(v_iter->first, ((t_map*)ttype)->get_key_type()); | 
 | 89 |         resolve_const_value(v_iter->second, ((t_map*)ttype)->get_val_type()); | 
 | 90 |       } | 
 | 91 |     } else if (ttype->is_list() || ttype->is_set()) { | 
 | 92 |       const std::vector<t_const_value*>& val = const_val->get_list(); | 
 | 93 |       std::vector<t_const_value*>::const_iterator v_iter; | 
 | 94 |       for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { | 
 | 95 |         resolve_const_value((*v_iter), ((t_list*)ttype)->get_elem_type()); | 
 | 96 |       } | 
 | 97 |     } else if (ttype->is_struct()) { | 
 | 98 |       t_struct* tstruct = (t_struct*)ttype; | 
 | 99 |       const std::map<t_const_value*, t_const_value*>& map = const_val->get_map(); | 
 | 100 |       std::map<t_const_value*, t_const_value*>::const_iterator v_iter; | 
 | 101 |       for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { | 
 | 102 |         t_field* field = tstruct->get_field_by_name(v_iter->first->get_string()); | 
| Bryan Duxbury | 656683c | 2010-06-23 16:57:51 +0000 | [diff] [blame] | 103 |         if (field == NULL) { | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 104 |           throw "No field named \"" + v_iter->first->get_string() + "\" was found in struct of type \"" + tstruct->get_name() + "\""; | 
| Bryan Duxbury | 656683c | 2010-06-23 16:57:51 +0000 | [diff] [blame] | 105 |         } | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 106 |         resolve_const_value(v_iter->second, field->get_type()); | 
 | 107 |       } | 
 | 108 |     } else if (const_val->get_type() == t_const_value::CV_IDENTIFIER) { | 
 | 109 |       if (ttype->is_enum()) { | 
 | 110 |         const_val->set_enum((t_enum*)ttype); | 
 | 111 |       } else { | 
 | 112 |         t_const* constant = get_constant(const_val->get_identifier()); | 
 | 113 |         if (constant == NULL) { | 
 | 114 |           throw "No enum value or constant found named \"" + const_val->get_identifier() + "\"!"; | 
 | 115 |         } | 
 | 116 |  | 
| David Reiss | 41d3058 | 2010-10-05 16:39:29 +0000 | [diff] [blame] | 117 |         // Resolve typedefs to the underlying type | 
 | 118 |         t_type* const_type = constant->get_type()->get_true_type(); | 
 | 119 |  | 
 | 120 |         if (const_type->is_base_type()) { | 
 | 121 |           switch (((t_base_type*)const_type)->get_base()) { | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 122 |             case t_base_type::TYPE_I16: | 
 | 123 |             case t_base_type::TYPE_I32: | 
 | 124 |             case t_base_type::TYPE_I64: | 
 | 125 |             case t_base_type::TYPE_BOOL: | 
 | 126 |             case t_base_type::TYPE_BYTE: | 
 | 127 |               const_val->set_integer(constant->get_value()->get_integer()); | 
 | 128 |               break; | 
 | 129 |             case t_base_type::TYPE_STRING: | 
 | 130 |               const_val->set_string(constant->get_value()->get_string()); | 
 | 131 |               break; | 
 | 132 |             case t_base_type::TYPE_DOUBLE: | 
 | 133 |               const_val->set_double(constant->get_value()->get_double()); | 
 | 134 |               break; | 
 | 135 |             case t_base_type::TYPE_VOID: | 
 | 136 |               throw "Constants cannot be of type VOID"; | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 137 |           } | 
| David Reiss | 41d3058 | 2010-10-05 16:39:29 +0000 | [diff] [blame] | 138 |         } else if (const_type->is_map()) { | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 139 |           const std::map<t_const_value*, t_const_value*>& map = constant->get_value()->get_map(); | 
 | 140 |           std::map<t_const_value*, t_const_value*>::const_iterator v_iter; | 
 | 141 |  | 
 | 142 |           const_val->set_map(); | 
 | 143 |           for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { | 
 | 144 |             const_val->add_map(v_iter->first, v_iter->second); | 
 | 145 |           } | 
| David Reiss | 41d3058 | 2010-10-05 16:39:29 +0000 | [diff] [blame] | 146 |         } else if (const_type->is_list()) { | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 147 |           const std::vector<t_const_value*>& val = constant->get_value()->get_list(); | 
 | 148 |           std::vector<t_const_value*>::const_iterator v_iter; | 
 | 149 |  | 
 | 150 |           const_val->set_list(); | 
 | 151 |           for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { | 
 | 152 |             const_val->add_list(*v_iter); | 
 | 153 |           } | 
 | 154 |         } | 
 | 155 |       } | 
 | 156 |     } else if (ttype->is_enum()) { | 
 | 157 |       // enum constant with non-identifier value. set the enum and find the | 
 | 158 |       // value's name. | 
 | 159 |       t_enum* tenum = (t_enum*)ttype; | 
 | 160 |       t_enum_value* enum_value = tenum->get_constant_by_value(const_val->get_integer()); | 
 | 161 |       if (enum_value == NULL) { | 
| David Reiss | aca320d | 2010-08-31 16:51:26 +0000 | [diff] [blame] | 162 |         std::ostringstream valstm; | 
 | 163 |         valstm << const_val->get_integer(); | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 164 |         throw "Couldn't find a named value in enum " + tenum->get_name() + " for value " + valstm.str(); | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 165 |       } | 
| Bryan Duxbury | cb0218f | 2010-09-12 15:22:21 +0000 | [diff] [blame] | 166 |       const_val->set_identifier(tenum->get_name() + "." + enum_value->get_name()); | 
| Bryan Duxbury | 2d80470 | 2009-12-18 19:41:11 +0000 | [diff] [blame] | 167 |       const_val->set_enum(tenum); | 
 | 168 |     } | 
 | 169 |   } | 
 | 170 |  | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 171 |  private: | 
 | 172 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 173 |   // Map of names to types | 
 | 174 |   std::map<std::string, t_type*> types_; | 
 | 175 |  | 
| Mark Slee | d0767c5 | 2007-07-27 22:14:41 +0000 | [diff] [blame] | 176 |   // Map of names to constants | 
 | 177 |   std::map<std::string, t_const*> constants_; | 
 | 178 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 179 |   // Map of names to services | 
| David Reiss | 0c90f6f | 2008-02-06 22:18:40 +0000 | [diff] [blame] | 180 |   std::map<std::string, t_service*> services_; | 
| Konrad Grochowski | 240120c | 2014-11-18 11:33:31 +0100 | [diff] [blame^] | 181 |  | 
| Mark Slee | f0712dc | 2006-10-25 19:03:57 +0000 | [diff] [blame] | 182 | }; | 
 | 183 |  | 
 | 184 | #endif |