lean2/src/frontends/lean/tactic_hint.cpp
Leonardo de Moura 2dca68e645 chore(util/list): add inline functions for commonly used patterns in list processing code
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2014-08-03 13:51:38 -07:00

118 lines
3.8 KiB
C++

/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include <string>
#include "util/sstream.h"
#include "kernel/type_checker.h"
#include "library/scoped_ext.h"
#include "library/kernel_serializer.h"
#include "library/tactic/tactic.h"
#include "library/tactic/expr_to_tactic.h"
#include "frontends/lean/tactic_hint.h"
#include "frontends/lean/cmd_table.h"
#include "frontends/lean/parser.h"
#include "frontends/lean/class.h"
namespace lean {
typedef list<tactic_hint_entry> tactic_hint_entries;
struct tactic_hint_state {
typedef rb_map<name, tactic_hint_entries, name_quick_cmp> class_tactics;
class_tactics m_class_tactics;
tactic_hint_entries m_tactics;
};
struct tactic_hint_config {
typedef tactic_hint_state state;
typedef tactic_hint_entry entry;
typedef tactic_hint_entries entries;
static entries add(entries const & l, entry const & e) {
return cons(e, filter(l, [&](entry const & e1) { return e1.m_pre_tactic != e.m_pre_tactic; }));
}
static void add_entry_core(state & s, entry const & e) {
if (e.m_class.is_anonymous())
s.m_tactics = add(s.m_tactics, e);
else if (auto it = s.m_class_tactics.find(e.m_class))
s.m_class_tactics.insert(e.m_class, add(*it, e));
else
s.m_class_tactics.insert(e.m_class, entries(e));
}
static void add_entry(environment const & env, io_state const &, state & s, entry const & e) {
if (!e.m_compiled) {
entry new_e(e);
new_e.m_tactic = expr_to_tactic(env, e.m_pre_tactic, nullptr);
new_e.m_compiled = true;
add_entry_core(s, new_e);
} else {
add_entry_core(s, e);
}
}
static name const & get_class_name() {
static name g_class_name("tactic_hint");
return g_class_name;
}
static std::string const & get_serialization_key() {
static std::string g_key("tachint");
return g_key;
}
static void write_entry(serializer & s, entry const & e) {
s << e.m_class << e.m_pre_tactic;
}
static entry read_entry(deserializer & d) {
entry e;
d >> e.m_class >> e.m_pre_tactic;
return e;
}
};
template class scoped_ext<tactic_hint_config>;
typedef scoped_ext<tactic_hint_config> tactic_hint_ext;
list<tactic_hint_entry> get_tactic_hints(environment const & env, name const & c) {
tactic_hint_state const & s = tactic_hint_ext::get_state(env);
return ptr_to_list(s.m_class_tactics.find(c));
}
list<tactic_hint_entry> get_tactic_hints(environment const & env) {
tactic_hint_state const & s = tactic_hint_ext::get_state(env);
return s.m_tactics;
}
expr parse_tactic_name(parser & p) {
auto pos = p.pos();
name pre_tac = p.check_constant_next("invalid tactic name, constant expected");
expr pre_tac_type = p.env().get(pre_tac).get_type();
if (!is_constant(pre_tac_type) || const_name(pre_tac_type) != name({"tactic", "tactic"}))
throw parser_error(sstream() << "invalid tactic name, '" << pre_tac << "' is not a tactic", pos);
return mk_constant(pre_tac);
}
static name g_lbracket("[");
static name g_rbracket("]");
environment tactic_hint_cmd(parser & p) {
name cls;
if (p.curr_is_token(g_lbracket)) {
p.next();
cls = get_class_name(p.env(), p.parse_expr());
p.check_token_next(g_rbracket, "invalid tactic hint, ']' expected");
}
expr pre_tac = parse_tactic_name(p);
tactic tac = expr_to_tactic(p.env(), pre_tac, nullptr);
return tactic_hint_ext::add_entry(p.env(), get_dummy_ios(), tactic_hint_entry(cls, pre_tac, tac));
}
void register_tactic_hint_cmd(cmd_table & r) {
add_cmd(r, cmd_info("tactic_hint", "add a new tactic hint", tactic_hint_cmd));
}
}