refactor(*): explicit initialization/finalization for serialization

modules, expression annotations, and tactics
This commit is contained in:
Leonardo de Moura 2014-09-22 15:26:41 -07:00
parent b1ee888aae
commit b6781711b1
47 changed files with 684 additions and 376 deletions

View file

@ -7,13 +7,18 @@ Author: Leonardo de Moura
#include "frontends/lean/extra_info.h"
namespace lean {
name const & get_extra_info() {
static name g_extra_info("extra_info");
static register_annotation_fn g_extra_info_annotation(g_extra_info);
return g_extra_info;
}
static name g_extra_info_name = get_extra_info(); // force 'extra_info' annotation to be registered
static name * g_extra_info = nullptr;
name const & get_extra_info() { return *g_extra_info; }
expr mk_extra_info(expr const & e) { return mk_annotation(get_extra_info(), e); }
bool is_extra_info(expr const & e) { return is_annotation(e, get_extra_info()); }
void initialize_extra_info() {
g_extra_info = new name("extra_info");
register_annotation(*g_extra_info);
}
void finalize_extra_info() {
delete g_extra_info;
}
}

View file

@ -14,4 +14,7 @@ namespace lean {
expr mk_extra_info(expr const & e);
/** \brief Return true iff \c e is a term annotated with mk_extra_info */
bool is_extra_info(expr const & e);
void initialize_extra_info();
void finalize_extra_info();
}

View file

@ -7,14 +7,20 @@ Author: Leonardo de Moura
#include "frontends/lean/elaborator.h"
#include "frontends/lean/pp_options.h"
#include "frontends/lean/parser.h"
#include "frontends/lean/no_info.h"
#include "frontends/lean/extra_info.h"
namespace lean {
void initialize_frontend_lean_module() {
initialize_elaborator();
initialize_pp_options();
initialize_parser();
initialize_no_info();
initialize_extra_info();
}
void finalize_frontend_lean_module() {
finalize_extra_info();
finalize_no_info();
finalize_parser();
finalize_pp_options();
finalize_elaborator();

View file

@ -7,13 +7,18 @@ Author: Leonardo de Moura
#include "frontends/lean/no_info.h"
namespace lean {
name const & get_no_info() {
static name g_no_info("no_info");
static register_annotation_fn g_no_info_annotation(g_no_info);
return g_no_info;
}
static name g_no_info_name = get_no_info(); // force 'no_info' annotation to be registered
static name * g_no_info = nullptr;
name const & get_no_info() { return *g_no_info; }
expr mk_no_info(expr const & e) { return mk_annotation(get_no_info(), e); }
bool is_no_info(expr const & e) { return is_annotation(e, get_no_info()); }
void initialize_no_info() {
g_no_info = new name("no_info");
register_annotation(*g_no_info);
}
void finalize_no_info() {
delete g_no_info;
}
}

View file

@ -16,4 +16,7 @@ namespace lean {
expr mk_no_info(expr const & e);
/** \brief Return true iff \c e is a term annotated with mk_no_info */
bool is_no_info(expr const & e);
void initialize_no_info();
void finalize_no_info();
}

View file

@ -4,7 +4,9 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include "util/init_module.h"
#include "util/sexpr/init_module.h"
#include "kernel/init_module.h"
#include "library/init_module.h"
#include "library/tactic/init_module.h"
#include "frontends/lean/init_module.h"
@ -12,7 +14,9 @@ Author: Leonardo de Moura
namespace lean {
void initialize() {
initialize_util_module();
initialize_sexpr_module();
initialize_kernel_module();
initialize_library_module();
initialize_tactic_module();
initialize_frontend_lean_module();
@ -21,7 +25,9 @@ void finalize() {
finalize_frontend_lean_module();
finalize_tactic_module();
finalize_library_module();
finalize_kernel_module();
finalize_sexpr_module();
finalize_util_module();
}
initializer::initializer() {

View file

@ -3,6 +3,6 @@ replace_fn.cpp free_vars.cpp abstract.cpp instantiate.cpp
formatter.cpp declaration.cpp replace_visitor.cpp environment.cpp
justification.cpp pos_info_provider.cpp metavar.cpp converter.cpp
constraint.cpp type_checker.cpp error_msgs.cpp kernel_exception.cpp
normalizer_extension.cpp)
normalizer_extension.cpp init_module.cpp)
target_link_libraries(kernel ${LEAN_LIBS})

View file

@ -0,0 +1,12 @@
/*
Copyright (c) 2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
namespace lean {
void initialize_kernel_module() {
}
void finalize_kernel_module() {
}
}

11
src/kernel/init_module.h Normal file
View file

@ -0,0 +1,11 @@
/*
Copyright (c) 2014 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 {
void initialize_kernel_module();
void finalize_kernel_module();
}

View file

@ -8,18 +8,15 @@ Author: Leonardo de Moura
#include <memory>
#include <string>
#include "util/sstream.h"
#include "library/kernel_serializer.h"
#include "library/annotation.h"
namespace lean {
name const & get_annotation_name() {
static name g_annotation("annotation");
return g_annotation;
}
static name * g_annotation = nullptr;
static std::string * g_annotation_opcode = nullptr;
std::string const & get_annotation_opcode() {
static std::string g_annotation_opcode("Annot");
return g_annotation_opcode;
}
name const & get_annotation_name() { return *g_annotation; }
std::string const & get_annotation_opcode() { return *g_annotation_opcode; }
/** \brief We use a macro to mark expressions that denote "let" and "have"-expressions.
These marks have no real semantic meaning, but are useful for helping Lean's pretty printer.
@ -51,14 +48,12 @@ public:
};
typedef std::unordered_map<name, macro_definition, name_hash, name_eq> annotation_macros;
annotation_macros & get_annotation_macros() {
static std::unique_ptr<annotation_macros> g_annotation_macros;
if (!g_annotation_macros) g_annotation_macros.reset(new annotation_macros());
return *(g_annotation_macros.get());
}
static annotation_macros * g_annotation_macros = nullptr;
annotation_macros & get_annotation_macros() { return *g_annotation_macros; }
void register_annotation(name const & n) {
annotation_macros & ms = get_annotation_macros();
annotation_macros & ms = get_annotation_macros();
lean_assert(ms.find(n) == ms.end());
ms.insert(mk_pair(n, macro_definition(new annotation_macro_definition_cell(n))));
}
@ -124,32 +119,45 @@ expr copy_annotations(expr const & from, expr const & to) {
return r;
}
name const & get_have_name() {
static name g_have("have");
static register_annotation_fn g_have_annotation(g_have);
return g_have;
static name * g_have = nullptr;
static name * g_show = nullptr;
static name * g_proof_qed = nullptr;
expr mk_have_annotation(expr const & e) { return mk_annotation(*g_have, e); }
expr mk_show_annotation(expr const & e) { return mk_annotation(*g_show, e); }
expr mk_proof_qed_annotation(expr const & e) { return mk_annotation(*g_proof_qed, e); }
bool is_have_annotation(expr const & e) { return is_annotation(e, *g_have); }
bool is_show_annotation(expr const & e) { return is_annotation(e, *g_show); }
bool is_proof_qed_annotation(expr const & e) { return is_annotation(e, *g_proof_qed); }
void initialize_annotation() {
g_annotation = new name("annotation");
g_annotation_opcode = new std::string("Annot");
g_annotation_macros = new annotation_macros();
g_have = new name("have");
g_show = new name("show");
g_proof_qed = new name("proof-qed");
register_annotation(*g_have);
register_annotation(*g_show);
register_annotation(*g_proof_qed);
register_macro_deserializer(get_annotation_opcode(),
[](deserializer & d, unsigned num, expr const * args) {
if (num != 1)
throw corrupted_stream_exception();
name k;
d >> k;
return mk_annotation(k, args[0]);
});
}
name const & get_show_name() {
static name g_show("show");
static register_annotation_fn g_show_annotation(g_show);
return g_show;
void finalize_annotation() {
delete g_proof_qed;
delete g_show;
delete g_have;
delete g_annotation_macros;
delete g_annotation_opcode;
delete g_annotation;
}
name const & get_proof_qed_name() {
static name g_proof_qed("proof-qed");
static register_annotation_fn g_proof_qed_annotation(g_proof_qed);
return g_proof_qed;
}
static name g_have_name = get_have_name(); // force 'have' annotation to be registered
static name g_show_name = get_show_name(); // force 'show' annotation to be registered
static name g_proof_qed_name = get_proof_qed_name(); // force 'proof-qed' annotation to be registered
expr mk_have_annotation(expr const & e) { return mk_annotation(get_have_name(), e); }
expr mk_show_annotation(expr const & e) { return mk_annotation(get_show_name(), e); }
expr mk_proof_qed_annotation(expr const & e) { return mk_annotation(get_proof_qed_name(), e); }
bool is_have_annotation(expr const & e) { return is_annotation(e, get_have_name()); }
bool is_show_annotation(expr const & e) { return is_annotation(e, get_show_name()); }
bool is_proof_qed_annotation(expr const & e) { return is_annotation(e, get_proof_qed_name()); }
}

View file

@ -13,10 +13,6 @@ namespace lean {
Use helper obect #register_annotation_fn.
*/
void register_annotation(name const & n);
/** \brief Helper object for declaring a new kind of annotation */
struct register_annotation_fn {
register_annotation_fn(name const & kind) { register_annotation(kind); }
};
/** \brief Create an annotated expression with tag \c kind based on \c e.
@ -71,4 +67,7 @@ bool is_proof_qed_annotation(expr const & e);
/** \brief Return the serialization 'opcode' for annotation macros. */
std::string const & get_annotation_opcode();
void initialize_annotation();
void finalize_annotation();
}

View file

@ -11,10 +11,10 @@ Author: Leonardo de Moura
#include "library/kernel_serializer.h"
namespace lean {
static name g_choice_name("choice");
static std::string g_choice_opcode("Choice");
[[ noreturn ]] static void throw_ex() { throw exception("unexpected occurrence of 'choice' expression");
}
static name * g_choice_name = nullptr;
static std::string * g_choice_opcode = nullptr;
[[ noreturn ]] static void throw_ex() { throw exception("unexpected occurrence of 'choice' expression"); }
// We encode a 'choice' expression using a macro.
// This is a trick to avoid creating a new kind of expression.
@ -22,31 +22,44 @@ static std::string g_choice_opcode("Choice");
// and have no semantic significance.
class choice_macro_cell : public macro_definition_cell {
public:
virtual name get_name() const { return g_choice_name; }
virtual name get_name() const { return *g_choice_name; }
// Choice expressions must be replaced with metavariables before invoking the type checker.
// Choice expressions cannot be exported. They are transient/auxiliary objects.
virtual expr get_type(expr const &, expr const *, extension_context &) const { throw_ex(); }
virtual optional<expr> expand(expr const &, extension_context &) const { throw_ex(); }
virtual void write(serializer & s) const {
// we should be able to write choice expressions because of notation declarations
s.write_string(g_choice_opcode);
s.write_string(*g_choice_opcode);
}
};
static macro_definition g_choice(new choice_macro_cell());
static macro_definition * g_choice = nullptr;
expr mk_choice(unsigned num_es, expr const * es) {
lean_assert(num_es > 0);
if (num_es == 1)
return es[0];
else
return mk_macro(g_choice, num_es, es);
return mk_macro(*g_choice, num_es, es);
}
static register_macro_deserializer_fn
choice_macro_des_fn(g_choice_opcode, [](deserializer &, unsigned num, expr const * args) { return mk_choice(num, args); });
void initialize_choice() {
g_choice_name = new name("choice");
g_choice_opcode = new std::string("Choice");
g_choice = new macro_definition(new choice_macro_cell());
register_macro_deserializer(*g_choice_opcode,
[](deserializer &, unsigned num, expr const * args) {
return mk_choice(num, args);
});
}
void finalize_choice() {
delete g_choice;
delete g_choice_opcode;
delete g_choice_name;
}
bool is_choice(expr const & e) {
return is_macro(e) && macro_def(e) == g_choice;
return is_macro(e) && macro_def(e) == *g_choice;
}
unsigned get_num_choices(expr const & e) {

View file

@ -35,4 +35,6 @@ unsigned get_num_choices(expr const & e);
*/
expr const & get_choice(expr const & e, unsigned i);
void open_choice(lua_State * L);
void initialize_choice();
void finalize_choice();
}

View file

@ -10,38 +10,37 @@ Author: Leonardo de Moura
#include "library/kernel_bindings.h"
namespace lean {
name const & get_explicit_name() {
static name g_explicit_name("@");
static register_annotation_fn g_explicit_annotation(g_explicit_name);
return g_explicit_name;
}
static name * g_explicit_name = nullptr;
static name * g_implicit_name = nullptr;
static name * g_as_is_name = nullptr;
name const & get_implicit_name() {
static name g_implicit_name("@^-1");
static register_annotation_fn g_implicit_annotation(g_implicit_name);
return g_implicit_name;
}
name const & get_as_is_name() {
static name g_as_is_name("as_is");
static register_annotation_fn g_as_is_annotation(g_as_is_name);
return g_as_is_name;
}
static name g_explicit_name = get_explicit_name(); // force '@' annotation to be registered
static name g_implicit_name = get_implicit_name(); // force '@^-1' annotation to be registered
static name g_as_is_name = get_as_is_name(); // force 'as_is' annotation to be registered
expr mk_explicit(expr const & e) { return mk_annotation(get_explicit_name(), e); }
bool is_explicit(expr const & e) { return is_annotation(e, get_explicit_name()); }
bool is_nested_explicit(expr const & e) { return is_nested_annotation(e, get_explicit_name()); }
expr mk_as_is(expr const & e) { return mk_annotation(get_as_is_name(), e); }
bool is_as_is(expr const & e) { return is_annotation(e, get_as_is_name()); }
expr mk_implicit(expr const & e) { return mk_annotation(get_implicit_name(), e); }
bool is_implicit(expr const & e) { return is_annotation(e, get_implicit_name()); }
expr mk_explicit(expr const & e) { return mk_annotation(*g_explicit_name, e); }
bool is_explicit(expr const & e) { return is_annotation(e, *g_explicit_name); }
bool is_nested_explicit(expr const & e) { return is_nested_annotation(e, *g_explicit_name); }
expr mk_as_is(expr const & e) { return mk_annotation(*g_as_is_name, e); }
bool is_as_is(expr const & e) { return is_annotation(e, *g_as_is_name); }
expr mk_implicit(expr const & e) { return mk_annotation(*g_implicit_name, e); }
bool is_implicit(expr const & e) { return is_annotation(e, *g_implicit_name); }
expr const & get_explicit_arg(expr const & e) { lean_assert(is_explicit(e)); return get_annotation_arg(e); }
expr const & get_as_is_arg(expr const & e) { lean_assert(is_as_is(e)); return get_annotation_arg(e); }
expr const & get_implicit_arg(expr const & e) { lean_assert(is_implicit(e)); return get_annotation_arg(e); }
void initialize_explicit() {
g_explicit_name = new name("@");
g_implicit_name = new name("@^-1");
g_as_is_name = new name("as_is");
register_annotation(*g_explicit_name);
register_annotation(*g_implicit_name);
register_annotation(*g_as_is_name);
}
void finalize_explicit() {
delete g_as_is_name;
delete g_implicit_name;
delete g_explicit_name;
}
static int mk_explicit(lua_State * L) { return push_expr(L, mk_explicit(to_expr(L, 1))); }
static int is_explicit(lua_State * L) { return push_boolean(L, is_explicit(to_expr(L, 1))); }
static void check_explicit(lua_State * L, int idx) {

View file

@ -42,4 +42,6 @@ expr const & get_as_is_arg(expr const & e);
*/
expr const & get_implicit_arg(expr const & e);
void open_explicit(lua_State * L);
void initialize_explicit();
void finalize_explicit();
}

View file

@ -5,13 +5,37 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include "library/unifier.h"
#include "library/kernel_serializer.h"
#include "library/let.h"
#include "library/typed_expr.h"
#include "library/choice.h"
#include "library/string.h"
#include "library/resolve_macro.h"
#include "library/annotation.h"
#include "library/explicit.h"
namespace lean {
void initialize_library_module() {
initialize_unifier();
initialize_kernel_serializer();
initialize_let();
initialize_typed_expr();
initialize_choice();
initialize_string();
initialize_resolve_macro();
initialize_annotation();
initialize_explicit();
}
void finalize_library_module() {
finalize_explicit();
finalize_annotation();
finalize_resolve_macro();
finalize_string();
finalize_choice();
finalize_typed_expr();
finalize_let();
finalize_kernel_serializer();
finalize_unifier();
}
}

View file

@ -81,14 +81,14 @@ struct level_sd {
}
};
static level_sd g_level_sd;
static level_sd * g_level_sd = nullptr;
serializer & operator<<(serializer & s, level const & n) {
s.get_extension<level_serializer>(g_level_sd.m_s_extid).write(n);
s.get_extension<level_serializer>(g_level_sd->m_s_extid).write(n);
return s;
}
level read_level(deserializer & d) { return d.get_extension<level_deserializer>(g_level_sd.m_d_extid).read(); }
level read_level(deserializer & d) { return d.get_extension<level_deserializer>(g_level_sd->m_d_extid).read(); }
serializer & operator<<(serializer & s, levels const & ls) { return write_list<level>(s, ls); }
@ -96,11 +96,10 @@ levels read_levels(deserializer & d) { return read_list<level>(d, read_level); }
// Expression serialization
typedef std::unordered_map<std::string, macro_definition_cell::reader> macro_readers;
static std::unique_ptr<macro_readers> g_macro_readers;
static macro_readers * g_macro_readers = nullptr;
macro_readers & get_macro_readers() {
if (!g_macro_readers)
g_macro_readers.reset(new macro_readers());
return *(g_macro_readers.get());
return *g_macro_readers;
}
void register_macro_deserializer(std::string const & k, macro_definition_cell::reader rd) {
@ -133,7 +132,7 @@ static binder_info read_binder_info(deserializer & d) {
return binder_info(imp, cast, ctx, s_imp);
}
static name g_binder_name("a");
static name * g_binder_name = nullptr;
class expr_serializer : public object_serializer<expr, expr_hash_alloc, expr_eqp> {
typedef object_serializer<expr, expr_hash_alloc, expr_eqp> super;
@ -143,7 +142,7 @@ class expr_serializer : public object_serializer<expr, expr_hash_alloc, expr_eqp
void write_binder_name(serializer & s, name const & a) {
// make sure binding names are atomic string
if (!a.is_atomic() || a.is_numeral()) {
s << g_binder_name.append_after(m_next_id);
s << g_binder_name->append_after(m_next_id);
m_next_id++;
} else {
s << a;
@ -260,15 +259,15 @@ struct expr_sd {
m_d_extid = deserializer::register_extension([](){ return std::unique_ptr<deserializer::extension>(new expr_deserializer()); });
}
};
static expr_sd g_expr_sd;
static expr_sd * g_expr_sd = nullptr;
serializer & operator<<(serializer & s, expr const & n) {
s.get_extension<expr_serializer>(g_expr_sd.m_s_extid).write(n);
s.get_extension<expr_serializer>(g_expr_sd->m_s_extid).write(n);
return s;
}
expr read_expr(deserializer & d) {
return d.get_extension<expr_deserializer>(g_expr_sd.m_d_extid).read();
return d.get_extension<expr_deserializer>(g_expr_sd->m_d_extid).read();
}
// Declaration serialization
@ -359,13 +358,17 @@ inductive_decls read_inductive_decls(deserializer & d) {
return inductive_decls(ps, num_params, to_list(decls.begin(), decls.end()));
}
static register_macro_deserializer_fn
annotation_des_fn(get_annotation_opcode(),
[](deserializer & d, unsigned num, expr const * args) {
if (num != 1)
throw corrupted_stream_exception();
name k;
d >> k;
return mk_annotation(k, args[0]);
});
void initialize_kernel_serializer() {
g_level_sd = new level_sd();
g_macro_readers = new macro_readers();
g_binder_name = new name("a");
g_expr_sd = new expr_sd();
}
void finalize_kernel_serializer() {
delete g_expr_sd;
delete g_binder_name;
delete g_macro_readers;
delete g_level_sd;
}
}

View file

@ -26,15 +26,14 @@ serializer & operator<<(serializer & s, expr const & e);
expr read_expr(deserializer & d);
inline deserializer & operator>>(deserializer & d, expr & e) { e = read_expr(d); return d; }
void register_macro_deserializer(std::string const & k, macro_definition_cell::reader rd);
struct register_macro_deserializer_fn {
register_macro_deserializer_fn(std::string const & k, macro_definition_cell::reader rd) { register_macro_deserializer(k, rd); }
};
serializer & operator<<(serializer & s, declaration const & d);
declaration read_declaration(deserializer & d, module_idx midx);
typedef std::tuple<level_param_names, unsigned, list<inductive::inductive_decl>> inductive_decls;
serializer & operator<<(serializer & s, inductive_decls const & ds);
inductive_decls read_inductive_decls(deserializer & d);
void register_macro_deserializer(std::string const & k, macro_definition_cell::reader rd);
void initialize_kernel_serializer();
void finalize_kernel_serializer();
}

View file

@ -10,15 +10,17 @@ Author: Leonardo de Moura
#include "library/kernel_serializer.h"
namespace lean {
static name g_let_value("letv");
std::string const & get_let_value_opcode() {
static std::string g_let_value_opcode("LetV");
return g_let_value_opcode;
}
static name * g_let_value = nullptr;
static std::string * g_let_value_opcode = nullptr;
static atomic<unsigned> * g_next_let_value_id = nullptr;
static name * g_let = nullptr;
static std::string * g_let_opcode = nullptr;
std::string const & get_let_value_opcode() { return *g_let_value_opcode; }
std::string const & get_let_opcode() { return * g_let_opcode; }
static atomic<unsigned> g_next_let_value_id(0);
static unsigned next_let_value_id() {
return atomic_fetch_add_explicit(&g_next_let_value_id, 1u, memory_order_seq_cst);
return atomic_fetch_add_explicit(g_next_let_value_id, 1u, memory_order_seq_cst);
}
class let_value_definition_cell : public macro_definition_cell {
@ -29,7 +31,7 @@ class let_value_definition_cell : public macro_definition_cell {
}
public:
let_value_definition_cell():m_id(next_let_value_id()) {}
virtual name get_name() const { return g_let_value; }
virtual name get_name() const { return *g_let_value; }
virtual expr get_type(expr const & m, expr const * arg_types, extension_context &) const {
check_macro(m);
return arg_types[0];
@ -63,19 +65,6 @@ expr get_let_value_expr(expr const e) {
return macro_arg(e, 0);
}
static register_macro_deserializer_fn
let_value_des_fn(get_let_value_opcode(),
[](deserializer &, unsigned num, expr const * args) {
if (num != 1) throw corrupted_stream_exception();
return mk_let_value(args[0]);
});
static name g_let("let");
std::string const & get_let_opcode() {
static std::string g_let_opcode("Let");
return g_let_opcode;
}
class let_macro_definition_cell : public macro_definition_cell {
name m_var_name;
void check_macro(expr const & m) const {
@ -85,7 +74,7 @@ class let_macro_definition_cell : public macro_definition_cell {
public:
let_macro_definition_cell(name const & n):m_var_name(n) {}
name const & get_var_name() const { return m_var_name; }
virtual name get_name() const { return g_let; }
virtual name get_name() const { return *g_let; }
virtual expr get_type(expr const & m, expr const * arg_types, extension_context &) const {
check_macro(m);
return arg_types[1];
@ -125,12 +114,31 @@ expr const & get_let_body(expr const & e) {
return macro_arg(e, 1);
}
static register_macro_deserializer_fn
let_des_fn(get_let_opcode(),
[](deserializer & d, unsigned num, expr const * args) {
if (num != 2) throw corrupted_stream_exception();
name n;
d >> n;
return mk_let(n, args[0], args[1]);
});
void initialize_let() {
g_let_value = new name("letv");
g_let_value_opcode = new std::string("LetV");
g_next_let_value_id = new atomic<unsigned>(0);
register_macro_deserializer(*g_let_value_opcode,
[](deserializer &, unsigned num, expr const * args) {
if (num != 1) throw corrupted_stream_exception();
return mk_let_value(args[0]);
});
g_let = new name("let");
g_let_opcode = new std::string("Let");
register_macro_deserializer(*g_let_opcode,
[](deserializer & d, unsigned num, expr const * args) {
if (num != 2) throw corrupted_stream_exception();
name n;
d >> n;
return mk_let(n, args[0], args[1]);
});
}
void finalize_let() {
delete g_let_opcode;
delete g_let;
delete g_next_let_value_id;
delete g_let_value_opcode;
delete g_let_value;
}
}

View file

@ -17,4 +17,7 @@ bool is_let(expr const & e);
name const & get_let_var_name(expr const & e);
expr const & get_let_value(expr const & e);
expr const & get_let_body(expr const & e);
void initialize_let();
void finalize_let();
}

View file

@ -15,18 +15,17 @@ Author: Leonardo de Moura
#include "library/bin_app.h"
namespace lean {
static name g_resolve_macro_name("resolve");
static std::string g_resolve_opcode("Res");
static name * g_resolve_macro_name = nullptr;
static std::string * g_resolve_opcode = nullptr;
// Declarations used by the resolve_macro
static expr g_or(Const("or"));
static expr g_not(Const("not"));
static expr g_false(Const("false"));
static expr g_or_elim(Const(name("or", "elim")));
static expr g_or_intro_left(Const(name("or", "intro_left")));
static expr g_or_intro_right(Const(name("or", "intro_right")));
static expr g_absurd_elim(Const("absurd_elim"));
static expr g_var_0(mk_var(0));
static expr * g_or = nullptr;
static expr * g_not = nullptr;
static expr * g_false = nullptr;
static expr * g_or_elim = nullptr;
static expr * g_or_intro_left = nullptr;
static expr * g_or_intro_right = nullptr;
static expr * g_absurd_elim = nullptr;
static expr * g_var_0 = nullptr;
/**
\brief Resolve macro encodes a simple propositional resolution step.
It takes three arguments:
@ -68,7 +67,8 @@ class resolve_macro_definition_cell : public macro_definition_cell {
simple_delayed_justification m_dummy_jst;
public:
resolve_macro_definition_cell():m_dummy_jst([] { return mk_justification("resolve macro"); }) {
m_dummy_jst.get(); // the delayed_justification may be accessed by different threads, thus we force its initialization.
// the delayed_justification may be accessed by different threads, thus we force its initialization.
m_dummy_jst.get();
}
// The following const cast is say because we already initialized the delayed justification in the constructor.
@ -112,7 +112,7 @@ public:
return false;
}
bool is_or(expr const & a, expr & lhs, expr & rhs) const { return is_bin_app(a, g_or, lhs, rhs); }
bool is_or(expr const & a, expr & lhs, expr & rhs) const { return is_bin_app(a, *g_or, lhs, rhs); }
bool collect(expr const & lhs, expr const & rhs, expr const & l, buffer<expr> & R, extension_context & ctx) const {
bool r1 = collect(lhs, l, R, ctx);
@ -143,7 +143,7 @@ public:
environment const & env = ctx.env();
check_num_args(env, m);
expr l = whnf(macro_arg(m, 0), ctx);
expr not_l = whnf(g_not(l), ctx);
expr not_l = whnf(mk_app(*g_not, l), ctx);
expr C1 = arg_types[1];
expr C2 = arg_types[2];
buffer<expr> R; // resolvent
@ -151,7 +151,7 @@ public:
throw_kernel_exception(env, "invalid resolve macro, positive literal was not found", m);
if (!collect(C2, not_l, R, ctx))
throw_kernel_exception(env, "invalid resolve macro, negative literal was not found", m);
return mk_bin_rop(g_or, g_false, R.size(), R.data());
return mk_bin_rop(*g_or, *g_false, R.size(), R.data());
}
// End of resolve_macro get_type implementation
@ -166,7 +166,7 @@ public:
environment const & env = ctx.env();
check_num_args(env, m);
expr l = whnf(macro_arg(m, 0), ctx);
expr not_l = whnf(g_not(l), ctx);
expr not_l = whnf(mk_app(*g_not, l), ctx);
expr H1 = macro_arg(m, 1);
expr H2 = macro_arg(m, 2);
expr C1 = infer_type(H1, ctx);
@ -176,7 +176,7 @@ public:
return some_expr(mk_or_elim_tree1(l, not_l, C1, H1, C2, H2, R, ctx));
}
bool is_or_app(expr const & a) const { return is_bin_app(a, g_or); }
bool is_or_app(expr const & a) const { return is_bin_app(a, *g_or); }
/** \brief Given l : H, and R == (or ... l ...), create a proof term for R using or_intro_left and or_intro_right */
expr mk_or_intro(expr const & l, expr const & H, expr const & R, extension_context & ctx) const {
@ -187,11 +187,11 @@ public:
// or_intro_left {a : Prop} (H : a) (b : Prop) : a b
// or_intro_right {b : Prop} (a : Prop) (H : b) : a b
if (is_def_eq(l, lhs, ctx)) {
return g_or_intro_left(l, H, rhs);
return mk_app(*g_or_intro_left, l, H, rhs);
} else if (is_def_eq(l, rhs, ctx)) {
return g_or_intro_right(l, lhs, H);
return mk_app(*g_or_intro_right, l, lhs, H);
} else {
return g_or_intro_right(rhs, lhs, mk_or_intro(l, H, rhs, ctx));
return mk_app(*g_or_intro_right, rhs, lhs, mk_or_intro(l, H, rhs, ctx));
}
} else if (is_def_eq(l, R, ctx)) {
return H;
@ -242,9 +242,10 @@ public:
expr H2_1 = lift(H2);
expr R_1 = lift(R);
// or_elim {a b c : Prop} (H1 : a b) (H2 : a → c) (H3 : b → c) : c
return g_or_elim(lhs1, rhs1, R, H1,
mk_lambda("H2", lhs1, mk_or_elim_tree1(l_1, not_l_1, lhs1_1, g_var_0, C2_1, H2_1, R_1, ctx)),
mk_lambda("H3", rhs1, mk_or_elim_tree1(l_1, not_l_1, rhs1_1, g_var_0, C2_1, H2_1, R_1, ctx)));
return mk_app({*g_or_elim,
lhs1, rhs1, R, H1,
mk_lambda("H2", lhs1, mk_or_elim_tree1(l_1, not_l_1, lhs1_1, *g_var_0, C2_1, H2_1, R_1, ctx)),
mk_lambda("H3", rhs1, mk_or_elim_tree1(l_1, not_l_1, rhs1_1, *g_var_0, C2_1, H2_1, R_1, ctx))});
}
/**
@ -265,7 +266,7 @@ public:
return mk_or_elim_tree2(l, H, not_l, lhs, rhs, H2, R, ctx);
} else if (is_def_eq(C2, not_l, ctx)) {
// absurd_elim {a : Prop} (b : Prop) (H1 : a) (H2 : ¬ a) : b
return g_absurd_elim(l, R, H, H2);
return mk_app(*g_absurd_elim, l, R, H, H2);
} else {
return mk_or_intro(C2, H2, R, ctx);
}
@ -288,31 +289,58 @@ public:
expr rhs2_1 = lift(rhs2);
expr R_1 = lift(R);
// or_elim {a b c : Prop} (H1 : a b) (H2 : a → c) (H3 : b → c) : c
return g_or_elim(lhs2, rhs2, R, H2,
mk_lambda("H2", lhs2, mk_or_elim_tree2(l_1, H_1, not_l_1, lhs2_1, g_var_0, R_1, ctx)),
mk_lambda("H3", rhs2, mk_or_elim_tree2(l_1, H_1, not_l_1, rhs2_1, g_var_0, R_1, ctx)));
return mk_app({*g_or_elim,
lhs2, rhs2, R, H2,
mk_lambda("H2", lhs2, mk_or_elim_tree2(l_1, H_1, not_l_1, lhs2_1, *g_var_0, R_1, ctx)),
mk_lambda("H3", rhs2, mk_or_elim_tree2(l_1, H_1, not_l_1, rhs2_1, *g_var_0, R_1, ctx))});
}
virtual name get_name() const { return g_resolve_macro_name; }
virtual name get_name() const { return *g_resolve_macro_name; }
/** \brief Resolve is a very simple macro, we can trust its implementation most of the time. */
virtual unsigned trust_level() const { return 0; }
virtual void write(serializer & s) const { s.write_string(g_resolve_opcode); }
virtual void write(serializer & s) const { s.write_string(*g_resolve_opcode); }
};
static macro_definition g_resolve_macro_definition(new resolve_macro_definition_cell());
static macro_definition * g_resolve_macro_definition = nullptr;
expr mk_resolve_macro(expr const & l, expr const & H1, expr const & H2) {
expr args[3] = {l, H1, H2};
return mk_macro(g_resolve_macro_definition, 3, args);
return mk_macro(*g_resolve_macro_definition, 3, args);
}
static register_macro_deserializer_fn
resolve_macro_des_fn(g_resolve_opcode,
[](deserializer &, unsigned num, expr const * args) {
if (num != 3)
throw corrupted_stream_exception();
return mk_resolve_macro(args[0], args[1], args[2]);
});
void initialize_resolve_macro() {
g_resolve_macro_name = new name("resolve");
g_resolve_opcode = new std::string("Res");
g_or = new expr(Const("or"));
g_not = new expr(Const("not"));
g_false = new expr(Const("false"));
g_or_elim = new expr(Const(name("or", "elim")));
g_or_intro_left = new expr(Const(name("or", "intro_left")));
g_or_intro_right = new expr(Const(name("or", "intro_right")));
g_absurd_elim = new expr(Const("absurd_elim"));
g_var_0 = new expr(mk_var(0));
g_resolve_macro_definition = new macro_definition(new resolve_macro_definition_cell());
register_macro_deserializer(*g_resolve_opcode,
[](deserializer &, unsigned num, expr const * args) {
if (num != 3)
throw corrupted_stream_exception();
return mk_resolve_macro(args[0], args[1], args[2]);
});
}
void finalize_resolve_macro() {
delete g_resolve_macro_definition;
delete g_var_0;
delete g_absurd_elim;
delete g_or_intro_right;
delete g_or_intro_left;
delete g_or_elim;
delete g_false;
delete g_not;
delete g_or;
delete g_resolve_opcode;
delete g_resolve_macro_name;
}
static int mk_resolve_macro(lua_State * L) { return push_expr(L, mk_resolve_macro(to_expr(L, 1), to_expr(L, 2), to_expr(L, 3))); }
void open_resolve_macro(lua_State * L) { SET_GLOBAL_FUN(mk_resolve_macro, "resolve_macro"); }

View file

@ -11,4 +11,6 @@ Author: Leonardo de Moura
namespace lean {
expr mk_resolve_macro(expr const & l, expr const & H1, expr const & H2);
void open_resolve_macro(lua_State * L);
void initialize_resolve_macro();
void finalize_resolve_macro();
}

View file

@ -11,17 +11,16 @@ Author: Leonardo de Moura
#include "library/string.h"
namespace lean {
static name g_string_macro("string_macro");
static std::string g_string_opcode("Str");
static expr g_bool(Const(name("bool")));
static expr g_ff(Const(name("bool", "ff")));
static expr g_tt(Const(name("bool", "tt")));
static expr g_char(Const(name("char")));
static expr g_ascii(Const(name("char", "mk")));
static expr g_string(Const(name("string")));
static expr g_empty(Const(name("string", "empty")));
static expr g_str(Const(name("string", "str")));
static name * g_string_macro = nullptr;
static std::string * g_string_opcode = nullptr;
static expr * g_bool = nullptr;
static expr * g_ff = nullptr;
static expr * g_tt = nullptr;
static expr * g_char = nullptr;
static expr * g_ascii = nullptr;
static expr * g_string = nullptr;
static expr * g_empty = nullptr;
static expr * g_str = nullptr;
expr from_string_core(unsigned i, std::string const & s);
@ -33,9 +32,9 @@ public:
virtual bool lt(macro_definition_cell const & d) const {
return m_value < static_cast<string_macro const &>(d).m_value;
}
virtual name get_name() const { return g_string_macro; }
virtual name get_name() const { return *g_string_macro; }
virtual expr get_type(expr const &, expr const *, extension_context &) const {
return g_string;
return *g_string;
}
virtual optional<expr> expand(expr const &, extension_context &) const {
return some_expr(from_string_core(0, m_value));
@ -71,7 +70,7 @@ public:
}
virtual bool is_atomic_pp(bool, bool) const { return true; }
virtual unsigned hash() const { return std::hash<std::string>()(m_value); }
virtual void write(serializer & s) const { s << g_string_opcode << m_value; }
virtual void write(serializer & s) const { s << *g_string_opcode << m_value; }
std::string const & get_value() const { return m_value; }
};
@ -88,25 +87,49 @@ string_macro const & to_string_macro(expr const & e) {
return *static_cast<string_macro const *>(macro_def(e).raw());
}
static register_macro_deserializer_fn
string_macro_des_fn(g_string_opcode,
[](deserializer & d, unsigned num, expr const *) {
if (num != 0)
throw corrupted_stream_exception();
std::string v = d.read_string();
return mk_string_macro(v);
});
void initialize_string() {
g_string_macro = new name("string_macro");
g_string_opcode = new std::string("Str");
g_bool = new expr(Const(name("bool")));
g_ff = new expr(Const(name("bool", "ff")));
g_tt = new expr(Const(name("bool", "tt")));
g_char = new expr(Const(name("char")));
g_ascii = new expr(Const(name("char", "mk")));
g_string = new expr(Const(name("string")));
g_empty = new expr(Const(name("string", "empty")));
g_str = new expr(Const(name("string", "str")));
register_macro_deserializer(*g_string_opcode,
[](deserializer & d, unsigned num, expr const *) {
if (num != 0)
throw corrupted_stream_exception();
std::string v = d.read_string();
return mk_string_macro(v);
});
}
void finalize_string() {
delete g_str;
delete g_empty;
delete g_string;
delete g_ascii;
delete g_char;
delete g_tt;
delete g_ff;
delete g_bool;
delete g_string_opcode;
delete g_string_macro;
}
bool has_string_decls(environment const & env) {
try {
type_checker tc(env);
return
tc.infer(g_ff).first == g_bool &&
tc.infer(g_tt).first == g_bool &&
tc.infer(g_ascii).first == g_bool >> (g_bool >> (g_bool >> (g_bool >> (g_bool >> (g_bool >> (g_bool >> (g_bool >> g_char))))))) &&
tc.infer(g_empty).first == g_string &&
tc.infer(g_str).first == g_char >> (g_string >> g_string);
} catch (...) {
tc.infer(*g_ff).first == *g_bool &&
tc.infer(*g_tt).first == *g_bool &&
tc.infer(*g_ascii).first == *g_bool >> (*g_bool >> (*g_bool >> (*g_bool >> (*g_bool >> (*g_bool >> (*g_bool >> (*g_bool >> *g_char))))))) &&
tc.infer(*g_empty).first == *g_string &&
tc.infer(*g_str).first == *g_char >> (*g_string >> *g_string);
} catch (exception &) {
return false;
}
}
@ -115,21 +138,21 @@ expr from_char(unsigned char c) {
buffer<expr> bits;
while (c != 0) {
if (c % 2 == 1)
bits.push_back(g_tt);
bits.push_back(*g_tt);
else
bits.push_back(g_ff);
bits.push_back(*g_ff);
c /= 2;
}
while (bits.size() < 8)
bits.push_back(g_ff);
return mk_rev_app(g_ascii, bits.size(), bits.data());
bits.push_back(*g_ff);
return mk_rev_app(*g_ascii, bits.size(), bits.data());
}
expr from_string_core(unsigned i, std::string const & s) {
if (i == s.size())
return g_empty;
return *g_empty;
else
return mk_app(g_str, from_char(s[i]), from_string_core(i+1, s));
return mk_app(*g_str, from_char(s[i]), from_string_core(i+1, s));
}
expr from_string(std::string const & s) {
@ -138,13 +161,13 @@ expr from_string(std::string const & s) {
bool to_char_core(expr const & e, buffer<char> & tmp) {
buffer<expr> args;
if (get_app_rev_args(e, args) == g_ascii && args.size() == 8) {
if (get_app_rev_args(e, args) == *g_ascii && args.size() == 8) {
unsigned v = 0;
for (unsigned i = 0; i < args.size(); i++) {
v *= 2;
if (args[i] == g_tt)
if (args[i] == *g_tt)
v++;
else if (args[i] != g_ff)
else if (args[i] != *g_ff)
return false;
}
tmp.push_back(v);
@ -155,12 +178,12 @@ bool to_char_core(expr const & e, buffer<char> & tmp) {
}
bool to_string_core(expr const & e, buffer<char> & tmp) {
if (e == g_empty) {
if (e == *g_empty) {
return true;
} else {
buffer<expr> args;
return
get_app_args(e, args) == g_str &&
get_app_args(e, args) == *g_str &&
args.size() == 2 &&
to_char_core(args[0], tmp) &&
to_string_core(args[1], tmp);

View file

@ -36,4 +36,7 @@ expr from_string(std::string const & s);
\see from_string
*/
optional<std::string> to_string(expr const & e);
void initialize_string();
void finalize_string();
}

View file

@ -17,38 +17,39 @@ Author: Leonardo de Moura
namespace lean {
typedef std::unordered_map<name, expr_to_tactic_fn, name_hash, name_eq> expr_to_tactic_map;
static expr_to_tactic_map * g_map = nullptr;
expr_to_tactic_map & get_expr_to_tactic_map() {
static expr_to_tactic_map g_map;
return g_map;
return *g_map;
}
void register_expr_to_tactic(name const & n, expr_to_tactic_fn const & fn) {
void register_tac(name const & n, expr_to_tactic_fn const & fn) {
get_expr_to_tactic_map().insert(mk_pair(n, fn));
}
static name g_tac("tactic"), g_builtin_tac_name(g_tac, "builtin");
static name g_exact_tac_name(g_tac, "exact"), g_and_then_tac_name(g_tac, "and_then");
static name g_or_else_tac_name(g_tac, "or_else"), g_repeat_tac_name(g_tac, "repeat"), g_fixpoint_name(g_tac, "fixpoint");
static name g_determ_tac_name(g_tac, "determ");
static expr g_exact_tac_fn(Const(g_exact_tac_name)), g_and_then_tac_fn(Const(g_and_then_tac_name));
static expr g_or_else_tac_fn(Const(g_or_else_tac_name)), g_repeat_tac_fn(Const(g_repeat_tac_name));
static expr g_determ_tac_fn(Const(g_determ_tac_name));
static expr g_tac_type(Const(g_tac)), g_builtin_tac(Const(g_builtin_tac_name)), g_fixpoint_tac(Const(g_fixpoint_name));
expr const & get_exact_tac_fn() { return g_exact_tac_fn; }
expr const & get_and_then_tac_fn() { return g_and_then_tac_fn; }
expr const & get_or_else_tac_fn() { return g_or_else_tac_fn; }
expr const & get_determ_tac_fn() { return g_determ_tac_fn; }
expr const & get_repeat_tac_fn() { return g_repeat_tac_fn; }
expr const & get_tactic_type() { return g_tac_type; }
static expr * g_exact_tac_fn = nullptr;
static expr * g_and_then_tac_fn = nullptr;
static expr * g_or_else_tac_fn = nullptr;
static expr * g_repeat_tac_fn = nullptr;
static expr * g_determ_tac_fn = nullptr;
static expr * g_tac_type = nullptr;
static expr * g_builtin_tac = nullptr;
static expr * g_fixpoint_tac = nullptr;
expr const & get_exact_tac_fn() { return *g_exact_tac_fn; }
expr const & get_and_then_tac_fn() { return *g_and_then_tac_fn; }
expr const & get_or_else_tac_fn() { return *g_or_else_tac_fn; }
expr const & get_determ_tac_fn() { return *g_determ_tac_fn; }
expr const & get_repeat_tac_fn() { return *g_repeat_tac_fn; }
expr const & get_tactic_type() { return *g_tac_type; }
bool has_tactic_decls(environment const & env) {
try {
type_checker tc(env);
return
tc.infer(g_builtin_tac).first == g_tac_type &&
tc.infer(g_and_then_tac_fn).first == g_tac_type >> (g_tac_type >> g_tac_type) &&
tc.infer(g_or_else_tac_fn).first == g_tac_type >> (g_tac_type >> g_tac_type) &&
tc.infer(g_repeat_tac_fn).first == g_tac_type >> g_tac_type;
tc.infer(*g_builtin_tac).first == *g_tac_type &&
tc.infer(*g_and_then_tac_fn).first == *g_tac_type >> (*g_tac_type >> *g_tac_type) &&
tc.infer(*g_or_else_tac_fn).first == *g_tac_type >> (*g_tac_type >> *g_tac_type) &&
tc.infer(*g_repeat_tac_fn).first == *g_tac_type >> *g_tac_type;
} catch (exception &) {
return false;
}
@ -62,7 +63,7 @@ static void throw_failed(expr const & e) {
static bool is_builtin_tactic(expr const & v) {
if (is_lambda(v))
return is_builtin_tactic(binding_body(v));
else if (v == g_builtin_tac)
else if (v == *g_builtin_tac)
return true;
else
return false;
@ -107,13 +108,13 @@ tactic expr_to_tactic(type_checker & tc, expr e, pos_info_provider const * p) {
}
}
static name g_tmp_prefix = name::mk_internal_unique_name();
static name * g_tmp_prefix = nullptr;
MK_THREAD_LOCAL_GET(unsigned, get_expr_tac_id, 0)
static name_generator next_name_generator() {
unsigned & c = get_expr_tac_id();
unsigned r = c;
c++;
return name_generator(name(g_tmp_prefix, r));
return name_generator(name(*g_tmp_prefix, r));
}
tactic expr_to_tactic(environment const & env, expr const & e, pos_info_provider const * p) {
@ -127,16 +128,16 @@ tactic fixpoint(expr const & b) {
});
}
register_simple_tac::register_simple_tac(name const & n, std::function<tactic()> f) {
register_expr_to_tactic(n, [=](type_checker &, expr const & e, pos_info_provider const *) {
void register_simple_tac(name const & n, std::function<tactic()> const & f) {
register_tac(n, [=](type_checker &, expr const & e, pos_info_provider const *) {
if (!is_constant(e))
throw expr_to_tactic_exception(e, "invalid constant tactic");
return f();
});
}
register_bin_tac::register_bin_tac(name const & n, std::function<tactic(tactic const &, tactic const &)> f) {
register_expr_to_tactic(n, [=](type_checker & tc, expr const & e, pos_info_provider const * p) {
void register_bin_tac(name const & n, std::function<tactic(tactic const &, tactic const &)> const & f) {
register_tac(n, [=](type_checker & tc, expr const & e, pos_info_provider const * p) {
buffer<expr> args;
get_app_args(e, args);
if (args.size() != 2)
@ -146,8 +147,8 @@ register_bin_tac::register_bin_tac(name const & n, std::function<tactic(tactic c
});
}
register_unary_tac::register_unary_tac(name const & n, std::function<tactic(tactic const &)> f) {
register_expr_to_tactic(n, [=](type_checker & tc, expr const & e, pos_info_provider const * p) {
void register_unary_tac(name const & n, std::function<tactic(tactic const &)> const & f) {
register_tac(n, [=](type_checker & tc, expr const & e, pos_info_provider const * p) {
buffer<expr> args;
get_app_args(e, args);
if (args.size() != 1)
@ -156,8 +157,8 @@ register_unary_tac::register_unary_tac(name const & n, std::function<tactic(tact
});
}
register_unary_num_tac::register_unary_num_tac(name const & n, std::function<tactic(tactic const &, unsigned k)> f) {
register_expr_to_tactic(n, [=](type_checker & tc, expr const & e, pos_info_provider const * p) {
void register_unary_num_tac(name const & n, std::function<tactic(tactic const &, unsigned k)> const & f) {
register_tac(n, [=](type_checker & tc, expr const & e, pos_info_provider const * p) {
buffer<expr> args;
get_app_args(e, args);
if (args.size() != 2)
@ -174,64 +175,103 @@ register_unary_num_tac::register_unary_num_tac(name const & n, std::function<tac
});
}
static register_simple_tac reg_id(name(g_tac, "id"), []() { return id_tactic(); });
static register_simple_tac reg_now(name(g_tac, "now"), []() { return now_tactic(); });
static register_simple_tac reg_assumption(name(g_tac, "assumption"), []() { return assumption_tactic(); });
static register_simple_tac reg_eassumption(name(g_tac, "eassumption"), []() { return eassumption_tactic(); });
static register_simple_tac reg_fail(name(g_tac, "fail"), []() { return fail_tactic(); });
static register_simple_tac reg_beta(name(g_tac, "beta"), []() { return beta_tactic(); });
static register_bin_tac reg_then(g_and_then_tac_name, [](tactic const & t1, tactic const & t2) { return then(t1, t2); });
static register_bin_tac reg_append(name(g_tac, "append"), [](tactic const & t1, tactic const & t2) { return append(t1, t2); });
static register_bin_tac reg_interleave(name(g_tac, "interleave"), [](tactic const & t1, tactic const & t2) { return interleave(t1, t2); });
static register_bin_tac reg_par(name(g_tac, "par"), [](tactic const & t1, tactic const & t2) { return par(t1, t2); });
static register_bin_tac reg_orelse(g_or_else_tac_name, [](tactic const & t1, tactic const & t2) { return orelse(t1, t2); });
static register_unary_tac reg_repeat(g_repeat_tac_name, [](tactic const & t1) { return repeat(t1); });
static register_tac reg_state(name(g_tac, "state"), [](type_checker &, expr const & e, pos_info_provider const * p) {
if (p)
if (auto it = p->get_pos_info(e))
return trace_state_tactic(std::string(p->get_file_name()), *it);
return trace_state_tactic();
});
static register_tac reg_trace(name(g_tac, "trace"), [](type_checker & tc, expr const & e, pos_info_provider const *) {
buffer<expr> args;
get_app_args(e, args);
if (args.size() != 1)
throw expr_to_tactic_exception(e, "invalid trace tactic, argument expected");
if (auto str = to_string(args[0]))
return trace_tactic(*str);
else if (auto str = to_string(tc.whnf(args[0]).first))
return trace_tactic(*str);
else
throw expr_to_tactic_exception(e, "invalid trace tactic, string value expected");
});
static register_tac reg_apply(name(g_tac, "apply"), [](type_checker &, expr const & e, pos_info_provider const *) {
return apply_tactic(app_arg(e));
});
static register_tac reg_exact(g_exact_tac_name, [](type_checker &, expr const & e, pos_info_provider const *) {
return exact_tactic(app_arg(e));
});
static register_tac reg_unfold(name(g_tac, "unfold"), [](type_checker &, expr const & e, pos_info_provider const *) {
expr id = get_app_fn(app_arg(e));
if (!is_constant(id))
return fail_tactic();
else
return unfold_tactic(const_name(id));
});
static register_unary_num_tac reg_at_most(name(g_tac, "at_most"), [](tactic const & t, unsigned k) { return take(t, k); });
static register_unary_num_tac reg_discard(name(g_tac, "discard"), [](tactic const & t, unsigned k) { return discard(t, k); });
static register_unary_num_tac reg_focus_at(name(g_tac, "focus_at"), [](tactic const & t, unsigned k) { return focus(t, k); });
static register_unary_num_tac reg_try_for(name(g_tac, "try_for"), [](tactic const & t, unsigned k) { return try_for(t, k); });
static register_tac reg_fixpoint(g_fixpoint_name, [](type_checker & tc, expr const & e, pos_info_provider const *) {
if (!is_constant(app_fn(e)))
throw expr_to_tactic_exception(e, "invalid fixpoint tactic, it must have one argument");
expr r = tc.whnf(mk_app(app_arg(e), e)).first;
return fixpoint(r);
});
static name * g_by_name = nullptr;
static name g_by_name("by");
register_annotation_fn g_by_annotation(g_by_name);
expr mk_by(expr const & e) { return mk_annotation(g_by_name, e); }
bool is_by(expr const & e) { return is_annotation(e, g_by_name); }
expr mk_by(expr const & e) { return mk_annotation(*g_by_name, e); }
bool is_by(expr const & e) { return is_annotation(e, *g_by_name); }
expr const & get_by_arg(expr const & e) { lean_assert(is_by(e)); return get_annotation_arg(e); }
void initialize_expr_to_tactic() {
g_tmp_prefix = new name(name::mk_internal_unique_name());
g_by_name = new name("by");
register_annotation(*g_by_name);
g_map = new expr_to_tactic_map();
name g_tac("tactic");
name g_builtin_tac_name(g_tac, "builtin");
name g_exact_tac_name(g_tac, "exact");
name g_and_then_tac_name(g_tac, "and_then");
name g_or_else_tac_name(g_tac, "or_else");
name g_repeat_tac_name(g_tac, "repeat");
name g_fixpoint_name(g_tac, "fixpoint");
name g_determ_tac_name(g_tac, "determ");
g_exact_tac_fn = new expr(Const(g_exact_tac_name));
g_and_then_tac_fn = new expr(Const(g_and_then_tac_name));
g_or_else_tac_fn = new expr(Const(g_or_else_tac_name));
g_repeat_tac_fn = new expr(Const(g_repeat_tac_name));
g_determ_tac_fn = new expr(Const(g_determ_tac_name));
g_tac_type = new expr(Const(g_tac));
g_builtin_tac = new expr(Const(g_builtin_tac_name));
g_fixpoint_tac = new expr(Const(g_fixpoint_name));
register_simple_tac(name(g_tac, "id"), []() { return id_tactic(); });
register_simple_tac(name(g_tac, "now"), []() { return now_tactic(); });
register_simple_tac(name(g_tac, "assumption"), []() { return assumption_tactic(); });
register_simple_tac(name(g_tac, "eassumption"), []() { return eassumption_tactic(); });
register_simple_tac(name(g_tac, "fail"), []() { return fail_tactic(); });
register_simple_tac(name(g_tac, "beta"), []() { return beta_tactic(); });
register_bin_tac(g_and_then_tac_name, [](tactic const & t1, tactic const & t2) { return then(t1, t2); });
register_bin_tac(name(g_tac, "append"), [](tactic const & t1, tactic const & t2) { return append(t1, t2); });
register_bin_tac(name(g_tac, "interleave"), [](tactic const & t1, tactic const & t2) { return interleave(t1, t2); });
register_bin_tac(name(g_tac, "par"), [](tactic const & t1, tactic const & t2) { return par(t1, t2); });
register_bin_tac(g_or_else_tac_name, [](tactic const & t1, tactic const & t2) { return orelse(t1, t2); });
register_unary_tac(g_repeat_tac_name, [](tactic const & t1) { return repeat(t1); });
register_tac(name(g_tac, "state"), [](type_checker &, expr const & e, pos_info_provider const * p) {
if (p)
if (auto it = p->get_pos_info(e))
return trace_state_tactic(std::string(p->get_file_name()), *it);
return trace_state_tactic();
});
register_tac(name(g_tac, "trace"), [](type_checker & tc, expr const & e, pos_info_provider const *) {
buffer<expr> args;
get_app_args(e, args);
if (args.size() != 1)
throw expr_to_tactic_exception(e, "invalid trace tactic, argument expected");
if (auto str = to_string(args[0]))
return trace_tactic(*str);
else if (auto str = to_string(tc.whnf(args[0]).first))
return trace_tactic(*str);
else
throw expr_to_tactic_exception(e, "invalid trace tactic, string value expected");
});
register_tac(name(g_tac, "apply"), [](type_checker &, expr const & e, pos_info_provider const *) {
return apply_tactic(app_arg(e));
});
register_tac(g_exact_tac_name, [](type_checker &, expr const & e, pos_info_provider const *) {
return exact_tactic(app_arg(e));
});
register_tac(name(g_tac, "unfold"), [](type_checker &, expr const & e, pos_info_provider const *) {
expr id = get_app_fn(app_arg(e));
if (!is_constant(id))
return fail_tactic();
else
return unfold_tactic(const_name(id));
});
register_unary_num_tac(name(g_tac, "at_most"), [](tactic const & t, unsigned k) { return take(t, k); });
register_unary_num_tac(name(g_tac, "discard"), [](tactic const & t, unsigned k) { return discard(t, k); });
register_unary_num_tac(name(g_tac, "focus_at"), [](tactic const & t, unsigned k) { return focus(t, k); });
register_unary_num_tac(name(g_tac, "try_for"), [](tactic const & t, unsigned k) { return try_for(t, k); });
register_tac(g_fixpoint_name, [](type_checker & tc, expr const & e, pos_info_provider const *) {
if (!is_constant(app_fn(e)))
throw expr_to_tactic_exception(e, "invalid fixpoint tactic, it must have one argument");
expr r = tc.whnf(mk_app(app_arg(e), e)).first;
return fixpoint(r);
});
}
void finalize_expr_to_tactic() {
delete g_fixpoint_tac;
delete g_builtin_tac;
delete g_tac_type;
delete g_determ_tac_fn;
delete g_repeat_tac_fn;
delete g_or_else_tac_fn;
delete g_and_then_tac_fn;
delete g_exact_tac_fn;
delete g_map;
delete g_by_name;
delete g_tmp_prefix;
}
}

View file

@ -57,21 +57,12 @@ public:
typedef std::function<tactic(type_checker & tc, expr const & e, pos_info_provider const *)> expr_to_tactic_fn;
/** \brief Register a new "procedural attachment" for expr_to_tactic. */
void register_expr_to_tactic(name const & n, expr_to_tactic_fn const & fn);
void register_tac(name const & n, expr_to_tactic_fn const & fn);
void register_simple_tac(name const & n, std::function<tactic()> const & f);
void register_bin_tac(name const & n, std::function<tactic(tactic const &, tactic const &)> const & f);
void register_unary_tac(name const & n, std::function<tactic(tactic const &)> const & f);
void register_unary_num_tac(name const & n, std::function<tactic(tactic const &, unsigned)> const & f);
struct register_tac {
register_tac(name const & n, expr_to_tactic_fn fn) { register_expr_to_tactic(n, fn); }
};
struct register_simple_tac {
register_simple_tac(name const & n, std::function<tactic()> f);
};
struct register_bin_tac {
register_bin_tac(name const & n, std::function<tactic(tactic const &, tactic const &)> f);
};
struct register_unary_tac {
register_unary_tac(name const & n, std::function<tactic(tactic const &)> f);
};
struct register_unary_num_tac {
register_unary_num_tac(name const & n, std::function<tactic(tactic const &, unsigned)> f);
};
void initialize_expr_to_tactic();
void finalize_expr_to_tactic();
}

View file

@ -5,13 +5,16 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
*/
#include "library/tactic/proof_state.h"
#include "library/tactic/expr_to_tactic.h"
namespace lean {
void initialize_tactic_module() {
initialize_proof_state();
initialize_expr_to_tactic();
}
void finalize_tactic_module() {
finalize_expr_to_tactic();
finalize_proof_state();
}
}

View file

@ -8,16 +8,12 @@ Author: Leonardo de Moura
#include "library/kernel_serializer.h"
namespace lean {
name const & get_typed_expr_name() {
static name g_typed_expr("typed_expr");
return g_typed_expr;
}
std::string const & get_typed_expr_opcode() {
static std::string g_typed_expr_opcode("TyE");
return g_typed_expr_opcode;
}
static name * g_typed_expr_name = nullptr;
static std::string * g_typed_expr_opcode = nullptr;
static macro_definition * g_typed_expr = nullptr;
name const & get_typed_expr_name() { return *g_typed_expr_name; }
std::string const & get_typed_expr_opcode() { return *g_typed_expr_opcode; }
/** \brief This macro is used to "enforce" a given type to an expression.
It is equivalent to
@ -51,24 +47,33 @@ public:
}
};
static macro_definition g_typed_expr(new typed_expr_macro_definition_cell());
bool is_typed_expr(expr const & e) {
return is_macro(e) && macro_def(e) == g_typed_expr;
return is_macro(e) && macro_def(e) == *g_typed_expr;
}
expr mk_typed_expr(expr const & t, expr const & v) {
expr args[2] = {t, v};
return mk_macro(g_typed_expr, 2, args);
return mk_macro(*g_typed_expr, 2, args);
}
expr get_typed_expr_type(expr const & e) { lean_assert(is_typed_expr(e)); return macro_arg(e, 0); }
expr get_typed_expr_expr(expr const & e) { lean_assert(is_typed_expr(e)); return macro_arg(e, 1); }
static register_macro_deserializer_fn
typed_expr_macro_des_fn(get_typed_expr_opcode(), [](deserializer &, unsigned num, expr const * args) {
if (num != 2)
throw corrupted_stream_exception();
return mk_typed_expr(args[0], args[1]);
});
void initialize_typed_expr() {
g_typed_expr_name = new name("typed_expr");
g_typed_expr_opcode = new std::string("TyE");
g_typed_expr = new macro_definition(new typed_expr_macro_definition_cell());
register_macro_deserializer(*g_typed_expr_opcode,
[](deserializer &, unsigned num, expr const * args) {
if (num != 2)
throw corrupted_stream_exception();
return mk_typed_expr(args[0], args[1]);
});
}
void finalize_typed_expr() {
delete g_typed_expr;
delete g_typed_expr_opcode;
delete g_typed_expr_name;
}
}

View file

@ -22,4 +22,7 @@ expr get_typed_expr_type(expr const & e);
\remark get_typed_expr_type(mk_typed_expr(t, e)) == e
*/
expr get_typed_expr_expr(expr const & e);
void initialize_typed_expr();
void finalize_typed_expr();
}

View file

@ -10,11 +10,15 @@ Author: Leonardo de Moura
#include <vector>
#include <limits>
#include "util/test.h"
#include "util/init_module.h"
#include "util/sexpr/init_module.h"
#include "kernel/expr.h"
#include "kernel/expr_sets.h"
#include "kernel/free_vars.h"
#include "kernel/abstract.h"
#include "kernel/instantiate.h"
#include "kernel/init_module.h"
#include "library/init_module.h"
#include "library/max_sharing.h"
#include "library/print.h"
#include "library/deep_copy.h"
@ -363,6 +367,10 @@ static void tst18() {
int main() {
save_stack_info();
initialize_util_module();
initialize_sexpr_module();
initialize_kernel_module();
initialize_library_module();
init_default_print_fn();
lean_assert(sizeof(expr) == sizeof(optional<expr>));
tst1();
@ -392,5 +400,9 @@ int main() {
std::cout << "sizeof(optional<sexpr>): " << sizeof(optional<sexpr>) << "\n";
std::cout << "sizeof(std::function): " << sizeof(std::function<expr(expr const &, optional<expr> const &)>) << "\n";
std::cout << "done" << "\n";
finalize_library_module();
finalize_kernel_module();
finalize_sexpr_module();
finalize_util_module();
return has_violations() ? 1 : 0;
}

View file

@ -7,8 +7,12 @@ Author: Leonardo de Moura
#include <locale>
#include "util/test.h"
#include "util/exception.h"
#include "util/init_module.h"
#include "util/sexpr/init_module.h"
#include "kernel/init_module.h"
#include "kernel/level.h"
#include "library/kernel_serializer.h"
#include "library/init_module.h"
using namespace lean;
static void check_serializer(level const & l) {
@ -63,7 +67,15 @@ static void tst2() {
int main() {
save_stack_info();
initialize_util_module();
initialize_sexpr_module();
initialize_kernel_module();
initialize_library_module();
tst1();
tst2();
finalize_library_module();
finalize_kernel_module();
finalize_sexpr_module();
finalize_util_module();
return has_violations() ? 1 : 0;
}

View file

@ -10,6 +10,7 @@ Author: Soonho Kong
#include <utility>
#include <string>
#include "util/test.h"
#include "util/init_module.h"
#include "util/numerics/mpq.h"
#include "util/sexpr/format.h"
#include "util/sexpr/sexpr_fn.h"
@ -127,6 +128,7 @@ static void tst6() {
int main() {
save_stack_info();
initialize_util_module();
initialize_sexpr_module();
tst1();
tst2();
@ -135,5 +137,6 @@ int main() {
tst5();
tst6();
finalize_sexpr_module();
finalize_util_module();
return has_violations() ? 1 : 0;
}

View file

@ -7,6 +7,7 @@ Author: Leonardo de Moura
#include <cstring>
#include <sstream>
#include "util/test.h"
#include "util/init_module.h"
#include "util/sexpr/options.h"
#include "util/sexpr/option_declarations.h"
#include "util/sexpr/init_module.h"
@ -155,6 +156,7 @@ static void tst6() {
int main() {
save_stack_info();
initialize_util_module();
initialize_sexpr_module();
name fakeopt("fakeopt");
register_bool_option(fakeopt, false, "fake option");
@ -167,5 +169,6 @@ int main() {
tst6();
finalize_sexpr_module();
finalize_util_module();
return has_violations() ? 1 : 0;
}

View file

@ -16,6 +16,7 @@ Author: Leonardo de Moura
#include "util/debug.h"
#include "util/list.h"
#include "util/name.h"
#include "util/init_module.h"
using namespace lean;
template<typename T>
@ -66,15 +67,15 @@ struct list_int_initializer {
}
};
static list_int_initializer g_list_int_initializer;
std::unique_ptr<list_int_initializer> g_list_int_initializer;
serializer & operator<<(serializer & s, list<int> const & l) {
s.get_extension<list_int_serializer>(g_list_int_initializer.m_serializer_extid).write(l);
s.get_extension<list_int_serializer>(g_list_int_initializer->m_serializer_extid).write(l);
return s;
}
deserializer & operator>>(deserializer & d, list<int> & l) {
l = d.get_extension<list_int_deserializer>(g_list_int_initializer.m_deserializer_extid).read();
l = d.get_extension<list_int_deserializer>(g_list_int_initializer->m_deserializer_extid).read();
return d;
}
@ -171,9 +172,13 @@ static void tst4() {
}
int main() {
save_stack_info();
initialize_util_module();
g_list_int_initializer.reset(new list_int_initializer());
tst1();
tst2();
tst3();
tst4();
finalize_util_module();
return has_violations() ? 1 : 0;
}

View file

@ -8,6 +8,7 @@ Author: Leonardo de Moura
#include <string>
#include "util/test.h"
#include "util/name.h"
#include "util/init_module.h"
#include "util/numerics/mpq.h"
#include "util/sexpr/sexpr.h"
#include "util/sexpr/sexpr_fn.h"
@ -240,6 +241,7 @@ static void tst10() {
int main() {
save_stack_info();
initialize_util_module();
initialize_sexpr_module();
tst1();
tst2();
@ -252,5 +254,6 @@ int main() {
tst9();
tst10();
finalize_sexpr_module();
finalize_util_module();
return has_violations() ? 1 : 0;
}

View file

@ -10,6 +10,7 @@ add_library(util trace.cpp debug.cpp name.cpp name_set.cpp
realpath.cpp script_state.cpp script_exception.cpp rb_map.cpp
lua.cpp luaref.cpp lua_named_param.cpp stackinfo.cpp lean_path.cpp
serializer.cpp lbool.cpp thread_script_state.cpp bitap_fuzzy_search.cpp
init_module.cpp
${THREAD_CPP})
target_link_libraries(util ${LEAN_LIBS})

View file

@ -49,13 +49,10 @@ public:
}
};
static std::unique_ptr<extension_factory> g_extension_factory;
static extension_factory & get_extension_factory() {
if (!g_extension_factory)
g_extension_factory.reset(new extension_factory());
return *g_extension_factory;
}
static extension_factory * g_extension_factory;
static void initialize() { g_extension_factory = new extension_factory(); }
static void finalize() { delete g_extension_factory; }
static extension_factory & get_extension_factory() { return *g_extension_factory; }
static unsigned register_extension(mk_extension mk) {
return get_extension_factory().register_extension(mk);
@ -79,5 +76,6 @@ public:
}
};
template<typename T>
std::unique_ptr<typename extensible_object<T>::extension_factory> extensible_object<T>::g_extension_factory;
typename extensible_object<T>::extension_factory *
extensible_object<T>::g_extension_factory = nullptr;
}

19
src/util/init_module.cpp Normal file
View file

@ -0,0 +1,19 @@
/*
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 "util/serializer.h"
#include "util/name.h"
namespace lean {
void initialize_util_module() {
initialize_serializer();
initialize_name();
}
void finalize_util_module() {
finalize_name();
finalize_serializer();
}
}

12
src/util/init_module.h Normal file
View file

@ -0,0 +1,12 @@
/*
Copyright (c) 2014 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 {
void initialize_util_module();
void finalize_util_module();
}

View file

@ -477,15 +477,23 @@ struct name_sd {
m_deserializer_extid = deserializer::register_extension([](){ return std::unique_ptr<deserializer::extension>(new name_deserializer()); });
}
};
static name_sd g_name_sd;
static name_sd * g_name_sd = nullptr;
void initialize_name() {
g_name_sd = new name_sd();
}
void finalize_name() {
delete g_name_sd;
}
serializer & operator<<(serializer & s, name const & n) {
s.get_extension<name_serializer>(g_name_sd.m_serializer_extid).write(n);
s.get_extension<name_serializer>(g_name_sd->m_serializer_extid).write(n);
return s;
}
name read_name(deserializer & d) {
return d.get_extension<name_deserializer>(g_name_sd.m_deserializer_extid).read();
return d.get_extension<name_deserializer>(g_name_sd->m_deserializer_extid).read();
}
DECL_UDATA(name)

View file

@ -196,4 +196,6 @@ list<name> & to_list_name(lua_State * L, int idx);
list<name> to_list_name_ext(lua_State * L, int idx);
int push_list_name(lua_State * L, list<name> const & l);
void open_name(lua_State * L);
void initialize_name();
void finalize_name();
}

View file

@ -1,5 +1,5 @@
/*
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
Copyright (c) 2013-2014 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura
@ -14,9 +14,7 @@ Author: Leonardo de Moura
#endif
namespace lean {
/**
\brief Helper class for serializing objects.
*/
/** \brief Helper class for serializing objects. */
template<class T, class HashFn, class EqFn>
class object_serializer : public serializer::extension {
std::unordered_map<T, unsigned, HashFn, EqFn> m_table;
@ -43,9 +41,7 @@ public:
}
};
/**
\brief Helper class for deserializing objects.
*/
/** \brief Helper class for deserializing objects. */
template<class T>
class object_deserializer : public deserializer::extension {
std::vector<T> m_table;

View file

@ -12,6 +12,16 @@ Author: Leonardo de Moura
#include "util/exception.h"
namespace lean {
void initialize_serializer() {
serializer::initialize();
deserializer::initialize();
}
void finalize_serializer() {
deserializer::finalize();
serializer::finalize();
}
void serializer_core::write_unsigned(unsigned i) {
static_assert(sizeof(i) == 4, "unexpected unsigned size");
m_out.put((i >> 24) & 0xff);

View file

@ -71,6 +71,9 @@ public:
corrupted_stream_exception();
};
void initialize_serializer();
void finalize_serializer();
template<typename T>
serializer & write_list(serializer & s, list<T> const & ls) {
s << length(ls);

View file

@ -10,6 +10,7 @@ Author: Leonardo de Moura
namespace lean {
void initialize_sexpr_module() {
initialize_sexpr();
initialize_option_declarations();
initialize_options();
initialize_format();
@ -19,5 +20,6 @@ void finalize_sexpr_module() {
finalize_format();
finalize_options();
finalize_option_declarations();
finalize_sexpr();
}
}

View file

@ -370,15 +370,23 @@ struct sexpr_sd {
m_d_extid = deserializer::register_extension([](){ return std::unique_ptr<deserializer::extension>(new sexpr_deserializer()); });
}
};
static sexpr_sd g_sexpr_sd;
static sexpr_sd * g_sexpr_sd = nullptr;
void initialize_sexpr() {
g_sexpr_sd = new sexpr_sd();
}
void finalize_sexpr() {
delete g_sexpr_sd;
}
serializer & operator<<(serializer & s, sexpr const & n) {
s.get_extension<sexpr_serializer>(g_sexpr_sd.m_s_extid).write(n);
s.get_extension<sexpr_serializer>(g_sexpr_sd->m_s_extid).write(n);
return s;
}
sexpr read_sexpr(deserializer & d) {
return d.get_extension<sexpr_deserializer>(g_sexpr_sd.m_d_extid).read();
return d.get_extension<sexpr_deserializer>(g_sexpr_sd->m_d_extid).read();
}
DECL_UDATA(sexpr)

View file

@ -186,4 +186,6 @@ inline deserializer & operator>>(deserializer & d, sexpr & a) { a = read_sexpr(d
UDATA_DEFS(sexpr)
void open_sexpr(lua_State * L);
void initialize_sexpr();
void finalize_sexpr();
}