Repository navigation
feat: write a proved machine as TypeScript - #89
Merged
Merged
Conversation
The TypeScript conformance folders hold the modules accord build must write, byte for byte, written before the generator. This one fixes how a machine crosses the boundary: a readonly state type, one check of the state's fields, invariants and helper invariants for every event and observer, and events that return the next state. A machine whose invariant isn't proved inductive must be refused. Refs #82
A pub machine becomes a state type, a check of a state's fields and every invariant and helper invariant, and an exported function for each init, event and observer; the generator reuses the functions' parameter and requires checks, expressions and decision tables. Build writes it only when every obligation is proved, and refuses a module whose names would collide. The differential test runs each member against the interpreter, including states that break an invariant, which the module must reject. Refs #82
A review showed the state check and the event each read the state, so an accessor could pass the check with one value and hand the event another. The check now returns one snapshot of the fields, which is all the event reads, and its generated names end in $ so no field or parameter can collide with them. Refs #82
The state check returns a snapshot built from its single read, and events and observers run on it, so a getter can't pass the check and then give the body another value. Generated names end in $, so fields called state or where no longer collide. Enums and machines sharing an exported type name are refused. Refs #82
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 10's second slice:
accord buildwrites apub machineas a TypeScript module, once every obligation is proved and every example passes. The ports (ProviderRetry, opossum) come next.The module
The reference is
conformance/typescript/machine/out/switch.ts. It was written by hand before the generator, and the generator matches it byte for byte.export type M = { readonly field: T; … }.checkM$(where$, state$)reads the state once. It checks the object, each field's type and range, every invariant, and every helper invariant, then returns that snapshot. Failures throwTypeErrororRangeError, naming the field or the invariant.inittakes its parameters and returns a state.(state$, params…), runs only on the checked snapshot, checks its parameters andrequires, and returns the next state (for an event) without changing the one it was given.$, which no Accord name can use. A module whose exported value or type names would collide is refused.not_inductiveincluded, isn't written (refused-machine).Process
5f74f30).b383518), then the code (f3c626f):pressreturnedpresses: -4, breaking the invariant.stateorwhereproduced a module that wouldn't import.Verification
cargo fmt --all --checkandcargo clippy --workspace --all-targets --locked -- -D warningsare clean.cargo test --workspace --lockedwith the pinned solvers: 97 passed, 1 ignored. That includes:stateandwhere.score.py --self-testandmaterials.py) passes, run without a bytecode cache.Not established: no reference covers
i64fields, event parameters that are text or lists, or a decision table nested in anif.tscwasn't run; Node strips types, and the module is checked for typing only where the existing tests typecheck generated code.Risk note
Two-way door: TypeScript output is "unstable until the first release" (
docs/typescript.md), and nothing is published. Blast radius:accord buildfor programs with machines; function-only output is unchanged byte for byte. Evidence: the reference module, the differential test, and the review's attacks rerun.Refs #82