2013-09-29 19:33:12 +00:00
|
|
|
/*
|
|
|
|
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
|
2013-11-24 01:05:46 +00:00
|
|
|
#include <utility>
|
2013-09-29 19:33:12 +00:00
|
|
|
#include "util/debug.h"
|
2013-11-23 23:33:25 +00:00
|
|
|
#include "util/rc.h"
|
|
|
|
#include "util/optional.h"
|
2013-09-29 19:33:12 +00:00
|
|
|
|
|
|
|
namespace lean {
|
|
|
|
/**
|
|
|
|
\brief ML-like lazy lists.
|
|
|
|
*/
|
|
|
|
template<typename T>
|
|
|
|
class lazy_list {
|
|
|
|
public:
|
2013-11-23 23:33:25 +00:00
|
|
|
typedef optional<std::pair<T, lazy_list>> maybe_pair; // head and tail pair
|
|
|
|
private:
|
|
|
|
class cell_base {
|
2013-09-29 19:33:12 +00:00
|
|
|
MK_LEAN_RC();
|
|
|
|
void dealloc() { delete this; }
|
|
|
|
public:
|
2013-11-23 23:33:25 +00:00
|
|
|
cell_base():m_rc(0) {}
|
|
|
|
virtual ~cell_base() {}
|
|
|
|
virtual maybe_pair pull() const = 0;
|
2013-09-29 19:33:12 +00:00
|
|
|
};
|
|
|
|
|
2013-11-23 23:33:25 +00:00
|
|
|
template<typename F>
|
|
|
|
class cell : public cell_base {
|
|
|
|
F m_f;
|
2013-09-29 19:33:12 +00:00
|
|
|
public:
|
2013-11-23 23:33:25 +00:00
|
|
|
cell(F && f):cell_base(), m_f(f) {}
|
|
|
|
virtual ~cell() {}
|
|
|
|
virtual maybe_pair pull() const { return m_f(); }
|
2013-09-29 19:33:12 +00:00
|
|
|
};
|
|
|
|
|
2013-11-23 23:33:25 +00:00
|
|
|
cell_base * m_ptr;
|
2013-09-29 19:33:12 +00:00
|
|
|
public:
|
|
|
|
lazy_list():m_ptr(nullptr) {}
|
|
|
|
lazy_list(lazy_list const & s):m_ptr(s.m_ptr) { if (m_ptr) m_ptr->inc_ref(); }
|
2013-11-23 23:33:25 +00:00
|
|
|
lazy_list(lazy_list && s):m_ptr(s.m_ptr) { s.m_ptr = nullptr; }
|
|
|
|
template<typename F> explicit lazy_list(F && f):m_ptr(new cell<F>(std::forward<F>(f))) { m_ptr->inc_ref(); }
|
2013-09-29 19:33:12 +00:00
|
|
|
~lazy_list() { if (m_ptr) m_ptr->dec_ref(); }
|
|
|
|
|
2013-11-23 23:33:25 +00:00
|
|
|
lazy_list & operator=(lazy_list const & s) { LEAN_COPY_REF(lazy_list, s); }
|
|
|
|
lazy_list & operator=(lazy_list && s) { LEAN_MOVE_REF(lazy_list, s); }
|
2013-09-29 19:33:12 +00:00
|
|
|
|
2013-11-23 23:33:25 +00:00
|
|
|
maybe_pair pull() const {
|
|
|
|
if (m_ptr)
|
|
|
|
return m_ptr->pull();
|
|
|
|
else
|
|
|
|
return maybe_pair();
|
|
|
|
}
|
2013-09-29 19:33:12 +00:00
|
|
|
|
2013-11-23 23:33:25 +00:00
|
|
|
friend T head(lazy_list const & l) { return l.pull()->first; }
|
|
|
|
friend lazy_list tail(lazy_list const & l) { return l.pull()->second; }
|
2013-09-29 19:33:12 +00:00
|
|
|
};
|
|
|
|
}
|