@ ProgramNode (location: (1,0)-(7,47))
├── locals: []
└── statements:
    @ StatementsNode (location: (1,0)-(7,47))
    └── body: (length: 4)
        ├── @ WhileNode (location: (1,0)-(1,45))
        │   ├── keyword_loc: (1,0)-(1,5) = "while"
        │   ├── closing_loc: (1,42)-(1,45) = "end"
        │   ├── predicate:
        │   │   @ DefNode (location: (1,6)-(1,33))
        │   │   ├── name: :foo
        │   │   ├── name_loc: (1,10)-(1,13) = "foo"
        │   │   ├── receiver: ∅
        │   │   ├── parameters:
        │   │   │   @ ParametersNode (location: (1,14)-(1,28))
        │   │   │   ├── requireds: (length: 0)
        │   │   │   ├── optionals: (length: 1)
        │   │   │   │   └── @ OptionalParameterNode (location: (1,14)-(1,28))
        │   │   │   │       ├── name: :a
        │   │   │   │       ├── name_loc: (1,14)-(1,15) = "a"
        │   │   │   │       ├── operator_loc: (1,16)-(1,17) = "="
        │   │   │   │       └── value:
        │   │   │   │           @ CallNode (location: (1,18)-(1,28))
        │   │   │   │           ├── receiver: ∅
        │   │   │   │           ├── call_operator_loc: ∅
        │   │   │   │           ├── message_loc: (1,18)-(1,21) = "tap"
        │   │   │   │           ├── opening_loc: ∅
        │   │   │   │           ├── arguments: ∅
        │   │   │   │           ├── closing_loc: ∅
        │   │   │   │           ├── block:
        │   │   │   │           │   @ BlockNode (location: (1,22)-(1,28))
        │   │   │   │           │   ├── locals: []
        │   │   │   │           │   ├── parameters: ∅
        │   │   │   │           │   ├── body: ∅
        │   │   │   │           │   ├── opening_loc: (1,22)-(1,24) = "do"
        │   │   │   │           │   └── closing_loc: (1,25)-(1,28) = "end"
        │   │   │   │           ├── flags: ∅
        │   │   │   │           └── name: :tap
        │   │   │   ├── rest: ∅
        │   │   │   ├── posts: (length: 0)
        │   │   │   ├── keywords: (length: 0)
        │   │   │   ├── keyword_rest: ∅
        │   │   │   └── block: ∅
        │   │   ├── body: ∅
        │   │   ├── locals: [:a]
        │   │   ├── def_keyword_loc: (1,6)-(1,9) = "def"
        │   │   ├── operator_loc: ∅
        │   │   ├── lparen_loc: ∅
        │   │   ├── rparen_loc: ∅
        │   │   ├── equal_loc: ∅
        │   │   └── end_keyword_loc: (1,30)-(1,33) = "end"
        │   ├── statements:
        │   │   @ StatementsNode (location: (1,35)-(1,40))
        │   │   └── body: (length: 1)
        │   │       └── @ BreakNode (location: (1,35)-(1,40))
        │   │           ├── arguments: ∅
        │   │           └── keyword_loc: (1,35)-(1,40) = "break"
        │   └── flags: ∅
        ├── @ WhileNode (location: (3,0)-(3,42))
        │   ├── keyword_loc: (3,0)-(3,5) = "while"
        │   ├── closing_loc: (3,39)-(3,42) = "end"
        │   ├── predicate:
        │   │   @ DefNode (location: (3,6)-(3,30))
        │   │   ├── name: :foo
        │   │   ├── name_loc: (3,10)-(3,13) = "foo"
        │   │   ├── receiver: ∅
        │   │   ├── parameters: ∅
        │   │   ├── body:
        │   │   │   @ StatementsNode (location: (3,15)-(3,25))
        │   │   │   └── body: (length: 1)
        │   │   │       └── @ CallNode (location: (3,15)-(3,25))
        │   │   │           ├── receiver: ∅
        │   │   │           ├── call_operator_loc: ∅
        │   │   │           ├── message_loc: (3,15)-(3,18) = "tap"
        │   │   │           ├── opening_loc: ∅
        │   │   │           ├── arguments: ∅
        │   │   │           ├── closing_loc: ∅
        │   │   │           ├── block:
        │   │   │           │   @ BlockNode (location: (3,19)-(3,25))
        │   │   │           │   ├── locals: []
        │   │   │           │   ├── parameters: ∅
        │   │   │           │   ├── body: ∅
        │   │   │           │   ├── opening_loc: (3,19)-(3,21) = "do"
        │   │   │           │   └── closing_loc: (3,22)-(3,25) = "end"
        │   │   │           ├── flags: ∅
        │   │   │           └── name: :tap
        │   │   ├── locals: []
        │   │   ├── def_keyword_loc: (3,6)-(3,9) = "def"
        │   │   ├── operator_loc: ∅
        │   │   ├── lparen_loc: ∅
        │   │   ├── rparen_loc: ∅
        │   │   ├── equal_loc: ∅
        │   │   └── end_keyword_loc: (3,27)-(3,30) = "end"
        │   ├── statements:
        │   │   @ StatementsNode (location: (3,32)-(3,37))
        │   │   └── body: (length: 1)
        │   │       └── @ BreakNode (location: (3,32)-(3,37))
        │   │           ├── arguments: ∅
        │   │           └── keyword_loc: (3,32)-(3,37) = "break"
        │   └── flags: ∅
        ├── @ WhileNode (location: (5,0)-(5,50))
        │   ├── keyword_loc: (5,0)-(5,5) = "while"
        │   ├── closing_loc: (5,47)-(5,50) = "end"
        │   ├── predicate:
        │   │   @ DefNode (location: (5,6)-(5,38))
        │   │   ├── name: :foo
        │   │   ├── name_loc: (5,15)-(5,18) = "foo"
        │   │   ├── receiver:
        │   │   │   @ SelfNode (location: (5,10)-(5,14))
        │   │   ├── parameters:
        │   │   │   @ ParametersNode (location: (5,19)-(5,33))
        │   │   │   ├── requireds: (length: 0)
        │   │   │   ├── optionals: (length: 1)
        │   │   │   │   └── @ OptionalParameterNode (location: (5,19)-(5,33))
        │   │   │   │       ├── name: :a
        │   │   │   │       ├── name_loc: (5,19)-(5,20) = "a"
        │   │   │   │       ├── operator_loc: (5,21)-(5,22) = "="
        │   │   │   │       └── value:
        │   │   │   │           @ CallNode (location: (5,23)-(5,33))
        │   │   │   │           ├── receiver: ∅
        │   │   │   │           ├── call_operator_loc: ∅
        │   │   │   │           ├── message_loc: (5,23)-(5,26) = "tap"
        │   │   │   │           ├── opening_loc: ∅
        │   │   │   │           ├── arguments: ∅
        │   │   │   │           ├── closing_loc: ∅
        │   │   │   │           ├── block:
        │   │   │   │           │   @ BlockNode (location: (5,27)-(5,33))
        │   │   │   │           │   ├── locals: []
        │   │   │   │           │   ├── parameters: ∅
        │   │   │   │           │   ├── body: ∅
        │   │   │   │           │   ├── opening_loc: (5,27)-(5,29) = "do"
        │   │   │   │           │   └── closing_loc: (5,30)-(5,33) = "end"
        │   │   │   │           ├── flags: ∅
        │   │   │   │           └── name: :tap
        │   │   │   ├── rest: ∅
        │   │   │   ├── posts: (length: 0)
        │   │   │   ├── keywords: (length: 0)
        │   │   │   ├── keyword_rest: ∅
        │   │   │   └── block: ∅
        │   │   ├── body: ∅
        │   │   ├── locals: [:a]
        │   │   ├── def_keyword_loc: (5,6)-(5,9) = "def"
        │   │   ├── operator_loc: (5,14)-(5,15) = "."
        │   │   ├── lparen_loc: ∅
        │   │   ├── rparen_loc: ∅
        │   │   ├── equal_loc: ∅
        │   │   └── end_keyword_loc: (5,35)-(5,38) = "end"
        │   ├── statements:
        │   │   @ StatementsNode (location: (5,40)-(5,45))
        │   │   └── body: (length: 1)
        │   │       └── @ BreakNode (location: (5,40)-(5,45))
        │   │           ├── arguments: ∅
        │   │           └── keyword_loc: (5,40)-(5,45) = "break"
        │   └── flags: ∅
        └── @ WhileNode (location: (7,0)-(7,47))
            ├── keyword_loc: (7,0)-(7,5) = "while"
            ├── closing_loc: (7,44)-(7,47) = "end"
            ├── predicate:
            │   @ DefNode (location: (7,6)-(7,35))
            │   ├── name: :foo
            │   ├── name_loc: (7,15)-(7,18) = "foo"
            │   ├── receiver:
            │   │   @ SelfNode (location: (7,10)-(7,14))
            │   ├── parameters: ∅
            │   ├── body:
            │   │   @ StatementsNode (location: (7,20)-(7,30))
            │   │   └── body: (length: 1)
            │   │       └── @ CallNode (location: (7,20)-(7,30))
            │   │           ├── receiver: ∅
            │   │           ├── call_operator_loc: ∅
            │   │           ├── message_loc: (7,20)-(7,23) = "tap"
            │   │           ├── opening_loc: ∅
            │   │           ├── arguments: ∅
            │   │           ├── closing_loc: ∅
            │   │           ├── block:
            │   │           │   @ BlockNode (location: (7,24)-(7,30))
            │   │           │   ├── locals: []
            │   │           │   ├── parameters: ∅
            │   │           │   ├── body: ∅
            │   │           │   ├── opening_loc: (7,24)-(7,26) = "do"
            │   │           │   └── closing_loc: (7,27)-(7,30) = "end"
            │   │           ├── flags: ∅
            │   │           └── name: :tap
            │   ├── locals: []
            │   ├── def_keyword_loc: (7,6)-(7,9) = "def"
            │   ├── operator_loc: (7,14)-(7,15) = "."
            │   ├── lparen_loc: ∅
            │   ├── rparen_loc: ∅
            │   ├── equal_loc: ∅
            │   └── end_keyword_loc: (7,32)-(7,35) = "end"
            ├── statements:
            │   @ StatementsNode (location: (7,37)-(7,42))
            │   └── body: (length: 1)
            │       └── @ BreakNode (location: (7,37)-(7,42))
            │           ├── arguments: ∅
            │           └── keyword_loc: (7,37)-(7,42) = "break"
            └── flags: ∅
