2013-08-04 16:37:52 +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 "expr.h"
namespace lean {
2013-08-06 03:06:07 +00:00
/**
2013-08-15 17:46:13 +00:00
\ brief Return unit if < tt > num_args = = 0 < / tt > , args [ 0 ] if < tt > num_args = = 1 < / tt > , and
< tt > ( op args [ 0 ] ( op args [ 1 ] ( op . . . ) ) ) < / tt >
2013-08-06 03:06:07 +00:00
*/
2013-08-16 16:04:59 +00:00
expr mk_bin_rop ( expr const & op , expr const & unit , unsigned num_args , expr const * args ) ;
expr mk_bin_rop ( expr const & op , expr const & unit , std : : initializer_list < expr > const & l ) ;
/**
\ brief Return unit if < tt > num_args = = 0 < / tt > , args [ 0 ] if < tt > num_args = = 1 < / tt > , and
< tt > ( op . . . ( op ( op args [ 0 ] args [ 1 ] ) args [ 2 ] ) . . . ) < / tt >
*/
expr mk_bin_lop ( expr const & op , expr const & unit , unsigned num_args , expr const * args ) ;
expr mk_bin_lop ( expr const & op , expr const & unit , std : : initializer_list < expr > const & l ) ;
2013-08-06 03:06:07 +00:00
/** \brief Return (Type m) m >= bottom + Offset */
2013-09-02 16:11:53 +00:00
extern expr const TypeM ;
2013-08-06 03:06:07 +00:00
/** \brief Return (Type u) u >= m + Offset */
2013-09-02 16:11:53 +00:00
extern expr const TypeU ;
2013-08-06 03:06:07 +00:00
/** \brief Return the Lean Boolean type. */
2013-08-06 18:27:14 +00:00
expr mk_bool_type ( ) ;
2013-09-02 16:11:53 +00:00
extern expr const Bool ;
2013-08-04 16:37:52 +00:00
2013-08-06 03:06:07 +00:00
/** \brief Create a Lean Boolean value (true/false) */
2013-08-06 18:27:14 +00:00
expr mk_bool_value ( bool v ) ;
2013-09-02 16:11:53 +00:00
extern expr const True ;
extern expr const False ;
2013-08-06 03:06:07 +00:00
/** \brief Return true iff \c e is a Lean Boolean value. */
2013-08-04 16:37:52 +00:00
bool is_bool_value ( expr const & e ) ;
2013-08-06 03:06:07 +00:00
/**
\ brief Convert a Lean Boolean value into a C + + Boolean value .
\ pre is_bool_value ( e )
*/
2013-08-04 16:37:52 +00:00
bool to_bool ( expr const & e ) ;
2013-08-06 03:06:07 +00:00
/** \brief Return true iff \c e is the Lean true value. */
2013-08-04 16:37:52 +00:00
bool is_true ( expr const & e ) ;
2013-08-06 03:06:07 +00:00
/** \brief Return true iff \c e is the Lean false value. */
2013-08-04 16:37:52 +00:00
bool is_false ( expr const & e ) ;
2013-08-05 21:23:43 +00:00
2013-08-06 03:06:07 +00:00
/** \brief Return the Lean If-Then-Else operator. It has type: pi (A : Type), bool -> A -> A -> A */
2013-08-06 18:27:14 +00:00
expr mk_if_fn ( ) ;
2013-08-06 03:06:07 +00:00
/** \brief Return the term (if A c t e) */
2013-08-06 18:27:14 +00:00
inline expr mk_if ( expr const & A , expr const & c , expr const & t , expr const & e ) { return mk_app ( mk_if_fn ( ) , A , c , t , e ) ; }
inline expr If ( expr const & A , expr const & c , expr const & t , expr const & e ) { return mk_if ( A , c , t , e ) ; }
2013-08-06 03:06:07 +00:00
/** \brief Return the term (if bool c t e) */
2013-08-06 18:27:14 +00:00
inline expr mk_bool_if ( expr const & c , expr const & t , expr const & e ) { return mk_if ( mk_bool_type ( ) , c , t , e ) ; }
inline expr bIf ( expr const & c , expr const & t , expr const & e ) { return mk_bool_if ( c , t , e ) ; }
2013-08-06 03:06:07 +00:00
2013-08-07 08:16:37 +00:00
/** \brief Return the Lean Implies operator */
2013-08-07 03:21:43 +00:00
expr mk_implies_fn ( ) ;
2013-08-07 08:16:37 +00:00
/** \brief Return the term (e1 => e2) */
2013-08-07 03:21:43 +00:00
inline expr mk_implies ( expr const & e1 , expr const & e2 ) { return mk_app ( mk_implies_fn ( ) , e1 , e2 ) ; }
2013-08-16 16:04:59 +00:00
inline expr mk_implies ( unsigned num_args , expr const * args ) { lean_assert ( num_args > = 2 ) ; return mk_bin_rop ( mk_implies_fn ( ) , False , num_args , args ) ; }
2013-08-07 03:21:43 +00:00
inline expr Implies ( expr const & e1 , expr const & e2 ) { return mk_implies ( e1 , e2 ) ; }
2013-08-16 16:04:59 +00:00
inline expr Implies ( std : : initializer_list < expr > const & l ) { return mk_implies ( l . size ( ) , l . begin ( ) ) ; }
2013-08-07 03:21:43 +00:00
2013-08-18 22:03:58 +00:00
/** \brief Return the Lean Iff operator */
expr mk_iff_fn ( ) ;
/** \brief Return (e1 iff e2) */
inline expr mk_iff ( expr const & e1 , expr const & e2 ) { return mk_app ( mk_iff_fn ( ) , e1 , e2 ) ; }
inline expr mk_iff ( unsigned num_args , expr const * args ) { return mk_bin_rop ( mk_iff_fn ( ) , True , num_args , args ) ; }
inline expr Iff ( expr const & e1 , expr const & e2 ) { return mk_iff ( e1 , e2 ) ; }
inline expr Iff ( std : : initializer_list < expr > const & l ) { return mk_iff ( l . size ( ) , l . begin ( ) ) ; }
2013-08-07 08:16:37 +00:00
/** \brief Return the Lean And operator */
2013-08-06 18:27:14 +00:00
expr mk_and_fn ( ) ;
2013-08-07 08:16:37 +00:00
/** \brief Return (e1 and e2) */
2013-08-06 18:27:14 +00:00
inline expr mk_and ( expr const & e1 , expr const & e2 ) { return mk_app ( mk_and_fn ( ) , e1 , e2 ) ; }
2013-08-16 16:04:59 +00:00
inline expr mk_and ( unsigned num_args , expr const * args ) { return mk_bin_rop ( mk_and_fn ( ) , True , num_args , args ) ; }
2013-08-06 18:27:14 +00:00
inline expr And ( expr const & e1 , expr const & e2 ) { return mk_and ( e1 , e2 ) ; }
inline expr And ( std : : initializer_list < expr > const & l ) { return mk_and ( l . size ( ) , l . begin ( ) ) ; }
2013-08-06 03:06:07 +00:00
2013-08-07 08:16:37 +00:00
/** \brief Return the Lean Or operator */
2013-08-06 18:27:14 +00:00
expr mk_or_fn ( ) ;
2013-08-07 08:16:37 +00:00
/** \brief Return (e1 Or e2) */
2013-08-06 18:27:14 +00:00
inline expr mk_or ( expr const & e1 , expr const & e2 ) { return mk_app ( mk_or_fn ( ) , e1 , e2 ) ; }
2013-08-16 16:04:59 +00:00
inline expr mk_or ( unsigned num_args , expr const * args ) { return mk_bin_rop ( mk_or_fn ( ) , False , num_args , args ) ; }
2013-08-06 18:27:14 +00:00
inline expr Or ( expr const & e1 , expr const & e2 ) { return mk_or ( e1 , e2 ) ; }
inline expr Or ( std : : initializer_list < expr > const & l ) { return mk_or ( l . size ( ) , l . begin ( ) ) ; }
2013-08-06 03:06:07 +00:00
/** \brief Return the Lean not operator */
2013-08-06 18:27:14 +00:00
expr mk_not_fn ( ) ;
2013-08-07 08:16:37 +00:00
/** \brief Return (Not e) */
2013-08-06 18:27:14 +00:00
inline expr mk_not ( expr const & e ) { return mk_app ( mk_not_fn ( ) , e ) ; }
inline expr Not ( expr const & e ) { return mk_not ( e ) ; }
2013-08-06 03:06:07 +00:00
2013-08-15 17:46:13 +00:00
/** \brief Return the Lean forall operator. It has type: <tt>Pi (A : Type), (A -> bool) -> Bool</tt> */
2013-08-06 18:27:14 +00:00
expr mk_forall_fn ( ) ;
2013-08-07 08:16:37 +00:00
/** \brief Return the term (Forall A P), where A is a type and P : A -> bool */
2013-08-06 18:27:14 +00:00
inline expr mk_forall ( expr const & A , expr const & P ) { return mk_app ( mk_forall_fn ( ) , A , P ) ; }
inline expr Forall ( expr const & A , expr const & P ) { return mk_forall ( A , P ) ; }
2013-08-06 03:06:07 +00:00
2013-08-15 17:46:13 +00:00
/** \brief Return the Lean exists operator. It has type: <tt>Pi (A : Type), (A -> Bool) -> Bool</tt> */
2013-08-06 18:27:14 +00:00
expr mk_exists_fn ( ) ;
2013-08-06 03:06:07 +00:00
/** \brief Return the term (exists A P), where A is a type and P : A -> bool */
2013-08-06 18:27:14 +00:00
inline expr mk_exists ( expr const & A , expr const & P ) { return mk_app ( mk_exists_fn ( ) , A , P ) ; }
inline expr Exists ( expr const & A , expr const & P ) { return mk_exists ( A , P ) ; }
2013-08-06 03:06:07 +00:00
2013-08-30 21:26:12 +00:00
/** \brief Homogeneous equality. It has type: <tt>Pi (A : Type), A -> A -> Bool */
expr mk_homo_eq_fn ( ) ;
/** \brief Return the term (homo_eq A l r) */
inline expr mk_homo_eq ( expr const & A , expr const & l , expr const & r ) { return mk_app ( mk_homo_eq_fn ( ) , A , l , r ) ; }
inline expr hEq ( expr const & A , expr const & l , expr const & r ) { return mk_homo_eq ( A , l , r ) ; }
2013-09-07 01:31:47 +00:00
/** \brief Type Cast. It has type <tt>Pi (A : Type u) (B : Type u) (H : A = B) (a : A), B</tt> */
expr mk_cast_fn ( ) ;
/** \brief Return the term (cast A B H a) */
inline expr mk_cast ( expr const & A , expr const & B , expr const & H , expr const & a ) { return mk_app ( mk_cast_fn ( ) , A , B , H , a ) ; }
inline expr Cast ( expr const & A , expr const & B , expr const & H , expr const & a ) { return mk_cast ( A , B , H , a ) ; }
2013-08-07 08:16:37 +00:00
/** \brief Modus Ponens axiom */
2013-08-07 03:21:43 +00:00
expr mk_mp_fn ( ) ;
2013-08-08 04:47:58 +00:00
/** \brief (Axiom) {a : Bool}, {b : Bool}, H1 : a => b, H2 : a |- MP(a, b, H1, H2) : b */
2013-08-07 03:21:43 +00:00
inline expr MP ( expr const & a , expr const & b , expr const & H1 , expr const & H2 ) { return mk_app ( mk_mp_fn ( ) , a , b , H1 , H2 ) ; }
2013-08-07 08:16:37 +00:00
/** \brief Discharge axiom */
2013-08-07 03:21:43 +00:00
expr mk_discharge_fn ( ) ;
2013-08-08 04:47:58 +00:00
/** \brief (Axiom) {a : Bool}, {b : Bool}, H : a -> b |- Discharge(a, b, H) : a => b */
2013-08-07 03:21:43 +00:00
inline expr Discharge ( expr const & a , expr const & b , expr const & H ) { return mk_app ( mk_discharge_fn ( ) , a , b , H ) ; }
2013-08-06 18:27:14 +00:00
2013-08-07 08:16:37 +00:00
/** \brief Reflexivity axiom */
2013-08-06 18:27:14 +00:00
expr mk_refl_fn ( ) ;
2013-08-08 04:47:58 +00:00
/** \brief (Axiom) {A : Type u}, a : A |- Refl(A, a) : a = a */
2013-08-06 18:27:14 +00:00
inline expr Refl ( expr const & A , expr const & a ) { return mk_app ( mk_refl_fn ( ) , A , a ) ; }
2013-08-06 21:37:30 +00:00
2013-08-07 08:16:37 +00:00
/** \brief Case analysis axiom */
expr mk_case_fn ( ) ;
/** \brief (Axiom) P : Bool -> Bool, H1 : P True, H2 : P False, a : Bool |- Case(P, H1, H2, a) : P a */
inline expr Case ( expr const & P , expr const & H1 , expr const & H2 , expr const & a ) { return mk_app ( mk_case_fn ( ) , P , H1 , H2 , a ) ; }
/** \brief Substitution axiom */
2013-08-06 18:27:14 +00:00
expr mk_subst_fn ( ) ;
2013-08-08 04:47:58 +00:00
/** \brief (Axiom) {A : Type u}, {a b : A}, P : A -> Bool, H1 : P a, H2 : a = b |- Subst(A, a, b, P, H1, H2) : P b */
inline expr Subst ( expr const & A , expr const & a , expr const & b , expr const & P , expr const & H1 , expr const & H2 ) { return mk_app ( { mk_subst_fn ( ) , A , a , b , P , H1 , H2 } ) ; }
2013-08-06 21:37:30 +00:00
2013-08-07 08:16:37 +00:00
/** \brief Eta conversion axiom */
2013-08-06 21:47:13 +00:00
expr mk_eta_fn ( ) ;
2013-08-08 04:47:58 +00:00
/** \brief (Axiom) {A : Type u}, {B : A -> Type u}, f : (Pi x : A, B x) |- Eta(A, B, f) : ((Fun x : A => f x) = f) */
2013-08-06 21:47:13 +00:00
inline expr Eta ( expr const & A , expr const & B , expr const & f ) { return mk_app ( mk_eta_fn ( ) , A , B , f ) ; }
2013-08-07 15:29:20 +00:00
/** \brief Implies Anti-symmetry */
expr mk_imp_antisym_fn ( ) ;
2013-08-08 04:47:58 +00:00
/** \brief (Axiom) {a : Bool}, {b : Bool}, H1 : a => b, H2 : b => a |- ImpAntisym(a, b, H1, H2) : a = b */
2013-08-07 15:29:20 +00:00
inline expr ImpAntisym ( expr const & a , expr const & b , expr const & H1 , expr const & H2 ) { return mk_app ( mk_imp_antisym_fn ( ) , a , b , H1 , H2 ) ; }
2013-09-07 01:31:47 +00:00
/** \brief Domain Injectivity. It has type <tt>Pi (A A': Type u) (B : A -> Type u) (B' : A' -> Type u) (H : (Pi x : A, B x) = (Pi x : A', B' x)), A = A' </tt> */
expr mk_dom_inj_fn ( ) ;
/** \brief Return the term (DomInj A A' B B' H) */
inline expr mk_dom_inj ( expr const & A , expr const & Ap , expr const & B , expr const & Bp , expr const & H ) { return mk_app ( { mk_dom_inj_fn ( ) , A , Ap , B , Bp , H } ) ; }
inline expr DomInj ( expr const & A , expr const & Ap , expr const & B , expr const & Bp , expr const & H ) { return mk_dom_inj ( A , Ap , B , Bp , H ) ; }
/** \brief Range Injectivity. It has type <tt>Pi (A A': Type u) (B : A -> Type u) (B' : A' -> Type u) (H : (Pi x : A, B x) = (Pi x : A', B' x)) (a : A),
B a = B ' ( cast A A ' ( DomInj A A ' B B ' H ) a ) < / tt >
*/
expr mk_ran_inj_fn ( ) ;
/** \brief Return the term (RanInj A A' B B' H) */
inline expr mk_ran_inj ( expr const & A , expr const & Ap , expr const & B , expr const & Bp , expr const & H , expr const & a ) { return mk_app ( { mk_ran_inj_fn ( ) , A , Ap , B , Bp , H , a } ) ; }
inline expr RanInj ( expr const & A , expr const & Ap , expr const & B , expr const & Bp , expr const & H , expr const & a ) { return mk_ran_inj ( A , Ap , B , Bp , H , a ) ; }
2013-08-05 21:23:43 +00:00
class environment ;
2013-08-06 03:06:07 +00:00
/** \brief Initialize the environment with basic builtin declarations and axioms */
2013-08-05 21:23:43 +00:00
void add_basic_theory ( environment & env ) ;
/**
\ brief Helper macro for defining constants such as bool_type , int_type , int_add , etc .
*/
# define MK_BUILTIN(Name, ClassName) \
2013-08-06 18:27:14 +00:00
expr mk_ # # Name ( ) { \
static thread_local expr r = mk_value ( * ( new ClassName ( ) ) ) ; \
2013-08-05 21:23:43 +00:00
return r ; \
} \
/**
\ brief Helper macro for generating " defined " constants .
*/
2013-08-06 03:06:07 +00:00
# define MK_CONSTANT(Name, NameObj) \
static name Name # # _name = NameObj ; \
2013-08-06 18:27:14 +00:00
expr mk_ # # Name ( ) { \
static thread_local expr r = mk_constant ( Name # # _name ) ; \
2013-08-06 03:06:07 +00:00
return r ; \
2013-08-05 21:23:43 +00:00
}
2013-08-04 16:37:52 +00:00
}