Kernel Objects and Theorems
proof_kernel.hproof_kernel.h is the vocabulary of a proof block. A [[cst::proof]][[cst::proof]] function does not write separation-logic formulas as syntax; it builds them as HOL objects, and every object it needs that the logic builds in — the connectives, the heap-proposition constants, the C types, the theorems the kernel ships — reaches C code through an accessor declared in this header.
There are three kinds of thing here, and only three. Opaque handle types (termterm, thmthm, typetype, and their list and pair companions) are the currency every other header traffics in. Constant accessors — functions returning a termterm or a typetype — name the pieces of syntax a proof assembles into a goal. Theorem accessors — functions returning a thmthm — name the kernel’s proved rules, the things a proof cites. Nothing here performs inference: the rules that apply a theorem are in hol_prover_client.hhol_prover_client.h, and the engine calls that consume the result are in symexec.hsymexec.h.
This page is a name-indexed catalogue in header order. It says what is declared, under what name, and — where the header records it — the exact HOL statement the accessor returns. It does not explain the logic. The conceptual presentation, with the rules grouped by what they do, the primitive laws separated from their consequences, and the axioms flagged as axioms, is Proof Rules the predicates many of the theorems talk about are in Typed Memory Predicates.
Every logical object lives in the prover, not in the C process. The C side holds handles: pointers to structures the header declares but never defines. This is deliberate — a termterm cannot be inspected, allocated or forged by proof code, only passed back to the kernel, which is how the LCF discipline survives the language boundary (see LCF-Based Proof).
typedef struct hol_term term;typedef struct hol_theorem thm;typedef struct hol_type type;typedef struct hol_conversion conv;typedef struct hol_term_pair term_pair;typedef struct hol_thm_pair thm_pair;typedef struct hol_type_pair type_pair;typedef struct hol_instantiation instantiation;typedef struct new_datatype_definition_results indtype;typedef struct new_inductive_definition_results inddef;
typedef struct hol_term term;typedef struct hol_theorem thm;typedef struct hol_type type;typedef struct hol_conversion conv;typedef struct hol_term_pair term_pair;typedef struct hol_thm_pair thm_pair;typedef struct hol_type_pair type_pair;typedef struct hol_instantiation instantiation;typedef struct new_datatype_definition_results indtype;typedef struct new_inductive_definition_results inddef;
termterm is a HOL term — a formula, an expression, an hprophprop. thmthm is a theorem: a sequent the kernel has proved, and the one type C code cannot construct except through an inference rule. typetype is a HOL type, such as :hprop:hprop or :ctype:ctype. convconv is a conversion, a rewriting function from a term to an equational theorem; the conversion combinators are in HOL API: Conversions and Solvers.
The last three are results rather than syntax. instantiationinstantiation is the substitution produced by matching one term against another and consumed by the instantiation rules. indtypeindtype and inddefinddef package what new_datatype_definitionnew_datatype_definition and new_inductive_definitionnew_inductive_definition return — the induction, recursion and case theorems for a newly defined datatype or inductive relation — which is why they are structures with several theorem fields rather than single handles.
Pairs and lists are the argument types of the bulk operations. A term_pairterm_pair is one substitution component; the six list aliases rename vector types that hol_prover_client.hhol_prover_client.h declares:
typedef hol_term_list term_list;typedef hol_theorem_list thm_list;typedef hol_type_list type_list;typedef hol_term_pair_list term_pair_list;typedef hol_thm_pair_list thm_pair_list;typedef hol_type_pair_list type_pair_list;
typedef hol_term_list term_list;typedef hol_theorem_list thm_list;typedef hol_type_list type_list;typedef hol_term_pair_list term_pair_list;typedef hol_thm_pair_list thm_pair_list;typedef hol_type_pair_list type_pair_list;
These are the types that the TERM_LISTTERM_LIST and THM_LISTTHM_LIST constructors of proof_runtime.hproof_runtime.h build (see Symbolic Execution and Runtime API). Because they are typedefs rather than declarations, they are quoted verbatim here rather than listed as entries: everything below this section is generated from the header’s macro and function declarations.
Three macros stand behind every accessor on this page. They are why the catalogue is uniform: each constant and each theorem is fetched from the prover exactly once, by name, on first use.
LazyInitmacroproof_kernel.h:24#define LazyInit(type, name, f, ...) \ inline type get_##name() { \ static bool initialized = false; \ static type __##name; \ if (!initialized) { \ initialized = true; \ __##name = f(__VA_ARGS__); \ } \ return __##name; \ }
#define LazyInit(type, name, f, ...) \ inline type get_##name() { \ static bool initialized = false; \ static type __##name; \ if (!initialized) { \ initialized = true; \ __##name = f(__VA_ARGS__); \ } \ return __##name; \ }
LazyInitTheoremmacroproof_kernel.h:35#define LazyInitTheorem(name) LazyInit(thm, name, get_theorem_by_name, #name)
#define LazyInitTheorem(name) LazyInit(thm, name, get_theorem_by_name, #name)
__DeclareTheoremmacroproof_kernel.h:37#define __DeclareTheorem(name) thm get_##name()
#define __DeclareTheorem(name) thm get_##name()
LazyInit(type, name, f, ...)LazyInit(type, name, f, ...) defines get_<name>()get_<name>() as an inline function holding two function-local statics: a flag and the cached object. The first call evaluates f(__VA_ARGS__)f(__VA_ARGS__) — an RPC into the prover — and stores the result; every later call returns the cached handle without touching the connection. LazyInitTheorem(name)LazyInitTheorem(name) is the specialisation used for theorems: it expands to LazyInit(thm, name, get_theorem_by_name, #name)LazyInit(thm, name, get_theorem_by_name, #name), so the fetch is a lookup of the theorem’s own name in the prover’s theorem database, with #name#name stringifying the macro argument.
__DeclareTheorem(name)__DeclareTheorem(name) is the declaration counterpart. It expands to thm get_##name()thm get_##name(), so the header line
__DeclareTheorem(hsep_assoc);
__DeclareTheorem(hsep_assoc);
declares thm get_hsep_assoc();thm get_hsep_assoc();, and the implementation supplies the body with LazyInitTheorem(hsep_assoc)LazyInitTheorem(hsep_assoc). That is the whole convention: a theorem named TT in the kernel is reached from C as get_T()get_T(). The final line of the header does #undef __DeclareTheorem#undef __DeclareTheorem, so the macro is not visible to user code — it exists only to write the header compactly.
Four accessors return the HOL Light boolean connectives as terms. They are ordinary HOL constants, not C* additions; proof code needs them when it builds a pure side condition to hand to a decision procedure, or takes a goal of implication form apart.
get_conj_opterm-constproof_kernel.h:44term get_conj_op();
term get_conj_op();
/\ : bool->bool->bool
/\ : bool->bool->bool
get_disj_opterm-constproof_kernel.h:47term get_disj_op();
term get_disj_op();
\/ : bool->bool->bool
\/ : bool->bool->bool
get_iff_opterm-constproof_kernel.h:50term get_iff_op();
term get_iff_op();
<=> : bool->bool->bool
<=> : bool->bool->bool
get_imp_opterm-constproof_kernel.h:53term get_imp_op();
term get_imp_op();
==> : bool->bool->bool
==> : bool->bool->bool
These are the constants themselves, not applications: get_conj_op()get_conj_op() is the operator /\/\ of type bool->bool->boolbool->bool->bool, to be applied with the term constructors of HOL API: Types and Terms.
The separation-logic vocabulary. get_hprop_type()get_hprop_type() returns the type :hprop:hprop of heap propositions; the rest return the constants that build one. What each means is in Memory Model and Assertions here they are the accessors, with the type each constant carries.
get_hprop_typetypeproof_kernel.h:56type get_hprop_type();
type get_hprop_type();
:hprop
:hprop
get_hfactterm-constproof_kernel.h:59term get_hfact();
term get_hfact();
fact : bool->hprop
fact : bool->hprop
get_hentailterm-constproof_kernel.h:62term get_hentail();
term get_hentail();
|-- : hprop->hprop->hprop
|-- : hprop->hprop->hprop
get_hequalterm-constproof_kernel.h:65term get_hequal();
term get_hequal();
-|- : hprop->hprop->hprop
-|- : hprop->hprop->hprop
get_hconjterm-constproof_kernel.h:68term get_hconj();
term get_hconj();
** : hprop->hprop->hprop
** : hprop->hprop->hprop
get_hempterm-constproof_kernel.h:71term get_hemp();
term get_hemp();
emp : hprop
emp : hprop
get_htrueterm-constproof_kernel.h:74term get_htrue();
term get_htrue();
true : hprop
true : hprop
get_hfalseterm-constproof_kernel.h:77term get_hfalse();
term get_hfalse();
false : hprop
false : hprop
get_hwandterm-constproof_kernel.h:80term get_hwand();
term get_hwand();
-* : hprop->hprop->hprop
-* : hprop->hprop->hprop
get_himplterm-constproof_kernel.h:83term get_himpl();
term get_himpl();
--> : hprop->hprop->hprop
--> : hprop->hprop->hprop
get_horterm-constproof_kernel.h:86term get_hor();
term get_hor();
|| : hprop->hprop->hprop
|| : hprop->hprop->hprop
get_handterm-constproof_kernel.h:89term get_hand();
term get_hand();
&& : hprop->hprop->hprop
&& : hprop->hprop->hprop
get_hforallterm-constproof_kernel.h:92term get_hforall();
term get_hforall();
forall : (A->hprop)->hprop
forall : (A->hprop)->hprop
get_hexiststerm-constproof_kernel.h:95term get_hexists();
term get_hexists();
exists : (A->hprop)->hprop
exists : (A->hprop)->hprop
get_hpureterm-constproof_kernel.h:98term get_hpure();
term get_hpure();
pure : bool->hprop
pure : bool->hprop
get_true_termterm-constproof_kernel.h:101term get_true_term();
term get_true_term();
T : bool
T : bool
get_false_termterm-constproof_kernel.h:104term get_false_term();
term get_false_term();
F : bool
F : bool
Two naming details are worth fixing in mind. get_hconjget_hconj returns the separating conjunction **** , not the additive one — the additive conjunction &&&& is get_handget_hand. And get_hentailget_hentail and get_hequalget_hequal return |--|-- and -|--|- , entailment and entailment-equivalence between heap propositions; the header’s comment for get_hequalget_hequal opens with an apostrophe instead of a backtick, which is a typo in the header and not a different constant.
The last two are not heap propositions at all: get_true_term()get_true_term() and get_false_term()get_false_term() return the boolean constants TT and FF . They appear at this point because a proof most often needs them to fill in a pure side condition — pure(T)pure(T), fact(F)fact(F) — and the header declares them here.
The logic models a C type as an element of the inductive type :ctype:ctype, and data_atdata_at, sizeofsizeof, min_ofmin_of and max_ofmax_of are all indexed by one. These accessors return that type and its nine built-in constructors, plus the two types used for struct and field names.
get_ctype_typetypeproof_kernel.h:343type get_ctype_type();
type get_ctype_type();
:ctype
:ctype
get_Tcharterm-constproof_kernel.h:346term get_Tchar();
term get_Tchar();
Tchar : ctype
Tchar : ctype
get_Tucharterm-constproof_kernel.h:349term get_Tuchar();
term get_Tuchar();
Tuchar : ctype
Tuchar : ctype
get_Tshortterm-constproof_kernel.h:352term get_Tshort();
term get_Tshort();
Tshort : ctype
Tshort : ctype
get_Tushortterm-constproof_kernel.h:355term get_Tushort();
term get_Tushort();
Tushort : ctype
Tushort : ctype
get_Tintterm-constproof_kernel.h:358term get_Tint();
term get_Tint();
Tint : ctype
Tint : ctype
get_Tuintterm-constproof_kernel.h:361term get_Tuint();
term get_Tuint();
Tuint : ctype
Tuint : ctype
get_Tint64term-constproof_kernel.h:364term get_Tint64();
term get_Tint64();
Tint64 : ctype
Tint64 : ctype
get_Tuint64term-constproof_kernel.h:367term get_Tuint64();
term get_Tuint64();
Tuint64 : ctype
Tuint64 : ctype
get_Tptrterm-constproof_kernel.h:370term get_Tptr();
term get_Tptr();
Tptr : ctype
Tptr : ctype
get_struct_name_typetypeproof_kernel.h:571type get_struct_name_type();
type get_struct_name_type();
:struct_name
:struct_name
get_field_typetypeproof_kernel.h:574type get_field_type();
type get_field_type();
:field
:field
The TT-prefix convention is the whole naming scheme: TintTint is the logic’s name for C’s intint, TucharTuchar for unsigned charunsigned char, TptrTptr for a pointer of any pointee type. There is no accessor for TstructTstruct, the constructor taking a struct_namestruct_name: a struct type is built by applying it, and the struct’s name is a :struct_name:struct_name constant registered with cst_add_type_to_headercst_add_type_to_header (see Kernel Headers). get_struct_name_type()get_struct_name_type() and get_field_type()get_field_type() return the two types those constants inhabit; the header declares them at its very end, and they are grouped here because they belong with the C-type vocabulary rather than with the theorem catalogue. C* Extensions gives the full picture, including field_addrfield_addr and the FF-prefixed field constants.
The rest of the header is the theorem library: 141 accessors, each returning a theorem the kernel has already proved, each fetched by name from the prover’s database on first use. What follows is that catalogue, in header order.
Citing one of these is what a proof block does most: obtain the thmthm, then feed it to an inference rule from hol_prover_client.hhol_prover_client.h or to an entailment solver. What each rule is for — which are the primitive laws of the separation algebra, which are their consequences, and which are axioms the C* memory model adds — is the subject of Proof Rules and Typed Memory Predicates. The order below is the header’s, which is close to but not identical with the conceptual order those pages use.
Six general HOL Light theorems, plus the two trivial theorems about truth and falsity, are re-exported here so that proof code need not look them up by string. get_true_thm()get_true_thm() and get_false_thm()get_false_thm() are declared directly rather than through __DeclareTheorem__DeclareTheorem, which is why their entries carry the get_get_ prefix.
get_true_thmtheoremproof_kernel.h:107thm get_true_thm();
thm get_true_thm();
|- T
|- T
get_false_thmtheoremproof_kernel.h:110thm get_false_thm();
thm get_false_thm();
|- !t. F ==> t
|- !t. F ==> t
ABS_SIMPtheoremproof_kernel.h:113thm get_ABS_SIMP();
thm get_ABS_SIMP();
!t1 t2. (\x. t1) t2 = t1
!t1 t2. (\x. t1) t2 = t1
EXCLUDED_MIDDLEtheoremproof_kernel.h:116thm get_EXCLUDED_MIDDLE();
thm get_EXCLUDED_MIDDLE();
!t. t \/ ~t
!t. t \/ ~t
list_CASEStheoremproof_kernel.h:119thm get_list_CASES();
thm get_list_CASES();
!l. l = [] \/ (?h t. l = CONS h t)
!l. l = [] \/ (?h t. l = CONS h t)
list_INDUCTtheoremproof_kernel.h:122thm get_list_INDUCT();
thm get_list_INDUCT();
!P. P [] /\ (!a0 a1. P a1 ==> P (CONS a0 a1)) ==> (!x. P x)
!P. P [] /\ (!a0 a1. P a1 ==> P (CONS a0 a1)) ==> (!x. P x)
num_CASEStheoremproof_kernel.h:125thm get_num_CASES();
thm get_num_CASES();
!m. m = 0 \/ (?n. m = SUC n)
!m. m = 0 \/ (?n. m = SUC n)
num_INDUCTIONtheoremproof_kernel.h:128thm get_num_INDUCTION();
thm get_num_INDUCTION();
!P. P 0 /\ (!n. P n ==> P (SUC n)) ==> (!n. P n)
!P. P 0 /\ (!n. P n ==> P (SUC n)) ==> (!n. P n)
list_INDUCTlist_INDUCT and num_INDUCTIONnum_INDUCTION are the two induction principles a proof about a loop or a linked structure reaches for; list_CASESlist_CASES and num_CASESnum_CASES are their case-analysis counterparts. ABS_SIMPABS_SIMP is beta-reduction in equational form, and EXCLUDED_MIDDLEEXCLUDED_MIDDLE is what makes the logic classical.
The backbone. Entailment |--|-- is reflexive and transitive, and antisymmetric with respect to -|--|- ; the separating conjunction **** is associative and commutative with empemp as unit; -*-* is its right adjoint; and entailment is a congruence for **** on either side.
hentail_refltheoremproof_kernel.h:131thm get_hentail_refl();
thm get_hentail_refl();
!hp. hp |-- hp
!hp. hp |-- hp
hentail_transtheoremproof_kernel.h:134thm get_hentail_trans();
thm get_hentail_trans();
!hp1 hp2 hp3. (hp1 |-- hp2) ==> (hp2 |-- hp3) ==> (hp1 |-- hp3)
!hp1 hp2 hp3. (hp1 |-- hp2) ==> (hp2 |-- hp3) ==> (hp1 |-- hp3)
hentail_antisymtheoremproof_kernel.h:137thm get_hentail_antisym();
thm get_hentail_antisym();
!hp1 hp2. (hp1 |-- hp2) ==> (hp2 |-- hp1) ==> (hp1 -|- hp2)
!hp1 hp2. (hp1 |-- hp2) ==> (hp2 |-- hp1) ==> (hp1 -|- hp2)
hsep_assoctheoremproof_kernel.h:140thm get_hsep_assoc();
thm get_hsep_assoc();
!hp1 hp2 hp3. (hp1 ** hp2) ** hp3 -|- hp1 ** (hp2 ** hp3)
!hp1 hp2 hp3. (hp1 ** hp2) ** hp3 -|- hp1 ** (hp2 ** hp3)
hsep_commtheoremproof_kernel.h:143thm get_hsep_comm();
thm get_hsep_comm();
!hp1 hp2. hp1 ** hp2 -|- hp2 ** hp1
!hp1 hp2. hp1 ** hp2 -|- hp2 ** hp1
hsep_hemp_lefttheoremproof_kernel.h:146thm get_hsep_hemp_left();
thm get_hsep_hemp_left();
!hp. emp ** hp -|- hp
!hp. emp ** hp -|- hp
hsep_hemp_righttheoremproof_kernel.h:149thm get_hsep_hemp_right();
thm get_hsep_hemp_right();
!hp. hp ** emp -|- hp
!hp. hp ** emp -|- hp
hwand_hsep_adjointtheoremproof_kernel.h:152thm get_hwand_hsep_adjoint();
thm get_hwand_hsep_adjoint();
!hp1 hp2 hp3. (hp1 ** hp2 |-- hp3) <=> (hp1 |-- hp2 -* hp3)
!hp1 hp2 hp3. (hp1 ** hp2 |-- hp3) <=> (hp1 |-- hp2 -* hp3)
hsep_cancel_lefttheoremproof_kernel.h:155thm get_hsep_cancel_left();
thm get_hsep_cancel_left();
!hp2 hp2' hp1. (hp2 |-- hp2') ==> (hp1 ** hp2 |-- hp1 ** hp2')
!hp2 hp2' hp1. (hp2 |-- hp2') ==> (hp1 ** hp2 |-- hp1 ** hp2')
hsep_cancel_righttheoremproof_kernel.h:158thm get_hsep_cancel_right();
thm get_hsep_cancel_right();
!hp1 hp1' hp2. (hp1 |-- hp1') ==> (hp1 ** hp2 |-- hp1' ** hp2)
!hp1 hp1' hp2. (hp1 |-- hp1') ==> (hp1 ** hp2 |-- hp1' ** hp2)
hsep_monotonetheoremproof_kernel.h:161thm get_hsep_monotone();
thm get_hsep_monotone();
!hp1 hp1' hp2 hp2'. (hp1 |-- hp1') ==> (hp2 |-- hp2') ==> (hp1 ** hp2 |-- hp1' ** hp2')
!hp1 hp1' hp2 hp2'. (hp1 |-- hp1') ==> (hp2 |-- hp2') ==> (hp1 ** hp2 |-- hp1' ** hp2')
hsep_cancel_lefthsep_cancel_left is the frame rule of this development: from hp2 |-- hp2'hp2 |-- hp2' it concludes hp1 ** hp2 |-- hp1 ** hp2'hp1 ** hp2 |-- hp1 ** hp2', leaving hp1hp1 untouched. hsep_cancel_righthsep_cancel_right frames on the other side, and hsep_monotonehsep_monotone frames on both at once.
truetrue and falsefalse as heap propositions, their relationship to purepure and factfact, their absorption behaviour under **** , and introduction and elimination for the additive conjunction &&&& , disjunction |||| and implication -->--> .
htrue_deftheoremproof_kernel.h:164thm get_htrue_def();
thm get_htrue_def();
true -|- pure(T)
true -|- pure(T)
hfalse_deftheoremproof_kernel.h:167thm get_hfalse_def();
thm get_hfalse_def();
false -|- pure(F)
false -|- pure(F)
htrue_introtheoremproof_kernel.h:170thm get_htrue_intro();
thm get_htrue_intro();
!hp. hp |-- true
!hp. hp |-- true
htrue_hemptheoremproof_kernel.h:173thm get_htrue_hemp();
thm get_htrue_hemp();
fact(T) -|- emp
fact(T) -|- emp
hfalse_elimtheoremproof_kernel.h:176thm get_hfalse_elim();
thm get_hfalse_elim();
!hp. false |-- hp
!hp. false |-- hp
hfact_false_elimtheoremproof_kernel.h:179thm get_hfact_false_elim();
thm get_hfact_false_elim();
!hp. fact(F) |-- hp
!hp. fact(F) |-- hp
htrue_elim_lefttheoremproof_kernel.h:182thm get_htrue_elim_left();
thm get_htrue_elim_left();
!hp. fact(T) ** hp -|- hp
!hp. fact(T) ** hp -|- hp
htrue_elim_righttheoremproof_kernel.h:185thm get_htrue_elim_right();
thm get_htrue_elim_right();
!hp. hp ** fact(T) -|- hp
!hp. hp ** fact(T) -|- hp
hfalse_absorb_lefttheoremproof_kernel.h:188thm get_hfalse_absorb_left();
thm get_hfalse_absorb_left();
!hp. fact(F) ** hp -|- fact(F)
!hp. fact(F) ** hp -|- fact(F)
hfalse_absorb_righttheoremproof_kernel.h:191thm get_hfalse_absorb_right();
thm get_hfalse_absorb_right();
!hp. hp ** fact(F) -|- fact(F)
!hp. hp ** fact(F) -|- fact(F)
hand_introtheoremproof_kernel.h:194thm get_hand_intro();
thm get_hand_intro();
!hp1 hp2 hp3. (hp1 |-- hp2) ==> (hp1 |-- hp3) ==> (hp1 |-- hp2 && hp3)
!hp1 hp2 hp3. (hp1 |-- hp2) ==> (hp1 |-- hp3) ==> (hp1 |-- hp2 && hp3)
hand_elim1theoremproof_kernel.h:197thm get_hand_elim1();
thm get_hand_elim1();
!hp1 hp2. (hp1 && hp2 |-- hp1)
!hp1 hp2. (hp1 && hp2 |-- hp1)
hand_elim2theoremproof_kernel.h:200thm get_hand_elim2();
thm get_hand_elim2();
!hp1 hp2. (hp1 && hp2 |-- hp2)
!hp1 hp2. (hp1 && hp2 |-- hp2)
hor_intro1theoremproof_kernel.h:203thm get_hor_intro1();
thm get_hor_intro1();
!hp1 hp2. (hp1 |-- hp1 || hp2)
!hp1 hp2. (hp1 |-- hp1 || hp2)
hor_intro2theoremproof_kernel.h:206thm get_hor_intro2();
thm get_hor_intro2();
!hp1 hp2. (hp2 |-- hp1 || hp2)
!hp1 hp2. (hp2 |-- hp1 || hp2)
hor_elimtheoremproof_kernel.h:209thm get_hor_elim();
thm get_hor_elim();
!hp1 hp2 hp3. (hp1 |-- hp3) ==> (hp2 |-- hp3) ==> (hp1 || hp2 |-- hp3)
!hp1 hp2 hp3. (hp1 |-- hp3) ==> (hp2 |-- hp3) ==> (hp1 || hp2 |-- hp3)
himpl_hand_adjointtheoremproof_kernel.h:212thm get_himpl_hand_adjoint();
thm get_himpl_hand_adjoint();
!hp1 hp2 hp3. (hp1 && hp2 |-- hp3) <=> (hp1 |-- hp2 --> hp3)
!hp1 hp2 hp3. (hp1 && hp2 |-- hp3) <=> (hp1 |-- hp2 --> hp3)
Note the asymmetry recorded by htrue_hemphtrue_hemp: fact(T)fact(T) is equivalent to empemp, not to truetrue. factfact carries the claim that the heap is empty; purepure does not. That distinction is the reason for two embeddings of booleans, and it is why the pure-fact rules below come in two families.
Introduction and elimination for the heap-proposition quantifiers existsexists and forallforall , which are HOL binders over a function into hprophprop.
hexists_introtheoremproof_kernel.h:215thm get_hexists_intro();
thm get_hexists_intro();
!(x : A) hp hpA. (hp |-- hpA x) ==> (hp |-- (exists x : A. hpA x))
!(x : A) hp hpA. (hp |-- hpA x) ==> (hp |-- (exists x : A. hpA x))
hexists_elimtheoremproof_kernel.h:218thm get_hexists_elim();
thm get_hexists_elim();
!hp hpA. (!x : A. hpA x |-- hp) ==> ((exists y : A. hpA y) |-- hp)
!hp hpA. (!x : A. hpA x |-- hp) ==> ((exists y : A. hpA y) |-- hp)
hforall_introtheoremproof_kernel.h:221thm get_hforall_intro();
thm get_hforall_intro();
!hp hpA. (!x : A. hp |-- hpA x) ==> (hp |-- (forall x : A. hpA x))
!hp hpA. (!x : A. hp |-- hpA x) ==> (hp |-- (forall x : A. hpA x))
hforall_elimtheoremproof_kernel.h:224thm get_hforall_elim();
thm get_hforall_elim();
!hp hpA (x : A). (hpA x |-- hp) ==> ((forall x : A. hpA x) |-- hp)
!hp hpA (x : A). (hpA x |-- hp) ==> ((forall x : A. hpA x) |-- hp)
The rules moving a pure boolean claim into and out of a heap proposition, together with the associativity and commutativity of &&&& that the header declares at this point.
hpure_introtheoremproof_kernel.h:227thm get_hpure_intro();
thm get_hpure_intro();
!p hp1 hp2. p ==> (hp1 |-- hp2) ==> (hp1 |-- pure(p) && hp2)
!p hp1 hp2. p ==> (hp1 |-- hp2) ==> (hp1 |-- pure(p) && hp2)
hpure_elimtheoremproof_kernel.h:230thm get_hpure_elim();
thm get_hpure_elim();
!p hp1 hp2. (p ==> (hp1 |-- hp2)) ==> (pure(p) && hp1 |-- hp2)
!p hp1 hp2. (p ==> (hp1 |-- hp2)) ==> (pure(p) && hp1 |-- hp2)
hand_assoctheoremproof_kernel.h:233thm get_hand_assoc();
thm get_hand_assoc();
!hp1 hp2 hp3. (hp1 && hp2) && hp3 -|- hp1 && (hp2 && hp3)
!hp1 hp2 hp3. (hp1 && hp2) && hp3 -|- hp1 && (hp2 && hp3)
hand_commtheoremproof_kernel.h:236thm get_hand_comm();
thm get_hand_comm();
!hp1 hp2. hp1 && hp2 -|- hp2 && hp1
!hp1 hp2. hp1 && hp2 -|- hp2 && hp1
hsep_hpure_lefttheoremproof_kernel.h:239thm get_hsep_hpure_left();
thm get_hsep_hpure_left();
!p hp1 hp2. (pure(p) && hp1) ** hp2 -|- pure(p) && (hp1 ** hp2)
!p hp1 hp2. (pure(p) && hp1) ** hp2 -|- pure(p) && (hp1 ** hp2)
hsep_hpure_righttheoremproof_kernel.h:242thm get_hsep_hpure_right();
thm get_hsep_hpure_right();
!p hp1 hp2. hp1 ** (pure(p) && hp2) -|- pure(p) && (hp1 ** hp2)
!p hp1 hp2. hp1 ** (pure(p) && hp2) -|- pure(p) && (hp1 ** hp2)
hfact_deftheoremproof_kernel.h:245thm get_hfact_def();
thm get_hfact_def();
!p hp. fact(p) -|- (pure(p) && emp)
!p hp. fact(p) -|- (pure(p) && emp)
hfact_hpuretheoremproof_kernel.h:248thm get_hfact_hpure();
thm get_hfact_hpure();
!p hp. fact(p) ** hp -|- pure(p) && hp
!p hp. fact(p) ** hp -|- pure(p) && hp
hfact_introtheoremproof_kernel.h:251thm get_hfact_intro();
thm get_hfact_intro();
!p hp1 hp2. p ==> (hp1 |-- hp2) ==> (hp1 |-- fact(p) ** hp2)
!p hp1 hp2. p ==> (hp1 |-- hp2) ==> (hp1 |-- fact(p) ** hp2)
hfact_elimtheoremproof_kernel.h:254thm get_hfact_elim();
thm get_hfact_elim();
!p hp1 hp2. (p ==> (hp1 |-- hp2)) ==> (fact(p) ** hp1 |-- hp2)
!p hp1 hp2. (p ==> (hp1 |-- hp2)) ==> (fact(p) ** hp1 |-- hp2)
hfact_duptheoremproof_kernel.h:257thm get_hfact_dup();
thm get_hfact_dup();
!p. fact(p) |-- fact(p) ** fact(p)
!p. fact(p) |-- fact(p) ** fact(p)
hsep_hfact_lefttheoremproof_kernel.h:260thm get_hsep_hfact_left();
thm get_hsep_hfact_left();
!p hp1 hp2. (fact(p) ** hp1) ** hp2 -|- fact(p) ** (hp1 ** hp2)
!p hp1 hp2. (fact(p) ** hp1) ** hp2 -|- fact(p) ** (hp1 ** hp2)
hsep_hfact_righttheoremproof_kernel.h:263thm get_hsep_hfact_right();
thm get_hsep_hfact_right();
!p hp1 hp2. hp1 ** (fact(p) ** hp2) -|- fact(p) ** (hp1 ** hp2)
!p hp1 hp2. hp1 ** (fact(p) ** hp2) -|- fact(p) ** (hp1 ** hp2)
hfact_defhfact_def fixes the relationship between the two embeddings — fact(p)fact(p) is pure(p) && emppure(p) && emp — and hfact_hpurehfact_hpure is the form used constantly in practice: fact(p) ** hpfact(p) ** hp and pure(p) && hppure(p) && hp are the same proposition. hfact_duphfact_dup is duplication, sound because a pure fact owns nothing.
How **** and &&&& interact with a quantifier on the left or on the right. The existential cases are equivalences; the universal cases are entailments in one direction only, which is the expected asymmetry — a quantified separation is weaker than a separated quantification.
hsep_hexists_lefttheoremproof_kernel.h:266thm get_hsep_hexists_left();
thm get_hsep_hexists_left();
!hpA hp. (exists x : A. hpA x) ** hp -|- exists x : A. (hpA x ** hp)
!hpA hp. (exists x : A. hpA x) ** hp -|- exists x : A. (hpA x ** hp)
hsep_hexists_righttheoremproof_kernel.h:269thm get_hsep_hexists_right();
thm get_hsep_hexists_right();
!hp hpA. hp ** (exists x : A. hpA x) -|- exists x : A. (hp ** hpA x)
!hp hpA. hp ** (exists x : A. hpA x) -|- exists x : A. (hp ** hpA x)
hsep_hforall_lefttheoremproof_kernel.h:272thm get_hsep_hforall_left();
thm get_hsep_hforall_left();
!hpA hp. (forall x : A. hpA x) ** hp |-- forall x : A. (hpA x ** hp)
!hpA hp. (forall x : A. hpA x) ** hp |-- forall x : A. (hpA x ** hp)
hsep_hforall_righttheoremproof_kernel.h:275thm get_hsep_hforall_right();
thm get_hsep_hforall_right();
!hp hpA. hp ** (forall x : A. hpA x) |-- forall x : A. (hp ** hpA x)
!hp hpA. hp ** (forall x : A. hpA x) |-- forall x : A. (hp ** hpA x)
hand_hexists_lefttheoremproof_kernel.h:278thm get_hand_hexists_left();
thm get_hand_hexists_left();
!hpA hp. (exists x : A. hpA x) && hp -|- exists x : A. (hpA x && hp)
!hpA hp. (exists x : A. hpA x) && hp -|- exists x : A. (hpA x && hp)
hand_hexists_righttheoremproof_kernel.h:281thm get_hand_hexists_right();
thm get_hand_hexists_right();
!hp hpA. hp && (exists x : A. hpA x) -|- exists x : A. (hp && hpA x)
!hp hpA. hp && (exists x : A. hpA x) -|- exists x : A. (hp && hpA x)
hand_hforall_lefttheoremproof_kernel.h:284thm get_hand_hforall_left();
thm get_hand_hforall_left();
!hpA hp. (forall x : A. hpA x) && hp |-- forall x : A. (hpA x && hp)
!hpA hp. (forall x : A. hpA x) && hp |-- forall x : A. (hpA x && hp)
hand_hforall_righttheoremproof_kernel.h:287thm get_hand_hforall_right();
thm get_hand_hforall_right();
!hp hpA. hp && (forall x : A. hpA x) |-- forall x : A. (hp && hpA x)
!hp hpA. hp && (forall x : A. hpA x) |-- forall x : A. (hp && hpA x)
Congruence of entailment for the quantifiers and for the additive connectives, completing the set begun by hsep_cancel_lefthsep_cancel_left above.
hexists_monotonetheoremproof_kernel.h:291thm get_hexists_monotone();
thm get_hexists_monotone();
!hpA hpA'. (!x:A. hpA x |-- hpA' x) ==> ((exists x:A. hpA x) |-- (exists x:A. hpA' x))
!hpA hpA'. (!x:A. hpA x |-- hpA' x) ==> ((exists x:A. hpA x) |-- (exists x:A. hpA' x))
hforall_monotonetheoremproof_kernel.h:294thm get_hforall_monotone();
thm get_hforall_monotone();
!hpA hpA'. (!x:A. hpA x |-- hpA' x) ==> ((forall x:A. hpA x) |-- (forall x:A. hpA' x))
!hpA hpA'. (!x:A. hpA x |-- hpA' x) ==> ((forall x:A. hpA x) |-- (forall x:A. hpA' x))
hand_monotonetheoremproof_kernel.h:297thm get_hand_monotone();
thm get_hand_monotone();
!hp1 hp1' hp2 hp2'. (hp1 |-- hp1') ==> (hp2 |-- hp2') ==> (hp1 && hp2 |-- hp1' && hp2')
!hp1 hp1' hp2 hp2'. (hp1 |-- hp1') ==> (hp2 |-- hp2') ==> (hp1 && hp2 |-- hp1' && hp2')
hor_monotonetheoremproof_kernel.h:300thm get_hor_monotone();
thm get_hor_monotone();
!hp1 hp1' hp2 hp2'. (hp1 |-- hp1') ==> (hp2 |-- hp2') ==> (hp1 || hp2 |-- hp1' || hp2')
!hp1 hp1' hp2 hp2'. (hp1 |-- hp1') ==> (hp2 |-- hp2') ==> (hp1 || hp2 |-- hp1' || hp2')
Ten accessors carry a derivedderived badge, from the header’s @derived@derived marker. The marker records layering inside the kernel’s own development: these lemmas are proved from the rules above rather than belonging to the core set the separation algebra is built from. It says nothing about trust. Derived and undecorated accessors alike return theorems the prover has proved, and a proof cites them the same way.
They exist because they are the shapes that come up when an assertion is rearranged by hand: commuting a factfact past a heap proposition, pulling the second conjunct of a three-way **** to the front, turning an equivalence into an entailment in the direction currently needed.
hsep_hfalse_lefttheoremderivedproof_kernel.h:304thm get_hsep_hfalse_left();
thm get_hsep_hfalse_left();
!hp. false ** hp |-- false
!hp. false ** hp |-- false
hsep_hfact_commtheoremderivedproof_kernel.h:308thm get_hsep_hfact_comm();
thm get_hsep_hfact_comm();
!hp p. hp ** fact(p) -|- fact(p) ** hp
!hp p. hp ** fact(p) -|- fact(p) ** hp
hfact_hpure_righttheoremderivedproof_kernel.h:312thm get_hfact_hpure_right();
thm get_hfact_hpure_right();
!p hp1 hp2. hp1 ** (pure(p) && hp2) -|- pure(p) && (hp1 ** hp2)
!p hp1 hp2. hp1 ** (pure(p) && hp2) -|- pure(p) && (hp1 ** hp2)
hsep_comm_left_parttheoremderivedproof_kernel.h:316thm get_hsep_comm_left_part();
thm get_hsep_comm_left_part();
!hp hp1 hp2. hp1 ** hp ** hp2 -|- hp ** hp1 ** hp2
!hp hp1 hp2. hp1 ** hp ** hp2 -|- hp ** hp1 ** hp2
hentail_sym_lefttheoremderivedproof_kernel.h:320thm get_hentail_sym_left();
thm get_hentail_sym_left();
!hp1 hp2. (hp1 -|- hp2) ==> (hp1 |-- hp2)
!hp1 hp2. (hp1 -|- hp2) ==> (hp1 |-- hp2)
hsep_cancel_left_eqtheoremderivedproof_kernel.h:324thm get_hsep_cancel_left_eq();
thm get_hsep_cancel_left_eq();
!hp1 hp2 hp2'. (hp2 -|- hp2') ==> (hp1 ** hp2 -|- hp1 ** hp2')
!hp1 hp2 hp2'. (hp2 -|- hp2') ==> (hp1 ** hp2 -|- hp1 ** hp2')
hfact_elim_duptheoremderivedproof_kernel.h:328thm get_hfact_elim_dup();
thm get_hfact_elim_dup();
!p hp1 hp2. (p ==> (hp1 |-- hp2)) ==> (fact(p) ** hp1 |-- fact(p) ** hp2)
!p hp1 hp2. (p ==> (hp1 |-- hp2)) ==> (fact(p) ** hp1 |-- fact(p) ** hp2)
hpure_add_hfacttheoremderivedproof_kernel.h:332thm get_hpure_add_hfact();
thm get_hpure_add_hfact();
!p hp. (hp |-- pure(p)) ==> (hp |-- fact(p) ** hp)
!p hp. (hp |-- pure(p)) ==> (hp |-- fact(p) ** hp)
hsep_actheoremderivedproof_kernel.h:336thm get_hsep_ac();
thm get_hsep_ac();
(hp1 ** hp2 -|- hp2 ** hp1) && ((hp1 ** hp2) ** hp3 -|- hp1 ** (hp2 ** hp3)) && (hp1 ** (hp2 ** hp3) -|- hp2 ** (hp1 ** hp3))
(hp1 ** hp2 -|- hp2 ** hp1) && ((hp1 ** hp2) ** hp3 -|- hp1 ** (hp2 ** hp3)) && (hp1 ** (hp2 ** hp3) -|- hp2 ** (hp1 ** hp3))
heq_symtheoremderivedproof_kernel.h:340thm get_heq_sym();
thm get_heq_sym();
!hp1 hp2. (hp1 -|- hp2) <=> (hp2 -|- hp1)
!hp1 hp2. (hp1 -|- hp2) <=> (hp2 -|- hp1)
hsep_achsep_ac bundles the three rearrangements of a nested **** that an associativity–commutativity normalisation needs, which is why its statement is a conjunction rather than a single equivalence.
Four accessors concern the :ctype:ctype index: the recursive equations defining sizeofsizeof, min_ofmin_of and max_ofmax_of, plus the one consequence the kernel exports directly.
sizeof_deftheoremproof_kernel.h:373thm get_sizeof_def();
thm get_sizeof_def();
the definition of `sizeof : ctype->int
the definition of `sizeof : ctype->int
sizeof_ge_0theoremproof_kernel.h:376thm get_sizeof_ge_0();
thm get_sizeof_ge_0();
!ty. sizeof ty >= &0
!ty. sizeof ty >= &0
min_of_deftheoremproof_kernel.h:379thm get_min_of_def();
thm get_min_of_def();
the definition of `min_of : ctype->int
the definition of `min_of : ctype->int
max_of_deftheoremproof_kernel.h:382thm get_max_of_def();
thm get_max_of_def();
the definition of `max_of : ctype->int
the definition of `max_of : ctype->int
A comment reading “the definition of ff” means the accessor returns the defining theorem — the conjunction of equations, one per constructor — which is what a rewriting step needs to compute sizeof Tintsizeof Tint down to a numeral. sizeof_ge_0sizeof_ge_0 is the fact that no C type has negative size, needed whenever an array address x + i * sizeof(ty)x + i * sizeof(ty) has to be bounded.
The four rules about data_atdata_at and undef_data_atundef_data_at, the memory predicates for a single typed cell, followed by the six definitional theorems for the array predicates.
data_at_to_undef_data_attheoremproof_kernel.h:385thm get_data_at_to_undef_data_at();
thm get_data_at_to_undef_data_at();
!x ty v. data_at x ty v |-- undef_data_at x ty
!x ty v. data_at x ty v |-- undef_data_at x ty
data_at_rangetheoremproof_kernel.h:388thm get_data_at_range();
thm get_data_at_range();
!x ty v. data_at x ty v |-- data_at x ty v ** fact(min_of(ty) <= v && v <= max_of(ty))
!x ty v. data_at x ty v |-- data_at x ty v ** fact(min_of(ty) <= v && v <= max_of(ty))
data_at_duptheoremproof_kernel.h:391thm get_data_at_dup();
thm get_data_at_dup();
!x ty v1 v2. data_at x ty v1 ** data_at x ty v2 |-- false
!x ty v1 v2. data_at x ty v1 ** data_at x ty v2 |-- false
undef_data_at_duptheoremproof_kernel.h:394thm get_undef_data_at_dup();
thm get_undef_data_at_dup();
!x ty. undef_data_at x ty ** undef_data_at x ty |-- false
!x ty. undef_data_at x ty ** undef_data_at x ty |-- false
array_at_rec_deftheoremproof_kernel.h:397thm get_array_at_rec_def();
thm get_array_at_rec_def();
the definition of `array_at_rec : addr->ctype->int->int->(int)list->hprop
the definition of `array_at_rec : addr->ctype->int->int->(int)list->hprop
array_at_missing_i_rec_deftheoremproof_kernel.h:400thm get_array_at_missing_i_rec_def();
thm get_array_at_missing_i_rec_def();
the definition of `array_at_missing_i_rec : addr->ctype->int->int->int->(int)list->hprop
the definition of `array_at_missing_i_rec : addr->ctype->int->int->int->(int)list->hprop
array_at_deftheoremproof_kernel.h:403thm get_array_at_def();
thm get_array_at_def();
the definition of `array_at : addr->ctype->int->(int)list->hprop
the definition of `array_at : addr->ctype->int->(int)list->hprop
undef_array_at_rec_deftheoremproof_kernel.h:406thm get_undef_array_at_rec_def();
thm get_undef_array_at_rec_def();
the definition of `undef_array_at_rec : addr->ctype->int->int->num->hprop
the definition of `undef_array_at_rec : addr->ctype->int->int->num->hprop
undef_array_at_missing_i_rec_deftheoremproof_kernel.h:409thm get_undef_array_at_missing_i_rec_def();
thm get_undef_array_at_missing_i_rec_def();
the definition of `undef_array_at_missing_i_rec : addr->ctype->int->int->int->num->hprop
the definition of `undef_array_at_missing_i_rec : addr->ctype->int->int->int->num->hprop
undef_array_at_deftheoremproof_kernel.h:412thm get_undef_array_at_def();
thm get_undef_array_at_def();
the definition of `undef_array_at : addr->ctype->int->hprop
the definition of `undef_array_at : addr->ctype->int->hprop
data_at_rangedata_at_range is where the type index earns its keep: a stored value always lies between min_of(ty)min_of(ty) and max_of(ty)max_of(ty), and the rule makes that available as a pure fact without consuming the cell. data_at_dupdata_at_dup and undef_data_at_dupundef_data_at_dup are the anti-duplication facts that make ownership exclusive — two claims on the same address entail falsefalse.
The _def_def entries return definitions, and their comments give the signature of the predicate being defined rather than an equation. The _rec_rec variants take an explicit index range lolo, hihi; the plain array_atarray_at is the length-indexed form built on top of them; and the missing_imissing_i variants describe an array with the cell at index ii carved out, which is what a split leaves behind.
Array contents are HOL lists, so the kernel exports the list vocabulary the array rules are stated in. LENGTHLENGTH, MEMMEM, APPENDAPPEND, REVERSEREVERSE and REPLICATEREPLICATE are HOL Light’s own; the II-prefixed operations — ilengthilength, inthinth, ifirstnifirstn, iskipniskipn, ireplicateireplicate, replace_inthreplace_inth, sublistsublist — are C*‘s integer-indexed counterparts, introduced so that list indices and C’s integer arithmetic live in one type.
LENGTHtheoremproof_kernel.h:415thm get_LENGTH();
thm get_LENGTH();
LENGTH [] = 0 /\ (!h t. LENGTH (CONS h t) = SUC (LENGTH t))
LENGTH [] = 0 /\ (!h t. LENGTH (CONS h t) = SUC (LENGTH t))
ILENGTH_DEFtheoremproof_kernel.h:418thm get_ILENGTH_DEF();
thm get_ILENGTH_DEF();
the definition of `ilength : (A)list->int
the definition of `ilength : (A)list->int
NTH_DEFtheoremproof_kernel.h:421thm get_NTH_DEF();
thm get_NTH_DEF();
the definition of `NTH : num->(A)list->A
the definition of `NTH : num->(A)list->A
INTH_DEFtheoremproof_kernel.h:424thm get_INTH_DEF();
thm get_INTH_DEF();
the definition of `inth : int->(A)list->A
the definition of `inth : int->(A)list->A
REPLACE_NTH_DEFtheoremproof_kernel.h:427thm get_REPLACE_NTH_DEF();
thm get_REPLACE_NTH_DEF();
the definition of `REPLACE_NTH : num->A->(A)list->(A)list
the definition of `REPLACE_NTH : num->A->(A)list->(A)list
REPLACE_INTH_DEFtheoremproof_kernel.h:430thm get_REPLACE_INTH_DEF();
thm get_REPLACE_INTH_DEF();
the definition of `replace_inth : int->A->(A)list->(A)list
the definition of `replace_inth : int->A->(A)list->(A)list
FIRSTN_DEFtheoremproof_kernel.h:433thm get_FIRSTN_DEF();
thm get_FIRSTN_DEF();
the definition of `FIRSTN : num->(A)list->(A)list
the definition of `FIRSTN : num->(A)list->(A)list
IFIRSTN_DEFtheoremproof_kernel.h:436thm get_IFIRSTN_DEF();
thm get_IFIRSTN_DEF();
the definition of `ifirstn : int->(A)list->(A)list
the definition of `ifirstn : int->(A)list->(A)list
SKIPN_DEFtheoremproof_kernel.h:439thm get_SKIPN_DEF();
thm get_SKIPN_DEF();
the definition of `SKIPN : num->(A)list->(A)list
the definition of `SKIPN : num->(A)list->(A)list
ISKIPN_DEFtheoremproof_kernel.h:442thm get_ISKIPN_DEF();
thm get_ISKIPN_DEF();
the definition of `iskipn : int->(A)list->(A)list
the definition of `iskipn : int->(A)list->(A)list
REPLICATEtheoremproof_kernel.h:445thm get_REPLICATE();
thm get_REPLICATE();
REPLICATE 0 x = [] /\ REPLICATE (SUC n) x = CONS x (REPLICATE n x)
REPLICATE 0 x = [] /\ REPLICATE (SUC n) x = CONS x (REPLICATE n x)
IREPLICATE_DEFtheoremproof_kernel.h:448thm get_IREPLICATE_DEF();
thm get_IREPLICATE_DEF();
the definition of `ireplicate : int->A->(A)list
the definition of `ireplicate : int->A->(A)list
SUBLIST_DEFtheoremproof_kernel.h:451thm get_SUBLIST_DEF();
thm get_SUBLIST_DEF();
the definition of `sublist : int->int->(A)list->(A)list
the definition of `sublist : int->int->(A)list->(A)list
MEMtheoremproof_kernel.h:454thm get_MEM();
thm get_MEM();
(MEM x [] <=> F) /\ (MEM x (CONS h t) <=> x = h \/ MEM x t)
(MEM x [] <=> F) /\ (MEM x (CONS h t) <=> x = h \/ MEM x t)
APPENDtheoremproof_kernel.h:457thm get_APPEND();
thm get_APPEND();
(!l. APPEND [] l = l) /\ (!h t l. APPEND (CONS h t) l = CONS h (APPEND t l))
(!l. APPEND [] l = l) /\ (!h t l. APPEND (CONS h t) l = CONS h (APPEND t l))
REVERSEtheoremproof_kernel.h:460thm get_REVERSE();
thm get_REVERSE();
REVERSE [] = [] /\ REVERSE (CONS x l) = APPEND (REVERSE l) [x]
REVERSE [] = [] /\ REVERSE (CONS x l) = APPEND (REVERSE l) [x]
ILENGTH_NONNEGtheoremproof_kernel.h:463thm get_ILENGTH_NONNEG();
thm get_ILENGTH_NONNEG();
!l:(A)list. &0 <= ilength l
!l:(A)list. &0 <= ilength l
ILENGTH_APPENDtheoremproof_kernel.h:466thm get_ILENGTH_APPEND();
thm get_ILENGTH_APPEND();
!l1:(A)list l2:(A)list. ilength(l1 ++ l2) == ilength(l1) + ilength(l2)
!l1:(A)list l2:(A)list. ilength(l1 ++ l2) == ilength(l1) + ilength(l2)
ISKIPN_SPLIT_FIRSTtheoremproof_kernel.h:469thm get_ISKIPN_SPLIT_FIRST();
thm get_ISKIPN_SPLIT_FIRST();
!i:int l:(A)list. &0 <= i && i < ilength l ==> iskipn i l == (inth i l) :: (iskipn (i + &1) l)
!i:int l:(A)list. &0 <= i && i < ilength l ==> iskipn i l == (inth i l) :: (iskipn (i + &1) l)
ISKIPN_ILENGTHtheoremproof_kernel.h:472thm get_ISKIPN_ILENGTH();
thm get_ISKIPN_ILENGTH();
!l:(A)list. iskipn (ilength l) l == []
!l:(A)list. iskipn (ilength l) l == []
ILENGTH_IREPLICATEtheoremproof_kernel.h:475thm get_ILENGTH_IREPLICATE();
thm get_ILENGTH_IREPLICATE();
!n:int v:A. ilength(ireplicate n v) == n
!n:int v:A. ilength(ireplicate n v) == n
IREPLICATE_APPENDtheoremproof_kernel.h:478thm get_IREPLICATE_APPEND();
thm get_IREPLICATE_APPEND();
!l:(A)list v:A. (ireplicate n v) ++ [v] == ireplicate (n + &1) v
!l:(A)list v:A. (ireplicate n v) ++ [v] == ireplicate (n + &1) v
The last six are the proved facts about those operations that array reasoning keeps needing: that ilengthilength is non-negative and additive over append, that skipping one element off the front of a non-empty suffix behaves as expected, that skipping the whole length leaves the empty list, and the two facts about ireplicateireplicate used when an uninitialized array is filled in.
The thirty rules that make array reasoning possible: length and range facts, splitting a cell out of an array and merging it back, working at the head or the tail, rebasing an index range, dividing an array in two, and the empty case — each in an initialized array_atarray_at form and, where it makes sense, an undef_array_atundef_array_at mirror.
array_at_rec_lengththeoremproof_kernel.h:481thm get_array_at_rec_length();
thm get_array_at_rec_length();
!x ty lo hi l. array_at_rec x ty lo hi l |-- array_at_rec x ty lo hi l ** fact(ilength(l) == hi - lo)
!x ty lo hi l. array_at_rec x ty lo hi l |-- array_at_rec x ty lo hi l ** fact(ilength(l) == hi - lo)
array_at_lengththeoremproof_kernel.h:484thm get_array_at_length();
thm get_array_at_length();
!x ty n l. array_at x ty n l |-- array_at x ty n l ** fact(ilength(l) == n)
!x ty n l. array_at x ty n l |-- array_at x ty n l ** fact(ilength(l) == n)
array_at_rangetheoremproof_kernel.h:487thm get_array_at_range();
thm get_array_at_range();
!x ty n l. array_at x ty n l |-- array_at x ty n l ** fact(!i. &0 <= i ==> i < n ==> (min_of(ty) <= inth i l && inth i l <= max_of(ty)))
!x ty n l. array_at x ty n l |-- array_at x ty n l ** fact(!i. &0 <= i ==> i < n ==> (min_of(ty) <= inth i l && inth i l <= max_of(ty)))
array_at_rec_splittheoremproof_kernel.h:490thm get_array_at_rec_split();
thm get_array_at_rec_split();
!x ty lo n m l. (lo <= n) ==> (n < m) ==> (array_at_rec x ty lo m l |-- data_at (x + n * sizeof(ty)) ty (inth (n - lo) l) ** array_at_missing_i_rec x ty n lo m l)
!x ty lo n m l. (lo <= n) ==> (n < m) ==> (array_at_rec x ty lo m l |-- data_at (x + n * sizeof(ty)) ty (inth (n - lo) l) ** array_at_missing_i_rec x ty n lo m l)
array_at_splittheoremproof_kernel.h:493thm get_array_at_split();
thm get_array_at_split();
!x ty n m l. (&0 <= n) ==> (n < m) ==> (array_at x ty m l |-- data_at (x + n * sizeof(ty)) ty (inth n l) ** array_at_missing_i_rec x ty n (&0) m l)
!x ty n m l. (&0 <= n) ==> (n < m) ==> (array_at x ty m l |-- data_at (x + n * sizeof(ty)) ty (inth n l) ** array_at_missing_i_rec x ty n (&0) m l)
array_at_rec_mergetheoremproof_kernel.h:496thm get_array_at_rec_merge();
thm get_array_at_rec_merge();
!x ty lo n m a l. (lo <= n) ==> (n < m) ==> (data_at (x + n * sizeof(ty)) ty a ** array_at_missing_i_rec x ty n lo m l |-- array_at_rec x ty lo m (replace_inth (n - lo) a l))
!x ty lo n m a l. (lo <= n) ==> (n < m) ==> (data_at (x + n * sizeof(ty)) ty a ** array_at_missing_i_rec x ty n lo m l |-- array_at_rec x ty lo m (replace_inth (n - lo) a l))
array_at_mergetheoremproof_kernel.h:499thm get_array_at_merge();
thm get_array_at_merge();
!x ty n m a l. (&0 <= n) ==> (n < m) ==> (data_at (x + n * sizeof(ty)) ty a ** array_at_missing_i_rec x ty n (&0) m l |-- array_at x ty m (replace_inth n a l))
!x ty n m a l. (&0 <= n) ==> (n < m) ==> (data_at (x + n * sizeof(ty)) ty a ** array_at_missing_i_rec x ty n (&0) m l |-- array_at x ty m (replace_inth n a l))
array_at_rec_headtheoremproof_kernel.h:502thm get_array_at_rec_head();
thm get_array_at_rec_head();
!x ty lo hi l. (lo < hi) ==> (array_at_rec x ty lo hi l |-- data_at (x + lo * sizeof(ty)) ty (inth (&0) l) ** array_at_rec x ty (lo + &1) hi (sublist (&1) (hi - lo) l))
!x ty lo hi l. (lo < hi) ==> (array_at_rec x ty lo hi l |-- data_at (x + lo * sizeof(ty)) ty (inth (&0) l) ** array_at_rec x ty (lo + &1) hi (sublist (&1) (hi - lo) l))
array_at_rec_head_mergetheoremproof_kernel.h:505thm get_array_at_rec_head_merge();
thm get_array_at_rec_head_merge();
!x ty lo hi a l. (lo < hi) ==> (data_at (x + lo * sizeof(ty)) ty a ** array_at_rec x ty (lo + &1) hi l |-- array_at_rec x ty lo hi (a :: l))
!x ty lo hi a l. (lo < hi) ==> (data_at (x + lo * sizeof(ty)) ty a ** array_at_rec x ty (lo + &1) hi l |-- array_at_rec x ty lo hi (a :: l))
array_at_array_rec_constheoremproof_kernel.h:508thm get_array_at_array_rec_cons();
thm get_array_at_array_rec_cons();
!x ty lo hi a l. (lo < hi) ==> (array_at_rec x ty lo hi (a :: l) |-- data_at (x + lo * sizeof(ty)) ty a ** array_at_rec x ty (lo + &1) hi l)
!x ty lo hi a l. (lo < hi) ==> (array_at_rec x ty lo hi (a :: l) |-- data_at (x + lo * sizeof(ty)) ty a ** array_at_rec x ty (lo + &1) hi l)
array_at_rec_tail_mergetheoremproof_kernel.h:511thm get_array_at_rec_tail_merge();
thm get_array_at_rec_tail_merge();
!x ty lo hi a l. (lo <= hi) ==> (data_at (x + hi * sizeof(ty)) ty a ** array_at_rec x ty lo hi l |-- array_at_rec x ty lo (hi + &1) (l ++ [a]))
!x ty lo hi a l. (lo <= hi) ==> (data_at (x + hi * sizeof(ty)) ty a ** array_at_rec x ty lo hi l |-- array_at_rec x ty lo (hi + &1) (l ++ [a]))
array_at_rec_basetheoremproof_kernel.h:514thm get_array_at_rec_base();
thm get_array_at_rec_base();
!x ty m k n l. array_at_rec x ty (m + k) n l -|- array_at_rec (x + k * sizeof(ty)) ty m (n - k) l
!x ty m k n l. array_at_rec x ty (m + k) n l -|- array_at_rec (x + k * sizeof(ty)) ty m (n - k) l
array_at_rec_divide_auxtheoremproof_kernel.h:517thm get_array_at_rec_divide_aux();
thm get_array_at_rec_divide_aux();
!x ty lo m n l. (lo <= m) ==> (m <= n) ==> (ilength(l) == n - lo) ==> (array_at_rec x ty lo n l -|- array_at_rec x ty lo m (sublist (&0) (m - lo) l) ** array_at_rec x ty m n (sublist (m - lo) (n - lo) l))
!x ty lo m n l. (lo <= m) ==> (m <= n) ==> (ilength(l) == n - lo) ==> (array_at_rec x ty lo n l -|- array_at_rec x ty lo m (sublist (&0) (m - lo) l) ** array_at_rec x ty m n (sublist (m - lo) (n - lo) l))
array_at_rec_dividetheoremproof_kernel.h:520thm get_array_at_rec_divide();
thm get_array_at_rec_divide();
!x ty m n l. (&0 <= m) ==> (m <= n) ==> (ilength(l) == n) ==> (array_at_rec x ty (&0) n l -|- array_at_rec x ty (&0) m (sublist (&0) m l) ** array_at_rec x ty m n (sublist m n l))
!x ty m n l. (&0 <= m) ==> (m <= n) ==> (ilength(l) == n) ==> (array_at_rec x ty (&0) n l -|- array_at_rec x ty (&0) m (sublist (&0) m l) ** array_at_rec x ty m n (sublist m n l))
array_at_dividetheoremproof_kernel.h:523thm get_array_at_divide();
thm get_array_at_divide();
!x ty n l m. (&0 <= m) ==> (m <= n) ==> (ilength(l) == n) ==> (array_at x ty n l -|- array_at x ty m (sublist (&0) m l) ** array_at (x + m * sizeof(ty)) ty (n - m) (sublist m n l))
!x ty n l m. (&0 <= m) ==> (m <= n) ==> (ilength(l) == n) ==> (array_at x ty n l -|- array_at x ty m (sublist (&0) m l) ** array_at (x + m * sizeof(ty)) ty (n - m) (sublist m n l))
array_at_divide2theoremproof_kernel.h:526thm get_array_at_divide2();
thm get_array_at_divide2();
!x ty n m l1 l2. (ilength(l1) == n) ==> (ilength(l2) == m) ==> (array_at x ty (n + m) (l1 ++ l2) -|- array_at x ty n l1 ** array_at (x + n * sizeof(ty)) ty m l2)
!x ty n m l1 l2. (ilength(l1) == n) ==> (ilength(l2) == m) ==> (array_at x ty (n + m) (l1 ++ l2) -|- array_at x ty n l1 ** array_at (x + n * sizeof(ty)) ty m l2)
array_at_divide_rectheoremproof_kernel.h:529thm get_array_at_divide_rec();
thm get_array_at_divide_rec();
!x ty n l m. (&0 <= m) ==> (m <= n) ==> (ilength(l) == n) ==> (array_at x ty n l -|- array_at_rec x ty (&0) m (sublist (&0) m l) ** array_at_rec x ty m n (sublist m n l))
!x ty n l m. (&0 <= m) ==> (m <= n) ==> (ilength(l) == n) ==> (array_at x ty n l -|- array_at_rec x ty (&0) m (sublist (&0) m l) ** array_at_rec x ty m n (sublist m n l))
undef_array_at_rec_basetheoremproof_kernel.h:532thm get_undef_array_at_rec_base();
thm get_undef_array_at_rec_base();
!x ty m k n len. undef_array_at_rec x ty (m + k) n len -|- undef_array_at_rec (x + k * sizeof(ty)) ty m (n - k) len
!x ty m k n len. undef_array_at_rec x ty (m + k) n len -|- undef_array_at_rec (x + k * sizeof(ty)) ty m (n - k) len
undef_array_at_dividetheoremproof_kernel.h:535thm get_undef_array_at_divide();
thm get_undef_array_at_divide();
!x ty n m. (&0 <= m) ==> (m <= n) ==> (undef_array_at x ty n -|- undef_array_at x ty m ** undef_array_at (x + m * sizeof(ty)) ty (n - m))
!x ty n m. (&0 <= m) ==> (m <= n) ==> (undef_array_at x ty n -|- undef_array_at x ty m ** undef_array_at (x + m * sizeof(ty)) ty (n - m))
undef_Tuchar_array_at_splittheoremproof_kernel.h:538thm get_undef_Tuchar_array_at_split();
thm get_undef_Tuchar_array_at_split();
!x ty n. n >= sizeof(ty) ==> (undef_array_at x Tuchar n -|- undef_data_at x ty ** undef_array_at (x + sizeof(ty)) Tuchar (n - sizeof(ty)))
!x ty n. n >= sizeof(ty) ==> (undef_array_at x Tuchar n -|- undef_data_at x ty ** undef_array_at (x + sizeof(ty)) Tuchar (n - sizeof(ty)))
array_at_split_firsttheoremproof_kernel.h:541thm get_array_at_split_first();
thm get_array_at_split_first();
!x ty n v l. (n >= &1) ==> (array_at x ty n (v :: l) |-- data_at x ty v ** array_at (x + sizeof(ty)) ty (n - &1) l)
!x ty n v l. (n >= &1) ==> (array_at x ty n (v :: l) |-- data_at x ty v ** array_at (x + sizeof(ty)) ty (n - &1) l)
array_at_merge_firsttheoremproof_kernel.h:544thm get_array_at_merge_first();
thm get_array_at_merge_first();
!x ty n v l. data_at x ty v ** array_at (x + sizeof(ty)) ty n l |-- array_at x ty (n + &1) (v :: l)
!x ty n v l. data_at x ty v ** array_at (x + sizeof(ty)) ty n l |-- array_at x ty (n + &1) (v :: l)
array_at_split_lasttheoremproof_kernel.h:547thm get_array_at_split_last();
thm get_array_at_split_last();
!x ty n v l. (n >= &1) ==> (array_at x ty n (l ++ [v]) |-- array_at x ty (n - &1) l ** data_at (x + (n - &1) * sizeof(ty)) ty v)
!x ty n v l. (n >= &1) ==> (array_at x ty n (l ++ [v]) |-- array_at x ty (n - &1) l ** data_at (x + (n - &1) * sizeof(ty)) ty v)
array_at_merge_lasttheoremproof_kernel.h:550thm get_array_at_merge_last();
thm get_array_at_merge_last();
!x ty n v l. array_at x ty n l ** data_at (x + n * sizeof(ty)) ty v |-- array_at x ty (n + &1) (l ++ [v])
!x ty n v l. array_at x ty n l ** data_at (x + n * sizeof(ty)) ty v |-- array_at x ty (n + &1) (l ++ [v])
undef_array_at_split_firsttheoremproof_kernel.h:553thm get_undef_array_at_split_first();
thm get_undef_array_at_split_first();
!x ty n. (n >= &1) ==> (undef_array_at x ty n |-- undef_data_at x ty ** undef_array_at (x + sizeof(ty)) ty (n - &1))
!x ty n. (n >= &1) ==> (undef_array_at x ty n |-- undef_data_at x ty ** undef_array_at (x + sizeof(ty)) ty (n - &1))
undef_array_at_merge_firsttheoremproof_kernel.h:556thm get_undef_array_at_merge_first();
thm get_undef_array_at_merge_first();
!x ty n. undef_data_at x ty ** undef_array_at (x + sizeof(ty)) ty n |-- undef_array_at x ty (n + &1)
!x ty n. undef_data_at x ty ** undef_array_at (x + sizeof(ty)) ty n |-- undef_array_at x ty (n + &1)
undef_array_at_split_lasttheoremproof_kernel.h:559thm get_undef_array_at_split_last();
thm get_undef_array_at_split_last();
!x ty n. (n >= &1) ==> (undef_array_at x ty n |-- undef_array_at x ty (n - &1) ** undef_data_at (x + (n - &1) * sizeof(ty)) ty)
!x ty n. (n >= &1) ==> (undef_array_at x ty n |-- undef_array_at x ty (n - &1) ** undef_data_at (x + (n - &1) * sizeof(ty)) ty)
undef_array_at_merge_lasttheoremproof_kernel.h:562thm get_undef_array_at_merge_last();
thm get_undef_array_at_merge_last();
!x ty n. undef_array_at x ty n ** undef_data_at (x + n * sizeof(ty)) ty |-- undef_array_at x ty (n + &1)
!x ty n. undef_array_at x ty n ** undef_data_at (x + n * sizeof(ty)) ty |-- undef_array_at x ty (n + &1)
array_at_zerotheoremproof_kernel.h:565thm get_array_at_zero();
thm get_array_at_zero();
!x ty n l. (n == &0) ==> (l == []) ==> (array_at x ty n l -|- emp)
!x ty n l. (n == &0) ==> (l == []) ==> (array_at x ty n l -|- emp)
undef_array_at_zerotheoremproof_kernel.h:568thm get_undef_array_at_zero();
thm get_undef_array_at_zero();
!x ty n. (n == &0) ==> (undef_array_at x ty n -|- emp)
!x ty n. (n == &0) ==> (undef_array_at x ty n -|- emp)
One addressing convention runs through all of them: element ii of an array based at xx with element type tyty lives at x + i * sizeof(ty)x + i * sizeof(ty). Typed Memory Predicates groups these same rules by what they do and works through the ones a loop invariant actually needs.
proof_kernel.hproof_kernel.h declares ten opaque handle types and six list aliases, three macros implementing the accessor convention, thirty-three accessors for the logic’s built-in terms and types, and one hundred and forty-one theorem accessors. A theorem named TT in the kernel is get_T()get_T() in C; the object is fetched from the prover once and cached for the rest of the run.
That is the entire interface between proof code and the logic’s built-in vocabulary. Everything a proof then does with the objects it obtains here — matching, instantiating, rewriting, discharging — belongs to the prover API, and everything the engine does with the results belongs to the symbolic execution API.