Synopsis - Cross-Reference
File: src/Synopsis/SymbolLookup/Scopes.cc1// 2// Copyright (C) 2004 Stefan Seefeld 3// All rights reserved. 4// Licensed to the public under the terms of the GNU LGPL (>= 2), 5// see the file COPYING for details. 6// 7#include <Synopsis/SymbolLookup/Scopes.hh> 8#include <Synopsis/PTree/Writer.hh> 9#include <Synopsis/PTree/Display.hh> 10#include <Synopsis/Trace.hh> 11#include <sstream> 12#include <cassert> 13 14using namespace Synopsis; 15using namespace PTree; 16using namespace SymbolLookup; 17 18SymbolSet 19TemplateParameterScope::unqualified_lookup(Encoding const &name, 20 LookupContext context) const 21{ 22 Trace trace("TemplateParameterScope::unqualified_lookup", Trace::SYMBOLLOOKUP); 23 trace << name; 24 SymbolSet symbols = find(name, context == SCOPE); 25 return symbols.size() ? symbols : my_outer->unqualified_lookup(name, context); 26} 27 28SymbolSet 29LocalScope::unqualified_lookup(Encoding const &name, 30 LookupContext context) const 31{ 32 Trace trace("LocalScope::unqualified_lookup", Trace::SYMBOLLOOKUP); 33 trace << name; 34 SymbolSet symbols = find(name, context == SCOPE); 35 return symbols.size() ? symbols : my_outer->unqualified_lookup(name, context); 36} 37 38FunctionScope::FunctionScope(PTree::Declaration const *decl, 39 PrototypeScope *proto, 40 Scope const *outer) 41 : my_decl(decl), my_outer(outer->ref()), 42 my_parameters(proto->parameters()) 43{ 44 for (SymbolTable::iterator i = proto->my_symbols.begin(); 45 i != proto->my_symbols.end(); 46 ++i) 47 { 48 Symbol const *symbol = i->second; 49 my_symbols.insert(std::make_pair(i->first, 50 new VariableName(symbol->type(), 51 symbol->ptree(), 52 true, this))); 53 } 54 proto->unref(); 55} 56 57void FunctionScope::use(PTree::UsingDirective const *udecl) 58{ 59 if (*PTree::second(udecl) == "namespace") // using.dir 60 { 61 PTree::Encoding name = PTree::third(udecl)->encoded_name(); 62 SymbolSet symbols = lookup(name); 63 // now get the namespace associated with that symbol: 64 Symbol const *symbol = *symbols.begin(); 65 // FIXME: may this symbol-to-scope conversion be implemented 66 // by the appropriate Symbol subclass(es) ? 67 Scope const *scope = symbol->scope()->find_scope(name, symbol); 68 Namespace const *ns = dynamic_cast<Namespace const *>(scope); 69 if (ns) my_using.insert(ns); 70 } 71 else 72 { 73 std::cout << "sorry, using declaration not supported yet" << std::endl; 74 } 75} 76 77SymbolSet 78FunctionScope::unqualified_lookup(Encoding const &name, 79 LookupContext context) const 80{ 81 Trace trace("FunctionScope::unqualified_lookup", Trace::SYMBOLLOOKUP); 82 trace << name; 83 SymbolSet symbols = find(name, context); 84 if (my_parameters) 85 { 86 SymbolSet more = my_parameters->find(name, context); 87 symbols.insert(more.begin(), more.end()); 88 } 89 if (symbols.size()) return symbols; 90 91 // see 7.3.4 [namespace.udir] 92 for (Using::const_iterator i = my_using.begin(); i != my_using.end(); ++i) 93 { 94 SymbolSet more = (*i)->unqualified_lookup(name, context | USING); 95 symbols.insert(more.begin(), more.end()); 96 } 97 if (symbols.size() || !my_outer) 98 return symbols; 99 else 100 return my_outer->unqualified_lookup(name, context); 101} 102 103std::string FunctionScope::name() const 104{ 105 std::ostringstream oss; 106 oss << PTree::reify(PTree::third(my_decl)); 107 return oss.str(); 108} 109 110SymbolSet 111FunctionScope::qualified_lookup(PTree::Encoding const &name, 112 LookupContext context) const 113{ 114 Trace trace("FunctionScope::qualified_lookup", Trace::SYMBOLLOOKUP); 115 trace << name; 116 PTree::Encoding symbol_name = name.get_scope(); 117 PTree::Encoding remainder = name.get_symbol(); 118 119 if (symbol_name.empty()) 120 { 121 symbol_name = name; 122 remainder.clear(); 123 } 124 125 // find symbol locally 126 SymbolSet symbols = find(symbol_name, context); 127 // see 7.3.4 [namespace.udir] 128 if (symbols.empty()) 129 for (Using::const_iterator i = my_using.begin(); i != my_using.end(); ++i) 130 { 131 SymbolSet more = (*i)->qualified_lookup(name, context); 132 symbols.insert(more.begin(), more.end()); 133 } 134 if (symbols.empty()) return symbols; // nothing found 135 136 // If the remainder is empty, just return the found symbol(s). 137 else if (remainder.empty()) return symbols; 138 139 // Having multiple symbols implies they are all overloaded functions. 140 // That's a type error if the reminder is non-empty, as we are looking 141 // for a scope. 142 else if (symbols.size() > 1) 143 throw TypeError(symbol_name, (*symbols.begin())->ptree()->encoded_type()); 144 145 // Find the scope the symbol refers to 146 // and look up the remainder there. 147 148 // move into inner scope and start over the lookup 149 Scope const *nested = find_scope(symbol_name, *symbols.begin()); 150 if (!nested) throw InternalError("undeclared scope !"); 151 152 return nested->qualified_lookup(remainder, context); 153} 154 155SymbolSet 156PrototypeScope::unqualified_lookup(PTree::Encoding const &, 157 LookupContext) const 158{ 159 Trace trace("PrototypeScope::unqualified_lookup", Trace::SYMBOLLOOKUP); 160 return SymbolSet(); 161} 162 163std::string PrototypeScope::name() const 164{ 165 std::ostringstream oss; 166 oss << PTree::reify(my_decl); 167 return oss.str(); 168} 169 170SymbolSet 171Class::unqualified_lookup(Encoding const &name, 172 LookupContext context) const 173{ 174 Trace trace("Class::unqualified_lookup", Trace::SYMBOLLOOKUP); 175 trace << name; 176 SymbolSet symbols = find(name, context); 177 for (Bases::const_iterator i = my_bases.begin(); i != my_bases.end(); ++i) 178 { 179 SymbolSet more = (*i)->find(name, context); 180 symbols.insert(more.begin(), more.end()); 181 } 182 if (my_parameters) 183 { 184 SymbolSet more = my_parameters->find(name, context); 185 symbols.insert(more.begin(), more.end()); 186 } 187 return symbols.size() ? symbols : my_outer->unqualified_lookup(name, context); 188} 189 190std::string Class::name() const 191{ 192 PTree::Node const *name_spec = PTree::second(my_spec); 193 // FIXME: why is name_spec for anonumous classes 'list(0, 0)' ? 194 // see Parser::class_spec()... 195 if (name_spec && name_spec->is_atom()) 196 return std::string(name_spec->position(), name_spec->length()); 197 return ""; 198} 199 200Namespace *Namespace::find_namespace(PTree::NamespaceSpec const *spec) const 201{ 202 std::string name = "<anonymous>"; 203 PTree::Node const *ns_name = PTree::second(spec); 204 if (ns_name) 205 name.assign(ns_name->position(), ns_name->length()); 206 for (ScopeTable::const_iterator i = my_scopes.begin(); 207 i != my_scopes.end(); 208 ++i) 209 { 210 Namespace *ns = dynamic_cast<Namespace *>(i->second); 211 if (ns && name == ns->name()) 212 return ns; 213 } 214 return 0; 215} 216 217void Namespace::use(PTree::UsingDirective const *udecl) 218{ 219 if (*PTree::second(udecl) == "namespace") // using.dir 220 { 221 PTree::Encoding name = PTree::third(udecl)->encoded_name(); 222 SymbolSet symbols = lookup(name); 223 // now get the namespace associated with that symbol: 224 Symbol const *symbol = *symbols.begin(); 225 // FIXME: may this symbol-to-scope conversion be implemented 226 // by the appropriate Symbol subclass(es) ? 227 Scope const *scope = symbol->scope()->find_scope(name, symbol); 228 Namespace const *ns = dynamic_cast<Namespace const *>(scope); 229 if (ns) my_using.insert(ns); 230 } 231 else 232 { 233 std::cout << "sorry, using declaration not supported yet" << std::endl; 234 } 235} 236 237SymbolSet 238Namespace::unqualified_lookup(Encoding const &name, 239 LookupContext context) const 240{ 241 Using searched; 242 return unqualified_lookup(name, context, searched); 243} 244 245SymbolSet 246Namespace::qualified_lookup(PTree::Encoding const &name, 247 LookupContext context) const 248{ 249 Using searched; 250 return qualified_lookup(name, context, searched); 251} 252 253std::string Namespace::name() const 254{ 255 if (!my_spec) return "<global>"; 256 PTree::Node const *name_spec = PTree::second(my_spec); 257 if (name_spec) 258 return std::string(name_spec->position(), name_spec->length()); 259 else 260 return "<anonymous>"; 261} 262 263SymbolSet Namespace::unqualified_lookup(Encoding const &name, 264 LookupContext context, 265 Using &searched) const 266{ 267 Trace trace("Namespace::unqualified_lookup", Trace::SYMBOLLOOKUP, this->name()); 268 trace << name; 269 searched.insert(this); 270 SymbolSet symbols = find(name, context); 271 if (symbols.size()) return symbols; 272 273 // see 7.3.4 [namespace.udir] 274 for (Using::const_iterator i = my_using.begin(); i != my_using.end(); ++i) 275 if (searched.find(*i) == searched.end()) 276 { 277 SymbolSet more = (*i)->unqualified_lookup(name, context | USING, searched); 278 symbols.insert(more.begin(), more.end()); 279 } 280 if (symbols.size() || 281 context & USING || 282 !my_outer || 283 searched.find(my_outer) != searched.end()) 284 return symbols; 285 else 286 return my_outer->unqualified_lookup(name, context, searched); 287} 288 289SymbolSet Namespace::qualified_lookup(PTree::Encoding const &name, 290 LookupContext context, 291 Using &searched) const 292{ 293 Trace trace("Namespace::qualified_lookup", Trace::SYMBOLLOOKUP, this->name()); 294 trace << name; 295 296 PTree::Encoding symbol_name = name.get_scope(); 297 PTree::Encoding remainder = name.get_symbol(); 298 299 if (symbol_name.empty()) 300 { 301 symbol_name = name; 302 remainder.clear(); 303 } 304 305 // find symbol locally 306 SymbolSet symbols = find(symbol_name, context); 307 308 // see 3.4.3.2/2 and 3.4.3.2/6 309 if (!symbols.size() && (context ^ DECLARATION || name.is_qualified())) 310 for (Using::const_iterator i = my_using.begin(); i != my_using.end(); ++i) 311 if (searched.find(*i) == searched.end()) 312 { 313 SymbolSet more = (*i)->qualified_lookup(name, context, searched); 314 symbols.insert(more.begin(), more.end()); 315 } 316 if (symbols.empty()) return symbols; // nothing found 317 318 // If the remainder is empty, just return the found symbol(s). 319 else if (remainder.empty()) return symbols; 320 321 // Having multiple symbols implies they are all overloaded functions. 322 // That's a type error if the reminder is non-empty, as we are looking 323 // for a scope. 324 else if (symbols.size() > 1) 325 throw TypeError(symbol_name, (*symbols.begin())->ptree()->encoded_type()); 326 327 // Find the scope the symbol refers to 328 // and look up the remainder there. 329 330 // move into inner scope and start over the lookup 331 Scope const *nested = find_scope(symbol_name, *symbols.begin()); 332 if (!nested) throw InternalError("undeclared scope !"); 333 334 return nested->qualified_lookup(remainder, context); 335} 336
Generated on Tue May 13 02:39:45 2008 by
synopsis (version 0.10)
synopsis (version 0.10)