2014-05-20 16:40:30 +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
*/
2015-02-06 21:27:10 +00:00
# include <string>
2014-10-27 23:49:29 +00:00
# include "util/interrupt.h"
2014-05-20 16:40:30 +00:00
# include "util/name_generator.h"
2015-06-07 03:30:14 +00:00
# include "kernel/replace_fn.h"
2014-05-20 16:40:30 +00:00
# include "kernel/type_checker.h"
# include "kernel/instantiate.h"
# include "kernel/abstract.h"
2015-03-12 07:31:10 +00:00
# include "kernel/free_vars.h"
2014-12-15 02:49:48 +00:00
# include "kernel/inductive/inductive.h"
2015-06-07 03:30:14 +00:00
# include "library/replace_visitor.h"
2014-09-27 03:16:03 +00:00
# include "library/reducible.h"
2015-02-06 20:12:52 +00:00
# include "library/util.h"
# include "library/scoped_ext.h"
# include "library/kernel_serializer.h"
2015-12-18 04:56:02 +00:00
# include "library/attribute_manager.h"
2014-05-20 16:40:30 +00:00
namespace lean {
2015-02-06 20:12:52 +00:00
/**
2015-04-05 09:47:37 +00:00
\ brief unfold hints instruct the normalizer ( and simplifier ) that
a function application . We have two kinds of hints :
2015-07-07 23:37:06 +00:00
- [ unfold ] ( f a_1 . . . a_i . . . a_n ) should be unfolded
2015-04-05 09:47:37 +00:00
when argument a_i is a constructor .
2015-07-07 23:37:06 +00:00
- [ unfold - full ] ( f a_1 . . . a_i . . . a_n ) should be unfolded when it is fully applied .
2015-05-07 18:56:42 +00:00
- constructor ( f . . . ) should be unfolded when it is the major premise of a recursor - like operator
2015-02-06 20:12:52 +00:00
*/
2015-04-05 09:47:37 +00:00
struct unfold_hint_entry {
2015-07-07 23:37:06 +00:00
enum kind { Unfold , UnfoldFull , Constructor } ;
2015-07-08 01:01:57 +00:00
kind m_kind ; //!< true if it is an unfold_c hint
bool m_add ; //!< add/remove hint
name m_decl_name ;
list < unsigned > m_arg_idxs ; //!< only relevant if m_kind == Unfold
unfold_hint_entry ( ) : m_kind ( Unfold ) , m_add ( false ) { }
unfold_hint_entry ( kind k , bool add , name const & n ) :
m_kind ( k ) , m_add ( add ) , m_decl_name ( n ) { }
unfold_hint_entry ( bool add , name const & n , list < unsigned > const & idxs ) :
m_kind ( Unfold ) , m_add ( add ) , m_decl_name ( n ) , m_arg_idxs ( idxs ) { }
2015-02-06 20:12:52 +00:00
} ;
2015-07-08 01:01:57 +00:00
unfold_hint_entry mk_add_unfold_entry ( name const & n , list < unsigned > const & idxs ) { return unfold_hint_entry ( true , n , idxs ) ; }
unfold_hint_entry mk_erase_unfold_entry ( name const & n ) { return unfold_hint_entry ( unfold_hint_entry : : Unfold , false , n ) ; }
unfold_hint_entry mk_add_unfold_full_entry ( name const & n ) { return unfold_hint_entry ( unfold_hint_entry : : UnfoldFull , true , n ) ; }
unfold_hint_entry mk_erase_unfold_full_entry ( name const & n ) { return unfold_hint_entry ( unfold_hint_entry : : UnfoldFull , false , n ) ; }
unfold_hint_entry mk_add_constructor_entry ( name const & n ) { return unfold_hint_entry ( unfold_hint_entry : : Constructor , true , n ) ; }
unfold_hint_entry mk_erase_constructor_entry ( name const & n ) { return unfold_hint_entry ( unfold_hint_entry : : Constructor , false , n ) ; }
2015-04-05 09:47:37 +00:00
static name * g_unfold_hint_name = nullptr ;
2015-02-06 20:12:52 +00:00
static std : : string * g_key = nullptr ;
2015-04-05 09:47:37 +00:00
struct unfold_hint_state {
2015-07-08 01:01:57 +00:00
name_map < list < unsigned > > m_unfold ;
name_set m_unfold_full ;
name_set m_constructor ;
2015-04-05 09:47:37 +00:00
} ;
struct unfold_hint_config {
typedef unfold_hint_state state ;
typedef unfold_hint_entry entry ;
2015-02-06 20:12:52 +00:00
static void add_entry ( environment const & , io_state const & , state & s , entry const & e ) {
2015-05-04 21:23:04 +00:00
switch ( e . m_kind ) {
2015-07-07 23:37:06 +00:00
case unfold_hint_entry : : Unfold :
2015-04-05 09:47:37 +00:00
if ( e . m_add )
2015-07-08 01:01:57 +00:00
s . m_unfold . insert ( e . m_decl_name , e . m_arg_idxs ) ;
2015-04-05 09:47:37 +00:00
else
2015-07-07 23:37:06 +00:00
s . m_unfold . erase ( e . m_decl_name ) ;
2015-05-04 21:23:04 +00:00
break ;
2015-07-07 23:37:06 +00:00
case unfold_hint_entry : : UnfoldFull :
2015-04-05 09:47:37 +00:00
if ( e . m_add )
2015-07-07 23:37:06 +00:00
s . m_unfold_full . insert ( e . m_decl_name ) ;
2015-04-05 09:47:37 +00:00
else
2015-07-07 23:37:06 +00:00
s . m_unfold_full . erase ( e . m_decl_name ) ;
2015-05-04 21:23:04 +00:00
break ;
2015-07-07 23:37:06 +00:00
case unfold_hint_entry : : Constructor :
2015-05-04 21:23:04 +00:00
if ( e . m_add )
2015-05-07 18:56:42 +00:00
s . m_constructor . insert ( e . m_decl_name ) ;
2015-05-04 21:23:04 +00:00
else
2015-05-07 18:56:42 +00:00
s . m_constructor . erase ( e . m_decl_name ) ;
2015-05-04 21:23:04 +00:00
break ;
2015-04-05 09:47:37 +00:00
}
2015-02-06 20:12:52 +00:00
}
static name const & get_class_name ( ) {
2015-04-05 09:47:37 +00:00
return * g_unfold_hint_name ;
2015-02-06 20:12:52 +00:00
}
static std : : string const & get_serialization_key ( ) {
return * g_key ;
}
static void write_entry ( serializer & s , entry const & e ) {
2015-07-08 01:01:57 +00:00
s < < static_cast < char > ( e . m_kind ) < < e . m_add < < e . m_decl_name ;
if ( e . m_kind = = unfold_hint_entry : : Unfold )
write_list ( s , e . m_arg_idxs ) ;
2015-02-06 20:12:52 +00:00
}
static entry read_entry ( deserializer & d ) {
2015-05-04 21:23:04 +00:00
char k ;
2015-02-06 20:12:52 +00:00
entry e ;
2015-07-08 01:01:57 +00:00
d > > k > > e . m_add > > e . m_decl_name ;
2015-05-04 21:23:04 +00:00
e . m_kind = static_cast < unfold_hint_entry : : kind > ( k ) ;
2015-07-08 01:01:57 +00:00
if ( e . m_kind = = unfold_hint_entry : : Unfold )
e . m_arg_idxs = read_list < unsigned > ( d ) ;
2015-02-06 20:12:52 +00:00
return e ;
}
static optional < unsigned > get_fingerprint ( entry const & e ) {
return some ( e . m_decl_name . hash ( ) ) ;
}
} ;
2015-04-05 09:47:37 +00:00
template class scoped_ext < unfold_hint_config > ;
typedef scoped_ext < unfold_hint_config > unfold_hint_ext ;
2015-02-06 20:12:52 +00:00
2015-12-05 18:28:01 +00:00
environment add_unfold_hint ( environment const & env , name const & n , list < unsigned > const & idxs , name const & ns , bool persistent ) {
2015-07-08 01:01:57 +00:00
lean_assert ( idxs ) ;
2015-02-06 20:42:53 +00:00
declaration const & d = env . get ( n ) ;
2015-05-08 22:42:42 +00:00
if ( ! d . is_definition ( ) )
2015-07-07 23:37:06 +00:00
throw exception ( " invalid [unfold] hint, declaration must be a non-opaque definition " ) ;
2015-12-05 18:28:01 +00:00
return unfold_hint_ext : : add_entry ( env , get_dummy_ios ( ) , mk_add_unfold_entry ( n , idxs ) , ns , persistent ) ;
2015-02-06 20:12:52 +00:00
}
2015-07-08 01:01:57 +00:00
list < unsigned > has_unfold_hint ( environment const & env , name const & d ) {
2015-04-05 09:47:37 +00:00
unfold_hint_state const & s = unfold_hint_ext : : get_state ( env ) ;
2015-07-07 23:37:06 +00:00
if ( auto it = s . m_unfold . find ( d ) )
2015-07-08 01:01:57 +00:00
return list < unsigned > ( * it ) ;
2015-02-06 20:12:52 +00:00
else
2015-07-08 01:01:57 +00:00
return list < unsigned > ( ) ;
2015-02-06 20:12:52 +00:00
}
2015-12-05 18:28:01 +00:00
environment erase_unfold_hint ( environment const & env , name const & n , name const & ns , bool persistent ) {
return unfold_hint_ext : : add_entry ( env , get_dummy_ios ( ) , mk_erase_unfold_entry ( n ) , ns , persistent ) ;
2015-04-05 09:47:37 +00:00
}
2015-12-05 18:28:01 +00:00
environment add_unfold_full_hint ( environment const & env , name const & n , name const & ns , bool persistent ) {
2015-04-05 09:47:37 +00:00
declaration const & d = env . get ( n ) ;
2015-05-08 22:42:42 +00:00
if ( ! d . is_definition ( ) )
2015-10-09 20:21:03 +00:00
throw exception ( " invalid [unfold_full] hint, declaration must be a non-opaque definition " ) ;
2015-12-05 18:28:01 +00:00
return unfold_hint_ext : : add_entry ( env , get_dummy_ios ( ) , mk_add_unfold_full_entry ( n ) , ns , persistent ) ;
2015-04-05 09:47:37 +00:00
}
2015-07-07 23:37:06 +00:00
bool has_unfold_full_hint ( environment const & env , name const & d ) {
2015-04-05 09:47:37 +00:00
unfold_hint_state const & s = unfold_hint_ext : : get_state ( env ) ;
2015-07-07 23:37:06 +00:00
return s . m_unfold_full . contains ( d ) ;
2015-04-05 09:47:37 +00:00
}
2015-12-05 18:28:01 +00:00
environment erase_unfold_full_hint ( environment const & env , name const & n , name const & ns , bool persistent ) {
return unfold_hint_ext : : add_entry ( env , get_dummy_ios ( ) , mk_erase_unfold_full_entry ( n ) , ns , persistent ) ;
2015-04-05 09:47:37 +00:00
}
2015-12-05 18:28:01 +00:00
environment add_constructor_hint ( environment const & env , name const & n , name const & ns , bool persistent ) {
2015-05-07 18:56:42 +00:00
env . get ( n ) ;
2015-12-05 18:28:01 +00:00
return unfold_hint_ext : : add_entry ( env , get_dummy_ios ( ) , mk_add_constructor_entry ( n ) , ns , persistent ) ;
2015-05-04 21:23:04 +00:00
}
2015-05-07 18:56:42 +00:00
bool has_constructor_hint ( environment const & env , name const & d ) {
2015-05-04 21:23:04 +00:00
unfold_hint_state const & s = unfold_hint_ext : : get_state ( env ) ;
2015-05-07 18:56:42 +00:00
return s . m_constructor . contains ( d ) ;
2015-05-04 21:23:04 +00:00
}
2015-12-05 18:28:01 +00:00
environment erase_constructor_hint ( environment const & env , name const & n , name const & ns , bool persistent ) {
return unfold_hint_ext : : add_entry ( env , get_dummy_ios ( ) , mk_erase_constructor_entry ( n ) , ns , persistent ) ;
2015-05-04 21:23:04 +00:00
}
2015-02-06 20:12:52 +00:00
void initialize_normalize ( ) {
2015-12-28 18:30:23 +00:00
g_unfold_hint_name = new name ( " unfold " ) ;
g_key = new std : : string ( " UNFOLDH " ) ;
2015-04-05 09:47:37 +00:00
unfold_hint_ext : : initialize ( ) ;
2015-12-18 04:56:02 +00:00
register_params_attribute ( " unfold " , " unfold definition when the given positions are constructors " ,
[ ] ( environment const & env , io_state const & , name const & d , list < unsigned > const & idxs , name const & ns , bool persistent ) {
return add_unfold_hint ( env , d , idxs , ns , persistent ) ;
} ,
[ ] ( environment const & env , name const & n ) { return static_cast < bool > ( has_unfold_hint ( env , n ) ) ; } ,
[ ] ( environment const & env , name const & n ) { return has_unfold_hint ( env , n ) ; } ) ;
register_attribute ( " unfold_full " ,
" instructs normalizer (and simplifier) that function application (f a_1 ... a_n) should be unfolded when it is fully applied " ,
[ ] ( environment const & env , io_state const & , name const & d , name const & ns , bool persistent ) {
return add_unfold_full_hint ( env , d , ns , persistent ) ;
} ,
has_unfold_full_hint ) ;
register_attribute ( " constructor " ,
" instructs normalizer (and simplifier) that function application (f ...) should be unfolded when it is the major premise of a constructor like operator " ,
[ ] ( environment const & env , io_state const & , name const & d , name const & ns , bool persistent ) {
return add_constructor_hint ( env , d , ns , persistent ) ;
} ,
has_constructor_hint ) ;
2015-02-06 20:12:52 +00:00
}
void finalize_normalize ( ) {
2015-04-05 09:47:37 +00:00
unfold_hint_ext : : finalize ( ) ;
delete g_unfold_hint_name ;
2015-02-06 20:12:52 +00:00
delete g_key ;
}
2015-05-29 22:08:49 +00:00
expr try_eta ( expr const & e ) {
if ( is_lambda ( e ) ) {
expr const & b = binding_body ( e ) ;
if ( is_lambda ( b ) ) {
expr new_b = try_eta ( b ) ;
if ( is_eqp ( b , new_b ) ) {
return e ;
} else if ( is_app ( new_b ) & & is_var ( app_arg ( new_b ) , 0 ) & & ! has_free_var ( app_fn ( new_b ) , 0 ) ) {
return lower_free_vars ( app_fn ( new_b ) , 1 ) ;
} else {
return update_binding ( e , binding_domain ( e ) , new_b ) ;
}
} else if ( is_app ( b ) & & is_var ( app_arg ( b ) , 0 ) & & ! has_free_var ( app_fn ( b ) , 0 ) ) {
return lower_free_vars ( app_fn ( b ) , 1 ) ;
} else {
return e ;
}
} else {
return e ;
}
}
2015-06-07 03:30:14 +00:00
template < bool Eta , bool Beta >
class eta_beta_reduce_fn : public replace_visitor {
public :
virtual expr visit_app ( expr const & e ) {
expr e1 = replace_visitor : : visit_app ( e ) ;
if ( Beta & & is_head_beta ( e1 ) ) {
return visit ( head_beta_reduce ( e1 ) ) ;
} else {
return e1 ;
}
}
virtual expr visit_lambda ( expr const & e ) {
expr e1 = replace_visitor : : visit_lambda ( e ) ;
if ( Eta ) {
while ( true ) {
expr e2 = try_eta ( e1 ) ;
if ( is_eqp ( e1 , e2 ) )
return e1 ;
else
e1 = e2 ;
}
} else {
return e1 ;
}
}
} ;
expr beta_reduce ( expr t ) {
return eta_beta_reduce_fn < false , true > ( ) ( t ) ;
}
2015-06-10 23:26:32 +00:00
expr eta_reduce ( expr t ) {
return eta_beta_reduce_fn < true , false > ( ) ( t ) ;
}
2015-06-07 03:30:14 +00:00
expr beta_eta_reduce ( expr t ) {
return eta_beta_reduce_fn < true , true > ( ) ( t ) ;
}
2014-05-20 16:40:30 +00:00
class normalize_fn {
2014-10-27 21:49:11 +00:00
type_checker & m_tc ;
2015-08-16 21:22:02 +00:00
// Remark: the normalizer/type-checker m_tc has been provided by the "user".
// It may be a constrained one (e.g., it may only unfold definitions marked as [reducible].
// So, we should not use it for inferring types and/or checking whether an expression is
// a proposition or not. Such checks may fail because of the restrictions on m_tc.
// So, we use m_full_tc for this kind of operation. It is an unconstrained type checker.
// See issue #801
type_checker m_full_tc ;
2014-10-27 21:49:11 +00:00
name_generator m_ngen ;
2014-10-27 23:49:29 +00:00
std : : function < bool ( expr const & ) > m_pred ; // NOLINT
2014-10-27 21:49:11 +00:00
bool m_save_cnstrs ;
constraint_seq m_cnstrs ;
2015-03-12 07:31:10 +00:00
bool m_use_eta ;
2015-05-21 02:09:44 +00:00
bool m_eval_nested_prop ;
environment const & env ( ) const { return m_tc . env ( ) ; }
2014-05-20 16:40:30 +00:00
expr normalize_binding ( expr const & e ) {
expr d = normalize ( binding_domain ( e ) ) ;
2014-06-30 16:14:55 +00:00
expr l = mk_local ( m_ngen . next ( ) , binding_name ( e ) , d , binding_info ( e ) ) ;
2014-05-20 16:40:30 +00:00
expr b = abstract ( normalize ( instantiate ( binding_body ( e ) , l ) ) , l ) ;
return update_binding ( e , d , b ) ;
}
2015-07-08 01:01:57 +00:00
list < unsigned > has_unfold_hint ( expr const & f ) {
2015-02-06 20:12:52 +00:00
if ( ! is_constant ( f ) )
2015-07-08 01:01:57 +00:00
return list < unsigned > ( ) ;
2015-07-07 23:37:06 +00:00
return : : lean : : has_unfold_hint ( env ( ) , const_name ( f ) ) ;
2015-02-06 20:12:52 +00:00
}
2015-07-07 23:37:06 +00:00
bool has_unfold_full_hint ( expr const & f ) {
return is_constant ( f ) & & : : lean : : has_unfold_full_hint ( env ( ) , const_name ( f ) ) ;
2015-04-05 09:47:37 +00:00
}
2015-05-04 21:23:04 +00:00
optional < expr > is_constructor_like ( expr const & e ) {
2015-05-21 02:09:44 +00:00
if ( is_constructor_app ( env ( ) , e ) )
2015-05-04 21:23:04 +00:00
return some_expr ( e ) ;
expr const & f = get_app_fn ( e ) ;
2015-05-21 02:09:44 +00:00
if ( is_constant ( f ) & & has_constructor_hint ( env ( ) , const_name ( f ) ) ) {
if ( auto r = unfold_term ( env ( ) , e ) )
2015-05-07 18:56:42 +00:00
return r ;
else
return some_expr ( e ) ;
2015-05-04 21:23:04 +00:00
} else {
return none_expr ( ) ;
}
}
2015-07-08 01:01:57 +00:00
optional < expr > unfold_recursor_core ( expr const & f , unsigned i ,
buffer < unsigned > const & idxs , buffer < expr > & args , bool is_rec ) {
if ( i = = idxs . size ( ) ) {
expr new_app = mk_rev_app ( f , args ) ;
if ( is_rec )
return some_expr ( normalize ( new_app ) ) ;
else if ( optional < expr > r = unfold_app ( env ( ) , new_app ) )
return some_expr ( normalize ( * r ) ) ;
else
return none_expr ( ) ;
} else {
unsigned idx = idxs [ i ] ;
if ( idx > = args . size ( ) )
return none_expr ( ) ;
2015-05-04 21:23:04 +00:00
expr & arg = args [ args . size ( ) - idx - 1 ] ;
2015-07-08 01:01:57 +00:00
optional < expr > new_arg = is_constructor_like ( arg ) ;
if ( ! new_arg )
return none_expr ( ) ;
flet < expr > set_arg ( arg , * new_arg ) ;
return unfold_recursor_core ( f , i + 1 , idxs , args , is_rec ) ;
2015-05-04 21:23:04 +00:00
}
}
2015-07-08 01:01:57 +00:00
optional < expr > unfold_recursor_like ( expr const & f , list < unsigned > const & idx_lst , buffer < expr > & args ) {
buffer < unsigned > idxs ;
to_buffer ( idx_lst , idxs ) ;
return unfold_recursor_core ( f , 0 , idxs , args , false ) ;
2015-05-04 21:23:04 +00:00
}
optional < expr > unfold_recursor_major ( expr const & f , unsigned idx , buffer < expr > & args ) {
2015-07-08 01:01:57 +00:00
buffer < unsigned > idxs ;
idxs . push_back ( idx ) ;
return unfold_recursor_core ( f , 0 , idxs , args , true ) ;
2015-05-04 21:23:04 +00:00
}
2014-05-20 18:53:58 +00:00
expr normalize_app ( expr const & e ) {
buffer < expr > args ;
2014-12-15 02:49:48 +00:00
bool modified = false ;
2014-05-20 18:53:58 +00:00
expr f = get_app_rev_args ( e , args ) ;
2014-12-15 02:49:48 +00:00
for ( expr & a : args ) {
2015-05-21 02:09:44 +00:00
expr new_a = a ;
2015-08-16 21:22:02 +00:00
if ( m_eval_nested_prop | | ! m_full_tc . is_prop ( m_full_tc . infer ( a ) . first ) . first )
2015-05-21 02:09:44 +00:00
new_a = normalize ( a ) ;
2014-12-15 02:49:48 +00:00
if ( new_a ! = a )
modified = true ;
a = new_a ;
}
2015-07-07 23:37:06 +00:00
if ( has_unfold_full_hint ( f ) ) {
2015-08-16 21:22:02 +00:00
if ( ! is_pi ( m_full_tc . whnf ( m_full_tc . infer ( e ) . first ) . first ) ) {
if ( optional < expr > r = unfold_app ( env ( ) , mk_rev_app ( f , args ) ) ) {
2015-04-05 09:47:37 +00:00
return normalize ( * r ) ;
2015-08-16 21:22:02 +00:00
}
2015-04-05 09:47:37 +00:00
}
}
2015-07-08 01:01:57 +00:00
if ( auto idxs = has_unfold_hint ( f ) ) {
if ( auto r = unfold_recursor_like ( f , idxs , args ) )
2015-05-04 21:23:04 +00:00
return * r ;
}
if ( is_constant ( f ) ) {
2015-05-21 02:09:44 +00:00
if ( auto idx = inductive : : get_elim_major_idx ( env ( ) , const_name ( f ) ) ) {
2015-05-04 21:23:04 +00:00
if ( auto r = unfold_recursor_major ( f , * idx , args ) )
return * r ;
2015-02-06 20:12:52 +00:00
}
}
2014-12-15 02:49:48 +00:00
if ( ! modified )
return e ;
expr r = mk_rev_app ( f , args ) ;
2015-05-29 22:49:10 +00:00
if ( is_constant ( f ) & & env ( ) . is_recursor ( const_name ( f ) ) ) {
2014-12-15 02:49:48 +00:00
return normalize ( r ) ;
} else {
return r ;
}
2014-05-20 18:53:58 +00:00
}
2014-05-20 16:40:30 +00:00
expr normalize ( expr e ) {
2014-10-27 23:49:29 +00:00
check_system ( " normalize " ) ;
2014-10-27 21:49:11 +00:00
if ( ! m_pred ( e ) )
return e ;
auto w = m_tc . whnf ( e ) ;
e = w . first ;
if ( m_save_cnstrs )
m_cnstrs + = w . second ;
2014-05-20 16:40:30 +00:00
switch ( e . kind ( ) ) {
case expr_kind : : Var : case expr_kind : : Constant : case expr_kind : : Sort :
case expr_kind : : Meta : case expr_kind : : Local : case expr_kind : : Macro :
return e ;
2015-03-12 07:31:10 +00:00
case expr_kind : : Lambda : {
e = normalize_binding ( e ) ;
if ( m_use_eta )
return try_eta ( e ) ;
else
return e ;
}
case expr_kind : : Pi :
2014-05-20 16:40:30 +00:00
return normalize_binding ( e ) ;
case expr_kind : : App :
2014-05-20 18:53:58 +00:00
return normalize_app ( e ) ;
2014-05-20 16:40:30 +00:00
}
lean_unreachable ( ) ; // LCOV_EXCL_LINE
}
public :
2015-05-21 02:09:44 +00:00
normalize_fn ( type_checker & tc , bool save , bool eta , bool nested_prop = true ) :
2015-08-16 21:22:02 +00:00
m_tc ( tc ) , m_full_tc ( tc . env ( ) ) , m_ngen ( m_tc . mk_ngen ( ) ) ,
2014-10-27 21:49:11 +00:00
m_pred ( [ ] ( expr const & ) { return true ; } ) ,
2015-05-21 02:09:44 +00:00
m_save_cnstrs ( save ) , m_use_eta ( eta ) , m_eval_nested_prop ( nested_prop ) {
if ( ! is_standard ( env ( ) ) )
m_eval_nested_prop = true ;
}
2014-10-27 21:49:11 +00:00
2015-05-21 02:09:44 +00:00
normalize_fn ( type_checker & tc , std : : function < bool ( expr const & ) > const & fn , bool eta , bool nested_prop = true ) : // NOLINT
2015-08-16 21:22:02 +00:00
m_tc ( tc ) , m_full_tc ( tc . env ( ) ) , m_ngen ( m_tc . mk_ngen ( ) ) ,
2015-05-21 02:09:44 +00:00
m_pred ( fn ) , m_save_cnstrs ( true ) , m_use_eta ( eta ) , m_eval_nested_prop ( nested_prop ) {
if ( ! is_standard ( env ( ) ) )
m_eval_nested_prop = true ;
}
2014-10-27 21:49:11 +00:00
expr operator ( ) ( expr const & e ) {
m_cnstrs = constraint_seq ( ) ;
return normalize ( e ) ;
}
2014-09-27 03:16:03 +00:00
expr operator ( ) ( level_param_names const & ls , expr const & e ) {
2014-10-27 21:49:11 +00:00
m_cnstrs = constraint_seq ( ) ;
return m_tc . with_params ( ls , [ & ] ( ) {
2014-09-27 03:16:03 +00:00
return normalize ( e ) ;
} ) ;
}
2014-10-27 21:49:11 +00:00
constraint_seq get_cnstrs ( ) const { return m_cnstrs ; }
2014-05-20 16:40:30 +00:00
} ;
2015-03-12 07:31:10 +00:00
expr normalize ( environment const & env , expr const & e , bool eta ) {
2015-05-08 21:36:38 +00:00
auto tc = mk_type_checker ( env ) ;
2014-10-27 21:49:11 +00:00
bool save_cnstrs = false ;
2015-03-12 07:31:10 +00:00
return normalize_fn ( * tc , save_cnstrs , eta ) ( e ) ;
2014-10-27 21:49:11 +00:00
}
2015-03-12 07:31:10 +00:00
expr normalize ( environment const & env , level_param_names const & ls , expr const & e , bool eta ) {
2015-05-08 21:36:38 +00:00
auto tc = mk_type_checker ( env ) ;
2014-10-27 21:49:11 +00:00
bool save_cnstrs = false ;
2015-03-12 07:31:10 +00:00
return normalize_fn ( * tc , save_cnstrs , eta ) ( ls , e ) ;
2014-10-27 21:49:11 +00:00
}
2015-03-12 07:31:10 +00:00
expr normalize ( type_checker & tc , expr const & e , bool eta ) {
2014-10-27 21:49:11 +00:00
bool save_cnstrs = false ;
2015-03-12 07:31:10 +00:00
return normalize_fn ( tc , save_cnstrs , eta ) ( e ) ;
2014-10-27 21:49:11 +00:00
}
2015-05-21 02:09:44 +00:00
expr normalize ( type_checker & tc , level_param_names const & ls , expr const & e , bool eta , bool eval_nested_prop ) {
2015-02-07 23:19:41 +00:00
bool save_cnstrs = false ;
2015-05-21 02:09:44 +00:00
return normalize_fn ( tc , save_cnstrs , eta , eval_nested_prop ) ( ls , e ) ;
2015-02-07 23:19:41 +00:00
}
2015-03-12 07:31:10 +00:00
expr normalize ( type_checker & tc , expr const & e , constraint_seq & cs , bool eta ) {
bool save_cnstrs = false ;
normalize_fn fn ( tc , save_cnstrs , eta ) ;
2014-10-27 21:49:11 +00:00
expr r = fn ( e ) ;
cs + = fn . get_cnstrs ( ) ;
return r ;
}
2014-10-27 23:49:29 +00:00
expr normalize ( type_checker & tc , expr const & e , std : : function < bool ( expr const & ) > const & pred , // NOLINT
2015-03-12 07:31:10 +00:00
constraint_seq & cs , bool eta ) {
normalize_fn fn ( tc , pred , eta ) ;
2014-10-27 21:49:11 +00:00
expr r = fn ( e ) ;
cs + = fn . get_cnstrs ( ) ;
return r ;
}
2014-05-20 16:40:30 +00:00
}