# Dictionary: Word Used In ...

Given a word `w0` , I wish to know all words that uses `w0`.
To that end, first I need to know whether a word `w1` uses
`w0` or not.

There are two candidate cell patterns for `w0` usage in `w1`.
These are:

`'lica.... i` or `LIteral CAll 0 0` in nga.
`'lica.... i` in nga is #2049.

~~~
#2049 'LICA.... const (LIteral_CAll_0_0_instruction
:lica....? (n-f) LICA.... eq? ;
~~~

`'liju.... i` or `LIteral JUmp 0 0` in nga.
`'liju.... i` in nga is #1793.

~~~
#1793 'LIJU.... const (LIteral_JUmp_0_0_instruction
:liju....? (n-f) LIJU.... eq? ;
~~~

The `pattern?` word will check for both.

~~~
:pattern? [ lica....? ] [ liju....? ] bi or ;
~~~

If pattern is followed by `w0`'s execution token `xt0`, 
then `w1` uses `w0`.

The pattern of two cells to be sought is

  LICA....  (or LIJU....)
  xt0

The name of `w1` may be found by `'a1 d:lookup d:name`
in which `a1` is `w1`'s address.

Variables `Used` contains `a0` and `In` contains `a1`.
Make sure the word's class is `class:word` and not something
else, like `class:primitive`, `class:data`, etc.
 
~~~
'Used var (a0
'In   var (a1
:class:word? (a-f) d:class fetch &class:word eq? ;
:used (a-) dup !Used ;
:in   (a-) dup !In   ;
~~~

Set the code range to search for the pattern.

~~~
'Start var
'End   var
~~~

The start is the execution token.

~~~
:start (-) @In d:xt !Start ; 
~~~

The end is two cells before the first newer entry to the
dictionary.

If that cell is not `lica...`, then the next cell does not 
hold an execution token.

The first newer entry may be found by `d:new fetch` .

~~~
:d:new-old (a-aa)_returns_(This_0)_if_This_is_d:last
  d:last dup-pair eq?     (this_last_flag
  [ drop #0 ] if;         (exit_if_this_is_last (this_last
  [ dup-pair d:link fetch (this_newer_this_new
    eq? [ TRUE ] [ d:link fetch FALSE ] choose (this_newer_flag
  ] until (this_newer
  swap d:link fetch ;     (newer_old

:d:new (a-a) d:new-old drop ;

:end (-) @In d:new dup n:zero?
  [ here #2 - ] [ dup #2 - n:max ] choose !End ;
~~~

Check if a pair of cells indicates that the word is used.

~~~
:pair? (a-f) dup fetch pattern? 
  [ #1 + fetch @Used d:xt fetch eq? ] [ drop FALSE ] choose ;
~~~

~~~
'Address var (head_address_of_the_pair_being_checked
'More    var (TRUE_=_there_are_remaining_pairs_to_check
'Found   var (TRUE_=_@In_used_@Used
:more    (-) @Address @End lt? [ TRUE ] [ FALSE ] choose !More ;
:prepare (-) start end  @Start !Address  FALSE !Found  more ;

:uses? (-f)_does_@In_use_@Used_?
  prepare [ 
    (pair-found @Address pair? [ &Found v:on ] if )
    (more-to-check more &Address v:inc )
    (condition-to-loop @Found not @More and ) ] while @Found ;
~~~

```
:t (aa-) used in start end ;
:a 'a s:put ;
:b a 'b s:put ;
:c b 'c s:put ;
'b d:lookup in 'a d:lookup used
uses? n:put nl
```

Final product.

~~~
:used-in (a-)
  used 
  [ dup class:word?
    [ in uses? [ @In d:name s:put sp ] if drop ] [ drop ] choose 
  ] d:for-each drop ;
:d:used-in (s-) d:lookup used-in ;
~~~

```
'a d:lookup used-in
```

Hide unnecessary words.

~~~
'LICA....  d:lookup d:link fetch
'd:used-in d:lookup d:link store 
~~~~

# Limitations

This only searches visible words. Any headers that are hidden
from the dictionary are no longer visible. So:

    :foo dup * + ;

    {{
      :test #2 #3 foo ;
    ----reveal--
      :bar test n:put nl ;
    }}

    'foo d:used-in

This will not see the use of `foo` in `test` as the header for
`test` is not visible after the closing `}}`.
