2015-06-12 20:38:57 +00:00
/*
Copyright ( c ) 2015 Microsoft Corporation . All rights reserved .
Released under Apache 2.0 license as described in the file LICENSE .
Author : Leonardo de Moura
*/
# include "library/replace_visitor.h"
# include "library/normalize.h"
# include "library/reducible.h"
# include "library/class.h"
# include "library/relation_manager.h"
# include "library/user_recursors.h"
# include "library/coercion.h"
2015-11-19 23:30:38 +00:00
# include "library/blast/simplifier/simp_rule_set.h"
2015-11-18 23:41:44 +00:00
# include "library/blast/backward/backward_rule_set.h"
2015-11-24 23:22:21 +00:00
# include "library/blast/forward/pattern.h"
2015-12-03 02:28:45 +00:00
# include "library/blast/forward/forward_lemma_set.h"
2015-06-12 20:38:57 +00:00
# include "frontends/lean/decl_attributes.h"
# include "frontends/lean/parser.h"
# include "frontends/lean/tokens.h"
# include "frontends/lean/util.h"
namespace lean {
2015-06-18 00:23:20 +00:00
decl_attributes : : decl_attributes ( bool is_abbrev , bool persistent ) :
2015-06-12 20:38:57 +00:00
m_priority ( ) {
m_is_abbrev = is_abbrev ;
m_persistent = persistent ;
m_is_instance = false ;
2015-06-21 19:36:43 +00:00
m_is_trans_instance = false ;
2015-06-12 20:38:57 +00:00
m_is_coercion = false ;
m_is_reducible = is_abbrev ;
m_is_irreducible = false ;
m_is_semireducible = false ;
m_is_quasireducible = false ;
m_is_class = false ;
m_is_parsing_only = false ;
m_has_multiple_instances = false ;
2015-07-07 23:37:06 +00:00
m_unfold_full_hint = false ;
2015-06-12 20:38:57 +00:00
m_constructor_hint = false ;
m_symm = false ;
m_trans = false ;
m_refl = false ;
m_subst = false ;
m_recursor = false ;
2015-07-22 16:01:42 +00:00
m_simp = false ;
2015-07-23 00:21:47 +00:00
m_congr = false ;
2015-11-18 23:41:44 +00:00
m_backward = false ;
2015-11-26 01:44:58 +00:00
m_forward = false ;
2015-11-24 23:22:21 +00:00
m_no_pattern = false ;
2015-06-12 20:38:57 +00:00
}
2015-11-17 06:34:06 +00:00
void decl_attributes : : parse ( parser & p ) {
2015-06-12 20:38:57 +00:00
while ( true ) {
auto pos = p . pos ( ) ;
if ( p . curr_is_token ( get_instance_tk ( ) ) ) {
m_is_instance = true ;
2015-06-21 19:36:43 +00:00
if ( m_is_trans_instance )
2015-10-09 20:21:03 +00:00
throw parser_error ( " invalid '[instance]' attribute, '[trans_instance]' was already provided " , pos ) ;
2015-06-21 19:36:43 +00:00
p . next ( ) ;
} else if ( p . curr_is_token ( get_trans_inst_tk ( ) ) ) {
m_is_trans_instance = true ;
if ( m_is_instance )
2015-10-09 20:21:03 +00:00
throw parser_error ( " invalid '[trans_instance]' attribute, '[instance]' was already provided " , pos ) ;
2015-06-12 20:38:57 +00:00
p . next ( ) ;
} else if ( p . curr_is_token ( get_coercion_tk ( ) ) ) {
p . next ( ) ;
m_is_coercion = true ;
} else if ( p . curr_is_token ( get_reducible_tk ( ) ) ) {
if ( m_is_irreducible | | m_is_semireducible | | m_is_quasireducible )
throw parser_error ( " invalid '[reducible]' attribute, '[irreducible]', '[quasireducible]' or '[semireducible]' was already provided " , pos ) ;
m_is_reducible = true ;
p . next ( ) ;
} else if ( p . curr_is_token ( get_irreducible_tk ( ) ) ) {
if ( m_is_reducible | | m_is_semireducible | | m_is_quasireducible )
throw parser_error ( " invalid '[irreducible]' attribute, '[reducible]', '[quasireducible]' or '[semireducible]' was already provided " , pos ) ;
m_is_irreducible = true ;
p . next ( ) ;
} else if ( p . curr_is_token ( get_semireducible_tk ( ) ) ) {
if ( m_is_reducible | | m_is_irreducible | | m_is_quasireducible )
throw parser_error ( " invalid '[irreducible]' attribute, '[reducible]', '[quasireducible]' or '[irreducible]' was already provided " , pos ) ;
m_is_semireducible = true ;
p . next ( ) ;
} else if ( p . curr_is_token ( get_quasireducible_tk ( ) ) ) {
if ( m_is_reducible | | m_is_irreducible | | m_is_semireducible )
throw parser_error ( " invalid '[quasireducible]' attribute, '[reducible]', '[semireducible]' or '[irreducible]' was already provided " , pos ) ;
m_is_quasireducible = true ;
p . next ( ) ;
} else if ( p . curr_is_token ( get_class_tk ( ) ) ) {
m_is_class = true ;
p . next ( ) ;
} else if ( p . curr_is_token ( get_multiple_instances_tk ( ) ) ) {
m_has_multiple_instances = true ;
p . next ( ) ;
2015-06-30 23:22:52 +00:00
} else if ( auto it = parse_priority ( p ) ) {
2015-06-12 20:38:57 +00:00
m_priority = * it ;
2015-11-26 01:44:58 +00:00
if ( ! m_is_instance & & ! m_simp & & ! m_congr & & ! m_backward & & ! m_forward ) {
throw parser_error ( " invalid '[priority]' attribute, declaration must be marked as an '[instance]', '[simp]', '[congr]', '[backward]' or '[forward]' " , pos ) ;
2015-06-12 20:38:57 +00:00
}
} else if ( p . curr_is_token ( get_parsing_only_tk ( ) ) ) {
if ( ! m_is_abbrev )
2015-10-09 20:21:03 +00:00
throw parser_error ( " invalid '[parsing_only]' attribute, only abbreviations can be "
" marked as '[parsing_only]' " , pos ) ;
2015-06-12 20:38:57 +00:00
m_is_parsing_only = true ;
p . next ( ) ;
2015-07-07 23:37:06 +00:00
} else if ( p . curr_is_token ( get_unfold_full_tk ( ) ) ) {
2015-06-12 20:38:57 +00:00
p . next ( ) ;
2015-07-07 23:37:06 +00:00
m_unfold_full_hint = true ;
2015-06-12 20:38:57 +00:00
} else if ( p . curr_is_token ( get_constructor_tk ( ) ) ) {
p . next ( ) ;
m_constructor_hint = true ;
2015-07-07 23:37:06 +00:00
} else if ( p . curr_is_token ( get_unfold_tk ( ) ) ) {
2015-06-12 20:38:57 +00:00
p . next ( ) ;
2015-07-08 01:01:57 +00:00
buffer < unsigned > idxs ;
while ( true ) {
unsigned r = p . parse_small_nat ( ) ;
if ( r = = 0 )
throw parser_error ( " invalid '[unfold]' attribute, value must be greater than 0 " , pos ) ;
idxs . push_back ( r - 1 ) ;
if ( p . curr_is_token ( get_rbracket_tk ( ) ) )
break ;
}
p . next ( ) ;
m_unfold_hint = to_list ( idxs ) ;
2015-06-12 20:38:57 +00:00
} else if ( p . curr_is_token ( get_symm_tk ( ) ) ) {
p . next ( ) ;
m_symm = true ;
} else if ( p . curr_is_token ( get_refl_tk ( ) ) ) {
p . next ( ) ;
m_refl = true ;
} else if ( p . curr_is_token ( get_trans_tk ( ) ) ) {
p . next ( ) ;
m_trans = true ;
} else if ( p . curr_is_token ( get_subst_tk ( ) ) ) {
p . next ( ) ;
m_subst = true ;
2015-07-22 16:01:42 +00:00
} else if ( p . curr_is_token ( get_simp_attr_tk ( ) ) ) {
2015-06-12 20:38:57 +00:00
p . next ( ) ;
2015-07-22 16:01:42 +00:00
m_simp = true ;
2015-07-23 00:21:47 +00:00
} else if ( p . curr_is_token ( get_congr_attr_tk ( ) ) ) {
p . next ( ) ;
m_congr = true ;
2015-11-18 23:41:44 +00:00
} else if ( p . curr_is_token ( get_backward_attr_tk ( ) ) ) {
p . next ( ) ;
m_backward = true ;
2015-11-26 01:44:58 +00:00
} else if ( p . curr_is_token ( get_forward_attr_tk ( ) ) ) {
p . next ( ) ;
m_forward = true ;
2015-11-24 23:22:21 +00:00
} else if ( p . curr_is_token ( get_no_pattern_attr_tk ( ) ) ) {
p . next ( ) ;
m_no_pattern = true ;
2015-06-12 20:38:57 +00:00
} else if ( p . curr_is_token ( get_recursor_tk ( ) ) ) {
p . next ( ) ;
if ( ! p . curr_is_token ( get_rbracket_tk ( ) ) ) {
unsigned r = p . parse_small_nat ( ) ;
if ( r = = 0 )
throw parser_error ( " invalid '[recursor]' attribute, value must be greater than 0 " , pos ) ;
m_recursor_major_pos = r - 1 ;
}
p . check_token_next ( get_rbracket_tk ( ) , " invalid 'recursor', ']' expected " ) ;
m_recursor = true ;
} else {
break ;
}
}
}
environment decl_attributes : : apply ( environment env , io_state const & ios , name const & d ) const {
2015-11-26 19:41:56 +00:00
bool forward = m_forward ;
if ( has_pattern_hints ( env . get ( d ) . get_type ( ) ) ) {
// turn on [forward] if patterns hints have been used in the type.
forward = true ;
}
2015-06-12 20:38:57 +00:00
if ( m_is_instance ) {
if ( m_priority ) {
# if defined(__GNUC__) && !defined(__CLANG__)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
# endif
env = add_instance ( env , d , * m_priority , m_persistent ) ;
} else {
env = add_instance ( env , d , m_persistent ) ;
}
}
2015-06-21 19:36:43 +00:00
if ( m_is_trans_instance ) {
if ( m_priority ) {
# if defined(__GNUC__) && !defined(__CLANG__)
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
# endif
env = add_trans_instance ( env , d , * m_priority , m_persistent ) ;
} else {
env = add_trans_instance ( env , d , m_persistent ) ;
}
}
2015-06-12 20:38:57 +00:00
if ( m_is_coercion )
2015-07-01 23:32:34 +00:00
env = add_coercion ( env , ios , d , m_persistent ) ;
2015-06-12 20:38:57 +00:00
auto decl = env . find ( d ) ;
if ( decl & & decl - > is_definition ( ) ) {
if ( m_is_reducible )
env = set_reducible ( env , d , reducible_status : : Reducible , m_persistent ) ;
if ( m_is_irreducible )
env = set_reducible ( env , d , reducible_status : : Irreducible , m_persistent ) ;
if ( m_is_semireducible )
env = set_reducible ( env , d , reducible_status : : Semireducible , m_persistent ) ;
if ( m_is_quasireducible )
env = set_reducible ( env , d , reducible_status : : Quasireducible , m_persistent ) ;
2015-07-07 23:37:06 +00:00
if ( m_unfold_hint )
2015-07-08 01:01:57 +00:00
env = add_unfold_hint ( env , d , m_unfold_hint , m_persistent ) ;
2015-07-07 23:37:06 +00:00
if ( m_unfold_full_hint )
env = add_unfold_full_hint ( env , d , m_persistent ) ;
2015-06-12 20:38:57 +00:00
}
if ( m_constructor_hint )
env = add_constructor_hint ( env , d , m_persistent ) ;
if ( m_symm )
env = add_symm ( env , d , m_persistent ) ;
if ( m_refl )
env = add_refl ( env , d , m_persistent ) ;
if ( m_trans )
env = add_trans ( env , d , m_persistent ) ;
if ( m_subst )
env = add_subst ( env , d , m_persistent ) ;
if ( m_recursor )
env = add_user_recursor ( env , d , m_recursor_major_pos , m_persistent ) ;
if ( m_is_class )
env = add_class ( env , d , m_persistent ) ;
2015-11-17 06:34:06 +00:00
if ( m_simp ) {
if ( m_priority )
env = add_simp_rule ( env , d , * m_priority , m_persistent ) ;
else
env = add_simp_rule ( env , d , LEAN_SIMP_DEFAULT_PRIORITY , m_persistent ) ;
}
if ( m_congr ) {
if ( m_priority )
env = add_congr_rule ( env , d , * m_priority , m_persistent ) ;
else
env = add_congr_rule ( env , d , LEAN_SIMP_DEFAULT_PRIORITY , m_persistent ) ;
}
2015-11-18 23:41:44 +00:00
if ( m_backward ) {
if ( m_priority )
env = add_backward_rule ( env , d , * m_priority , m_persistent ) ;
else
env = add_backward_rule ( env , d , LEAN_BACKWARD_DEFAULT_PRIORITY , m_persistent ) ;
}
2015-11-26 19:41:56 +00:00
if ( forward ) {
2015-11-26 01:44:58 +00:00
if ( m_priority )
2015-12-03 02:28:45 +00:00
env = add_forward_lemma ( env , d , * m_priority , m_persistent ) ;
2015-11-26 01:44:58 +00:00
else
2015-12-03 02:28:45 +00:00
env = add_forward_lemma ( env , d , LEAN_FORWARD_LEMMA_DEFAULT_PRIORITY , m_persistent ) ;
2015-11-26 01:44:58 +00:00
}
2015-11-24 23:22:21 +00:00
if ( m_no_pattern ) {
env = add_no_pattern ( env , d , m_persistent ) ;
}
2015-06-12 20:38:57 +00:00
if ( m_has_multiple_instances )
env = mark_multiple_instances ( env , d , m_persistent ) ;
return env ;
}
2015-06-13 00:32:18 +00:00
void decl_attributes : : write ( serializer & s ) const {
2015-06-21 19:36:43 +00:00
s < < m_is_abbrev < < m_persistent < < m_is_instance < < m_is_trans_instance < < m_is_coercion
2015-06-13 00:32:18 +00:00
< < m_is_reducible < < m_is_irreducible < < m_is_semireducible < < m_is_quasireducible
2015-07-07 23:37:06 +00:00
< < m_is_class < < m_is_parsing_only < < m_has_multiple_instances < < m_unfold_full_hint
2015-06-13 00:32:18 +00:00
< < m_constructor_hint < < m_symm < < m_trans < < m_refl < < m_subst < < m_recursor
2015-11-26 01:44:58 +00:00
< < m_simp < < m_congr < < m_recursor_major_pos < < m_priority < < m_backward
< < m_forward < < m_no_pattern ;
2015-07-08 01:01:57 +00:00
write_list ( s , m_unfold_hint ) ;
2015-06-13 00:32:18 +00:00
}
void decl_attributes : : read ( deserializer & d ) {
2015-06-21 19:36:43 +00:00
d > > m_is_abbrev > > m_persistent > > m_is_instance > > m_is_trans_instance > > m_is_coercion
2015-06-13 00:32:18 +00:00
> > m_is_reducible > > m_is_irreducible > > m_is_semireducible > > m_is_quasireducible
2015-07-07 23:37:06 +00:00
> > m_is_class > > m_is_parsing_only > > m_has_multiple_instances > > m_unfold_full_hint
2015-06-13 00:32:18 +00:00
> > m_constructor_hint > > m_symm > > m_trans > > m_refl > > m_subst > > m_recursor
2015-11-26 01:44:58 +00:00
> > m_simp > > m_congr > > m_recursor_major_pos > > m_priority > > m_backward
> > m_forward > > m_no_pattern ;
2015-07-08 01:01:57 +00:00
m_unfold_hint = read_list < unsigned > ( d ) ;
2015-06-13 00:32:18 +00:00
}
2015-06-12 20:38:57 +00:00
}