PageRenderTime 1513ms CodeModel.GetById 165ms RepoModel.GetById 36ms app.codeStats 0ms

/src/lib/List.h

http://phc.googlecode.com/
C Header | 257 lines | 187 code | 40 blank | 30 comment | 8 complexity | abb37ed7b81b6735ad8f9f6325d6ec8b MD5 | raw file
Possible License(s): GPL-2.0, 0BSD, BSD-3-Clause, Unlicense, MPL-2.0-no-copyleft-exception, LGPL-2.1
  1. /*
  2. * phc -- the open source PHP compiler
  3. * See doc/license/README.license for licensing information
  4. *
  5. * Wrap the STL list
  6. */
  7. #ifndef PHC_LIST_H
  8. #define PHC_LIST_H
  9. #include <list>
  10. #include "lib/Object.h"
  11. #include "process_ir/Foreach.h"
  12. #include <boost/type_traits/is_pointer.hpp>
  13. #include <boost/type_traits/is_scalar.hpp>
  14. // XXX HACK
  15. /*
  16. * The implementation of List requires a clone() method, because it was
  17. * originally designed for the maketea derived clone() methods. But we want to
  18. * use List instead of std::list to make sure garbage collection is used
  19. * everywhere. This "hack" allows us to call Object::clone(), and fail if
  20. * clone() is called for classes that don't support it (all other classes).
  21. */
  22. namespace IR { class Node; class FOREIGN; class PHP_script; }
  23. #define MAKETEA_USER_DEFINED(TYPE) SET_CLONABLE(TYPE) SET_COMPARABLE(TYPE)
  24. MAKETEA_USER_DEFINED(IR::Node)
  25. MAKETEA_USER_DEFINED(IR::FOREIGN)
  26. MAKETEA_USER_DEFINED(IR::PHP_script)
  27. #include "AST_user_defined.h"
  28. #include "HIR_user_defined.h"
  29. #include "MIR_user_defined.h"
  30. #undef MAKETEA_USER_DEFINED
  31. /*
  32. * For all classes on which SET_CLONABLE is set, supports_cloning<T>::value is
  33. * true, making the template call obj->clone(). All other classes will default
  34. * to false, calling assert (0) instead. Using this approach means that other
  35. * classes do not have to have a clone() method - all other approaches I tried
  36. * led to compile-time failure, or didnt do the right thing.
  37. */
  38. template<bool b>
  39. struct clone_algorithm_selector
  40. {
  41. template<typename T>
  42. static T clone (T object)
  43. {
  44. return object;
  45. }
  46. };
  47. // Call to clone for classes that support it.
  48. template<>
  49. struct clone_algorithm_selector<true>
  50. {
  51. template<typename T>
  52. static T clone (T object)
  53. {
  54. if (object == NULL)
  55. return NULL;
  56. return object->clone ();
  57. }
  58. };
  59. template<typename T>
  60. T phc_clone (T object)
  61. {
  62. return clone_algorithm_selector<supports_cloning<T>::value>::clone(object);
  63. }
  64. template<bool supports_equality, bool is_scalar, bool is_pointer>
  65. struct equals_algorithm_selector
  66. {
  67. template<typename T>
  68. static bool equals (T object1, T object2)
  69. {
  70. // This probably doesn't do what you want in this case.
  71. abort();
  72. }
  73. };
  74. // Non-pointers which have operator== should work too (like strings and
  75. // primitives).
  76. template<>
  77. struct equals_algorithm_selector<false, true, false>
  78. {
  79. template<typename T>
  80. static bool equals (T object1, T object2)
  81. {
  82. return object1 == object2;
  83. }
  84. };
  85. // Call to equals for classes that support it.
  86. template<>
  87. struct equals_algorithm_selector<true, true, true>
  88. {
  89. template<typename T>
  90. static bool equals (T object1, T object2)
  91. {
  92. return object1->equals (object2);
  93. }
  94. };
  95. template<>
  96. struct equals_algorithm_selector<true, false, false>
  97. {
  98. template<typename T>
  99. static bool equals (T object1, T object2)
  100. {
  101. return object1.equals (&object2);
  102. }
  103. };
  104. template<typename T>
  105. bool phc_equals (T object1, T object2)
  106. {
  107. return equals_algorithm_selector<supports_equality<T>::value, boost::is_scalar<T>::value, boost::is_pointer<T>::value>::equals(object1, object2);
  108. }
  109. template<typename _Tp, typename _Alloc = phc_allocator<_Tp> >
  110. class List : public std::list<_Tp, _Alloc>, virtual public Object
  111. {
  112. public:
  113. using std::list<_Tp, _Alloc>::push_back;
  114. public:
  115. List() : std::list<_Tp, _Alloc>() {}
  116. virtual ~List() {}
  117. // Create a list with one, two or three elements
  118. public:
  119. List(_Tp elem1) : std::list<_Tp, _Alloc>()
  120. {
  121. push_back(elem1);
  122. }
  123. List(_Tp elem1, _Tp elem2) : std::list<_Tp, _Alloc>()
  124. {
  125. push_back(elem1);
  126. push_back(elem2);
  127. }
  128. List(_Tp elem1, _Tp elem2, _Tp elem3) : std::list<_Tp, _Alloc>()
  129. {
  130. push_back(elem1);
  131. push_back(elem2);
  132. push_back(elem3);
  133. }
  134. // We're probably pushing it at 4...
  135. List(_Tp elem1, _Tp elem2, _Tp elem3, _Tp elem4) : std::list<_Tp, _Alloc>()
  136. {
  137. push_back(elem1);
  138. push_back(elem2);
  139. push_back(elem3);
  140. push_back(elem4);
  141. }
  142. public:
  143. using std::list<_Tp, _Alloc>::begin;
  144. using std::list<_Tp, _Alloc>::end;
  145. void push_back_all (List* other)
  146. {
  147. insert(end(), other->begin(), other->end());
  148. }
  149. void push_front_all (List* other)
  150. {
  151. insert(begin(), other->begin(), other->end());
  152. }
  153. public:
  154. List* clone ()
  155. {
  156. List* result = new List<_Tp, _Alloc>;
  157. foreach (_Tp elem, *this)
  158. {
  159. result->push_back (phc_clone (elem));
  160. }
  161. return result;
  162. }
  163. List* clone () const
  164. {
  165. // Just reuse clone(), we know it's const.
  166. return const_cast<const List<_Tp, _Alloc>*> (this)->clone ();
  167. }
  168. _Tp at (int index) const
  169. {
  170. int i = 0;
  171. assert (this->size () > (unsigned int)(i));
  172. foreach (_Tp elem, *this)
  173. {
  174. if (i == index)
  175. return elem;
  176. i++;
  177. }
  178. assert (0);
  179. }
  180. bool has (const _Tp needle) const
  181. {
  182. foreach (_Tp elem, *this)
  183. if (elem == needle)
  184. return true;
  185. return false;
  186. }
  187. };
  188. template <class Result_type, class List_type>
  189. List<Result_type*>* rewrap_list (const List<List_type*>* list)
  190. {
  191. List<Result_type*>* result = new List<Result_type*>;
  192. foreach (List_type* n, *list)
  193. {
  194. result->push_back (dyc<Result_type> (n));
  195. }
  196. return result;
  197. }
  198. // A filter that removes objects not of the type FILTER_TYPE.
  199. template <class Filter_type, class List_type>
  200. List<Filter_type*>* filter_types (const List<List_type*>* list)
  201. {
  202. List<Filter_type*>* result = new List<Filter_type*>;
  203. foreach (List_type* n, *list)
  204. {
  205. if (isa<Filter_type> (n))
  206. result->push_back (dyc<Filter_type> (n));
  207. }
  208. return result;
  209. }
  210. typedef List<Object*> Object_list;
  211. #define DECL_LIST(T) typedef List<T*> T##_list;
  212. #define DECL_CONST_LIST(T) typedef List<const T*> c##T##_list;
  213. #define DECL(T) class T; DECL_LIST(T); DECL_CONST_LIST(T)
  214. DECL (Boolean);
  215. DECL (Integer);
  216. DECL (String);
  217. #endif // PHC_LIST_H