Add list template.

Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
Leonardo de Moura 2013-07-24 16:32:50 -07:00
parent b45a5d231c
commit 5889c6488f
4 changed files with 113 additions and 1 deletions

View file

@ -10,3 +10,6 @@ add_test(format ${CMAKE_CURRENT_BINARY_DIR}/format)
add_executable(buffer buffer.cpp)
target_link_libraries(buffer ${EXTRA_LIBS})
add_test(buffer ${CMAKE_CURRENT_BINARY_DIR}/buffer)
add_executable(list list.cpp)
target_link_libraries(list ${EXTRA_LIBS})
add_test(list ${CMAKE_CURRENT_BINARY_DIR}/list)

View file

@ -6,6 +6,7 @@ Author: Leonardo de Moura
*/
#include <vector>
#include "buffer.h"
#include "test.h"
using namespace lean;
template<typename C>
@ -27,6 +28,7 @@ void perftest() {
}
int main() {
continue_on_violation(true);
loop<buffer<int>>(100);
return 0;
return has_violations() ? 1 : 0;
}

28
src/tests/util/list.cpp Normal file
View file

@ -0,0 +1,28 @@
/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include "list.h"
#include "test.h"
using namespace lean;
static void tst1() {
list<int> l;
lean_assert(is_nil(l));
for (int i = 0; i < 10; i++) {
list<int> old = l;
l = list<int>(i, l);
lean_assert(!is_nil(l));
lean_assert(car(l) == i);
lean_assert(cdr(l) == old);
}
std::cout << l << "\n";
}
int main() {
continue_on_violation(true);
tst1();
return has_violations() ? 1 : 0;
}

79
src/util/list.h Normal file
View file

@ -0,0 +1,79 @@
/*
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 <iostream>
#include "rc.h"
#include "debug.h"
namespace lean {
/**
\brief Basic list template.
Remark: == is pointer equality.
*/
template<typename T>
class list {
struct cell {
MK_LEAN_RC()
T m_head;
list m_tail;
cell(T const & h, list const & t):m_rc(1), m_head(h), m_tail(t) {}
~cell() {}
void dealloc() { delete this; }
};
cell * m_ptr;
public:
list():m_ptr(nullptr) {}
list(T const & h, list const & t):m_ptr(new cell(h, t)) {}
list(list const & s):m_ptr(s.m_ptr) { if (m_ptr) m_ptr->inc_ref(); }
list(list&& s):m_ptr(s.m_ptr) { s.m_ptr = 0; }
~list() { if (m_ptr) m_ptr->dec_ref(); }
list & operator=(list const & s) {
if (s.m_ptr)
s.m_ptr->inc_ref();
if (m_ptr)
m_ptr->dec_ref();
m_ptr = s.m_ptr;
return *this;
}
list & operator=(list && s) {
if (m_ptr)
m_ptr->dec_ref();
m_ptr = s.m_ptr;
s.m_ptr = 0;
return *this;
}
friend bool is_nil(list const & l) { return l.m_ptr == nullptr; }
friend T const & head(list const & l) { lean_assert(!is_nil(l)); return l.m_ptr->m_head; }
friend list const & tail(list const & l) { lean_assert(!is_nil(l)); return l.m_ptr->m_tail; }
friend bool operator==(list const & l1, list const & l2) { return l1.m_ptr == l2.m_ptr; }
friend bool operator!=(list const & l1, list const & l2) { return l1.m_ptr != l2.m_ptr; }
};
template<typename T> inline list<T> cons(T const & h, list<T> const & t) { return list<T>(h, t); }
template<typename T> inline T const & car(list<T> const & l) { return head(l); }
template<typename T> inline list<T> const & cdr(list<T> const & l) { return tail(l); }
template<typename T> inline std::ostream & operator<<(std::ostream & out, list<T> const & l) {
out << "(";
bool first = true;
list<T> const * ptr = &l;
while (!is_nil(*ptr)) {
if (first)
first = false;
else
out << " ";
out << head(*ptr);
ptr = &tail(*ptr);
}
out << ")";
return out;
}
}