Lectures onType Theory
Difference refinements and source proof-carrying code
appendix sectionrules

Difference refinements and source proof-carrying code

The system of chapter 10 is a separate, nondependent calculus. Its base types, values, atoms, computations, and expressions are B::=intarr,v::=nn0,,nk1(λx.e:x:st)(fix f(x).e:x:st),a::=xv,c::=a+klenageta1a2a1a2,e::=alet x=c in eif δ then e1 else e2error. Here k,n,niZ. Terms are A-normal by grammar. Bind composition, with capture-avoiding renaming before its let clause, is axe2=e2[a/x],(let y=c in e)xe2=let y=c in(exe2),(if δ then e0 else e1)xe2=if δ then(e0xe2) else(e1xe2),errorxe2=error. Reduction is on closed terms. For A=n0,,nm1 its complete root table is

q=n+k in Z
let x=n+k in ee[q/x]
E-Shift
let x=lenA in ee[m/x]
E-Len
0i<m
let x=getAi in ee[ni/x]
E-Get
let y=(λx.e1:x:st)v in e2e1[v/x]ye2
E-Beta
F=(fix f(x).e1:x:st)
let y=Fv in e2e1[F/f,v/x]ye2
E-Fix
δ is true
if δ then e1 else e2e1
E-IfT
δ is false
if δ then e1 else e2e2
E-IfF

There is no reduction root for an out-of-bounds get and no congruence relation: the grammar exposes the next computation at the head of a let.

Predicate vertices, atoms, conjunctions, and types are r::=0xLa,δ::=rsk,p::=trueδp,t::={ν:Bp}x:st. La abbreviates len(a). An integer declaration contributes x to the vertex scope, an array declaration contributes Lx, and a function declaration contributes no vertex. Put μint(ν)=ν and μarr(ν)=Lν. The complement of one integer atom is rsk:=srk1. Literal substitution replaces an integer literal n by 0+n and an array literal of length m by 0+m, then moves constants to the right side of . Contexts and their complete formation table are

 ctx
WF-Empty
Γ ctxΓt typexdom(Γ)
Γ,x:t ctx
WF-Var
Γ ctxδ over V(Γ)
Γ,δ ctx
WF-Guard
Γ ctxp over V(Γ){μB(ν)}
Γ{ν:Bp} type
WF-Base
Γs typeΓ,x:st type
Γx:st type
WF-Arrow

The shape operation is |{ν:Bp}|=B and |x:st|=|s||t|.

The context embedding and semantic entailment are =true,Γ,x:{ν:Bp}=Γp[x/ν],Γ,x:(y:st)=Γ,Γ,δ=Γδ. A valuation maps integer variables to integers and array variables to finite integer arrays, interprets La by array length, and satisfies Γ when it satisfies Γ. The judgment Γp means that every such valuation satisfying Γ satisfies p.

For certificate replay, GΓ has vertices 0 and V(Γ). Every replayed goal atom is required to use only those vertices. Each hypothesis rsk contributes an identified edge skr, and every array vertex contributes the implicit edge La00. A path certificate for rsk is a possibly empty adjacent edge list from s to r with weight sum at most k. A contradiction certificate is a nonempty adjacent cyclic edge list of negative sum. The replay checker re-reads the identified edges, verifies adjacency and endpoints, adds weights in Z, and checks the final bound. A conjunctive goal accepts one contradiction certificate or one path certificate per conjunct. These checks, rather than an external solver’s answer, are the certificate judgment.

Subtyping has exactly two rules. Every displayed type is well formed; z is fresh in the base rule, and arrow binders are alpha-aligned.

zdom(Γ)Γ,z:{ν:Bp}q[z/ν]
Γ{ν:Bp}<:{ν:Bq}
S-Base
Γs1<:t1Γ,x:s1t2<:s2
Γ(x:t1t2)<:(x:s1s2)
S-Arrow

For an integer atom, (x,0) and (0,n) are its representatives; for an array atom, (La,0) and (0,m) are its length representatives. The exact result constructors and get precondition are EqI(r,k)={ν:intνrkrνk},Shift(a,j)=EqI(r,k+j),Length(a)=EqI(r,k),Arraym={ν:arrLν0m0Lνm},Bnd(a,i)=(0riki)(rirakaki1). The second through fourth lines use the representative appropriate to their argument. Atoms and computations synthesize; expressions check. The complete declarative table is

x:tΓ
Γxt
D-Var
ΓnEqI(0,n)
D-Int
A has length m
ΓAArraym
D-Array
Γx:st typeΓ,x:set
Γ(λx.e:x:st)x:st
D-Lam
Γx:st typeΓ,f:(x:st),x:set
Γ(fix f(x).e:x:st)x:st
D-Fix
Γas|s|=int
Γa+kcShift(a,k)
D-Shift
Γas|s|=arr
ΓlenacLength(a)
D-Length
Γas|s|=arrΓiu|u|=intΓBnd(a,i)
Γgetaicint
D-Get
Γfx:stΓas
Γfact[a/x]
D-App
ΓasΓs<:t
Γat
D-Sub
ΓccsΓ,x:setxfv(t)
Γlet x=c in et
D-Let
Γ,δ ctxΓ,δe1tΓ,δe2t
Γif δ then e1 else e2t
D-If
Γt type
Γerrort
D-Error

The VC generator has the three partial judgments ΓatC,ΓcctC,ΓetC. Its subtyping translation, with z fresh, is SubVC(Γ;{ν:Bp},{ν:Bq})={(Γ,z:{ν:Bp};q[z/ν])},SubVC(Γ;(x:s1s2),(x:t1t2))=SubVC(Γ;t1,s1)SubVC(Γ,x:t1;s2,t2). It fails on a shape mismatch, an ill-formed displayed type, or a failed recursive call. With A, Comp, and K denoting the three deterministic partial functions, the atom clauses are AΓ(x)=(Γ(x),),AΓ(n)=(EqI(0,n),),AΓ(n0,,nm1)=(Arraym,),AΓ(λx.e:x:st)=(x:st,C)if KΓ,x:s(e,t)=C,AΓ(fix f(x).e:x:st)=(x:st,C)if KΓ,f:(x:st),x:s(e,t)=C. Every annotation and entry is also checked for well-formedness. Put BΓ(a,i)={(Γ;δ)δ is a conjunct of Bnd(a,i)}. The computation clauses are CompΓ(a+k)=(Shift(a,k),C)if AΓ(a)=(s,C) and |s|=int,CompΓ(lena)=(Length(a),C)if AΓ(a)=(s,C) and |s|=arr,CompΓ(getai)=(int,CaCiBΓ(a,i))if AΓ(a)=(s,Ca), |s|=arr,if AΓ(i)=(u,Ci), |u|=int,CompΓ(fa)=(t[a/x],CfCa)if AΓ(f)=(x:st,Cf)and KΓ(a,s)=Ca. The checking clauses, where eδ=if δ then e1 else e2, are KΓ(a,t)=CSubVC(Γ;s,t)if AΓ(a)=(s,C),KΓ(let x=c in e,t)=CcCeif CompΓ(c)=(s,Cc),if KΓ,x:s(e,t)=Ce,if xfv(t),KΓ(eδ,t)=C1C2if KΓ,δ(e1,t)=C1,if KΓ,δ(e2,t)=C2,KΓ(error,t)=. No other clause is implicit. A generated sequent is accepted only after the certificate checker above accepts its evidence.

For finite-qualifier inference, K is a finite set of predicate unknowns and each Qκ is a finite set of well-scoped difference atoms. An assignment ηκKP(Qκ) replaces κ by the conjunction of the chosen subset; the empty subset means true. Enumeration instantiates the annotated program, runs the displayed VC generator, and accepts the first assignment for which every generated VC has checked replay evidence. This is the entire Liquid fragment: it introduces no additional typing or entailment rule.

The first-order dynamic guard is a source term defined by guard(true,e)=e,guard(δp,e)=if δ thenguard(p,e) elseerror. It is not a higher-order contract wrapper. The source proof-carrying-code package is (e,t,Π). Its consumer parses the chapter grammar and checks well-formedness; recomputes the complete VC list for et; matches Π against that recomputed list and replays every certificate; and enables the displayed source reduction only after all checks accept. Producer-supplied VC lists are ignored.

For the erasure boundary, simple types and contexts are τ::=intarrττ,Ξ::=Ξ,x:τ. Erasure maps refinements to their base shape, dependent arrows to simple arrows, declarations pointwise, and guard entries to nothing. It is homomorphic on terms except for erasing lambda and fixpoint refinements from annotations; dynamic conditionals and error remain. The target has the three judgments Ξ0aτ, Ξ0ccτ, and Ξ0eτ. Its complete term table is

x:τΞ
Ξ0xτ
ST-Var
Ξ0nint
ST-Int
Ξ0Aarr
ST-Array
Ξ,x:τ0eσ
Ξ0(λx.e:τσ)τσ
ST-Lam
Ξ,f:(τσ),x:τ0eσ
Ξ0(fix f(x).e:τσ)τσ
ST-Fix
Ξ0aint
Ξ0a+kcint
ST-Shift
Ξ0aarr
Ξ0lenacint
ST-Length
Ξ0aarrΞ0iint
Ξ0getaicint
ST-Get
Ξ0fτσΞ0aτ
Ξ0facσ
ST-App
Ξ0aτ
Ξ0aτ
ST-Atom
Ξ0ccτΞ,x:τ0eσ
Ξ0let x=c in eσ
ST-Let
δ over V(Ξ)Ξ0e1τΞ0e2τ
Ξ0if δ then e1 else e2τ
ST-If
Ξ0τ type
Ξ0errorτ
ST-Error

Simple formation has exactly the three base/arrow constructors of τ; there is no target subtyping judgment. The target deliberately omits the source bounds premise from ST-Get.

Search the book

Type to search the local edition.