[net.lang.forth] Information Hiding in FORTH

tim@amdcad.UUCP (Tim Olson) (06/25/86)

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!"

ma168a@sdcc3.UUCP (John Wavrik) (06/26/86)

In article <12110@amdcad.UUCP>, tim@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

steve@jplgodo.UUCP (06/26/86)

In article <12110@amdcad.UUCP>, tim@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

rb@cci632.UUCP (Rex Ballard) (07/02/86)

In article <12110@amdcad.UUCP> tim@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.

pmy@uvacs.UUCP (07/07/86)

> 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!"

jimc@iscuva.UUCP (07/15/86)

> 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?"

toma@tekgvs.UUCP (Thomas Almy) (07/16/86)

In article <242@iscuva.UUCP> jimc@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

rb@cci632.UUCP (Rex Ballard) (07/21/86)

In article <622@uvacs.UUCP> pmy@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.