/* 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 #include #include #include "util/sstream.h" #include "library/attribute_manager.h" namespace lean { struct attribute_decl { std::string m_id; std::string m_descr; std::string m_token; has_attribute_proc m_tester; }; struct default_attribute_decl : public attribute_decl { set_attribute_proc m_setter; }; struct prioritized_attribute_decl : public attribute_decl { set_prio_attribute_proc m_setter; get_attribute_prio_proc m_getter; }; struct param_attribute_decl : public attribute_decl { set_param_attribute_proc m_setter; get_attribute_param_proc m_getter; }; struct opt_param_attribute_decl : public attribute_decl { set_opt_param_attribute_proc m_setter; get_attribute_param_proc m_getter; }; struct params_attribute_decl : public attribute_decl { set_params_attribute_proc m_setter; get_attribute_params_proc m_getter; }; static std::vector * g_default_attrs = nullptr; static std::vector * g_prio_attrs = nullptr; static std::vector * g_param_attrs = nullptr; static std::vector * g_opt_param_attrs = nullptr; static std::vector * g_params_attrs = nullptr; static std::vector> * g_incomp = nullptr; template bool is_attribute(Decls const & decls, char const * attr) { for (auto const & d : decls) { if (d.m_id == attr) return true; } return false; } bool is_attribute(char const * attr) { return is_attribute(*g_default_attrs, attr) || is_attribute(*g_prio_attrs, attr) || is_attribute(*g_param_attrs, attr) || is_attribute(*g_opt_param_attrs, attr) || is_attribute(*g_params_attrs, attr); } template void set_core_fields(Decl & decl, char const * attr, char const * descr, Setter const & setter, Tester const & tester) { decl.m_id = attr; decl.m_descr = descr; decl.m_setter = setter; decl.m_tester = tester; } void register_attribute(char const * attr, char const * descr, set_attribute_proc const & setter, has_attribute_proc const & tester) { lean_assert(!is_attribute(attr)); default_attribute_decl decl; set_core_fields(decl, attr, descr, setter, tester); decl.m_token = std::string("[") + attr + "]"; g_default_attrs->push_back(decl); } void register_prio_attribute(char const * attr, char const * descr, set_prio_attribute_proc const & setter, has_attribute_proc const & tester, get_attribute_prio_proc const & getter) { lean_assert(!is_attribute(attr)); prioritized_attribute_decl decl; set_core_fields(decl, attr, descr, setter, tester); decl.m_token = std::string("[") + attr + "]"; decl.m_getter = getter; g_prio_attrs->push_back(decl); } void register_param_attribute(char const * attr, char const * descr, set_param_attribute_proc const & setter, has_attribute_proc const & tester, get_attribute_param_proc const & getter) { lean_assert(!is_attribute(attr)); param_attribute_decl decl; set_core_fields(decl, attr, descr, setter, tester); decl.m_token = std::string("[") + attr; decl.m_getter = getter; g_param_attrs->push_back(decl); } void register_opt_param_attribute(char const * attr, char const * descr, set_opt_param_attribute_proc const & setter, has_attribute_proc const & tester, get_attribute_param_proc const & getter) { lean_assert(!is_attribute(attr)); opt_param_attribute_decl decl; set_core_fields(decl, attr, descr, setter, tester); decl.m_token = std::string("[") + attr; decl.m_getter = getter; g_opt_param_attrs->push_back(decl); } void register_params_attribute(char const * attr, char const * descr, set_params_attribute_proc const & setter, has_attribute_proc const & tester, get_attribute_params_proc const & getter) { lean_assert(!is_attribute(attr)); params_attribute_decl decl; set_core_fields(decl, attr, descr, setter, tester); decl.m_token = std::string("[") + attr; decl.m_getter = getter; g_params_attrs->push_back(decl); } void register_incompatible(char const * attr1, char const * attr2) { lean_assert(is_attribute(attr1)); lean_assert(is_attribute(attr2)); std::string s1(attr1); std::string s2(attr2); if (s1 > s2) std::swap(s1, s2); g_incomp->emplace_back(s1, s2); } template void get_attributes(Decls const & decls, buffer & r) { for (auto const & d : decls) r.push_back(d.m_id.c_str()); } void get_attributes(buffer & r) { get_attributes(*g_default_attrs, r); get_attributes(*g_prio_attrs, r); get_attributes(*g_param_attrs, r); get_attributes(*g_opt_param_attrs, r); get_attributes(*g_params_attrs, r); } template void get_attribute_tokens(Decls const & decls, buffer & r) { for (auto const & d : decls) r.push_back(d.m_token.c_str()); } void get_attribute_tokens(buffer & r) { get_attribute_tokens(*g_default_attrs, r); get_attribute_tokens(*g_prio_attrs, r); get_attribute_tokens(*g_param_attrs, r); get_attribute_tokens(*g_opt_param_attrs, r); get_attribute_tokens(*g_params_attrs, r); } template char const * get_attribute_from_token(Decls const & decls, char const * tk) { for (auto const & d : decls) { if (d.m_token == tk) return d.m_id.c_str(); } return nullptr; } char const * get_attribute_from_token(char const * tk) { if (auto r = get_attribute_from_token(*g_default_attrs, tk)) return r; if (auto r = get_attribute_from_token(*g_prio_attrs, tk)) return r; if (auto r = get_attribute_from_token(*g_param_attrs, tk)) return r; if (auto r = get_attribute_from_token(*g_opt_param_attrs, tk)) return r; if (auto r = get_attribute_from_token(*g_params_attrs, tk)) return r; return nullptr; } attribute_kind get_attribute_kind (char const * attr) { lean_assert(is_attribute(attr)); if (is_attribute(*g_default_attrs, attr)) return attribute_kind::Default; if (is_attribute(*g_prio_attrs, attr)) return attribute_kind::Prioritized; if (is_attribute(*g_param_attrs, attr)) return attribute_kind::Parametric; if (is_attribute(*g_opt_param_attrs, attr)) return attribute_kind::OptParametric; if (is_attribute(*g_params_attrs, attr)) return attribute_kind::MultiParametric; lean_unreachable(); } template bool has_attribute(Decls const & decls, environment const & env, char const * attr, name const & d) { for (auto const & decl : decls) { if (decl.m_id == attr) return decl.m_tester(env, d); } return false; } bool has_attribute(environment const & env, char const * attr, name const & d) { return has_attribute(*g_default_attrs, env, attr, d) || has_attribute(*g_prio_attrs, env, attr, d) || has_attribute(*g_param_attrs, env, attr, d) || has_attribute(*g_opt_param_attrs, env, attr, d) || has_attribute(*g_params_attrs, env, attr, d); } [[ noreturn ]] void throw_unknown_attribute(char const * attr) { throw exception(sstream() << "unknown attribute '" << attr << "'"); } environment set_attribute(environment const & env, io_state const & ios, char const * attr, name const & d, name const & ns, bool persistent) { for (auto const & decl : *g_default_attrs) { if (decl.m_id == attr) return decl.m_setter(env, ios, d, ns, persistent); } throw_unknown_attribute(attr); } environment set_attribute(environment const & env, io_state const & ios, char const * attr, name const & d, unsigned prio, name const & ns, bool persistent) { for (auto const & decl : *g_prio_attrs) { if (decl.m_id == attr) return decl.m_setter(env, ios, d, prio, ns, persistent); } throw_unknown_attribute(attr); } environment set_attribute(environment const & env, io_state const & ios, char const * attr, name const & d, unsigned const & param, name const & ns, bool persistent) { for (auto const & decl : *g_param_attrs) { if (decl.m_id == attr) return decl.m_setter(env, ios, d, param, ns, persistent); } throw_unknown_attribute(attr); } environment set_attribute(environment const & env, io_state const & ios, char const * attr, name const & d, optional const & param, name const & ns, bool persistent) { for (auto const & decl : *g_opt_param_attrs) { if (decl.m_id == attr) return decl.m_setter(env, ios, d, param, ns, persistent); } throw_unknown_attribute(attr); } environment set_attribute(environment const & env, io_state const & ios, char const * attr, name const & d, list const & params, name const & ns, bool persistent) { for (auto const & decl : *g_params_attrs) { if (decl.m_id == attr) return decl.m_setter(env, ios, d, params, ns, persistent); } throw_unknown_attribute(attr); } unsigned get_attribute_prio(environment const & env, char const * attr, name const & d) { for (auto const & decl : *g_prio_attrs) { if (decl.m_id == attr) return decl.m_getter(env, d); } throw_unknown_attribute(attr); } unsigned get_attribute_param(environment const & env, char const * attr, name const & d) { for (auto const & decl : *g_param_attrs) { if (decl.m_id == attr) return decl.m_getter(env, d); } for (auto const & decl : *g_opt_param_attrs) { if (decl.m_id == attr) return decl.m_getter(env, d); } throw_unknown_attribute(attr); } list get_attribute_params(environment const & env, char const * attr, name const & d) { for (auto const & decl : *g_params_attrs) { if (decl.m_id == attr) return decl.m_getter(env, d); } throw_unknown_attribute(attr); } bool are_incompatible(char const * attr1, char const * attr2) { std::string s1(attr1); std::string s2(attr2); if (s1 > s2) std::swap(s1, s2); return std::find(g_incomp->begin(), g_incomp->end(), mk_pair(s1, s2)) != g_incomp->end(); } void initialize_attribute_manager() { g_default_attrs = new std::vector(); g_prio_attrs = new std::vector(); g_param_attrs = new std::vector(); g_opt_param_attrs = new std::vector(); g_params_attrs = new std::vector(); g_incomp = new std::vector>(); } void finalize_attribute_manager() { delete g_default_attrs; delete g_prio_attrs; delete g_param_attrs; delete g_opt_param_attrs; delete g_params_attrs; } }