[comp.lang.forth] Pascal-like records in FORTH

ns@gnome.cs.cmu.edu (Nicholas Spies) (08/04/87)

Here is some simple (perhaps trivial) code that might be useful:
The following enable the definition of "records" in FORTH, which have
two properties; the record name returns the length of the record it
names (in bytes), useful for ALLOT and such; the field words will, when
given the start address of an instantiated record, return the address
of the field relative to that location. 

This implementation assumes your FORTH does not pass stuff on the stack
when compiling, because END-RECORD needs to have a valid address to store
the final byte count in the word defined by RECORD. If stuff IS passed on
the stack, just use [ and ] to arrange it so that HERE 0 are intact after
RECORD executes... 

------- cut here ---------
( Records and Field Offsets )

( Words to create words that add offset to start address, by field type: )

: RECORD ( -- here 0 ) CREATE HERE 0 DUP , DOES> @ ; ( create record header)
	
: END-RECORD ( addr bytecount -- ) SWAP ! ;	( store length in record )

( Defining word to create field-offset defining words ) 

: FIELD ( length -- ) CREATE , DOES> @ CREATE SWAP DUP , + DOES> @ + ;

( Sample FIELD words ... 
	1 	FIELD Byte:
	2 	FIELD Int:
	4 	FIELD Long:
	4 	FIELD Ptr:
	4 	FIELD Handle:
	4 	FIELD Point:
	8 	FIELD Rect:
	8	FIELD Pattern:
	Etc...
)
( Sample record, particularly useful for Mac programming...
RECORD Rectangle
	Int: +top
	Int: +left
	Int: +bottom
	Int: +right
END-RECORD
)
( Sample usage ... )
(
	Create aRect Rectangle ALLOT
	10 aRect +top  !
	20 aRect +left !
	aRect +top  @ 20 + aRect +bottom !
	aRect +left @ 30 + aRect +right  !	
)
( RECORDs must be defined in execute mode, obviously)
( Error-checks could, and probably should, be added )

oster@dewey.soe.berkeley.edu (David Phillip Oster) (08/05/87)

In article <49@gnome.cs.cmu.edu> ns@gnome.cs.cmu.edu (Nicholas Spies) writes:
...
>The following enable the definition of "records" in FORTH, which have
>two properties; the record name returns the length of the record it
>names (in bytes), useful for ALLOT and such; the field words will, when
>given the start address of an instantiated record, return the address
>of the field relative to that location. 
...
>RECORD Rectangle
>	Int: +top
>	Int: +left
>	Int: +bottom
>	Int: +right
>END-RECORD
...

Note that this record package isn't as good as the one I posted last week.
In my package, you would say:

2 MAKEREC: Int:
RECORD
	Int: +top
	Int: +left
	Int: +bottom
	Int: +right
ENDRECT: Rect:

Then, two declare a rectangle or type rect, you would say:

Rect: RectVariable

Now here is the critical difference: In my record package, records can be
used to define other records in addition to defining variables. You can
now also say:

RECORD
  Rect: +bound
  Int:  +color
ENDREC: ColoredRec:


and you've created a record of type colored rect. If you want the size,
you just say SIZEOF< RECT:  This works in both interpreter and compiler
mode.

--- David Phillip Oster            --My Good News: "I'm a perfectionist."
Arpa: oster@dewey.soe.berkeley.edu --My Bad News: "I don't charge by the hour."
Uucp: {seismo,decvax,...}!ucbvax!oster%dewey.soe.berkeley.edu