Tests for Inline.lean #
One command per pass, so a failure localizes. Every command checks the proof it gets
(Meta.check, and that it proves the expected statement about the input), and every command
that prints surface syntax also re-parses what it printed (ProgTest.roundtrip). #flattenCall
prints the uncleaned output of Flatten.flattenCall — full of applyLens and chain*; its
shape is determined by the input's shape, with no simp set in the loop.
Elaborate a test's input term.
Equations
Instances For
Check that step.proof proves input.EquivInLens step.stmt step.trafo.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Check that proof proves procedureDenotation p' = procedureDenotation p.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Flatten call n of a statement, uncleaned.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Flatten call n of a statement, cleaned.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The whole pass on a statement.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The whole pass on a procedure.
Equations
- One or more equations did not get rendered due to their size.
Instances For
flattenSeq alone.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Unfold a module term to the procedure it denotes.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Unfold the callee of one call site.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Unfold the callee of one call site, then flatten it.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Inline one call site of a procedure.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A first end-to-end case #
More cases #
Two calls in one body, and a name collision: both callees call their local w, and so does
the caller. The caller's w keeps its name; the callees' are renamed.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A callee whose variable has the name of a parameter of the caller that the body never mentions: the parameter keeps its name (the entry state has to stay the same), the callee's variable is renamed.
Equations
Instances For
flattenSeq on its own #
Nested blocks and skips, with no call anywhere: the spine is re-associated to the right and the
skips disappear, and the proof is a chain of seq_assoc/skip_seq/seq_skip.
What is left alone #
A callee that is not spelled out at the call site stays a call, and a statement with no flattenable call at all is an error.
Equations
- GaudisCrypt.InlineTest.callsOpaque = proc () : ℕ { var x : ℕ; x <- 1; x <- call GaudisCrypt.InlineTest.opaqueCallee (§x); return §x }
Instances For
Inlining: callees named through modules #
A module type with one procedure, a module over it that calls a parameter, and a module that
calls nothing: the two shapes inlining evaluates, T.f ‹module expression› and M.f.
The record of a module's fields: U.structure m is U.Structure.mk applied to U.g of m.
Inverse of U.mk (U.mk_destruct, U.destruct_mk).
Instances For
Builds a module of type U from the record U.Structure of its fields, as a right-nested Module.pair'. @[reducible].
Inverse of U.structure (U.mk_destruct, U.destruct_mk); a single field of a module built this way is read back by the @[simp] lemmas U.g.mk_simp.
Equations
- GaudisCrypt.InlineTest.U.mk theRecord✝ = theRecord✝.g
Instances For
@[simp]: U.structure (U.mk r) = r — destructing a module built from a record gives that record back.
What is derivable about the accessor U.g, bundled into one ModuleTypeUtilities (one name per field in the namespace, rather than one per fact):
U.g.utilities.accessorModule : U →ₘ …— the accessor as a module, a projection being a module morphism;U.g.utilities.apply_simp—Module.app U.g.utilities.accessorModule m = U.g m: applying that module is the accessor;U.g.utilities.expression_eq— the same at the level of expressions:(U.g m).expression = (U.g.utilities.proj m.expression).reduce.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The field g of a module of type U: the projection onto component 0 of the right-nested tuple U.typeRep, as a chain of Module.fst'/Module.snd'. Tagged @[module_accessor].
U.g.mk_simp reads this field back off a module built by U.mk; U.g.utilities has the accessor as a module, and the lemmas about it.
Instances For
The IsModule U instance: U is a module type, with representation U.typeRep.
It is what lets the name U stand where a module type is expected — in Module.Arr/Module.Prod (→ₘ/×ₘ), say — which the underlying Module U.typeRep would do on its own but U, a plain (non-reducible) def, would not.
Equations
- GaudisCrypt.InlineTest.instIsModuleU = { moduleTypeRep := GaudisCrypt.InlineTest.U.typeRep, isModule := ⋯ }
The module type declared by moduletype U, with fields g: the type Module U.typeRep of modules that are a right-nested tuple of the field types.
Build one from a record of its fields with U.mk, read a single field off one with the accessors U.g, and get the whole record back with U.structure.
Instances For
@[simp]: reading the field g back off a module built from a record — U.g (U.mk r) = r.g.
It is what carries the right-hand side of an X.apply_simp (which is an U.mk) on to the field the caller actually asked for, so that simp chains X.apply_simp into X.g.apply_simp.
The module type declared by moduletype T, with fields f, h: the type Module T.typeRep of modules that are a right-nested tuple of the field types.
Build one from a record of its fields with T.mk, read a single field off one with the accessors T.f, T.h, and get the whole record back with T.structure.
Instances For
The record of a module's fields: T.structure m is T.Structure.mk applied to T.f, T.h of m.
Inverse of T.mk (T.mk_destruct, T.destruct_mk).
Instances For
Builds a module of type T from the record T.Structure of its fields, as a right-nested Module.pair'. @[reducible].
Inverse of T.structure (T.mk_destruct, T.destruct_mk); a single field of a module built this way is read back by the @[simp] lemmas T.f.mk_simp, T.h.mk_simp.
Equations
- GaudisCrypt.InlineTest.T.mk theRecord✝ = GaudisCrypt.Module.pair' theRecord✝.f theRecord✝.h
Instances For
What is derivable about the accessor T.f, bundled into one ModuleTypeUtilities (one name per field in the namespace, rather than one per fact):
T.f.utilities.accessorModule : T →ₘ …— the accessor as a module, a projection being a module morphism;T.f.utilities.apply_simp—Module.app T.f.utilities.accessorModule m = T.f m: applying that module is the accessor;T.f.utilities.expression_eq— the same at the level of expressions:(T.f m).expression = (T.f.utilities.proj m.expression).reduce.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The field f of a module of type T: the projection onto component 0 of the right-nested tuple T.typeRep, as a chain of Module.fst'/Module.snd'. Tagged @[module_accessor].
T.f.mk_simp reads this field back off a module built by T.mk; T.f.utilities has the accessor as a module, and the lemmas about it.
Equations
- theModule✝.f = GaudisCrypt.Module.fst' theModule✝
Instances For
The field h of a module of type T: the projection onto component 1 of the right-nested tuple T.typeRep, as a chain of Module.fst'/Module.snd'. Tagged @[module_accessor].
T.h.mk_simp reads this field back off a module built by T.mk; T.h.utilities has the accessor as a module, and the lemmas about it.
It takes no parameters (recorded in @[gaudiProcParamNames]).
Equations
- theModule✝.h = GaudisCrypt.Module.snd' theModule✝
Instances For
@[simp]: reading the field h back off a module built from a record — T.h (T.mk r) = r.h.
It is what carries the right-hand side of an X.apply_simp (which is an T.mk) on to the field the caller actually asked for, so that simp chains X.apply_simp into X.h.apply_simp.
@[simp]: T.structure (T.mk r) = r — destructing a module built from a record gives that record back.
@[simp]: reading the field f back off a module built from a record — T.f (T.mk r) = r.f.
It is what carries the right-hand side of an X.apply_simp (which is an T.mk) on to the field the caller actually asked for, so that simp chains X.apply_simp into X.f.apply_simp.
What is derivable about the accessor T.h, bundled into one ModuleTypeUtilities (one name per field in the namespace, rather than one per fact):
T.h.utilities.accessorModule : T →ₘ …— the accessor as a module, a projection being a module morphism;T.h.utilities.apply_simp—Module.app T.h.utilities.accessorModule m = T.h m: applying that module is the accessor;T.h.utilities.expression_eq— the same at the level of expressions:(T.h m).expression = (T.h.utilities.proj m.expression).reduce.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The IsModule T instance: T is a module type, with representation T.typeRep.
It is what lets the name T stand where a module type is expected — in Module.Arr/Module.Prod (→ₘ/×ₘ), say — which the underlying Module T.typeRep would do on its own but T, a plain (non-reducible) def, would not.
Equations
- GaudisCrypt.InlineTest.instIsModuleT = { moduleTypeRep := GaudisCrypt.InlineTest.T.typeRep, isModule := ⋯ }
proc f of module M as a module, abstracted over the module parameters it uses (A, in declaration order): Module.Arr … (Module.Proc (procsig …)).
Apply it with the @[simp] lemma M.f.apply_simp, which fills the holes of M.f.procedure with the callees the body called.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Instantiating the holes of M.f.procedure with a tuple holeArgs of procedures: the body of proc f as written, with each hole call replaced by the matching holeArgs.lookup (HoleIndex.zero being the first hole the body declared). True by rfl.
Deliberately not @[simp], unlike the other apply_simp lemmas: its right-hand side is the whole body written out, so letting it fire on its own would turn any goal mentioning an instantiated procedure into that body. Inlining a procedure is a step to ask for by name (simp [M.f.procedure.apply_simp]).
@[simp]: applying M.f to the parameters proc f uses (A) is Module.proc (M.f.procedure.instantiate …) — the procedure with its holes filled by the callees they were made from, each written as it was in the body (with the arguments in place of the module parameters) and turned into a Procedure by Module.Proc.procedure.
proc h of module M as a module: Module.proc M.h.procedure, of type Module.Proc (procsig …). It uses no module parameter, so it is not a function — M.h.apply_simp says exactly that.
Instances For
Instantiating the holes of M.h.procedure with a tuple holeArgs of procedures: the body of proc h as written, with each hole call replaced by the matching holeArgs.lookup (HoleIndex.zero being the first hole the body declared). True by rfl.
Deliberately not @[simp], unlike the other apply_simp lemmas: its right-hand side is the whole body written out, so letting it fire on its own would turn any goal mentioning an instantiated procedure into that body. Inlining a procedure is a step to ask for by name (simp [M.h.procedure.apply_simp]).
@[simp]: M.h = Module.proc M.h.procedure — true by definition, proc h using no module parameter and so having no holes to fill.
The module declared by module M, abstracted over its single parameter A, which it takes as one right-nested tuple: Module.Arr (T₁ ×ₘ (… ×ₘ Tₙ)) M, with M the module type it was declared with.
Applied to such a tuple it is the record of its procedures M.f, M.h, each applied to the parameters that procedure itself uses — which is what the @[simp] lemma M.apply_simp says.
Equations
- One or more equations did not get rendered due to their size.
Instances For
@[simp]: applying M to a tuple of its single parameter A — the record of its procedures M.f, M.h, each applied to the parameters it uses.
This is the lemma that unfolds a module use: simp rewrites with it, then with the field lemmas of the module type (N.f.mk_simp) to get at the one procedure the goal is about, and then with M.f.apply_simp, M.h.apply_simp to fill that procedure's holes.
The body of proc f of module M, as a procedure of its own: the one call it makes to a module parameter (A) is its single hole.
A hole stands for a call whose callee is not known here — a module parameter is supplied only when the module is applied — so the body is a ProcedureWithHoles, to be instantiated (see M.f.procedure.apply_simp) rather than run. Use M.f for this procedure as a module.
Equations
Instances For
The body of proc h of module M, as a procedure of its own: it calls no module parameter, so it has no holes.
A hole stands for a call whose callee is not known here — a module parameter is supplied only when the module is applied — so the body is a ProcedureWithHoles, to be instantiated (see M.h.procedure.apply_simp) rather than run. Use M.h for this procedure as a module.
Equations
- GaudisCrypt.InlineTest.M.h.procedure = proc () : ℕ { skip; return 5 }
Instances For
proc h of module N as a module: Module.proc N.h.procedure, of type Module.Proc (procsig …). It uses no module parameter, so it is not a function — N.h.apply_simp says exactly that.
Instances For
@[simp]: N.f = Module.proc N.f.procedure — true by definition, proc f using no module parameter and so having no holes to fill.
Instantiating the holes of N.h.procedure with a tuple holeArgs of procedures: the body of proc h as written, with each hole call replaced by the matching holeArgs.lookup (HoleIndex.zero being the first hole the body declared). True by rfl.
Deliberately not @[simp], unlike the other apply_simp lemmas: its right-hand side is the whole body written out, so letting it fire on its own would turn any goal mentioning an instantiated procedure into that body. Inlining a procedure is a step to ask for by name (simp [N.h.procedure.apply_simp]).
The body of proc h of module N, as a procedure of its own: it calls no module parameter, so it has no holes.
A hole stands for a call whose callee is not known here — a module parameter is supplied only when the module is applied — so the body is a ProcedureWithHoles, to be instantiated (see N.h.procedure.apply_simp) rather than run. Use N.h for this procedure as a module.
Equations
- GaudisCrypt.InlineTest.N.h.procedure = proc () : ℕ { skip; return 7 }
Instances For
Instantiating the holes of N.f.procedure with a tuple holeArgs of procedures: the body of proc f as written, with each hole call replaced by the matching holeArgs.lookup (HoleIndex.zero being the first hole the body declared). True by rfl.
Deliberately not @[simp], unlike the other apply_simp lemmas: its right-hand side is the whole body written out, so letting it fire on its own would turn any goal mentioning an instantiated procedure into that body. Inlining a procedure is a step to ask for by name (simp [N.f.procedure.apply_simp]).
The module declared by module N: the record of its procedures N.f, N.h.
The declaration has no parameter list, so no procedure of it can call one either and the module is not a function — it is the plain record itself, and there is no N.apply_simp to apply it with.
Equations
Instances For
proc f of module N as a module: Module.proc N.f.procedure, of type Module.Proc (procsig …). It uses no module parameter, so it is not a function — N.f.apply_simp says exactly that.
Instances For
The body of proc f of module N, as a procedure of its own: it calls no module parameter, so it has no holes.
A hole stands for a call whose callee is not known here — a module parameter is supplied only when the module is applied — so the body is a ProcedureWithHoles, to be instantiated (see N.f.procedure.apply_simp) rather than run. Use N.f for this procedure as a module.
Equations
Instances For
@[simp]: N.h = Module.proc N.h.procedure — true by definition, proc h using no module parameter and so having no holes to fill.
proc f of module Q as a module, abstracted over the module parameters it uses (A, B, in declaration order): Module.Arr … (Module.Proc (procsig …)).
Apply it with the @[simp] lemma Q.f.apply_simp, which fills the holes of Q.f.procedure with the callees the body called.
Equations
- One or more equations did not get rendered due to their size.
Instances For
@[simp]: applying Q to a tuple of its 2 parameters A, B — the record of its procedures Q.f, Q.h, each applied to the parameters it uses.
This is the lemma that unfolds a module use: simp rewrites with it, then with the field lemmas of the module type (N.f.mk_simp) to get at the one procedure the goal is about, and then with Q.f.apply_simp, Q.h.apply_simp to fill that procedure's holes.
proc h of module Q as a module: Module.proc Q.h.procedure, of type Module.Proc (procsig …). It uses no module parameter, so it is not a function — Q.h.apply_simp says exactly that.
Instances For
@[simp]: Q.h = Module.proc Q.h.procedure — true by definition, proc h using no module parameter and so having no holes to fill.
The body of proc f of module Q, as a procedure of its own: the 2 calls it makes to module parameters (A, B) are its holes, in the order the body makes them.
A hole stands for a call whose callee is not known here — a module parameter is supplied only when the module is applied — so the body is a ProcedureWithHoles, to be instantiated (see Q.f.procedure.apply_simp) rather than run. Use Q.f for this procedure as a module.
Equations
Instances For
@[simp]: applying Q.f to the parameters proc f uses (A, B) is Module.proc (Q.f.procedure.instantiate …) — the procedure with its holes filled by the callees they were made from, each written as it was in the body (with the arguments in place of the module parameters) and turned into a Procedure by Module.Proc.procedure.
Instantiating the holes of Q.h.procedure with a tuple holeArgs of procedures: the body of proc h as written, with each hole call replaced by the matching holeArgs.lookup (HoleIndex.zero being the first hole the body declared). True by rfl.
Deliberately not @[simp], unlike the other apply_simp lemmas: its right-hand side is the whole body written out, so letting it fire on its own would turn any goal mentioning an instantiated procedure into that body. Inlining a procedure is a step to ask for by name (simp [Q.h.procedure.apply_simp]).
Instantiating the holes of Q.f.procedure with a tuple holeArgs of procedures: the body of proc f as written, with each hole call replaced by the matching holeArgs.lookup (HoleIndex.zero being the first hole the body declared). True by rfl.
Deliberately not @[simp], unlike the other apply_simp lemmas: its right-hand side is the whole body written out, so letting it fire on its own would turn any goal mentioning an instantiated procedure into that body. Inlining a procedure is a step to ask for by name (simp [Q.f.procedure.apply_simp]).
The module declared by module Q, abstracted over its 2 parameters A, B, which it takes as one right-nested tuple: Module.Arr (T₁ ×ₘ (… ×ₘ Tₙ)) M, with M the module type it was declared with.
Applied to such a tuple it is the record of its procedures Q.f, Q.h, each applied to the parameters that procedure itself uses — which is what the @[simp] lemma Q.apply_simp says.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The body of proc h of module Q, as a procedure of its own: it calls no module parameter, so it has no holes.
A hole stands for a call whose callee is not known here — a module parameter is supplied only when the module is applied — so the body is a ProcedureWithHoles, to be instantiated (see Q.h.procedure.apply_simp) rather than run. Use Q.h for this procedure as a module.
Equations
- GaudisCrypt.InlineTest.Q.h.procedure = proc () : ℕ { skip; return 1 }
Instances For
A caller whose callee is named through modules: flattening cannot handle it (the callee is not spelled out at the call site), inlining can unfold it first.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Call sites are numbered including holes #
P.f calls its module parameter first and a concrete module second, so its body has two call
sites: number 0 is the hole, number 1 the call — and neither pass will renumber them.
Instantiating the holes of P.h.procedure with a tuple holeArgs of procedures: the body of proc h as written, with each hole call replaced by the matching holeArgs.lookup (HoleIndex.zero being the first hole the body declared). True by rfl.
Deliberately not @[simp], unlike the other apply_simp lemmas: its right-hand side is the whole body written out, so letting it fire on its own would turn any goal mentioning an instantiated procedure into that body. Inlining a procedure is a step to ask for by name (simp [P.h.procedure.apply_simp]).
proc f of module P as a module, abstracted over the module parameters it uses (A, in declaration order): Module.Arr … (Module.Proc (procsig …)).
Apply it with the @[simp] lemma P.f.apply_simp, which fills the holes of P.f.procedure with the callees the body called.
Equations
- One or more equations did not get rendered due to their size.
Instances For
@[simp]: applying P to a tuple of its single parameter A — the record of its procedures P.f, P.h, each applied to the parameters it uses.
This is the lemma that unfolds a module use: simp rewrites with it, then with the field lemmas of the module type (N.f.mk_simp) to get at the one procedure the goal is about, and then with P.f.apply_simp, P.h.apply_simp to fill that procedure's holes.
@[simp]: P.h = Module.proc P.h.procedure — true by definition, proc h using no module parameter and so having no holes to fill.
Instantiating the holes of P.f.procedure with a tuple holeArgs of procedures: the body of proc f as written, with each hole call replaced by the matching holeArgs.lookup (HoleIndex.zero being the first hole the body declared). True by rfl.
Deliberately not @[simp], unlike the other apply_simp lemmas: its right-hand side is the whole body written out, so letting it fire on its own would turn any goal mentioning an instantiated procedure into that body. Inlining a procedure is a step to ask for by name (simp [P.f.procedure.apply_simp]).
The module declared by module P, abstracted over its single parameter A, which it takes as one right-nested tuple: Module.Arr (T₁ ×ₘ (… ×ₘ Tₙ)) M, with M the module type it was declared with.
Applied to such a tuple it is the record of its procedures P.f, P.h, each applied to the parameters that procedure itself uses — which is what the @[simp] lemma P.apply_simp says.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The body of proc f of module P, as a procedure of its own: the one call it makes to a module parameter (A) is its single hole.
A hole stands for a call whose callee is not known here — a module parameter is supplied only when the module is applied — so the body is a ProcedureWithHoles, to be instantiated (see P.f.procedure.apply_simp) rather than run. Use P.f for this procedure as a module.
Equations
- One or more equations did not get rendered due to their size.
Instances For
@[simp]: applying P.f to the parameters proc f uses (A) is Module.proc (P.f.procedure.instantiate …) — the procedure with its holes filled by the callees they were made from, each written as it was in the body (with the arguments in place of the module parameters) and turned into a Procedure by Module.Proc.procedure.
proc h of module P as a module: Module.proc P.h.procedure, of type Module.Proc (procsig …). It uses no module parameter, so it is not a function — P.h.apply_simp says exactly that.
Instances For
The body of proc h of module P, as a procedure of its own: it calls no module parameter, so it has no holes.
A hole stands for a call whose callee is not known here — a module parameter is supplied only when the module is applied — so the body is a ProcedureWithHoles, to be instantiated (see P.h.procedure.apply_simp) rather than run. Use P.h for this procedure as a module.
Equations
- GaudisCrypt.InlineTest.P.h.procedure = proc () : ℕ { skip; return 0 }