Lean2Js.Value
The values eval returns, and the traps that line the semantics up with JS #
The values eval returns, and the traps that have to be taken to line the semantics up with JS.
Where Lean and JS split on the answer, both sides fail rather than one being bent toward the other.
Division by zero is the archetype: Lean's / 0 = 0 and JS's Infinity are both "right", so trapping is
the only way to make them agree.
Lean2Js.int53Max
sourceJS's Number.MAX_SAFE_INTEGER.
Equations
- Lean2Js.int53Max = 9007199254740991
Instances For
Used by
Lean2Js.int53Min
sourceJS's Number.MIN_SAFE_INTEGER.
Equations
- Lean2Js.int53Min = -9007199254740991
Instances For
Used by
Lean2Js.Value
sourceA value with a constructor becomes a tagged object on the JS side too. Option is not specialised to
T | null because the moment one is nested, none and some none stop being distinguishable.
Instances For
Used by
Lean2Js.instReprValue
sourceEquations
- Lean2Js.instReprValue = { reprPrec := Lean2Js.instReprValue.repr }
Used by
Lean2Js.instReprValue.repr
sourceUsed by
Lean2Js.instInhabitedValue
sourceEquations
Used by
Lean2Js.lookupFieldV
sourceA constructor value's field by name. Everything that walks a value asks for a key rather than for a position, because the field order a value carries is the declaration's and not the caller's.
Equations
- Lean2Js.lookupFieldV fields k = Option.map (fun (x : String × Lean2Js.Value) => x.snd) (List.find? (fun (x : String × Lean2Js.Value) => x.fst == k) fields)
Instances For
Used by
Lean2Js.sizeOf_lookupFieldV
sourceUsed by
Lean2Js.Err
sourceInstances For
Used by
Lean2Js.instReprErr
sourceEquations
- Lean2Js.instReprErr = { reprPrec := Lean2Js.instReprErr.repr }
Used by
Lean2Js.instReprErr.repr
sourceEquations
- One or more equations did not get rendered due to their size.
- Lean2Js.instReprErr.repr Lean2Js.Err.divByZero prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "Lean2Js.Err.divByZero")).group prec✝
- Lean2Js.instReprErr.repr Lean2Js.Err.int53Overflow prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "Lean2Js.Err.int53Overflow")).group prec✝
- Lean2Js.instReprErr.repr Lean2Js.Err.outOfFuel prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "Lean2Js.Err.outOfFuel")).group prec✝
- Lean2Js.instReprErr.repr Lean2Js.Err.indexOutOfBounds prec✝ = Repr.addAppParen (Std.Format.nest (if prec✝ ≥ 1024 then 1 else 2) (Std.Format.text "Lean2Js.Err.indexOutOfBounds")).group prec✝
Instances For
Used by
Lean2Js.instBEqErr.beq
sourceEquations
- Lean2Js.instBEqErr.beq Lean2Js.Err.divByZero Lean2Js.Err.divByZero = true
- Lean2Js.instBEqErr.beq Lean2Js.Err.int53Overflow Lean2Js.Err.int53Overflow = true
- Lean2Js.instBEqErr.beq Lean2Js.Err.outOfFuel Lean2Js.Err.outOfFuel = true
- Lean2Js.instBEqErr.beq Lean2Js.Err.indexOutOfBounds Lean2Js.Err.indexOutOfBounds = true
- Lean2Js.instBEqErr.beq Lean2Js.Err.noMatchingAlternative Lean2Js.Err.noMatchingAlternative = true
- Lean2Js.instBEqErr.beq (Lean2Js.Err.typeError a) (Lean2Js.Err.typeError b) = (a == b)
- Lean2Js.instBEqErr.beq (Lean2Js.Err.unknownVar a) (Lean2Js.Err.unknownVar b) = (a == b)
- Lean2Js.instBEqErr.beq (Lean2Js.Err.unknownFn a) (Lean2Js.Err.unknownFn b) = (a == b)
- Lean2Js.instBEqErr.beq (Lean2Js.Err.arity a) (Lean2Js.Err.arity b) = (a == b)
- Lean2Js.instBEqErr.beq x✝¹ x✝ = false
Instances For
Used by
Lean2Js.instBEqErr
sourceEquations
- Lean2Js.instBEqErr = { beq := Lean2Js.instBEqErr.beq }
Used by
Lean2Js.instInhabitedErr
sourceEquations
- Lean2Js.instInhabitedErr = { default := Lean2Js.instInhabitedErr.default }
Used by
Lean2Js.Err.code
sourceEquations
- Lean2Js.Err.divByZero.code = "divByZero"
- Lean2Js.Err.int53Overflow.code = "int53Overflow"
- Lean2Js.Err.outOfFuel.code = "outOfFuel"
- Lean2Js.Err.indexOutOfBounds.code = "indexOutOfBounds"
- Lean2Js.Err.noMatchingAlternative.code = "noMatchingAlternative"
- (Lean2Js.Err.typeError a).code = "typeError"
- (Lean2Js.Err.unknownVar a).code = "unknownVar"
- (Lean2Js.Err.unknownFn a).code = "unknownFn"
- (Lean2Js.Err.arity a).code = "arity"
Instances For
Used by
Lean2Js.Value.beq
sourceStructural equality. JS's === compares references, so the generated code calls a helper following
the same rules.
Equations
- (Lean2Js.Value.bool a).beq (Lean2Js.Value.bool b) = (a == b)
- (Lean2Js.Value.int53 a).beq (Lean2Js.Value.int53 b) = (a == b)
- (Lean2Js.Value.uint32 a).beq (Lean2Js.Value.uint32 b) = (a == b)
- (Lean2Js.Value.str a).beq (Lean2Js.Value.str b) = (a == b)
- (Lean2Js.Value.bigint a).beq (Lean2Js.Value.bigint b) = (a == b)
- (Lean2Js.Value.obj ca fa).beq (Lean2Js.Value.obj cb fb) = (ca == cb && Lean2Js.Value.beqFields fa fb)
- (Lean2Js.Value.arr xs).beq (Lean2Js.Value.arr ys) = Lean2Js.Value.beqList xs ys
- (Lean2Js.Value.dict a).beq (Lean2Js.Value.dict b) = Lean2Js.Value.beqFields a b
- (Lean2Js.Value.fn a).beq (Lean2Js.Value.fn b) = (a == b)
- x✝¹.beq x✝ = false
Instances For
Used by
Lean2Js.Value.beqFields
sourceEquations
Instances For
Used by
Lean2Js.Value.beqList
sourceEquations
- Lean2Js.Value.beqList [] [] = true
- Lean2Js.Value.beqList (a :: as) (b :: bs) = (a.beq b && Lean2Js.Value.beqList as bs)
- Lean2Js.Value.beqList x✝¹ x✝ = false
Instances For
Used by
Lean2Js.instBEqValue
sourceEquations
- Lean2Js.instBEqValue = { beq := Lean2Js.Value.beq }
Used by
Lean2Js.Value.beq_def
sourceWhere a proof about matching a pattern literal starts: matchPat compares with ==, and what
reduces on a literal is Value.beq.
Used by
Value.beq is structural equality, and the two halves of saying so are what lets a claim about
== on an author's own type be settled by comparing encodings.
Lean2Js.Value.beq_refl
sourceUsed by
Lean2Js.Value.beqFields_refl
sourceUsed by
Lean2Js.Value.beqList_refl
sourceUsed by
Lean2Js.Value.eq_of_beq
sourceUsed by
Lean2Js.Value.eq_of_beqFields
sourceUsed by
Lean2Js.Value.eq_of_beqList
sourceUsed by
Lean2Js.keysDistinct
sourceA JS Map cannot hold one key twice, so a dictionary that does has no value on the other side of the
boundary and is rejected there.
Equations
- Lean2Js.keysDistinct [] = true
- Lean2Js.keysDistinct (k :: rest) = (!rest.contains k && Lean2Js.keysDistinct rest)
Instances For
Used by
Lean2Js.entrySet
sourceWhat a Map filled from these entries holds, said on the side of the model's values. It mirrors
Js.Runtime.mapSetAll across encodeValue, which is what the entry check needs when a dictionary
reached it as a plain object: the object's entries are set into a Map one at a time, and this is the
list that Map is left holding.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.entrySetAll
sourceEquations
- Lean2Js.entrySetAll x✝ [] = x✝
- Lean2Js.entrySetAll x✝ ((k, v) :: rest) = Lean2Js.entrySetAll (Lean2Js.entrySet x✝ k v) rest
Instances For
Used by
Lean2Js.Value.hasTy
sourceChecks that a value matches its declared type. This is what pins the public API boundary down by type.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.Value.hasTy p (Lean2Js.Value.bool b) Lean2Js.Core.Ty.bool = true
- Lean2Js.Value.hasTy p (Lean2Js.Value.int53 i) Lean2Js.Core.Ty.int53 = (decide (Lean2Js.int53Min ≤ i) && decide (i ≤ Lean2Js.int53Max))
- Lean2Js.Value.hasTy p (Lean2Js.Value.uint32 n) Lean2Js.Core.Ty.uint32 = true
- Lean2Js.Value.hasTy p (Lean2Js.Value.str s) Lean2Js.Core.Ty.string = true
- Lean2Js.Value.hasTy p (Lean2Js.Value.bigint i) Lean2Js.Core.Ty.bigint = true
- Lean2Js.Value.hasTy p (Lean2Js.Value.obj "none" fields) elem.option = fields.isEmpty
- Lean2Js.Value.hasTy p (Lean2Js.Value.obj "some" fields) elem.option = Lean2Js.Value.hasFieldTys p fields [("value", elem)]
- Lean2Js.Value.hasTy p (Lean2Js.Value.obj ctor fields) elem.option = false
- Lean2Js.Value.hasTy p (Lean2Js.Value.obj "ok" fields) (ok.result err) = Lean2Js.Value.hasFieldTys p fields [("value", ok)]
- Lean2Js.Value.hasTy p (Lean2Js.Value.obj "error" fields) (ok.result err) = Lean2Js.Value.hasFieldTys p fields [("error", err)]
- Lean2Js.Value.hasTy p (Lean2Js.Value.obj ctor fields) (ok.result err) = false
- Lean2Js.Value.hasTy p (Lean2Js.Value.arr xs) elem.array = Lean2Js.Value.hasElemTy p xs elem
- Lean2Js.Value.hasTy p (Lean2Js.Value.dict entries) elem.dict = (Lean2Js.keysDistinct (List.map (fun (x : String × Lean2Js.Value) => x.fst) entries) && Lean2Js.Value.hasEntryTys p entries elem)
- Lean2Js.Value.hasTy p x✝¹ x✝ = false
Instances For
Used by
Lean2Js.Value.hasFieldTys
sourceEquations
- Lean2Js.Value.hasFieldTys p [] [] = true
- Lean2Js.Value.hasFieldTys p ((key, value) :: rest) ((name, ty) :: tys) = (key == name && Lean2Js.Value.hasTy p value ty && Lean2Js.Value.hasFieldTys p rest tys)
- Lean2Js.Value.hasFieldTys p x✝¹ x✝ = false
Instances For
Used by
Lean2Js.Value.hasElemTy
sourceEquations
- Lean2Js.Value.hasElemTy p [] x✝ = true
- Lean2Js.Value.hasElemTy p (x_2 :: rest) x✝ = (Lean2Js.Value.hasTy p x_2 x✝ && Lean2Js.Value.hasElemTy p rest x✝)
Instances For
Used by
Lean2Js.Value.hasEntryTys
sourceEquations
- Lean2Js.Value.hasEntryTys p [] x✝ = true
- Lean2Js.Value.hasEntryTys p ((fst, v) :: rest) x✝ = (Lean2Js.Value.hasTy p v x✝ && Lean2Js.Value.hasEntryTys p rest x✝)
Instances For
Used by
Reading the entry check #
The check a public function runs on its arguments is stated over Value.hasTy, which is defined by
well-founded recursion and so does not reduce on its own. One lemma per shape lets a proof about a
declaration discharge the check without unfolding the type machinery by hand.
Lean2Js.hasTy_bool
sourceUsed by
Lean2Js.hasTy_uint32
sourceUsed by
Lean2Js.hasTy_str
sourceUsed by
Lean2Js.hasTy_bigint
sourceUsed by
Lean2Js.hasTy_int53
sourceUsed by
Lean2Js.hasTy_named
sourceUsed by
Lean2Js.hasTy_none
sourceUsed by
Lean2Js.hasTy_some
sourceUsed by
Lean2Js.hasTy_ok
sourceUsed by
Lean2Js.hasTy_error
sourceUsed by
Lean2Js.hasTy_array
sourceUsed by
Lean2Js.hasTy_dict
sourceUsed by
Lean2Js.hasTy_dictObj
sourceA dictionary declared to cross as a plain object is the same value as one that crosses as a Map:
the constructor moves the boundary's shape, not the model's.
Used by
Lean2Js.hasTy_dictObj_eq_dict
sourceThe two spellings of a dictionary ask a value for exactly the same thing. This is what lets one operation read a receiver at either of them: what the constructor decides is the shape the boundary writes, and inside the module there is one predicate, not two.