🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: net.lang.forth
Article #337

Re: Defining a structure in FORTH?

#337
From: Jeff Bartlett
Date: Wed, 18 Jun 1986 03:46
167 lines
5852 bytes
> I am very much a novice FORTH programmer, and I don't even have a good
> textbook to go by.  I recently purchased a FORTH for my Macintosh at home
> (MACH1, distributed by the Palo Alto Shipping Co.), and would like some
> advice.  Professionally I do a lot of work with LISP, and I would like to
> implement something similar to a `DEFSTRUCT' package in FORTH.  In other
> words, I'd like to be able to do something like:
> 
> 	DEFSTRUCT[ RECTANGLE
> 		   TOP    2
> 		   LEFT   2
> 		   BOTTOM 2
> 		   RIGHT  2 ]ENDSTRUCT
> 
> Which would automatically define the following:
> 
> 	8 CONSTANT RECTANGLE-SIZE
> 	: RECTANGLE-TOP@ ( a - n ) @ ;
> 	: RECTANGLE-TOP! ( n a - ) ! ;
> 	: RECTANGLE-LEFT@ ( a - n ) 2 + @ ;
> 	: RECTANGLE-LEFT! ( n a - ) 2 + ! ;
> 	: RECTANGLE-BOTTOM@ ( a - n ) 4 + @ ;
> 	: RECTANGLE-BOTTOM! ( n a - ) 4 + ! ;
> 	: RECTANGLE-RIGHT@ ( a - n ) 6 + @ ;
> 	: RECTANGLE-RIGHT! ( n a - ) 6 + ! ;
> 	: MAKE-RECTANGLE ( whatever code necessary to allocate 8 bytes
> 			   of variable storage and assign a dictionary
> 			   entry to the word which follows.  This I guess
> 			   would be implementation specific. ) ;
> 
> While I'm sure that this could be done by defining `DEFSTRUCT[' so that it
> constructs all of the necessary dictionary headers etc. at the bit and byte
> level, this would doubtless be complicated and not very portable.  I wonder
> then, if there is a higher level method of defining such a beast?  Any help
> (even "no that can't be done") would be appreciated.
> 
> Bruce Florman	-----------------------------	florman@rand-unix.ARPA

This should do what you want to do.  The idea is to create a screen
on-the-fly that contains the definitions, then just load 'em.

    999 constant (DEFSTRUCT-SCREEN) ( screen scratch area, site-dependant)
    0 variable (DEFSTRUCT-STATE)
    0 variable (DEFSTRUCT-OFFSET)
    0 variable (DEFSTRUCT-BYTES)
    0 variable (DEFSTRUCT-LABEL) 32 allot

    : (DEFSTRUCT-EMIT)  ( c -- )
	(DEFSTRUCT-SCREEN) block (DEFSTRUCT-OFFSET) @ + c! update
	(DEFSTRUCT-OFFSET) @ 1 + 
		dup b/buf > if ." DEFSTRUCT[ output too large" abort endif
	(DEFSTRUCT-OFFSET) !
	;

    : (DEFSTRUCT-TYPE) ( addr -- )
		count 0 do dup c@ (DEFSTRUCT-EMIT) 1 + loop drop ;
	
    : (DEFSTRUCT-LEADIN) ( -- )
	bl (DEFSTRUCT-EMIT)
	" : " (DEFSTRUCT-TYPE)
	(DEFSTRUCT-LABEL) (DEFSTRUCT-TYPE)
        '-' (DEFSTRUCT-EMIT)
        here (DEFSTRUCT-TYPE)
       ;

    : (DEFSTRUCT-PROFFSET) ( -- )
	bl (DEFSTRUCT-EMIT)
	(DEFSTRUCT-OFFSET) @ <# #S #> (DEFSTRUCT-TYPE)
	bl (DEFSTRUCT-EMIT)
	;

    : (DEFSTRUCT) ( -- )
	(DEFSTRUCT-STATE) @
		dup 0 = if
			0 (DEFSTRUCT-OFFSET) !
			0 (DEFSTRUCT-BYTES) !
			here (DEFSTRUCT-LABEL) here c@ cmove
			1 (DEFSTRUCT-STATE) !
		else dup 1 = if
			(DEFSTRUCT-LEADIN)
			" @ "                (DEFSTRUCT-TYPE)
			(DEFSTRUCT-PROFFSET)
			" + @ ; "            (DEFSTRUCT-TYPE)

			(DEFSTRUCT-LEADIN)
			" ! "                (DEFSTRUCT-TYPE)
			(DEFSTRUCT-PROFFSET)
			" + ! ; "            (DEFSTRUCT-TYPE)

			2 (DEFSTRUCT-STATE) !
		else dup 2 = if

			0 0 here number drop (DEFSTRUCT-BYTES) !+

			1 (DEFSTRUCT-STATE) !
		endif endif endif
        drop
     ;

    : (DEFSTRUCT-CLOSEUP)
	(DEFSTRUCT-PROFFSET)
	" constant "            (DEFSTRUCT-TYPE)
	(DEFSTRUCT-LABEL)       (DEFSTRUCT-TYPE)
	" -SIZE "               (DEFSTRUCT-TYPE)

	" : MAKE-"              (DEFSTRUCT-TYPE)
	(DEFSTRUCT-LABEL)       (DEFSTRUCT-TYPE)
	BL                      (DEFSTRUCT-EMIT)
	" <builds "             (DEFSTRUCT-TYPE)
	(DEFSTRUCT-PROFFSET)
	BL                      (DEFSTRUCT-EMIT)
	" allot does> ; "       (DEFSTRUCT-TYPE)
	" ;s "                  (DEFSTRUCT-TYPE)
     ;

    0 variable (strequal-flag)

    : strequal ( s1 s2 -- f )
	1 (strequal-flag) !
	count drop swap count 0 do
		2dup c@ swap c@ = if
			1+ swap 1+ swap
		else
			0 (strequal-flag) ! leave
		endif
	loop 2drop (strequal-flag) @ ;

    : DEFSTRUCT[ 
         0 (DEFSTRUCT-STATE) !
         begin
	    BL WORD
	    HERE " ]ENDSTRUCT" strequal not
         while
            (DEFSTRUCT)
         again
	     (DEFSTRUCT-CLOSEUP) (DEFSTRUCT-SCREEN) load
	    ; immediate

It's based on the fig-forth model, or what I remember of it.

This was pounded into the editor and has not be tested.
Everything except the string literals should be in upper case.
I don't have a reference handy so check the usage of
	'DO' '<#','#S','#>', 'cmove', 'number' etc...
(no expressed or implied warranty, blah, blah ....)

the generated code should look like this (except that it will span
	lines randomly) :


   : RECTANGLE-TOP@ 0 + @ ; : RECTANGLE-TOP! 0 + ! ;
   : RECTANGLE-LEFT@ 2 + @ ; : RECTANGLE-LEFT! 2 + ! ;
   : RECTANGLE-BOTTOM@ 4 + @ ; : RECTANGLE-BOTTOM! 4 + ! ;
   : RECTANGLE-RIGHT@ 6 + @ ; : RECTANGLE-RIGHT! 6 + ! ;
   8 CONSTANT RECTANGLE-SIZE : MAKE-RECTANGLE <BUILDS 8 ALLOT DOES> ; ;S


Hope this will help.  If you use this, please post your improved version
to the net.

For the versions of forth that load from text files, create a tempfile
and input it.

Jeff Bartlett
Center for Digital Systems Research
Research Triangle Institute		mcnc!rti-sel!jb

with generic_disclaimer; use generic_disclaimer;
Technical Details
Message-ID: <862@rti-sel.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!mcnc!rti-sel!jb
References: <364@randvax.UUCP>

Show Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!burl!ulysses!allegra!mit-eddie!genrad!decvax!mcnc!rti-sel!jb
From: jb@rti-sel.UUCP (Jeff Bartlett)
Newsgroups: net.lang.forth
Subject: Re: Defining a structure in FORTH?
Message-ID: <862@rti-sel.UUCP>
Date: Tue, 17-Jun-86 23:46:01 EDT
Article-I.D.: rti-sel.862
Posted: Tue Jun 17 23:46:01 1986
Date-Received: Thu, 19-Jun-86 19:41:05 EDT
References: <364@randvax.UUCP>
Distribution: net
Organization: Research Triangle Institute, NC
Lines: 167