/* Copyright (c) 2016 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Leonardo de Moura */ #include #include "util/sstream.h" #include "util/name_set.h" #include "util/fresh_name.h" #include "util/thread.h" #include "util/shared_mutex.h" namespace lean { static name_set * g_fresh_name_prefixes = nullptr; static shared_mutex * g_fresh_name_prefixes_guard = nullptr; static void register_fresh_name_prefix(name const & p) { exclusive_lock lock(*g_fresh_name_prefixes_guard); g_fresh_name_prefixes->insert(p); } MK_THREAD_LOCAL_GET_DEF(name, get_prefix); LEAN_THREAD_VALUE(unsigned, g_next_idx, 0); static bool is_fresh_prefix(name const & p) { if (p == get_prefix()) return true; shared_lock lock(*g_fresh_name_prefixes_guard); return g_fresh_name_prefixes->contains(p); }; name mk_fresh_name() { name & prefix = get_prefix(); if (prefix.is_anonymous()) { // prefix has not been initialized for this thread yet. prefix = name::mk_internal_unique_name(); register_fresh_name_prefix(prefix); } if (g_next_idx == std::numeric_limits::max()) { // avoid overflow prefix = name(prefix, g_next_idx); register_fresh_name_prefix(prefix); g_next_idx = 0; } name r(prefix, g_next_idx); g_next_idx++; return r; } bool is_fresh_name(name const & n) { if (n.is_anonymous() || !n.is_numeral()) return false; else if (is_fresh_prefix(n.get_prefix())) return true; else return is_fresh_name(n.get_prefix()); } static void sanitize_fresh(sstream & strm, name const & n) { if (n.is_anonymous()) { strm << "_fresh"; } else if (n.is_numeral()) { sanitize_fresh(strm, n.get_prefix()); strm << "_" << n.get_numeral(); } else { lean_unreachable(); } } name sanitize_if_fresh(name const & n) { if (!is_fresh_name(n)) return n; sstream strm; sanitize_fresh(strm, n); return name(strm.str()); } name mk_tagged_fresh_name(name const & tag) { lean_assert(tag.is_atomic()); name & prefix = get_prefix(); if (prefix.is_anonymous()) { // prefix has not been initialized for this thread yet. prefix = name::mk_internal_unique_name(); } if (g_next_idx == std::numeric_limits::max()) { // avoid overflow prefix = name(prefix, g_next_idx); g_next_idx = 0; } name r(tag + prefix, g_next_idx); g_next_idx++; return r; } bool is_tagged_by(name const & n, name const & tag) { lean_assert(tag.is_atomic()); if (n.is_atomic()) return false; name t = n; while (!t.is_atomic()) t = t.get_prefix(); return t == tag; } /* A tagged name is of the form tag.unique_id.suffix */ optional get_tagged_name_suffix(name const & n, name const & tag) { if (n.is_atomic()) { return optional(); } else if (n.get_prefix() == tag) { return optional(name()); } else if (auto new_prefix = get_tagged_name_suffix(n.get_prefix(), tag)) { if (n.is_string()) { return optional(name(*new_prefix, n.get_string())); } else { return optional(name(*new_prefix, n.get_numeral())); } } else { return optional(); } } void initialize_fresh_name() { g_fresh_name_prefixes = new name_set(); g_fresh_name_prefixes_guard = new shared_mutex(); } void finalize_fresh_name() { delete g_fresh_name_prefixes; delete g_fresh_name_prefixes_guard; } }