2014-01-18 10:47:11 +00:00
|
|
|
/*
|
|
|
|
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
|
2014-01-27 23:02:05 +00:00
|
|
|
#include <memory>
|
2014-01-18 10:47:11 +00:00
|
|
|
#include "util/lua.h"
|
|
|
|
#include "kernel/environment.h"
|
2014-01-29 04:30:47 +00:00
|
|
|
#include "kernel/metavar.h"
|
2014-01-18 10:47:11 +00:00
|
|
|
#include "library/expr_pair.h"
|
2014-01-27 02:52:41 +00:00
|
|
|
#include "library/simplifier/rewrite_rule_set.h"
|
2014-01-18 10:47:11 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2014-01-27 23:02:05 +00:00
|
|
|
class simplifier_monitor;
|
|
|
|
|
|
|
|
/** \brief Simplifier object cell. */
|
|
|
|
class simplifier_cell {
|
|
|
|
friend class simplifier;
|
2014-01-28 07:29:53 +00:00
|
|
|
class imp;
|
2014-01-27 23:02:05 +00:00
|
|
|
std::unique_ptr<imp> m_ptr;
|
|
|
|
public:
|
2014-01-29 20:01:01 +00:00
|
|
|
/**
|
|
|
|
\brief Simplification result
|
|
|
|
*/
|
|
|
|
class result {
|
|
|
|
friend class imp;
|
|
|
|
expr m_expr; // new expression
|
|
|
|
optional<expr> m_proof; // a proof that the m_expr is equal to the input (when m_proofs_enabled)
|
|
|
|
bool m_heq_proof; // true if the proof has type lhs == rhs (i.e., it is a heterogeneous equality)
|
|
|
|
explicit result(expr const & out, bool heq_proof = false):m_expr(out), m_heq_proof(heq_proof) {}
|
|
|
|
result(expr const & out, expr const & pr, bool heq_proof = false):m_expr(out), m_proof(pr), m_heq_proof(heq_proof) {}
|
|
|
|
result(expr const & out, optional<expr> const & pr, bool heq_proof = false):
|
|
|
|
m_expr(out), m_proof(pr), m_heq_proof(heq_proof) {}
|
|
|
|
result update_expr(expr const & new_e) const { return result(new_e, m_proof, m_heq_proof); }
|
|
|
|
result update_proof(expr const & new_pr) const { return result(m_expr, new_pr, m_heq_proof); }
|
|
|
|
public:
|
|
|
|
result() {}
|
|
|
|
expr get_expr() const { return m_expr; }
|
|
|
|
optional<expr> get_proof() const { return m_proof; }
|
|
|
|
bool is_heq_proof() const { return m_heq_proof; }
|
|
|
|
};
|
|
|
|
|
2014-01-27 23:02:05 +00:00
|
|
|
simplifier_cell(ro_environment const & env, options const & o, unsigned num_rs, rewrite_rule_set const * rs,
|
|
|
|
std::shared_ptr<simplifier_monitor> const & monitor);
|
2014-01-30 02:32:40 +00:00
|
|
|
result operator()(expr const & e, optional<ro_metavar_env> const & menv);
|
2014-01-27 23:02:05 +00:00
|
|
|
void clear();
|
|
|
|
|
|
|
|
unsigned get_depth() const;
|
|
|
|
ro_environment const & get_environment() const;
|
|
|
|
options const & get_options() const;
|
|
|
|
};
|
|
|
|
|
|
|
|
/** \brief Reference to simplifier object */
|
|
|
|
class simplifier {
|
|
|
|
friend class ro_simplifier;
|
|
|
|
std::shared_ptr<simplifier_cell> m_ptr;
|
|
|
|
public:
|
2014-01-29 20:01:01 +00:00
|
|
|
typedef simplifier_cell::result result;
|
2014-01-27 23:02:05 +00:00
|
|
|
simplifier(ro_environment const & env, options const & o, unsigned num_rs, rewrite_rule_set const * rs,
|
|
|
|
std::shared_ptr<simplifier_monitor> const & monitor);
|
|
|
|
simplifier_cell * operator->() const { return m_ptr.get(); }
|
|
|
|
simplifier_cell & operator*() const { return *(m_ptr.get()); }
|
2014-01-30 02:32:40 +00:00
|
|
|
result operator()(expr const & e, optional<ro_metavar_env> const & menv) {
|
|
|
|
return (*m_ptr)(e, menv);
|
2014-01-29 04:30:47 +00:00
|
|
|
}
|
2014-01-27 23:02:05 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
/** \brief Read only reference to simplifier object */
|
|
|
|
class ro_simplifier {
|
|
|
|
std::shared_ptr<simplifier_cell const> m_ptr;
|
|
|
|
public:
|
|
|
|
typedef std::weak_ptr<simplifier_cell const> weak_ref;
|
|
|
|
ro_simplifier(simplifier const & s);
|
|
|
|
ro_simplifier(weak_ref const & s);
|
|
|
|
explicit operator weak_ref() const { return weak_ref(m_ptr); }
|
|
|
|
weak_ref to_weak_ref() const { return weak_ref(m_ptr); }
|
|
|
|
simplifier_cell const * operator->() const { return m_ptr.get(); }
|
|
|
|
simplifier_cell const & operator*() const { return *(m_ptr.get()); }
|
|
|
|
};
|
|
|
|
|
2014-01-27 19:46:28 +00:00
|
|
|
/**
|
|
|
|
\brief Abstract class that specifies the interface for monitoring
|
|
|
|
the behavior of the simplifier.
|
|
|
|
*/
|
|
|
|
class simplifier_monitor {
|
|
|
|
public:
|
2014-01-27 23:02:05 +00:00
|
|
|
virtual ~simplifier_monitor() {}
|
2014-01-27 19:46:28 +00:00
|
|
|
/**
|
|
|
|
\brief This method is invoked to sign that the simplifier is starting to process the expression \c e.
|
|
|
|
*/
|
2014-01-27 23:02:05 +00:00
|
|
|
virtual void pre_eh(ro_simplifier const & s, expr const & e) = 0;
|
2014-01-27 19:46:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief This method is invoked to sign that \c e has be rewritten into \c new_e with proof \c pr.
|
|
|
|
The proof is none if proof generation is disabled or if \c e and \c new_e are definitionally equal.
|
|
|
|
*/
|
2014-01-27 23:02:05 +00:00
|
|
|
virtual void step_eh(ro_simplifier const & s, expr const & e, expr const & new_e, optional<expr> const & pr) = 0;
|
2014-01-27 19:46:28 +00:00
|
|
|
/**
|
|
|
|
\brief This method is invoked to sign that \c e has be rewritten into \c new_e using the conditional equation \c ceq.
|
|
|
|
*/
|
2014-01-27 23:02:05 +00:00
|
|
|
virtual void rewrite_eh(ro_simplifier const & s, expr const & e, expr const & new_e, expr const & ceq, name const & ceq_id) = 0;
|
2014-01-27 19:46:28 +00:00
|
|
|
|
|
|
|
enum class failure_kind { Unsupported, TypeMismatch, AssumptionNotProved, MissingArgument, PermutationGe, AbstractionBody };
|
|
|
|
|
|
|
|
/**
|
|
|
|
\brief This method is invoked when the simplifier fails to rewrite an application \c e.
|
|
|
|
\c i is the argument where the simplifier gave up, and \c k is the reason for failure.
|
|
|
|
Two possible values are: Unsupported or TypeMismatch (may happen when simplifying terms that use dependent types).
|
|
|
|
*/
|
2014-01-27 23:02:05 +00:00
|
|
|
virtual void failed_app_eh(ro_simplifier const & s, expr const & e, unsigned i, failure_kind k) = 0;
|
2014-01-27 19:46:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief This method is invoked when the simplifier fails to apply a conditional equation \c ceq to \c e.
|
|
|
|
The \c ceq may have several arguments, the value \c i is the argument where the simplifier gave up, and \c k is the reason for failure.
|
|
|
|
The possible failure values are: AssumptionNotProved (failed to synthesize a proof for an assumption required by \c ceq),
|
|
|
|
MissingArgument (failed to infer one of the arguments needed by the conditional equation), PermutationGe
|
|
|
|
(the conditional equation is a permutation, and the result is not smaller in the term ordering, \c i is irrelevant in this case).
|
|
|
|
*/
|
2014-01-27 23:02:05 +00:00
|
|
|
virtual void failed_rewrite_eh(ro_simplifier const & s, expr const & e, expr const & ceq, name const & ceq_id, unsigned i, failure_kind k) = 0;
|
2014-01-27 19:46:28 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief This method is invoked when the simplifier fails to simplify an abstraction (Pi or Lambda).
|
|
|
|
The possible failure values are: Unsupported, TypeMismatch, and AbstractionBody (failed to rewrite the body of the abstraction,
|
|
|
|
this may happen when we are using dependent types).
|
|
|
|
*/
|
2014-01-27 23:02:05 +00:00
|
|
|
virtual void failed_abstraction_eh(ro_simplifier const & s, expr const & e, failure_kind k) = 0;
|
2014-01-27 19:46:28 +00:00
|
|
|
};
|
|
|
|
|
2014-01-29 03:36:31 +00:00
|
|
|
class simplifier_stack_space_exception : public stack_space_exception {
|
|
|
|
public:
|
|
|
|
simplifier_stack_space_exception();
|
|
|
|
virtual char const * what() const noexcept;
|
|
|
|
virtual exception * clone() const;
|
|
|
|
virtual void rethrow() const;
|
|
|
|
};
|
|
|
|
|
2014-01-30 02:32:40 +00:00
|
|
|
simplifier::result simplify(expr const & e, ro_environment const & env, options const & pts,
|
2014-01-29 20:01:01 +00:00
|
|
|
unsigned num_rs, rewrite_rule_set const * rs,
|
|
|
|
optional<ro_metavar_env> const & menv = none_ro_menv(),
|
|
|
|
std::shared_ptr<simplifier_monitor> const & monitor = std::shared_ptr<simplifier_monitor>());
|
2014-01-30 02:32:40 +00:00
|
|
|
simplifier::result simplify(expr const & e, ro_environment const & env, options const & opts,
|
2014-01-29 20:01:01 +00:00
|
|
|
unsigned num_ns, name const * ns,
|
|
|
|
optional<ro_metavar_env> const & menv = none_ro_menv(),
|
|
|
|
std::shared_ptr<simplifier_monitor> const & monitor = std::shared_ptr<simplifier_monitor>());
|
2014-01-18 10:47:11 +00:00
|
|
|
void open_simplifier(lua_State * L);
|
2014-01-31 21:49:24 +00:00
|
|
|
/**
|
|
|
|
\brief Associate the given simplifier monitor with the lua_State object \c L.
|
|
|
|
*/
|
|
|
|
void set_global_simplifier_monitor(lua_State * L, std::shared_ptr<simplifier_monitor> const & monitor);
|
|
|
|
/**
|
|
|
|
\brief Return the simplifier monitor associated with the given lua_State.
|
|
|
|
The result is nullptr if the lua_State object does not have a monitor associated with it.
|
|
|
|
*/
|
|
|
|
std::shared_ptr<simplifier_monitor> get_global_simplifier_monitor(lua_State * L);
|
|
|
|
/**
|
|
|
|
\brief Return a simplifier object at position \c i on the Lua stack. If there is a nil stored
|
|
|
|
on this position of the stack, then return \c get_global_simplifier_monitor.
|
|
|
|
|
|
|
|
\remark This procedure throws an exception if the object stored at position \c i not a
|
|
|
|
simplifier monitor nor nil.
|
|
|
|
*/
|
|
|
|
std::shared_ptr<simplifier_monitor> get_simplifier_monitor(lua_State * L, int i);
|
2014-01-18 10:47:11 +00:00
|
|
|
}
|