/* Copyright (c) 2013 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ #pragma once #include #include "util/list.h" #include "util/buffer.h" #include "util/pair.h" namespace lean { /** \brief Copy the values in the list \c l to the buffer \c r. */ template void to_buffer(list const & l, buffer & r) { for (T const & v : l) { r.push_back(v); } } /** \brief Auxiliary function for reverse function. */ template list reverse_aux(list const & l, list const & r) { if (is_nil(l)) return r; else return reverse_aux(cdr(l), cons(car(l), r)); } /** \brief Return the reverse list. */ template list reverse(list const & l) { return reverse_aux(l, list()); } /** \brief Return two lists \c l1 and \c l2 of approximately the same size s.t. append(l1, l2) == l */ template std::pair, list> split(list const & l) { if (is_nil(l)) { return mk_pair(l, l); } else if (is_nil(cdr(l))) { return mk_pair(l, list()); } else { buffer tmp; to_buffer(l, tmp); unsigned mid = tmp.size() / 2; auto beg = tmp.begin(); lean_assert(beg + mid <= tmp.end()); return mk_pair(to_list(beg, beg + mid), to_list(beg + mid, tmp.end())); } } /** \brief Return two lists \c l1 and \c l2 of approximately the same size s.t. append(l1, reverse(l2)) == l */ template std::pair, list> split_reverse_second(list const & l) { if (is_nil(l)) { return mk_pair(l, l); } else if (is_nil(cdr(l))) { return mk_pair(l, list()); } else { buffer tmp; to_buffer(l, tmp); unsigned mid = tmp.size() / 2; auto beg = tmp.begin(); lean_assert(beg + mid <= tmp.end()); return mk_pair(to_list(beg, beg + mid), reverse_to_list(beg+mid, tmp.end())); } } /** \brief Append two lists */ template list append(list const & l1, list const & l2) { if (!l1) { return l2; } else if (!l2) { return l1; } else { buffer tmp; list r = l2; to_buffer(l1, tmp); unsigned i = tmp.size(); while (i > 0) { --i; r = cons(tmp[i], r); } return r; } } /** \brief Given list (a_0, ..., a_k), return list (f(a_0), ..., f(a_k)). */ template list map(list const & l, F f) { static_assert(std::is_same::type, T>::value, "map: return type of f is not sxpr"); if (is_nil(l)) { return l; } else { return list(f(head(l)), map(tail(l), f)); } } /** \brief Given list (a_0, ..., a_k), exec f(a_0); f(a_1); ... f(a_k). */ template void for_each(list const & l, F f) { static_assert(std::is_same::type, void>::value, "for_each: return type of f is not void"); if (is_nil(l)) { return; } else { f(head(l)); return for_each(tail(l), f); } } /** \brief Compare two lists using the binary predicate p. */ template bool compare(list const & l1, list const & l2, P p) { static_assert(std::is_same::type, bool>::value, "compare: return type of f is not bool"); auto it1 = l1.begin(); auto it2 = l2.begin(); auto end1 = l1.end(); auto end2 = l2.end(); for (; it1 != end1 && it2 != end2; ++it1, ++it2) { if (!p(*it1, *it2)) return false; } return it1 == end1 && it2 == end2; } }