~/bend-docscommunity

src/doctor/world.bend source

src/doctor/world.bend on the hub · documented module

# doctor/world: what `ez doctor` reads. The C compiler `$CC` names ("" when# it is unset) and `$BEND_LIB` ("" when it is unset), which the planner# (doctor/plan.bend) turns into the compiler and the library it reports on;# the ledger's text and the lock's text, None when there is no file; and the# answers to the questions the planner asked. There is no field for the# clock or the rest of the environment, because the planner reads neither.## A question is a program asked for its version, the names of the packages# under BEND_LIB, the project's sources, or a package's tree under BEND_LIB.# The sources are every `.bend` file git tracks, with its text, which is the# lock's own listing (`W.Listing`), read the way `ez lock` reads it. So doctor# judges the import lines `ez lock` judges. A tree is asked about with the# lock's own question (`W.Ask`) and answered only from BEND_LIB: the manifest# there and the text of each file it names, or that there is none. Doctor# never asks the network, so this is all it can know of a package. A name the# lock records is asked about as the file bend reads its hash from,# `$BEND_LIB/names/<nv>`, as it is.import Baseimport ../lock/world.bend as Wimport ../ledger/manifest.bend as M# a question the planner askstype Ask is Data:  Probe{name: String}   # the program asked for its version  Lib{dir: String}      # the names under the library directory, as `ls` prints them  Sources{}             # every `.bend` file git tracks, with its text  Tree{ask: W.Ask}      # the lock's question about a package, put to BEND_LIB  Name{nv: String}      # the file BEND_LIB/names/<nv>, as it is# the answer to one: what a program printed, and whether it ran; or the# sources as the lock lists them; or a package's tree as BEND_LIB holds it,# or that BEND_LIB holds nonetype Answer is Data:  Printed{ok: Bool, text: String}                  # Probe, Lib  Listed{listing: W.Listing}                       # Sources  Laid{manifest: String, srcs: List<&2, String>}   # Tree, there  Away{}                                           # Tree, not there  Held{got: Maybe<&2, String>}                     # Name: the file's text, None when it is not there# one question, answeredtype Reply is Data:  Reply{ask: Ask, answer: Answer}# everything `ez doctor` readstype World is Data:  World{cc: String, lib: String, ledger: Maybe<&2, String>, lock: Maybe<&2, String>,    replies: List<&2, Reply>}# the ledger's path, which is fixeddef toml() -> String:  "ez.toml"# the lock's path, which is fixeddef lockfile() -> String:  "ez.lock.toml"# what `$CC` holds, "" when it is unsetdef cc(world: World) -> String:  World{c, _lib, _ledger, _lock, _replies} = world  c# what `$BEND_LIB` holds, "" when it is unsetdef lib(world: World) -> String:  World{_cc, l, _ledger, _lock, _replies} = world  l# the ledger's text, None when there is no ez.tomldef ledger(world: World) -> Maybe<&2, String>:  World{_cc, _lib, l, _lock, _replies} = world  l# the lock's text, None when there is no ez.lock.tomldef lock(world: World) -> Maybe<&2, String>:  World{_cc, _lib, _ledger, l, _replies} = world  l# every question answered so fardef replies(world: World) -> List<&2, Reply>:  World{_cc, _lib, _ledger, _lock, rs} = world  rs# the ledger as read: what the file says, or, with no file, a read that did# not parse and says why, as every command that reads a ledger says itdef read.of(got: Maybe<&2, String>) -> M.Read:  match got:    case None{}:      M.Bad{"none here; ez init makes one"}    case Some{text}:      M.parse(text)# the ledger, readdef read(world: World) -> M.Read:  read.of(ledger(world))# a question as a key. A program's name and a directory hold no newline, so# the fields are kept apart by one.def key(ask: Ask) -> String:  match ask:    case Probe{name}:      "probe\n" ++ name    case Lib{dir}:      "lib\n" ++ dir    case Sources{}:      "sources"    case Tree{ask}:      "tree\n" ++ W.ask.hash(ask)    case Name{nv}:      "name\n" ++ nv# an answer looked up, or none yettype Heard is Data:  Heard{answer: Answer}  Open{}# this answer when it is the question's, otherwise the rest's. The rest# arrives as a thunk, so the first hit ends the scan.def look.step(hit: Bool, answer: Answer, rest: Unit -> Heard) -> Heard:  match hit:    case True{}:      Heard{answer}    case False{}:      rest(Unit{})# the first answer given to a questiondef look(rs: List<&2, Reply>, +want: String) -> Heard:  match rs:    case []:      Open{}    case Reply{ask, answer} <> t:      look.step(String.eq(key(ask), want), answer, _u => look(t, want))# the answer to a question, or none yetdef heard(rs: List<&2, Reply>, ask: Ask) -> Heard:  look(rs, key(ask))# the answer the sources question has had on a World, or none yetdef sources(world: World) -> Heard:  heard(replies(world), Sources{})