Add operator== to list
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
5bfb074eaf
commit
913fd14549
5 changed files with 58 additions and 6 deletions
|
@ -5,18 +5,22 @@ Released under Apache 2.0 license as described in the file LICENSE.
|
||||||
Author: Leonardo de Moura
|
Author: Leonardo de Moura
|
||||||
*/
|
*/
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
#include <unordered_map>
|
||||||
#include "frontend.h"
|
#include "frontend.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
|
#include "operator_info.h"
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
|
|
||||||
static name g_overload_prefix(name(0u), "overload");
|
|
||||||
|
|
||||||
/** \brief Implementation of the Lean frontend */
|
/** \brief Implementation of the Lean frontend */
|
||||||
struct frontend::imp {
|
struct frontend::imp {
|
||||||
|
// Remark: only named objects are stored in the dictionary.
|
||||||
|
typedef std::unordered_map<name, operator_info, name_hash, name_eq> operator_table;
|
||||||
std::atomic<unsigned> m_num_children;
|
std::atomic<unsigned> m_num_children;
|
||||||
std::shared_ptr<imp> m_parent;
|
std::shared_ptr<imp> m_parent;
|
||||||
environment m_env;
|
environment m_env;
|
||||||
|
operator_table m_nud; // nud table for Pratt's parser
|
||||||
|
operator_table m_led; // led table for Pratt's parser
|
||||||
|
operator_table m_name_to_operator; // map internal names to operators (this is used for pretty printing)
|
||||||
|
|
||||||
bool has_children() const { return m_num_children > 0; }
|
bool has_children() const { return m_num_children > 0; }
|
||||||
void inc_children() { m_num_children++; }
|
void inc_children() { m_num_children++; }
|
||||||
|
|
|
@ -30,6 +30,15 @@ struct operator_info::imp {
|
||||||
imp(imp const & s):
|
imp(imp const & s):
|
||||||
m_rc(1), m_fixity(s.m_fixity), m_assoc(s.m_assoc), m_precedence(s.m_precedence), m_op_parts(s.m_op_parts), m_names(s.m_names) {
|
m_rc(1), m_fixity(s.m_fixity), m_assoc(s.m_assoc), m_precedence(s.m_precedence), m_op_parts(s.m_op_parts), m_names(s.m_names) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool is_eq(imp const & other) const {
|
||||||
|
return
|
||||||
|
m_fixity == other.m_fixity &&
|
||||||
|
m_assoc == other.m_assoc &&
|
||||||
|
m_precedence == other.m_precedence &&
|
||||||
|
m_op_parts == other.m_op_parts;
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
operator_info::operator_info(imp * p):m_ptr(p) {}
|
operator_info::operator_info(imp * p):m_ptr(p) {}
|
||||||
|
@ -62,6 +71,15 @@ list<name> const & operator_info::get_op_name_parts() const { lean_assert(m_ptr)
|
||||||
|
|
||||||
operator_info operator_info::copy() const { return operator_info(new imp(*m_ptr)); }
|
operator_info operator_info::copy() const { return operator_info(new imp(*m_ptr)); }
|
||||||
|
|
||||||
|
bool operator==(operator_info const & op1, operator_info const & op2) {
|
||||||
|
if ((op1.m_ptr == nullptr) != (op2.m_ptr == nullptr))
|
||||||
|
return false;
|
||||||
|
if (op1.m_ptr)
|
||||||
|
return op1.m_ptr->is_eq(*(op2.m_ptr));
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
operator_info infixr(name const & op, unsigned precedence) {
|
operator_info infixr(name const & op, unsigned precedence) {
|
||||||
return operator_info(new operator_info::imp(op, fixity::Infix, associativity::Right, precedence));
|
return operator_info(new operator_info::imp(op, fixity::Infix, associativity::Right, precedence));
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,9 @@ public:
|
||||||
|
|
||||||
/** \brief Return a copy of the operator. */
|
/** \brief Return a copy of the operator. */
|
||||||
operator_info copy() const;
|
operator_info copy() const;
|
||||||
|
|
||||||
|
friend bool operator==(operator_info const & op1, operator_info const & op2);
|
||||||
|
friend bool operator!=(operator_info const & op1, operator_info const & op2) { return !(op1 == op2); }
|
||||||
};
|
};
|
||||||
operator_info infixl(name const & op, unsigned precedence);
|
operator_info infixl(name const & op, unsigned precedence);
|
||||||
operator_info infixr(name const & op, unsigned precedence);
|
operator_info infixr(name const & op, unsigned precedence);
|
||||||
|
|
|
@ -17,7 +17,7 @@ static void tst1() {
|
||||||
l = list<int>(i, l);
|
l = list<int>(i, l);
|
||||||
lean_assert(!is_nil(l));
|
lean_assert(!is_nil(l));
|
||||||
lean_assert(car(l) == i);
|
lean_assert(car(l) == i);
|
||||||
lean_assert(cdr(l) == old);
|
lean_assert(is_eqp(cdr(l), old));
|
||||||
}
|
}
|
||||||
std::cout << l << "\n";
|
std::cout << l << "\n";
|
||||||
}
|
}
|
||||||
|
@ -45,9 +45,22 @@ static void tst3() {
|
||||||
lean_assert(length(tail(list<int>(10, list<int>()))) == 0);
|
lean_assert(length(tail(list<int>(10, list<int>()))) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tst4() {
|
||||||
|
list<int> l1{1, 2, 3};
|
||||||
|
list<int> l2{1, 2, 3};
|
||||||
|
lean_assert(l1 == l2);
|
||||||
|
lean_assert(l1 != cons(1, l2));
|
||||||
|
lean_assert(l1 != tail(l1));
|
||||||
|
lean_assert(list<int>() == list<int>());
|
||||||
|
lean_assert(l2 != list<int>());
|
||||||
|
lean_assert(l1 != list<int>({1, 2, 3, 4}));
|
||||||
|
lean_assert(l1 != tail(list<int>{1, 2, 3, 4}));
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
tst1();
|
tst1();
|
||||||
tst2();
|
tst2();
|
||||||
tst3();
|
tst3();
|
||||||
|
tst4();
|
||||||
return has_violations() ? 1 : 0;
|
return has_violations() ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,22 @@ public:
|
||||||
friend bool is_nil(list const & l) { return l.m_ptr == nullptr; }
|
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 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 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; }
|
friend bool is_eqp(list const & l1, list const & l2) { return l1.m_ptr == l2.m_ptr; }
|
||||||
|
friend bool operator==(list const & l1, list const & l2) {
|
||||||
|
cell * it1 = l1.m_ptr;
|
||||||
|
cell * it2 = l2.m_ptr;
|
||||||
|
while (it1 != nullptr && it2 != nullptr) {
|
||||||
|
if (it1 == it2)
|
||||||
|
return true;
|
||||||
|
if (it1->m_head != it2->m_head)
|
||||||
|
return false;
|
||||||
|
it1 = it1->m_tail.m_ptr;
|
||||||
|
it2 = it2->m_tail.m_ptr;
|
||||||
|
}
|
||||||
|
return it1 == nullptr && it2 == nullptr;
|
||||||
|
}
|
||||||
|
friend bool operator!=(list const & l1, list const & l2) { return !(l1 == l2); }
|
||||||
|
|
||||||
class iterator {
|
class iterator {
|
||||||
friend class list;
|
friend class list;
|
||||||
|
|
Loading…
Reference in a new issue