2013-07-29 05:34:39 +00:00
/*
2014-04-18 21:21:49 +00:00
Copyright ( c ) 2013 - 2014 Microsoft Corporation . All rights reserved .
2013-07-29 05:34:39 +00:00
Released under Apache 2.0 license as described in the file LICENSE .
Author : Leonardo de Moura
*/
2014-04-18 21:21:49 +00:00
# include <limits>
2013-09-13 03:04:10 +00:00
# include "kernel/environment.h"
2014-04-18 21:21:49 +00:00
# include "kernel/kernel_exception.h"
2013-07-29 05:34:39 +00:00
namespace lean {
2013-12-13 00:33:31 +00:00
/**
2014-04-18 21:21:49 +00:00
\ brief " Do nothing " normalizer extension .
2013-12-13 00:33:31 +00:00
*/
2014-04-18 21:21:49 +00:00
class noop_normalizer_extension : public normalizer_extension {
public :
virtual optional < std : : pair < expr , constraints > > operator ( ) ( expr const & , environment const & , type_checker & ) const {
return optional < std : : pair < expr , constraints > > ( ) ;
2013-12-13 00:33:31 +00:00
}
2014-04-18 21:21:49 +00:00
} ;
2013-08-06 19:24:20 +00:00
2014-04-21 20:38:39 +00:00
environment_header : : environment_header ( unsigned trust_lvl , bool proof_irrel , bool eta , std : : unique_ptr < normalizer_extension const > ext ) :
m_trust_lvl ( trust_lvl ) , m_proof_irrel ( proof_irrel ) , m_eta ( eta ) , m_norm_ext ( std : : move ( ext ) ) { }
2013-12-22 19:51:38 +00:00
2014-04-18 21:21:49 +00:00
environment_extension : : ~ environment_extension ( ) { }
2013-08-05 03:52:14 +00:00
2014-04-21 21:28:50 +00:00
environment_id : : environment_id ( ) : m_trail ( 0 , list < unsigned > ( ) ) { }
environment_id : : environment_id ( environment_id const & ancestor , bool ) : m_trail ( car ( ancestor . m_trail ) + 1 , ancestor . m_trail ) { }
bool environment_id : : is_descendant ( environment_id const & id ) const {
list < unsigned > const * it = & m_trail ;
while ( ! is_nil ( * it ) ) {
if ( is_eqp ( * it , id . m_trail ) )
return true ;
if ( car ( * it ) > = car ( id . m_trail ) )
return false ;
it = & cdr ( * it ) ;
}
return false ;
}
environment : : environment ( header const & h , environment_id const & ancestor , definitions const & d , extensions const & exts ) :
m_header ( h ) , m_id ( environment_id : : mk_descendant ( ancestor ) ) , m_definitions ( d ) , m_extensions ( exts ) { }
2013-08-06 03:06:07 +00:00
2014-04-21 20:38:39 +00:00
environment : : environment ( unsigned trust_lvl , bool proof_irrel , bool eta ) :
environment ( trust_lvl , proof_irrel , eta , std : : unique_ptr < normalizer_extension > ( new noop_normalizer_extension ( ) ) )
2014-04-18 21:21:49 +00:00
{ }
2014-01-15 19:02:47 +00:00
2014-04-21 20:38:39 +00:00
environment : : environment ( unsigned trust_lvl , bool proof_irrel , bool eta , std : : unique_ptr < normalizer_extension > ext ) :
m_header ( std : : make_shared < environment_header > ( trust_lvl , proof_irrel , eta , std : : move ( ext ) ) ) ,
2014-04-18 21:21:49 +00:00
m_extensions ( std : : make_shared < environment_extensions const > ( ) )
{ }
2013-08-15 01:16:11 +00:00
2014-04-18 21:21:49 +00:00
optional < definition > environment : : find ( name const & n ) const {
definition const * r = m_definitions . find ( n ) ;
return r ? some_definition ( * r ) : none_definition ( ) ;
2013-08-05 03:52:14 +00:00
}
2014-04-18 21:21:49 +00:00
definition environment : : get ( name const & n ) const {
definition const * r = m_definitions . find ( n ) ;
if ( ! r )
throw_unknown_declaration ( * this , n ) ;
return * r ;
2013-08-17 17:55:42 +00:00
}
2014-04-18 21:21:49 +00:00
[[ noreturn ]] void throw_incompatible_environment ( environment const & env ) {
throw_kernel_exception ( env , " invalid declaration, it was checked/certified in an incompatible environment " ) ;
2013-12-29 01:31:35 +00:00
}
2014-04-18 21:21:49 +00:00
environment environment : : add ( certified_definition const & d ) const {
2014-04-21 21:28:50 +00:00
if ( ! m_id . is_descendant ( d . get_id ( ) ) )
2014-04-18 21:21:49 +00:00
throw_incompatible_environment ( * this ) ;
name const & n = d . get_definition ( ) . get_name ( ) ;
if ( find ( n ) )
throw_already_declared ( * this , n ) ;
2014-04-21 21:28:50 +00:00
return environment ( m_header , m_id , insert ( m_definitions , n , d . get_definition ( ) ) , m_extensions ) ;
2013-12-29 11:43:45 +00:00
}
2014-04-18 21:21:49 +00:00
environment environment : : replace ( certified_definition const & t ) const {
2014-04-21 21:28:50 +00:00
if ( ! m_id . is_descendant ( t . get_id ( ) ) )
2014-04-18 21:21:49 +00:00
throw_incompatible_environment ( * this ) ;
name const & n = t . get_definition ( ) . get_name ( ) ;
auto ax = find ( n ) ;
if ( ! ax )
throw_kernel_exception ( * this , " invalid replacement of axiom with theorem, the environment does not have an axiom with the given name " ) ;
if ( ! ax - > is_axiom ( ) )
throw_kernel_exception ( * this , " invalid replacement of axiom with theorem, the current declaration in the environment is not an axiom " ) ;
if ( ! t . get_definition ( ) . is_theorem ( ) )
throw_kernel_exception ( * this , " invalid replacement of axiom with theorem, the new declaration is not a theorem " ) ;
if ( ax - > get_type ( ) ! = t . get_definition ( ) . get_type ( ) )
throw_kernel_exception ( * this , " invalid replacement of axiom with theorem, the 'replace' operation can only be used when the axiom and theorem have the same type " ) ;
2014-04-21 21:28:50 +00:00
return environment ( m_header , m_id , insert ( m_definitions , n , t . get_definition ( ) ) , m_extensions ) ;
2013-12-29 01:31:35 +00:00
}
2014-04-18 21:21:49 +00:00
class extension_manager {
std : : vector < std : : shared_ptr < environment_extension const > > m_exts ;
mutex m_mutex ;
public :
unsigned register_extension ( std : : shared_ptr < environment_extension const > const & ext ) {
lock_guard < mutex > lock ( m_mutex ) ;
unsigned r = m_exts . size ( ) ;
m_exts . push_back ( ext ) ;
return r ;
2013-12-29 01:31:35 +00:00
}
2013-08-08 23:12:46 +00:00
2014-04-18 21:21:49 +00:00
bool has_ext ( unsigned extid ) const { return extid < m_exts . size ( ) ; }
2013-12-29 03:20:04 +00:00
2014-04-18 21:21:49 +00:00
environment_extension const & get_initial ( unsigned extid ) {
lock_guard < mutex > lock ( m_mutex ) ;
return * ( m_exts [ extid ] . get ( ) ) ;
2014-01-31 07:02:19 +00:00
}
2014-04-18 21:21:49 +00:00
} ;
2013-11-07 19:29:01 +00:00
2014-04-18 21:21:49 +00:00
static std : : unique_ptr < extension_manager > g_extension_manager ;
2013-11-07 03:21:22 +00:00
2014-04-18 21:21:49 +00:00
static extension_manager & get_extension_manager ( ) {
if ( ! g_extension_manager )
g_extension_manager . reset ( new extension_manager ( ) ) ;
return * g_extension_manager ;
2013-11-07 03:21:22 +00:00
}
2014-04-18 21:21:49 +00:00
unsigned environment : : register_extension ( std : : shared_ptr < environment_extension const > const & initial ) {
return get_extension_manager ( ) . register_extension ( initial ) ;
2013-11-07 03:21:22 +00:00
}
2014-04-18 21:21:49 +00:00
[[ noreturn ]] void throw_invalid_extension ( environment const & env ) {
throw_kernel_exception ( env , " invalid environment extension identifier " ) ;
2013-11-07 03:21:22 +00:00
}
2013-11-12 04:29:53 +00:00
2014-04-18 21:21:49 +00:00
environment_extension const & environment : : get_extension ( unsigned id ) const {
if ( id > = get_extension_manager ( ) . has_ext ( id ) )
throw_invalid_extension ( * this ) ;
if ( id < m_extensions - > size ( ) | | ! ( * m_extensions ) [ id ] )
return get_extension_manager ( ) . get_initial ( id ) ;
return * ( ( * m_extensions ) [ id ] . get ( ) ) ;
2013-11-12 04:29:53 +00:00
}
2014-04-18 21:21:49 +00:00
environment environment : : update ( unsigned id , std : : shared_ptr < environment_extension const > const & ext ) const {
if ( id > = get_extension_manager ( ) . has_ext ( id ) )
throw_invalid_extension ( * this ) ;
auto new_exts = std : : make_shared < environment_extensions > ( * m_extensions ) ;
if ( id > = new_exts - > size ( ) )
new_exts - > resize ( id + 1 ) ;
( * new_exts ) [ id ] = ext ;
2014-04-21 21:28:50 +00:00
return environment ( m_header , m_id , m_definitions , new_exts ) ;
2013-11-12 04:29:53 +00:00
}
2013-07-29 05:34:39 +00:00
}