Lean2Js.Step
The small-step semantics, as an abstract machine with explicit continuations #
The small-step semantics of the subset, written as an abstract machine with explicit continuations.
Where the big-step eval only says "what it returns", this one holds the states along the way. Rules
where the question is "when is it not evaluated" — short-circuiting, evaluation order — cannot be stated
without those intermediate states.
Agreement with eval is proved in StepAgree: given enough steps, the machine answers every call the way
eval does.
Lean2Js.Frame
sourceA continuation waiting to be evaluated. andK / orK stand on their own because JS's && and ||
short-circuit; waiting on both sides with binL would always evaluate the right one.
Instances For
Used by
Lean2Js.instInhabitedFrame
sourceEquations
Used by
Lean2Js.State
sourceInstances For
Used by
Lean2Js.instInhabitedState
sourceEquations
Used by
Lean2Js.State.fail
sourceEquations
Instances For
Used by
Lean2Js.State.finish
sourceEquations
Instances For
Used by
Lean2Js.continueArgs
sourceEvaluates the argument list left to right, building the constructor or call once nothing is left.
Equations
- Lean2Js.continueArgs build done [] env k frame = build done
- Lean2Js.continueArgs build done (e :: more) env k frame = Lean2Js.State.eval env e (frame done more :: k)
Instances For
Used by
Lean2Js.continueMap
sourceWalks the elements left to right, one lambda body per element. The three combinators differ only in what they carry between elements: the results so far, the elements kept so far, or the accumulator.
Equations
- Lean2Js.continueMap binder body env done [] k = Lean2Js.State.finish (Lean2Js.Value.arr done) k
- Lean2Js.continueMap binder body env done (x :: more) k = Lean2Js.State.eval ((binder, x) :: env) body (Lean2Js.Frame.mapK binder body env done more :: k)
Instances For
Used by
Lean2Js.sortDone
sourceEquations
- Lean2Js.sortDone ps k = match Lean2Js.sortPairs ps with | Except.ok vs => Lean2Js.State.finish (Lean2Js.Value.arr vs) k | Except.error e => Lean2Js.State.fail e
Instances For
Used by
Lean2Js.continueSort
sourceThe key of each element is worked out on the way past, and the order is settled once, at the end, on the pairs the walk collected.
Equations
- Lean2Js.continueSort binder body env done [] k = Lean2Js.sortDone done k
- Lean2Js.continueSort binder body env done (x :: more) k = Lean2Js.State.eval ((binder, x) :: env) body (Lean2Js.Frame.sortK binder body env done x more :: k)
Instances For
Used by
Lean2Js.continueFilter
sourceEquations
- Lean2Js.continueFilter binder body env done [] k = Lean2Js.State.finish (Lean2Js.Value.arr done) k
- Lean2Js.continueFilter binder body env done (x :: more) k = Lean2Js.State.eval ((binder, x) :: env) body (Lean2Js.Frame.filterK binder body env done x more :: k)
Instances For
Used by
Lean2Js.continueFind
sourceEquations
- Lean2Js.continueFind binder body env [] k = Lean2Js.State.finish (Lean2Js.Value.obj "none" []) k
- Lean2Js.continueFind binder body env (x :: more) k = Lean2Js.State.eval ((binder, x) :: env) body (Lean2Js.Frame.findK binder body env x more :: k)
Instances For
Used by
Lean2Js.continueQuant
sourceEquations
- Lean2Js.continueQuant op binder body env [] k = Lean2Js.State.finish (Lean2Js.Value.bool (op == Lean2Js.Core.QuantOp.all)) k
- Lean2Js.continueQuant op binder body env (x :: more) k = Lean2Js.State.eval ((binder, x) :: env) body (Lean2Js.Frame.quantK op binder body env more :: k)
Instances For
Used by
Lean2Js.continueReduce
sourceEquations
- Lean2Js.continueReduce accName elemName body env acc [] k = Lean2Js.State.finish acc k
- Lean2Js.continueReduce accName elemName body env acc (x :: more) k = Lean2Js.State.eval ((elemName, x) :: (accName, acc) :: env) body (Lean2Js.Frame.reduceK accName elemName body env more :: k)
Instances For
Used by
The walk a fold takes #
A node is walked one declared field at a time. A field that came round is handed back to the machine as
a value to walk rather than walked here, so these two recur on the field list and on the element list
alone and the descent into the value is a transition — which is what keeps step a structural match.
Lean2Js.continueFoldFields
sourceEquations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.continueFoldElems
sourceEquations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.beginFold
sourceOpens one node of the walk: the constructor the value carries decides which fields come round.
Equations
- One or more equations did not get rendered due to their size.
- Lean2Js.beginFold p typeName tyArgs alts env v k = Lean2Js.State.fail (Lean2Js.Err.typeError (toString "fold expects a value of " ++ toString typeName))
Instances For
Used by
Lean2Js.step
sourceEquations
- One or more equations did not get rendered due to their size.
- Lean2Js.step p (Lean2Js.State.done r) = Lean2Js.State.done r
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.lit l) k) = Lean2Js.State.finish (Lean2Js.litValue l) k
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.un op x_1) k) = Lean2Js.State.eval env x_1 (Lean2Js.Frame.unK op :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.bin Lean2Js.Core.BinOp.and lhs rhs) k) = Lean2Js.State.eval env lhs (Lean2Js.Frame.andK rhs env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.bin Lean2Js.Core.BinOp.or lhs rhs) k) = Lean2Js.State.eval env lhs (Lean2Js.Frame.orK rhs env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.bin op lhs rhs) k) = Lean2Js.State.eval env lhs (Lean2Js.Frame.binL op rhs env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (c.cond t e_2) k) = Lean2Js.State.eval env c (Lean2Js.Frame.condK t e_2 env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.letE name ty val body) k) = Lean2Js.State.eval env val (Lean2Js.Frame.letK name body env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (e_2.proj field) k) = Lean2Js.State.eval env e_2 (Lean2Js.Frame.projK field :: k)
- Lean2Js.step p (Lean2Js.State.eval env (scrut.matchE alts) k) = Lean2Js.State.eval env scrut (Lean2Js.Frame.matchK alts env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (scrut.foldE typeName tyArgs result alts) k) = Lean2Js.State.eval env scrut (Lean2Js.Frame.foldScrutK typeName tyArgs alts env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.noneE elem) k) = Lean2Js.State.finish (Lean2Js.Value.obj "none" []) k
- Lean2Js.step p (Lean2Js.State.eval env e_2.someE k) = Lean2Js.State.eval env e_2 (Lean2Js.Frame.someK :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.okE err e_2) k) = Lean2Js.State.eval env e_2 (Lean2Js.Frame.okK :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.errorE ok e_2) k) = Lean2Js.State.eval env e_2 (Lean2Js.Frame.errorK :: k)
- Lean2Js.step p (Lean2Js.State.eval env (arr.index idx) k) = Lean2Js.State.eval env arr (Lean2Js.Frame.indexL idx env :: k)
- Lean2Js.step p (Lean2Js.State.eval env arr.length k) = Lean2Js.State.eval env arr (Lean2Js.Frame.lengthK :: k)
- Lean2Js.step p (Lean2Js.State.eval env (arr.mapE binder body) k) = Lean2Js.State.eval env arr (Lean2Js.Frame.mapArrK binder body env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (arr.sortByKeyE binder body) k) = Lean2Js.State.eval env arr (Lean2Js.Frame.sortArrK binder body env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (arr.filterE binder body) k) = Lean2Js.State.eval env arr (Lean2Js.Frame.filterArrK binder body env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (arr.findE binder body) k) = Lean2Js.State.eval env arr (Lean2Js.Frame.findArrK binder body env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.quantE op arr binder body) k) = Lean2Js.State.eval env arr (Lean2Js.Frame.quantArrK op binder body env :: k)
- Lean2Js.step p (Lean2Js.State.eval env (arr.reduceE init accName elemName body) k) = Lean2Js.State.eval env arr (Lean2Js.Frame.reduceArrK init accName elemName body env :: k)
- Lean2Js.step p (Lean2Js.State.eval env d.dictKeys k) = Lean2Js.State.eval env d (Lean2Js.Frame.dictKeysK :: k)
- Lean2Js.step p (Lean2Js.State.eval env d.dictValues k) = Lean2Js.State.eval env d (Lean2Js.Frame.dictValuesK :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.strUn op e_2) k) = Lean2Js.State.eval env e_2 (Lean2Js.Frame.strUnK op :: k)
- Lean2Js.step p (Lean2Js.State.eval env (Lean2Js.Core.Expr.strBin op lhs rhs) k) = Lean2Js.State.eval env lhs (Lean2Js.Frame.strBinL op rhs env :: k)
- Lean2Js.step p (Lean2Js.State.eval env arr.arrayReverse k) = Lean2Js.State.eval env arr (Lean2Js.Frame.arrayReverseK :: k)
- Lean2Js.step p (Lean2Js.State.apply v []) = Lean2Js.State.done (Except.ok v)
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.unK op :: k)) = match Lean2Js.applyUn op v with | Except.ok w => Lean2Js.State.finish w k | Except.error e => Lean2Js.State.fail e
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.binL op rhs env :: k)) = Lean2Js.State.eval env rhs (Lean2Js.Frame.binR op v :: k)
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.binR op lhs :: k)) = match Lean2Js.applyBin op lhs v with | Except.ok w => Lean2Js.State.finish w k | Except.error e => Lean2Js.State.fail e
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool false) (Lean2Js.Frame.andK rhs env :: k)) = Lean2Js.State.finish (Lean2Js.Value.bool false) k
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool true) (Lean2Js.Frame.andK rhs env :: k)) = Lean2Js.State.eval env rhs (Lean2Js.Frame.boolK :: k)
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.andK rhs env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "&& expects Bool operands")
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool true) (Lean2Js.Frame.orK rhs env :: k)) = Lean2Js.State.finish (Lean2Js.Value.bool true) k
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool false) (Lean2Js.Frame.orK rhs env :: k)) = Lean2Js.State.eval env rhs (Lean2Js.Frame.boolK :: k)
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.orK rhs env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "|| expects Bool operands")
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool true) (Lean2Js.Frame.condK thenE elseE env :: k)) = Lean2Js.State.eval env thenE k
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool false) (Lean2Js.Frame.condK thenE elseE env :: k)) = Lean2Js.State.eval env elseE k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.condK thenE elseE env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "condition expects a Bool")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.letK name body env :: k)) = Lean2Js.State.eval ((name, v) :: env) body k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.projK field :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "field access expects a constructor value")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.foldScrutK typeName tyArgs alts env :: k)) = Lean2Js.beginFold p typeName tyArgs alts env v k
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool b) (Lean2Js.Frame.boolK :: k)) = Lean2Js.State.finish (Lean2Js.Value.bool b) k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.boolK :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "expected a Bool")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.someK :: k)) = Lean2Js.State.finish (Lean2Js.Value.obj "some" [("value", v)]) k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.okK :: k)) = Lean2Js.State.finish (Lean2Js.Value.obj "ok" [("value", v)]) k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.errorK :: k)) = Lean2Js.State.finish (Lean2Js.Value.obj "error" [("error", v)]) k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.indexL idx env :: k)) = Lean2Js.State.eval env idx (Lean2Js.Frame.indexR v :: k)
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.indexR arr :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "index expects an Array and an Int53")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.lengthK :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "length expects an Array, a String or a Dict")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.dictKeysK :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "keys expects a Dict")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.dictValuesK :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "values expects a Dict")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.strUnK op :: k)) = match Lean2Js.applyStrUn op v with | Except.ok w => Lean2Js.State.finish w k | Except.error e => Lean2Js.State.fail e
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.strBinL op rhs env :: k)) = Lean2Js.State.eval env rhs (Lean2Js.Frame.strBinR op v :: k)
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.arr xs) (Lean2Js.Frame.arrayReverseK :: k)) = Lean2Js.State.finish (Lean2Js.Value.arr xs.reverse) k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.arrayReverseK :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "reverse expects an Array")
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.arr xs) (Lean2Js.Frame.mapArrK binder body env :: k)) = Lean2Js.continueMap binder body env [] xs k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.mapArrK binder body env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "map expects an Array")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.mapK binder body env done rest :: k)) = Lean2Js.continueMap binder body env (done ++ [v]) rest k
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.arr xs) (Lean2Js.Frame.sortArrK binder body env :: k)) = Lean2Js.continueSort binder body env [] xs k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.sortArrK binder body env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "sortByKey expects an Array")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.sortK binder body env done elem rest :: k)) = Lean2Js.continueSort binder body env (done ++ [(v, elem)]) rest k
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.arr xs) (Lean2Js.Frame.filterArrK binder body env :: k)) = Lean2Js.continueFilter binder body env [] xs k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.filterArrK binder body env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "filter expects an Array")
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool true) (Lean2Js.Frame.filterK binder body env done kept rest :: k)) = Lean2Js.continueFilter binder body env (done ++ [kept]) rest k
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool false) (Lean2Js.Frame.filterK binder body env done kept rest :: k)) = Lean2Js.continueFilter binder body env done rest k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.filterK binder body env done kept rest :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "filter expects a Bool predicate")
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.arr xs) (Lean2Js.Frame.findArrK binder body env :: k)) = Lean2Js.continueFind binder body env xs k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.findArrK binder body env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "find expects an Array")
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.bool false) (Lean2Js.Frame.findK binder body env candidate rest :: k)) = Lean2Js.continueFind binder body env rest k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.findK binder body env candidate rest :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "find expects a Bool predicate")
- Lean2Js.step p (Lean2Js.State.apply (Lean2Js.Value.arr xs) (Lean2Js.Frame.quantArrK op binder body env :: k)) = Lean2Js.continueQuant op binder body env xs k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.quantArrK op binder body env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError (toString op.name ++ toString " expects an Array"))
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.quantK op binder body env rest :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError (toString op.name ++ toString " expects a Bool predicate"))
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.reduceArrK init accName elemName body env :: k)) = Lean2Js.State.fail (Lean2Js.Err.typeError "reduce expects an Array")
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.reduceInitK items accName elemName body env :: k)) = Lean2Js.continueReduce accName elemName body env v items k
- Lean2Js.step p (Lean2Js.State.apply v (Lean2Js.Frame.reduceK accName elemName body env rest :: k)) = Lean2Js.continueReduce accName elemName body env v rest k
Instances For
Used by
Lean2Js.step.buildCall
sourceEquations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.step.buildCtor
sourceEquations
- One or more equations did not get rendered due to their size.
Instances For
Used by
Lean2Js.step.buildDictGet
sourceEquations
- Lean2Js.step.buildDictGet [Lean2Js.Value.dict entries, Lean2Js.Value.str key] k = Lean2Js.State.finish (Lean2Js.dictLookup entries key) k
- Lean2Js.step.buildDictGet args k = Lean2Js.State.fail (Lean2Js.Err.typeError "get expects a Dict and a String key")
Instances For
Used by
Lean2Js.step.buildDictHas
sourceEquations
- Lean2Js.step.buildDictHas [Lean2Js.Value.dict entries, Lean2Js.Value.str key] k = Lean2Js.State.finish (Lean2Js.Value.bool (entries.any fun (x : String × Lean2Js.Value) => x.fst == key)) k
- Lean2Js.step.buildDictHas args k = Lean2Js.State.fail (Lean2Js.Err.typeError "has expects a Dict and a String key")
Instances For
Used by
Lean2Js.step.buildDictSet
sourceEquations
- Lean2Js.step.buildDictSet [Lean2Js.Value.dict entries, Lean2Js.Value.str key, val] k = Lean2Js.State.finish (Lean2Js.Value.dict (Lean2Js.dictWith entries key val)) k
- Lean2Js.step.buildDictSet args k = Lean2Js.State.fail (Lean2Js.Err.typeError "set expects a Dict and a String key")
Instances For
Used by
Lean2Js.step.buildDictDelete
sourceEquations
- One or more equations did not get rendered due to their size.
- Lean2Js.step.buildDictDelete args k = Lean2Js.State.fail (Lean2Js.Err.typeError "delete expects a Dict and a String key")
Instances For
Used by
Lean2Js.step.buildArraySlice
sourceEquations
- Lean2Js.step.buildArraySlice [a, lo, hi] k = match Lean2Js.sliceArr a lo hi with | Except.ok w => Lean2Js.State.finish w k | Except.error e => Lean2Js.State.fail e
- Lean2Js.step.buildArraySlice args k = Lean2Js.State.fail (Lean2Js.Err.arity "slice")
Instances For
Used by
Lean2Js.step.buildSlice
sourceEquations
- Lean2Js.step.buildSlice [a, lo, hi] k = match Lean2Js.sliceStr a lo hi with | Except.ok w => Lean2Js.State.finish w k | Except.error e => Lean2Js.State.fail e
- Lean2Js.step.buildSlice args k = Lean2Js.State.fail (Lean2Js.Err.arity "substring")
Instances For
Used by
Lean2Js.run
sourceEquations
- Lean2Js.run p 0 x✝ = Except.error Lean2Js.Err.outOfFuel
- Lean2Js.run p n.succ (Lean2Js.State.done r) = r
- Lean2Js.run p f.succ x✝ = Lean2Js.run p f (Lean2Js.step p x✝)
Instances For
Used by
Lean2Js.stepCall
sourceCalls one exported function on the abstract machine, letting it take at most bound steps. The type
check at the entry is the same as evalCall's.
Equations
- One or more equations did not get rendered due to their size.