vendor/lint.bend
bend-lint-pack@0.1.1.0 · 233 lines · 45 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14import Base
15
16
17
18type Fact is Data:
19 Fact{id: U32}
20
21type Term is Data:
22 Term{id: U32}
23
24type Node is Data:
25 Node{id: U32}
26
27type Source is Data:
28 Source{path: String, text: String, root: Bool}
29
30
31type Value is Data:
32 OptionNum{value: U32}
33 OptionFlag{value: Bool}
34 OptionText{value: String}
35
36type Option is Data:
37 Option{key: String, value: Value}
38
39type Input is Data:
40 Input{sources: List<&2, Source>, options: List<&2, Option>}
41
42
43type Scope is Data:
44 File{}
45 Program{}
46
47
48
49
50
51type Want is Data:
52 NoFacts{}
53 Want{scope: Scope, kinds: List<&2, String>, defs: List<&2, String>, names: List<&2, String>}
54
55type Span is Data:
56 Span{path: String, beg: U32, end: U32}
57
58type Severity is Data:
59 Error{}
60 Warning{}
61 Information{}
62 Hint{}
63
64
65type Applicability is Data:
66 Safe{}
67 Suggested{}
68 Dangerous{}
69
70type Edit is Data:
71 Edit{span: Span, text: String}
72
73type Fix is Data:
74 Fix{title: String, applicability: Applicability, edits: List<&2, Edit>}
75
76type Diag is Data:
77 Diag{severity: Severity, message: String, span: Maybe<&2, Span>, fixes: List<&2, Fix>}
78
79
80type Quantity is Data:
81 Erased{}
82 Once{}
83 Many{}
84
85type Use is Data:
86 Use{name: String, quantity: Quantity}
87
88
89
90
91
92
93type View is Data:
94 View{owner: String, inst: Bool, kind: String, name: String, quantity: Quantity, span: Maybe<&2, Span>, inner: Maybe<&2, Span>}
95
96
97
98type Shape is Data:
99 Shape{kind: String, name: String, span: Maybe<&2, Span>, children: List<&2, Node>}
100
101def input() -> IO(Input):
102 import "./effects.js"
103
104def report(diags: List<&2, Diag>) -> IO(Unit):
105 import "./effects.js"
106
107
108def next_fact() -> IO(Maybe<&2, Fact>):
109 import "./effects.js"
110
111
112def fold_next(~A: Type, ~step: A -> @+f: Fact -> IO(A), m: Maybe<&2, Fact>, acc: A, again: A -> IO(A)) -> IO(A):
113 match m:
114 case None{}:
115 IO.pure(A, acc)
116 case Some{f}:
117 IO.bind(A, A, step(acc, f), again)
118
119
120
121
122@unsafe
123def fold_facts(~A: Type, ~step: A -> @+f: Fact -> IO(A), acc: A) -> IO(A):
124 do IO<A>:
125 m : Maybe<&2, Fact> <- next_fact()
126 fold_next(~A, ~step, m, acc, a => fold_facts(~A, ~step, a))
127
128def view(fact: Fact) -> IO(View):
129 import "./effects.js"
130
131
132def type_of(fact: Fact) -> IO(Term):
133 import "./effects.js"
134
135
136def binder(fact: Fact) -> IO(Maybe<&2, Term>):
137 import "./effects.js"
138
139
140
141def same(fact: Fact, a: Term, b: Term) -> IO(Bool):
142 import "./effects.js"
143
144def show(fact: Fact, t: Term) -> IO(String):
145 import "./effects.js"
146
147
148def normal(fact: Fact, t: Term) -> IO(Term):
149 import "./effects.js"
150
151
152def uses(fact: Fact) -> IO(List<&2, Use>):
153 import "./effects.js"
154
155
156def text(span: Span) -> IO(String):
157 import "./effects.js"
158
159
160def body(name: String) -> IO(Maybe<&2, Node>):
161 import "./effects.js"
162
163
164def node(fact: Fact) -> IO(Node):
165 import "./effects.js"
166
167def shape(n: Node) -> IO(Shape):
168 import "./effects.js"
169
170
171def fact(n: Node) -> IO(Maybe<&2, Fact>):
172 import "./effects.js"
173
174def pick(hit: Bool, v: Value, later: Maybe<&2, Value>) -> Maybe<&2, Value>:
175 match hit:
176 case True{}:
177 Some{v}
178 case False{}:
179 later
180
181
182def find(opts: List<&2, Option>, +key: String) -> Maybe<&2, Value>:
183 match opts:
184 case Nil{}:
185 None{}
186 case Con{Option{k, v}, rest}:
187 pick(String.eq(k, key), v, find(rest, key))
188
189def option_number_or(m: Maybe<&2, Value>, default: U32) -> U32:
190 match m:
191 case Some{OptionNum{n}}:
192 n
193 case Some{OptionFlag{b}}:
194 default
195 case Some{OptionText{t}}:
196 default
197 case None{}:
198 default
199
200
201def option_number(opts: List<&2, Option>, key: String, default: U32) -> U32:
202 option_number_or(find(opts, key), default)
203
204def option_flag_or(m: Maybe<&2, Value>, default: Bool) -> Bool:
205 match m:
206 case Some{OptionFlag{b}}:
207 b
208 case Some{OptionNum{n}}:
209 default
210 case Some{OptionText{t}}:
211 default
212 case None{}:
213 default
214
215def option_flag(opts: List<&2, Option>, key: String, default: Bool) -> Bool:
216 option_flag_or(find(opts, key), default)
217
218def option_text_or(m: Maybe<&2, Value>, default: String) -> String:
219 match m:
220 case Some{OptionText{t}}:
221 t
222 case Some{OptionNum{n}}:
223 default
224 case Some{OptionFlag{b}}:
225 default
226 case None{}:
227 default
228
229def option_text(opts: List<&2, Option>, key: String, default: String) -> String:
230 option_text_or(find(opts, key), default)
231
232def serve(run: Input -> IO(List<&2, Diag>)) -> IO(Unit):
233 IO.bind(Input, Unit, input(), i => IO.bind(List<&2, Diag>, Unit, run(i), report))