oster@ucblapis.berkeley.edu (David Phillip Oster) (06/18/86)
Here's what you've been asking for, here is the source code to define structures in Forth. I first wrote this code almost two years ago, when I was in the process of writing my own implementation of Forth-83 for the Macintosh. Menu Clock is written in that Forth. ( Pascal Record Package,I ( David Phillip Oster 3/4/85 ) \ Structures in Forth are almost as simple as arrays in Forth. \ Here it is. (Note that the actual code, without the comments, is only 16 \ lines long.) \ This structure package is \ Copyright (c) 1985, 1986 David Phillip Oster. All Rights Reserved \ You may use it as you see fit except: \ 1 ) all copies of the source code of the package must contain \ this copyright message. \ 2 ) If you describe this idea you must give David Oster \ full credit for its invention. \ ****************** General Comments ********************* \ Structure: \ This file consists of: \ General Coments: this overview \ Implementation: the underlying implementation of the record package \ Example 1: Declaring some macintosh types. \ Example 2: Using those types to do some mac programming \ \ Use: \ This package defines two defining words, \ "RECORD" ( starts a pascal-like record-type definition) \ "ENDREC:" ( ends, and gives a name to the record-type) \ \ and also \ \ "SIZEOF(" ( takes a type name and returns the size fo that type.) \ \ and lastly: \ \ "MAKEREC:" ( record types are defined in terms of other \ record types. \ To start the system off, you need a more primitive way of \ creating record types. ) \ \ Features: \ Record-types can be used inside other record-types to declare \ field names. Record-types can also be used to declare variables in the \ dictionary of that type. \ \ The code generated by the package is optimized: field names that \ merely add 0 to the record base address generate no run-time code! \ \ Record-types, created with this package can be used in the definition of \ yet other records. Record-types can also be used to declare variables \ of that type. \ Field names are also defined by this package. Field names can be applied \ to record variables to give the address of the beginning of that field. \ \ Naming Conventions: \ field names start with a period. Record-Types, like all defining words, \ end with a colon. I pretty print against the right-edge, since the verbs \ in forth are on the right. \ \ Limitations: \ The Forth-83 vocabulary structure is NOT used, so you can apply field \ names for type A to a record of type B, and no-one but you will ever \ catch the mistake (this is no worse than most of Forth.) \ The underlying implementation of the record package should really be in \ a hidden vocabulary. \ Field names are just words in the vocabulary, so they should be unique. \ Some-one should extend this so that all the field names of a record \ are grouped in that record's "record-type vocabulary" \ using a record variable sets the "record-type vocabulary" \ this would allow a record type A to have a field named ".foo" and a \ second record-type B to have a field name ".foo" without B's definition \ overriding A's. (This package overrides.) \ \ ****************** The Structure package ****************** VARIABLE INRECORD ( Holds a flag - are we defining a record or a variable?) ( WALIGN - if you need it align to word boundary ) \ In Mac Pascal, successive byte sized fields are packed, but you \ skip a byte if you have an odd number of byte sized fields and the next \ field is larger than a byte. : WALIGN ( AmtUsed MySiz - AdjustUse MySiz ) DUP 1 = NOT IF SWAP 1+ [ HEX ] FFFE [ DECIMAL ] AND SWAP THEN ; ( DOOFFSETR - Runtime of a .Field name ) : DOOFFSETR DOES> ( adrRecord adrOffset - adrRecord+Offset ) @ + ; ( DOPASREC - run time actions for PascalType: ) \ two major cases: declaring a .Field, or declaring a var \ If first field, make .PascalField a compileTime noop : DOPASREC ( -- ) DOES> @ CREATE INRECORD @ IF WALIGN OVER ?DUP IF , DOOFFSETR ELSE -2 DP +! ['] NOOP @ , IMMEDIATE THEN + ELSE ALLOT THEN ; \ ****************** Stucture package top level ****************** \ begin a record definition : RECORD ( - 0 | intialize vars ) INRECORD ON 0 ; \ takes number of bytes, which is the size of the field : MAKEREC: ( n - ; name ) CREATE , DOPASREC ; \ interested in fields, not in the final record, so just end : ENDREC ( n - |Used when just defining fields) INRECORD OFF DROP ; \ create the record : ENDREC: ( n - ; name ) INRECORD OFF MAKEREC: ; \ takes a type-name from the input : SIZEOF( ( - n ;typename) ' >BODY @ STATE @ IF LITERAL THEN ; IMMEDIATE \ ****************** An example, some Macintosh structures ****************** ( Mac FontInfoRec Point record definitions ( 12/26/84 dpo) 4 MAKEREC: LINT: \ LongInt 2 MAKEREC: INT: \ Integer 1 MAKEREC: BOOL: \ Boolean 8 MAKEREC: Pattern: 32 MAKEREC: Bits16: 4 MAKEREC: RgnHandle: 4 MAKEREC: Handle: 4 MAKEREC: PTR: \ Ptr RECORD INT: .ASCENT INT: .DESCENT INT: .WIDMAX INT: .LEADING ENDREC: FontInfoRec: RECORD INT: .V INT: .H ENDREC: Point: RECORD Point: .topLeft Point: .botRight ENDREC: Rect: \ Other names for fields of rect: : .bottom .botright .v ; : .top .topLeft .v ; : .right .botright .h ; : .left .topleft .h ; RECORD PTR: .BASEADDR INT: .ROWBYTES RECT: .BOUNDS ENDREC: BitMap: \ ****************** Example, continued ****************** Point: SavePen SavePen GetPen 100 100 MoveTo SavePen .x @ SavePen .y @ LineTo Rect: 4Square : CopyPoint ( &Point &Point - ) SIZEOF( Point: CMOVE ; SavePen 4Square .topLeft CopyPoint SavePen 4Square .botRight CopyPoint 4Square .bottom 4 +! 4Square .right 4 +! 4Square FrameRect --- David Phillip Oster -- "The goal of Computer Science is to Arpa: oster@lapis.berkeley.edu -- build something that will last at Uucp: ucbvax!ucblapis!oster -- least until we've finished building it." U.S.Mail: David Oster Mosaic Codes Suite 1036 2000 Center St. Berkeley, Ca. 94704
oster@ucblapis.berkeley.edu (David Phillip Oster) (06/20/86)
Clarification of some funky forth: replace DP +! by ALLOT . (ALLOT is usually defined as : ALLOT DP +! ;) some of you asked about the defs of ON and OFF: : ON TRUE !; : OFF FALSE ! ; in Forth-83 0 CONSTANT FALSE -1 CONSTANT TRUE but any reasonable definition of true and false should work. --- David Phillip Oster -- "We live in a Global Village." Arpa: oster@lapis.berkeley.edu -- Uucp: ucbvax!ucblapis!oster -- "You are Number Six."