/* * Vitry, copyright (C) Hans Hoglund 2011 * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * See COPYING.txt for details. */ package vitry.runtime.struct; import vitry.runtime.Function; import vitry.runtime.Native; import vitry.runtime.util.Utils; /** * Sequence operations used by runtime. */ public final class Seqs { private static final Object[] EMPTY_ARRAY = new Object[0]; private Seqs() {} public static boolean isNil(Object xs) { if (xs == null) return true; if (xs instanceof Seq) { return ((Seq<?>) xs).isNil(); } else return false; } public static <T> Seq<T> single(T x) { return cons(x, null); } public static <T> Seq<T> cons(T x, Seq<T> xs) { // if (isNil(xs)) if (xs == null) return new SingleSeq<T>(x); else return xs.prepend(x); } public static <T> Seq<T> from(T... a) { if (a.length == 0) return null; else return new ArraySeq<T>(a); } public static <T> Seq<T> from(Iterable<T> a) { if (!a.iterator().hasNext()) return null; else return new IterableSeq<T>(a); } public static <T> T head(Seq<T> xs) { return xs.head(); } public static <T> Seq<T> tail(Seq<T> xs) { return xs.tail(); } public static <T> T last(Seq<T> xs) { while (!isNil(xs.tail())) { xs = tail(xs); } T r = xs.head(); return r; } public static <T> Seq<T> init(Seq<T> xs) { return reverse(reverse(xs).tail()); } public static <T> Seq<T> untilElement(Seq<T> xs, T y) { if (isNil(xs) || xs.head().equals(y)) return null; else return cons(head(xs), untilElement(tail(xs), y)); } public static int length(Finite<?> xs) { return xs.length(); } public static int length(Seq<?> xs) { int length = 0; do { length++; xs = xs.tail(); } while (!isNil(xs)); return length; } public static <T> T first(Seq<T> xs) { return xs.head(); } public static <T> T second(Seq<T> xs) { return xs.tail().head(); } public static <T> T third(Seq<T> xs) { return xs.tail().tail().head(); } public static <T> T nth(Seq<T> xs, int n) { for (int i = 0; i < n; i++) xs = tail(xs); return xs.head(); } public static <U, T> U foldl(Function f, U z, Seq<T> xs) { U res = z; while (!isNil(xs)) { res = Utils.<U> unsafe(f.apply(res, xs.head())); xs = xs.tail(); } return res; } public static <U, T> U foldr(Function f, U z, Seq<T> xs) { U res = z; xs = reverse(xs); while (!isNil(xs)) { res = Utils.<U> unsafe(f.apply(xs.head(), res)); xs = xs.tail(); } return res; } public static <U, T> U foldlUnwrap(Function f, U z, Seq<T> xs) { U res = z; while (!isNil(xs)) { res = Utils.<U> unsafe(f.apply(res, Native.unwrap(xs.head()))); xs = xs.tail(); } return res; } public static <U, T> U foldrUnwrap(Function f, U z, Seq<T> xs) { U res = z; xs = reverse(xs); while (!isNil(xs)) { res = Utils.<U> unsafe(f.apply(Native.unwrap(xs.head()), res)); xs = xs.tail(); } return res; } public static <T> Seq<T> concat(Seq<T> xs, Seq<T> ys) { if (isNil(xs)) return ys; return new ConcedSeq<T>(xs, ys); } public static <T> Seq<T> reverse(Seq<T> xs) { Seq<T> ys = null; while (!isNil(xs)) { ys = cons(xs.head(), ys); xs = xs.tail(); } return ys; } // Utils public static <T> Seq<T> printable(Seq<T> s) { return new PrintableSeq<T>(s); } public static <T> SeqIterator<T> iterate(Seq<T> s) { return new SeqIterator<T>(s); } public static <T> java.util.List<T> toCollection(Seq<T> s) { java.util.List<T> l = new java.util.LinkedList<T>(); while (!isNil(s)) { l.add(s.head()); s = tail(s); } return l; } public static Object[] toArray(Seq<?> s) { if (isNil(s)) return EMPTY_ARRAY; Object[] a; if (s instanceof Finite) a = new Object[ ((Finite<?>) s).length()]; else a = new Object[length(s)]; int i = 0; do { a[i++] = s.head(); s = s.tail(); } while (!isNil(s)); return a; } public static <T> T[] toArray(Seq<T> s, T[] dummy) { java.util.List<T> l = new java.util.LinkedList<T>(); if (isNil(s)) return l.toArray(dummy); do { l.add(s.head()); s = tail(s); } while (!isNil(s)); return l.toArray(dummy); } }