refactor(frontends/lean): use extension objects to store lean default frontend data in the environment
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
80e23f98c7
commit
2141ee12f4
6 changed files with 192 additions and 222 deletions
|
@ -25,8 +25,10 @@ Author: Leonardo de Moura
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
static std::vector<bool> g_empty_vector;
|
static std::vector<bool> g_empty_vector;
|
||||||
/** \brief Implementation of the Lean frontend */
|
/**
|
||||||
struct frontend::imp {
|
\brief Environment extension object for the Lean default frontend.
|
||||||
|
*/
|
||||||
|
struct lean_extension : public environment::extension {
|
||||||
typedef std::pair<std::vector<bool>, name> implicit_info;
|
typedef std::pair<std::vector<bool>, name> implicit_info;
|
||||||
// Remark: only named objects are stored in the dictionary.
|
// Remark: only named objects are stored in the dictionary.
|
||||||
typedef std::unordered_map<name, operator_info, name_hash, name_eq> operator_table;
|
typedef std::unordered_map<name, operator_info, name_hash, name_eq> operator_table;
|
||||||
|
@ -36,9 +38,6 @@ struct frontend::imp {
|
||||||
typedef std::unordered_map<expr, list<expr_pair>, expr_hash, std::equal_to<expr>> expr_to_coercions;
|
typedef std::unordered_map<expr, list<expr_pair>, expr_hash, std::equal_to<expr>> expr_to_coercions;
|
||||||
typedef std::unordered_set<expr, expr_hash, std::equal_to<expr>> coercion_set;
|
typedef std::unordered_set<expr, expr_hash, std::equal_to<expr>> coercion_set;
|
||||||
|
|
||||||
std::atomic<unsigned> m_num_children;
|
|
||||||
std::shared_ptr<imp> m_parent;
|
|
||||||
environment m_env;
|
|
||||||
operator_table m_nud; // nud table for Pratt's parser
|
operator_table m_nud; // nud table for Pratt's parser
|
||||||
operator_table m_led; // led table for Pratt's parser
|
operator_table m_led; // led table for Pratt's parser
|
||||||
expr_to_operators m_expr_to_operators; // map denotations to operators (this is used for pretty printing)
|
expr_to_operators m_expr_to_operators; // map denotations to operators (this is used for pretty printing)
|
||||||
|
@ -46,21 +45,19 @@ struct frontend::imp {
|
||||||
coercion_map m_coercion_map; // mapping from (given_type, expected_type) -> coercion
|
coercion_map m_coercion_map; // mapping from (given_type, expected_type) -> coercion
|
||||||
coercion_set m_coercion_set; // Set of coercions
|
coercion_set m_coercion_set; // Set of coercions
|
||||||
expr_to_coercions m_type_coercions; // mapping type -> list (to-type, function)
|
expr_to_coercions m_type_coercions; // mapping type -> list (to-type, function)
|
||||||
state m_state;
|
|
||||||
|
|
||||||
bool has_children() const { return m_num_children > 0; }
|
lean_extension const * get_parent() const {
|
||||||
void inc_children() { m_num_children++; }
|
return environment::extension::get_parent<lean_extension>();
|
||||||
void dec_children() { m_num_children--; }
|
}
|
||||||
|
|
||||||
bool has_parent() const { return m_parent != nullptr; }
|
|
||||||
|
|
||||||
/** \brief Return the nud operator for the given symbol. */
|
/** \brief Return the nud operator for the given symbol. */
|
||||||
operator_info find_nud(name const & n) const {
|
operator_info find_nud(name const & n) const {
|
||||||
auto it = m_nud.find(n);
|
auto it = m_nud.find(n);
|
||||||
if (it != m_nud.end())
|
if (it != m_nud.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
else if (has_parent())
|
lean_extension const * parent = get_parent();
|
||||||
return m_parent->find_nud(n);
|
if (parent)
|
||||||
|
return parent->find_nud(n);
|
||||||
else
|
else
|
||||||
return operator_info();
|
return operator_info();
|
||||||
}
|
}
|
||||||
|
@ -70,8 +67,9 @@ struct frontend::imp {
|
||||||
auto it = m_led.find(n);
|
auto it = m_led.find(n);
|
||||||
if (it != m_led.end())
|
if (it != m_led.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
else if (has_parent())
|
lean_extension const * parent = get_parent();
|
||||||
return m_parent->find_led(n);
|
if (parent)
|
||||||
|
return parent->find_led(n);
|
||||||
else
|
else
|
||||||
return operator_info();
|
return operator_info();
|
||||||
}
|
}
|
||||||
|
@ -110,17 +108,18 @@ struct frontend::imp {
|
||||||
return op;
|
return op;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
lean_extension const * parent = get_parent();
|
||||||
if (has_parent())
|
if (parent)
|
||||||
return m_parent->find_op_for(e, unicode);
|
return parent->find_op_for(e, unicode);
|
||||||
else
|
else
|
||||||
return operator_info();
|
return operator_info();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** \brief Remove all internal denotations that are associated with the given operator symbol (aka notation) */
|
/** \brief Remove all internal denotations that are associated with the given operator symbol (aka notation) */
|
||||||
void remove_bindings(operator_info const & op) {
|
void remove_bindings(operator_info const & op) {
|
||||||
|
lean_extension const * parent = get_parent();
|
||||||
for (expr const & d : op.get_denotations()) {
|
for (expr const & d : op.get_denotations()) {
|
||||||
if (has_parent() && m_parent->find_op_for(d, true)) {
|
if (parent && parent->find_op_for(d, true)) {
|
||||||
// parent has an association for d... we must hide it.
|
// parent has an association for d... we must hide it.
|
||||||
insert(m_expr_to_operators, d, list<operator_info>(operator_info()));
|
insert(m_expr_to_operators, d, list<operator_info>(operator_info()));
|
||||||
} else {
|
} else {
|
||||||
|
@ -129,6 +128,7 @@ struct frontend::imp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/** \brief Add a new entry d -> op in the mapping m_expr_to_operators */
|
/** \brief Add a new entry d -> op in the mapping m_expr_to_operators */
|
||||||
void insert_expr_to_operator_entry(expr const & d, operator_info const & op) {
|
void insert_expr_to_operator_entry(expr const & d, operator_info const & op) {
|
||||||
list<operator_info> & l = m_expr_to_operators[d];
|
list<operator_info> & l = m_expr_to_operators[d];
|
||||||
|
@ -181,7 +181,7 @@ struct frontend::imp {
|
||||||
2) It is a real conflict, and report the issue in the
|
2) It is a real conflict, and report the issue in the
|
||||||
diagnostic channel, and override the existing operator (aka notation).
|
diagnostic channel, and override the existing operator (aka notation).
|
||||||
*/
|
*/
|
||||||
void add_op(operator_info new_op, expr const & d, bool led) {
|
void add_op(operator_info new_op, expr const & d, bool led, environment & env, state & st) {
|
||||||
name const & opn = new_op.get_op_name();
|
name const & opn = new_op.get_op_name();
|
||||||
operator_info old_op = find_op(opn, led);
|
operator_info old_op = find_op(opn, led);
|
||||||
if (!old_op) {
|
if (!old_op) {
|
||||||
|
@ -199,31 +199,21 @@ struct frontend::imp {
|
||||||
register_new_op(new_op, d, led);
|
register_new_op(new_op, d, led);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
diagnostic(m_state) << "The denotation(s) for the existing notation:\n " << old_op
|
diagnostic(st) << "The denotation(s) for the existing notation:\n " << old_op
|
||||||
<< "\nhave been replaced with the new denotation:\n " << d
|
<< "\nhave been replaced with the new denotation:\n " << d
|
||||||
<< "\nbecause they conflict on how implicit arguments are used.\n";
|
<< "\nbecause they conflict on how implicit arguments are used.\n";
|
||||||
remove_bindings(old_op);
|
remove_bindings(old_op);
|
||||||
register_new_op(new_op, d, led);
|
register_new_op(new_op, d, led);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
diagnostic(m_state) << "Notation has been redefined, the existing notation:\n " << old_op
|
diagnostic(st) << "Notation has been redefined, the existing notation:\n " << old_op
|
||||||
<< "\nhas been replaced with:\n " << new_op << "\nbecause they conflict with each other.\n";
|
<< "\nhas been replaced with:\n " << new_op << "\nbecause they conflict with each other.\n";
|
||||||
remove_bindings(old_op);
|
remove_bindings(old_op);
|
||||||
register_new_op(new_op, d, led);
|
register_new_op(new_op, d, led);
|
||||||
}
|
}
|
||||||
m_env.add_neutral_object(new notation_declaration(new_op, d));
|
env.add_neutral_object(new notation_declaration(new_op, d));
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_infix(name const & opn, unsigned p, expr const & d) { add_op(infix(opn, p), d, true); }
|
|
||||||
void add_infixl(name const & opn, unsigned p, expr const & d) { add_op(infixl(opn, p), d, true); }
|
|
||||||
void add_infixr(name const & opn, unsigned p, expr const & d) { add_op(infixr(opn, p), d, true); }
|
|
||||||
void add_prefix(name const & opn, unsigned p, expr const & d) { add_op(prefix(opn, p), d, false); }
|
|
||||||
void add_postfix(name const & opn, unsigned p, expr const & d) { add_op(postfix(opn, p), d, true); }
|
|
||||||
void add_mixfixl(unsigned sz, name const * opns, unsigned p, expr const & d) { add_op(mixfixl(sz, opns, p), d, false); }
|
|
||||||
void add_mixfixr(unsigned sz, name const * opns, unsigned p, expr const & d) { add_op(mixfixr(sz, opns, p), d, true); }
|
|
||||||
void add_mixfixc(unsigned sz, name const * opns, unsigned p, expr const & d) { add_op(mixfixc(sz, opns, p), d, false); }
|
|
||||||
void add_mixfixo(unsigned sz, name const * opns, unsigned p, expr const & d) { add_op(mixfixo(sz, opns, p), d, true); }
|
|
||||||
|
|
||||||
expr mk_explicit_definition_body(expr type, name const & n, unsigned i, unsigned sz) {
|
expr mk_explicit_definition_body(expr type, name const & n, unsigned i, unsigned sz) {
|
||||||
if (i == sz) {
|
if (i == sz) {
|
||||||
buffer<expr> args;
|
buffer<expr> args;
|
||||||
|
@ -237,16 +227,16 @@ struct frontend::imp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void mark_implicit_arguments(name const & n, unsigned sz, bool const * implicit) {
|
void mark_implicit_arguments(name const & n, unsigned sz, bool const * implicit, environment & env) {
|
||||||
if (has_children())
|
if (env.has_children())
|
||||||
throw exception(sstream() << "failed to mark implicit arguments, frontend object is read-only");
|
throw exception(sstream() << "failed to mark implicit arguments, frontend object is read-only");
|
||||||
object const & obj = m_env.get_object(n);
|
object const & obj = env.get_object(n);
|
||||||
if (obj.kind() != object_kind::Definition && obj.kind() != object_kind::Postulate && obj.kind() != object_kind::Builtin)
|
if (obj.kind() != object_kind::Definition && obj.kind() != object_kind::Postulate && obj.kind() != object_kind::Builtin)
|
||||||
throw exception(sstream() << "failed to mark implicit arguments, the object '" << n << "' is not a definition or postulate");
|
throw exception(sstream() << "failed to mark implicit arguments, the object '" << n << "' is not a definition or postulate");
|
||||||
if (has_implicit_arguments(n))
|
if (has_implicit_arguments(n))
|
||||||
throw exception(sstream() << "the object '" << n << "' already has implicit argument information associated with it");
|
throw exception(sstream() << "the object '" << n << "' already has implicit argument information associated with it");
|
||||||
name explicit_version(n, "explicit");
|
name explicit_version(n, "explicit");
|
||||||
if (m_env.find_object(explicit_version))
|
if (env.find_object(explicit_version))
|
||||||
throw exception(sstream() << "failed to mark implicit arguments for '" << n << "', the frontend already has an object named '" << explicit_version << "'");
|
throw exception(sstream() << "failed to mark implicit arguments for '" << n << "', the frontend already has an object named '" << explicit_version << "'");
|
||||||
expr const & type = obj.get_type();
|
expr const & type = obj.get_type();
|
||||||
unsigned num_args = 0;
|
unsigned num_args = 0;
|
||||||
|
@ -258,58 +248,58 @@ struct frontend::imp {
|
||||||
m_implicit_table[n] = mk_pair(v, explicit_version);
|
m_implicit_table[n] = mk_pair(v, explicit_version);
|
||||||
expr body = mk_explicit_definition_body(type, n, 0, sz);
|
expr body = mk_explicit_definition_body(type, n, 0, sz);
|
||||||
if (obj.is_axiom() || obj.is_theorem()) {
|
if (obj.is_axiom() || obj.is_theorem()) {
|
||||||
m_env.add_theorem(explicit_version, type, body);
|
env.add_theorem(explicit_version, type, body);
|
||||||
} else {
|
} else {
|
||||||
m_env.add_definition(explicit_version, type, body);
|
env.add_definition(explicit_version, type, body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool has_implicit_arguments(name const & n) {
|
bool has_implicit_arguments(name const & n) const {
|
||||||
if (m_implicit_table.find(n) != m_implicit_table.end()) {
|
if (m_implicit_table.find(n) != m_implicit_table.end())
|
||||||
return true;
|
return true;
|
||||||
} else if (has_parent()) {
|
lean_extension const * parent = get_parent();
|
||||||
return m_parent->has_implicit_arguments(n);
|
if (parent)
|
||||||
} else {
|
return parent->has_implicit_arguments(n);
|
||||||
|
else
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<bool> const & get_implicit_arguments(name const & n) {
|
std::vector<bool> const & get_implicit_arguments(name const & n) const {
|
||||||
auto it = m_implicit_table.find(n);
|
auto it = m_implicit_table.find(n);
|
||||||
if (it != m_implicit_table.end()) {
|
if (it != m_implicit_table.end())
|
||||||
return it->second.first;
|
return it->second.first;
|
||||||
} else if (has_parent()) {
|
lean_extension const * parent = get_parent();
|
||||||
return m_parent->get_implicit_arguments(n);
|
if (parent)
|
||||||
} else {
|
return parent->get_implicit_arguments(n);
|
||||||
|
else
|
||||||
return g_empty_vector;
|
return g_empty_vector;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<bool> const & get_implicit_arguments(expr const & n) {
|
std::vector<bool> const & get_implicit_arguments(expr const & n) const {
|
||||||
if (is_constant(n))
|
if (is_constant(n))
|
||||||
return get_implicit_arguments(const_name(n));
|
return get_implicit_arguments(const_name(n));
|
||||||
else
|
else
|
||||||
return g_empty_vector;
|
return g_empty_vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
name const & get_explicit_version(name const & n) {
|
name const & get_explicit_version(name const & n) const {
|
||||||
auto it = m_implicit_table.find(n);
|
auto it = m_implicit_table.find(n);
|
||||||
if (it != m_implicit_table.end()) {
|
if (it != m_implicit_table.end())
|
||||||
return it->second.second;
|
return it->second.second;
|
||||||
} else if (has_parent()) {
|
lean_extension const * parent = get_parent();
|
||||||
return m_parent->get_explicit_version(n);
|
if (parent)
|
||||||
} else {
|
return parent->get_explicit_version(n);
|
||||||
|
else
|
||||||
return name::anonymous();
|
return name::anonymous();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_explicit(name const & n) {
|
bool is_explicit(name const & n) const {
|
||||||
return !n.is_atomic() && get_explicit_version(n.get_prefix()) == n;
|
return !n.is_atomic() && get_explicit_version(n.get_prefix()) == n;
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_coercion(expr const & f) {
|
void add_coercion(expr const & f, environment & env) {
|
||||||
expr type = m_env.infer_type(f);
|
expr type = env.infer_type(f);
|
||||||
expr norm_type = m_env.normalize(type);
|
expr norm_type = env.normalize(type);
|
||||||
if (!is_arrow(norm_type))
|
if (!is_arrow(norm_type))
|
||||||
throw exception("invalid coercion declaration, a coercion must have an arrow type (i.e., a non-dependent functional type)");
|
throw exception("invalid coercion declaration, a coercion must have an arrow type (i.e., a non-dependent functional type)");
|
||||||
expr from = abst_domain(norm_type);
|
expr from = abst_domain(norm_type);
|
||||||
|
@ -322,16 +312,17 @@ struct frontend::imp {
|
||||||
m_coercion_set.insert(f);
|
m_coercion_set.insert(f);
|
||||||
list<expr_pair> l = get_coercions(from);
|
list<expr_pair> l = get_coercions(from);
|
||||||
insert(m_type_coercions, from, cons(expr_pair(to, f), l));
|
insert(m_type_coercions, from, cons(expr_pair(to, f), l));
|
||||||
m_env.add_neutral_object(new coercion_declaration(f));
|
env.add_neutral_object(new coercion_declaration(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
expr get_coercion(expr const & from_type, expr const & to_type) {
|
expr get_coercion(expr const & from_type, expr const & to_type) const {
|
||||||
expr_pair p(from_type, to_type);
|
expr_pair p(from_type, to_type);
|
||||||
auto it = m_coercion_map.find(p);
|
auto it = m_coercion_map.find(p);
|
||||||
if (it != m_coercion_map.end())
|
if (it != m_coercion_map.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
else if (has_parent())
|
lean_extension const * parent = get_parent();
|
||||||
return m_parent->get_coercion(from_type, to_type);
|
if (parent)
|
||||||
|
return parent->get_coercion(from_type, to_type);
|
||||||
else
|
else
|
||||||
return expr();
|
return expr();
|
||||||
}
|
}
|
||||||
|
@ -340,91 +331,81 @@ struct frontend::imp {
|
||||||
auto r = m_type_coercions.find(from_type);
|
auto r = m_type_coercions.find(from_type);
|
||||||
if (r != m_type_coercions.end())
|
if (r != m_type_coercions.end())
|
||||||
return r->second;
|
return r->second;
|
||||||
else if (has_parent())
|
lean_extension const * parent = get_parent();
|
||||||
return m_parent->get_coercions(from_type);
|
if (parent)
|
||||||
|
return parent->get_coercions(from_type);
|
||||||
else
|
else
|
||||||
return list<expr_pair>();
|
return list<expr_pair>();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_coercion(expr const & f) {
|
bool is_coercion(expr const & f) const {
|
||||||
return m_coercion_set.find(f) != m_coercion_set.end();
|
return m_coercion_set.find(f) != m_coercion_set.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_interrupt(bool flag) {
|
|
||||||
m_env.set_interrupt(flag);
|
|
||||||
m_state.set_interrupt(flag);
|
|
||||||
}
|
|
||||||
|
|
||||||
imp(frontend &):
|
|
||||||
m_num_children(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit imp(std::shared_ptr<imp> const & parent):
|
|
||||||
m_num_children(0),
|
|
||||||
m_parent(parent),
|
|
||||||
m_env(m_parent->m_env.mk_child()),
|
|
||||||
m_state(m_parent->m_state) {
|
|
||||||
m_parent->inc_children();
|
|
||||||
}
|
|
||||||
|
|
||||||
~imp() {
|
|
||||||
if (m_parent)
|
|
||||||
m_parent->dec_children();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
frontend::frontend():m_ptr(new imp(*this)) {
|
struct lean_extension_initializer {
|
||||||
import_all(m_ptr->m_env);
|
unsigned m_extid;
|
||||||
|
lean_extension_initializer() {
|
||||||
|
m_extid = environment::register_extension([](){ return std::unique_ptr<environment::extension>(new lean_extension()); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static lean_extension_initializer g_lean_extension_initializer;
|
||||||
|
|
||||||
|
static lean_extension & to_ext(environment const & env) {
|
||||||
|
return env.get_extension<lean_extension>(g_lean_extension_initializer.m_extid);
|
||||||
|
}
|
||||||
|
|
||||||
|
frontend::frontend() {
|
||||||
|
import_all(m_env);
|
||||||
init_builtin_notation(*this);
|
init_builtin_notation(*this);
|
||||||
m_ptr->m_state.set_formatter(mk_pp_formatter(*this));
|
m_state.set_formatter(mk_pp_formatter(*this));
|
||||||
}
|
}
|
||||||
frontend::frontend(imp * new_ptr):m_ptr(new_ptr) {
|
frontend::frontend(environment const & env, state const & s):m_env(env), m_state(s) {
|
||||||
m_ptr->m_state.set_formatter(mk_pp_formatter(*this));
|
|
||||||
}
|
}
|
||||||
frontend::frontend(std::shared_ptr<imp> const & ptr):m_ptr(ptr) {}
|
|
||||||
frontend::~frontend() {}
|
|
||||||
|
|
||||||
frontend frontend::mk_child() const { return frontend(new imp(m_ptr)); }
|
void frontend::add_infix(name const & opn, unsigned p, expr const & d) {
|
||||||
bool frontend::has_children() const { return m_ptr->has_children(); }
|
to_ext(m_env).add_op(infix(opn, p), d, true, m_env, m_state);
|
||||||
bool frontend::has_parent() const { return m_ptr->has_parent(); }
|
}
|
||||||
frontend frontend::parent() const { lean_assert(has_parent()); return frontend(m_ptr->m_parent); }
|
void frontend::add_infixl(name const & opn, unsigned p, expr const & d) {
|
||||||
|
to_ext(m_env).add_op(infixl(opn, p), d, true, m_env, m_state);
|
||||||
environment const & frontend::get_environment() const { return m_ptr->m_env; }
|
}
|
||||||
|
void frontend::add_infixr(name const & opn, unsigned p, expr const & d) {
|
||||||
level frontend::add_uvar(name const & n, level const & l) { return m_ptr->m_env.add_uvar(n, l); }
|
to_ext(m_env).add_op(infixr(opn, p), d, true, m_env, m_state);
|
||||||
level frontend::add_uvar(name const & n) { return m_ptr->m_env.add_uvar(n); }
|
}
|
||||||
level frontend::get_uvar(name const & n) const { return m_ptr->m_env.get_uvar(n); }
|
void frontend::add_prefix(name const & opn, unsigned p, expr const & d) {
|
||||||
|
to_ext(m_env).add_op(prefix(opn, p), d, false, m_env, m_state);
|
||||||
void frontend::add_definition(name const & n, expr const & t, expr const & v, bool opaque) {
|
}
|
||||||
return m_ptr->m_env.add_definition(n, t, v, opaque);
|
void frontend::add_postfix(name const & opn, unsigned p, expr const & d) {
|
||||||
|
to_ext(m_env).add_op(postfix(opn, p), d, true, m_env, m_state);
|
||||||
|
}
|
||||||
|
void frontend::add_mixfixl(unsigned sz, name const * opns, unsigned p, expr const & d) {
|
||||||
|
to_ext(m_env).add_op(mixfixl(sz, opns, p), d, false, m_env, m_state);
|
||||||
|
}
|
||||||
|
void frontend::add_mixfixr(unsigned sz, name const * opns, unsigned p, expr const & d) {
|
||||||
|
to_ext(m_env).add_op(mixfixr(sz, opns, p), d, true, m_env, m_state);
|
||||||
|
}
|
||||||
|
void frontend::add_mixfixc(unsigned sz, name const * opns, unsigned p, expr const & d) {
|
||||||
|
to_ext(m_env).add_op(mixfixc(sz, opns, p), d, false, m_env, m_state);
|
||||||
|
}
|
||||||
|
void frontend::add_mixfixo(unsigned sz, name const * opns, unsigned p, expr const & d) {
|
||||||
|
to_ext(m_env).add_op(mixfixo(sz, opns, p), d, true, m_env, m_state);
|
||||||
|
}
|
||||||
|
operator_info frontend::find_op_for(expr const & n, bool unicode) const {
|
||||||
|
return to_ext(m_env).find_op_for(n, unicode);
|
||||||
|
}
|
||||||
|
operator_info frontend::find_nud(name const & n) const {
|
||||||
|
return to_ext(m_env).find_nud(n);
|
||||||
|
}
|
||||||
|
operator_info frontend::find_led(name const & n) const {
|
||||||
|
return to_ext(m_env).find_led(n);
|
||||||
|
}
|
||||||
|
void frontend::mark_implicit_arguments(name const & n, unsigned sz, bool const * implicit) {
|
||||||
|
to_ext(m_env).mark_implicit_arguments(n, sz, implicit, m_env);
|
||||||
|
}
|
||||||
|
void frontend::mark_implicit_arguments(name const & n, std::initializer_list<bool> const & l) {
|
||||||
|
mark_implicit_arguments(n, l.size(), l.begin());
|
||||||
}
|
}
|
||||||
void frontend::add_theorem(name const & n, expr const & t, expr const & v) { return m_ptr->m_env.add_theorem(n, t, v); }
|
|
||||||
void frontend::add_definition(name const & n, expr const & v, bool opaque) { return m_ptr->m_env.add_definition(n, v, opaque); }
|
|
||||||
void frontend::add_axiom(name const & n, expr const & t) { return m_ptr->m_env.add_axiom(n, t); }
|
|
||||||
void frontend::add_var(name const & n, expr const & t) { return m_ptr->m_env.add_var(n, t); }
|
|
||||||
object const & frontend::get_object(name const & n) const { return m_ptr->m_env.get_object(n); }
|
|
||||||
object const & frontend::find_object(name const & n) const { return m_ptr->m_env.find_object(n); }
|
|
||||||
bool frontend::has_object(name const & n) const { return m_ptr->m_env.has_object(n); }
|
|
||||||
frontend::object_iterator frontend::begin_objects() const { return m_ptr->m_env.begin_objects(); }
|
|
||||||
frontend::object_iterator frontend::end_objects() const { return m_ptr->m_env.end_objects(); }
|
|
||||||
frontend::object_iterator frontend::begin_local_objects() const { return m_ptr->m_env.begin_local_objects(); }
|
|
||||||
frontend::object_iterator frontend::end_local_objects() const { return m_ptr->m_env.end_local_objects(); }
|
|
||||||
|
|
||||||
void frontend::add_infix(name const & opn, unsigned p, expr const & d) { m_ptr->add_infix(opn, p, d); }
|
|
||||||
void frontend::add_infixl(name const & opn, unsigned p, expr const & d) { m_ptr->add_infixl(opn, p, d); }
|
|
||||||
void frontend::add_infixr(name const & opn, unsigned p, expr const & d) { m_ptr->add_infixr(opn, p, d); }
|
|
||||||
void frontend::add_prefix(name const & opn, unsigned p, expr const & d) { m_ptr->add_prefix(opn, p, d); }
|
|
||||||
void frontend::add_postfix(name const & opn, unsigned p, expr const & d) { m_ptr->add_postfix(opn, p, d); }
|
|
||||||
void frontend::add_mixfixl(unsigned sz, name const * opns, unsigned p, expr const & d) { m_ptr->add_mixfixl(sz, opns, p, d); }
|
|
||||||
void frontend::add_mixfixr(unsigned sz, name const * opns, unsigned p, expr const & d) { m_ptr->add_mixfixr(sz, opns, p, d); }
|
|
||||||
void frontend::add_mixfixc(unsigned sz, name const * opns, unsigned p, expr const & d) { m_ptr->add_mixfixc(sz, opns, p, d); }
|
|
||||||
void frontend::add_mixfixo(unsigned sz, name const * opns, unsigned p, expr const & d) { m_ptr->add_mixfixo(sz, opns, p, d); }
|
|
||||||
operator_info frontend::find_op_for(expr const & n, bool unicode) const { return m_ptr->find_op_for(n, unicode); }
|
|
||||||
operator_info frontend::find_nud(name const & n) const { return m_ptr->find_nud(n); }
|
|
||||||
operator_info frontend::find_led(name const & n) const { return m_ptr->find_led(n); }
|
|
||||||
|
|
||||||
void frontend::mark_implicit_arguments(name const & n, unsigned sz, bool const * implicit) { m_ptr->mark_implicit_arguments(n, sz, implicit); }
|
|
||||||
void frontend::mark_implicit_arguments(name const & n, std::initializer_list<bool> const & l) { mark_implicit_arguments(n, l.size(), l.begin()); }
|
|
||||||
void frontend::mark_implicit_arguments(expr const & n, std::initializer_list<bool> const & l) {
|
void frontend::mark_implicit_arguments(expr const & n, std::initializer_list<bool> const & l) {
|
||||||
if (is_constant(n)) {
|
if (is_constant(n)) {
|
||||||
mark_implicit_arguments(const_name(n), l);
|
mark_implicit_arguments(const_name(n), l);
|
||||||
|
@ -433,21 +414,28 @@ void frontend::mark_implicit_arguments(expr const & n, std::initializer_list<boo
|
||||||
mark_implicit_arguments(to_value(n).get_name(), l);
|
mark_implicit_arguments(to_value(n).get_name(), l);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool frontend::has_implicit_arguments(name const & n) const { return m_ptr->has_implicit_arguments(n); }
|
bool frontend::has_implicit_arguments(name const & n) const {
|
||||||
std::vector<bool> const & frontend::get_implicit_arguments(name const & n) const { return m_ptr->get_implicit_arguments(n); }
|
return to_ext(m_env).has_implicit_arguments(n);
|
||||||
name const & frontend::get_explicit_version(name const & n) const { return m_ptr->get_explicit_version(n); }
|
}
|
||||||
bool frontend::is_explicit(name const & n) const { return m_ptr->is_explicit(n); }
|
std::vector<bool> const & frontend::get_implicit_arguments(name const & n) const {
|
||||||
|
return to_ext(m_env).get_implicit_arguments(n);
|
||||||
void frontend::add_coercion(expr const & f) { m_ptr->add_coercion(f); }
|
}
|
||||||
expr frontend::get_coercion(expr const & from_type, expr const & to_type) const { return m_ptr->get_coercion(from_type, to_type); }
|
name const & frontend::get_explicit_version(name const & n) const {
|
||||||
list<expr_pair> frontend::get_coercions(expr const & from_type) const { return m_ptr->get_coercions(from_type); }
|
return to_ext(m_env).get_explicit_version(n);
|
||||||
bool frontend::is_coercion(expr const & f) const { return m_ptr->is_coercion(f); }
|
}
|
||||||
|
bool frontend::is_explicit(name const & n) const {
|
||||||
state const & frontend::get_state() const { return m_ptr->m_state; }
|
return to_ext(m_env).is_explicit(n);
|
||||||
state & frontend::get_state_core() { return m_ptr->m_state; }
|
}
|
||||||
void frontend::set_options(options const & opts) { return m_ptr->m_state.set_options(opts); }
|
void frontend::add_coercion(expr const & f) {
|
||||||
void frontend::set_regular_channel(std::shared_ptr<output_channel> const & out) { return m_ptr->m_state.set_regular_channel(out); }
|
to_ext(m_env).add_coercion(f, m_env);
|
||||||
void frontend::set_diagnostic_channel(std::shared_ptr<output_channel> const & out) { return m_ptr->m_state.set_diagnostic_channel(out); }
|
}
|
||||||
|
expr frontend::get_coercion(expr const & from_type, expr const & to_type) const {
|
||||||
void frontend::set_interrupt(bool flag) { m_ptr->set_interrupt(flag); }
|
return to_ext(m_env).get_coercion(from_type, to_type);
|
||||||
|
}
|
||||||
|
list<expr_pair> frontend::get_coercions(expr const & from_type) const {
|
||||||
|
return to_ext(m_env).get_coercions(from_type);
|
||||||
|
}
|
||||||
|
bool frontend::is_coercion(expr const & f) const {
|
||||||
|
return to_ext(m_env).is_coercion(f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,64 +14,46 @@ Author: Leonardo de Moura
|
||||||
|
|
||||||
namespace lean {
|
namespace lean {
|
||||||
/**
|
/**
|
||||||
\brief Object for managing the environment, parser, pretty printer,
|
\brief Wrapper for environment/state that provides additional objects
|
||||||
elaborator, etc.
|
that are specific to the Lean frontend.
|
||||||
|
|
||||||
|
This wrapper provides APIs for accessing/using the Lean frontend
|
||||||
|
extension data in the environment.
|
||||||
*/
|
*/
|
||||||
class frontend {
|
class frontend {
|
||||||
struct imp;
|
environment m_env;
|
||||||
std::shared_ptr<imp> m_ptr;
|
state m_state;
|
||||||
explicit frontend(imp * new_ptr);
|
|
||||||
explicit frontend(std::shared_ptr<imp> const & ptr);
|
|
||||||
state & get_state_core();
|
|
||||||
public:
|
public:
|
||||||
frontend();
|
frontend();
|
||||||
~frontend();
|
frontend(environment const & env, state const & s);
|
||||||
|
|
||||||
/**
|
frontend mk_child() const { return frontend(m_env.mk_child(), m_state); }
|
||||||
@name Parent/Child frontend management.
|
bool has_children() const { return m_env.has_children(); }
|
||||||
*/
|
bool has_parent() const { return m_env.has_parent(); }
|
||||||
/*@{*/
|
|
||||||
/**
|
|
||||||
\brief Create a child environment. This frontend object will
|
|
||||||
only allow "read-only" operations until all children frontend
|
|
||||||
objects are deleted.
|
|
||||||
*/
|
|
||||||
frontend mk_child() const;
|
|
||||||
|
|
||||||
/** \brief Return true iff this fronted has children frontend. */
|
environment const & get_environment() const { return m_env; }
|
||||||
bool has_children() const;
|
operator environment const &() const { return get_environment(); }
|
||||||
|
|
||||||
/** \brief Return true iff this frontend has a parent frontend. */
|
|
||||||
bool has_parent() const;
|
|
||||||
|
|
||||||
/** \brief Return parent frontend */
|
|
||||||
frontend parent() const;
|
|
||||||
/*@}*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@name Environment API
|
@name Environment API
|
||||||
*/
|
*/
|
||||||
/*@{*/
|
/*@{*/
|
||||||
/** \brief Coercion frontend -> environment. */
|
level add_uvar(name const & n, level const & l) { return m_env.add_uvar(n, l); }
|
||||||
environment const & get_environment() const;
|
level add_uvar(name const & n) { return m_env.add_uvar(n); }
|
||||||
operator environment const &() const { return get_environment(); }
|
level get_uvar(name const & n) const { return m_env.get_uvar(n); }
|
||||||
|
void add_definition(name const & n, expr const & t, expr const & v, bool opaque = false) { m_env.add_definition(n, t, v, opaque); }
|
||||||
level add_uvar(name const & n, level const & l);
|
void add_theorem(name const & n, expr const & t, expr const & v) { m_env.add_theorem(n, t, v); }
|
||||||
level add_uvar(name const & n);
|
void add_definition(name const & n, expr const & v, bool opaque = false) { m_env.add_definition(n, v, opaque); }
|
||||||
level get_uvar(name const & n) const;
|
void add_axiom(name const & n, expr const & t) { m_env.add_axiom(n, t); }
|
||||||
void add_definition(name const & n, expr const & t, expr const & v, bool opaque = false);
|
void add_var(name const & n, expr const & t) { m_env.add_var(n, t); }
|
||||||
void add_theorem(name const & n, expr const & t, expr const & v);
|
object const & get_object(name const & n) const { return m_env.get_object(n); }
|
||||||
void add_definition(name const & n, expr const & v, bool opaque = false);
|
object const & find_object(name const & n) const { return m_env.find_object(n); }
|
||||||
void add_axiom(name const & n, expr const & t);
|
bool has_object(name const & n) const { return m_env.has_object(n); }
|
||||||
void add_var(name const & n, expr const & t);
|
|
||||||
object const & get_object(name const & n) const;
|
|
||||||
object const & find_object(name const & n) const;
|
|
||||||
bool has_object(name const & n) const;
|
|
||||||
typedef environment::object_iterator object_iterator;
|
typedef environment::object_iterator object_iterator;
|
||||||
object_iterator begin_objects() const;
|
object_iterator begin_objects() const { return m_env.begin_objects(); }
|
||||||
object_iterator end_objects() const;
|
object_iterator end_objects() const { return m_env.end_objects(); }
|
||||||
object_iterator begin_local_objects() const;
|
object_iterator begin_local_objects() const { return m_env.begin_local_objects(); }
|
||||||
object_iterator end_local_objects() const;
|
object_iterator end_local_objects() const { return m_env.end_local_objects(); }
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,18 +177,19 @@ public:
|
||||||
@name State management.
|
@name State management.
|
||||||
*/
|
*/
|
||||||
/*@{*/
|
/*@{*/
|
||||||
state const & get_state() const;
|
state const & get_state() const { return m_state; }
|
||||||
operator state const &() const { return get_state(); }
|
operator state const &() const { return m_state; }
|
||||||
void set_options(options const & opts);
|
options get_options() const { return m_state.get_options(); }
|
||||||
template<typename T> void set_option(name const & n, T const & v) { get_state_core().set_option(n, v); }
|
void set_options(options const & opts) { return m_state.set_options(opts); }
|
||||||
void set_regular_channel(std::shared_ptr<output_channel> const & out);
|
template<typename T> void set_option(name const & n, T const & v) { m_state.set_option(n, v); }
|
||||||
void set_diagnostic_channel(std::shared_ptr<output_channel> const & out);
|
void set_regular_channel(std::shared_ptr<output_channel> const & out) { m_state.set_regular_channel(out); }
|
||||||
|
void set_diagnostic_channel(std::shared_ptr<output_channel> const & out) { m_state.set_diagnostic_channel(out); }
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@name Interrupts.
|
@name Interrupts.
|
||||||
*/
|
*/
|
||||||
void set_interrupt(bool flag);
|
void set_interrupt(bool flag) { m_env.set_interrupt(flag); m_state.set_interrupt(flag); }
|
||||||
void interrupt() { set_interrupt(true); }
|
void interrupt() { set_interrupt(true); }
|
||||||
void reset_interrupt() { set_interrupt(false); }
|
void reset_interrupt() { set_interrupt(false); }
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
|
@ -116,7 +116,7 @@ class parser::imp {
|
||||||
typedef std::pair<unsigned, unsigned> pos_info;
|
typedef std::pair<unsigned, unsigned> pos_info;
|
||||||
typedef expr_map<pos_info> expr_pos_info;
|
typedef expr_map<pos_info> expr_pos_info;
|
||||||
typedef buffer<std::tuple<pos_info, name, expr, bool>> bindings_buffer;
|
typedef buffer<std::tuple<pos_info, name, expr, bool>> bindings_buffer;
|
||||||
frontend m_frontend;
|
frontend & m_frontend;
|
||||||
scanner m_scanner;
|
scanner m_scanner;
|
||||||
frontend_elaborator m_elaborator;
|
frontend_elaborator m_elaborator;
|
||||||
scanner::token m_curr;
|
scanner::token m_curr;
|
||||||
|
@ -1563,7 +1563,7 @@ class parser::imp {
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
imp(frontend const & fe, std::istream & in, bool use_exceptions, bool interactive):
|
imp(frontend & fe, std::istream & in, bool use_exceptions, bool interactive):
|
||||||
m_frontend(fe),
|
m_frontend(fe),
|
||||||
m_scanner(in),
|
m_scanner(in),
|
||||||
m_elaborator(fe),
|
m_elaborator(fe),
|
||||||
|
@ -1576,7 +1576,7 @@ public:
|
||||||
scan();
|
scan();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void show_prompt(bool interactive, frontend const & fe) {
|
static void show_prompt(bool interactive, frontend & fe) {
|
||||||
if (interactive) {
|
if (interactive) {
|
||||||
regular(fe) << "# ";
|
regular(fe) << "# ";
|
||||||
regular(fe).flush();
|
regular(fe).flush();
|
||||||
|
@ -1655,7 +1655,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
parser::parser(frontend const & fe, std::istream & in, bool use_exceptions, bool interactive) {
|
parser::parser(frontend & fe, std::istream & in, bool use_exceptions, bool interactive) {
|
||||||
parser::imp::show_prompt(interactive, fe);
|
parser::imp::show_prompt(interactive, fe);
|
||||||
m_ptr.reset(new imp(fe, in, use_exceptions, interactive));
|
m_ptr.reset(new imp(fe, in, use_exceptions, interactive));
|
||||||
}
|
}
|
||||||
|
@ -1675,7 +1675,7 @@ expr parser::parse_expr() {
|
||||||
return m_ptr->parse_expr_main();
|
return m_ptr->parse_expr_main();
|
||||||
}
|
}
|
||||||
|
|
||||||
shell::shell(frontend const & fe):m_frontend(fe) {
|
shell::shell(frontend & fe):m_frontend(fe) {
|
||||||
}
|
}
|
||||||
|
|
||||||
shell::~shell() {
|
shell::~shell() {
|
||||||
|
|
|
@ -15,7 +15,7 @@ class parser {
|
||||||
class imp;
|
class imp;
|
||||||
std::unique_ptr<imp> m_ptr;
|
std::unique_ptr<imp> m_ptr;
|
||||||
public:
|
public:
|
||||||
parser(frontend const & fe, std::istream & in, bool use_exceptions = true, bool interactive = false);
|
parser(frontend & fe, std::istream & in, bool use_exceptions = true, bool interactive = false);
|
||||||
~parser();
|
~parser();
|
||||||
|
|
||||||
/** \brief Parse a sequence of commands */
|
/** \brief Parse a sequence of commands */
|
||||||
|
@ -31,10 +31,10 @@ public:
|
||||||
|
|
||||||
/** \brief Implements the Read Eval Print loop */
|
/** \brief Implements the Read Eval Print loop */
|
||||||
class shell {
|
class shell {
|
||||||
frontend m_frontend;
|
frontend & m_frontend;
|
||||||
interruptable_ptr<parser> m_parser;
|
interruptable_ptr<parser> m_parser;
|
||||||
public:
|
public:
|
||||||
shell(frontend const & fe);
|
shell(frontend & fe);
|
||||||
~shell();
|
~shell();
|
||||||
|
|
||||||
bool operator()();
|
bool operator()();
|
||||||
|
@ -47,7 +47,7 @@ public:
|
||||||
inline bool parse_commands(frontend & fe, std::istream & in, bool use_exceptions = true, bool interactive = false) {
|
inline bool parse_commands(frontend & fe, std::istream & in, bool use_exceptions = true, bool interactive = false) {
|
||||||
return parser(fe, in, use_exceptions, interactive)();
|
return parser(fe, in, use_exceptions, interactive)();
|
||||||
}
|
}
|
||||||
inline expr parse_expr(frontend const & fe, std::istream & in) {
|
inline expr parse_expr(frontend & fe, std::istream & in) {
|
||||||
return parser(fe, in).parse_expr();
|
return parser(fe, in).parse_expr();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,6 @@ static void tst9() {
|
||||||
{
|
{
|
||||||
frontend c = f.mk_child();
|
frontend c = f.mk_child();
|
||||||
lean_assert(f.has_children());
|
lean_assert(f.has_children());
|
||||||
lean_assert(c.parent().has_children());
|
|
||||||
}
|
}
|
||||||
lean_assert(!f.has_children());
|
lean_assert(!f.has_children());
|
||||||
f.add_uvar("l", level()+1);
|
f.add_uvar("l", level()+1);
|
||||||
|
|
|
@ -49,7 +49,7 @@ static void tst1() {
|
||||||
parse(fe, "Check Pi (A : Type), A -> A");
|
parse(fe, "Check Pi (A : Type), A -> A");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void check(frontend const & fe, char const * str, expr const & expected) {
|
static void check(frontend & fe, char const * str, expr const & expected) {
|
||||||
std::istringstream in(str);
|
std::istringstream in(str);
|
||||||
try {
|
try {
|
||||||
expr got = parse_expr(fe, in);
|
expr got = parse_expr(fe, in);
|
||||||
|
|
Loading…
Add table
Reference in a new issue