fix(frontends/lean): pretty printing in sections with parameters

fix #530
This commit is contained in:
Leonardo de Moura 2015-04-21 22:40:20 -07:00
parent caf28f4053
commit 53653c3526
15 changed files with 193 additions and 17 deletions

View file

@ -8,6 +8,6 @@ structure_cmd.cpp info_manager.cpp info_annotation.cpp find_cmd.cpp
coercion_elaborator.cpp info_tactic.cpp
init_module.cpp elaborator_context.cpp calc_proof_elaborator.cpp
parse_tactic_location.cpp parse_rewrite_tactic.cpp
type_util.cpp elaborator_exception.cpp migrate_cmd.cpp)
type_util.cpp elaborator_exception.cpp migrate_cmd.cpp local_ref_info.cpp)
target_link_libraries(lean_frontend ${LEAN_LIBS})

View file

@ -270,12 +270,12 @@ environment namespace_cmd(parser & p) {
return push_scope(p.env(), p.ios(), scope_kind::Namespace, n);
}
static void redeclare_aliases(parser & p,
list<pair<name, level>> old_level_entries,
list<pair<name, expr>> old_entries) {
environment const & env = p.env();
if (!in_context(env) && !in_section(env))
return;
static environment redeclare_aliases(environment env, parser & p,
list<pair<name, level>> old_level_entries,
list<pair<name, expr>> old_entries) {
environment const & old_env = p.env();
if (!in_context(old_env) && !in_section(old_env))
return env;
list<pair<name, expr>> new_entries = p.get_local_entries();
buffer<pair<name, expr>> to_redeclare;
name_set popped_locals;
@ -299,8 +299,9 @@ static void redeclare_aliases(parser & p,
for (auto const & entry : to_redeclare) {
expr new_ref = update_local_ref(entry.second, popped_levels, popped_locals);
if (!is_constant(new_ref))
p.add_local_expr(entry.first, new_ref);
env = p.add_local_ref(env, entry.first, new_ref);
}
return env;
}
environment end_scoped_cmd(parser & p) {
@ -310,12 +311,10 @@ environment end_scoped_cmd(parser & p) {
if (p.curr_is_identifier()) {
name n = p.check_atomic_id_next("invalid end of scope, atomic identifier expected");
environment env = pop_scope(p.env(), p.ios(), n);
redeclare_aliases(p, level_entries, entries);
return env;
return redeclare_aliases(env, p, level_entries, entries);
} else {
environment env = pop_scope(p.env(), p.ios());
redeclare_aliases(p, level_entries, entries);
return env;
return redeclare_aliases(env, p, level_entries, entries);
}
}

View file

@ -952,10 +952,10 @@ class definition_cmd_fn {
local_ls = remove_local_vars(m_p, local_ls);
if (!locals.empty()) {
expr ref = mk_local_ref(m_real_name, local_ls, locals);
m_p.add_local_expr(m_name, ref);
m_env = m_p.add_local_ref(m_env, m_name, ref);
} else if (local_ls) {
expr ref = mk_constant(m_real_name, local_ls);
m_p.add_local_expr(m_name, ref);
m_env = m_p.add_local_ref(m_env, m_name, ref);
}
} else {
update_univ_parameters(m_ls_buffer, collect_univ_params(m_value, collect_univ_params(m_type)), m_p);

View file

@ -27,6 +27,7 @@ Author: Leonardo de Moura
#include "frontends/lean/scanner.h"
#include "frontends/lean/pp.h"
#include "frontends/lean/server.h"
#include "frontends/lean/local_ref_info.h"
namespace lean {
void initialize_frontend_lean_module() {
@ -53,8 +54,10 @@ void initialize_frontend_lean_module() {
initialize_calc_proof_elaborator();
initialize_server();
initialize_find_cmd();
initialize_local_ref_info();
}
void finalize_frontend_lean_module() {
finalize_local_ref_info();
finalize_find_cmd();
finalize_server();
finalize_calc_proof_elaborator();

View file

@ -0,0 +1,79 @@
/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <string>
#include "library/scoped_ext.h"
namespace lean {
/*
When we declare a definition in a section, we create an alias for it that fixes the parameters in
universe parameters. We have to store the number of parameters and universes that have been fixed
to be able to correctly pretty print terms.
*/
struct local_ref_entry {
name m_name;
unsigned m_num_fix_univs;
unsigned m_num_fix_args;
local_ref_entry() {}
local_ref_entry(name const & n, unsigned u, unsigned p):
m_name(n), m_num_fix_univs(u), m_num_fix_args(p) {}
};
static name * g_local_ref_name = nullptr;
static std::string * g_key = nullptr;
struct local_ref_config {
typedef name_map<pair<unsigned, unsigned>> state;
typedef local_ref_entry entry;
static void add_entry(environment const &, io_state const &, state & s, entry const & e) {
s.insert(e.m_name, mk_pair(e.m_num_fix_univs, e.m_num_fix_args));
}
static name const & get_class_name() {
return *g_local_ref_name;
}
static std::string const & get_serialization_key() {
return *g_key;
}
static void write_entry(serializer &, entry const &) {
lean_unreachable();
}
static entry read_entry(deserializer &) {
lean_unreachable();
}
static optional<unsigned> get_fingerprint(entry const &) {
return optional<unsigned>();
}
};
template class scoped_ext<local_ref_config>;
typedef scoped_ext<local_ref_config> local_ref_ext;
environment save_local_ref_info(environment const & env, name const & n, unsigned num_fix_univs, unsigned num_fix_args) {
bool persistent = false;
return local_ref_ext::add_entry(env, get_dummy_ios(), local_ref_entry(n, num_fix_univs, num_fix_args), persistent);
}
optional<pair<unsigned, unsigned>> get_local_ref_info(environment const & env, name const & n) {
if (auto r = local_ref_ext::get_state(env).find(n))
return optional<pair<unsigned, unsigned>>(*r);
else
return optional<pair<unsigned, unsigned>>();
}
void initialize_local_ref_info() {
g_local_ref_name = new name("localrefinfo");
g_key = new std::string("localrefinfo");
local_ref_ext::initialize();
}
void finalize_local_ref_info() {
local_ref_ext::finalize();
delete g_local_ref_name;
delete g_key;
}
}

View file

@ -0,0 +1,14 @@
/*
Copyright (c) 2015 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#pragma once
namespace lean {
environment save_local_ref_info(environment const & env, name const & n, unsigned num_fix_univs, unsigned num_fix_args);
optional<pair<unsigned, unsigned>> get_local_ref_info(environment const & env, name const & n);
void initialize_local_ref_info();
void finalize_local_ref_info();
}

View file

@ -47,6 +47,7 @@ Author: Leonardo de Moura
#include "frontends/lean/info_annotation.h"
#include "frontends/lean/parse_rewrite_tactic.h"
#include "frontends/lean/update_environment_exception.h"
#include "frontends/lean/local_ref_info.h"
#ifndef LEAN_DEFAULT_PARSER_SHOW_ERRORS
#define LEAN_DEFAULT_PARSER_SHOW_ERRORS true
@ -494,6 +495,20 @@ void parser::add_local_expr(name const & n, expr const & p, bool is_variable) {
}
}
environment parser::add_local_ref(environment const & env, name const & n, expr const & ref) {
add_local_expr(n, ref, false);
if (is_as_atomic(ref)) {
buffer<expr> args;
expr f = get_app_args(get_as_atomic_arg(ref), args);
if (is_explicit(f))
f = get_explicit_arg(f);
if (is_constant(f)) {
return save_local_ref_info(env, const_name(f), length(const_levels(f)), args.size());
}
}
return env;
}
void parser::add_parameter(name const & n, expr const & p) {
lean_assert(is_local(p));
add_local_expr(n, p, false);

View file

@ -400,6 +400,7 @@ public:
bool has_locals() const { return !m_local_decls.empty() || !m_local_level_decls.empty(); }
void add_local_level(name const & n, level const & l, bool is_variable = false);
void add_local_expr(name const & n, expr const & p, bool is_variable = false);
environment add_local_ref(environment const & env, name const & n, expr const & ref);
void add_parameter(name const & n, expr const & p);
void add_local(expr const & p) { return add_local_expr(local_pp_name(p), p); }
bool has_params() const { return m_has_params; }

View file

@ -33,6 +33,7 @@ Author: Leonardo de Moura
#include "frontends/lean/token_table.h"
#include "frontends/lean/builtin_exprs.h"
#include "frontends/lean/parser_config.h"
#include "frontends/lean/local_ref_info.h"
namespace lean {
static format * g_ellipsis_n_fmt = nullptr;
@ -438,9 +439,19 @@ auto pretty_fn::pp_const(expr const & e) -> result {
n = *n1;
}
if (m_universes && !empty(const_levels(e))) {
unsigned first_idx = 0;
buffer<level> ls;
to_buffer(const_levels(e), ls);
if (auto info = get_local_ref_info(m_env, n)) {
if (ls.size() <= info->first)
return result(format(n));
else
first_idx = info->first;
}
format r = compose(format(n), format(".{"));
bool first = true;
for (auto const & l : const_levels(e)) {
for (unsigned i = first_idx; i < ls.size(); i++) {
level const & l = ls[i];
format l_fmt = pp_level(l);
if (is_max(l) || is_imax(l))
l_fmt = paren(l_fmt);
@ -490,6 +501,15 @@ bool pretty_fn::has_implicit_args(expr const & f) {
}
auto pretty_fn::pp_app(expr const & e) -> result {
expr const & rfn = get_app_fn(e);
if (is_constant(rfn)) {
if (auto info = get_local_ref_info(m_env, const_name(rfn))) {
buffer<expr> args;
get_app_args(e, args);
if (args.size() == info->second)
return pp_const(rfn);
}
}
expr const & fn = app_fn(e);
if (auto it = is_abbreviated(fn))
return pp_abbreviation(e, *it, true);

View file

@ -31,7 +31,7 @@ environment add_alias(parser & p, environment env, bool composite,
id = name(full_id.get_string());
if (!empty(ctx_levels) || !ctx_params.empty()) {
expr r = mk_local_ref(full_id, ctx_levels, ctx_params);
p.add_local_expr(id, r);
env = p.add_local_ref(env, id, r);
}
if (full_id != id)
env = add_expr_alias_rec(env, id, full_id);

View file

@ -3,7 +3,7 @@ tst1 : nat → nat → nat
errors.lean:12:2: error: function expected at
tactic.cases [tactic.expr add] tactic.expr_list.nil
errors.lean:22:12: error: unknown identifier 'b'
tst3 A : A → A → A
tst3 : A → A → A
foo.tst1 :
foo.tst2 :
foo.tst3 : Π (A : Type), A → A → A

View file

@ -0,0 +1,20 @@
section
parameters {A : Type} (a : A)
variable f : A → A → A
definition id : A := a
check id
definition pr (b : A) : A := f a b
check pr f id
set_option pp.universes true
check pr f id
definition pr2 (B : Type) (b : B) : A := a
check pr2 num 10
end

View file

@ -0,0 +1,4 @@
id : A
pr f id : A
pr f id : A
pr2.{1} num 10 : A

View file

@ -0,0 +1,17 @@
section
parameters {A : Type} (a : A)
section
parameters {B : Type} (b : B)
variable f : A → B → A
definition id := f a b
check id
set_option pp.universes true
check id
end
check id
end
check id

View file

@ -0,0 +1,4 @@
id : (A → B → A) → A
id : (A → B → A) → A
id.{l_2} : ?B a → (A → ?B a → A) → A
id.{l_1 l_2} : ?A → (Π {B : Type.{l_2}}, B → (?A → B → ?A) → ?A)