src/role.bend
bolt@1.27.0.0 · 192 lines · 24 definitions
1
2
3
4
5
6
7
8
9
10
11
12import Base
13import bolt@1.27.0.0/src/paths.bend as Paths
14import bolt@1.27.0.0/src/src.bend as Src
15import bolt@1.27.0.0/src/lazy/lazy.bend as Lazy
16import bolt@1.27.0.0/src/rules/imports.bend as Imports
17import bolt@1.27.0.0/src/syntax/lex.bend as Lex
18import bolt@1.27.0.0/src/syntax/outline.bend as Outline
19import bolt@1.27.0.0/src/finding.bend as F
20
21
22type Role is Data:
23 Plain{}
24 Laws{}
25 Proof{}
26
27
28def of_path(+path: String) -> Role:
29 Bool.pick(Role, Paths.is_laws(path), Laws{}, Bool.pick(Role, Paths.is_proof(path), Proof{}, Plain{}))
30
31
32def is_laws(rr: Role) -> Bool:
33 match rr:
34 case Laws{}:
35 True{}
36 case other:
37 False{}
38
39
40def is_proof(rr: Role) -> Bool:
41 match rr:
42 case Proof{}:
43 True{}
44 case other:
45 False{}
46
47
48def is_law_file(rr: Role) -> Bool:
49 match rr:
50 case Plain{}:
51 False{}
52 case other:
53 True{}
54
55
56
57def skip(+rr: Role, run: Unit -> List<&2, F.Finding>) -> List<&2, F.Finding>:
58 Lazy.stop(List<&2, F.Finding>, is_law_file(rr), [], run)
59
60
61
62
63
64
65def reached(laws: Bool) -> Role:
66 Bool.pick(Role, laws, Laws{}, Proof{})
67
68
69
70type Fact is Data:
71 Fact{norm: String, deps: List<&2, String>, named: Role, entry: Bool}
72
73
74def fact(ss: Src.Src) -> Fact:
75 Src.Src{+path, _text, _toks, _tree, _bound, items} = ss
76 +nn = Imports.norm(path)
77 Fact{nn, Imports.targets(items, nn), of_path(path), String.eq(Paths.base(path), "main.bend")}
78
79
80
81def fact.text(+path: String, +text: String) -> Fact:
82 +nn = Imports.norm(path)
83 Fact{nn, Imports.targets(Outline.of_tokens(text, Lex.tokens(text)), nn), of_path(path),
84 String.eq(Paths.base(path), "main.bend")}
85
86
87def facts(ss: List<&2, Src.Src>) -> List<&2, Fact>:
88 match ss:
89 case Nil{}:
90 Nil{}
91 case Con{s, rest}:
92 fact(s) <> facts(rest)
93
94
95
96
97
98type Mark is Data:
99 Mark{norm: String, role: Role}
100
101
102def edges(fs: List<&2, Fact>) -> List<&2, Imports.Edge>:
103 match fs:
104 case Nil{}:
105 Nil{}
106 case Con{Fact{norm, deps, _named, _entry}, rest}:
107 Imports.Edge{norm, deps} <> edges(rest)
108
109
110def paths(fs: List<&2, Fact>) -> List<&2, String>:
111 match fs:
112 case Nil{}:
113 Nil{}
114 case Con{Fact{norm, _deps, _named, _entry}, rest}:
115 norm <> paths(rest)
116
117
118def roots(fs: List<&2, Fact>) -> List<&2, String>:
119 match fs:
120 case Nil{}:
121 Nil{}
122 case Con{Fact{norm, _deps, +named, _entry}, rest}:
123 +more = roots(rest)
124 Bool.pick(List<&2, String>, is_law_file(named), norm <> more, more)
125
126
127def lawful(fs: List<&2, Fact>) -> List<&2, String>:
128 match fs:
129 case Nil{}:
130 Nil{}
131 case Con{Fact{norm, _deps, +named, _entry}, rest}:
132 +more = lawful(rest)
133 Bool.pick(List<&2, String>, is_laws(named), norm <> more, more)
134
135
136def reach(+fs: List<&2, Fact>, +from: List<&2, String>) -> List<&2, String>:
137 Imports.walk(List.length(&2, Fact, fs), from, from, edges(fs), paths(fs))
138
139
140
141def code(fs: List<&2, Fact>, +laws: List<&2, String>) -> List<&2, String>:
142 match fs:
143 case Nil{}:
144 Nil{}
145 case Con{Fact{+norm, _deps, _named, entry}, rest}:
146 +more = code(rest, laws)
147 Bool.pick(List<&2, String>, Bool.or(entry, Bool.not(Imports.has(laws, norm))), norm <> more, more)
148
149
150def role.of(+named: Role, reach: Role) -> Role:
151 Bool.pick(Role, is_law_file(named), named, reach)
152
153
154
155def marks.of(
156 fs: List<&2, Fact>,
157 +laws: List<&2, String>,
158 +lawful: List<&2, String>,
159 +code: List<&2, String>
160) -> List<&2, Mark>:
161 match fs:
162 case Nil{}:
163 Nil{}
164 case Con{Fact{+norm, _deps, +named, _entry}, rest}:
165 +more = marks.of(rest, laws, lawful, code)
166 Bool.pick(List<&2, Mark>, Bool.and(Imports.has(laws, norm), Bool.not(Imports.has(code, norm))),
167 Mark{norm, role.of(named, reached(Imports.has(lawful, norm)))} <> more, more)
168
169
170def marks.facts(+fs: List<&2, Fact>) -> List<&2, Mark>:
171 +ls = reach(fs, roots(fs))
172 marks.of(fs, ls, reach(fs, lawful(fs)), reach(fs, code(fs, ls)))
173
174
175
176
177def marks(ss: List<&2, Src.Src>) -> List<&2, Mark>:
178 marks.facts(facts(ss))
179
180
181
182def of.norm(ms: List<&2, Mark>, +nn: String) -> Role:
183 match ms:
184 case Nil{}:
185 Plain{}
186 case Con{Mark{+norm, role}, rest}:
187 Lazy.either(Role, String.eq(norm, nn), _u => role, _v => of.norm(rest, nn))
188
189
190
191def of(ms: List<&2, Mark>, +path: String) -> Role:
192 role.of(of_path(path), of.norm(ms, Imports.norm(path)))