/* 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 #include #include #include "runtime/sstream.h" #include "util/name_hash_map.h" #include "library/abstract_type_context.h" #include "library/annotation.h" #include "library/pos_info_provider.h" namespace lean { static name * g_annotation = nullptr; kvmap mk_annotation_kvmap(name const & k) { return set_name(kvmap(), *g_annotation, k); } typedef name_hash_map annotation_maps; static annotation_maps * g_annotation_maps = nullptr; void register_annotation(name const & kind) { lean_assert(g_annotation_maps->find(kind) == g_annotation_maps->end()); g_annotation_maps->insert(mk_pair(kind, mk_annotation_kvmap(kind))); } optional is_annotation(expr const & e) { expr e2 = unwrap_pos(e); if (is_mdata(e2) && get_name(mdata_data(e2), *g_annotation)) return some_expr(e2); else return none_expr(); } name get_annotation_kind(expr const & e) { auto o = is_annotation(e); lean_assert(o); return *get_name(mdata_data(*o), *g_annotation); } bool is_annotation(expr const & e, name const & kind) { auto o = is_annotation(e); return o && get_annotation_kind(*o) == kind; } expr const & get_annotation_arg(expr const & e) { auto o = is_annotation(e); lean_assert(o); return mdata_expr(*o); } expr mk_annotation(name const & kind, expr const & e) { auto it = g_annotation_maps->find(kind); if (it != g_annotation_maps->end()) { expr r = mk_mdata(it->second, e); lean_assert(is_annotation(r)); lean_assert(get_annotation_kind(r) == kind); return r; } else { throw exception(sstream() << "unknown annotation kind '" << kind << "'"); } } bool is_nested_annotation(expr const & e, name const & kind) { expr const * it = &e; while (is_annotation(*it)) { if (get_annotation_kind(*it) == kind) return true; it = &get_annotation_arg(*it); } return false; } expr const & get_nested_annotation_arg(expr const & e) { expr const * it = &e; while (is_annotation(*it)) it = &get_annotation_arg(*it); return *it; } expr copy_annotations(expr const & from, expr const & to) { buffer trace; expr const * it = &from; while (is_annotation(*it)) { trace.push_back(*it); it = &get_annotation_arg(*it); } expr r = to; unsigned i = trace.size(); while (i > 0) { --i; r = mk_annotation(get_annotation_kind(trace[i]), r); } return r; } static name * g_have = nullptr; static name * g_show = nullptr; static name * g_suffices = nullptr; static name * g_checkpoint = 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_suffices_annotation(expr const & e) { return mk_annotation(*g_suffices, e); } expr mk_checkpoint_annotation(expr const & e) { return mk_annotation(*g_checkpoint, 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_suffices_annotation(expr const & e) { return is_annotation(e, *g_suffices); } bool is_checkpoint_annotation(expr const & e) { return is_annotation(e, *g_checkpoint); } void initialize_annotation() { g_annotation = new name("annotation"); g_annotation_maps = new annotation_maps(); g_have = new name("have"); g_show = new name("show"); g_suffices = new name("suffices"); g_checkpoint = new name("checkpoint"); register_annotation(*g_have); register_annotation(*g_show); register_annotation(*g_suffices); register_annotation(*g_checkpoint); } void finalize_annotation() { delete g_checkpoint; delete g_show; delete g_have; delete g_suffices; delete g_annotation; } }