src/rules/correctness/put.bend
bolt@1.27.0.0 · 81 lines · 8 definitions
1
2
3
4
5
6
7
8import Base
9import bolt@1.27.0.0/src/src.bend as Src
10import bolt@1.27.0.0/src/lazy/lazy.bend as Lazy
11import bolt@1.27.0.0/src/finding.bend as F
12import bolt@1.27.0.0/src/syntax/lex.bend as Lex
13import bolt@1.27.0.0/src/rules/tokens.bend as T
14
15
16def defines.named(toks: List<&2, Lex.Tok>) -> Bool:
17 match toks:
18 case Con{Lex.Tok{k, +t, l, c}, rest}:
19 String.eq(t, "Map.put")
20 case Nil{}:
21 False{}
22
23
24def defines.key(kk: Lex.TokKind) -> Bool:
25 match kk:
26 case Lex.TKey{}:
27 True{}
28 case other:
29 False{}
30
31
32def calls.dotted(kk: Lex.TokKind) -> Bool:
33 match kk:
34 case Lex.TDotted{}:
35 True{}
36 case other:
37 False{}
38
39
40def defines(toks: List<&2, Lex.Tok>) -> Bool:
41 match toks:
42 case Con{Lex.Tok{k, +d, l, c}, +rest}:
43 Lazy.or_else(Bool.and(defines.key(k), Bool.and(String.eq(d, "def"), defines.named(rest))), _u => defines(rest))
44 case Nil{}:
45 False{}
46
47
48
49def calls.one(
50 +tt: String,
51 +oo: String,
52 +ll: U32,
53 +cc: U32,
54 +path: String,
55 +more: List<&2, F.Finding>
56) -> List<&2, F.Finding>:
57 Bool.pick(List<&2, F.Finding>, Bool.and(String.eq(tt, "Map.put"), String.eq(oo, "(")),
58 F.Finding{path, ll, cc, 7, "put", "Map.put does not compare keys, so a new key can overwrite an existing entry; use Map.set."}
59 <> more,
60 more)
61
62
63def calls(toks: List<&2, Lex.Tok>, +path: String) -> List<&2, F.Finding>:
64 match toks:
65 case Con{Lex.Tok{k, +t, +l, +c}, +rest}:
66 match rest:
67 case Con{Lex.Tok{k2, +o, l2, c2}, r2}:
68 Lazy.either(List<&2, F.Finding>, Bool.and(calls.dotted(k), Lex.is_open(k2)), _u => calls.one(t, o, l, c, path,
69 calls(r2, path)), _v => calls(rest, path))
70 case Nil{}:
71 Nil{}
72 case Nil{}:
73 Nil{}
74
75def check.on(+toks: List<&2, Lex.Tok>, path: String) -> List<&2, F.Finding>:
76 Lazy.stop(List<&2, F.Finding>, defines(toks), [], _u => calls(toks, path))
77
78
79def check(ss: Src.Src) -> List<&2, F.Finding>:
80 Src.Src{path, text, toks, tree, bound, items} = ss
81 check.on(T.sig(toks), path)