diff --git a/src/kernel/context.cpp b/src/kernel/context.cpp index 5504d1fca3..13a2d25447 100644 --- a/src/kernel/context.cpp +++ b/src/kernel/context.cpp @@ -31,6 +31,17 @@ context_entry const & context::lookup(unsigned i) const { throw exception("unknown free variable"); } +optional context::find(unsigned i) const { + list const * it1 = &m_list; + while (*it1) { + if (i == 0) + return some(head(*it1)); + --i; + it1 = &tail(*it1); + } + return optional(); +} + static list remove_core(list const & l, unsigned s, unsigned n) { if (s == 0) { if (n > 0) { diff --git a/src/kernel/context.h b/src/kernel/context.h index 803efdf494..1813eb1830 100644 --- a/src/kernel/context.h +++ b/src/kernel/context.h @@ -44,6 +44,8 @@ public: explicit context(list const & l):m_list(l) {} context_entry const & lookup(unsigned vidx) const; std::pair lookup_ext(unsigned vidx) const; + /** \brief Similar to lookup, but always succeed */ + optional find(unsigned vidx) const; bool empty() const { return is_nil(m_list); } explicit operator bool() const { return !empty(); } unsigned size() const { return length(m_list); } @@ -75,6 +77,7 @@ inline std::pair lookup_ext(context const & c, u Bruijn index \c i. */ inline context_entry const & lookup(context const & c, unsigned i) { return c.lookup(i); } +inline optional find(context const & c, unsigned i) { return c.find(i); } inline context extend(context const & c, name const & n, optional const & d, expr const & b) { return context(c, n, d, b); } inline context extend(context const & c, name const & n, expr const & d, optional const & b) { return context(c, n, d, b); } inline context extend(context const & c, name const & n, expr const & d, expr const & b) { return context(c, n, d, b); } diff --git a/src/kernel/printer.cpp b/src/kernel/printer.cpp index 3aca989d69..92750420c1 100644 --- a/src/kernel/printer.cpp +++ b/src/kernel/printer.cpp @@ -99,13 +99,14 @@ struct print_expr_fn { case expr_kind::MetaVar: print_metavar(a, c); break; - case expr_kind::Var: - try { - out() << lookup(c, var_idx(a)).get_name(); - } catch (exception & ex) { + case expr_kind::Var: { + auto e = find(c, var_idx(a)); + if (e) + out() << e->get_name(); + else out() << "#" << var_idx(a); - } break; + } case expr_kind::Constant: out() << const_name(a); break; diff --git a/src/library/elaborator/elaborator.cpp b/src/library/elaborator/elaborator.cpp index a745a74a7a..21452085d5 100644 --- a/src/library/elaborator/elaborator.cpp +++ b/src/library/elaborator/elaborator.cpp @@ -513,12 +513,9 @@ class elaborator::imp { /** \brief Replace variables by their definition if the context contains it. */ void process_var(context const & ctx, expr & a) { if (is_var(a)) { - try { - context_entry const & e = lookup(ctx, var_idx(a)); - if (e.get_body()) - a = *(e.get_body()); - } catch (exception&) { - } + auto e = find(ctx, var_idx(a)); + if (e && e->get_body()) + a = *(e->get_body()); } } @@ -652,13 +649,8 @@ class elaborator::imp { /** \brief Return true iff the variable with id \c vidx has a body/definition in the context \c ctx. */ static bool has_body(context const & ctx, unsigned vidx) { - try { - context_entry const & e = lookup(ctx, vidx); - if (e.get_body()) - return true; - } catch (exception&) { - } - return false; + auto e = find(ctx, vidx); + return e && e->get_body(); } /**