1 # src/codes: the stable id of every rule. A bolt.bend still names the slug 2 # (`wrap`); a diagnostic shows the code (`S003`) and, in an editor, the 3 # source `bolt(group:slug)`. Numbers are assigned once, in the group order 4 # of src/README.md: do not renumber a rule, and do not reuse a retired code 5 # (L004 was `quantify`, now `closed` itself; C001 was `shadow` and U005 was 6 # `nat`, whose failures bend 2.0.25 no longer has; U014 was `argv`, retired 7 # before its first release, since every reader already drops the program; 8 # U008 `table`, U009 `hoist`, U010 `ring`, U012 `unit` and U013 `scan` were 9 # retired for want of real hits, and L003 `unsafe` since bend 2.0.32 reports 10 # an unsafe def a proof reaches itself). A code names the rule, not its 11 # group: a rule that moves keeps its code (`strings` and `chars` are `perf`, 12 # `foreign` and the cost rules `fuel`, `index`, `strict` and `rewalk` are 13 # `pedantic`). 14 # 15 # No law can say this, since it is about versions: a released code is never 16 # renumbered or reused, which review of this table keeps. 17 import Base 18 import ./lazy/lazy.bend as Lazy 19 20 # one rule: the slug bolt.bend names, its code, its group 21 type Entry is Data: 22 Entry{slug: String, id: String, grp: String} 23 24 # every rule, in group order 25 def table() -> List<&2, Entry>: 26 [ 27 Entry{"hole", "C002", "correctness"}, 28 Entry{"pick", "C003", "correctness"}, 29 Entry{"put", "C004", "correctness"}, 30 Entry{"arms", "C005", "correctness"}, 31 Entry{"escape", "C006", "correctness"}, 32 Entry{"twice", "C007", "correctness"}, 33 Entry{"setting", "C011", "correctness"}, 34 Entry{"unused", "U001", "suspicious"}, 35 Entry{"eager", "U003", "suspicious"}, 36 Entry{"concat", "U004", "suspicious"}, 37 Entry{"thunk", "U015", "suspicious"}, 38 Entry{"fromrev", "U016", "suspicious"}, 39 Entry{"prefix", "U017", "suspicious"}, 40 Entry{"empty", "U018", "suspicious"}, 41 Entry{"strings", "C008", "perf"}, 42 Entry{"chars", "C009", "perf"}, 43 Entry{"doc", "S001", "style"}, 44 Entry{"space", "S002", "style"}, 45 Entry{"wrap", "S003", "style"}, 46 Entry{"param", "S004", "style"}, 47 Entry{"noqa", "S005", "style"}, 48 Entry{"transcong", "S006", "style"}, 49 Entry{"coverage", "L001", "laws"}, 50 Entry{"closed", "L002", "laws"}, 51 Entry{"foreign", "C010", "pedantic"}, 52 Entry{"strict", "U002", "pedantic"}, 53 Entry{"fuel", "U006", "pedantic"}, 54 Entry{"index", "U007", "pedantic"}, 55 Entry{"rewalk", "U011", "pedantic"}, 56 Entry{"tail", "P001", "pedantic"}] 57 58 # this row is the slug 59 def find.same(+row: Entry, +slug: String) -> Bool: 60 Entry{+s, _id, _grp} = row 61 String.eq(s, slug) 62 63 # the row for a slug 64 def find(rows: List<&2, Entry>, +slug: String) -> Maybe<&2, Entry>: 65 match rows: 66 case Nil{}: 67 None{} 68 case Con{+row, rest}: 69 Lazy.stop(Maybe<&2, Entry>, find.same(row, slug), Some{row}, _u => find(rest, slug)) 70 71 # the stable code; the slug itself when it is not a rule 72 def code.at(mm: Maybe<&2, Entry>, +slug: String) -> String: 73 match mm: 74 case None{}: 75 slug 76 case Some{Entry{_s, +id, _grp}}: 77 id 78 79 # the stable code; the slug itself when it is not a rule 80 def code(+slug: String) -> String: 81 code.at(find(table(), slug), slug) 82 83 # the group; empty when the slug is not a rule 84 def group.at(mm: Maybe<&2, Entry>) -> String: 85 match mm: 86 case None{}: 87 "" 88 case Some{Entry{_s, _id, +grp}}: 89 grp 90 91 # the group; empty when the slug is not a rule 92 def group(+slug: String) -> String: 93 group.at(find(table(), slug)) 94 95 # `bolt(group:slug)`; `bolt` when the slug is not a rule 96 def source.at(mm: Maybe<&2, Entry>) -> String: 97 match mm: 98 case None{}: 99 "bolt" 100 case Some{Entry{+s, _id, +grp}}: 101 "bolt(" ++ grp ++ ":" ++ s ++ ")" 102 103 # `bolt(group:slug)`; `bolt` when the slug is not a rule 104 def source(+slug: String) -> String: 105 source.at(find(table(), slug))