feat(frontends/lean): add "polymorphic" print command

closes #524
This commit is contained in:
Leonardo de Moura 2015-04-29 16:17:33 -07:00
parent 1a28a3c36f
commit d6d30f12c6
4 changed files with 140 additions and 6 deletions

View file

@ -178,6 +178,23 @@ static void print_definition(parser const & p, name const & n, pos_info const &
new_out << d.get_value() << endl; new_out << d.get_value() << endl;
} }
void print_attributes(parser & p, name const & n) {
environment const & env = p.env();
io_state_stream out = p.regular_stream();
if (is_coercion(env, n))
out << " [coercion]";
if (is_class(env, n))
out << " [class]";
if (is_instance(env, n))
out << " [instance]";
switch (get_reducible_status(env, n)) {
case reducible_status::Reducible: out << " [reducible]"; break;
case reducible_status::Irreducible: out << " [irreducible]"; break;
case reducible_status::Quasireducible: out << " [quasireducible]"; break;
case reducible_status::Semireducible: break;
}
}
static void print_inductive(parser & p, name const & n, pos_info const & pos) { static void print_inductive(parser & p, name const & n, pos_info const & pos) {
environment const & env = p.env(); environment const & env = p.env();
io_state_stream out = p.regular_stream(); io_state_stream out = p.regular_stream();
@ -189,8 +206,7 @@ static void print_inductive(parser & p, name const & n, pos_info const & pos) {
else else
out << "inductive"; out << "inductive";
out << " " << n; out << " " << n;
if (is_class(env, n)) print_attributes(p, n);
out << " [class]";
out << " : " << env.get(n).get_type() << "\n"; out << " : " << env.get(n).get_type() << "\n";
if (is_structure(env, n)) { if (is_structure(env, n)) {
out << "fields:\n"; out << "fields:\n";
@ -208,6 +224,96 @@ static void print_inductive(parser & p, name const & n, pos_info const & pos) {
} }
} }
bool print_constant(parser & p, char const * kind, declaration const & d) {
io_state_stream out = p.regular_stream();
out << kind << " " << d.get_name();
print_attributes(p, d.get_name());
out << " : " << d.get_type() << "\n";
return true;
}
bool print_polymorphic(parser & p) {
environment const & env = p.env();
io_state_stream out = p.regular_stream();
auto pos = p.pos();
try {
name id = p.check_id_next("");
// declarations
try {
name c = p.to_constant(id, "", pos);
declaration const & d = env.get(c);
if (d.is_theorem()) {
print_constant(p, "theorem", d);
print_definition(p, c, pos);
return true;
} else if (d.is_axiom() || d.is_constant_assumption()) {
if (inductive::is_inductive_decl(env, c)) {
print_inductive(p, c, pos);
return true;
} else if (inductive::is_intro_rule(env, c)) {
return print_constant(p, "constructor", d);
} else if (inductive::is_elim_rule(env, c)) {
return print_constant(p, "eliminator", d);
} else if (is_quotient_decl(env, c)) {
return print_constant(p, "builtin-quotient-type-constant", d);
} else if (is_hits_decl(env, c)) {
return print_constant(p, "builtin-HIT-constant", d);
} else if (d.is_axiom()) {
return print_constant(p, "axiom", d);
} else if (d.is_constant_assumption()) {
return print_constant(p, "constant", d);
}
} else if (d.is_definition()) {
print_constant(p, "definition", d);
print_definition(p, c, pos);
return true;
}
} catch (exception & ex) {}
// variables and parameters
if (expr const * type = p.get_local(id)) {
if (is_local(*type)) {
if (p.is_local_variable(*type)) {
out << "variable " << id << " : " << mlocal_type(*type) << "\n";
} else {
out << "parameter " << id << " : " << mlocal_type(*type) << "\n";
}
return true;
}
}
// options
for (auto odecl : get_option_declarations()) {
auto opt = odecl.second;
if (opt.get_name() == id || opt.get_name() == name("lean") + id) {
out << "option " << opt.get_name() << " (" << opt.kind() << ") "
<< opt.get_description() << " (default: " << opt.get_default_value() << ")" << endl;
return true;
}
}
} catch (exception &) {}
// notation
if (p.curr_is_keyword()) {
buffer<name> tokens;
name tk = p.get_token_info().token();
tokens.push_back(tk);
bool found = false;
if (print_parse_table(p, get_nud_table(p.env()), true, tokens)) {
p.next();
found = true;
}
if (print_parse_table(p, get_led_table(p.env()), false, tokens)) {
p.next();
found = true;
}
if (found)
return true;
}
return false;
}
environment print_cmd(parser & p) { environment print_cmd(parser & p) {
flycheck_information info(p.regular_stream()); flycheck_information info(p.regular_stream());
if (info.enabled()) { if (info.enabled()) {
@ -279,6 +385,7 @@ environment print_cmd(parser & p) {
auto pos = p.pos(); auto pos = p.pos();
name c = p.check_constant_next("invalid 'print inductive', constant expected"); name c = p.check_constant_next("invalid 'print inductive', constant expected");
print_inductive(p, c, pos); print_inductive(p, c, pos);
} else if (print_polymorphic(p)) {
} else { } else {
throw parser_error("invalid print command", p.pos()); throw parser_error("invalid print command", p.pos());
} }

View file

@ -1192,11 +1192,8 @@ expr parser::id_to_expr(name const & id, pos_info const & p) {
return *r; return *r;
} }
name parser::check_constant_next(char const * msg) { name parser::to_constant(name const & id, char const * msg, pos_info const & p) {
auto p = pos();
name id = check_id_next(msg);
expr e = id_to_expr(id, p); expr e = id_to_expr(id, p);
if (in_section(m_env) && is_as_atomic(e)) { if (in_section(m_env) && is_as_atomic(e)) {
e = get_app_fn(get_as_atomic_arg(e)); e = get_app_fn(get_as_atomic_arg(e));
if (is_explicit(e)) if (is_explicit(e))
@ -1213,6 +1210,12 @@ name parser::check_constant_next(char const * msg) {
} }
} }
name parser::check_constant_next(char const * msg) {
auto p = pos();
name id = check_id_next(msg);
return to_constant(id, msg, p);
}
expr parser::parse_id() { expr parser::parse_id() {
auto p = pos(); auto p = pos();
name id = get_name_val(); name id = get_name_val();

View file

@ -333,6 +333,7 @@ public:
/** \brief Check if the current token is an atomic identifier, if it is, return it and move to next token, /** \brief Check if the current token is an atomic identifier, if it is, return it and move to next token,
otherwise throw an exception. */ otherwise throw an exception. */
name check_atomic_id_next(char const * msg); name check_atomic_id_next(char const * msg);
name to_constant(name const & id, char const * msg, pos_info const & p);
/** \brief Check if the current token is a constant, if it is, return it and move to next token, otherwise throw an exception. */ /** \brief Check if the current token is a constant, if it is, return it and move to next token, otherwise throw an exception. */
name check_constant_next(char const * msg); name check_constant_next(char const * msg);

View file

@ -0,0 +1,23 @@
import classical
open nat
print pp.max_depth
print +
print -
print nat
print nat.zero
print nat.add
print nat.rec
print em
print quot.lift
print nat.of_num
print nat.add.assoc
section
parameter {A : Type}
variable {a : A}
print A
print a
end