Line data Source code
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 : * Copyright 2006-2017 The Apache Software Foundation. 20 : * https://github.com/apache/thrift 21 : */ 22 : 23 : #ifndef T_SCOPE_H 24 : #define T_SCOPE_H 25 : 26 : #include <map> 27 : #include <string> 28 : #include <sstream> 29 : 30 : #include "t_type.h" 31 : #include "t_service.h" 32 : #include "t_const.h" 33 : #include "t_const_value.h" 34 : #include "t_base_type.h" 35 : #include "t_map.h" 36 : #include "t_list.h" 37 : #ifdef SANDESH 38 : #include "t_sandesh.h" 39 : #endif 40 : 41 : /** 42 : * This represents a variable scope used for looking up predefined types and 43 : * services. Typically, a scope is associated with a t_program. Scopes are not 44 : * used to determine code generation, but rather to resolve identifiers at 45 : * parse time. 46 : * 47 : */ 48 : class t_scope { 49 : public: 50 776 : t_scope() {} 51 : 52 7450 : void add_type(std::string name, t_type* type) { 53 7450 : types_[name] = type; 54 7450 : } 55 : 56 5619 : t_type* get_type(std::string name) { 57 5619 : return types_[name]; 58 : } 59 : 60 0 : void add_service(std::string name, t_service* service) { 61 0 : services_[name] = service; 62 0 : } 63 : 64 0 : t_service* get_service(std::string name) { 65 0 : return services_[name]; 66 : } 67 : 68 : #ifdef SANDESH 69 8080 : void add_sandesh(std::string name, t_sandesh* sandesh) { 70 8080 : sandeshs_[name] = sandesh; 71 8080 : } 72 : 73 5804 : t_sandesh* get_sandesh(std::string name) { 74 5804 : return sandeshs_[name]; 75 : } 76 : #endif 77 : 78 8638 : void add_constant(std::string name, t_const* constant) { 79 8638 : if (constants_.find(name) != constants_.end()) { 80 0 : throw "Enum " + name + " is already defined!"; 81 : } else { 82 8638 : constants_[name] = constant; 83 : } 84 8638 : } 85 : 86 4120 : t_const* get_constant(std::string name) { 87 4120 : return constants_[name]; 88 : } 89 : 90 : void print() { 91 : std::map<std::string, t_type*>::iterator iter; 92 : for (iter = types_.begin(); iter != types_.end(); ++iter) { 93 : printf("%s => %s\n", 94 : iter->first.c_str(), 95 : iter->second->get_name().c_str()); 96 : } 97 : } 98 : 99 37530 : void resolve_const_value(t_const_value* const_val, t_type* ttype) { 100 37530 : if (ttype->is_map()) { 101 535 : const std::map<t_const_value*, t_const_value*>& map = const_val->get_map(); 102 535 : std::map<t_const_value*, t_const_value*>::const_iterator v_iter; 103 6207 : for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { 104 5672 : resolve_const_value(v_iter->first, ((t_map*)ttype)->get_key_type()); 105 5672 : resolve_const_value(v_iter->second, ((t_map*)ttype)->get_val_type()); 106 : } 107 36995 : } else if (ttype->is_list() || ttype->is_set()) { 108 964 : const std::vector<t_const_value*>& val = const_val->get_list(); 109 964 : std::vector<t_const_value*>::const_iterator v_iter; 110 7641 : for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 111 6677 : resolve_const_value((*v_iter), ((t_list*)ttype)->get_elem_type()); 112 : } 113 36031 : } else if (ttype->is_struct()) { 114 4940 : t_struct* tstruct = (t_struct*)ttype; 115 4940 : const std::map<t_const_value*, t_const_value*>& map = const_val->get_map(); 116 4940 : std::map<t_const_value*, t_const_value*>::const_iterator v_iter; 117 20800 : for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { 118 15860 : t_field* field = tstruct->get_field_by_name(v_iter->first->get_string()); 119 15860 : if (field == NULL) { 120 0 : throw "No field named \"" + v_iter->first->get_string() + "\" was found in struct of type \"" + tstruct->get_name() + "\""; 121 : } 122 15860 : resolve_const_value(v_iter->second, field->get_type()); 123 : } 124 31091 : } else if (const_val->get_type() == t_const_value::CV_IDENTIFIER) { 125 9092 : if (ttype->is_enum()) { 126 4972 : const_val->set_enum((t_enum*)ttype); 127 : } else { 128 4120 : t_const* constant = get_constant(const_val->get_identifier()); 129 4120 : if (constant == NULL) { 130 0 : throw "No enum value or constant found named \"" + const_val->get_identifier() + "\"!"; 131 : } 132 : 133 : // Resolve typedefs to the underlying type 134 4120 : t_type* const_type = constant->get_type()->get_true_type(); 135 : 136 4120 : if (const_type->is_base_type()) { 137 4120 : switch (((t_base_type*)const_type)->get_base()) { 138 159 : case t_base_type::TYPE_I16: 139 : case t_base_type::TYPE_I32: 140 : case t_base_type::TYPE_I64: 141 : case t_base_type::TYPE_BOOL: 142 : case t_base_type::TYPE_BYTE: 143 159 : const_val->set_integer(constant->get_value()->get_integer()); 144 159 : break; 145 3631 : case t_base_type::TYPE_STRING: 146 3631 : const_val->set_string(constant->get_value()->get_string()); 147 3631 : break; 148 0 : case t_base_type::TYPE_DOUBLE: 149 0 : const_val->set_double(constant->get_value()->get_double()); 150 0 : break; 151 0 : case t_base_type::TYPE_VOID: 152 0 : throw "Constants cannot be of type VOID"; 153 : #ifdef SANDESH 154 330 : case t_base_type::TYPE_U16: 155 : case t_base_type::TYPE_U32: 156 : case t_base_type::TYPE_U64: 157 330 : const_val->set_integer(constant->get_value()->get_integer()); 158 330 : break; 159 0 : case t_base_type::TYPE_STATIC_CONST_STRING: 160 : case t_base_type::TYPE_XML: 161 0 : const_val->set_string(constant->get_value()->get_string()); 162 0 : break; 163 0 : case t_base_type::TYPE_SANDESH_SYSTEM: 164 0 : break; 165 0 : case t_base_type::TYPE_SANDESH_REQUEST: 166 0 : break; 167 0 : case t_base_type::TYPE_SANDESH_RESPONSE: 168 0 : break; 169 0 : case t_base_type::TYPE_SANDESH_TRACE: 170 0 : break; 171 0 : case t_base_type::TYPE_SANDESH_TRACE_OBJECT: 172 0 : break; 173 0 : case t_base_type::TYPE_SANDESH_BUFFER: 174 0 : break; 175 0 : case t_base_type::TYPE_SANDESH_UVE: 176 0 : break; 177 0 : case t_base_type::TYPE_SANDESH_DYNAMIC_UVE: 178 0 : break; 179 0 : case t_base_type::TYPE_SANDESH_OBJECT: 180 0 : break; 181 0 : case t_base_type::TYPE_SANDESH_FLOW: 182 0 : break; 183 0 : case t_base_type::TYPE_SANDESH_SESSION: 184 0 : break; 185 : #endif 186 : } 187 0 : } else if (const_type->is_map()) { 188 0 : const std::map<t_const_value*, t_const_value*>& map = constant->get_value()->get_map(); 189 0 : std::map<t_const_value*, t_const_value*>::const_iterator v_iter; 190 : 191 0 : const_val->set_map(); 192 0 : for (v_iter = map.begin(); v_iter != map.end(); ++v_iter) { 193 0 : const_val->add_map(v_iter->first, v_iter->second); 194 : } 195 0 : } else if (const_type->is_list()) { 196 0 : const std::vector<t_const_value*>& val = constant->get_value()->get_list(); 197 0 : std::vector<t_const_value*>::const_iterator v_iter; 198 : 199 0 : const_val->set_list(); 200 0 : for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) { 201 0 : const_val->add_list(*v_iter); 202 : } 203 : } 204 : } 205 21999 : } else if (ttype->is_enum()) { 206 : // enum constant with non-identifier value. set the enum and find the 207 : // value's name. 208 0 : t_enum* tenum = (t_enum*)ttype; 209 0 : t_enum_value* enum_value = tenum->get_constant_by_value(const_val->get_integer()); 210 0 : if (enum_value == NULL) { 211 0 : std::ostringstream valstm; 212 0 : valstm << const_val->get_integer(); 213 0 : throw "Couldn't find a named value in enum " + tenum->get_name() + " for value " + valstm.str(); 214 0 : } 215 0 : const_val->set_identifier(tenum->get_name() + "." + enum_value->get_name()); 216 0 : const_val->set_enum(tenum); 217 : } 218 37530 : } 219 : 220 : private: 221 : 222 : // Map of names to types 223 : std::map<std::string, t_type*> types_; 224 : 225 : // Map of names to constants 226 : std::map<std::string, t_const*> constants_; 227 : 228 : // Map of names to services 229 : std::map<std::string, t_service*> services_; 230 : 231 : #ifdef SANDESH 232 : // Map of names to sandeshs 233 : std::map<std::string, t_sandesh*> sandeshs_; 234 : #endif 235 : 236 : }; 237 : 238 : #endif