Decode the Elm compiler's binary cache files from elm-stuff/.
When you run elm make, the compiler writes a set of binary cache files
under elm-stuff/<compiler-version>/. These aren't documented or meant to
be read by anything other than the compiler itself, but they contain useful
information: what every module exposes, its inferred types, and its
compiled (pre-JS) representation. This library decodes those files into
plain Elm values.
Unlike other tools (like elm-syntax parser), elm-stuff only has access to your code that has been verified by the compiler, as well as all the dependencies.
You can use the Interfaces to derive Json encoders/decoders, or the Graphs to transpile to something else.
| File | Decoder | Contents |
|---|---|---|
d.dat |
decodeDetails |
What the compiler built last time, used to decide what needs recompiling. |
i.dat |
decodeInterfaces |
What every dependency module exposes. |
o.dat |
decodeGlobalGraph |
Every dependency's compiled code. |
FolderName-ModuleName.elmi |
decodeInterface |
What one locally-compiled module exposes. |
FolderName-ModuleName.elmo |
decodeLocalGraph |
One locally-compiled module's own compiled code. |
elm install Warry/elm-stuff
Each decoder takes Bytes (for example read via elm/file's
File.toBytes) and returns a Maybe of the decoded value.
import Bytes exposing (Bytes)
import ElmStuff
readDetails : Bytes -> Maybe ElmStuff.Details
readDetails bytes =
ElmStuff.decodeDetails bytesA minimal example reading a file picked from disk:
import Bytes exposing (Bytes)
import ElmStuff
import File exposing (File)
import File.Select as Select
import Task
type Msg
= PickFile
| GotFile File
| GotBytes Bytes
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
PickFile ->
( model, Select.file [] GotFile )
GotFile file ->
( model, Task.perform GotBytes (File.toBytes file) )
GotBytes bytes ->
case ElmStuff.decodeDetails bytes of
Just details ->
( { model | details = Just details }, Cmd.none )
Nothing ->
( { model | error = Just "decode failed" }, Cmd.none )See example/src/Main.elm for a complete browser-based app that lets you
pick any of the 5 file kinds and inspect the decoded result.
The top-level ElmStuff module exposes one decoder per cache file:
decodeDetails : Bytes -> Maybe Details.Details
decodeInterfaces : Bytes -> Maybe (DictAny.Dict ModuleName.Canonical Interface.DependencyInterface)
decodeGlobalGraph : Bytes -> Maybe Optimized.GlobalGraph
decodeInterface : Bytes -> Maybe Interface.Interface
decodeLocalGraph : Bytes -> Maybe Optimized.LocalGraphThe decoded types themselves (Details, Interface, GlobalGraph,
LocalGraph, and the supporting types they're built from -- canonical
types, module names, packages, decision trees, kernel chunks, and so on)
live in the ElmStuff.* modules and are also exposed, in case you need to
decode a sub-structure directly or write your own Bytes.Decode.Decoder
that composes with these:
ElmStuff.Details-- thed.datrecord and its fields.ElmStuff.Interface-- module interfaces (.elmi, andi.dat's values).ElmStuff.Optimized-- compiled-code graphs (.elmo,o.dat).ElmStuff.Canonical-- canonical AST types (annotations, unions, aliases).ElmStuff.DecisionTree-- compiled pattern-match tests.ElmStuff.Kernel-- kernel (JS) source chunks.ElmStuff.ModuleName-- module names resolved to their defining package.ElmStuff.Package-- package names and versions.ElmStuff.Binop-- infix operator associativity/precedence.ElmStuff.Region-- source-code spans.ElmStuff.Outline--elm.jsonsource directory entries as embedded inDetails.
HelpBytes is an internal module of low-level decoding helpers (fixed-size
integers, length-prefixed strings, Haskell containers-style maps, and so
on) that the rest of the library is built on. It isn't part of the public
API and its shape may change without notice.
The decoders are derived from the Haskell compiler's Binary instances
(compiler commit e20e8c8e, Elm 0.19.2). The cache files have no header,
magic number, or version byte, so decoding failure just means either the
bytes are corrupt or these decoders have drifted from whatever compiler
version produced them.
elm make src/ElmStuff.elm # type-check the library
elm-test # run the test suite