Pick.walk: def of bolt@1.27.0.0 Import: import bolt@1.27.0.0/src/rules/correctness/pick.bend as Pick Lines 68-103 of bolt@1.27.0.0/src/rules/correctness/pick.bend: https://jend.leeeet.dev/read.txt?path=bolt@1.27.0.0/src/rules/correctness/pick.bend&start_line=68&end_line=103 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 import bolt@1.27.0.0/src/rules/calls.bend as Calls # every `Bool.pick(..)` in a chain, at any depth, that recurses in both # branches or in one. The chain is argument nth of a group with quiet # (inside a branch of a reported pick) and hush (the group is a reported # pick, so its branches are quiet); a pick in the condition still counts. def walk(nn: Tree.Node, +name: String, +path: String, +quiet: Bool, +hush: Bool, +nth: Nat) -> List<&2, F.Finding>: match nn: case Tree.NCons{Tree.Leaf{Lex.Tok{k, +t, +l, +c}}, Tree.NCons{Tree.Group{open, +kids, close}, rest}}: +at = next(k, nth) +q = mute(quiet, hush, at) +as = Calls.args(kids) +ispick = String.eq(t, "Bool.pick") +two = Bool.and(Bool.and(ispick, Bool.not(q)), both(as, name)) +one = Bool.and(Bool.and(ispick, Bool.not(two)), Bool.and(Bool.not(q), once(as, name))) +more = List.concat(&2, F.Finding, [walk(kids, name, path, q, Bool.or(two, one), 0n), walk(rest, name, path, quiet, hush, at)]) Bool.pick(List<&2, F.Finding>, two, F.Finding{path, l, c, 9, "pick", name ++ " calls itself in both branches of Bool.pick, which evaluates both, so both calls run; bind the call once above the pick."} <> more, Bool.pick(List<&2, F.Finding>, one, F.Finding{path, l, c, 9, "pick", name ++ " calls itself in one branch of Bool.pick, which evaluates both, so the call always runs and never exits early; branch with `match` on the condition instead."} <> more, more)) case Tree.NCons{Tree.Leaf{Lex.Tok{k, t, l, c}}, rest}: walk(rest, name, path, quiet, hush, next(k, nth)) case Tree.NCons{Tree.Group{open, kids, close}, rest}: List.concat(&2, F.Finding, [walk(kids, name, path, mute(quiet, hush, nth), False{}, 0n), walk(rest, name, path, quiet, hush, nth)]) case Tree.NCons{Tree.Stmt{kind, kids, body}, rest}: List.concat(&2, F.Finding, [walk(kids, name, path, mute(quiet, hush, nth), False{}, 0n), walk(body, name, path, mute(quiet, hush, nth), False{}, 0n), walk(rest, name, path, quiet, hush, nth)]) case Tree.NCons{h, rest}: walk(rest, name, path, quiet, hush, nth) case other: Nil{} Uses (19): https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=Bool https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=Bool.and https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=Bool.not https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=Bool.or https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=Bool.pick https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=List https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=List.concat https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=Nat https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=String https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=String.append https://jend.leeeet.dev/definition.txt?path=Base/base.bend&name=String.eq https://jend.leeeet.dev/definition.txt?path=bolt@1.27.0.0/src/finding.bend&name=Finding https://jend.leeeet.dev/definition.txt?path=bolt@1.27.0.0/src/rules/calls.bend&name=args https://jend.leeeet.dev/definition.txt?path=bolt@1.27.0.0/src/rules/correctness/pick.bend&name=both https://jend.leeeet.dev/definition.txt?path=bolt@1.27.0.0/src/rules/correctness/pick.bend&name=mute https://jend.leeeet.dev/definition.txt?path=bolt@1.27.0.0/src/rules/correctness/pick.bend&name=next https://jend.leeeet.dev/definition.txt?path=bolt@1.27.0.0/src/rules/correctness/pick.bend&name=once https://jend.leeeet.dev/definition.txt?path=bolt@1.27.0.0/src/syntax/lex.bend&name=Tok https://jend.leeeet.dev/definition.txt?path=bolt@1.27.0.0/src/syntax/tree.bend&name=Node