retroforth/tools/retro-describe.retro
crc 660e52bdcb rename words in sys: to script: (old names still work in this release, but are deprecated)
FossilOrigin-Name: 1a43743f43076eb087ee4dd7fbfa96b8dfda2aa4ddcff41e6a5a9634ba6e239c
2020-09-14 19:55:02 +00:00

166 lines
4.3 KiB
Text
Executable file

#!/usr/bin/env retro
# retro-describe
This is a small tool to display some helpful information
about a word.
# Usage
retro-describe wordname
# Notes
This is based on the `glossary.forth` tool included with
Retro. It's basically just the `describe` functionality,
but is a little more streamlined to use and abandons the
editing and export functionality of the full tool.
# The Code
First, gather the command line arguments. If no word name
was passed, just exit.
~~~
script:arguments n:zero? [ #0 unix:exit ] if
~~~
~~~
#167 'DATA-START const
~~~
# Data File
/usr/local/share/RETRO12/words.tsv
I like plain text formats, so the data is stored as a plain text
file, with one line per word. Each line has a number of fields.
These are tab separated. The fields are:
| name | 0
| data stack | 1
| address stack | 2
| float stack | 3
| general description | 4
| interpret time description | 5
| compile time description | 6
| class handler | 7
| example 1 | 8
| example 2 | 9
| namespace | 10
| interface | 11
I use a variable named `SourceLine` to point to the current line
contents.
~~~
'SourceLine var
~~~
I next define words to access each field. This involves helpers
to skip over fields I'm not intersted in, a word to return a
specific field, and the top level wrappers over these.
Rather than manually enter each of the field accessors, I am
just listing them in a set and constructing the words via some
simple code.
~~~
{{
:skip (n-) [ ASCII:HT s:split drop n:inc ] times ;
:select (n-s)
@SourceLine swap skip ASCII:HT s:split nip ;
---reveal---
#0 { 'name 'dstack 'astack 'fstack
'descr 'itime 'ctime 'class
'ex1 'ex2 'namespace 'interface }
[ 'field: s:prepend d:create
dup compile:lit &select compile:call compile:ret
&class:word reclass n:inc ] a:for-each drop
}}
~~~
# Display an Entry
I implement a word to display an entry. This will use a
format like:
name
Data: -
Addr: -
Float: -
A description of the word.
Class Handler: class:word | Namespace: global | Interface Layer: all
If there are specific notes on interpret or compile time
actions, or any examples, they will be displayed after
the description.
~~~
{{
:s:putfmt (s-) s:format s:put ;
:name field:name '%s\n\n s:putfmt ;
:data field:dstack '__Data:__%s\n s:putfmt ;
:address field:astack '__Addr:__%s\n s:putfmt ;
:float field:fstack '__Float:_%s\n\n s:putfmt ;
:description field:descr '%s\n\n s:putfmt ;
:interpret-time field:itime s:length 0; drop
field:itime 'Interpret_Time:\n__%s\n\n s:putfmt ;
:compile-time field:ctime s:length 0; drop
field:ctime 'Compile_Time:\n__%s\n\n s:putfmt ;
:| '_|_ s:put ;
:class field:class 'Class:_%s s:putfmt ;
:namespace field:namespace 'Namespace:_%s s:putfmt ;
:interface field:interface 'Interface_Layer:_%s s:putfmt ;
:example1 field:ex1 '{n/a} s:eq? not 0; drop
field:ex1 s:format '\nExample_#1:\n\n%s\n\n s:putfmt ;
:example2 field:ex2 '{n/a} s:eq? not 0; drop
field:ex2 s:format '\nExample_#1:\n\n%s\n\n s:putfmt ;
---reveal---
:display-result
name
data (stack)
address (stack)
float (stack)
description
interpret-time
compile-time
class | namespace | interface nl
example1
example2 ;
}}
~~~
## Describe a Word
~~~
{{
'Target var
'LineNumber var
:matched? (-f) field:name @Target s:eq? ;
:entry? (-f)
@LineNumber DATA-START gteq? &LineNumber v:inc ;
---reveal---
:find-and-display-entry
#0 !LineNumber
s:keep !Target
script:name [ &Heap [ s:keep !SourceLine entry? 0; drop matched? [ display-result ] if ] v:preserve ] file:for-each-line nl ;
}}
~~~
# Finish
This checks the command line arguments and calls the proper words to
handle each case.
~~~
script:arguments [ I script:get-argument find-and-display-entry ] indexed-times
~~~
# Glossary Data