src/ez/start.bend

ezx@1.10.0.0 · 109 lines · 0 definitions

1# ez/start: what `ez check`, `ez build` and `ez run` start, decided from the
2# ledger they read and the words they were given. Each starts one bend on
3# the entry the ledger names, or refuses and starts nothing when there is no
4# ez.toml or it does not parse, as cargo refuses a directory with no
5# Cargo.toml. The interpreter (`ez/cmd.bend`) reads ez.toml, puts the
6# project's BEND_LIB in front of the line (`Env.line`), runs it and exits;
7# that it does so faithfully is EZ-TRUST-2.
8import Base
9import ezx@1.10.0.0/src/ledger/manifest.bend as M
10import ezx@1.10.0.0/src/share/args.bend as Args
11
12# which of the three commands is asking, with what it was told: where a
13# build goes, and every word of the line for a run
14type Ask is Data:
15  Check{}
16  Build{out: String}
17  Run{as: List<&2, String>}
18
19# what a command does: refuse with a reason, having started nothing, or start
20# bend with this line
21type Start is Data:
22  Refused{why: String}
23  Starts{line: List<&2, String>}
24
25# what each command is for, in the words a refusal says it with
26def does(ask: Ask) -> String:
27  match ask:
28    case Check{}:
29      "ez check checks a project's entry"
30    case Build{_out}:
31      "ez build builds a project's entry"
32    case Run{_as}:
33      "ez run runs a project's entry"
34
35# why a directory with no ez.toml is refused
36def none(ask: Ask) -> String:
37  "ez: no ez.toml here; " ++ does(ask) ++ ", and ez init makes one"
38
39# the entry file a ledger names, or "main.bend" when it names none
40def entry.or(+file: String) -> String:
41  Bool.pick(String, String.is_empty(file), "main.bend", file)
42
43# the entry file of a ledger that parsed
44def entry(ledger: M.Manifest) -> String:
45  M.Manifest{_n, e, _b, _h, _pa, _pv, _ds, _ts} = ledger
46  entry.or(e)
47
48# the name a ledger that parsed gives the package
49def named(ledger: M.Manifest) -> String:
50  M.Manifest{n, _e, _b, _h, _pa, _pv, _ds, _ts} = ledger
51  n
52
53# where a build lands when nothing said: `bin/<package name>.out`. The name
54# and not the entry file, because the entry is where a program starts and the
55# name is what it is called: a package named `bolt` with its entry at
56# `bolt/main.bend` builds `bin/bolt.out` and not `bin/main.out`.
57def build.named(+name: String) -> String:
58  "bin/" ++ name ++ ".out"
59
60# where a build lands: what was asked for, or the default
61def build.out(+at: String, +name: String) -> String:
62  Bool.pick(String, String.is_empty(at), build.named(name), at)
63
64# the line each command starts bend with, over a ledger that parsed: the
65# entry checked into `.ez/check.js` and never run, built to a native binary,
66# or run with every word after `run` (EZ-TOOL-9)
67def line(ask: Ask, +ledger: M.Manifest) -> List<&2, String>:
68  match ask:
69    case Check{}:
70      ["bend", entry(ledger), "-o", ".ez/check.js"]
71    case Build{+out}:
72      ["bend", entry(ledger), "-o", build.out(out, named(ledger))]
73    case Run{as}:
74      Args.run.line(entry(ledger), as)
75
76# what a command does with the ledger it read
77def read(+ask: Ask, ledger: M.Read) -> Start:
78  match ledger:
79    case M.Bad{why}:
80      Refused{"ez: " ++ M.show(M.Bad{why})}
81    case M.Good{+m}:
82      Starts{line(ask, m)}
83
84# what a command does with ez.toml's text, None when there is none
85def start(+ask: Ask, text: Maybe<&2, String>) -> Start:
86  match text:
87    case None{}:
88      Refused{none(ask)}
89    case Some{t}:
90      read(ask, M.parse(t))
91
92# the status `ez run` exits with, given the status of the program it started
93# (EZ-OUT-1): 1 for a refusal, which started none, and the program's own
94# status otherwise, as `cargo run` exits. `ez check` and `ez build` end on
95# what bend printed instead (`ez/ends.bend`).
96def code(start: Start, program: U32) -> U32:
97  match start:
98    case Refused{_why}:
99      1
100    case Starts{_line}:
101      program
102
103# why a command refused, or "" when it started bend
104def why(start: Start) -> String:
105  match start:
106    case Refused{w}:
107      w
108    case Starts{_line}:
109      ""