def work

bolt@1.27.0.0 · src/rules/suspicious/eager.bend:102

import bolt@1.27.0.0/src/rules/suspicious/eager.bend as Eager
import Base
import bolt@1.27.0.0/src/finding.bend as F
import bolt@1.27.0.0/src/syntax/lex.bend as Lex
import bolt@1.27.0.0/src/syntax/tree.bend as Tree

102# the work under a def's body: hot says the node sits in a branch argument of
103# a `Bool.pick` (so it runs whatever the condition), seg counts the arguments
104# of the pick whose group this chain is (0 the type, 1 the condition, 2 and 3
105# the branches; 9 for a chain that is not a pick's), and keep is what hot
106# returns to at the next comma of a chain that is not a pick's, so a `=>`
107# clears hot for the lambda's own body and not for the arguments after it. A
108# leaf moves the state by its kind (work.hot, work.seg); a `=>` or a comma
109# before a group names no call, so that group is walked as any other
110def work(
111  nn: Tree.Node,
112  +ns: List<&2, String>,
113  +self: String,
114  +path: String,
115  +hot: Bool,
116  +seg: U32,
117  +keep: Bool
118) -> List<&2, F.Finding>:
119  match nn:
120    case Tree.NCons{Tree.Leaf{Lex.Tok{+k, +t, +l, +c}}, Tree.NCons{Tree.Group{Lex.Tok{_, +o, _, _}, +kids, _}, rest}}:
121      +now = work.hot(k, hot, seg, keep)
122      +call = Bool.and(work.name(k), String.eq(o, "("))
123      +is_pick = Bool.and(call, String.eq(t, "Bool.pick"))
124      +known = List.contains(~String, ~String.eq, ns, t)
125      +mine = Bool.and(Bool.not(String.eq(t, self)), known)
126      +report = Bool.and(now, Bool.and(call, mine))
127      +inner = Bool.and(now, Bool.not(is_pick))
128      +more = List.concat(&2, F.Finding,
129        [work(kids, ns, self, path, inner, Bool.pick(U32, is_pick, 0, 9), inner),
130          work(rest, ns, self, path, now, work.seg(k, seg), keep)])
131      Bool.pick(List<&2, F.Finding>, report,
132        F.Finding{path, l, c, U32.from_nat(String.length(t)), "eager",
133          t ++ " is called in a branch of Bool.pick, which evaluates both branches, so it runs whatever the condition; bind it above the pick, or branch with `match` on the condition."}
134          <> more,
135        more)
136    case Tree.NCons{Tree.Leaf{Lex.Tok{+k, t, l, c}}, rest}:
137      work(rest, ns, self, path, work.hot(k, hot, seg, keep), work.seg(k, seg), keep)
138    case Tree.NCons{Tree.Group{open, +kids, close}, rest}:
139      List.concat(&2, F.Finding, [work(kids, ns, self, path, hot, 9, hot), work(rest, ns, self, path, hot, seg, keep)])
140    case Tree.NCons{Tree.Stmt{kind, +kids, body}, rest}:
141      List.concat(&2, F.Finding, [work(kids, ns, self, path, False{}, 9, False{}),
142        work(body, ns, self, path, False{}, 9, False{}),
143        work(rest, ns, self, path, hot, seg, keep)])
144    case Tree.NCons{h, rest}:
145      work(rest, ns, self, path, hot, seg, keep)
146    case other:
147      Nil{}

Uses (19)

Used by (1)