PageRenderTime 47ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/langtools/src/share/classes/com/sun/tools/javac/util/List.java

http://github.com/ceylon/ceylon-compiler
Java | 486 lines | 318 code | 53 blank | 115 comment | 89 complexity | 9296ab60b651d9c26bdab15e061484da MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
  3. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4. *
  5. * This code is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License version 2 only, as
  7. * published by the Free Software Foundation. Oracle designates this
  8. * particular file as subject to the "Classpath" exception as provided
  9. * by Oracle in the LICENSE file that accompanied this code.
  10. *
  11. * This code is distributed in the hope that it will be useful, but WITHOUT
  12. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  14. * version 2 for more details (a copy is included in the LICENSE file that
  15. * accompanied this code).
  16. *
  17. * You should have received a copy of the GNU General Public License version
  18. * 2 along with this work; if not, write to the Free Software Foundation,
  19. * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22. * or visit www.oracle.com if you need additional information or have any
  23. * questions.
  24. */
  25. package com.sun.tools.javac.util;
  26. import java.lang.reflect.Array;
  27. import java.util.ArrayList;
  28. import java.util.Collection;
  29. import java.util.Collections;
  30. import java.util.Iterator;
  31. import java.util.AbstractCollection;
  32. import java.util.ListIterator;
  33. import java.util.NoSuchElementException;
  34. /** A class for generic linked lists. Links are supposed to be
  35. * immutable, the only exception being the incremental construction of
  36. * lists via ListBuffers. List is the main container class in
  37. * GJC. Most data structures and algorthms in GJC use lists rather
  38. * than arrays.
  39. *
  40. * <p>Lists are always trailed by a sentinel element, whose head and tail
  41. * are both null.
  42. *
  43. * <p><b>This is NOT part of any supported API.
  44. * If you write code that depends on this, you do so at your own risk.
  45. * This code and its internal interfaces are subject to change or
  46. * deletion without notice.</b>
  47. */
  48. public class List<A> extends AbstractCollection<A> implements java.util.List<A> {
  49. /** The first element of the list, supposed to be immutable.
  50. */
  51. public A head;
  52. /** The remainder of the list except for its first element, supposed
  53. * to be immutable.
  54. */
  55. //@Deprecated
  56. public List<A> tail;
  57. /** Construct a list given its head and tail.
  58. */
  59. List(A head, List<A> tail) {
  60. this.tail = tail;
  61. this.head = head;
  62. }
  63. /** Construct an empty list.
  64. */
  65. @SuppressWarnings("unchecked")
  66. public static <A> List<A> nil() {
  67. return (List<A>)EMPTY_LIST;
  68. }
  69. private static List<?> EMPTY_LIST = new List<Object>(null,null) {
  70. public List<Object> setTail(List<Object> tail) {
  71. throw new UnsupportedOperationException();
  72. }
  73. public boolean isEmpty() {
  74. return true;
  75. }
  76. };
  77. /** Construct a list consisting of given element.
  78. */
  79. public static <A> List<A> of(A x1) {
  80. return new List<A>(x1, List.<A>nil());
  81. }
  82. /** Construct a list consisting of given elements.
  83. */
  84. public static <A> List<A> of(A x1, A x2) {
  85. return new List<A>(x1, of(x2));
  86. }
  87. /** Construct a list consisting of given elements.
  88. */
  89. public static <A> List<A> of(A x1, A x2, A x3) {
  90. return new List<A>(x1, of(x2, x3));
  91. }
  92. /** Construct a list consisting of given elements.
  93. */
  94. @SuppressWarnings({"varargs", "unchecked"})
  95. public static <A> List<A> of(A x1, A x2, A x3, A... rest) {
  96. return new List<A>(x1, new List<A>(x2, new List<A>(x3, from(rest))));
  97. }
  98. /**
  99. * Construct a list consisting all elements of given array.
  100. * @param array an array; if {@code null} return an empty list
  101. */
  102. public static <A> List<A> from(A[] array) {
  103. List<A> xs = nil();
  104. if (array != null)
  105. for (int i = array.length - 1; i >= 0; i--)
  106. xs = new List<A>(array[i], xs);
  107. return xs;
  108. }
  109. /** Construct a list consisting of a given number of identical elements.
  110. * @param len The number of elements in the list.
  111. * @param init The value of each element.
  112. */
  113. @Deprecated
  114. public static <A> List<A> fill(int len, A init) {
  115. List<A> l = nil();
  116. for (int i = 0; i < len; i++) l = new List<A>(init, l);
  117. return l;
  118. }
  119. /** Does list have no elements?
  120. */
  121. @Override
  122. public boolean isEmpty() {
  123. return tail == null;
  124. }
  125. /** Does list have elements?
  126. */
  127. //@Deprecated
  128. public boolean nonEmpty() {
  129. return tail != null;
  130. }
  131. /** Return the number of elements in this list.
  132. */
  133. //@Deprecated
  134. public int length() {
  135. List<A> l = this;
  136. int len = 0;
  137. while (l.tail != null) {
  138. l = l.tail;
  139. len++;
  140. }
  141. return len;
  142. }
  143. @Override
  144. public int size() {
  145. return length();
  146. }
  147. public List<A> setTail(List<A> tail) {
  148. this.tail = tail;
  149. return tail;
  150. }
  151. /** Prepend given element to front of list, forming and returning
  152. * a new list.
  153. */
  154. public List<A> prepend(A x) {
  155. return new List<A>(x, this);
  156. }
  157. /** Prepend given list of elements to front of list, forming and returning
  158. * a new list.
  159. */
  160. public List<A> prependList(List<A> xs) {
  161. if (this.isEmpty()) return xs;
  162. if (xs.isEmpty()) return this;
  163. if (xs.tail.isEmpty()) return prepend(xs.head);
  164. // return this.prependList(xs.tail).prepend(xs.head);
  165. List<A> result = this;
  166. List<A> rev = xs.reverse();
  167. Assert.check(rev != xs);
  168. // since xs.reverse() returned a new list, we can reuse the
  169. // individual List objects, instead of allocating new ones.
  170. while (rev.nonEmpty()) {
  171. List<A> h = rev;
  172. rev = rev.tail;
  173. h.setTail(result);
  174. result = h;
  175. }
  176. return result;
  177. }
  178. /** Reverse list.
  179. * If the list is empty or a singleton, then the same list is returned.
  180. * Otherwise a new list is formed.
  181. */
  182. public List<A> reverse() {
  183. // if it is empty or a singleton, return itself
  184. if (isEmpty() || tail.isEmpty())
  185. return this;
  186. List<A> rev = nil();
  187. for (List<A> l = this; l.nonEmpty(); l = l.tail)
  188. rev = new List<A>(l.head, rev);
  189. return rev;
  190. }
  191. /** Append given element at length, forming and returning
  192. * a new list.
  193. */
  194. public List<A> append(A x) {
  195. return of(x).prependList(this);
  196. }
  197. /** Append given list at length, forming and returning
  198. * a new list.
  199. */
  200. public List<A> appendList(List<A> x) {
  201. return x.prependList(this);
  202. }
  203. /**
  204. * Append given list buffer at length, forming and returning a new
  205. * list.
  206. */
  207. public List<A> appendList(ListBuffer<A> x) {
  208. return appendList(x.toList());
  209. }
  210. /** Copy successive elements of this list into given vector until
  211. * list is exhausted or end of vector is reached.
  212. */
  213. @Override @SuppressWarnings("unchecked")
  214. public <T> T[] toArray(T[] vec) {
  215. int i = 0;
  216. List<A> l = this;
  217. Object[] dest = vec;
  218. while (l.nonEmpty() && i < vec.length) {
  219. dest[i] = l.head;
  220. l = l.tail;
  221. i++;
  222. }
  223. if (l.isEmpty()) {
  224. if (i < vec.length)
  225. vec[i] = null;
  226. return vec;
  227. }
  228. vec = (T[])Array.newInstance(vec.getClass().getComponentType(), size());
  229. return toArray(vec);
  230. }
  231. public Object[] toArray() {
  232. return toArray(new Object[size()]);
  233. }
  234. /** Form a string listing all elements with given separator character.
  235. */
  236. public String toString(String sep) {
  237. if (isEmpty()) {
  238. return "";
  239. } else {
  240. StringBuffer buf = new StringBuffer();
  241. buf.append(head);
  242. for (List<A> l = tail; l.nonEmpty(); l = l.tail) {
  243. buf.append(sep);
  244. buf.append(l.head);
  245. }
  246. return buf.toString();
  247. }
  248. }
  249. /** Form a string listing all elements with comma as the separator character.
  250. */
  251. @Override
  252. public String toString() {
  253. return toString(",");
  254. }
  255. /** Compute a hash code, overrides Object
  256. * @see java.util.List#hashCode
  257. */
  258. @Override
  259. public int hashCode() {
  260. List<A> l = this;
  261. int h = 1;
  262. while (l.tail != null) {
  263. h = h * 31 + (l.head == null ? 0 : l.head.hashCode());
  264. l = l.tail;
  265. }
  266. return h;
  267. }
  268. /** Is this list the same as other list?
  269. * @see java.util.List#equals
  270. */
  271. @Override
  272. public boolean equals(Object other) {
  273. if (other instanceof List<?>)
  274. return equals(this, (List<?>)other);
  275. if (other instanceof java.util.List<?>) {
  276. List<A> t = this;
  277. Iterator<?> oIter = ((java.util.List<?>) other).iterator();
  278. while (t.tail != null && oIter.hasNext()) {
  279. Object o = oIter.next();
  280. if ( !(t.head == null ? o == null : t.head.equals(o)))
  281. return false;
  282. t = t.tail;
  283. }
  284. return (t.isEmpty() && !oIter.hasNext());
  285. }
  286. return false;
  287. }
  288. /** Are the two lists the same?
  289. */
  290. public static boolean equals(List<?> xs, List<?> ys) {
  291. while (xs.tail != null && ys.tail != null) {
  292. if (xs.head == null) {
  293. if (ys.head != null) return false;
  294. } else {
  295. if (!xs.head.equals(ys.head)) return false;
  296. }
  297. xs = xs.tail;
  298. ys = ys.tail;
  299. }
  300. return xs.tail == null && ys.tail == null;
  301. }
  302. /** Does the list contain the specified element?
  303. */
  304. @Override
  305. public boolean contains(Object x) {
  306. List<A> l = this;
  307. while (l.tail != null) {
  308. if (x == null) {
  309. if (l.head == null) return true;
  310. } else {
  311. if (l.head.equals(x)) return true;
  312. }
  313. l = l.tail;
  314. }
  315. return false;
  316. }
  317. /** The last element in the list, if any, or null.
  318. */
  319. public A last() {
  320. A last = null;
  321. List<A> t = this;
  322. while (t.tail != null) {
  323. last = t.head;
  324. t = t.tail;
  325. }
  326. return last;
  327. }
  328. @SuppressWarnings("unchecked")
  329. public static <T> List<T> convert(Class<T> klass, List<?> list) {
  330. if (list == null)
  331. return null;
  332. for (Object o : list)
  333. klass.cast(o);
  334. return (List<T>)list;
  335. }
  336. private static Iterator<?> EMPTYITERATOR = new Iterator<Object>() {
  337. public boolean hasNext() {
  338. return false;
  339. }
  340. public Object next() {
  341. throw new java.util.NoSuchElementException();
  342. }
  343. public void remove() {
  344. throw new UnsupportedOperationException();
  345. }
  346. };
  347. @SuppressWarnings("unchecked")
  348. private static <A> Iterator<A> emptyIterator() {
  349. return (Iterator<A>)EMPTYITERATOR;
  350. }
  351. @Override
  352. public Iterator<A> iterator() {
  353. if (tail == null)
  354. return emptyIterator();
  355. return new Iterator<A>() {
  356. List<A> elems = List.this;
  357. public boolean hasNext() {
  358. return elems.tail != null;
  359. }
  360. public A next() {
  361. if (elems.tail == null)
  362. throw new NoSuchElementException();
  363. A result = elems.head;
  364. elems = elems.tail;
  365. return result;
  366. }
  367. public void remove() {
  368. throw new UnsupportedOperationException();
  369. }
  370. };
  371. }
  372. public A get(int index) {
  373. if (index < 0)
  374. throw new IndexOutOfBoundsException(String.valueOf(index));
  375. List<A> l = this;
  376. for (int i = index; i-- > 0 && !l.isEmpty(); l = l.tail)
  377. ;
  378. if (l.isEmpty())
  379. throw new IndexOutOfBoundsException("Index: " + index + ", " +
  380. "Size: " + size());
  381. return l.head;
  382. }
  383. public boolean addAll(int index, Collection<? extends A> c) {
  384. if (c.isEmpty())
  385. return false;
  386. throw new UnsupportedOperationException();
  387. }
  388. public A set(int index, A element) {
  389. throw new UnsupportedOperationException();
  390. }
  391. public void add(int index, A element) {
  392. throw new UnsupportedOperationException();
  393. }
  394. public A remove(int index) {
  395. throw new UnsupportedOperationException();
  396. }
  397. public int indexOf(Object o) {
  398. int i = 0;
  399. for (List<A> l = this; l.tail != null; l = l.tail, i++) {
  400. if (l.head == null ? o == null : l.head.equals(o))
  401. return i;
  402. }
  403. return -1;
  404. }
  405. public int lastIndexOf(Object o) {
  406. int last = -1;
  407. int i = 0;
  408. for (List<A> l = this; l.tail != null; l = l.tail, i++) {
  409. if (l.head == null ? o == null : l.head.equals(o))
  410. last = i;
  411. }
  412. return last;
  413. }
  414. public ListIterator<A> listIterator() {
  415. return Collections.unmodifiableList(new ArrayList<A>(this)).listIterator();
  416. }
  417. public ListIterator<A> listIterator(int index) {
  418. return Collections.unmodifiableList(new ArrayList<A>(this)).listIterator(index);
  419. }
  420. public java.util.List<A> subList(int fromIndex, int toIndex) {
  421. if (fromIndex < 0 || toIndex > size() || fromIndex > toIndex)
  422. throw new IllegalArgumentException();
  423. ArrayList<A> a = new ArrayList<A>(toIndex - fromIndex);
  424. int i = 0;
  425. for (List<A> l = this; l.tail != null; l = l.tail, i++) {
  426. if (i == toIndex)
  427. break;
  428. if (i >= fromIndex)
  429. a.add(l.head);
  430. }
  431. return Collections.unmodifiableList(a);
  432. }
  433. }