src/rules/suspicious/ring.bend checks
raw source on the hub · import 0xd96f2ab40f5df4925c42e96d0ba857ff/src/rules/suspicious/ring.bend as Ring
rule ring: a self-call replaces a binder with List.append of List.drop
(or String.append / ++, or tail) by a constant count, passing it back
in the binder's own parameter position. Each step copies that fixed window.
Keep it in an Array and advance an index. A list the def matches and walks
(as any scrutinee of a match) is variable-length input, a window dropped
into another parameter's slot is not carried, and a one-shot trim is not a
loop: all stay quiet. Growing an accumulator by append, with no drop of
that same value, is concat. Laws and proofs do not run (a def with no
type at all fills a law: it is a proof).
7 imports
import Base import ../../src.bend as Src import ../../finding.bend as F import ../../syntax/lex.bend as Lex import ../../syntax/tree.bend as Tree import ../calls.bend as Calls import ../../lazy/lazy.bend as Lazy
Definitions
def or_tok source · line 19 · raw
@aa:Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok> -> @+bb:Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
the first of two maybes
def is_num source · line 27 · raw
@nn:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> Bool
is the chain exactly one number?
def name_text source · line 35 · raw
@nn:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> String
the chain is exactly one lowercase name; its text, or empty
def win_name source · line 43 · raw
@nn:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+wins:List<&2, String> -> Bool
this argument is a window binder
def has_name source · line 48 · raw
@as:List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node> -> @+wins:List<&2, String> -> Bool
does any argument name the window?
def last_num source · line 57 · raw
@as:List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node> -> Bool
is the last argument a number?
def drop_ok source · line 67 · raw
@+tt:String -> @+as:List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node> -> @+wins:List<&2, String> -> Bool
a fixed drop or tail of a named window
def drop_tok source · line 73 · raw
@kk:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.TokKind -> @+tt:String -> @+line:U32 -> @+col:U32 -> @kids:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+wins:List<&2, String> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
the callee token when this call is a fixed drop
def here_of source · line 84 · raw
@+open:Bool -> @kk:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.TokKind -> @+tt:String -> @+line:U32 -> @+col:U32 -> @kids:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+wins:List<&2, String> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
the drop this call is, when the group is an application
def drop_in source · line 100 · raw
@nn:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+wins:List<&2, String> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
a drop anywhere under the node
def receiver_is source · line 117 · raw
@+list:Bool -> @+str:Bool -> @+as:List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node> -> @+wins:List<&2, String> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
which list an append extends
def receiver source · line 127 · raw
@+tt:String -> @kids:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+wins:List<&2, String> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
the drop an append copies onto, when this call is List.append or String.append
def pp_found source · line 131 · raw
@+is_pp:Bool -> @seen:Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
a ++ whose left already dropped: that drop; otherwise nothing
def pp_seen source · line 141 · raw
@+is_pp:Bool -> @+seen:Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
the drop still in play after this operator (++ starts a new left side)
def call_recv source · line 149 · raw
@+open:Bool -> @+tt:String -> @kids:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+wins:List<&2, String> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
an application's append-receiver drop; a bracket is not an application
def call_drop source · line 157 · raw
@+open:Bool -> @+kk:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.TokKind -> @+tt:String -> @+line:U32 -> @+col:U32 -> @+kids:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+wins:List<&2, String> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
a drop this node itself is: the call when it is an application, else under a bracket
def plus_scan source · line 173 · raw
@nn:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+seen:Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok> -> @+wins:List<&2, String> -> Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok>
a drop then ++, or an append onto a drop, in this chain
def slide_at source · line 197 · raw
@mm:Maybe<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/lex.Tok> -> @+path:String -> List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/finding.Finding>
a finding at the drop the scan found
def slide source · line 206 · raw
@aa:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+path:String -> @+wins:List<&2, String> -> List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/finding.Finding>
a finding at the drop, when the argument slides a window
def slot_wins source · line 211 · raw
@+slot:String -> @+wins:List<&2, String> -> List<&2, String>
the windows an argument in this parameter's slot may slide: the parameter itself when it is a window, else none
def slides source · line 216 · raw
@as:List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node> -> @+params:List<&2, String> -> @+path:String -> @+wins:List<&2, String> -> List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/finding.Finding>
every self-call argument that slides the window of its own slot (params, from the argument's position on)
def walk source · line 231 · raw
@nn:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+self:String -> @+params:List<&2, String> -> @+path:String -> @+wins:List<&2, String> -> List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/finding.Finding>
every self-call's sliding arguments
def names_in source · line 254 · raw
@nn:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @acc:List<&2, String> -> List<&2, String>
the top-level names of a chain, onto acc
def match_names source · line 264 · raw
@kids:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+acc:List<&2, String> -> List<&2, String>
every scrutinee of match a b ..:, onto acc (acc alone for any other chain)
def matched source · line 272 · raw
@nn:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @+acc:List<&2, String> -> List<&2, String>
names the def matches, as any scrutinee: variable-length input, not a window
def windows.go source · line 287 · raw
@ps:List<&2, String> -> @+bad:List<&2, String> -> @+acc:List<&2, String> -> List<&2, String>
parameters that are not matched as input
def windows source · line 296 · raw
@sig:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> @body:0xd96f2ab40f5df4925c42e96d0ba857ff/src/syntax/tree.Node -> List<&2, String>
parameters that are not matched as input
def check.go source · line 299 · raw
@ds:List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/rules/calls.Def> -> @+path:String -> @acc:List<&2, List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/finding.Finding>> -> List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/finding.Finding>
def check source · line 310 · raw
@ss:0xd96f2ab40f5df4925c42e96d0ba857ff/src/src.Src -> List<&2, 0xd96f2ab40f5df4925c42e96d0ba857ff/src/finding.Finding>
the rule