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