2014-08-06 22:25:28 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
2014-08-17 19:14:42 +00:00
|
|
|
#include <algorithm>
|
2014-08-07 01:10:33 +00:00
|
|
|
#include <vector>
|
2014-08-27 01:06:37 +00:00
|
|
|
#include <set>
|
2014-08-17 19:14:42 +00:00
|
|
|
#include "util/thread.h"
|
2014-08-27 01:06:37 +00:00
|
|
|
#include "kernel/environment.h"
|
2014-08-06 22:25:28 +00:00
|
|
|
#include "library/choice.h"
|
2014-09-18 23:51:59 +00:00
|
|
|
#include "library/scoped_ext.h"
|
2014-08-06 22:25:28 +00:00
|
|
|
#include "frontends/lean/info_manager.h"
|
|
|
|
#include "frontends/lean/pp_options.h"
|
|
|
|
|
|
|
|
namespace lean {
|
2014-08-17 19:14:42 +00:00
|
|
|
class info_data;
|
2014-08-16 01:09:31 +00:00
|
|
|
|
2014-09-03 18:52:35 +00:00
|
|
|
enum class info_kind { Type = 0, ExtraType, Synth, Overload, Coercion, Symbol, Identifier };
|
2014-08-26 21:23:12 +00:00
|
|
|
bool operator<(info_kind k1, info_kind k2) { return static_cast<unsigned>(k1) < static_cast<unsigned>(k2); }
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
class info_data_cell {
|
|
|
|
unsigned m_column;
|
|
|
|
MK_LEAN_RC();
|
|
|
|
void dealloc() { delete this; }
|
|
|
|
protected:
|
|
|
|
friend info_data;
|
|
|
|
virtual info_data_cell * instantiate(substitution &) const { return nullptr; }
|
|
|
|
public:
|
|
|
|
info_data_cell():m_column(0), m_rc(0) {}
|
|
|
|
info_data_cell(unsigned c):m_column(c), m_rc(0) {}
|
|
|
|
virtual ~info_data_cell() {}
|
2014-09-04 21:02:53 +00:00
|
|
|
/** \brief Return true iff the information is considered "cheap"
|
|
|
|
If the column number is not provided in the method info_manager::display,
|
|
|
|
then only "cheap" information is displayed.
|
|
|
|
*/
|
|
|
|
virtual bool is_cheap() const { return true; }
|
2014-08-26 21:23:12 +00:00
|
|
|
virtual info_kind kind() const = 0;
|
2014-08-17 19:14:42 +00:00
|
|
|
unsigned get_column() const { return m_column; }
|
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const = 0;
|
|
|
|
virtual int compare(info_data_cell const & d) const {
|
|
|
|
if (m_column != d.m_column)
|
|
|
|
return m_column < d.m_column ? -1 : 1;
|
2014-08-26 21:23:12 +00:00
|
|
|
if (kind() != d.kind())
|
|
|
|
return kind() < d.kind() ? -1 : 1;
|
2014-08-17 19:14:42 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
2014-08-06 22:25:28 +00:00
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
class info_data {
|
|
|
|
private:
|
|
|
|
info_data_cell * m_ptr;
|
|
|
|
public:
|
|
|
|
info_data();
|
|
|
|
info_data(info_data_cell * c):m_ptr(c) { lean_assert(c); m_ptr->inc_ref(); }
|
|
|
|
info_data(info_data const & s):m_ptr(s.m_ptr) { if (m_ptr) m_ptr->inc_ref(); }
|
|
|
|
info_data(info_data && s):m_ptr(s.m_ptr) { s.m_ptr = nullptr; }
|
|
|
|
~info_data() { if (m_ptr) m_ptr->dec_ref(); }
|
|
|
|
friend void swap(info_data & a, info_data & b) { std::swap(a.m_ptr, b.m_ptr); }
|
|
|
|
info_data & operator=(info_data const & s) { LEAN_COPY_REF(s); }
|
|
|
|
info_data & operator=(info_data && s) { LEAN_MOVE_REF(s); }
|
|
|
|
int compare(info_data const & d) const { return m_ptr->compare(*d.m_ptr); }
|
|
|
|
int compare(info_data_cell const & d) const { return m_ptr->compare(d); }
|
|
|
|
info_data instantiate(substitution & s) const;
|
|
|
|
unsigned get_column() const { return m_ptr->get_column(); }
|
2014-09-04 21:02:53 +00:00
|
|
|
bool is_cheap() const { return m_ptr->is_cheap(); }
|
2014-08-17 19:14:42 +00:00
|
|
|
void display(io_state_stream const & ios, unsigned line) const { m_ptr->display(ios, line); }
|
2014-09-03 08:35:04 +00:00
|
|
|
info_data_cell const * raw() const { return m_ptr; }
|
2014-08-17 15:28:02 +00:00
|
|
|
};
|
2014-08-06 22:25:28 +00:00
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
struct tmp_info_data : public info_data_cell {
|
|
|
|
tmp_info_data(unsigned c):info_data_cell(c) {}
|
2014-08-26 21:23:12 +00:00
|
|
|
virtual info_kind kind() const { lean_unreachable(); }
|
2014-08-17 19:14:42 +00:00
|
|
|
virtual void display(io_state_stream const &, unsigned) const { lean_unreachable(); } // LCOV_EXCL_LINE
|
|
|
|
};
|
2014-08-14 17:37:24 +00:00
|
|
|
|
2014-09-23 17:00:36 +00:00
|
|
|
static info_data * g_dummy = nullptr;
|
|
|
|
void initialize_info_manager() {
|
|
|
|
g_dummy = new info_data(new tmp_info_data(0));
|
|
|
|
}
|
|
|
|
|
|
|
|
void finalize_info_manager() {
|
|
|
|
delete g_dummy;
|
|
|
|
}
|
|
|
|
|
|
|
|
info_data::info_data():info_data(*g_dummy) {}
|
2014-08-17 19:14:42 +00:00
|
|
|
|
2014-08-17 15:28:02 +00:00
|
|
|
info_data info_data::instantiate(substitution & s) const {
|
|
|
|
if (auto r = m_ptr->instantiate(s)) {
|
|
|
|
return info_data(r);
|
|
|
|
} else {
|
|
|
|
return *this;
|
2014-08-06 22:25:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-17 15:28:02 +00:00
|
|
|
class type_info_data : public info_data_cell {
|
|
|
|
protected:
|
|
|
|
expr m_expr;
|
|
|
|
public:
|
|
|
|
type_info_data() {}
|
2014-08-17 19:14:42 +00:00
|
|
|
type_info_data(unsigned c, expr const & e):info_data_cell(c), m_expr(e) {}
|
2014-08-17 15:28:02 +00:00
|
|
|
|
2014-08-22 22:55:15 +00:00
|
|
|
expr const & get_type() const { return m_expr; }
|
2014-08-17 15:28:02 +00:00
|
|
|
|
2014-08-26 21:23:12 +00:00
|
|
|
virtual info_kind kind() const { return info_kind::Type; }
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const {
|
|
|
|
ios << "-- TYPE|" << line << "|" << get_column() << "\n";
|
2014-08-17 15:28:02 +00:00
|
|
|
ios << m_expr << endl;
|
|
|
|
ios << "-- ACK" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual info_data_cell * instantiate(substitution & s) const {
|
|
|
|
expr e = s.instantiate(m_expr);
|
2014-08-22 22:55:15 +00:00
|
|
|
return is_eqp(e, m_expr) ? nullptr : new type_info_data(get_column(), e);
|
2014-08-17 15:28:02 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-03 18:52:35 +00:00
|
|
|
class extra_type_info_data : public info_data_cell {
|
|
|
|
protected:
|
|
|
|
expr m_expr;
|
|
|
|
expr m_type;
|
|
|
|
public:
|
|
|
|
extra_type_info_data() {}
|
|
|
|
extra_type_info_data(unsigned c, expr const & e, expr const & t):info_data_cell(c), m_expr(e), m_type(t) {}
|
|
|
|
|
|
|
|
virtual info_kind kind() const { return info_kind::ExtraType; }
|
2014-09-04 21:02:53 +00:00
|
|
|
virtual bool is_cheap() const { return false; }
|
2014-09-03 18:52:35 +00:00
|
|
|
|
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const {
|
|
|
|
ios << "-- EXTRA_TYPE|" << line << "|" << get_column() << "\n";
|
|
|
|
ios << m_expr << endl;
|
|
|
|
ios << "--" << endl;
|
|
|
|
ios << m_type << endl;
|
|
|
|
ios << "-- ACK" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual info_data_cell * instantiate(substitution & s) const {
|
|
|
|
expr e = s.instantiate(m_expr);
|
|
|
|
expr t = s.instantiate(m_type);
|
|
|
|
return is_eqp(e, m_expr) && is_eqp(t, m_type) ? nullptr : new extra_type_info_data(get_column(), e, t);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-08-17 15:28:02 +00:00
|
|
|
class synth_info_data : public type_info_data {
|
|
|
|
public:
|
2014-08-17 19:14:42 +00:00
|
|
|
synth_info_data(unsigned c, expr const & e):type_info_data(c, e) {}
|
2014-08-26 21:23:12 +00:00
|
|
|
|
|
|
|
virtual info_kind kind() const { return info_kind::Synth; }
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const {
|
|
|
|
ios << "-- SYNTH|" << line << "|" << get_column() << "\n";
|
2014-08-17 15:28:02 +00:00
|
|
|
ios << m_expr << endl;
|
|
|
|
ios << "-- ACK" << endl;
|
|
|
|
}
|
2014-08-22 22:55:15 +00:00
|
|
|
|
|
|
|
virtual info_data_cell * instantiate(substitution & s) const {
|
|
|
|
expr e = s.instantiate(m_expr);
|
|
|
|
return is_eqp(e, m_expr) ? nullptr : new synth_info_data(get_column(), e);
|
|
|
|
}
|
2014-09-03 08:35:04 +00:00
|
|
|
|
|
|
|
expr const & get_expr() const { return m_expr; }
|
2014-08-17 15:28:02 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class overload_info_data : public info_data_cell {
|
|
|
|
expr m_choices;
|
|
|
|
public:
|
2014-08-17 19:14:42 +00:00
|
|
|
overload_info_data(unsigned c, expr const & e):info_data_cell(c), m_choices(e) {}
|
2014-08-26 21:23:12 +00:00
|
|
|
|
|
|
|
virtual info_kind kind() const { return info_kind::Overload; }
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const {
|
|
|
|
ios << "-- OVERLOAD|" << line << "|" << get_column() << "\n";
|
2014-08-17 15:28:02 +00:00
|
|
|
options os = ios.get_options();
|
|
|
|
os = os.update(get_pp_full_names_option_name(), true);
|
|
|
|
auto new_ios = ios.update_options(os);
|
|
|
|
for (unsigned i = 0; i < get_num_choices(m_choices); i++) {
|
|
|
|
if (i > 0)
|
|
|
|
ios << "--\n";
|
|
|
|
new_ios << get_choice(m_choices, i) << endl;
|
|
|
|
}
|
|
|
|
new_ios << "-- ACK" << endl;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-09-10 00:44:19 +00:00
|
|
|
class overload_notation_info_data : public info_data_cell {
|
|
|
|
list<expr> m_alts;
|
|
|
|
public:
|
|
|
|
overload_notation_info_data(unsigned c, list<expr> const & as):info_data_cell(c), m_alts(as) {}
|
|
|
|
|
|
|
|
virtual info_kind kind() const { return info_kind::Overload; }
|
|
|
|
|
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const {
|
|
|
|
ios << "-- OVERLOAD|" << line << "|" << get_column() << "\n";
|
|
|
|
options os = ios.get_options();
|
|
|
|
os = os.update(get_pp_full_names_option_name(), true);
|
|
|
|
auto new_ios = ios.update_options(os);
|
|
|
|
bool first = true;
|
|
|
|
for (expr const & e : m_alts) {
|
|
|
|
if (first) first = false; else ios << "--\n";
|
|
|
|
new_ios << e << endl;
|
|
|
|
}
|
|
|
|
new_ios << "-- ACK" << endl;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-08-17 15:28:02 +00:00
|
|
|
class coercion_info_data : public info_data_cell {
|
2014-09-03 16:34:13 +00:00
|
|
|
expr m_expr;
|
|
|
|
expr m_type;
|
2014-08-17 15:28:02 +00:00
|
|
|
public:
|
2014-09-03 16:34:13 +00:00
|
|
|
coercion_info_data(unsigned c, expr const & e, expr const & t):
|
|
|
|
info_data_cell(c), m_expr(e), m_type(t) {}
|
2014-08-26 21:23:12 +00:00
|
|
|
|
|
|
|
virtual info_kind kind() const { return info_kind::Coercion; }
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const {
|
|
|
|
ios << "-- COERCION|" << line << "|" << get_column() << "\n";
|
2014-08-17 15:28:02 +00:00
|
|
|
options os = ios.get_options();
|
2014-09-08 15:30:08 +00:00
|
|
|
os = os.update(get_pp_coercions_option_name(), true);
|
2014-09-03 16:34:13 +00:00
|
|
|
ios.update_options(os) << m_expr << endl << "--" << endl << m_type << endl;
|
2014-08-17 15:28:02 +00:00
|
|
|
ios << "-- ACK" << endl;
|
|
|
|
}
|
2014-09-14 19:01:14 +00:00
|
|
|
|
|
|
|
virtual info_data_cell * instantiate(substitution & s) const {
|
|
|
|
expr e = s.instantiate(m_expr);
|
|
|
|
expr t = s.instantiate(m_type);
|
|
|
|
return is_eqp(e, m_expr) && is_eqp(t, m_type) ? nullptr : new coercion_info_data(get_column(), e, t);
|
|
|
|
}
|
2014-08-17 15:28:02 +00:00
|
|
|
};
|
|
|
|
|
2014-08-17 22:06:46 +00:00
|
|
|
class symbol_info_data : public info_data_cell {
|
|
|
|
name m_symbol;
|
|
|
|
public:
|
|
|
|
symbol_info_data(unsigned c, name const & s):info_data_cell(c), m_symbol(s) {}
|
2014-08-26 21:23:12 +00:00
|
|
|
|
|
|
|
virtual info_kind kind() const { return info_kind::Symbol; }
|
|
|
|
|
2014-08-17 22:06:46 +00:00
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const {
|
|
|
|
ios << "-- SYMBOL|" << line << "|" << get_column() << "\n";
|
|
|
|
ios << m_symbol << "\n";
|
|
|
|
ios << "-- ACK" << endl;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class identifier_info_data : public info_data_cell {
|
|
|
|
name m_full_id;
|
|
|
|
public:
|
|
|
|
identifier_info_data(unsigned c, name const & full_id):info_data_cell(c), m_full_id(full_id) {}
|
2014-08-26 21:23:12 +00:00
|
|
|
|
|
|
|
virtual info_kind kind() const { return info_kind::Identifier; }
|
|
|
|
|
2014-08-17 22:06:46 +00:00
|
|
|
virtual void display(io_state_stream const & ios, unsigned line) const {
|
|
|
|
ios << "-- IDENTIFIER|" << line << "|" << get_column() << "\n";
|
|
|
|
ios << m_full_id << "\n";
|
|
|
|
ios << "-- ACK" << endl;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
info_data mk_type_info(unsigned c, expr const & e) { return info_data(new type_info_data(c, e)); }
|
2014-09-03 18:52:35 +00:00
|
|
|
info_data mk_extra_type_info(unsigned c, expr const & e, expr const & t) { return info_data(new extra_type_info_data(c, e, t)); }
|
2014-08-17 19:14:42 +00:00
|
|
|
info_data mk_synth_info(unsigned c, expr const & e) { return info_data(new synth_info_data(c, e)); }
|
|
|
|
info_data mk_overload_info(unsigned c, expr const & e) { return info_data(new overload_info_data(c, e)); }
|
2014-09-10 00:44:19 +00:00
|
|
|
info_data mk_overload_notation_info(unsigned c, list<expr> const & a) { return info_data(new overload_notation_info_data(c, a)); }
|
2014-09-03 16:34:13 +00:00
|
|
|
info_data mk_coercion_info(unsigned c, expr const & e, expr const & t) { return info_data(new coercion_info_data(c, e, t)); }
|
2014-08-17 22:06:46 +00:00
|
|
|
info_data mk_symbol_info(unsigned c, name const & s) { return info_data(new symbol_info_data(c, s)); }
|
|
|
|
info_data mk_identifier_info(unsigned c, name const & full_id) { return info_data(new identifier_info_data(c, full_id)); }
|
2014-08-17 15:28:02 +00:00
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
struct info_data_cmp {
|
|
|
|
int operator()(info_data const & i1, info_data const & i2) const { return i1.compare(i2); }
|
|
|
|
};
|
2014-08-06 22:25:28 +00:00
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
struct info_manager::imp {
|
|
|
|
typedef rb_tree<info_data, info_data_cmp> info_data_set;
|
2014-08-27 01:06:37 +00:00
|
|
|
/** \brief Saved environment + options for a given line and iteration
|
|
|
|
Whenever "lean server" starts processing a file again, we bump the iteration.
|
|
|
|
*/
|
|
|
|
struct env_info {
|
2014-09-18 23:51:59 +00:00
|
|
|
unsigned m_line;
|
|
|
|
mutable unsigned m_iteration;
|
|
|
|
environment m_env;
|
|
|
|
options m_options;
|
2014-08-27 01:06:37 +00:00
|
|
|
env_info():m_line(0), m_iteration(0) {}
|
|
|
|
env_info(unsigned l, unsigned i, environment const & env, options const & o):
|
|
|
|
m_line(l), m_iteration(i), m_env(env), m_options(o) {}
|
|
|
|
friend bool operator<(env_info const & i1, env_info const & i2) { return i1.m_line < i2.m_line; }
|
|
|
|
};
|
2014-08-17 19:14:42 +00:00
|
|
|
mutex m_mutex;
|
2014-08-27 21:53:16 +00:00
|
|
|
bool m_block_new_info;
|
2014-08-17 19:14:42 +00:00
|
|
|
std::vector<info_data_set> m_line_data;
|
|
|
|
std::vector<bool> m_line_valid;
|
2014-08-27 01:06:37 +00:00
|
|
|
std::set<env_info> m_env_info;
|
|
|
|
unsigned m_iteration; // current interation
|
|
|
|
unsigned m_processed_upto;
|
2014-08-06 22:25:28 +00:00
|
|
|
|
2014-08-27 21:53:16 +00:00
|
|
|
imp():m_block_new_info(false), m_iteration(0), m_processed_upto(0) {}
|
2014-08-27 01:06:37 +00:00
|
|
|
|
2014-08-27 21:53:16 +00:00
|
|
|
void block_new_info(bool f) {
|
2014-08-27 01:06:37 +00:00
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
m_block_new_info = f;
|
2014-08-27 01:06:37 +00:00
|
|
|
}
|
2014-08-06 22:25:28 +00:00
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
void synch_line(unsigned l) {
|
|
|
|
lean_assert(l > 0);
|
|
|
|
if (l >= m_line_data.size()) {
|
|
|
|
m_line_data.resize(l+1);
|
2014-08-30 01:12:22 +00:00
|
|
|
m_line_valid.resize(l+1, false);
|
2014-08-06 22:25:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-27 01:06:37 +00:00
|
|
|
void save_environment_options(unsigned l, environment const & env, options const & o) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
|
|
|
// erase all entries in m_env_info such that e.m_line <= l and e.m_iteration < m_iteration
|
|
|
|
auto it = m_env_info.begin();
|
|
|
|
auto end = m_env_info.end();
|
|
|
|
while (it != end) {
|
2014-09-15 17:25:07 +00:00
|
|
|
if (it->m_line > l) {
|
2014-08-27 01:06:37 +00:00
|
|
|
break;
|
2014-09-15 17:25:07 +00:00
|
|
|
} else if (it->m_line <= l && it->m_iteration < m_iteration) {
|
|
|
|
m_env_info.erase(it++);
|
|
|
|
} else {
|
2014-08-27 01:06:37 +00:00
|
|
|
++it;
|
2014-09-15 17:25:07 +00:00
|
|
|
}
|
2014-08-27 01:06:37 +00:00
|
|
|
}
|
|
|
|
m_env_info.insert(env_info(l, m_iteration, env, o));
|
|
|
|
}
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
void add_type_info(unsigned l, unsigned c, expr const & e) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-17 19:14:42 +00:00
|
|
|
synch_line(l);
|
|
|
|
m_line_data[l].insert(mk_type_info(c, e));
|
|
|
|
}
|
2014-08-06 22:25:28 +00:00
|
|
|
|
2014-09-03 18:52:35 +00:00
|
|
|
void add_extra_type_info(unsigned l, unsigned c, expr const & e, expr const & t) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
if (m_block_new_info)
|
|
|
|
return;
|
|
|
|
synch_line(l);
|
|
|
|
m_line_data[l].insert(mk_extra_type_info(c, e, t));
|
|
|
|
}
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
void add_synth_info(unsigned l, unsigned c, expr const & e) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-17 19:14:42 +00:00
|
|
|
synch_line(l);
|
|
|
|
m_line_data[l].insert(mk_synth_info(c, e));
|
2014-08-06 22:25:28 +00:00
|
|
|
}
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
void add_overload_info(unsigned l, unsigned c, expr const & e) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-17 19:14:42 +00:00
|
|
|
synch_line(l);
|
|
|
|
m_line_data[l].insert(mk_overload_info(c, e));
|
|
|
|
}
|
|
|
|
|
2014-09-10 00:44:19 +00:00
|
|
|
void add_overload_notation_info(unsigned l, unsigned c, list<expr> const & a) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
if (m_block_new_info)
|
|
|
|
return;
|
|
|
|
synch_line(l);
|
|
|
|
m_line_data[l].insert(mk_overload_notation_info(c, a));
|
|
|
|
}
|
|
|
|
|
2014-09-03 16:34:13 +00:00
|
|
|
void add_coercion_info(unsigned l, unsigned c, expr const & e, expr const & t) {
|
2014-08-17 19:14:42 +00:00
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-17 19:14:42 +00:00
|
|
|
synch_line(l);
|
2014-09-03 16:34:13 +00:00
|
|
|
m_line_data[l].insert(mk_coercion_info(c, e, t));
|
2014-08-17 19:14:42 +00:00
|
|
|
}
|
|
|
|
|
2014-09-03 01:39:06 +00:00
|
|
|
void erase_coercion_info(unsigned l, unsigned c) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
if (m_block_new_info)
|
|
|
|
return;
|
|
|
|
synch_line(l);
|
2014-09-03 16:34:13 +00:00
|
|
|
m_line_data[l].erase(mk_coercion_info(c, expr(), expr()));
|
2014-09-03 01:39:06 +00:00
|
|
|
}
|
|
|
|
|
2014-08-17 22:06:46 +00:00
|
|
|
void add_symbol_info(unsigned l, unsigned c, name const & s) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-17 22:06:46 +00:00
|
|
|
synch_line(l);
|
|
|
|
m_line_data[l].insert(mk_symbol_info(c, s));
|
|
|
|
}
|
|
|
|
|
|
|
|
void add_identifier_info(unsigned l, unsigned c, name const & full_id) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-17 22:06:46 +00:00
|
|
|
synch_line(l);
|
|
|
|
m_line_data[l].insert(mk_identifier_info(c, full_id));
|
|
|
|
}
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
static info_data_set instantiate(info_data_set const & s, substitution & subst) {
|
|
|
|
info_data_set r;
|
|
|
|
s.for_each([&](info_data const & d) {
|
|
|
|
r.insert(d.instantiate(subst));
|
|
|
|
});
|
|
|
|
return r;
|
|
|
|
}
|
2014-08-07 04:56:57 +00:00
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
void instantiate(substitution const & s) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-17 19:14:42 +00:00
|
|
|
substitution tmp_s = s;
|
|
|
|
unsigned sz = m_line_data.size();
|
|
|
|
for (unsigned i = 0; i < sz; i++) {
|
|
|
|
m_line_data[i] = instantiate(m_line_data[i], tmp_s);
|
2014-08-14 17:53:22 +00:00
|
|
|
}
|
|
|
|
}
|
2014-08-14 17:37:24 +00:00
|
|
|
|
2014-08-27 01:06:37 +00:00
|
|
|
void merge(info_manager::imp const & m, bool overwrite) {
|
2014-08-17 19:14:42 +00:00
|
|
|
if (m.m_line_data.empty())
|
|
|
|
return;
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-17 19:14:42 +00:00
|
|
|
unsigned sz = m.m_line_data.size();
|
|
|
|
for (unsigned i = 1; i < sz; i++) {
|
2014-08-30 17:24:51 +00:00
|
|
|
info_data_set s = m.m_line_data[i];
|
|
|
|
if (s.empty())
|
|
|
|
continue;
|
|
|
|
synch_line(i);
|
|
|
|
if (!overwrite && m_line_valid[i])
|
|
|
|
continue;
|
2014-08-17 19:14:42 +00:00
|
|
|
s.for_each([&](info_data const & d) {
|
2014-09-05 08:12:08 +00:00
|
|
|
if (overwrite || !m_line_data[i].contains(d))
|
2014-08-27 01:06:37 +00:00
|
|
|
m_line_data[i].insert(d);
|
2014-08-17 19:14:42 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
2014-08-06 22:25:28 +00:00
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
void insert_line(unsigned l) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-30 01:12:22 +00:00
|
|
|
lean_assert(m_line_data.size() == m_line_valid.size());
|
2014-08-17 19:14:42 +00:00
|
|
|
synch_line(l);
|
2014-08-27 01:06:37 +00:00
|
|
|
if (m_processed_upto > l - 1)
|
|
|
|
m_processed_upto = l - 1;
|
2014-08-17 19:14:42 +00:00
|
|
|
m_line_data.push_back(info_data_set());
|
2014-08-30 01:12:22 +00:00
|
|
|
m_line_valid.push_back(false);
|
2014-08-17 19:14:42 +00:00
|
|
|
unsigned i = m_line_data.size();
|
|
|
|
while (i > l) {
|
|
|
|
--i;
|
|
|
|
m_line_data[i] = m_line_data[i-1];
|
|
|
|
m_line_valid[i] = m_line_valid[i-1];
|
|
|
|
}
|
|
|
|
m_line_valid[l] = false;
|
2014-08-06 22:25:28 +00:00
|
|
|
}
|
2014-08-17 19:14:42 +00:00
|
|
|
|
|
|
|
void remove_line(unsigned l) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-30 01:12:22 +00:00
|
|
|
lean_assert(m_line_data.size() == m_line_valid.size());
|
2014-08-17 19:14:42 +00:00
|
|
|
lean_assert(l > 0);
|
|
|
|
if (l >= m_line_data.size())
|
|
|
|
return;
|
|
|
|
lean_assert(!m_line_data.empty());
|
|
|
|
for (unsigned i = l; i < m_line_data.size() - 1; i++) {
|
|
|
|
m_line_data[i] = m_line_data[i+1];
|
|
|
|
m_line_valid[i] = m_line_valid[i+1];
|
|
|
|
}
|
|
|
|
m_line_data.pop_back();
|
2014-08-30 01:12:22 +00:00
|
|
|
m_line_valid.pop_back();
|
2014-08-27 01:06:37 +00:00
|
|
|
if (m_processed_upto > l - 1)
|
|
|
|
m_processed_upto = l - 1;
|
2014-08-17 19:14:42 +00:00
|
|
|
}
|
|
|
|
|
2014-08-28 04:09:52 +00:00
|
|
|
void invalidate_line_col_core(unsigned l, optional<unsigned> const & c) {
|
2014-08-17 19:14:42 +00:00
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-30 01:12:22 +00:00
|
|
|
lean_assert(m_line_data.size() == m_line_valid.size());
|
2014-08-17 19:14:42 +00:00
|
|
|
synch_line(l);
|
2014-08-27 01:06:37 +00:00
|
|
|
if (m_processed_upto > l - 1)
|
|
|
|
m_processed_upto = l - 1;
|
2014-08-28 04:09:52 +00:00
|
|
|
if (!c) {
|
|
|
|
m_line_data[l] = info_data_set();
|
|
|
|
} else {
|
|
|
|
info_data_set new_set;
|
|
|
|
m_line_data[l].for_each([&](info_data const & d) {
|
|
|
|
if (d.get_column() < *c)
|
|
|
|
new_set.insert(d);
|
|
|
|
});
|
|
|
|
m_line_data[l] = new_set;
|
|
|
|
}
|
2014-08-17 19:14:42 +00:00
|
|
|
m_line_valid[l] = false;
|
|
|
|
}
|
|
|
|
|
2014-08-28 04:09:52 +00:00
|
|
|
void invalidate_line(unsigned l) {
|
|
|
|
invalidate_line_col_core(l, optional<unsigned>());
|
|
|
|
}
|
|
|
|
|
|
|
|
void invalidate_line_col(unsigned l, unsigned c) {
|
|
|
|
invalidate_line_col_core(l, optional<unsigned>(c));
|
|
|
|
}
|
|
|
|
|
2014-08-30 01:12:22 +00:00
|
|
|
void set_processed_upto(unsigned l) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-30 17:24:51 +00:00
|
|
|
synch_line(l);
|
2014-08-30 01:12:22 +00:00
|
|
|
m_processed_upto = l;
|
|
|
|
}
|
|
|
|
|
2014-09-18 23:51:59 +00:00
|
|
|
void start_from(unsigned l) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
m_iteration++;
|
|
|
|
synch_line(l);
|
|
|
|
m_processed_upto = l;
|
|
|
|
for (auto it = m_env_info.begin(); it != m_env_info.end(); ++it) {
|
|
|
|
if (it->m_line < l)
|
|
|
|
it->m_iteration = m_iteration;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
m_block_new_info = false;
|
|
|
|
}
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
void commit_upto(unsigned l, bool valid) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-27 21:53:16 +00:00
|
|
|
if (m_block_new_info)
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
2014-08-30 17:24:51 +00:00
|
|
|
synch_line(l);
|
2014-08-27 01:06:37 +00:00
|
|
|
for (unsigned i = m_processed_upto; i < l && i < m_line_valid.size(); i++)
|
2014-08-17 19:14:42 +00:00
|
|
|
m_line_valid[i] = valid;
|
2014-08-27 01:06:37 +00:00
|
|
|
m_processed_upto = l;
|
2014-08-17 19:14:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool is_invalidated(unsigned l) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-08-30 01:12:22 +00:00
|
|
|
lean_assert(m_line_data.size() == m_line_valid.size());
|
2014-08-17 19:14:42 +00:00
|
|
|
if (l >= m_line_valid.size())
|
2014-08-30 01:12:22 +00:00
|
|
|
return true;
|
2014-08-17 19:14:42 +00:00
|
|
|
return !m_line_valid[l];
|
|
|
|
}
|
|
|
|
|
2014-09-04 21:02:53 +00:00
|
|
|
void display_core(environment const & env, options const & o, io_state const & ios, unsigned line,
|
|
|
|
optional<unsigned> const & col) {
|
2014-08-27 01:06:37 +00:00
|
|
|
io_state_stream out = regular(env, ios).update_options(o);
|
|
|
|
m_line_data[line].for_each([&](info_data const & d) {
|
2014-09-04 21:02:53 +00:00
|
|
|
if ((!col && d.is_cheap()) || (col && d.get_column() == *col))
|
|
|
|
d.display(out, line);
|
2014-08-27 01:06:37 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2014-09-04 21:02:53 +00:00
|
|
|
void display(environment const & env, io_state const & ios, unsigned line, optional<unsigned> const & col) {
|
2014-08-17 19:14:42 +00:00
|
|
|
lock_guard<mutex> lc(m_mutex);
|
2014-09-03 02:04:01 +00:00
|
|
|
if (line >= m_line_data.size() || m_line_data[line].empty()) {
|
2014-08-30 17:24:51 +00:00
|
|
|
// do nothing
|
|
|
|
} else if (m_env_info.empty()) {
|
2014-09-04 21:02:53 +00:00
|
|
|
display_core(env, ios.get_options(), ios, line, col);
|
2014-08-30 17:24:51 +00:00
|
|
|
} else {
|
|
|
|
auto it = m_env_info.begin();
|
|
|
|
auto end = m_env_info.end();
|
2014-08-27 01:06:37 +00:00
|
|
|
lean_assert(it != end);
|
2014-08-30 17:24:51 +00:00
|
|
|
if (it->m_line > line) {
|
2014-09-04 21:02:53 +00:00
|
|
|
display_core(env, ios.get_options(), ios, line, col);
|
2014-08-27 01:06:37 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-08-30 17:24:51 +00:00
|
|
|
while (true) {
|
|
|
|
lean_assert(it->m_line <= line);
|
|
|
|
lean_assert(it != end);
|
|
|
|
auto next = it;
|
|
|
|
++next;
|
|
|
|
if (next == end || next->m_line > line) {
|
2014-09-04 21:02:53 +00:00
|
|
|
display_core(it->m_env, join(it->m_options, ios.get_options()), ios, line, col);
|
2014-08-30 17:24:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
it = next;
|
|
|
|
}
|
2014-08-27 01:06:37 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
optional<pair<environment, options>> get_final_env_opts() {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
if (m_env_info.empty()) {
|
|
|
|
return optional<pair<environment, options>>();
|
|
|
|
} else {
|
|
|
|
auto it = m_env_info.end();
|
|
|
|
--it;
|
|
|
|
return optional<pair<environment, options>>(mk_pair(it->m_env, it->m_options));
|
|
|
|
}
|
2014-08-17 19:14:42 +00:00
|
|
|
}
|
|
|
|
|
2014-09-02 19:57:20 +00:00
|
|
|
optional<pair<environment, options>> get_closest_env_opts(unsigned linenum) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
auto it = m_env_info.begin();
|
|
|
|
if (it == m_env_info.end())
|
|
|
|
return optional<pair<environment, options>>();
|
|
|
|
if (it->m_line > linenum)
|
|
|
|
return optional<pair<environment, options>>(it->m_env, it->m_options);
|
|
|
|
while (true) {
|
|
|
|
lean_assert(it != m_env_info.end() && it->m_line <= linenum);
|
|
|
|
auto next = it;
|
|
|
|
next++;
|
2014-09-29 23:39:43 +00:00
|
|
|
if (next == m_env_info.end())
|
|
|
|
return optional<pair<environment, options>>(mk_pair(it->m_env, it->m_options));
|
|
|
|
if (next->m_line > linenum)
|
2014-09-19 00:03:59 +00:00
|
|
|
return optional<pair<environment, options>>(mk_pair(next->m_env, next->m_options));
|
2014-09-02 19:57:20 +00:00
|
|
|
it = next;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-03 08:35:04 +00:00
|
|
|
optional<expr> get_type_at(unsigned line, unsigned col) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
if (line >= m_line_data.size())
|
|
|
|
return none_expr();
|
|
|
|
if (auto it = m_line_data[line].find(mk_type_info(col, expr())))
|
|
|
|
return some_expr(static_cast<type_info_data const *>(it->raw())->get_type());
|
|
|
|
else
|
|
|
|
return none_expr();
|
|
|
|
}
|
|
|
|
|
|
|
|
optional<expr> get_meta_at(unsigned line, unsigned col) {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
if (line >= m_line_data.size())
|
|
|
|
return none_expr();
|
|
|
|
if (auto it = m_line_data[line].find(mk_synth_info(col, expr())))
|
|
|
|
return some_expr(static_cast<synth_info_data const *>(it->raw())->get_expr());
|
|
|
|
else
|
|
|
|
return none_expr();
|
|
|
|
}
|
|
|
|
|
2014-09-02 19:57:20 +00:00
|
|
|
unsigned get_processed_upto() {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
return m_processed_upto;
|
|
|
|
}
|
|
|
|
|
2014-08-17 19:14:42 +00:00
|
|
|
void clear() {
|
|
|
|
lock_guard<mutex> lc(m_mutex);
|
|
|
|
m_line_data.clear();
|
2014-08-27 01:06:37 +00:00
|
|
|
m_line_valid.clear();
|
2014-09-17 01:38:23 +00:00
|
|
|
m_env_info.clear();
|
|
|
|
m_iteration = 0;
|
|
|
|
m_processed_upto = 0;
|
2014-08-17 19:14:42 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
info_manager::info_manager():m_ptr(new imp()) {}
|
|
|
|
info_manager::~info_manager() {}
|
|
|
|
void info_manager::add_type_info(unsigned l, unsigned c, expr const & e) { m_ptr->add_type_info(l, c, e); }
|
2014-09-03 18:52:35 +00:00
|
|
|
void info_manager::add_extra_type_info(unsigned l, unsigned c, expr const & e, expr const & t) { m_ptr->add_extra_type_info(l, c, e, t); }
|
2014-08-17 19:14:42 +00:00
|
|
|
void info_manager::add_synth_info(unsigned l, unsigned c, expr const & e) { m_ptr->add_synth_info(l, c, e); }
|
|
|
|
void info_manager::add_overload_info(unsigned l, unsigned c, expr const & e) { m_ptr->add_overload_info(l, c, e); }
|
2014-09-10 00:44:19 +00:00
|
|
|
void info_manager::add_overload_notation_info(unsigned l, unsigned c, list<expr> const & a) { m_ptr->add_overload_notation_info(l, c, a); }
|
2014-09-03 16:34:13 +00:00
|
|
|
void info_manager::add_coercion_info(unsigned l, unsigned c, expr const & e, expr const & t) { m_ptr->add_coercion_info(l, c, e, t); }
|
2014-09-03 01:39:06 +00:00
|
|
|
void info_manager::erase_coercion_info(unsigned l, unsigned c) { m_ptr->erase_coercion_info(l, c); }
|
2014-08-17 22:06:46 +00:00
|
|
|
void info_manager::add_symbol_info(unsigned l, unsigned c, name const & s) { m_ptr->add_symbol_info(l, c, s); }
|
|
|
|
void info_manager::add_identifier_info(unsigned l, unsigned c, name const & full_id) {
|
|
|
|
m_ptr->add_identifier_info(l, c, full_id);
|
|
|
|
}
|
2014-08-17 19:14:42 +00:00
|
|
|
void info_manager::instantiate(substitution const & s) { m_ptr->instantiate(s); }
|
2014-08-27 01:06:37 +00:00
|
|
|
void info_manager::merge(info_manager const & m, bool overwrite) { m_ptr->merge(*m.m_ptr, overwrite); }
|
2014-08-17 19:14:42 +00:00
|
|
|
void info_manager::insert_line(unsigned l) { m_ptr->insert_line(l); }
|
|
|
|
void info_manager::remove_line(unsigned l) { m_ptr->remove_line(l); }
|
|
|
|
void info_manager::invalidate_line(unsigned l) { m_ptr->invalidate_line(l); }
|
2014-08-28 04:09:52 +00:00
|
|
|
void info_manager::invalidate_line_col(unsigned l, unsigned c) { m_ptr->invalidate_line_col(l, c); }
|
2014-08-17 19:14:42 +00:00
|
|
|
void info_manager::commit_upto(unsigned l, bool valid) { m_ptr->commit_upto(l, valid); }
|
2014-08-30 01:12:22 +00:00
|
|
|
void info_manager::set_processed_upto(unsigned l) { m_ptr->set_processed_upto(l); }
|
2014-08-17 19:14:42 +00:00
|
|
|
bool info_manager::is_invalidated(unsigned l) const { return m_ptr->is_invalidated(l); }
|
2014-08-27 01:06:37 +00:00
|
|
|
void info_manager::save_environment_options(unsigned l, environment const & env, options const & o) {
|
|
|
|
m_ptr->save_environment_options(l, env, o);
|
|
|
|
}
|
2014-08-17 19:14:42 +00:00
|
|
|
void info_manager::clear() { m_ptr->clear(); }
|
2014-09-03 08:35:04 +00:00
|
|
|
optional<pair<environment, options>> info_manager::get_final_env_opts() const { return m_ptr->get_final_env_opts(); }
|
|
|
|
optional<pair<environment, options>> info_manager::get_closest_env_opts(unsigned linenum) const { return m_ptr->get_closest_env_opts(linenum); }
|
2014-09-04 21:02:53 +00:00
|
|
|
void info_manager::display(environment const & env, io_state const & ios, unsigned line, optional<unsigned> const & col) const {
|
|
|
|
m_ptr->display(env, ios, line, col);
|
|
|
|
}
|
2014-09-03 08:35:04 +00:00
|
|
|
unsigned info_manager::get_processed_upto() const { return m_ptr->m_processed_upto; }
|
|
|
|
optional<expr> info_manager::get_type_at(unsigned line, unsigned col) const { return m_ptr->get_type_at(line, col); }
|
|
|
|
optional<expr> info_manager::get_meta_at(unsigned line, unsigned col) const { return m_ptr->get_meta_at(line, col); }
|
2014-09-18 23:51:59 +00:00
|
|
|
void info_manager::block_new_info() { m_ptr->block_new_info(true); }
|
|
|
|
void info_manager::start_from(unsigned l) { m_ptr->start_from(l); }
|
2014-08-06 22:25:28 +00:00
|
|
|
}
|