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

dtool/src/cppparser/cppInstance.cxx

Go to the documentation of this file.
00001 // Filename: cppInstance.cxx
00002 // Created by:  drose (19Oct99)
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 "cppInstance.h"
00021 #include "cppInstanceIdentifier.h"
00022 #include "cppIdentifier.h"
00023 #include "cppTemplateScope.h"
00024 #include "cppFunctionType.h"
00025 #include "cppSimpleType.h"
00026 #include "cppExpression.h"
00027 #include "cppPreprocessor.h"
00028 #include "indent.h"
00029 
00030 #include "cppReferenceType.h"
00031 #include "cppConstType.h"
00032 
00033 #include <algorithm>
00034 
00035 ////////////////////////////////////////////////////////////////////
00036 //     Function: CPPInstance::Constructor
00037 //       Access: Public
00038 //  Description:
00039 ////////////////////////////////////////////////////////////////////
00040 CPPInstance::
00041 CPPInstance(CPPType *type, const string &name, int storage_class) :
00042   CPPDeclaration(CPPFile()),
00043   _type(type),
00044   _ident(new CPPIdentifier(name)),
00045   _storage_class(storage_class)
00046 {
00047   _initializer = NULL;
00048 }
00049 
00050 ////////////////////////////////////////////////////////////////////
00051 //     Function: CPPInstance::Constructor
00052 //       Access: Public
00053 //  Description:
00054 ////////////////////////////////////////////////////////////////////
00055 CPPInstance::
00056 CPPInstance(CPPType *type, CPPIdentifier *ident, int storage_class) :
00057   CPPDeclaration(CPPFile()),
00058   _type(type),
00059   _ident(ident),
00060   _storage_class(storage_class)
00061 {
00062   _initializer = NULL;
00063 }
00064 
00065 ////////////////////////////////////////////////////////////////////
00066 //     Function: CPPInstance::Constructor
00067 //       Access: Public
00068 //  Description: Constructs a new CPPInstance object that defines a
00069 //               variable of the indicated type according to the type
00070 //               and the InstanceIdentifier.  The InstanceIdentifier
00071 //               pointer is deallocated.
00072 ////////////////////////////////////////////////////////////////////
00073 CPPInstance::
00074 CPPInstance(CPPType *type, CPPInstanceIdentifier *ii, int storage_class,
00075             const CPPFile &file) :
00076   CPPDeclaration(file)
00077 {
00078   _type = ii->unroll_type(type);
00079   _ident = ii->_ident;
00080   ii->_ident = NULL;
00081   _storage_class = storage_class;
00082   delete ii;
00083   _initializer = NULL;
00084 }
00085 
00086 ////////////////////////////////////////////////////////////////////
00087 //     Function: CPPInstance::Copy Constructor
00088 //       Access: Public
00089 //  Description:
00090 ////////////////////////////////////////////////////////////////////
00091 CPPInstance::
00092 CPPInstance(const CPPInstance &copy) :
00093   CPPDeclaration(copy),
00094   _type(copy._type),
00095   _ident(copy._ident),
00096   _initializer(copy._initializer),
00097   _storage_class(copy._storage_class)
00098 {
00099   assert(_type != NULL);
00100 }
00101 
00102 ////////////////////////////////////////////////////////////////////
00103 //     Function: CPPInstance::Destructor
00104 //       Access: Public
00105 //  Description:
00106 ////////////////////////////////////////////////////////////////////
00107 CPPInstance::
00108 ~CPPInstance() {
00109   // Can't delete the identifier.  Don't try.
00110 }
00111 
00112 
00113 ////////////////////////////////////////////////////////////////////
00114 //     Function: CPPInstance::make_typecast_function
00115 //       Access: Public, Static
00116 //  Description: Constructs and returns a new CPPInstance object that
00117 //               corresponds to a function prototype declaration for a
00118 //               typecast method, whose return type is implicit in the
00119 //               identifier type.
00120 ////////////////////////////////////////////////////////////////////
00121 CPPInstance *CPPInstance::
00122 make_typecast_function(CPPInstance *inst, CPPIdentifier *ident,
00123                        CPPParameterList *parameters, int function_flags) {
00124   CPPType *type = CPPType::new_type(inst->_type);
00125   delete inst;
00126 
00127   function_flags |= (int)CPPFunctionType::F_operator_typecast;
00128 
00129   CPPType *ft =
00130     CPPType::new_type(new CPPFunctionType(type, parameters, function_flags));
00131 
00132   return new CPPInstance(ft, ident);
00133 }
00134 
00135 ////////////////////////////////////////////////////////////////////
00136 //     Function: CPPInstance::Equivalence Operator
00137 //       Access: Public
00138 //  Description:
00139 ////////////////////////////////////////////////////////////////////
00140 bool CPPInstance::
00141 operator == (const CPPInstance &other) const {
00142   if (_type != other._type) {
00143     return false;
00144   }
00145   if (_storage_class != other._storage_class) {
00146     return false;
00147   }
00148 
00149   // We *do* care about the identifier.  We need to differentiate
00150   // types of function variables, among possibly other things, based
00151   // on the identifier.
00152   if ((_ident == NULL && other._ident != NULL) ||
00153       (_ident != NULL && other._ident == NULL) ||
00154       (_ident != NULL && other._ident != NULL && *_ident != *other._ident))
00155   {
00156     return false;
00157   }
00158 
00159   // We similarly care about the initializer.
00160   if ((_initializer == NULL && other._initializer != NULL) ||
00161       (_initializer != NULL && other._initializer == NULL) ||
00162       (_initializer != NULL && other._initializer != NULL &&
00163        *_initializer != *other._initializer))
00164   {
00165     return false;
00166   }
00167 
00168   return true;
00169 }
00170 
00171 ////////////////////////////////////////////////////////////////////
00172 //     Function: CPPInstance::Nonequivalence Operator
00173 //       Access: Public
00174 //  Description:
00175 ////////////////////////////////////////////////////////////////////
00176 bool CPPInstance::
00177 operator != (const CPPInstance &other) const {
00178   return !operator == (other);
00179 }
00180 
00181 ////////////////////////////////////////////////////////////////////
00182 //     Function: CPPInstance::Ordering Operator
00183 //       Access: Public
00184 //  Description:
00185 ////////////////////////////////////////////////////////////////////
00186 bool CPPInstance::
00187 operator < (const CPPInstance &other) const {
00188   if (_type != other._type) {
00189     return _type < other._type;
00190   }
00191   if (_storage_class != other._storage_class) {
00192     return _storage_class < other._storage_class;
00193   }
00194 
00195   // We *do* care about the identifier.  We need to differentiate
00196   // types of function variables, among possibly other things, based
00197   // on the identifier.
00198   if ((_ident == NULL && other._ident != NULL) ||
00199       (_ident != NULL && other._ident == NULL) ||
00200       (_ident != NULL && other._ident != NULL && *_ident != *other._ident))
00201   {
00202     if (_ident == NULL || other._ident == NULL) {
00203       return _ident < other._ident;
00204     }
00205     return *_ident < *other._ident;
00206   }
00207 
00208   // We similarly care about the initializer.
00209   if ((_initializer == NULL && other._initializer != NULL) ||
00210       (_initializer != NULL && other._initializer == NULL) ||
00211       (_initializer != NULL && other._initializer != NULL &&
00212        *_initializer != *other._initializer))
00213   {
00214     if (_initializer == NULL || other._initializer == NULL) {
00215       return _initializer < other._initializer;
00216     }
00217     return *_initializer < *other._initializer;
00218   }
00219 
00220   return false;
00221 }
00222 
00223 ////////////////////////////////////////////////////////////////////
00224 //     Function: CPPInstance::set_initializer
00225 //       Access: Public
00226 //  Description: Sets the value of the expression that is used to
00227 //               initialize the variable, or the default value for a
00228 //               parameter.  If a non-null expression is set on a
00229 //               function declaration, it implies that the function is
00230 //               pure virtual.
00231 ////////////////////////////////////////////////////////////////////
00232 void CPPInstance::
00233 set_initializer(CPPExpression *initializer) {
00234   if (_type->as_function_type() != (CPPFunctionType *)NULL) {
00235     // This is a function declaration.
00236     if (initializer == (CPPExpression *)NULL) {
00237       _storage_class &= ~SC_pure_virtual;
00238     } else {
00239       _storage_class |= SC_pure_virtual;
00240     }
00241     _initializer = (CPPExpression *)NULL;
00242   } else {
00243     _initializer = initializer;
00244   }
00245 }
00246 
00247 ////////////////////////////////////////////////////////////////////
00248 //     Function: CPPInstance::is_scoped
00249 //       Access: Public
00250 //  Description:
00251 ////////////////////////////////////////////////////////////////////
00252 bool CPPInstance::
00253 is_scoped() const {
00254   if (_ident == NULL) {
00255     return false;
00256   } else {
00257     return _ident->is_scoped();
00258   }
00259 }
00260 
00261 ////////////////////////////////////////////////////////////////////
00262 //     Function: CPPInstance::get_scope
00263 //       Access: Public
00264 //  Description:
00265 ////////////////////////////////////////////////////////////////////
00266 CPPScope *CPPInstance::
00267 get_scope(CPPScope *current_scope, CPPScope *global_scope,
00268           CPPPreprocessor *error_sink) const {
00269   if (_ident == NULL) {
00270     return current_scope;
00271   } else {
00272     return _ident->get_scope(current_scope, global_scope, error_sink);
00273   }
00274 }
00275 
00276 ////////////////////////////////////////////////////////////////////
00277 //     Function: CPPInstance::get_simple_name
00278 //       Access: Public
00279 //  Description:
00280 ////////////////////////////////////////////////////////////////////
00281 string CPPInstance::
00282 get_simple_name() const {
00283   if (_ident == NULL) {
00284     return "";
00285   } else {
00286     return _ident->get_simple_name();
00287   }
00288 }
00289 
00290 ////////////////////////////////////////////////////////////////////
00291 //     Function: CPPInstance::get_local_name
00292 //       Access: Public
00293 //  Description:
00294 ////////////////////////////////////////////////////////////////////
00295 string CPPInstance::
00296 get_local_name(CPPScope *scope) const {
00297   if (_ident == NULL) {
00298     return "";
00299   } else {
00300     return _ident->get_local_name(scope);
00301   }
00302 }
00303 
00304 ////////////////////////////////////////////////////////////////////
00305 //     Function: CPPInstance::get_fully_scoped_name
00306 //       Access: Public
00307 //  Description:
00308 ////////////////////////////////////////////////////////////////////
00309 string CPPInstance::
00310 get_fully_scoped_name() const {
00311   if (_ident == NULL) {
00312     return "";
00313   } else {
00314     return _ident->get_fully_scoped_name();
00315   }
00316 }
00317 
00318 ////////////////////////////////////////////////////////////////////
00319 //     Function: CPPInstance::check_for_constructor
00320 //       Access: Public
00321 //  Description: If this is a function type instance, checks whether
00322 //               the function name matches the class name (or ~name),
00323 //               and if so, flags it as a constructor (or destructor).
00324 ////////////////////////////////////////////////////////////////////
00325 void CPPInstance::
00326 check_for_constructor(CPPScope *current_scope, CPPScope *global_scope) {
00327   CPPScope *scope = get_scope(current_scope, global_scope);
00328   if (scope == NULL) {
00329     scope = current_scope;
00330   }
00331 
00332   CPPFunctionType *func = _type->as_function_type();
00333   if (func != NULL) {
00334     string method_name = get_local_name(scope);
00335     string class_name = scope->get_local_name();
00336 
00337     if (!method_name.empty() && !class_name.empty()) {
00338       if (method_name == class_name) {
00339         CPPType *void_type = CPPType::new_type
00340           (new CPPSimpleType(CPPSimpleType::T_void));
00341 
00342         _type = CPPType::new_type
00343           (new CPPFunctionType(void_type, func->_parameters,
00344                                func->_flags | CPPFunctionType::F_constructor));
00345 
00346       } else if (method_name == "~" + class_name) {
00347         CPPType *void_type = CPPType::new_type
00348           (new CPPSimpleType(CPPSimpleType::T_void));
00349 
00350         _type = CPPType::new_type
00351           (new CPPFunctionType(void_type, func->_parameters,
00352                                func->_flags | CPPFunctionType::F_destructor));
00353       }
00354     }
00355   }
00356 }
00357 
00358 ////////////////////////////////////////////////////////////////////
00359 //     Function: CPPInstance::instantiate
00360 //       Access: Public
00361 //  Description:
00362 ////////////////////////////////////////////////////////////////////
00363 CPPDeclaration *CPPInstance::
00364 instantiate(const CPPTemplateParameterList *actual_params,
00365             CPPScope *current_scope, CPPScope *global_scope,
00366             CPPPreprocessor *error_sink) const {
00367   if (!is_template()) {
00368     if (error_sink != NULL) {
00369       error_sink->warning("Ignoring template parameters for instance " +
00370                           _ident->get_local_name());
00371     }
00372     return (CPPInstance *)this;
00373   }
00374 
00375   Instantiations::const_iterator ii;
00376   ii = _instantiations.find(actual_params);
00377   if (ii != _instantiations.end()) {
00378     // We've already instantiated this instance with these parameters.
00379     // Return that.
00380     return (*ii).second;
00381   }
00382 
00383 
00384   CPPTemplateScope *tscope = get_template_scope();
00385 
00386   CPPDeclaration::SubstDecl subst;
00387   actual_params->build_subst_decl(tscope->_parameters, subst,
00388                                   current_scope, global_scope);
00389 
00390   CPPInstance *inst =
00391     ((CPPInstance *)this)->substitute_decl(subst, current_scope, global_scope)
00392     ->as_instance();
00393   if (inst == this) {
00394     // Hmm, nothing to substitute.  Make a new instance anyway, so we
00395     // can change the name.
00396     inst = new CPPInstance(*this);
00397   }
00398   assert(inst != NULL);
00399   inst->_ident = inst->_ident->substitute_decl(subst, current_scope, global_scope);
00400   if (inst->_ident == _ident) {
00401     inst->_ident = new CPPIdentifier(*inst->_ident);
00402   }
00403   inst->_ident->_names.back().set_templ
00404     (new CPPTemplateParameterList(*actual_params));
00405 
00406   inst->_template_scope = NULL;
00407 
00408   ((CPPInstance *)this)->_instantiations.insert(Instantiations::value_type(actual_params, inst));
00409   return inst;
00410 }
00411 
00412 ////////////////////////////////////////////////////////////////////
00413 //     Function: CPPInstance::is_fully_specified
00414 //       Access: Public, Virtual
00415 //  Description: Returns true if this declaration is an actual,
00416 //               factual declaration, or false if some part of the
00417 //               declaration depends on a template parameter which has
00418 //               not yet been instantiated.
00419 ////////////////////////////////////////////////////////////////////
00420 bool CPPInstance::
00421 is_fully_specified() const {
00422   if (_ident != NULL && !_ident->is_fully_specified()) {
00423     return false;
00424   }
00425   if (_initializer != NULL && !_initializer->is_fully_specified()) {
00426     return false;
00427   }
00428   return CPPDeclaration::is_fully_specified() &&
00429     _type->is_fully_specified();
00430 }
00431 
00432 ////////////////////////////////////////////////////////////////////
00433 //     Function: CPPInstance::substitute_decl
00434 //       Access: Public, Virtual
00435 //  Description:
00436 ////////////////////////////////////////////////////////////////////
00437 CPPDeclaration *CPPInstance::
00438 substitute_decl(CPPDeclaration::SubstDecl &subst,
00439                 CPPScope *current_scope, CPPScope *global_scope) {
00440   CPPDeclaration *top =
00441     CPPDeclaration::substitute_decl(subst, current_scope, global_scope);
00442   if (top != this) {
00443     return top;
00444   }
00445 
00446   CPPInstance *rep = new CPPInstance(*this);
00447   CPPDeclaration *new_type =
00448     _type->substitute_decl(subst, current_scope, global_scope);
00449   rep->_type = new_type->as_type();
00450 
00451   if (rep->_type == NULL) {
00452     cerr << "Type " << *_type << " became " << *new_type << " which isn't a type\n";
00453     rep->_type = _type;
00454   }
00455 
00456   if (_initializer != NULL) {
00457     rep->_initializer =
00458       _initializer->substitute_decl(subst, current_scope, global_scope)
00459       ->as_expression();
00460   }
00461 
00462   if (rep->_type == _type &&
00463       rep->_initializer == _initializer) {
00464     delete rep;
00465     rep = this;
00466   }
00467 
00468   subst.insert(SubstDecl::value_type(this, rep));
00469   return rep;
00470 }
00471 
00472 ////////////////////////////////////////////////////////////////////
00473 //     Function: CPPInstance::output
00474 //       Access: Public, Virtual
00475 //  Description:
00476 ////////////////////////////////////////////////////////////////////
00477 void CPPInstance::
00478 output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
00479   output(out, indent_level, scope, complete, -1);
00480 }
00481 
00482 ////////////////////////////////////////////////////////////////////
00483 //     Function: CPPInstance::output
00484 //       Access: Public
00485 //  Description: The extra parameter comes into play only when we
00486 //               happen to be outputting a function prototype.  See
00487 //               CPPFunctionType::output().
00488 ////////////////////////////////////////////////////////////////////
00489 void CPPInstance::
00490 output(ostream &out, int indent_level, CPPScope *scope, bool complete,
00491        int num_default_parameters) const {
00492   if (is_template()) {
00493     get_template_scope()->_parameters.write_formal(out, scope);
00494     indent(out, indent_level);
00495   }
00496   if (_storage_class & SC_static) {
00497     out << "static ";
00498   }
00499   if (_storage_class & SC_extern) {
00500     out << "extern ";
00501   }
00502   if (_storage_class & SC_c_binding) {
00503     out << "\"C\" ";
00504   }
00505   if (_storage_class & SC_virtual) {
00506     out << "virtual ";
00507   }
00508   if (_storage_class & SC_inline) {
00509     out << "inline ";
00510   }
00511   if (_storage_class & SC_explicit) {
00512     out << "explicit ";
00513   }
00514   if (_storage_class & SC_register) {
00515     out << "register ";
00516   }
00517   if (_storage_class & SC_volatile) {
00518     out << "volatile ";
00519   }
00520   if (_storage_class & SC_mutable) {
00521     out << "mutable ";
00522   }
00523 
00524   string name;
00525   if (_ident != NULL) {
00526     name = _ident->get_local_name(scope);
00527   }
00528   assert(_type != NULL);
00529 
00530   if (_type->as_function_type()) {
00531     _type->as_function_type()->
00532       output_instance(out, indent_level, scope, complete, "", name,
00533                       num_default_parameters);
00534   } else {
00535     _type->output_instance(out, indent_level, scope, complete, "", name);
00536   }
00537 
00538   if (_storage_class & SC_pure_virtual) {
00539     out << " = 0";
00540   }
00541   if (_initializer != NULL) {
00542     out << " = (" << *_initializer << ")";
00543   }
00544 }
00545 
00546 
00547 ////////////////////////////////////////////////////////////////////
00548 //     Function: CPPInstance::get_subtype
00549 //       Access: Public, Virtual
00550 //  Description:
00551 ////////////////////////////////////////////////////////////////////
00552 CPPDeclaration::SubType CPPInstance::
00553 get_subtype() const {
00554   return ST_instance;
00555 }
00556 
00557 ////////////////////////////////////////////////////////////////////
00558 //     Function: CPPInstance::as_instance
00559 //       Access: Public, Virtual
00560 //  Description:
00561 ////////////////////////////////////////////////////////////////////
00562 CPPInstance *CPPInstance::
00563 as_instance() {
00564   return this;
00565 }

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