src/rules/perf/chars.bend
bolt@1.27.0.0 · 72 lines · 6 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import Base
20import bolt@1.27.0.0/src/src.bend as Src
21import bolt@1.27.0.0/src/finding.bend as F
22import bolt@1.27.0.0/src/syntax/lex.bend as Lex
23import bolt@1.27.0.0/src/syntax/tree.bend as Tree
24import bolt@1.27.0.0/src/lazy/lazy.bend as Lazy
25import bolt@1.27.0.0/src/rules/tokens.bend as T
26
27
28def literal(kids: Tree.Node) -> U32:
29 match kids:
30 case Tree.NCons{Tree.Leaf{Lex.Tok{Lex.TChar{}, t, l, c}}, rest}:
31 1
32 case other:
33 0
34
35
36def tally(body: Tree.Node, +nn: U32) -> U32:
37 match body:
38 case Tree.NCons{Tree.Stmt{Tree.SCase{}, kids, b}, rest}:
39 +k = literal(T.pattern(kids))
40 tally(rest, (nn + k : U32))
41 case Tree.NCons{h, rest}:
42 tally(rest, nn)
43 case other:
44 nn
45
46
47def report(+nn: U32, +path: String, +ll: U32, +cc: U32) -> List<&2, F.Finding>:
48 Bool.pick(List<&2, F.Finding>, U32.is_gt(nn, 8),
49 [F.Finding{path, ll, cc, 5, "chars", "This match has " ++ U32.show(nn)
50 ++ " character-literal cases, over the limit of 8, which blows up compile time and memory; compare Char.to_u32(c) instead."}],
51 [])
52
53
54def on_stmt(+kids: Tree.Node, +body: Tree.Node, +path: String) -> List<&2, F.Finding>:
55 +hit = T.keyword(kids, "match")
56 Lazy.stop(List<&2, F.Finding>, Bool.not(hit), [],
57 _u => report(tally(body, 0), path, Tree.line(kids), Tree.col(kids)))
58
59
60def walk(nn: Tree.Node, +path: String) -> List<&2, F.Finding>:
61 match nn:
62 case Tree.NCons{Tree.Stmt{kind, kids, +body}, rest}:
63 List.concat(&2, F.Finding, [on_stmt(kids, body, path), walk(body, path), walk(rest, path)])
64 case Tree.NCons{h, rest}:
65 walk(rest, path)
66 case other:
67 Nil{}
68
69
70def check(ss: Src.Src) -> List<&2, F.Finding>:
71 Src.Src{path, text, toks, tree, bound, items} = ss
72 walk(tree, path)