Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

dtool/src/cppparser/cppIdentifier.cxx

Go to the documentation of this file.
00001 // Filename: cppIdentifier.cxx
00002 // Created by:  drose (26Oct99)
00003 //
00004 ////////////////////////////////////////////////////////////////////
00005 //
00006 // PANDA 3D SOFTWARE
00007 // Copyright (c) 2001, Disney Enterprises, Inc.  All rights reserved
00008 //
00009 // All use of this software is subject to the terms of the Panda 3d
00010 // Software license.  You should have received a copy of this license
00011 // along with this source code; you will also find a current copy of
00012 // the license at http://www.panda3d.org/license.txt .
00013 //
00014 // To contact the maintainers of this program write to
00015 // panda3d@yahoogroups.com .
00016 //
00017 ////////////////////////////////////////////////////////////////////
00018 
00019 
00020 #include "cppIdentifier.h"
00021 #include "cppScope.h"
00022 #include "cppTemplateScope.h"
00023 #include "cppPreprocessor.h"
00024 #include "cppTemplateParameterList.h"
00025 #include "cppTBDType.h"
00026 #include "cppStructType.h"
00027 
00028 
00029 ////////////////////////////////////////////////////////////////////
00030 //     Function: CPPIdentifier::Constructor
00031 //       Access: Public
00032 //  Description:
00033 ////////////////////////////////////////////////////////////////////
00034 CPPIdentifier::
00035 CPPIdentifier(const string &name, const CPPFile &file) : _file(file) {
00036   _names.push_back(CPPNameComponent(name));
00037   _native_scope = (CPPScope *)NULL;
00038 }
00039 
00040 ////////////////////////////////////////////////////////////////////
00041 //     Function: CPPIdentifier::Constructor
00042 //       Access: Public
00043 //  Description:
00044 ////////////////////////////////////////////////////////////////////
00045 CPPIdentifier::
00046 CPPIdentifier(const CPPNameComponent &name) {
00047   _names.push_back(name);
00048   _native_scope = (CPPScope *)NULL;
00049 }
00050 
00051 ////////////////////////////////////////////////////////////////////
00052 //     Function: CPPIdentifier::add_name
00053 //       Access: Public
00054 //  Description:
00055 ////////////////////////////////////////////////////////////////////
00056 void CPPIdentifier::
00057 add_name(const string &name) {
00058   _names.push_back(CPPNameComponent(name));
00059 }
00060 
00061 ////////////////////////////////////////////////////////////////////
00062 //     Function: CPPIdentifier::add_name
00063 //       Access: Public
00064 //  Description:
00065 ////////////////////////////////////////////////////////////////////
00066 void CPPIdentifier::
00067 add_name(const CPPNameComponent &name) {
00068   _names.push_back(name);
00069 }
00070 
00071 ////////////////////////////////////////////////////////////////////
00072 //     Function: CPPIdentifier::Equivalence Operator
00073 //       Access: Public
00074 //  Description:
00075 ////////////////////////////////////////////////////////////////////
00076 bool CPPIdentifier::
00077 operator == (const CPPIdentifier &other) const {
00078   if (_names.size() != other._names.size()) {
00079     return false;
00080   }
00081   for (int i = 0; i < (int)_names.size(); i++) {
00082     if (_names[i] != other._names[i]) {
00083       return false;
00084     }
00085   }
00086 
00087   return true;
00088 }
00089 
00090 ////////////////////////////////////////////////////////////////////
00091 //     Function: CPPIdentifier::Nonequivalence Operator
00092 //       Access: Public
00093 //  Description:
00094 ////////////////////////////////////////////////////////////////////
00095 bool CPPIdentifier::
00096 operator != (const CPPIdentifier &other) const {
00097   return !(*this == other);
00098 }
00099 
00100 ////////////////////////////////////////////////////////////////////
00101 //     Function: CPPIdentifier::Ordering Operator
00102 //       Access: Public
00103 //  Description:
00104 ////////////////////////////////////////////////////////////////////
00105 bool CPPIdentifier::
00106 operator < (const CPPIdentifier &other) const {
00107   if (_names.size() != other._names.size()) {
00108     return _names.size() < other._names.size();
00109   }
00110   for (int i = 0; i < (int)_names.size(); i++) {
00111     if (_names[i] != other._names[i]) {
00112       return _names[i] < other._names[i];
00113     }
00114   }
00115 
00116   return false;
00117 }
00118 
00119 ////////////////////////////////////////////////////////////////////
00120 //     Function: CPPIdentifier::is_scoped
00121 //       Access: Public
00122 //  Description:
00123 ////////////////////////////////////////////////////////////////////
00124 bool CPPIdentifier::
00125 is_scoped() const {
00126   return _names.size() > 1;
00127 }
00128 
00129 
00130 ////////////////////////////////////////////////////////////////////
00131 //     Function: CPPIdentifier::get_simple_name
00132 //       Access: Public
00133 //  Description:
00134 ////////////////////////////////////////////////////////////////////
00135 string CPPIdentifier::
00136 get_simple_name() const {
00137   return _names.back().get_name();
00138 }
00139 
00140 ////////////////////////////////////////////////////////////////////
00141 //     Function: CPPIdentifier::get_local_name
00142 //       Access: Public
00143 //  Description:
00144 ////////////////////////////////////////////////////////////////////
00145 string CPPIdentifier::
00146 get_local_name(CPPScope *scope) const {
00147   assert(!_names.empty());
00148 
00149   string result;
00150 
00151   if (scope == NULL || (_native_scope == NULL && _names.size() == 1)) {
00152     result = _names.back().get_name_with_templ(scope);
00153   } else if (_names.front().empty()) {
00154     result = get_fully_scoped_name();
00155   } else {
00156     // Determine the scope of everything up until but not including the
00157     // last name.
00158     CPPScope *my_scope = get_scope(scope, NULL);
00159 
00160     if (my_scope == NULL) {
00161       result = get_fully_scoped_name();
00162     } else if (my_scope == scope) {
00163       return _names.back().get_name_with_templ(scope);
00164     } else {
00165       result = my_scope->get_local_name(scope);
00166       if (!result.empty()) {
00167         result += "::";
00168       }
00169       result += _names.back().get_name_with_templ(scope);
00170     }
00171   }
00172   return result;
00173 }
00174 
00175 ////////////////////////////////////////////////////////////////////
00176 //     Function: CPPIdentifier::get_fully_scoped_name
00177 //       Access: Public
00178 //  Description:
00179 ////////////////////////////////////////////////////////////////////
00180 string CPPIdentifier::
00181 get_fully_scoped_name() const {
00182   assert(!_names.empty());
00183   Names::const_iterator ni = _names.begin();
00184   string name = (*ni).get_name_with_templ();
00185   ++ni;
00186   while (ni != _names.end()) {
00187     name += "::" + (*ni).get_name_with_templ();
00188     ++ni;
00189   }
00190   return name;
00191 }
00192 
00193 ////////////////////////////////////////////////////////////////////
00194 //     Function: CPPIdentifier::is_fully_specified
00195 //       Access: Public
00196 //  Description: Returns true if this declaration is an actual,
00197 //               factual declaration, or false if some part of the
00198 //               declaration depends on a template parameter which has
00199 //               not yet been instantiated.
00200 ////////////////////////////////////////////////////////////////////
00201 bool CPPIdentifier::
00202 is_fully_specified() const {
00203   Names::const_iterator ni;
00204   for (ni = _names.begin(); ni != _names.end(); ++ni) {
00205     if ((*ni).has_templ() && !(*ni).get_templ()->is_fully_specified()) {
00206       return false;
00207     }
00208   }
00209 
00210   return true;
00211 }
00212 
00213 ////////////////////////////////////////////////////////////////////
00214 //     Function: CPPIdentifier::is_tbd
00215 //       Access: Public
00216 //  Description: Returns true if the identifier includes a
00217 //               template parameter list that includes some
00218 //               not-yet-defined type.
00219 ////////////////////////////////////////////////////////////////////
00220 bool CPPIdentifier::
00221 is_tbd() const {
00222   Names::const_iterator ni;
00223   for (ni = _names.begin(); ni != _names.end(); ++ni) {
00224     if ((*ni).is_tbd()) {
00225       return true;
00226     }
00227   }
00228 
00229   return false;
00230 }
00231 
00232 ////////////////////////////////////////////////////////////////////
00233 //     Function: CPPIdentifier::get_scope
00234 //       Access: Public
00235 //  Description:
00236 ////////////////////////////////////////////////////////////////////
00237 CPPScope *CPPIdentifier::
00238 get_scope(CPPScope *current_scope, CPPScope *global_scope,
00239           CPPPreprocessor *error_sink) const {
00240   assert(!_names.empty());
00241 
00242   CPPScope *scope = _native_scope;
00243   if (scope == (CPPScope *)NULL) {
00244     scope = current_scope;
00245   }
00246   int i = 0;
00247 
00248   if (_names[i].empty()) {
00249     // This identifier starts with a ::, thus it begins at the global
00250     // scope.
00251     scope = global_scope;
00252     i++;
00253   }
00254 
00255   while (i + 1 < (int)_names.size() && scope != NULL) {
00256     CPPScope *next_scope = scope->find_scope(_names[i].get_name());
00257     if (next_scope == (CPPScope *)NULL) {
00258       if (error_sink != NULL) {
00259         error_sink->error("Symbol " + _names[i].get_name() +
00260                           " is not a known scope in " +
00261                           scope->get_fully_scoped_name());
00262       }
00263       return (CPPScope *)NULL;
00264     }
00265     if (_names[i].has_templ()) {
00266       next_scope = next_scope->instantiate(_names[i].get_templ(),
00267                                            current_scope, global_scope);
00268     }
00269     scope = next_scope;
00270     i++;
00271   }
00272 
00273   return scope;
00274 }
00275 
00276 ////////////////////////////////////////////////////////////////////
00277 //     Function: CPPIdentifier::get_scope
00278 //       Access: Public
00279 //  Description:
00280 ////////////////////////////////////////////////////////////////////
00281 CPPScope *CPPIdentifier::
00282 get_scope(CPPScope *current_scope, CPPScope *global_scope,
00283           CPPDeclaration::SubstDecl &subst,
00284           CPPPreprocessor *error_sink) const {
00285   assert(!_names.empty());
00286 
00287   CPPScope *scope = _native_scope;
00288   if (scope == (CPPScope *)NULL) {
00289     scope = current_scope;
00290   }
00291   int i = 0;
00292 
00293   if (_names[i].empty()) {
00294     // This identifier starts with a ::, thus it begins at the global
00295     // scope.
00296     scope = global_scope;
00297     i++;
00298   }
00299 
00300   while (i + 1 < (int)_names.size() && scope != NULL) {
00301     CPPScope *next_scope = scope->find_scope(_names[i].get_name(), subst,
00302                                              global_scope);
00303     if (next_scope == (CPPScope *)NULL) {
00304       if (error_sink != NULL) {
00305         error_sink->error("Symbol " + _names[i].get_name() +
00306                           " is not a known scope in " +
00307                           scope->get_fully_scoped_name());
00308       }
00309       return (CPPScope *)NULL;
00310     }
00311     if (_names[i].has_templ()) {
00312       next_scope = next_scope->instantiate(_names[i].get_templ(),
00313                                            current_scope, global_scope);
00314     }
00315     scope = next_scope;
00316     i++;
00317   }
00318 
00319   return scope;
00320 }
00321 
00322 ////////////////////////////////////////////////////////////////////
00323 //     Function: CPPIdentifier::find_type
00324 //       Access: Public
00325 //  Description: Looks up the identifier in the current and/or global
00326 //               scopes, and returns a CPPType pointer if it seems to
00327 //               refer to a type, or NULL if it does not.  If
00328 //               force_instantiate is true, the type will be
00329 //               instantiated as fully as possible right now, even if
00330 //               it means instantiating it into an identical template
00331 //               type.  Otherwise, the instantiation may be delayed
00332 //               for optimization reasons, and a CPPTBDType
00333 //               placeholder may be returned instead.
00334 ////////////////////////////////////////////////////////////////////
00335 CPPType *CPPIdentifier::
00336 find_type(CPPScope *current_scope, CPPScope *global_scope,
00337           bool force_instantiate,
00338           CPPPreprocessor *error_sink) const {
00339   CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
00340   if (scope == NULL) {
00341     return NULL;
00342   }
00343 
00344   CPPType *type = NULL;
00345   if (!_names.back().has_templ()) {
00346     type = scope->find_type(get_simple_name());
00347 
00348   } else {
00349     CPPDeclaration *decl = find_symbol(current_scope, global_scope, error_sink);
00350     type = decl->as_type();
00351     /*
00352     if (type != NULL) {
00353       if (!type->is_incomplete() || force_instantiate) {
00354         type = type->instantiate(_names.back().get_templ(),
00355                                  current_scope, global_scope,
00356                                  error_sink)->as_type();
00357 
00358         // If we ended up with another template, instantiate later.
00359         if (type->is_template() && !force_instantiate) {
00360           type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
00361         }
00362 
00363       } else {
00364         // Otherwise, we'll have to instantiate the type later.
00365         type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
00366       }
00367       //    type->_file.replace_nearer(_file);
00368     }
00369     */
00370   }
00371   return type;
00372 }
00373 
00374 ////////////////////////////////////////////////////////////////////
00375 //     Function: CPPIdentifier::find_type
00376 //       Access: Public
00377 //  Description: This flavor of find_type() will instantiate any scope
00378 //               names in the identifier.  It's useful for fully
00379 //               defining a type while instantiating a class.
00380 ////////////////////////////////////////////////////////////////////
00381 CPPType *CPPIdentifier::
00382 find_type(CPPScope *current_scope, CPPScope *global_scope,
00383           CPPDeclaration::SubstDecl &subst,
00384           CPPPreprocessor *error_sink) const {
00385   CPPScope *scope = get_scope(current_scope, global_scope, subst, error_sink);
00386   if (scope == NULL) {
00387     return NULL;
00388   }
00389   CPPType *type = scope->find_type(get_simple_name(), subst, global_scope);
00390   if (type != NULL && _names.back().has_templ()) {
00391     // This is a template type.
00392 
00393     if (is_fully_specified()) {
00394       // If our identifier fully specifies the instantiation, then
00395       // apply it.
00396       CPPDeclaration *decl =
00397         type->instantiate(_names.back().get_templ(),
00398                           current_scope, global_scope,
00399                           error_sink);
00400       assert(decl != NULL);
00401       CPPType *new_type = decl->as_type();
00402       assert(new_type != NULL);
00403       if (new_type == type) {
00404         type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
00405         //      type = new_type;
00406       } else {
00407         type = new_type;
00408       }
00409     } else {
00410       // Otherwise, we'll have to instantiate the type later.
00411       type = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
00412     }
00413     //    type->_file.replace_nearer(_file);
00414   }
00415   return type;
00416 }
00417 
00418 
00419 ////////////////////////////////////////////////////////////////////
00420 //     Function: CPPIdentifier::find_symbol
00421 //       Access: Public
00422 //  Description:
00423 ////////////////////////////////////////////////////////////////////
00424 CPPDeclaration *CPPIdentifier::
00425 find_symbol(CPPScope *current_scope, CPPScope *global_scope,
00426             CPPPreprocessor *error_sink) const {
00427   CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
00428   if (scope == NULL) {
00429     return NULL;
00430   }
00431   CPPDeclaration *sym;
00432   if (!_names.back().has_templ()) {
00433     sym = scope->find_symbol(get_simple_name());
00434 
00435   } else {
00436     sym = scope->find_template(get_simple_name());
00437     if (sym != NULL) {
00438       CPPType *type = sym->as_type();
00439       if (type != NULL && type->is_incomplete()) {
00440         // We can't instantiate an incomplete type.
00441         sym = CPPType::new_type(new CPPTBDType((CPPIdentifier *)this));
00442       } else {
00443         // Instantiate the symbol.
00444         sym = sym->instantiate(_names.back().get_templ(), current_scope,
00445                                global_scope, error_sink);
00446       }
00447     }
00448   }
00449 
00450   return sym;
00451 }
00452 
00453 ////////////////////////////////////////////////////////////////////
00454 //     Function: CPPIdentifier::find_template
00455 //       Access: Public
00456 //  Description:
00457 ////////////////////////////////////////////////////////////////////
00458 CPPDeclaration *CPPIdentifier::
00459 find_template(CPPScope *current_scope, CPPScope *global_scope,
00460               CPPPreprocessor *error_sink) const {
00461   CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
00462   if (scope == NULL) {
00463     return NULL;
00464   }
00465   return scope->find_template(get_simple_name());
00466 }
00467 
00468 ////////////////////////////////////////////////////////////////////
00469 //     Function: CPPIdentifier::find_scope
00470 //       Access: Public
00471 //  Description:
00472 ////////////////////////////////////////////////////////////////////
00473 CPPScope *CPPIdentifier::
00474 find_scope(CPPScope *current_scope, CPPScope *global_scope,
00475            CPPPreprocessor *error_sink) const {
00476   CPPScope *scope = get_scope(current_scope, global_scope, error_sink);
00477   if (scope == NULL) {
00478     return NULL;
00479   }
00480   return scope->find_scope(get_simple_name());
00481 }
00482 
00483 
00484 ////////////////////////////////////////////////////////////////////
00485 //     Function: CPPIdentifier::substitute_decl
00486 //       Access: Public
00487 //  Description:
00488 ////////////////////////////////////////////////////////////////////
00489 CPPIdentifier *CPPIdentifier::
00490 substitute_decl(CPPDeclaration::SubstDecl &subst,
00491                 CPPScope *current_scope, CPPScope *global_scope) {
00492   CPPIdentifier *rep = new CPPIdentifier(*this);
00493 
00494   bool anything_changed = false;
00495   for (int i = 0; i < (int)rep->_names.size(); i++) {
00496     if (_names[i].has_templ()) {
00497       rep->_names[i].set_templ
00498         (_names[i].get_templ()->substitute_decl(subst, current_scope, global_scope));
00499       if (rep->_names[i].get_templ() != _names[i].get_templ()) {
00500         anything_changed = true;
00501       }
00502     }
00503   }
00504 
00505   if (!anything_changed) {
00506     delete rep;
00507     rep = this;
00508   }
00509 
00510   return rep;
00511 }
00512 
00513 ////////////////////////////////////////////////////////////////////
00514 //     Function: CPPIdentifier::output
00515 //       Access: Public
00516 //  Description:
00517 ////////////////////////////////////////////////////////////////////
00518 void CPPIdentifier::
00519 output(ostream &out, CPPScope *scope) const {
00520   if (scope == NULL) {
00521     output_fully_scoped_name(out);
00522   } else {
00523     output_local_name(out, scope);
00524   }
00525 }
00526 
00527 
00528 ////////////////////////////////////////////////////////////////////
00529 //     Function: CPPIdentifier::output_local_name
00530 //       Access: Public
00531 //  Description:
00532 ////////////////////////////////////////////////////////////////////
00533 void CPPIdentifier::
00534 output_local_name(ostream &out, CPPScope *scope) const {
00535   assert(!_names.empty());
00536 
00537   if (scope == NULL || (_native_scope == NULL && _names.size() == 1)) {
00538     out << _names.back();
00539   } else if (_names.front().empty()) {
00540     output_fully_scoped_name(out);
00541   } else {
00542     // Determine the scope of everything up until but not including the
00543     // last name.
00544     CPPScope *my_scope = get_scope(scope, NULL);
00545 
00546     if (my_scope == NULL) {
00547       output_fully_scoped_name(out);
00548     } else {
00549       out << my_scope->get_local_name(scope) << "::" << _names.back();
00550     }
00551   }
00552 }
00553 
00554 ////////////////////////////////////////////////////////////////////
00555 //     Function: CPPIdentifier::output_fully_scoped_name
00556 //       Access: Public
00557 //  Description:
00558 ////////////////////////////////////////////////////////////////////
00559 void CPPIdentifier::
00560 output_fully_scoped_name(ostream &out) const {
00561   if (_native_scope != NULL) {
00562     _native_scope->output(out, (CPPScope *)NULL);
00563     out << "::";
00564   }
00565   Names::const_iterator ni = _names.begin();
00566   out << (*ni);
00567   ++ni;
00568   while (ni != _names.end()) {
00569     out << "::" << (*ni);
00570     ++ni;
00571   }
00572 }
00573 

Generated on Thu May 1 22:12:52 2003 for DTool by doxygen1.3