Introduction
Those of you familiar with ANS Forth, know about "VOCABULARY"s. A "context" is similar in that it encapsulates a list of words, and controls access to those words. It is different primarily in that Reva contexts also permit custom "find" implementations on a per-context basis. The idea for Reva's contexts comes from HelFORTH, but our implementation is different in subtle ways.Contexts:
- Allow compartmentalization of code according to topic or usage (like vocabularies).
- May be nested as much as desired. That is, a context may in turn contain other contexts
- Permit custom "find"
The custom "find" opens up the possibilities of:
- Dynamic lookup of words
- Case-insensitive lookup
- Using different lookup mechanism (hash, for instance)
Architecture
At the lowest level, a context is just a memory-area which stores some state information and pointers to other information. Each one has its own value of last, so that in fact each is an independent linked-list of (dictionary entries for) words.Invoking the context places it on top of the list of active contexts, the "search-order". The word (find) knows to search each context in the search-order, from most recently added to the least recently added. All active contexts will be searched until the word sought is found.
Invoking exit~ removes the most recently invoked context from the search-order, and next context in-order then becomes top-most, and will be searched first. Unlike ANS, there is no way to rearrange search order, nor is there any need to. It is possible to look for a word in any specific context, whether or not it is in the list of active contexts - as long as one can find that context.
Words
These words implement contexts under Reva:context: ( <name> -- )
Creates a new context, in the currently active context. Thus it is possible to "nest" contexts if that is desired.
context-name ( -- )
Makes that context "context-name" the active (top-most) one.
exit~ ( -- )
Pops the current context off the search-order. The prior context is now top-most.
~ ( -- )
The base context, with the core Reva words in it. It is always the first context, meaning it is the last one searched. So by putting a similarly named word in another context and using that context, one may override the word of the same name in the ~ context, temporarily.
in~ ( <context> <word> -- )
Look up <word> in <context> rather than using the normal search order. The <context> must be visible in the search-order.
to~ ( <context> <word> -- )
Transfer <word> from the current context to the named <context>
with~ ( <context> -- )
Puts <context> in the search-order, under the top-most. Essentially a "tuck" for contexts. This allows one to access the words in <context> without making new definitions appear in it.
without~ ( -- )
Undoes the effect of with~, basically like a "nip" for contexts.
reset~ ( -- )
Resets the search order to only have the ~ context
only~ ( <context> -- )
Makes <context> the only active context.
push~ ( -- )
Saves the current search order for a subsequent pop~
pop~ ( -- )
Restores the search order saved a previous push~
setfind~ ( xt <ctx> -- )
Set the word used for (find) in that context. This is an extremely powerful feature, and can be used, for example, to make a context use 'case-insensitive' matching, or to implement a 'dynamic lookup' for words.
.~ ( -- )
Lists the current search order (top of search order to the left)
.contexts ( -- )
Lists all contexts which have been defined, whether visible or not
xwords ( -- )
Shows all words in all contexts
reva ( -- )
Sets the "default" context order, which mostly allows one to ignore contexts in most cases.
Usage and recommendations
It is the Reva custom to prepend a tilde ~ to differentiate contexts from other words. This is not required, but is a recommended standard. Words which operate on contexts have a trailing tilde, whereas words prefixed with a tilde are contexts.As an example of how one might use contexts:
context: ~editor | We are still in the ~reva context. New words are still in ~reva variable a | in the ~reva context 34 a ! ~editor | now we have put "~editor" as the top context variable a | in the ~editor context, does NOT make the other one invisible 12 a ! exit~ | flipped back to the ~reva context | Test the results: a @ . | will give "34" in~ ~editor a @ . | will give "12" ~editor a @ . | prints "12" in~ ~ a @ | prints "34" exit~
Playing well with others
Libraries which create contexts or add words to contexts, should be careful to restore the search order to what it was before the library was loaded. For example, lib/floats implements the "~floats" context, so it calls "push~" before doing its job, and "pop~" when it is finished loading.This helps the programmer remain in complete control of access to the words; he or she can add a context as needed to the search list, and not worry about side-effects of loading libraries.
If you have private words, consider putting them in the "~priv" context, or in a "-private" context. So for example, "~floats-private" would be the place to put auxiliary words needed for the "floats" library, which might be useful to others as well. This clearly flags those words as "internal", yet allows access to them if needed.
For a real application, it is a good idea to create a context, say "~app", and use it for the application specific words.
Pre-existing contexts
Reva ships with several contexts "in core":- ~ - the "root" context, where the base Reva words exist
- ~reva - contains words only required for the Reva application
- ~os - os-specific or low-level os words
- ~util - various utility words
- ~strings - string handling
- ~io - file and console I/O
- ~sys - low-level Reva words which are not as generally useful
- ~priv - undocumented and/or helper words
- ~help - the help system, usually you won't access this directly
- ~doubles - double-cell math (filled in more by the library "math/doubles")
Various libraries add their own contexts. For example, "math/floats" has "~floats". "db/sqlite" has "~db", etc. See the documentation for each library to find out if you need to use a specific context to access the words it provides.