|
| 1 | +/- |
| 2 | + Copyright Strata Contributors |
| 3 | +
|
| 4 | + SPDX-License-Identifier: Apache-2.0 OR MIT |
| 5 | +-/ |
| 6 | +module |
| 7 | + |
| 8 | +import all Strata.DL.Lambda.Denote.LExprAnnotated |
| 9 | +import all Strata.DL.Lambda.Semantics |
| 10 | +import all Strata.DL.Lambda.TypeFactoryWF |
| 11 | +import all Strata.DL.Lambda.FactoryWF |
| 12 | + |
| 13 | +/-! |
| 14 | +## Typing Assumptions |
| 15 | +
|
| 16 | +Collects all well-formedness and typing assumptions used by the denotational |
| 17 | +semantics proofs. Semantic (denotation-level) assumptions live in |
| 18 | +`LExprSemanticsConsistent`. |
| 19 | +
|
| 20 | +### Expression-level predicates (TODO: prove satisfied after `LExpr.resolve`) |
| 21 | +- `fvars_annotated_by` — free variable annotations match a type map |
| 22 | +- `OpsConsistent` — operator type annotations are valid factory instantiations |
| 23 | +
|
| 24 | +### Factory assumptions (TODO: prove satisfied after `Function.typeCheck`) |
| 25 | +- `Factory.WellTyped` / `Factory.EvalWellTyped` — bodies and evaluators preserve typing |
| 26 | +- `Factory.ConstrWellFormed` — constructor functions match the type factory |
| 27 | +- `Factory.BodyOpsConsistent` / `Factory.EvalOpsConsistent` — bodies and evaluators preserve `OpsConsistent` |
| 28 | +- `Factory.BodyAnnotated` / `Factory.EvalAnnotated` — bodies and evaluators preserve annotations |
| 29 | +
|
| 30 | +### Environment assumptions (TODO: prove satisfied by `Program.typeCheck`) |
| 31 | +- `Env.Typed` — environment values are well-typed |
| 32 | +
|
| 33 | +### Bundled assumptions |
| 34 | +- `Env.StepWF` — environment well-formedness for step preservation |
| 35 | +- `Factory.StepWF` — factory well-formedness for step preservation |
| 36 | +- `Factory.WF` — factory and type-factory well-formedness |
| 37 | +-/ |
| 38 | + |
| 39 | +namespace Lambda |
| 40 | + |
| 41 | +variable {T : LExprParams} [DecidableEq T.IDMeta] |
| 42 | + |
| 43 | +/-! ### Expression-level predicates -/ |
| 44 | + |
| 45 | +/-- Every fvar in `e` whose name is in `tyMap` is annotated with the |
| 46 | +corresponding type. -/ |
| 47 | +def fvars_annotated_by [DecidableEq T.IDMeta] |
| 48 | + (tyMap : Map T.Identifier LMonoTy) : LExpr T.mono → Prop |
| 49 | + | .fvar _ name (some ty) => |
| 50 | + ∀ ty', Map.find? tyMap name = some ty' → ty = ty' |
| 51 | + | .fvar _ _ none => False |
| 52 | + | .const _ _ => True |
| 53 | + | .bvar _ _ => True |
| 54 | + | .op _ _ _ => True |
| 55 | + | .app _ fn arg => fvars_annotated_by tyMap fn ∧ fvars_annotated_by tyMap arg |
| 56 | + | .abs _ _ _ body => fvars_annotated_by tyMap body |
| 57 | + | .ite _ c t e => fvars_annotated_by tyMap c ∧ fvars_annotated_by tyMap t ∧ fvars_annotated_by tyMap e |
| 58 | + | .eq _ e1 e2 => fvars_annotated_by tyMap e1 ∧ fvars_annotated_by tyMap e2 |
| 59 | + | .quant _ _ _ _ tr body => fvars_annotated_by tyMap tr ∧ fvars_annotated_by tyMap body |
| 60 | + |
| 61 | +/-- Every `.op` node in `e` whose name is in the factory has a type annotation |
| 62 | +that is a valid instantiation of the function's generic type (via `opTypeSubst`). |
| 63 | +This is checked at every `.op` node directly, not just at complete calls. -/ |
| 64 | +def OpsConsistent (F : @Factory T) : LExpr T.mono → Prop := fun e => |
| 65 | + match e with |
| 66 | + | .op _ name ty => |
| 67 | + match F[name.name]? with |
| 68 | + | some fn => |
| 69 | + match LFunc.opTypeSubst fn e with |
| 70 | + | some tySubst => |
| 71 | + match ty with |
| 72 | + | some ty_op => |
| 73 | + ty_op = (LMonoTy.mkArrow' fn.output (fn.inputs.map Prod.snd)).subst tySubst |
| 74 | + | none => False |
| 75 | + | none => False |
| 76 | + | none => True |
| 77 | + | .app _ fn arg => OpsConsistent F fn ∧ OpsConsistent F arg |
| 78 | + | .abs _ _ _ body => OpsConsistent F body |
| 79 | + | .ite _ c t f => OpsConsistent F c ∧ OpsConsistent F t ∧ OpsConsistent F f |
| 80 | + | .eq _ e1 e2 => OpsConsistent F e1 ∧ OpsConsistent F e2 |
| 81 | + | .quant _ _ _ _ tr body => OpsConsistent F tr ∧ OpsConsistent F body |
| 82 | + | _ => True |
| 83 | + |
| 84 | +/-! ### Factory assumptions -/ |
| 85 | + |
| 86 | +/-- A factory is well-typed when every function body type-checks at the |
| 87 | +function's declared output type. -/ |
| 88 | +def Factory.WellTyped [DecidableEq T.IDMeta] (F : @Factory T) : Prop := |
| 89 | + ∀ (f : String), (hf : f ∈ F) → ∀ body, (F[f]).body = some body → |
| 90 | + LExpr.HasTypeA [] body (F[f]).output ∧ |
| 91 | + fvars_annotated_by (F[f]).inputs body |
| 92 | + |
| 93 | +/-- A factory's concrete evaluators preserve well-typedness: if `ceval` returns |
| 94 | +a result and the arguments are well-typed at the instantiated input types, |
| 95 | +then the result is well-typed at the instantiated output type. -/ |
| 96 | +def Factory.EvalWellTyped [DecidableEq T.IDMeta] (F : @Factory T) : Prop := |
| 97 | + ∀ (f : String), (hf : f ∈ F) → ∀ ceval, (F[f]).concreteEval = some ceval → |
| 98 | + ∀ (md : T.Metadata) (args : List (LExpr T.mono)) (result : LExpr T.mono) (tySubst : Subst), |
| 99 | + ceval md args = some result → |
| 100 | + List.Forall₂ (LExpr.HasTypeA []) args ((F[f]).inputs.map Prod.snd |>.map (LMonoTy.subst tySubst)) → |
| 101 | + LExpr.HasTypeA [] result (LMonoTy.subst tySubst (F[f]).output) |
| 102 | + |
| 103 | +/-- `isConstr` faithfulness: `f.isConstr = true` implies `f` was generated |
| 104 | +from a constructor in the TypeFactory. -/ |
| 105 | +def Factory.ConstrWellFormed (F : @Factory T) (tf : @TypeFactory T.IDMeta) : Prop := |
| 106 | + ∀ (f : LFunc T), |
| 107 | + f ∈ F.toArray → |
| 108 | + f.isConstr = true → |
| 109 | + ∃ (d : LDatatype T.IDMeta) (_ : d ∈ tf.allDatatypes) |
| 110 | + (c : LConstr T.IDMeta) (_ : c ∈ d.constrs), |
| 111 | + f = constrFunc c d |
| 112 | + |
| 113 | +/-- Every function body in the factory satisfies `OpsConsistent` after type |
| 114 | +instantiation via `applySubst`. -/ |
| 115 | +def Factory.BodyOpsConsistent (F : @Factory T) : Prop := |
| 116 | + ∀ (f : String), (hf : f ∈ F) → ∀ body S, (F[f]).body = some body → |
| 117 | + OpsConsistent F (body.applySubst S) |
| 118 | + |
| 119 | +/-- Every concrete evaluator in the factory returns results that satisfy |
| 120 | +`OpsConsistent`. -/ |
| 121 | +def Factory.EvalOpsConsistent (F : @Factory T) : Prop := |
| 122 | + ∀ (f : String), (hf : f ∈ F) → ∀ ceval md args result, (F[f]).concreteEval = some ceval → |
| 123 | + .some result = ceval md args → OpsConsistent F result |
| 124 | + |
| 125 | +/-- Every function body in the factory, after type instantiation, has fvar |
| 126 | +annotations consistent with `tyMap`. -/ |
| 127 | +def Factory.BodyAnnotated [DecidableEq T.IDMeta] (F : @Factory T) |
| 128 | + (tyMap : Map T.Identifier LMonoTy) : Prop := |
| 129 | + ∀ (f : String), (hf : f ∈ F) → ∀ body S, (F[f]).body = some body → |
| 130 | + fvars_annotated_by tyMap (body.applySubst S) |
| 131 | + |
| 132 | +/-- Every concrete evaluator in the factory returns results with fvar |
| 133 | +annotations consistent with `tyMap`. -/ |
| 134 | +def Factory.EvalAnnotated [DecidableEq T.IDMeta] (F : @Factory T) |
| 135 | + (tyMap : Map T.Identifier LMonoTy) : Prop := |
| 136 | + ∀ (f : String), (hf : f ∈ F) → ∀ ceval md args result, (F[f]).concreteEval = some ceval → |
| 137 | + .some result = ceval md args → fvars_annotated_by tyMap result |
| 138 | + |
| 139 | +/-! ### Environment assumptions -/ |
| 140 | + |
| 141 | +/-- Environment values are well-typed: there is a type map `tyMap` such that |
| 142 | +every env value is well-typed at its corresponding type, and every env key |
| 143 | +has a type in the map. -/ |
| 144 | +structure Env.Typed [DecidableEq T.IDMeta] (env : Env T) where |
| 145 | + /-- The type map assigning types to environment keys. -/ |
| 146 | + tyMap : Map T.Identifier LMonoTy |
| 147 | + /-- Every env value is well-typed at the type given by `tyMap`. -/ |
| 148 | + wt : ∀ (x : T.Identifier) (e : LExpr T.mono) (ty : LMonoTy), |
| 149 | + env x = some e → Map.find? tyMap x = some ty → LExpr.HasTypeA [] e ty |
| 150 | + /-- Every env key has a type in `tyMap`. -/ |
| 151 | + cover : ∀ (x : T.Identifier) (e : LExpr T.mono), |
| 152 | + env x = some e → ∃ ty, Map.find? tyMap x = some ty |
| 153 | + |
| 154 | +/-! ### Bundled assumptions -/ |
| 155 | + |
| 156 | +/-- Bundled well-formedness assumptions on the environment for step preservation. |
| 157 | +- `typed` : `Env.Typed env` — environment maps identifiers to well-typed expressions |
| 158 | +- `lc` : environment values are locally closed (`lcAt 0`) |
| 159 | +- `ops` : environment values satisfy `OpsConsistent F` |
| 160 | +- `annot` : environment values satisfy `fvars_annotated_by typed.tyMap` |
| 161 | +-/ |
| 162 | +structure Env.StepWF (F : @Factory T) (env : Env T) where |
| 163 | + typed : Env.Typed env |
| 164 | + lc : ∀ (x : T.Identifier) (e : LExpr T.mono), env x = some e → LExpr.lcAt 0 e = true |
| 165 | + ops : ∀ (x : T.Identifier) (e : LExpr T.mono), env x = some e → OpsConsistent F e |
| 166 | + annot : ∀ (x : T.Identifier) (e : LExpr T.mono), env x = some e → |
| 167 | + fvars_annotated_by typed.tyMap e |
| 168 | + |
| 169 | +/-- Bundled well-formedness assumptions on the factory for step preservation. |
| 170 | +- `wt` : `Factory.WellTyped F` — factory function bodies are well-typed |
| 171 | +- `evalWt` : `Factory.EvalWellTyped F` — concrete evaluators return well-typed results |
| 172 | +- `bodyOps` : `Factory.BodyOpsConsistent F` — factory bodies satisfy `OpsConsistent` after substitution |
| 173 | +- `evalOps` : `Factory.EvalOpsConsistent F` — concrete evaluators return `OpsConsistent` results |
| 174 | +- `bodyAnnot` : `Factory.BodyAnnotated F tyMap` — factory bodies satisfy `fvars_annotated_by` after substitution |
| 175 | +- `evalAnnot` : `Factory.EvalAnnotated F tyMap` — concrete evaluators return annotated results |
| 176 | +-/ |
| 177 | +structure Factory.StepWF (F : @Factory T) (tyMap : Map T.Identifier LMonoTy) where |
| 178 | + wt : Factory.WellTyped F |
| 179 | + evalWt : Factory.EvalWellTyped F |
| 180 | + bodyOps : Factory.BodyOpsConsistent F |
| 181 | + evalOps : Factory.EvalOpsConsistent F |
| 182 | + bodyAnnot : Factory.BodyAnnotated F tyMap |
| 183 | + evalAnnot : Factory.EvalAnnotated F tyMap |
| 184 | + |
| 185 | +/-- Bundled well-formedness assumptions on the factory and type factory. |
| 186 | +- `factoryWF` : `FactoryWF F` — factory is well-formed |
| 187 | +- `constrWF` : `Factory.ConstrWellFormed F tf` — constructors are well-formed w.r.t. type factory |
| 188 | +- `tfWF` : `TypeFactoryWF tf` — type factory is well-formed |
| 189 | +-/ |
| 190 | +structure Factory.WF (F : @Factory T) (tf : @TypeFactory T.IDMeta) where |
| 191 | + factoryWF : FactoryWF F |
| 192 | + constrWF : Factory.ConstrWellFormed F tf |
| 193 | + tfWF : TypeFactoryWF tf |
| 194 | + |
| 195 | +end Lambda |
0 commit comments