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 `}}`.