848ba7303b
FossilOrigin-Name: b5feea667d30aac255d1cfca61fed355d438d2ce6021677f1e53af6302b15eee
80 lines
2.6 KiB
Text
80 lines
2.6 KiB
Text
Forth systems often have a word that displays the names of all
|
|
words in the dictionary. This can be helpful on occasion, but it
|
|
doesn't provide very much information and can be quite daunting
|
|
to newer users.
|
|
|
|
In Retro, I want to do better. The first step towards this is to
|
|
allow listing words in different ways. Retro includes two for
|
|
doing this:
|
|
|
|
|
|
word stack description
|
|
================ ===== ===================================
|
|
d:words - display all words in the dictionary
|
|
d:words-with s- display words with the specified
|
|
substring in their name
|
|
|
|
In this, I propose two additional ones:
|
|
|
|
word stack description
|
|
================ ===== ===================================
|
|
d:words-in-class a- display words with the specified
|
|
class handler
|
|
d:words-by-class - display all words, grouped by their
|
|
class handler
|
|
|
|
The first is pretty easy. Retro has a `d:for-each` combinator
|
|
for iterating over the dictionary. With this I can pass a pointer
|
|
to the class handler and compare this to each header, showing
|
|
only the entries that match.
|
|
|
|
I am using `reorder` to setup the stack. I could also have done
|
|
this via `[ over ] dip swap` or `push over pop swap`. The use of
|
|
`reorder` is simply done to make the stack alteration obvious.
|
|
|
|
~~~
|
|
:d:words-in-class (a-)
|
|
[ dup d:class fetch
|
|
'abc 'abca reorder
|
|
eq? [ d:name s:put sp ] &drop choose ] d:for-each
|
|
drop ;
|
|
~~~
|
|
|
|
The second one is a little more involved.
|
|
|
|
First, all class handlers must be identified. I do this with the
|
|
`d:for-each` combinator, looking for names that have a `class:`
|
|
prefix. (This suffices as I keep all my class handlers in the
|
|
`class:` namespace; it won't pick up ones with non-standard naming)
|
|
|
|
I iterate over the dictionary and construct a set to hold a pointer
|
|
to the header for each class I identify.
|
|
|
|
The exposed word also uses `d:for-each`, iterating over the
|
|
dictionary once for each class in the set. It displays the name of
|
|
the class, and then uses `d:words-in-class` to display the words.
|
|
|
|
Of note here, creating a set consumes space. I'm using the
|
|
`v:preserve` combinator to preserve the location of `here` so that
|
|
any used space is recovered.
|
|
|
|
~~~
|
|
{{
|
|
:identify-classes (-a)
|
|
here #0 ,
|
|
[ dup d:name 'class: s:contains-string?
|
|
&, &drop choose ] d:for-each
|
|
here over - n:dec over store ;
|
|
---reveal---
|
|
:d:words-by-class
|
|
&Heap [ identify-classes
|
|
[ [ d:name s:put nl ]
|
|
[ d:xt fetch d:words-in-class ] bi
|
|
nl nl ] a:for-each ] v:preserve ;
|
|
}}
|
|
~~~
|
|
|
|
|
|
```
|
|
d:words-by-class
|
|
```
|