Information Hiding in FORTH

4 views
Skip to first unread message

Tim Olson

unread,
Jun 25, 1986, 12:35:47 PM6/25/86
to
I have been recently thinking of a way to implement something like the
'C' static scoping type in forth. This would allow a word or group of
words to use a VARIABLE without letting the VARIABLE be visible outside
the group; something like:

: random-package ;

VARIABLE randval

: init-rand ( seed -- )
randval ! ;

: rand ( range -- rand# )
randval @ 21709 + 15273 * randval !
mod ;

HIDE randval

(No flames on the "randomness" of this random package, please :-)

HIDE is a word which, like tic ('), searches the dictionary for the
target word. HIDE also keeps a trailing pointer to the previous
word in the dictionary. When it finds the target word in the dictionary,
it takes it out of the dictionary search path by changing the previous
word's next pointer to point to the word following the target word.
This allows a VARIABLE or procedure word to be used normally in a
"package" and then be hidden from subsequent definitions.

a) Is this a useful construct, or is it the attempt of an
admittedly neophyte forth programmer (me) to force
other language ideas onto forth?

b) Can HIDE be written in forth, or must it be written in
assembly language?

c) Is there another (easier) way to do this that I am not
aware of?

Tim Olson
Advanced Micro Devices
ihnp4!amdcad!tim

no.6: "What do you want?"
no.2: "Information."
no.6: "You won't get it!"

John Wavrik

unread,
Jun 26, 1986, 1:33:35 PM6/26/86
to
In article <12...@amdcad.UUCP>, t...@amdcad.UUCP (Tim Olson) writes:
> I have been recently thinking of a way to implement something like the
> 'C' static scoping type in forth. This would allow a word or group of
> words to use a VARIABLE without letting the VARIABLE be visible outside
> the group;
>
> c) Is there another (easier) way to do this that I am not
> aware of?

When a name is re-used in Forth, the earlier
definition remains in the dictionary and is automatically used
by all words compiled when it was active. You can have many
variables named X -- and all will be, in effect local.
The problem comes if you would later like to refer to a variable
(or other object) that has been "covered". One way to do this
(absolutely against standards!) is to define a word ZAP
which locates the name field of a word and changes the
length byte to zero (make sure to preserve the higher
bits if necessary); or the first character of the name
to ascii 0; or in any other way destroys the name field
so that the word will not be found in a dictionary
search [the best change is system dependent].
Vocabularies can also be used to equip sub-applications
with special names without destroying access to previous
words with the same name.
Some Forth systems (e.g. MMS-Forth) provide for a
temporary dictionary area used only during compilation.
Words can have their name fields in the temporary area.
This creates local words -- with a saving of space in
the main dictionary (local words have no headers and
are not linked into the dictionary when the temporary
area is deleted - but their body is left in the dictionary).
There have been some experiments in Forth syntax
in which stack manipulation is eliminated by making
all arguments to a word into named local variables
(whose scope is just the word being defined). See
Dr. Dobbs journal of a few years ago.

--John J Wavrik
Math Dept - UCSD
..ucbvax!sdcsvax!sdcc3!ma168x

st...@jplgodo.uucp

unread,
Jun 26, 1986, 1:55:15 PM6/26/86
to
In article <12...@amdcad.UUCP>, t...@amdcad.UUCP (Tim Olson) writes:
> [ summary: a way of hiding a word to make its scope local is to fiddle
> with the link pointers and remove it from the dictionary chain]

I think an easier way of doing this is to use the sequence

' WORD-TO-HIDE NFA HEX 20 TOGGLE

This will set the 'smudge' bit in the word's name length field and hide it
quite nicely. It also doesn't require you to address into the header which
is prohibited in the Forth '79 standard.

Another way of doing this is by putting the 'local' word in a vocabulary
used by the package you are building. Then it will be visible anytime you
want it and invisible when you don't want it. My assembler uses words like
[ and ] for addressing modes. These are normal Forth words as well. When
I am using the assembler, I set the context to ASSEMBLER and the assembler
definitions for these words become visible. When I end a CODE definition,
I set the context back to FORTH and the normal definitions become visible.

--

...smeagol\ Steve Schlaifer
......wlbr->!jplgodo!steve Advance Projects Group, Jet Propulsion Labs
....logico/ 4800 Oak Grove Drive, M/S 156/204
Pasadena, California, 91109
+1 818 354 3171

Rex Ballard

unread,
Jul 2, 1986, 10:31:08 AM7/2/86
to
In article <12...@amdcad.UUCP> t...@amdcad.UUCP (Tim Olson) writes:
>I have been recently thinking of a way to implement something like the
>'C' static scoping type in forth. This would allow a word or group of
>words to use a VARIABLE without letting the VARIABLE be visible outside
>the group;

> c) Is there another (easier) way to do this that I am not
> aware of?

If you have '83, you might wish to look at the finer points of
vocabulary and context words. It is possible to create "statics"
this way. This feature is often under-used, but useful.

p...@uvacs.uucp

unread,
Jul 7, 1986, 4:11:36 PM7/7/86
to
> I have been recently thinking of a way to implement something like the
> 'C' static scoping type in forth. This would allow a word or group of
> words to use a VARIABLE without letting the VARIABLE be visible outside
> the group; something like:
>
> : random-package ;
>
> VARIABLE randval
>
> : init-rand ( seed -- )
> randval ! ;
>
> : rand ( range -- rand# )
> randval @ 21709 + 15273 * randval !
> mod ;
>
> HIDE randval
>
> (No flames on the "randomness" of this random package, please :-)
>
> HIDE is a word which, like tic ('), searches the dictionary for the
> target word. HIDE also keeps a trailing pointer to the previous
> word in the dictionary. When it finds the target word in the dictionary,
> it takes it out of the dictionary search path by changing the previous
> word's next pointer to point to the word following the target word.
> This allows a VARIABLE or procedure word to be used normally in a
> "package" and then be hidden from subsequent definitions.
>
> a) Is this a useful construct, or is it the attempt of an
> admittedly neophyte forth programmer (me) to force
> other language ideas onto forth?

Yes, i think this is a useful construct. It'd be nice too, if it
would "collapse" the now-useless word header to regain some dictionary
space. Of course, it would also have to relocate everything defined after
the target word. Could be tricky!

> b) Can HIDE be written in forth, or must it be written in
> assembly language?

I haven't played with FORTH in a long time, but i'm fairly certain that
it could be used to implement HIDE.

> c) Is there another (easier) way to do this that I am not
> aware of?

You could also corrupt the name field (e.g. blank fill it) to make the
word lexically unrecognizable. I think the pointer-shifting scheme is better
though, as it removes the word from the search stream altogether.

--

Pete Yadlowsky University of Virginia, Academic Computing Center
UUCP: decvax!mcnc!ncsu!uvacs!pmy
CSNET: pmy@virginia

"If ya can't stand the heat ... it's too hot!"

ji...@iscuva.uucp

unread,
Jul 14, 1986, 7:54:42 PM7/14/86
to
> I have been recently thinking of a way to implement something like the
> 'C' static scoping type in forth. This would allow a word or group of
> words to use a VARIABLE without letting the VARIABLE be visible outside
> the group; something like:

I believe map-Forth (Michael A Perry's version for my old CompuPro 68000)
included the words:

INTERNAL
<<boring and/or dangerous words to be hidden here>>
EXTERNAL
<<the visible stuff>>
MODULE (actually does the work)

I recall that both INTERNAL and EXTERNAL merely left addresses on the
data stack, and that MODULE patched the vocabulary search chain to
miss the internals. Woe be unto him whose internal or external definitions
which (on purpose or not) swallowed any of the data stack or left any extra!
Other than this caveat, I thought the idea and the implementation were
really first-class -- only a tiny bit of code.

As a side note, compressing the headers might not always be a good
idea, since the same Forth package had a tracer (hooked into NEXT) that
printed out the names of the currently executing words and the top few
values on the stack. I had a few words with headers missing that always
screwed up the trace output.

--

+----------------+
! II CCCCCC ! Jim Cathey
! II SSSSCC ! ISC Systems Corp.
! II CC ! Spokane, WA
! IISSSS CC ! UUCP: ihnp4!tektronix!reed!iscuva!jimc
! II CCCCCC ! (509)927-5757
+----------------+
"With excitement like this, who is needing enemas?"

Thomas Almy

unread,
Jul 16, 1986, 10:03:41 AM7/16/86
to
In article <2...@iscuva.UUCP> ji...@iscuva.UUCP (Jim Cathey) writes:
>> I have been recently thinking of a way to implement something like the
>> 'C' static scoping type in forth. This would allow a word or group of
>> words to use a VARIABLE without letting the VARIABLE be visible outside
>> the group; something like:
>
>I believe map-Forth (Michael A Perry's version for my old CompuPro 68000)
>included the words:
>
>INTERNAL
> <<boring and/or dangerous words to be hidden here>>
>EXTERNAL
> <<the visible stuff>>
>MODULE (actually does the work)
>
>I recall that both INTERNAL and EXTERNAL merely left addresses on the
>data stack, and that MODULE patched the vocabulary search chain to
>miss the internals. Woe be unto him whose internal or external definitions
>which (on purpose or not) swallowed any of the data stack or left any extra!

Which caused me to define these as so:

: INTERNAL LATEST 12543 ;

: EXTERNAL 12543 <> ABORT" Where is INTERNAL?"
LATEST N>LINK
25314 ;

: MODULE 25314 <> ABORT" Where is EXTERNAL?"
! ;


(This code will not work for Laxen & Perry F83 because of the hashed
vocabularies)

My current favorite technique (because it allows referencing the hidden words)
is a function which moves a word into a different vocabulary.

FooVoc DEFINITIONS BarVoc REVOC FooBar

moves word FooBar from vocabulary BarVoc to vocabulary FooVoc.

The implementation is straightforward, but is very system dependent.

Tom Almy
Tektronix

Rex Ballard

unread,
Jul 21, 1986, 12:08:34 AM7/21/86
to
In article <6...@uvacs.UUCP> p...@uvacs.UUCP writes:
>> I have been recently thinking of a way to implement something like the
>> 'C' static scoping type in forth. This would allow a word or group of
>> words to use a VARIABLE without letting the VARIABLE be visible outside
>> the group; something like:
>>
>> HIDE randval

>>
>> HIDE is a word which, like tic ('), searches the dictionary for the
>> target word. HIDE also keeps a trailing pointer to the previous
>> word in the dictionary.

There are actually two different techniques that can be used.

>> a) Is this a useful construct, or is it the attempt of an
>> admittedly neophyte forth programmer (me) to force
>> other language ideas onto forth?

>Yes, i think this is a useful construct.

So useful in fact, that it has already been done as a part of the language.

>> b) Can HIDE be written in forth, or must it be written in
>> assembly language?

>I haven't played with FORTH in a long time, but i'm fairly certain that
>it could be used to implement HIDE.

As I said, there are two ways to do this. The easiest is to use "Smudge".

>> c) Is there another (easier) way to do this that I am not
>> aware of?
>
>You could also corrupt the name field (e.g. blank fill it) to make the
>word lexically unrecognizable. I think the pointer-shifting scheme is better
>though, as it removes the word from the search stream altogether.

This is almost exactly what "smudge" does. The MSB of the first byte in the
name field can be used to fool ' (tick) into missing the definition, subsequent
smudges to an already existing definition toggle the bit.

An extension of the "smudge" is the "vocabulary" or "context" word. In these
cases, the NFA can be use to remove/enable an entire group of words from
the the vocabulary. For example, when you use the "editor" word, the
editor vocabulary "overrides" the forth definitions of the same name.
If you want the original forth definitions, just type "forth", and you
are back to the basic vocabulary. Your forth documentation should give
more explanation of VOCABULARY, CONTEXT, CURRENT, and DEFINITIONS.

Steve Willner

unread,
Jul 22, 1986, 1:49:08 PM7/22/86
to
>
>You could also corrupt the name field (e.g. blank fill it) to make the
>word lexically unrecognizable. I think the pointer-shifting scheme is better
>though, as it removes the word from the search stream altogether.
>
> This is almost exactly what "smudge" does. The MSB of the first byte in the
> name field can be used to fool ' (tick) into missing the definition, subsequent
> smudges to an already existing definition toggle the bit.
>
Better be careful here; this technique is highly implementation
dependent. The MSB is used as the precedence bit in many
implementations, but the next lower bit may be available. Also, a single
word will generally not toggle the bit, because the second time "smudge"
is used, it will not find the word that was previously smudged. Our
particular implementation of Forth (for the Data General Nova series - I
guarantee that yours is different!) uses the word LOCAL to smudge a
definition and GLOBAL to "unsmudge".

Another use of the "smudge" technique is to hide old definitions. This
is useful in our case because we use overlays, but it may also be useful
if you have many source files that are mixed and matched to make long
programs. For example:
: TODAY original definition ;
( lots of code, several source files, overlays, branch vocabularies, etc.)
: TODAY new definition, may include the existing TODAY ;
LOCAL TODAY LOCAL TODAY ( smudges both versions)
GLOBAL TODAY ( unsmudges only the later version)
Now if I'm in the wrong vocabulary and type TODAY, I'll get an error
message rather than the old version.

It should be very easy to write LOCAL in Forth, e.g.
: LOCAL ', 4 - DUP @ BITMASK @ OR SWAP ! ;
where 4 should be replaced by the difference (in your implementation)
between the address
returned by ', and the word you want to smudge and BITMASK is a variable
containing the smudge bit pattern. GLOBAL is much harder to write unless
you have access to the more primitive words used by ' or [']. (Send
e-mail if you want to know how we do it.) I hope this is helpful.
--

-------------------------------------------------------------------------
Steve Willner Phone 617-495-7123 Bitnet: willner@cfa1
60 Garden St. FTS: 830-7123 UUCP: willner@cfa
Cambridge, MA 02138 USA Telex: 921428 satellite cam

Reply all
Reply to author
Forward
0 new messages