2013-09-13 01:25:38 +00:00
|
|
|
/*
|
|
|
|
Copyright (c) 2013 Microsoft Corporation. All rights reserved.
|
|
|
|
Released under Apache 2.0 license as described in the file LICENSE.
|
|
|
|
|
|
|
|
Author: Leonardo de Moura
|
|
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include "util/pair.h"
|
2013-09-27 01:24:45 +00:00
|
|
|
#include "util/splay_map.h"
|
|
|
|
#include "util/name_generator.h"
|
2013-09-13 01:25:38 +00:00
|
|
|
#include "kernel/expr.h"
|
2013-09-16 02:37:59 +00:00
|
|
|
#include "kernel/context.h"
|
2013-10-23 20:42:14 +00:00
|
|
|
#include "kernel/justification.h"
|
2013-10-23 23:35:47 +00:00
|
|
|
#include "kernel/replace_visitor.h"
|
2013-09-13 01:25:38 +00:00
|
|
|
|
|
|
|
namespace lean {
|
2013-10-01 00:58:46 +00:00
|
|
|
/**
|
|
|
|
\brief Metavar environment. It is an auxiliary datastructure used for:
|
|
|
|
|
|
|
|
1- Creating metavariables.
|
|
|
|
2- Storing their types and the contexts where they were created.
|
|
|
|
3- Storing substitutions.
|
|
|
|
4- Collecting constraints
|
|
|
|
*/
|
|
|
|
class metavar_env {
|
2013-10-25 18:02:19 +00:00
|
|
|
struct data {
|
2013-10-27 18:02:29 +00:00
|
|
|
expr m_subst; // substitution
|
2013-10-25 18:02:19 +00:00
|
|
|
expr m_type; // type of the metavariable
|
|
|
|
context m_context; // context where the metavariable was defined
|
|
|
|
justification m_justification; // justification for assigned metavariables.
|
|
|
|
data(expr const & t = expr(), context const & ctx = context()):m_type(t), m_context(ctx) {}
|
|
|
|
};
|
|
|
|
typedef splay_map<name, data, name_quick_cmp> name2data;
|
2013-10-01 00:58:46 +00:00
|
|
|
|
2013-10-23 20:42:14 +00:00
|
|
|
name_generator m_name_generator;
|
2013-10-25 18:02:19 +00:00
|
|
|
name2data m_metavar_data;
|
2013-10-27 18:02:29 +00:00
|
|
|
unsigned m_size;
|
|
|
|
// If the following flag is true, then beta-reduction is automatically applied
|
|
|
|
// when we apply a substitution containing ?m <- fun (x : T), ...
|
|
|
|
// to an expression containing (?m a)
|
|
|
|
// The motivation is that higher order unification and matching produces a
|
|
|
|
// bunch of assignments of the form ?m <- fun (x : T), ...
|
|
|
|
bool m_beta_reduce_mv;
|
2013-10-23 20:42:14 +00:00
|
|
|
unsigned m_timestamp;
|
2013-10-01 00:58:46 +00:00
|
|
|
|
|
|
|
void inc_timestamp();
|
|
|
|
public:
|
2013-10-02 00:25:17 +00:00
|
|
|
metavar_env(name const & prefix);
|
2013-10-01 00:58:46 +00:00
|
|
|
metavar_env();
|
|
|
|
|
2013-10-27 18:02:29 +00:00
|
|
|
bool beta_reduce_metavar_application() const { return m_beta_reduce_mv; }
|
|
|
|
void set_beta_reduce_metavar_application(bool f) { m_beta_reduce_mv = f; }
|
|
|
|
|
2013-10-16 20:26:31 +00:00
|
|
|
friend void swap(metavar_env & a, metavar_env & b);
|
2013-10-16 00:32:02 +00:00
|
|
|
|
2013-10-01 00:58:46 +00:00
|
|
|
/**
|
|
|
|
\brief The timestamp is increased whenever this environment is
|
|
|
|
updated.
|
|
|
|
*/
|
|
|
|
unsigned get_timestamp() const { return m_timestamp; }
|
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Create a new metavariable in the given context and with the given type.
|
|
|
|
*/
|
|
|
|
expr mk_metavar(context const & ctx = context(), expr const & type = expr());
|
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Return the context where the given metavariable was created.
|
|
|
|
\pre is_metavar(m)
|
2013-10-02 00:25:17 +00:00
|
|
|
\pre !has_local_context(m)
|
2013-10-01 00:58:46 +00:00
|
|
|
*/
|
2013-10-02 00:25:17 +00:00
|
|
|
context get_context(expr const & m) const;
|
|
|
|
context get_context(name const & m) const;
|
2013-10-01 00:58:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Return the type of the given metavariable.
|
|
|
|
\pre is_metavar(m)
|
2013-10-02 00:25:17 +00:00
|
|
|
|
|
|
|
\remark If \c m does not have a type associated with it, then a new
|
|
|
|
metavariable is created to represent the type of \c m.
|
|
|
|
|
|
|
|
\remark If \c m has a local context, then the local context is applied.
|
2013-10-01 00:58:46 +00:00
|
|
|
*/
|
|
|
|
expr get_type(expr const & m);
|
|
|
|
expr get_type(name const & m);
|
|
|
|
|
2013-10-16 20:26:31 +00:00
|
|
|
/**
|
|
|
|
\brief Return true iff \c m has a type associated with it.
|
|
|
|
\pre is_metavar(m)
|
|
|
|
*/
|
|
|
|
bool has_type(expr const & m) const;
|
|
|
|
bool has_type(name const & m) const;
|
|
|
|
|
|
|
|
/**
|
2013-10-23 20:42:14 +00:00
|
|
|
\brief Return the justification for an assigned metavariable.
|
2013-10-16 20:26:31 +00:00
|
|
|
\pre is_metavar(m)
|
|
|
|
\pre is_assigned(m)
|
|
|
|
*/
|
2013-10-23 20:42:14 +00:00
|
|
|
justification get_justification(expr const & m) const;
|
|
|
|
justification get_justification(name const & m) const;
|
2013-10-16 20:26:31 +00:00
|
|
|
|
|
|
|
|
2013-10-01 00:58:46 +00:00
|
|
|
/**
|
|
|
|
\brief Return true iff the metavariable named \c m is assigned in this substitution.
|
|
|
|
*/
|
|
|
|
bool is_assigned(name const & m) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Return true if the given metavariable is assigned in this
|
|
|
|
substitution.
|
2013-09-17 18:09:59 +00:00
|
|
|
|
2013-10-01 00:58:46 +00:00
|
|
|
\pre is_metavar(m)
|
|
|
|
*/
|
|
|
|
bool is_assigned(expr const & m) const;
|
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Assign metavariable named \c m.
|
|
|
|
|
|
|
|
\pre !is_assigned(m)
|
|
|
|
*/
|
2013-10-23 20:42:14 +00:00
|
|
|
void assign(name const & m, expr const & t, justification const & j = justification());
|
2013-10-01 00:58:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Assign metavariable \c m to \c t.
|
|
|
|
|
|
|
|
\pre is_metavar(m)
|
|
|
|
\pre !has_meta_context(m)
|
|
|
|
\pre !is_assigned(m)
|
|
|
|
*/
|
2013-10-23 20:42:14 +00:00
|
|
|
void assign(expr const & m, expr const & t, justification const & j = justification());
|
2013-10-01 00:58:46 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Return the substitution associated with the given metavariable
|
|
|
|
in this substitution.
|
|
|
|
|
|
|
|
If the metavariable is not assigned in this substitution, then it returns the null
|
|
|
|
expression.
|
|
|
|
|
|
|
|
\pre is_metavar(m)
|
|
|
|
*/
|
2013-10-27 18:02:29 +00:00
|
|
|
expr get_subst(expr const & m) const;
|
2013-10-16 00:32:02 +00:00
|
|
|
|
|
|
|
/**
|
2013-10-27 18:02:29 +00:00
|
|
|
\brief Apply f to each substitution in the metavariable environment.
|
2013-10-16 00:32:02 +00:00
|
|
|
*/
|
2013-10-27 18:02:29 +00:00
|
|
|
template<typename F>
|
|
|
|
void for_each_subst(F f) const {
|
|
|
|
m_metavar_data.for_each([&](name const & k, data const & d) {
|
|
|
|
if (d.m_subst)
|
|
|
|
f(k, d.m_subst);
|
|
|
|
});
|
|
|
|
}
|
2013-09-13 01:25:38 +00:00
|
|
|
};
|
|
|
|
|
2013-10-16 20:26:31 +00:00
|
|
|
void swap(metavar_env & a, metavar_env & b);
|
|
|
|
|
2013-09-27 01:24:45 +00:00
|
|
|
/**
|
|
|
|
\brief Apply the changes in \c lctx to \c a.
|
|
|
|
*/
|
|
|
|
expr apply_local_context(expr const & a, local_context const & lctx);
|
2013-09-21 07:41:13 +00:00
|
|
|
|
2013-09-13 01:25:38 +00:00
|
|
|
/**
|
|
|
|
\brief Instantiate the metavariables occurring in \c e with the substitutions
|
2013-10-27 18:02:29 +00:00
|
|
|
provided by \c menv. Store the justification of replace variables in jsts.
|
2013-09-13 01:25:38 +00:00
|
|
|
*/
|
2013-10-27 18:02:29 +00:00
|
|
|
expr instantiate_metavars(expr const & e, metavar_env const & menv, buffer<justification> & jsts);
|
|
|
|
inline expr instantiate_metavars(expr const & e, metavar_env const & menv) {
|
|
|
|
buffer<justification> tmp;
|
|
|
|
return instantiate_metavars(e, menv, tmp);
|
|
|
|
}
|
2013-09-13 01:25:38 +00:00
|
|
|
|
2013-09-16 17:58:56 +00:00
|
|
|
/**
|
2013-09-27 01:24:45 +00:00
|
|
|
\brief Extend the local context \c lctx with the entry <tt>lift:s:n</tt>
|
2013-09-16 17:58:56 +00:00
|
|
|
*/
|
2013-09-27 01:24:45 +00:00
|
|
|
local_context add_lift(local_context const & lctx, unsigned s, unsigned n);
|
2013-09-16 17:58:56 +00:00
|
|
|
|
2013-09-13 01:25:38 +00:00
|
|
|
/**
|
|
|
|
\brief Add a lift:s:n operation to the context of the given metavariable.
|
|
|
|
|
|
|
|
\pre is_metavar(m)
|
|
|
|
*/
|
|
|
|
expr add_lift(expr const & m, unsigned s, unsigned n);
|
|
|
|
|
|
|
|
/**
|
2013-09-17 02:21:40 +00:00
|
|
|
\brief Add an inst:s:v operation to the context of the given metavariable.
|
2013-09-13 01:25:38 +00:00
|
|
|
|
|
|
|
\pre is_metavar(m)
|
|
|
|
*/
|
2013-09-17 02:21:40 +00:00
|
|
|
expr add_inst(expr const & m, unsigned s, expr const & v);
|
2013-09-13 01:25:38 +00:00
|
|
|
|
2013-09-16 17:58:56 +00:00
|
|
|
/**
|
2013-09-27 01:24:45 +00:00
|
|
|
\brief Extend the local context \c lctx with the entry <tt>inst:s v</tt>
|
2013-09-16 17:58:56 +00:00
|
|
|
*/
|
2013-09-27 01:24:45 +00:00
|
|
|
local_context add_inst(local_context const & lctx, unsigned s, expr const & v);
|
2013-09-16 17:58:56 +00:00
|
|
|
|
2013-09-13 01:25:38 +00:00
|
|
|
/**
|
|
|
|
\brief Return true iff the given metavariable has a non-empty
|
2013-09-27 01:24:45 +00:00
|
|
|
local context associated with it.
|
2013-09-13 01:25:38 +00:00
|
|
|
|
|
|
|
\pre is_metavar(m)
|
|
|
|
*/
|
2013-09-27 01:24:45 +00:00
|
|
|
bool has_local_context(expr const & m);
|
2013-09-13 01:25:38 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
\brief Return the same metavariable, but the head of the context is removed.
|
|
|
|
|
|
|
|
\pre is_metavar(m)
|
2013-09-19 03:46:00 +00:00
|
|
|
\pre has_meta_context(m)
|
2013-09-13 01:25:38 +00:00
|
|
|
*/
|
2013-09-19 03:46:00 +00:00
|
|
|
expr pop_meta_context(expr const & m);
|
|
|
|
|
|
|
|
/**
|
2013-10-27 18:02:29 +00:00
|
|
|
\brief Return true iff \c e has a metavariable that is assigned in \c menv.
|
2013-09-19 03:46:00 +00:00
|
|
|
*/
|
2013-10-27 18:02:29 +00:00
|
|
|
bool has_assigned_metavar(expr const & e, metavar_env const & menv);
|
2013-09-13 01:25:38 +00:00
|
|
|
|
|
|
|
/**
|
2013-09-27 01:24:45 +00:00
|
|
|
\brief Return true iff \c e contains the metavariable \c m.
|
2013-10-27 18:02:29 +00:00
|
|
|
The substitutions in \c menv are taken into account.
|
2013-09-27 01:24:45 +00:00
|
|
|
|
|
|
|
\brief is_metavar(m)
|
2013-09-13 01:25:38 +00:00
|
|
|
*/
|
2013-10-27 18:02:29 +00:00
|
|
|
bool has_metavar(expr const & e, expr const & m, metavar_env const & menv);
|
2013-09-13 01:25:38 +00:00
|
|
|
}
|