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 */ 19 20 #ifndef T_SCOPE_H 21 #define T_SCOPE_H 22 23 #include <map> 24 #include <string> 25 #include <sstream> 26 27 #include "thrift/parse/t_type.h" 28 #include "thrift/parse/t_service.h" 29 #include "thrift/parse/t_const.h" 30 #include "thrift/parse/t_const_value.h" 31 #include "thrift/parse/t_base_type.h" 32 #include "thrift/parse/t_map.h" 33 #include "thrift/parse/t_list.h" 34 #include "thrift/parse/t_set.h" 35 36 /** 37 * This represents a variable scope used for looking up predefined types and 38 * services. Typically, a scope is associated with a t_program. Scopes are not 39 * used to determine code generation, but rather to resolve identifiers at 40 * parse time. 41 * 42 */ 43 class t_scope { 44 public: 45 t_scope() = default; 46 add_type(std::string name,t_type * type)47 void add_type(std::string name, t_type* type) { types_[name] = type; } 48 get_type(std::string name)49 t_type* get_type(std::string name) { return types_[name]; } 50 get_type(std::string name)51 const t_type* get_type(std::string name) const { 52 const auto it = types_.find(name); 53 if (types_.end() != it) 54 { 55 return it->second; 56 } 57 return nullptr; 58 } 59 add_service(std::string name,t_service * service)60 void add_service(std::string name, t_service* service) { services_[name] = service; } 61 get_service(std::string name)62 t_service* get_service(std::string name) { return services_[name]; } 63 get_service(std::string name)64 const t_service* get_service(std::string name) const { 65 const auto it = services_.find(name); 66 if (services_.end() != it) 67 { 68 return it->second; 69 } 70 return nullptr; 71 } 72 add_constant(std::string name,t_const * constant)73 void add_constant(std::string name, t_const* constant) { 74 if (constants_.find(name) != constants_.end()) { 75 throw "Enum " + name + " is already defined!"; 76 } else { 77 constants_[name] = constant; 78 } 79 } 80 get_constant(std::string name)81 t_const* get_constant(std::string name) { return constants_[name]; } 82 get_constant(std::string name)83 const t_const* get_constant(std::string name) const { 84 const auto it = constants_.find(name); 85 if (constants_.end() != it) 86 { 87 return it->second; 88 } 89 return nullptr; 90 } 91 print()92 void print() { 93 std::map<std::string, t_type*>::iterator iter; 94 for (iter = types_.begin(); iter != types_.end(); ++iter) { 95 printf("%s => %s\n", iter->first.c_str(), iter->second->get_name().c_str()); 96 } 97 } 98 resolve_const_value(t_const_value * const_val,t_type * ttype)99 void resolve_const_value(t_const_value* const_val, t_type* ttype) { 100 if (ttype->is_map()) { 101 const std::map<t_const_value*, t_const_value*, t_const_value::value_compare>& map = const_val->get_map(); 102 std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 103 for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { 104 resolve_const_value(v_iter->first, ((t_map*)ttype)->get_key_type()); 105 resolve_const_value(v_iter->second, ((t_map*)ttype)->get_val_type()); 106 } 107 } else if (ttype->is_list()) { 108 const std::vector<t_const_value*>& val = const_val->get_list(); 109 std::vector<t_const_value*>::const_iterator v_iter; 110 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 111 resolve_const_value((*v_iter), ((t_list*)ttype)->get_elem_type()); 112 } 113 } else if (ttype->is_set()) { 114 const std::vector<t_const_value*>& val = const_val->get_list(); 115 std::vector<t_const_value*>::const_iterator v_iter; 116 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 117 resolve_const_value((*v_iter), ((t_set*)ttype)->get_elem_type()); 118 } 119 } else if (ttype->is_struct()) { 120 auto* tstruct = (t_struct*)ttype; 121 const std::map<t_const_value*, t_const_value*, t_const_value::value_compare>& map = const_val->get_map(); 122 std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 123 for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { 124 t_field* field = tstruct->get_field_by_name(v_iter->first->get_string()); 125 if (field == nullptr) { 126 throw "No field named \"" + v_iter->first->get_string() 127 + "\" was found in struct of type \"" + tstruct->get_name() + "\""; 128 } 129 resolve_const_value(v_iter->second, field->get_type()); 130 } 131 } else if (const_val->get_type() == t_const_value::CV_IDENTIFIER) { 132 if (ttype->is_enum()) { 133 const_val->set_enum((t_enum*)ttype); 134 } else { 135 t_const* constant = get_constant(const_val->get_identifier()); 136 if (constant == nullptr) { 137 throw "No enum value or constant found named \"" + const_val->get_identifier() + "\"!"; 138 } 139 140 // Resolve typedefs to the underlying type 141 t_type* const_type = constant->get_type()->get_true_type(); 142 143 if (const_type->is_base_type()) { 144 switch (((t_base_type*)const_type)->get_base()) { 145 case t_base_type::TYPE_I16: 146 case t_base_type::TYPE_I32: 147 case t_base_type::TYPE_I64: 148 case t_base_type::TYPE_BOOL: 149 case t_base_type::TYPE_I8: 150 const_val->set_integer(constant->get_value()->get_integer()); 151 break; 152 case t_base_type::TYPE_STRING: 153 const_val->set_string(constant->get_value()->get_string()); 154 break; 155 case t_base_type::TYPE_DOUBLE: 156 const_val->set_double(constant->get_value()->get_double()); 157 break; 158 case t_base_type::TYPE_VOID: 159 throw "Constants cannot be of type VOID"; 160 } 161 } else if (const_type->is_map()) { 162 const std::map<t_const_value*, t_const_value*, t_const_value::value_compare>& map = constant->get_value()->get_map(); 163 std::map<t_const_value*, t_const_value*, t_const_value::value_compare>::const_iterator v_iter; 164 165 const_val->set_map(); 166 for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { 167 const_val->add_map(v_iter->first, v_iter->second); 168 } 169 } else if (const_type->is_list()) { 170 const std::vector<t_const_value*>& val = constant->get_value()->get_list(); 171 std::vector<t_const_value*>::const_iterator v_iter; 172 173 const_val->set_list(); 174 for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 175 const_val->add_list(*v_iter); 176 } 177 } 178 } 179 } else if (ttype->is_enum()) { 180 // enum constant with non-identifier value. set the enum and find the 181 // value's name. 182 auto* tenum = (t_enum*)ttype; 183 t_enum_value* enum_value = tenum->get_constant_by_value(const_val->get_integer()); 184 if (enum_value == nullptr) { 185 std::ostringstream valstm; 186 valstm << const_val->get_integer(); 187 throw "Couldn't find a named value in enum " + tenum->get_name() + " for value " 188 + valstm.str(); 189 } 190 const_val->set_identifier(tenum->get_name() + "." + enum_value->get_name()); 191 const_val->set_enum(tenum); 192 } 193 } 194 195 private: 196 // Map of names to types 197 std::map<std::string, t_type*> types_; 198 199 // Map of names to constants 200 std::map<std::string, t_const*> constants_; 201 202 // Map of names to services 203 std::map<std::string, t_service*> services_; 204 }; 205 206 #endif 207