// Filename: cppTemplateParameterList.cxx // Created by: drose (28Oct99) // //////////////////////////////////////////////////////////////////// // // PANDA 3D SOFTWARE // Copyright (c) Carnegie Mellon University. All rights reserved. // // All use of this software is subject to the terms of the revised BSD // license. You should have received a copy of this license along // with this source code in a file named "LICENSE." // //////////////////////////////////////////////////////////////////// #include "cppTemplateParameterList.h" #include "cppClassTemplateParameter.h" #include "cppInstance.h" #include "cppExpression.h" //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// CPPTemplateParameterList:: CPPTemplateParameterList() { } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::Constructor // Access: Public // Description: //////////////////////////////////////////////////////////////////// string CPPTemplateParameterList:: get_string() const { ostringstream strname; strname << "< " << *this << " >"; return strname.str(); } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::build_subst_decl // Access: Public // Description: Matches up the actual parameters one-to-one with the // formal parameters they are replacing, so the template // may be instantiated by swapping out each occurrence // of a template standin type with its appropriate // replacement. //////////////////////////////////////////////////////////////////// void CPPTemplateParameterList:: build_subst_decl(const CPPTemplateParameterList &formal_params, CPPDeclaration::SubstDecl &subst, CPPScope *current_scope, CPPScope *global_scope) const { Parameters::const_iterator pfi, pai; for (pfi = formal_params._parameters.begin(), pai = _parameters.begin(); pfi != formal_params._parameters.end() && pai != _parameters.end(); ++pfi, ++pai) { CPPDeclaration *formal = *pfi; CPPDeclaration *actual = *pai; if (actual->as_type()) { actual = actual->as_type()->resolve_type(current_scope, global_scope); } if (!(formal == actual)) { subst.insert(CPPDeclaration::SubstDecl::value_type(formal, actual)); } } // Fill in the default template parameters. while (pfi != formal_params._parameters.end()) { CPPDeclaration *decl = (*pfi); if (decl->as_instance()) { // A value template parameter. Its default is an expression. CPPInstance *inst = decl->as_instance(); if (inst->_initializer != NULL) { CPPDeclaration *decl = inst->_initializer->substitute_decl(subst, current_scope, global_scope); if (!(*decl == *inst)) { subst.insert(CPPDeclaration::SubstDecl::value_type (inst, decl)); } } } else if (decl->as_class_template_parameter()) { // A class template parameter. CPPClassTemplateParameter *cparam = decl->as_class_template_parameter(); if (cparam->_default_type != NULL) { CPPDeclaration *decl = cparam->_default_type->substitute_decl(subst, current_scope, global_scope); if (!(*cparam == *decl)) { subst.insert(CPPDeclaration::SubstDecl::value_type (cparam, decl)); } } } ++pfi; } } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::is_fully_specified // Access: Public // Description: This function returns true if all the parameters in // the list are real expressions or classes, and not // types yet to-be-determined or template parameter // types. That is, this returns true for a normal // template instantiation, and false for a template // instantiation based on template parameters that have // not yet been specified. //////////////////////////////////////////////////////////////////// bool CPPTemplateParameterList:: is_fully_specified() const { for (int i = 0; i < (int)_parameters.size(); ++i) { if (!_parameters[i]->is_fully_specified()) { return false; } } return true; } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::is_tbd // Access: Public // Description: Returns true if any type within the parameter list is // a CPPTBDType and thus isn't fully determined right // now. //////////////////////////////////////////////////////////////////// bool CPPTemplateParameterList:: is_tbd() const { for (int i = 0; i < (int)_parameters.size(); ++i) { CPPType *type = _parameters[i]->as_type(); if (type != (CPPType *)NULL && (type->is_tbd() || type->as_class_template_parameter() != NULL)) { return true; } CPPExpression *expr = _parameters[i]->as_expression(); if (expr != NULL && expr->is_tbd()) { return true; } } return false; } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::Equivalence Operator // Access: Public // Description: //////////////////////////////////////////////////////////////////// bool CPPTemplateParameterList:: operator == (const CPPTemplateParameterList &other) const { if (_parameters.size() != other._parameters.size()) { return false; } for (int i = 0; i < (int)_parameters.size(); ++i) { if (*_parameters[i] != *other._parameters[i]) { return false; } } return true; } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::Nonequivalence Operator // Access: Public // Description: //////////////////////////////////////////////////////////////////// bool CPPTemplateParameterList:: operator != (const CPPTemplateParameterList &other) const { return !(*this == other); } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::Ordering Operator // Access: Public // Description: //////////////////////////////////////////////////////////////////// bool CPPTemplateParameterList:: operator < (const CPPTemplateParameterList &other) const { if (_parameters.size() != other._parameters.size()) { return _parameters.size() < other._parameters.size(); } for (int i = 0; i < (int)_parameters.size(); ++i) { if (*_parameters[i] != *other._parameters[i]) { return *_parameters[i] < *other._parameters[i]; } } return false; } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::substitute_decl // Access: Public // Description: //////////////////////////////////////////////////////////////////// CPPTemplateParameterList *CPPTemplateParameterList:: substitute_decl(CPPDeclaration::SubstDecl &subst, CPPScope *current_scope, CPPScope *global_scope) { CPPTemplateParameterList *rep = new CPPTemplateParameterList(*this); bool anything_changed = false; for (int i = 0; i < (int)rep->_parameters.size(); ++i) { rep->_parameters[i] = _parameters[i]->substitute_decl(subst, current_scope, global_scope); if (rep->_parameters[i] != _parameters[i]) { anything_changed = true; } } if (!anything_changed) { delete rep; rep = this; } return rep; } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::output // Access: Public // Description: //////////////////////////////////////////////////////////////////// void CPPTemplateParameterList:: output(ostream &out, CPPScope *scope) const { if (!_parameters.empty()) { Parameters::const_iterator pi = _parameters.begin(); (*pi)->output(out, 0, scope, false); ++pi; while (pi != _parameters.end()) { out << ", "; (*pi)->output(out, 0, scope, false); ++pi; } } } //////////////////////////////////////////////////////////////////// // Function: CPPTemplateParameterList::write_formal // Access: Public // Description: Writes the list as a set of formal parameters for a // template scope. Includes the keyword "template" and // the angle brackets, as well as the trailing newline. //////////////////////////////////////////////////////////////////// void CPPTemplateParameterList:: write_formal(ostream &out, CPPScope *scope) const { out << "template<"; if (!_parameters.empty()) { Parameters::const_iterator pi = _parameters.begin(); (*pi)->output(out, 0, scope, true); ++pi; while (pi != _parameters.end()) { out << ", "; (*pi)->output(out, 0, scope, true); ++pi; } } out << ">\n"; }