Lean2Js.Decl
Correctness at the boundary a caller crosses: one public function #
Turns the fragment's expression-level correctness into a claim about one public function. The bridge is built at the boundary a caller actually crosses: the entry check the generated code runs on its arguments, the environment that check hands the body, and the fuel the model spends getting there.
The entry check #
Value.hasTy is what evalCall requires of an argument; Js.checkTy is what the generated function
runs on the encoded one. They are separate definitions over separate value types, so nothing but a proof
holds them together.
Lean2Js.Decl.errNeOk
sourceUsed by
The environment a descriptor is read under #
tyDescIn walks under a stack of the declared types it is inside; the entry check walks under an
environment of what those types bound. StackAgrees is the two lined up: the k-th binder of the
environment is what expanding the k-th name on the stack produces, from that point outwards.
Lean2Js.Decl.envFor
sourceWhat a descriptor adds to the environment when the walk enters it: a binder if it is one, nothing otherwise.
Equations
- Lean2Js.Decl.envFor (Lean2Js.Js.TyDesc.mu key alts) env = (key, alts) :: env
- Lean2Js.Decl.envFor d env = env
Instances For
Used by
Lean2Js.Decl.StackAgrees
sourceEquations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Decl.StackAgrees.nil
sourceUsed by
Lean2Js.Decl.StackAgrees.drop
sourceUsed by
Lean2Js.Decl.StackAgrees.cons
sourceUsed by
Lean2Js.Decl.tyDesc_bool_inv
sourceUsed by
Lean2Js.Decl.tyDesc_int53_inv
sourceUsed by
Lean2Js.Decl.tyDesc_uint32_inv
sourceUsed by
Lean2Js.Decl.tyDesc_string_inv
sourceUsed by
Lean2Js.Decl.tyDesc_bigint_inv
sourceUsed by
Lean2Js.Decl.tyDesc_var_inv
sourceUsed by
Lean2Js.Decl.tyDesc_fn_inv
sourceUsed by
Lean2Js.Decl.tyDesc_option_inv
sourceUsed by
Lean2Js.Decl.tyDesc_array_inv
sourceUsed by
Lean2Js.Decl.tyDesc_dictObj_inv
sourceUsed by
Lean2Js.Decl.tyDesc_dict_inv
sourceUsed by
Lean2Js.Decl.tyDesc_result_inv
sourceUsed by
Lean2Js.Decl.tyDesc_named_inv
sourceA declared type expands one of three ways: to a ref where the name has come round again at the
same arguments, to a mu where the type can reach itself, and to a ctors where it cannot. The last
two differ only in what the walk is left standing under, which is what envFor says.
Used by
Lean2Js.Decl.checkTy_envFor
sourceA ctors and the mu that binds it are checked the same way, under environments that differ by
that binder.
Used by
Lean2Js.Decl.normTy_envFor
sourceUsed by
Reading the shape check #
Js.checkTy is well-founded too, so it needs the same one-lemma-per-shape treatment Value.hasTy got.
Lean2Js.Decl.checkTy_bool
sourceUsed by
Lean2Js.Decl.checkTy_int53
sourceUsed by
Lean2Js.Decl.checkTy_uint32
sourceUsed by
Lean2Js.Decl.checkTy_string
sourceUsed by
Lean2Js.Decl.checkTy_bigint
sourceUsed by
Lean2Js.Decl.checkTy_array
sourceUsed by
Lean2Js.Decl.checkTy_dict
sourceUsed by
Lean2Js.Decl.checkTy_dictObj_dict
sourceUsed by
Lean2Js.Decl.checkTy_dictObj_obj
sourceUsed by
Lean2Js.Decl.checkTy_none
sourceUsed by
Lean2Js.Decl.checkTy_some
sourceUsed by
Lean2Js.Decl.checkTy_ok
sourceUsed by
Lean2Js.Decl.checkTy_error
sourceUsed by
Lean2Js.Decl.checkTy_ctors
sourceUsed by
Lean2Js.Decl.checkList_nil
sourceUsed by
Lean2Js.Decl.checkList_cons
sourceUsed by
Lean2Js.Decl.checkEntries_nil
sourceUsed by
Lean2Js.Decl.checkEntries_cons
sourceUsed by
Finding a constructor's descriptor #
Value.hasTy looks the constructor up in the declaration; the generated check looks it up in the
descriptor list the compiler built from that same declaration.
Lean2Js.Decl.tyDescAlts_find
sourceUsed by
The entry check agrees #
If a value satisfies the type its declaration promised, its encoding passes the shape check the
generated function runs at the boundary. This is the positive direction only: a value that fails
Value.hasTy is left to the run-time agreement check.
Lean2Js.Decl.TypesNamesOk
sourceA declared type names its constructors apart from each other, every constructor names its fields
apart from each other and from the key the type is told apart by, and that key is the one the
constructor's name is carried under — the descriptor reads the type's, the encoding reads the name's,
and the entry check is where the two meet. Compile.validateType checks all four, and compileProgram
runs it over every declared type.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.Decl.hasFieldTys_singleton_inv
sourceUsed by
Lean2Js.Decl.named_unfolds
sourceHowever a declared type's descriptor was reached — written out, bound as a mu, or named by a ref
back to a binder — what the walk does next is read the constructors of one ctors node, under the
environment that node stands in. This is that node, and what it is read under.
What the node's field names have to be is carried as an implication rather than as a hypothesis: the
.d.ts direction needs the node and not the names.
Used by
Lean2Js.Decl.checkTy_encodeValue
sourceUsed by
Lean2Js.Decl.checkFields_encodeFields
sourceUsed by
Lean2Js.Decl.checkList_encodeList
sourceUsed by
Lean2Js.Decl.checkEntries_encodeFields
sourceUsed by
Normalisation leaves the canonical shape alone #
encodeValue already writes tag first, the declared fields in declared order, and nothing else, so the
entry check's normalisation has nothing to rebuild on what the reference semantics produced.
Lean2Js.Decl.normTy_encodeValue
sourceUsed by
Lean2Js.Decl.normFields_encodeFields
sourceUsed by
Lean2Js.Decl.normList_encodeList
sourceUsed by
Lean2Js.Decl.normEntries_encodeFields
sourceUsed by
The walk out reads the same value through its declared type #
outTy parts from normTy at one node and encodeAt parts from encodeValue at the same one, so
the two meet: what a declaration's entry hands back is the value the reference semantics produced,
read through the type the declaration was declared to return.
encodeValue v on the left is what the body built, which is what decl_correct says, and the walk is
what the entry runs over it. Where the return type reaches no dictObj, Js.outTy_eq_normTy makes
this normTy_encodeValue again and the entry emits no walk at all.
Lean2Js.Decl.outTy_encodeValue
sourceUsed by
Lean2Js.Decl.outFields_encodeFieldsAt
sourceUsed by
Lean2Js.Decl.outList_encodeListAt
sourceUsed by
Lean2Js.Decl.outEntries_encodeEntriesAt
sourceUsed by
The entry check refuses #
The other direction. What matters at the boundary is not that a bad Value fails the check — it is that
everything the check accepts is the encoding of a value the reference semantics accepts too, which is
what turns a refusal on one side into a refusal on the other.
The claim is stated about JS values rather than about Values because encodeValue is not injective:
an Int53 and a UInt32 holding the same number both encode to .num, so nothing on the generated
side could tell them apart. Over Values the direction is false; over what actually crosses the
boundary it holds.
Lean2Js.Decl.checkTy_bool_inv
sourceUsed by
Lean2Js.Decl.checkTy_int53_inv
sourceUsed by
Lean2Js.Decl.checkTy_uint32_inv
sourceUsed by
Lean2Js.Decl.checkTy_string_inv
sourceUsed by
Lean2Js.Decl.checkTy_bigint_inv
sourceUsed by
Lean2Js.Decl.checkTy_array_inv
sourceUsed by
Lean2Js.Decl.checkTy_dict_inv
sourceUsed by
Lean2Js.Decl.checkTy_dictObj_inv
sourceA dictionary declared to cross as a plain object is met as either shape: the object a consumer
writes, or the Map another declaration of the same package handed back.
Used by
Lean2Js.Decl.checkTy_option_shape
sourceUsed by
Lean2Js.Decl.checkTy_result_shape
sourceUsed by
Lean2Js.Decl.checkTy_ctors_shape
sourceUsed by
Lean2Js.Decl.checkTy_option_fields
sourceUsed by
Lean2Js.Decl.checkTy_result_fields
sourceUsed by
Lean2Js.Decl.checkTy_ctors_fields
sourceUsed by
Lean2Js.Decl.checkFields_singleton_inv
sourceUsed by
Lean2Js.Decl.dictKeysDistinct_obj
sourceUsed by
Lean2Js.Decl.dictKeysDistinct_arr
sourceUsed by
Lean2Js.Decl.dictKeysDistinct_dict
sourceUsed by
Lean2Js.Decl.dictKeysDistinctFields_cons
sourceUsed by
Lean2Js.Decl.dictKeysDistinctList_cons
sourceUsed by
Lean2Js.Decl.dictKeysDistinct_lookupField
sourceUsed by
Lean2Js.Decl.keysDistinct_of_js
sourceUsed by
Lean2Js.Decl.entrySetAll_nodup
sourceUsed by
Lean2Js.Decl.entrySetAll_mem
sourceUsed by
Lean2Js.Decl.encodeFields_entrySet
sourceUsed by
Lean2Js.Decl.encodeFields_entrySetAll
sourceUsed by
Lean2Js.Decl.encodeFields_keys
sourceUsed by
Lean2Js.Decl.keysDistinct_to_js
sourceUsed by
Lean2Js.Decl.mapSetAll_encodeFields
sourceA dictionary read out of an object and back into a Map is the dictionary it was: the keys a value
carries are distinct, so nothing collapses on the way.
Used by
The entry check reads back what the walk out wrote #
A call through a function value goes to the entry, which hands its result back through the declared
type. What the caller is holding is then encodeAt, not encodeValue, so the check it runs on the way
back in has to accept it and rebuild the Map the module works in. These are checkTy_encodeValue and
normTy_encodeValue with encodeAt on the left, and they part from them at the one node the two
encodings part at.
Lean2Js.Decl.checkTy_encodeAt
sourceUsed by
Lean2Js.Decl.checkFields_encodeFieldsAt
sourceUsed by
Lean2Js.Decl.checkList_encodeListAt
sourceUsed by
Lean2Js.Decl.checkEntries_encodeEntriesAt
sourceUsed by
Normalisation leaves the canonical shape alone #
encodeValue already writes tag first, the declared fields in declared order, and nothing else, so the
entry check's normalisation has nothing to rebuild on what the reference semantics produced.
Lean2Js.Decl.normTy_encodeAt
sourceUsed by
Lean2Js.Decl.normFields_encodeFieldsAt
sourceUsed by
Lean2Js.Decl.normList_encodeListAt
sourceUsed by
Lean2Js.Decl.normEntries_encodeEntriesAt
sourceUsed by
Lean2Js.Decl.tyDescAlts_find_inv
sourceThe mirror of tyDescAlts_find: a constructor the generated check found in the descriptor list is
one the declaration has.
Used by
Lean2Js.Decl.checkTy_sound
sourceEverything the generated entry check lets through normalises to the encoding of a value of the
declared type. The recursion is on the JS value, not on the type: unfolding a .named substitutes its
arguments into the field types, which can grow.
Used by
Lean2Js.Decl.checkFields_sound
sourceUsed by
Lean2Js.Decl.checkList_sound
sourceUsed by
Lean2Js.Decl.checkEntries_sound
sourceUsed by
The entry environment #
A public function's body runs under two layers: the checked parameters the entry left on top, and the raw
__p0, __p1, … the check read them from. Value.hasTy knows nothing about either, so the two have to
be lined up by hand. The reserved prefix is what keeps the layers apart.
Lean2Js.Decl.repr_inj
sourceUsed by
Lean2Js.Decl.rawParam_reserved
sourceUsed by
Lean2Js.Decl.rawParam_inj
sourceUsed by
Lean2Js.Decl.validateIdent_unreserved
sourceUsed by
Lean2Js.Decl.ne_rawParam
sourceUsed by
Lean2Js.Decl.RawBound
sourceWhich raw name each argument is reachable under. Stated as a lookup rather than as a shape so that the checked parameters the entry keeps stacking on top do not disturb it.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Decl.RawBound jenv x✝ [] = True
Instances For
Used by
Lean2Js.Decl.RawBound.cons_unreserved
sourceUsed by
Lean2Js.Decl.RawBound.cons_raw
sourceUsed by
Lean2Js.Decl.rawBound_bindAll
sourceUsed by
Lean2Js.Decl.Unreserved
sourceEquations
- Lean2Js.Decl.Unreserved [] = True
- Lean2Js.Decl.Unreserved (param :: ps) = (Lean2Js.isReserved param.name = false ∧ Lean2Js.Decl.Unreserved ps)
Instances For
Used by
Lean2Js.Decl.DistinctNames
sourceEquations
- Lean2Js.Decl.DistinctNames [] = True
- Lean2Js.Decl.DistinctNames (param :: ps) = ((List.map (fun (x : Lean2Js.Core.Param) => x.name) ps).contains param.name = false ∧ Lean2Js.Decl.DistinctNames ps)
Instances For
Used by
Lean2Js.Decl.NoFnParams
sourceNo parameter is function-typed, which is what Decl.isPublic decides. The entry emits no check for
one, so it is the line the refusing direction stops at.
Equations
- Lean2Js.Decl.NoFnParams [] = True
- Lean2Js.Decl.NoFnParams (param :: ps) = (param.ty.isFn = false ∧ Lean2Js.Decl.NoFnParams ps)
Instances For
Used by
Lean2Js.Decl.checkedBindings
sourceWhat the entry check leaves on top of the environment, newest first: the last parameter is checked last, so it ends up in front.
Equations
- Lean2Js.Decl.checkedBindings (param :: ps) (a :: as) = Lean2Js.Decl.checkedBindings ps as ++ [(param.name, Lean2Js.encodeValue a)]
- Lean2Js.Decl.checkedBindings x✝¹ x✝ = []
Instances For
Used by
Lean2Js.Decl.eval_ident
sourceUsed by
The descriptors the entry check reads #
The entry check reads a constructor's fields by name; encodeValue writes them in declared order. A
proof about the entry has to know the two are the same reading, which is Js.descOk, and for a
descriptor the compiler rendered it comes from the program having been validated.
Lean2Js.Decl.namesOk_of_nodup
sourceUsed by
Lean2Js.Decl.descOk_tyDesc
sourceUsed by
Lean2Js.Decl.descNoDictObj_tyDesc
sourceWhere the program declares no dictionary that crosses as a plain object and a type reaches none,
the descriptor the entry is compiled against reaches none either. This is what carries the author's
reading — "nothing here uses Dict.Obj" — over to the reading the compiler consults when it decides
whether an entry needs a walk out at all.
Used by
Lean2Js.Decl.retWalk_id_of_descNoDictObj
sourceAn entry whose return descriptor reaches no dictObj emits no walk out, so Compile.retWalk is
the identity and the function written out is the one it was before a dictionary could cross the boundary
as a plain object. The descriptor is that declaration's own return type expanded, so this is per
declaration: one declaration of a program may hand a dictionary across as an object while its neighbour
emits no walk at all.
Used by
Lean2Js.Decl.retWalk_id_of_retNoDictObj
sourceThe same, read off the return type as written, which takes the whole program: Ty.noDictObj
stops at a declared type's name, and such a type may carry a Dict.Obj field, so the expansion reaches
one where the return type does not. That is what hp rules out, and
retWalk_id_of_descNoDictObj is the reading that asks for neither.
Used by
Lean2Js.Decl.retWalk_id_of_noDictObj
sourceNo entry of a program that declares no dictObj anywhere emits a walk out, which is every
declaration of it at once.
Used by
Lean2Js.Decl.encodeAt_eq_encodeValue_of_desc
sourceWhere the descriptor the entry read reaches no dictionary crossing as a plain object, reading a value out through its declared type is reading it without one, so the entry emits no walk and hands back what the body built. This is what keeps every claim a package makes today where it is.
Used by
Lean2Js.Decl.eval_check
sourceUsed by
Lean2Js.Decl.eval_check_fail
sourceUsed by
Lean2Js.Decl.eval_out
sourceThe walk out runs no check: what the body handed back already has the declared type.
Used by
Lean2Js.Decl.eval_out_err
sourceAnd where the body threw, the walk never runs.
Used by
Lean2Js.Decl.evalStmts_const
sourceUsed by
Lean2Js.Decl.evalStmts_const_fail
sourceUsed by
Lean2Js.Decl.ArgsDecode
sourceWhat the entry check hands the body: each JS argument, put in the canonical shape its declared type
names, is the encoding of the corresponding Value. Key order and keys the type does not name are what
the normalisation absorbs, which is why this is weaker than jargs = args.map encodeValue.
A function-typed parameter is the one the entry hands through unchecked, so the only argument it decodes
is the encoding itself. Decl.isPublic rules that case out at the boundary; it is reachable only from a
call inside the program.
- cons : Compile.tyDesc p (Compile.tyDescBudget p param.ty) param.ty = Except.ok d → Js.checkTy [] ja d = true → Js.normTy [] ja d = encodeValue a → ArgsDecode p ps jas as → ArgsDecode p (param :: ps) (ja :: jas) (a :: as)
- fn : param.ty.isFn = true → ja = encodeValue a → ArgsDecode p ps jas as → ArgsDecode p (param :: ps) (ja :: jas) (a :: as)
Instances For
Used by
Lean2Js.Decl.ArgsDecode.length
sourceUsed by
Lean2Js.Decl.ArgsDecode.length_jargs
sourceUsed by
Lean2Js.Decl.tyDesc_isFn
sourceA type the entry check has a descriptor for is not a function type: that is the one case tyDesc
refuses, and it is what tells the two ArgsDecode constructors apart.
Used by
Lean2Js.Decl.evalStmts_paramChecks
sourceUsed by
Lean2Js.Decl.argsDecode_encodeValue
sourceThe canonical spelling is one of the spellings the entry accepts: an argument already in the shape its declared type names passes the check, and the normalisation leaves it where it is. This is what carries the general statement back to the call a declaration makes from inside the program.
Used by
Lean2Js.Decl.evalStmts_paramChecks_sound
sourceWalking the same entry, the other way. At each parameter the check either throws or hands back a
Value the argument is the encoding of, so reaching the body at all means every argument decoded.
Used by
Lean2Js.Decl.envCovers_bindParams
sourceUsed by
Lean2Js.Decl.checkedBindings_find_none
sourceUsed by
Lean2Js.Decl.jsEnvBinds_checkedBindings
sourceThe entry check stacks the parameters newest-first, the opposite of bindParams. Distinct parameter
names are what make the two agree anyway: only one binding can answer a lookup.
Used by
Lean2Js.Decl.bindParams_scrutFree
sourceUsed by
Lean2Js.Decl.bindParams_unreserved
sourceEvery name the entry binds is a parameter name, and those went through validateIdent.
Used by
Lean2Js.Decl.checkedBindings_fresh
sourceBeyond the parameters the entry binds, the generated environment holds only the raw arguments, whose names carry the reserved prefix. So an unreserved name the generated code can read is one the reference environment binds too — which is what a call needs, since it reads its callee out of the environment.
Used by
Lean2Js.Decl.bindAll_rawParams_reserved
sourceThe raw arguments the generated function is handed are bound to reserved names only.
Used by
Lean2Js.Decl.rawParam_notBody
sourceUsed by
Lean2Js.Decl.bindAll_rawParams_notBody
sourceThe raw arguments are bound outside the body prefix as well as inside the reserved one, which is what keeps a call the compiler redirected to a body from being shadowed by one of them.
Used by
Lean2Js.Decl.checkedBindings_notBody
sourceNothing the entry check binds carries the body prefix: every name it binds is a parameter name, and
those went through validateIdent.
Used by
Lean2Js.Decl.jsEnvAgrees_checkedBindings
sourceUsed by
The arguments the entry hands the body #
The entry check binds every parameter under its declared name and then calls the body with those names.
Walking that call needs one lookup per parameter, which is what ParamBound lines up.
Lean2Js.Decl.ParamBound
sourceEquations
- One or more equations did not get rendered due to their size.
- Lean2Js.Decl.ParamBound jenv [] [] = True
- Lean2Js.Decl.ParamBound jenv x✝¹ x✝ = False
Instances For
Used by
Lean2Js.Decl.name_of_lookup_bindParams
sourceUsed by
Lean2Js.Decl.paramBound_of_binds
sourceUsed by
Lean2Js.Decl.evalList_paramIdents
sourceUsed by
Lean2Js.Decl.bindAll_paramNames
sourceThe body function runs its declaration under exactly the environment the reference semantics does.
bindAll binds the parameters in declared order, which is the order bindParams binds them in, so the
generated environment is the encoding of the reference one and nothing more.
Used by
Lean2Js.Decl.jsEnvAgrees_bindParams
sourceUsed by
The body as statements #
compileBody opens the lets lined up at the head of a function into const statements instead of
nesting arrows, so the fragment's expression-level result has to be walked back along that list.
Lean2Js.Decl.EventuallyStmts
sourceEquations
Instances For
Used by
Lean2Js.Decl.evalStmts_ret
sourceUsed by
Lean2Js.Decl.compileBody_finish
sourceUsed by
Lean2Js.Decl.compileBody_correct
sourceUsed by
The body throws #
The mirror of the three above. What travels is the thrown code, so a let whose value throws does not
need its body compiled to anything in particular — only to exist, which is what compileBody_shape
says.
Lean2Js.Decl.EventuallyStmtsErr
sourceEquations
- Lean2Js.Decl.EventuallyStmtsErr m jenv stmts code = ∃ (g : Nat), ∀ (g' : Nat), g ≤ g' → Lean2Js.Js.evalStmts m g' jenv stmts = Except.error code
Instances For
Used by
Lean2Js.Decl.compileFinish_shape
sourceUsed by
Lean2Js.Decl.compileFinish_type
sourceThe type compileFinish returns is the one compileExpr gave the expression it wrapped.
Used by
Lean2Js.Decl.compileBody_type
sourceThe type compileBody gives an expression is the one compileExpr gives it. The leading lets it
opens into statements are the ones compileExpr would have put in an arrow, and both check the same
things in the same order. Only the let is worth reading; every other shape goes straight to
compileFinish, which is compileExpr with the value wrapped in a return.
Used by
Lean2Js.Decl.compileBody_shape
sourceUsed by
Lean2Js.Decl.compileBody_finish_traps
sourceUsed by
Lean2Js.Decl.compileBody_traps
sourceUsed by
One public function #
The pieces meet here. compileProgram compiles a declaration against the whole program and
callFunction runs the result; evalCall checks the arguments against the declaration and runs the
body. What is left is to read both apart and line them up.
Lean2Js.Decl.rawParams_length
sourceUsed by
Lean2Js.Decl.unreserved_of_validated
sourceUsed by
Lean2Js.Decl.distinctNames_of_validated
sourceUsed by
Lean2Js.Decl.paramsTyped_of_all
sourceUsed by
Lean2Js.Decl.all_of_paramsTyped
sourceUsed by
Lean2Js.Decl.evalCall_body
sourceUsed by
Lean2Js.Decl.evalCall_inv
sourceUsed by
The type declarations the arm chain reads #
Correct.SignatureOk is what the match case of the fragment assumes about the program's types.
compileProgram checks it before it compiles anything, so a module the compiler produced carries it.
Lean2Js.Decl.forM_ok
sourceUsed by
Lean2Js.Decl.nodup_of_validateDistinct
sourceUsed by
Lean2Js.Decl.keyFor_of_keyDeclared
sourceThe key a constructor's name is carried under is the one its type declares, which is what
Compile.keyDeclared refuses a program for not saying.
Used by
Lean2Js.Decl.validateType_ctors
sourceUsed by
Lean2Js.Decl.validateType_ctorNames
sourceUsed by
Lean2Js.Decl.ctorsAt_names
sourceUsed by
Lean2Js.Decl.typesNamesOk_of_compileProgram
sourceThe same reading of a validated program, in the form Compile.tyDesc walks: findType? and the
constructors it expands, rather than Compile.signature.
Used by
Lean2Js.Decl.signatureOk_of_compileProgram
sourceUsed by
Lean2Js.Decl.compileDecl_shape
sourceUsed by
Lean2Js.Decl.compileDecls_find
sourceThe two functions a declaration compiles to, found under the two names it takes. Both lookups are one theorem because the walk that skips a declaration's entry has to skip its body in the same step.
Used by
Lean2Js.Decl.compileDecls_mem
sourceUsed by
Lean2Js.Decl.programTyped_of_compileProgram
sourceEvery declaration of a program the compiler accepted compiles, under the context its parameters give, at the type it is declared to return. This is what a proof that reaches a call needs about the callee.
Used by
Lean2Js.Decl.compileProgram_find
sourceUsed by
The two levels, one induction #
A call runs the callee's body at one less fuel than the call itself, and the callee is a declaration, so the expression-level statement and the declaration-level one have to be proved together. Both are stated at one amount of fuel and the induction below hands each the other at the fuel it needs.
Lean2Js.Decl.argsDecode_of_compileProgram
sourceEvery declaration a compiled program has accepts the canonical spelling of its arguments: the one
encodeValue writes. This is the hypothesis a caller who has not reordered anything discharges.
Used by
Lean2Js.Decl.decl_agrees_body
sourceThe body function at one fuel, from the expression-level statement at every fuel up to it. This is where the compiled expression actually runs: the arguments arrive already encoded, under their declared names, and nothing is checked on the way in.
Used by
Lean2Js.Decl.decl_traps_body
sourceThe same on the other side.
Used by
Lean2Js.Decl.hasTy_ret_of_body
sourceThe value a declaration's body returns has the type the declaration was declared at. The entry reads its result back out through that type, so this is what the walk out is given.
Used by
Lean2Js.Decl.decl_agrees_jargs
sourceThe declaration-level statement at one fuel, at every spelling of the arguments the entry check
accepts. The entry checks its arguments, binds them under their declared names, hands them to the body
and reads the result back out through the declared return type, so this is decl_agrees_body with the
check the body did not run in front of it and the walk out behind it.
Used by
Lean2Js.Decl.decl_traps_jargs
sourceThe same on the other side.
Used by
Lean2Js.Decl.decl_agrees_at
sourceWhat the mutual induction needs for a call through a function value, which goes to the entry.
Used by
Lean2Js.Decl.decl_body_agrees_at
sourceAnd for a call whose callee the compiler read off the program, which goes to the body.
Used by
Lean2Js.Decl.decl_traps_at
sourceThe same on the other side.
Used by
Lean2Js.Decl.decl_body_traps_at
sourceAnd the body on the other side.
Used by
Lean2Js.Decl.find?_of_mem_nodup
sourceDistinct names make membership and lookup the same thing.
Used by
Lean2Js.Decl.moduleHasDecls_of_compileProgram
sourceEvery declaration of a compiled program has a function of its own name in the module.
Used by
Lean2Js.Decl.levels
sourceThe two directions at every fuel up to a bound. The step lemmas take the level below, and the declaration-level statements at that level come from the expression-level ones, so one induction settles both. The bound is what a body of nested lets needs: each let the entry opens costs one fuel.
Used by
Lean2Js.Decl.fragment_correct_in
sourceIf the reference semantics returns a value, the generated code returns the same value.
Used by
Lean2Js.Decl.fragment_correct
sourceThe shape the manifest quotes: the generated environment is exactly the encoded one.
The environment must bind no reserved name. Two things need it: match gives its scrutinee one, and a
call reads its callee out of the environment, so a binding the generated code cannot have would send the
two sides to different declarations. Every name a program can bind went through validateIdent, which
rejects the prefix, so an environment a compiled declaration builds satisfies it.
Used by
Lean2Js.Decl.fragment_traps_in
sourceIf the reference semantics refuses, the generated code refuses with the same thrown code, for the
failures Correct.Mirrorable names.
Used by
One public function #
What a caller of an exported function gets: for any JS arguments the entry check accepts, if the reference semantics returns a value then the generated module's function returns the same value, at every large enough amount of the model's fuel. The run-time agreement check's "the vectors we tried agreed" replaced by "any arguments at all", for every declaration the program has.
ArgsDecode is the spelling the claim is at, and it is the whole set the entry admits: key order and
keys the declared type does not name are absorbed by the normalisation, so {currency, amount} and
{amount, currency} are both covered, and decl_refuses says everything else throws.
The value is read through the type the declaration was declared to return, which is encodeValue v
wherever that type reaches no dictionary crossing as a plain object — encodeAt_eq_encodeValue_of_desc
and Agree.encodeAt_eq_encodeValue are the two readings of that, and every claim a package makes today
is stated through one of them.
Lean2Js.Decl.decl_correct
sourceUsed by
Lean2Js.Decl.decl_traps
sourceThe companion to decl_correct on the other side of the reference semantics. For arguments the
entry accepts, if eval throws then the generated module's function throws the same code.
The failures this carries are the ones Correct.Mirrorable names: every one but outOfFuel, which is
the reference side's alone.
Used by
Lean2Js.Decl.decl_traps_at_cost
sourceThe same claim with no fuel disclaimer. Cost.progOk and the fuel bound are decided from the program
alone, once, by the emitter -- so what could not be discharged from the result is now discharged from the
input, and outOfFuel is simply not among the answers eval can give.
Used by
The entry refuses #
The mirror of decl_correct. The entry check never looks at the body, so this direction does not ask
for InFragment. What it does ask for is paramsCheckable — a function-typed parameter is handed
straight through, because JS offers no way to check a function's signature at run time. Every exported
declaration satisfies it, and so does an internal one whose parameters have a shape: what the entry
refuses does not depend on whether the entry is exported.
Lean2Js.Decl.EvalAccepts
sourceThe arguments the reference semantics lets into the body: a decoding of the JS arguments whose length and types are the ones the declaration asked for.
Equations
- Lean2Js.Decl.EvalAccepts p d jargs = ∃ (args : List Lean2Js.Value), Lean2Js.Decl.ArgsDecode p d.params jargs args ∧ d.params.length = args.length ∧ Lean2Js.ParamsTyped p d.params args
Instances For
Used by
Lean2Js.Decl.noFnParams_of_checkable
sourceUsed by
Lean2Js.Decl.decl_refuses
sourceWhat a caller of an exported function cannot get past. If no decoding of the JS arguments is one the reference semantics would accept — the wrong number of them, or one whose shape breaks the declared type — the generated module's function throws instead of running the body.
dictKeysDistinctList is the assumption the model needs and the runtime supplies: the check is handed a
Map, which cannot hold one key twice, where this model holds a dictionary as an association list.
The fuel is not existential the way decl_correct's is. The check is one call of checkTy, a Bool
function whose recursion the model does not pay for, so two is enough however deep the type.
Used by
Lean2Js.Decl.decl_refuses_call
sourceThe same at the fuel the shipped artifact runs at.