2013-11-21 01:02:41 +00:00
|
|
|
/*
|
2014-06-28 01:42:59 +00:00
|
|
|
Copyright (c) 2013-2014 Microsoft Corporation. All rights reserved.
|
2013-11-21 01:02:41 +00:00
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <algorithm>
|
2013-11-22 02:39:33 +00:00
|
|
|
#include <utility>
|
2013-11-21 18:44:53 +00:00
|
|
|
#include <memory>
|
2013-11-23 23:33:25 +00:00
|
|
|
#include <string>
|
2013-11-22 02:39:33 +00:00
|
|
|
#include "util/lazy_list.h"
|
2014-06-28 01:35:59 +00:00
|
|
|
#include "library/io_state.h"
|
2015-02-17 00:56:42 +00:00
|
|
|
#include "library/generic_exception.h"
|
2013-11-21 01:02:41 +00:00
|
|
|
#include "library/tactic/proof_state.h"
|
|
|
|
|
|
|
|
namespace lean {
|
2014-07-03 01:32:44 +00:00
|
|
|
/** \brief Throw an exception is \c v contains local constants, \c e is only used for position information. */
|
|
|
|
void check_has_no_local(expr const & v, expr const & e, char const * tac_name);
|
|
|
|
|
2015-02-17 00:56:42 +00:00
|
|
|
class tactic_exception : public generic_exception {
|
|
|
|
optional<proof_state> m_ps;
|
2014-07-02 21:09:01 +00:00
|
|
|
public:
|
2015-02-17 00:56:42 +00:00
|
|
|
tactic_exception(char const * msg, optional<expr> const & m, pp_fn const & fn);
|
|
|
|
tactic_exception(char const * msg, optional<expr> const & m, proof_state const & ps, pp_fn const & fn);
|
|
|
|
tactic_exception(expr const & e, std::string const & msg);
|
2014-07-02 21:09:01 +00:00
|
|
|
tactic_exception(expr const & e, char const * msg);
|
|
|
|
tactic_exception(expr const & e, sstream const & strm);
|
2015-02-17 00:56:42 +00:00
|
|
|
tactic_exception(expr const & e, pp_fn const & fn);
|
|
|
|
tactic_exception(std::string const & msg);
|
|
|
|
tactic_exception(char const * msg);
|
|
|
|
tactic_exception(sstream const & strm);
|
|
|
|
tactic_exception(pp_fn const & fn);
|
|
|
|
optional<proof_state> const & get_proof_state() const { return m_ps; }
|
2014-07-02 21:09:01 +00:00
|
|
|
};
|
|
|
|
|
2015-02-17 00:56:42 +00:00
|
|
|
#define throw_tactic_exception_if_enabled(ps, msg) if (ps.report_failure()) throw tactic_exception(msg);
|
|
|
|
void throw_no_goal_if_enabled(proof_state const & ps);
|
|
|
|
|
2013-11-22 02:39:33 +00:00
|
|
|
typedef lazy_list<proof_state> proof_state_seq;
|
2013-11-21 18:44:53 +00:00
|
|
|
|
2014-11-27 17:15:49 +00:00
|
|
|
typedef std::function<proof_state_seq(environment const &, io_state const &, proof_state const &)> tactic;
|
2013-11-21 01:02:41 +00:00
|
|
|
|
2013-12-08 23:00:16 +00:00
|
|
|
inline optional<tactic> none_tactic() { return optional<tactic>(); }
|
2014-06-28 01:35:59 +00:00
|
|
|
inline optional<tactic> some_tactic(tactic const & t) { return optional<tactic>(t); }
|
|
|
|
inline optional<tactic> some_tactic(tactic && t) { return optional<tactic>(std::forward<tactic>(t)); }
|
2013-11-23 23:53:45 +00:00
|
|
|
|
2014-06-28 01:35:59 +00:00
|
|
|
template<typename F> inline proof_state_seq mk_proof_state_seq(F && f) { return mk_lazy_list<proof_state>(std::forward<F>(f)); }
|
2013-11-23 23:53:45 +00:00
|
|
|
|
2014-06-29 18:07:06 +00:00
|
|
|
tactic tactic01(std::function<optional<proof_state>(environment const &, io_state const & ios, proof_state const &)> f);
|
|
|
|
tactic tactic1(std::function<proof_state(environment const &, io_state const & ios, proof_state const &)> f);
|
2013-11-25 00:29:04 +00:00
|
|
|
|
2014-06-28 01:35:59 +00:00
|
|
|
/** \brief Return a "do nothing" tactic (aka skip). */
|
2013-11-21 23:31:55 +00:00
|
|
|
tactic id_tactic();
|
2014-06-28 01:35:59 +00:00
|
|
|
/** \brief Return a tactic the always fails. */
|
2013-11-21 23:31:55 +00:00
|
|
|
tactic fail_tactic();
|
2014-06-28 01:35:59 +00:00
|
|
|
/** \brief Return a tactic that fails if there are unsolved goals. */
|
2013-11-21 23:31:55 +00:00
|
|
|
tactic now_tactic();
|
2014-06-28 01:35:59 +00:00
|
|
|
/** \brief Return a tactic that performs \c t1 followed by \c t2. */
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic then(tactic const & t1, tactic const & t2);
|
|
|
|
inline tactic operator<<(tactic const & t1, tactic const & t2) { return then(t1, t2); }
|
2014-06-28 01:35:59 +00:00
|
|
|
/** \brief Return a tactic that applies \c t1, and if \c t1 returns the empty sequence of states, then applies \c t2. */
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic orelse(tactic const & t1, tactic const & t2);
|
|
|
|
inline tactic operator||(tactic const & t1, tactic const & t2) { return orelse(t1, t2); }
|
2015-05-06 03:03:00 +00:00
|
|
|
inline tactic try_tactic(tactic const & t) { return orelse(t, id_tactic()); }
|
2014-06-28 01:35:59 +00:00
|
|
|
/** \brief Return a tactic that appies \c t, but using the additional set of options \c opts. */
|
2013-11-25 00:29:04 +00:00
|
|
|
tactic using_params(tactic const & t, options const & opts);
|
2013-11-23 00:15:03 +00:00
|
|
|
/**
|
|
|
|
\brief Return a tactic that tries the tactic \c t for at most \c ms milliseconds.
|
|
|
|
If the tactic does not terminate in \c ms milliseconds, then the empty
|
|
|
|
sequence is returned.
|
|
|
|
|
|
|
|
\remark the tactic \c t is executed in a separate execution thread.
|
|
|
|
|
|
|
|
\remark \c check_ms is how often the main thread checks whether the child
|
|
|
|
thread finished.
|
|
|
|
*/
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic try_for(tactic const & t, unsigned ms, unsigned check_ms = 1);
|
2013-11-23 00:15:03 +00:00
|
|
|
/**
|
|
|
|
\brief Execute both tactics and and combines their results.
|
|
|
|
The results produced by tactic \c t1 are listed before the ones
|
|
|
|
from tactic \c t2.
|
|
|
|
*/
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic append(tactic const & t1, tactic const & t2);
|
2014-10-30 02:13:55 +00:00
|
|
|
|
|
|
|
/** \brief Return a tactic that rotate goals to the left n steps */
|
|
|
|
tactic rotate_left(unsigned n);
|
|
|
|
/** \brief Return a tactic that rotate goals to the right n steps */
|
|
|
|
tactic rotate_right(unsigned n);
|
|
|
|
|
2013-11-24 19:22:40 +00:00
|
|
|
inline tactic operator+(tactic const & t1, tactic const & t2) { return append(t1, t2); }
|
2013-11-23 00:15:03 +00:00
|
|
|
/**
|
|
|
|
\brief Execute both tactics and and combines their results.
|
|
|
|
The results produced by tactics \c t1 and \c t2 are interleaved
|
|
|
|
to guarantee fairness.
|
|
|
|
*/
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic interleave(tactic const & t1, tactic const & t2);
|
2013-11-23 00:15:03 +00:00
|
|
|
/**
|
2013-11-24 19:22:40 +00:00
|
|
|
\brief Return a tactic that executes \c t1 and \c t2 in parallel.
|
|
|
|
This is similar to \c append and \c interleave. The order of
|
|
|
|
the elements in the output sequence is not deterministic.
|
|
|
|
It depends on how fast \c t1 and \c t2 produce their output.
|
2013-11-23 00:15:03 +00:00
|
|
|
|
|
|
|
\remark \c check_ms is how often the main thread checks whether the children
|
|
|
|
threads finished.
|
|
|
|
*/
|
2013-11-29 06:11:07 +00:00
|
|
|
tactic par(tactic const & t1, tactic const & t2, unsigned check_ms);
|
|
|
|
inline tactic par(tactic const & t1, tactic const & t2) { return par(t1, t2, 1); }
|
2013-11-23 00:39:25 +00:00
|
|
|
/**
|
|
|
|
\brief Return a tactic that keeps applying \c t until it fails.
|
|
|
|
*/
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic repeat(tactic const & t);
|
2013-11-23 00:39:25 +00:00
|
|
|
/**
|
|
|
|
\brief Similar to \c repeat, but execute \c t at most \c k times.
|
2013-11-23 00:15:03 +00:00
|
|
|
|
2013-11-23 00:39:25 +00:00
|
|
|
\remark The value \c k is the depth of the recursion.
|
|
|
|
For example, if tactic \c t always produce a sequence of size 2,
|
|
|
|
then tactic \c t will be applied 2^k times.
|
|
|
|
*/
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic repeat_at_most(tactic const & t, unsigned k);
|
2013-11-23 01:05:18 +00:00
|
|
|
/**
|
|
|
|
\brief Return a tactic that applies \c t, but takes at most \c
|
2014-07-03 16:20:01 +00:00
|
|
|
\c k elements from the sequence produced by \c t.
|
2013-11-23 01:05:18 +00:00
|
|
|
*/
|
2013-11-24 19:22:40 +00:00
|
|
|
tactic take(tactic const & t, unsigned k);
|
2014-07-03 16:20:01 +00:00
|
|
|
/**
|
|
|
|
\brief Return a tactic that applies \c t, but discards the first
|
|
|
|
\c k elements from the sequence produced by \c t.
|
|
|
|
*/
|
|
|
|
tactic discard(tactic const & t, unsigned k);
|
|
|
|
|
2014-10-15 01:19:34 +00:00
|
|
|
/** \brief Return a tactic that renames hypothesis \c from into \c to in the current goal. */
|
|
|
|
tactic rename_tactic(name const & from, name const & to);
|
|
|
|
|
2014-06-28 01:42:59 +00:00
|
|
|
typedef std::function<bool(environment const & env, io_state const & ios, proof_state const & s)> proof_state_pred; // NOLINT
|
2013-11-24 20:04:32 +00:00
|
|
|
/**
|
2014-06-28 01:35:59 +00:00
|
|
|
\brief Return a tactic that applies the predicate \c p to the input state.
|
|
|
|
If \c p returns true, then applies \c t1. Otherwise, applies \c t2.
|
2013-11-24 20:04:32 +00:00
|
|
|
*/
|
2014-06-29 18:07:06 +00:00
|
|
|
tactic cond(proof_state_pred p, tactic const & t1, tactic const & t2);
|
2014-06-28 01:35:59 +00:00
|
|
|
/** \brief Syntax-sugar for cond(p, t, id_tactic()) */
|
2014-06-29 18:07:06 +00:00
|
|
|
inline tactic when(proof_state_pred p, tactic const & t) { return cond(p, t, id_tactic()); }
|
2013-11-30 19:28:10 +00:00
|
|
|
/**
|
|
|
|
\brief Return a tactic that applies \c t only to the i-th goal.
|
|
|
|
The tactic fails if the input state does have at least i goals.
|
|
|
|
*/
|
2014-07-01 23:11:19 +00:00
|
|
|
tactic focus(tactic const & t, unsigned i);
|
2015-03-26 00:42:34 +00:00
|
|
|
inline tactic focus(tactic const & t) { return focus(t, 0); }
|
2014-06-28 01:35:59 +00:00
|
|
|
/** \brief Return a tactic that applies beta-reduction. */
|
2013-12-02 16:10:51 +00:00
|
|
|
tactic beta_tactic();
|
2015-03-26 00:42:34 +00:00
|
|
|
/** \brief Apply \c t to all goals in the proof state */
|
|
|
|
tactic all_goals(tactic const & t);
|
2013-11-28 01:47:29 +00:00
|
|
|
|
|
|
|
UDATA_DEFS_CORE(proof_state_seq)
|
2014-06-28 01:35:59 +00:00
|
|
|
UDATA_DEFS_CORE(tactic);
|
2013-11-28 01:47:29 +00:00
|
|
|
void open_tactic(lua_State * L);
|
2013-11-21 20:34:37 +00:00
|
|
|
}
|