cppEnumType.cxx 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. // Filename: cppEnumType.cxx
  2. // Created by: drose (25Oct99)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "cppEnumType.h"
  15. #include "cppTypedefType.h"
  16. #include "cppExpression.h"
  17. #include "cppSimpleType.h"
  18. #include "cppConstType.h"
  19. #include "cppScope.h"
  20. #include "cppParser.h"
  21. #include "indent.h"
  22. ////////////////////////////////////////////////////////////////////
  23. // Function: CPPEnumType::Constructor
  24. // Access: Public
  25. // Description: Creates an untyped, unscoped enum.
  26. ////////////////////////////////////////////////////////////////////
  27. CPPEnumType::
  28. CPPEnumType(CPPIdentifier *ident, CPPScope *current_scope,
  29. const CPPFile &file) :
  30. CPPExtensionType(T_enum, ident, current_scope, file),
  31. _parent_scope(current_scope),
  32. _element_type(NULL),
  33. _last_value(NULL)
  34. {
  35. if (ident != NULL) {
  36. ident->_native_scope = current_scope;
  37. }
  38. }
  39. ////////////////////////////////////////////////////////////////////
  40. // Function: CPPEnumType::Constructor
  41. // Access: Public
  42. // Description: Creates a typed but unscoped enum.
  43. ////////////////////////////////////////////////////////////////////
  44. CPPEnumType::
  45. CPPEnumType(CPPIdentifier *ident, CPPType *element_type,
  46. CPPScope *current_scope, const CPPFile &file) :
  47. CPPExtensionType(T_enum, ident, current_scope, file),
  48. _parent_scope(current_scope),
  49. _element_type(element_type),
  50. _last_value(NULL)
  51. {
  52. if (ident != NULL) {
  53. ident->_native_scope = current_scope;
  54. }
  55. }
  56. ////////////////////////////////////////////////////////////////////
  57. // Function: CPPEnumType::add_element
  58. // Access: Public
  59. // Description:
  60. ////////////////////////////////////////////////////////////////////
  61. CPPInstance *CPPEnumType::
  62. add_element(const string &name, CPPExpression *value) {
  63. CPPIdentifier *ident = new CPPIdentifier(name);
  64. ident->_native_scope = _parent_scope;
  65. CPPInstance *inst;
  66. static CPPType *default_element_type = NULL;
  67. if (_element_type == NULL) {
  68. // This enum is untyped. Use a suitable default, ie. 'int'.
  69. if (default_element_type == NULL) {
  70. default_element_type =
  71. CPPType::new_type(new CPPConstType(new CPPSimpleType(CPPSimpleType::T_int, 0)));
  72. }
  73. inst = new CPPInstance(default_element_type, ident);
  74. } else {
  75. // This enum has an explicit type, so use that.
  76. inst = new CPPInstance(CPPType::new_type(new CPPConstType(_element_type)), ident);
  77. }
  78. _elements.push_back(inst);
  79. if (value == (CPPExpression *)NULL) {
  80. if (_last_value == (CPPExpression *)NULL) {
  81. // This is the first value, and should therefore be 0.
  82. static CPPExpression *const zero = new CPPExpression(0);
  83. value = zero;
  84. } else if (_last_value->_type == CPPExpression::T_integer) {
  85. value = new CPPExpression(_last_value->_u._integer + 1);
  86. } else {
  87. // We may not be able to determine the value just yet. No
  88. // problem; we'll just define it as another expression.
  89. static CPPExpression *const one = new CPPExpression(1);
  90. value = new CPPExpression('+', _last_value, one);
  91. }
  92. }
  93. inst->_initializer = value;
  94. _last_value = value;
  95. return inst;
  96. }
  97. ////////////////////////////////////////////////////////////////////
  98. // Function: CPPEnumType::is_incomplete
  99. // Access: Public, Virtual
  100. // Description: Returns true if the type has not yet been fully
  101. // specified, false if it has.
  102. ////////////////////////////////////////////////////////////////////
  103. bool CPPEnumType::
  104. is_incomplete() const {
  105. return false;
  106. }
  107. ////////////////////////////////////////////////////////////////////
  108. // Function: CPPEnumType::is_fully_specified
  109. // Access: Public, Virtual
  110. // Description: Returns true if this declaration is an actual,
  111. // factual declaration, or false if some part of the
  112. // declaration depends on a template parameter which has
  113. // not yet been instantiated.
  114. ////////////////////////////////////////////////////////////////////
  115. bool CPPEnumType::
  116. is_fully_specified() const {
  117. if (!CPPDeclaration::is_fully_specified()) {
  118. return false;
  119. }
  120. if (_ident != NULL && !_ident->is_fully_specified()) {
  121. return false;
  122. }
  123. if (_element_type != NULL && !_element_type->is_fully_specified()) {
  124. return false;
  125. }
  126. Elements::const_iterator ei;
  127. for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
  128. if (!(*ei)->is_fully_specified()) {
  129. return false;
  130. }
  131. }
  132. return true;
  133. }
  134. ////////////////////////////////////////////////////////////////////
  135. // Function: CPPEnumType::substitute_decl
  136. // Access: Public, Virtual
  137. // Description:
  138. ////////////////////////////////////////////////////////////////////
  139. CPPDeclaration *CPPEnumType::
  140. substitute_decl(CPPDeclaration::SubstDecl &subst,
  141. CPPScope *current_scope, CPPScope *global_scope) {
  142. SubstDecl::const_iterator si = subst.find(this);
  143. if (si != subst.end()) {
  144. return (*si).second;
  145. }
  146. CPPEnumType *rep = new CPPEnumType(*this);
  147. if (_ident != NULL) {
  148. rep->_ident =
  149. _ident->substitute_decl(subst, current_scope, global_scope);
  150. }
  151. if (_element_type != NULL) {
  152. rep->_element_type =
  153. _element_type->substitute_decl(subst, current_scope, global_scope)
  154. ->as_type();
  155. }
  156. bool any_changed = false;
  157. for (int i = 0; i < _elements.size(); ++i) {
  158. CPPInstance *elem_rep =
  159. _elements[i]->substitute_decl(subst, current_scope, global_scope)
  160. ->as_instance();
  161. if (elem_rep != _elements[i]) {
  162. rep->_elements[i] = elem_rep;
  163. any_changed = true;
  164. }
  165. }
  166. if (rep->_ident == _ident &&
  167. rep->_element_type == _element_type &&
  168. !any_changed) {
  169. delete rep;
  170. rep = this;
  171. }
  172. rep = CPPType::new_type(rep)->as_enum_type();
  173. subst.insert(SubstDecl::value_type(this, rep));
  174. return rep;
  175. }
  176. ////////////////////////////////////////////////////////////////////
  177. // Function: CPPEnumType::output
  178. // Access: Public, Virtual
  179. // Description:
  180. ////////////////////////////////////////////////////////////////////
  181. void CPPEnumType::
  182. output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
  183. if (!complete && _ident != NULL) {
  184. // If we have a name, use it.
  185. if (cppparser_output_class_keyword) {
  186. out << _type << " ";
  187. }
  188. out << _ident->get_local_name(scope);
  189. } else {
  190. out << _type;
  191. if (_ident != NULL) {
  192. out << " " << _ident->get_local_name(scope);
  193. }
  194. if (_element_type != NULL) {
  195. out << " : " << _element_type->get_local_name(scope);
  196. }
  197. out << " {\n";
  198. Elements::const_iterator ei;
  199. for (ei = _elements.begin(); ei != _elements.end(); ++ei) {
  200. indent(out, indent_level + 2) << (*ei)->get_local_name();
  201. if ((*ei)->_initializer != NULL) {
  202. out << " = " << *(*ei)->_initializer;
  203. }
  204. out << ",\n";
  205. }
  206. indent(out, indent_level) << "}";
  207. }
  208. }
  209. ////////////////////////////////////////////////////////////////////
  210. // Function: CPPEnumType::get_subtype
  211. // Access: Public, Virtual
  212. // Description:
  213. ////////////////////////////////////////////////////////////////////
  214. CPPDeclaration::SubType CPPEnumType::
  215. get_subtype() const {
  216. return ST_enum;
  217. }
  218. ////////////////////////////////////////////////////////////////////
  219. // Function: CPPEnumType::as_enum_type
  220. // Access: Public, Virtual
  221. // Description:
  222. ////////////////////////////////////////////////////////////////////
  223. CPPEnumType *CPPEnumType::
  224. as_enum_type() {
  225. return this;
  226. }