Lean2Js.Agree
Runtime agreement between the reference semantics and the model of the generated JS #
Checks, on the shipped artifact itself, that the reference semantics and the model of the generated JS agree.
The guarantee comes in two layers. Here we check that eval and JsSem agree; the differential test on
Node checks that the behaviour JsSem assumes and the real JS agree. The former lives on the model, so
the gap that compiler correctness has to close as a proof is exactly here.
Lean2Js.encodeValue
sourceA constructor value is written under the key its name is carried under. The key follows the name
rather than the type, because that is all a Value carries: Compile.objOf reads it the same way, so
the compiler and this write the same object.
Equations
- Lean2Js.encodeValue (Lean2Js.Value.bool b) = Lean2Js.Js.JsValue.bool b
- Lean2Js.encodeValue (Lean2Js.Value.int53 i) = Lean2Js.Js.JsValue.num i
- Lean2Js.encodeValue (Lean2Js.Value.uint32 n) = Lean2Js.Js.JsValue.num ↑n.toNat
- Lean2Js.encodeValue (Lean2Js.Value.str s) = Lean2Js.Js.JsValue.str s
- Lean2Js.encodeValue (Lean2Js.Value.bigint i) = Lean2Js.Js.JsValue.bigint i
- Lean2Js.encodeValue (Lean2Js.Value.obj ctor fields) = Lean2Js.Js.JsValue.obj ((Lean2Js.Core.keyFor ctor, Lean2Js.Js.JsValue.str ctor) :: Lean2Js.encodeFields fields)
- Lean2Js.encodeValue (Lean2Js.Value.arr xs) = Lean2Js.Js.JsValue.arr (Lean2Js.encodeList xs)
- Lean2Js.encodeValue (Lean2Js.Value.dict entries) = Lean2Js.Js.JsValue.dict (Lean2Js.encodeFields entries)
- Lean2Js.encodeValue (Lean2Js.Value.fn name) = Lean2Js.Js.JsValue.fn name
Instances For
Used by
Lean2Js.encodeFields
sourceEquations
- Lean2Js.encodeFields [] = []
- Lean2Js.encodeFields ((k, v) :: rest) = (k, Lean2Js.encodeValue v) :: Lean2Js.encodeFields rest
Instances For
Used by
Lean2Js.encodeList
sourceEquations
- Lean2Js.encodeList [] = []
- Lean2Js.encodeList (x_1 :: rest) = Lean2Js.encodeValue x_1 :: Lean2Js.encodeList rest
Instances For
Used by
Lean2Js.encodeAt
sourceencodeValue composed with the crossing at each dictObj position of the declared type.
The declared type is what says how a value leaves the module, and it is the only thing that says it:
encodeValue takes no type, so a dictionary encodes to a Map whether or not the author declared it to
cross as a plain object. This is what a public declaration's result is read through instead.
The recursion is on sizeOf v rather than on the type, the way Value.hasTy's is: a named type's
field types come out of the program, so the Ty need not shrink. Where the value and the type do not
line up — which the entry check is what rules out — the value is encoded as it stands.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.encodeAt p elem.option (Lean2Js.Value.obj ctor fields) = Lean2Js.encodeValue (Lean2Js.Value.obj ctor fields)
- Lean2Js.encodeAt p (ok.result err) (Lean2Js.Value.obj ctor fields) = Lean2Js.encodeValue (Lean2Js.Value.obj ctor fields)
- Lean2Js.encodeAt p elem.array (Lean2Js.Value.arr xs) = Lean2Js.Js.JsValue.arr (Lean2Js.encodeListAt p xs elem)
- Lean2Js.encodeAt p elem.dict (Lean2Js.Value.dict entries) = Lean2Js.Js.JsValue.dict (Lean2Js.encodeEntriesAt p entries elem)
- Lean2Js.encodeAt p elem.dictObj (Lean2Js.Value.dict entries) = Lean2Js.Js.JsValue.obj (Lean2Js.encodeEntriesAt p entries elem)
- Lean2Js.encodeAt p x✝¹ x✝ = Lean2Js.encodeValue x✝
Instances For
Used by
Lean2Js.encodeFieldsAt
sourceEquations
Instances For
Used by
Lean2Js.encodeListAt
sourceEquations
- Lean2Js.encodeListAt p [] x✝ = []
- Lean2Js.encodeListAt p (x_2 :: rest) x✝ = Lean2Js.encodeAt p x✝ x_2 :: Lean2Js.encodeListAt p rest x✝
Instances For
Used by
Lean2Js.encodeEntriesAt
sourceEquations
- Lean2Js.encodeEntriesAt p [] x✝ = []
- Lean2Js.encodeEntriesAt p ((k, v) :: rest) x✝ = (k, Lean2Js.encodeAt p x✝ v) :: Lean2Js.encodeEntriesAt p rest x✝
Instances For
Used by
Reading a result through its declared type #
encodeAt is a well-founded recursion for the reason Value.hasTy is, so each shape is unfolded once
here rather than by simp at every use.
Lean2Js.encodeAt_bool
sourceUsed by
Lean2Js.encodeAt_int53
sourceUsed by
Lean2Js.encodeAt_uint32
sourceUsed by
Lean2Js.encodeAt_string
sourceUsed by
Lean2Js.encodeAt_bigint
sourceUsed by
Lean2Js.encodeAt_fn
sourceUsed by
Lean2Js.encodeAt_none
sourceUsed by
Lean2Js.encodeAt_some
sourceUsed by
Lean2Js.encodeAt_ok
sourceUsed by
Lean2Js.encodeAt_error
sourceUsed by
Lean2Js.encodeAt_array
sourceUsed by
Lean2Js.encodeAt_dict
sourceUsed by
Lean2Js.encodeAt_dictObj
sourceUsed by
Lean2Js.encodeAt_named
sourceUsed by
Lean2Js.encodeFieldsAt_nil
sourceUsed by
Lean2Js.encodeFieldsAt_cons
sourceUsed by
Lean2Js.encodeListAt_nil
sourceUsed by
Lean2Js.encodeListAt_cons
sourceUsed by
Lean2Js.encodeEntriesAt_nil
sourceUsed by
Lean2Js.encodeEntriesAt_cons
sourceUsed by
Reading a value through the type it was declared at #
encodeAt is encodeValue wherever no dictObj is reachable, which is every package built before one
could be declared. The lemma below is what carries those claims across unchanged: each is rewritten
through it and keeps the exact text it has, rather than gaining a hypothesis it did not have.
Lean2Js.encodeAt_eq_encodeValue
sourceWhere no type the program declares reaches a dictObj and the type reaches none, reading a value
through its declared type is reading it without one.
Used by
Lean2Js.reshapeJs
sourceWhat the three perturbing shapes name, applied to an encoded argument. Reversing an object's keys
and giving it a key no type declares are both things the .d.ts admits and encodeValue never writes.
A dictionary's keys are left where they are: they are a Map's, and no order is declared for them.
asObject leaves an encoded value alone, because it is not a perturbation of one: encodeArg reads the
argument through its declared type instead, and never routes that shape here.
Used by
Lean2Js.encodeArg
sourceThe JavaScript value a vector offers as one argument. Three of the four shapes perturb the canonical
encoding and are applied to it; asObject is a second encoding — the argument read through the type it
was declared at, which is what writes a Dict.Obj argument as the plain object a consumer would write.
Reshaping an encoded value could not do it. Whether a dictionary crosses as an object is the declared
type's to say and an encoded value no longer carries the type, so turning every Map into an object
would be refused at a Dict parameter — and the vector says the call returns.
Equations
- Lean2Js.encodeArg p Lean2Js.ArgShape.asObject x✝¹ x✝ = Lean2Js.encodeAt p x✝¹ x✝
- Lean2Js.encodeArg p x✝² x✝¹ x✝ = Lean2Js.reshapeJs x✝² (Lean2Js.encodeValue x✝)
Instances For
Used by
Lean2Js.TestVector.jsArgs
sourceThe arguments the generated code is called with: each Value written the way the vector says a
caller may write it.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.agrees
sourceWhether the result of eval and the result of the model are the same. The expected value is read
out through the declaration's return type, because that is what the entry hands back — decl_correct
says so — and at a dictionary the declared type says crosses as a plain object the two readings differ.
Two failures are compared by the thrown code.
Equations
- Lean2Js.agrees p ret (Except.ok a) (Except.ok b) = (Lean2Js.encodeAt p ret a == b)
- Lean2Js.agrees p ret (Except.error e) (Except.error code) = (e.code == code)
- Lean2Js.agrees p ret x✝¹ x✝ = false
Instances For
Used by
Lean2Js.Disagreement
sourceInstances For
Used by
Lean2Js.Disagreement.render
sourceEquations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.disagreementsIn
sourceEquations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.checkAgreement
sourceChecks that the artifact does not disagree with the reference semantics, before writing it out.
The keys the program declares are installed here, so the compiler and the encoding read one reading —
Compile.validateType is what checks that reading against every type the program declares.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
The file both checkers read #
The vector's expected value is written as the JavaScript value the entry must hand back, which is
encodeAt of what eval returned: a dictionary the declared type says crosses as a plain object is
written as one. Writing the Value on its own instead was right only for as long as no declaration
returned such a dictionary, and it was what left the walk on the way out unmeasured.
An asObject argument is written the same way and for the same reason: the check on Node reads no
types, so which dictionaries in an argument cross as plain objects has to be decided here. Every other
argument is written as the Value and encoded there, which is what keeps the two sides' readings of a
canonical argument independent enough to disagree.
Lean2Js.Js.JsValue.toJson
sourceUsed by
Lean2Js.TestVector.toJson
sourceEquations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.renderVectors
sourceEquations
- One or more equations did not get rendered due to their size.