This is a quick little thing to generate some statistics from the RETRO image and VM, along with some introspection to identify sigil handlers and word classes.

First, memory. This is easy due to the defined constants and queries provided by RETRO.

~~~nl 'Memory: s:put nl nl     EOM '__Total_memory:_%n\n s:format s:put   FREE '__Free_memory:__%n\n s:format s:put   here '__Used_memory:__%n\n s:format s:put ~~~

Dictionary

Next, some statistics on the dictionary. The header sizing would need to be adjusted if you add or remove fields from them.

The header contains fields for:

link to prior address pointer to class handler null terminated string with the name

So the size is 4 cells (the three fields and null terminator) plus the length of the name.

~~~nl 'Dictionary: s:put nl nl     #0 [ d:name s:length #4 + + ] d:for-each   '__Headers_consume_%n\n s:format s:put     #0 [ d:name s:length + n:inc ] d:for-each   '__Names_consume_%n\n s:format s:put ~~~

Determine the number of words in the dictionary.

~~~  #0 [ drop n:inc ] d:for-each   '__%n_names_defined\n s:format s:put ~~~

Determine the average length of a word name.

~~~  #0 [ d:name s:length + ] d:for-each   #0 [ drop n:inc ] d:for-each   / '__Average_name_length:_%n\n s:format s:put ~~~

And without the sigils...

~~~  #0 #0 [ d:name dup $: s:index/char n:inc + s:length + [ n:inc ] dip ] d:for-each swap /   '__Average_name_without_namespace:_%n\n s:format s:put ~~~

Longest name are...

~~~  #0 [ d:name s:length n:max ] d:for-each   '__Longest_names_are_%n_characters\n s:format s:put ~~~

Word classes are conventionally named as:

class:<name>

This prints the names of words matching them. It also demonstrates constructing an array of the names, which can be adapted for other purposes.

~~~nl 'Classes: s:put nl nl   :identify-classes (-a)   here #0 ,   [ d:name dup 'class: s:contains/string?     &, &drop choose ] d:for-each   here over - n:dec over store ;   sp sp identify-classes [ s:put sp ] a:for-each nl ~~~

Sigils are named as:

sigil:<character>

Unlike classes, this is not merely a convention, but an actual requirement.

The process for obtaining an array of them and printing it is the same as with the class handlers.

~~~nl 'Sigils: s:put nl nl   :identify-sigils (-a)   here #0 ,   [ d:name dup 'sigil: s:contains/string?     &, &drop choose ] d:for-each   here over - n:dec over store ;   sp sp identify-sigils [ s:put sp ] a:for-each nl   nl ~~~