subred.aux.art


notation syntax rsyntax rels runtime rstatics conforms ;

import syntax rsyntax runtime0 wf wfenv rstatics1 statics1 rsubst cstatics subred.aux conforms ;

// Frame allocation preserves conformance, if all the conditions are right...

proof of // frame-allocation-lemma if TE wf_tyenv TE_wf !j. j < LEN(argvals) --> ?varty. (TE,heap) |- EL(j)(argvals) rval_hastype varty & TE |- varty varty_widens_to EL(j)(AT) args_fit (TE,heap) |- thisval rval_hastype objty addr_types TE |- objty varty_widens_to thisty this_fits frames1 = sAddFrame(frames0,frame1) frame1 = PGRAPH gframe1 <+ (this, thisval) gframe1 = { (x,z) | ?j. j < LEN(Xord) & x = EL(j)(Xord) & z = EL(j)(argvals) } gframe1 LEN(Xord) = LEN(argvals) [elim,auto] TE |- heap heap_conforms heap_conforms (TE,heap) |- frames0 frames_conform_to FT0 frames0_conform FT1 = FT0 ×! (Xtys <+ (this, thisty)) AT = MAP(PAPPLY(Xtys))(Xord) AT ELS(Xord) = PDOM(Xtys) no_repeats ORDERING(Xord) ordered_args then (TE,heap) |- frames1 frames_conform_to FT1 g; have IS_GRAPH gframe1 graph_frame1 by GRAPH_FROM_LISTS [Xord/l1,argvals/l2],gframe1,ordered_args; have (TE,heap) |- thisval val_conforms_to thisty this_fits2 by conforms-from-typing [TE,heap,thisval], val_conforms-trans [TE,heap,thisval], this_fits,heap_conforms,TE_wf,addr_types; have !j. j < LEN(argvals) --> (TE,heap) |- EL(j)(argvals) val_conforms_to EL(j)(AT) args_fit2 by conforms-from-typing [TE,heap], val_conforms-trans [TE,heap], args_fit,heap_conforms,TE_wf; // needs unification up to records/tuples given our aggressive untupling of quantifiers have LEN(frames0) = LEN(FT0) [rw,auto] by FRAMES_CONFORM_TO,frames0_conform; have LEN(frames1) = LEN(FT1) by sAddFrame; then consider fidx,FS,id,vt st + fidx < LEN(frames1) fidx + FS = EL(fidx)(FT1) + id :: PDOM(FS) id_in_FS + PLOOKUP(FS)(id) = SOME(vt) [rw,auto] - ?val. sGetStackVar(frames1,fidx,id) = SOME(val) & (TE,heap) |- val val_conforms_to vt g2 by FRAMES_CONFORM_TO,g; per cases case fidx = LEN(frames0) ; have FS = Xtys <+ (this, thisty) ; consider j st j < LEN(Xord) id <> this id = EL(j)(Xord) by ELS_ELIM,FUN_EQ,IN_ELIM,id_in_FS,no_repeats,GSPEC_ELIM, sGetStackVar,sAddFrame,this_fits2,g2 [thisval]; have (id,EL(j)(argvals)) :: gframe1 [auto,rw] by gframe1; have frame1 id = SOME(EL(j)(argvals)) [auto,rw] by IN_ELIM,PGRAPH_SOME [gframe1/R],graph_frame1; have PAPPLY(FS)(id) = vt [auto,rw] by PAPPLY_ELIM; qed by g2 [EL(j)(argvals)],args_fit2 [j],sGetStackVar,sAddFrame,AT,PAPPLY_ELIM; case fidx < LEN(frames0) ; qed by FRAMES_CONFORM_TO__stackvar [frames0,TE,heap,FT0,fidx,id,vt], frames0_conform,sGetStackVar,sAddFrame,id_in_FS; end by BOUNDED_CASES [fidx/m,LEN(frames0)/n],fidx,sAddFrame;

// Prove that translating from compiled source expressions preserves types // // One of those cool proofs where simplification and meson do all the work. // (Actually the last two cases are not proved automatically, though // they almost are! I've left them as future challenges as they are // good examples of how mixing equality reasoning and first order reasoning // is kind of difficult.)

proof of // mk_exp-preserves-types if TE wf_tyenv TE_wf fidx < LEN(FT:ftyenv) fidx_OK !id. PLOOKUP(EL(fidx)(FT))(id) = PLOOKUP(VE)(id) wf_FT then { if (TE,VE) |- var cvar_hastype var_ty var_types then (TE,FT,heap) |- (mk_rvar fidx var) rvar_hastype var_ty } and { if (TE,VE) |- exp cexp_hastype exp_ty exp_types then (TE,FT,heap) |- (mk_rexp fidx exp) rexp_hastype exp_ty }; proceed by rule induction on var_types with var,var_ty variable, exp_types with exp,exp_ty variable; case Id; qed by fidx_OK,wf_FT,rstatics__StackVar [TE],PDOM,IN_ELIM,mk_rexp; case Access; then qed by mk_rexp,rstatics__Access [TE,FT]; case FieldA; then qed by mk_rexp,rstatics__Field [TE,FT]; case Var; then qed by mk_rexp,rstatics__Var [TE,FT]; case Void; then qed by mk_rexp,rstatics__Void [TE,FT]; case Prim; then qed by mk_rexp,rval_hastype__Prim,rstatics__Value [TE,FT]; case NewClassA; then qed by mk_rexp,rstatics__NewClass [TE,FT,heap]; case NewArray; then qed by hard mk_rexp,rstatics__NewArray [TE,FT,heap],ALL_ELIM; // both of these fail - good examples of how equality reasoning and first order are hard to mix. Work on this case CallA; then qed by hard mk_rexp,rstatics__Call [TE,FT,heap],ALL_ELIM; // both of these fail - good examples of how equality reasoning and first order are hard to mix. Work on this end;

// And the same for statements...

proof of // mk_stmt-preserves-types if TE wf_tyenv fidx < LEN(FT:ftyenv) !id. PLOOKUP(EL(fidx)(FT))(id) = PLOOKUP(VE)(id) (TE,VE) |- stmt cstmt_hastype stmt_types then (TE,FT,heap) |- (mk_rstmt fidx stmt) rstmt_hastype; proceed by rule induction on stmt_types with stmt variable; case Assign stmt = AssignA(l,r) (TE,VE) |- l cvar_hastype lty l_types (TE,VE) |- r cexp_hastype SOME(rty) TE |- rty varty_widens_to lty; then qed by structural cases on l,mk_rexp, rstatics__AssignToField [TE,FT,heap], rstatics__AssignToArray [TE,FT,heap], rstatics__AssignToStackVar [TE,FT,heap], mk_exp-preserves-types [TE,FT,VE,heap,fidx,r], mk_var-preserves-types [TE,FT,VE,heap,fidx,l]; case If; then qed by mk_rexp,rstatics__If [TE,FT,heap],mk_exp-preserves-types [TE,FT,VE,heap,fidx]; case Block stmt = BlockA(stmts) !j. j < LEN stmts --> (TE,FT,heap) |- mk_rstmt fidx (EL j stmts) rstmt_hastype & (TE,VE) |- EL j stmts cstmt_hastype; then qed by mk_rexp,rstatics__Block [TE,FT,heap,MAP (mk_rstmt fidx) stmts],ALL_ELIM; case Expr; then qed by mk_rexp,rstatics__Expr [TE,FT,heap],mk_exp-preserves-types [TE,FT,VE,heap,fidx]; end;

// And thus the same for method bodies...

proof of // mk_body-preserves-types if TE wf_tyenv fidx < LEN(FT:ftyenv) !id. PLOOKUP(EL(fidx)(FT))(id) = PLOOKUP(VE)(id) (TE,VE) |- body cbody_hastype rt body_types then (TE,FT,heap) |- RBody(mk_rbody fidx body) rexp_hastype rt; qed by rule cases on body_types,mk_rbody, rstatics__Body [TE,FT], mk_exp-preserves-types [TE,FT,VE,heap,fidx], mk_stmt-preserves-types [TE,FT,VE,heap,fidx];