Documentation

GaudisCrypt.Language.Programs

Instances For

    A sequence of procedure signatures, describing the holes of a program.

    A cons list, head first: .cons X (.cons Y .empty) is the context of a body that calls X and then Y. Everything indexed by it agrees on that order — HoleIndex.zero is the head, HoleSigs.Instantiation is the tuple with the head's procedure first, toList, toModuleTypeRepTuple and toModuleExpr all put the head first, and the uses (…) display lists it first. So "hole 0" means one thing throughout: the first hole the body declares.

    Instances For
      Instances For
        def GaudisCrypt.HoleIndex.toFin {holes : HoleSigs} {sig : ProcedureSignature} :
        HoleIndex holes sig → Fin holes.length
        Equations
        Instances For
          theorem GaudisCrypt.HoleIndex.toFin_inj {holes : HoleSigs} {sig : ProcedureSignature} (i1 i2 : HoleIndex holes sig) :
          i1.toFin = i2.toFin → i1 = i2
          @[reducible, inline]
          abbrev GaudisCrypt.Var (a : Type u_1) :
          Type (max u_1 1)
          Equations
          Instances For
            @[reducible, inline]
            abbrev GaudisCrypt.Expr (a : Type u_1) :
            Type (max u_1 1)
            Equations
            Instances For

              Syntactic program (with arbitrary Lean terms as expressions). Every statement runs on a ProgramState: the globals, and the locals of the running procedure (its parameters among them).

              Instances For

                A procedure: its body and return value run on a ProgramState, and on a call the arguments are written into the local slots named parameterNames (with the types sig.params), see ProcedureWithHoles.initLocals.

                Instances For
                  @[reducible, inline]

                  The signature of a procedure-with-holes as a term — sig is otherwise only reachable as an implicit argument of the type, which makes it awkward to name in generated code.

                  Equations
                  Instances For

                    The locals a call of p with arguments args starts with: the arguments in the parameter slots, everything else at VariableAssignment.init.

                    Equations
                    Instances For
                      @[match_pattern]
                      Equations
                      Instances For

                        The setter that puts the local variables with a name in S (of every type) back to VariableAssignment.init, the value every local has when a procedure starts, and leaves every other one alone; the value written, (), is ignored. The values put back form a VariableAssignment, which lives in Type 1, so they cannot themselves be the value of an assign; assign (resetSetter S) ⟨fun _ => ()⟩ is the reset, reset_vars S; in the surface syntax. Flattening (Logic/Inline.lean) emits it for the frame of the callee it inlines.

                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For
                          Equations
                          Instances For

                            The procedures filling the holes holes, as a tuple: right-nested, with HoleIndex.zero — the last-appended hole — as the first component, the same order as HoleSigs.Instantiation.toList and HoleSigs.Instantiation.toModuleExpr. No holes at all is PUnit, so what one writes is

                            p.instantiate (c₁, c₂, c₃)   -- three holes, in the order the body declares them
                            p.instantiate c              -- one hole: the tuple is its element
                            

                            and nothing else is needed to build one: Prod.mk is the only constructor involved. Reading a hole out is HoleSigs.Instantiation.lookup.

                            A one-hole instantiation is the procedure itself rather than a pair with PUnit, which is what keeps the written form free of a trailing ⟨⟩. The cost is that knowing Instantiation (cons sig holes) is a pair takes two constructors, not one — so every function that recurses on holes and takes an instantiation apart splits on both levels, cons _ .empty beside cons _ (.cons ..). Do that split in the function itself; routing it through head/tail helpers instead makes them stuck at a variable holes, and then nothing about them is rfl any more.

                            It is a tuple rather than the function ∀ {sig}, HoleIndex holes sig → Procedure sig it used to be so that instantiations can be written and read as ordinary Lean tuples — the function form made every instantiation an implicit-lambda chain, in the source and in every goal that mentioned one. The price is that holes has to be concrete for the type to reduce: an instantiation at a symbolic holes can still be taken as a hypothesis and looked up (lookup recurses on the index, which refines holes), but not built or taken apart without recursing on holes in step.

                            The universe is written out only because PUnit would otherwise take one of its own: nothing in the .empty branch constrains its level, so Type _ gives the definition a universe parameter that no argument determines, and a use site inside an inductive (ModuleExpression.ReductionStep) then has nothing to infer it from.

                            Equations
                            Instances For

                              The procedure filling hole idx. Recursion is on the index, which refines holes as it goes — which is what lets this work at a holes that is still a variable.

                              Equations
                              Instances For
                                @[simp]

                                The only hole of a one-hole instantiation is the instantiation itself.

                                @[simp]
                                theorem GaudisCrypt.HoleSigs.Instantiation.lookup_zero_cons {holes : HoleSigs} {sig sig' : ProcedureSignature} (inst : (cons sig (cons sig' holes)).Instantiation) :
                                inst.lookup HoleIndex.zero = inst.1

                                The first hole of a tuple of two or more: its first component.

                                @[simp]
                                theorem GaudisCrypt.HoleSigs.Instantiation.lookup_succ {holes : HoleSigs} {sig sig' sig'' : ProcedureSignature} (inst : (cons sig (cons sig' holes)).Instantiation) (i : HoleIndex (cons sig' holes) sig'') :
                                inst.lookup i.succ = inst.2.lookup i

                                Any later hole: the rest of the tuple.

                                Convert an instantiation into a plain list of procedures (tagged by their signature), in the same right-nested order as the tuple itself and as HoleSigs.Instantiation.toModuleExpr.

                                The head of the list corresponds to the most-recently appended hole signature.

                                Equations
                                Instances For
                                  def GaudisCrypt.StmtWithHoles.instantiate {holes : HoleSigs} (stmt : StmtWithHoles holes) (instantiation : holes.Instantiation) :

                                  Instantiate all holes in a statement using resolve, turning each .hole into a .call' of the resolved procedure. Hole-free constructors are simply re-typed.

                                  Equations
                                  Instances For
                                    def GaudisCrypt.ProcedureWithHoles.instantiate {holes : HoleSigs} {sig : ProcedureSignature} (proc : ProcedureWithHoles holes sig) (instantiation : holes.Instantiation) :
                                    Equations
                                    • One or more equations did not get rendered due to their size.
                                    Instances For

                                      A structural size measure used to justify termination of programDenotation. The auto-generated sizeOf for StmtWithHoles is trivially 0 (the inductive lives in a higher universe because its constructors quantify over a : Type), so we define our own.

                                      Equations
                                      Instances For

                                        A hole-free statement has nothing to instantiate: every constructor is re-typed as itself, and the .hole case cannot occur (HoleIndex .empty _ is empty). Recursion is on depth — the statement's own index HoleSigs.empty is not a variable, so the equation compiler cannot recurse on it structurally.

                                        @[simp]

                                        Instantiating a procedure that has no holes leaves it alone.

                                        Run proc on fresh locals (ProcedureWithHoles.initLocals); the callee's locals are discarded at the end, only the globals are kept. The state and the result live in different universes, hence hbind in place of do.

                                        Not mutual with programDenotation, whose call' case repeats this body.

                                        Equations
                                        • One or more equations did not get rendered due to their size.
                                        Instances For
                                          theorem GaudisCrypt.programDenotation_call' {sig : ProcedureSignature} (x : Setter sig.ret ProgramState) (names : List String) (hlen : names.length = sig.params.length) (hnodup : names.Nodup) (body : Stmt) (ret : Getter sig.ret ProgramState) (args : Getter sig.ParamType ProgramState) :
                                          programDenotation (StmtWithHoles.call' x names hlen hnodup body ret args) = do let argValues ← ProgramDenotation.get args let retVal ← ProgramDenotation.zoom ProgramState.globalL (procedureDenotation { parameterNames := names, parameterNames_length := hlen, parameterNames_nodup := hnodup, body := body, return_val := ret } argValues) ProgramDenotation.set x retVal

                                          The call' case of programDenotation, with the callee run folded into procedureDenotation.

                                          The procedure denotation as an explicit wrapper: initialise locals, run the body, extract (return_val, globals).

                                          Equations
                                          Instances For

                                            procedureDenotation of an instantiated procedure is procWrap of its body (generic over the holes and their instantiation).