Path: utzoo!utgpu!news-server.csri.toronto.edu!clyde.concordia.ca!uunet!aplcen!uakari.primate.wisc.edu!zaphod.mps.ohio-state.edu!wuarchive!mit-eddie!uw-beaver!ubc-cs!alberta!myrias!aunro!apss!ncc!idacom!rob From: rob@idacom.uucp (Rob Chapman) Newsgroups: comp.lang.forth Subject: ... and zen there were objects. Message-ID: <1990Aug7.081509.2315@idacom.uucp> Date: 7 Aug 90 08:15:09 GMT Organization: IDACOM Electronics Ltd. Lines: 161 I did a paper about 3 years ago on adding structure defining words to Forth much in the way of the C struct{} (Roch'87). I designed the language for this extension with a few prototypes and a lot of gut feel about how I would like to use the words. Following Forth ideals, I desired to keep it simple (in implementation and in definition) as well as extendable. I implemented it twice and used it with a group of programmers to build a user interface toolkit. Then I thought about if for 3 years. I was going to include it in botForth if I could make it simple enough yet very powerful. A co-Forther, Andrew Scott, suggested that it would be nice to have a zen version of structures. This inspired the desire to seek a simple way. That night I prototyped a very simple set of words. It seemed to be what I was looking for. Only two words were needed. But it still didn't seem powerful enough. Suddenly I had an impulse to replace all occurances of the word structure with the word object and all the occurances of access with method. All of a sudden the code seemed to grow in ability. Before, I had used the structure words to define memory templates. Now, I could define more than just memory objects, they could be more abstract like a window or a file etc. What follows is an edited version of what I presented at one of our weekly FUG (Forth Users Group) gatherings. I still consider it raw code but it is amusing what can be done with 2 level defining words and by forming a link list of compilers. Interestingly the link listing allows a method to inherit objects. At the bottom, I've included a glossary of some words from botForth. ( ==== Excerpt from FUG Aug 2 1990 ==== ) Objects in botForth Rob Chapman Object Oriented Programming (OOP) employs the notion of objects and methods as a programming abstraction. By defining the two words OBJECT and METHOD, we can explore this programming paradigm. OBJECT is used to create objects which have three properties: 1. INSTANCE - creates a memory space for an object. 2. ELEMENT - used to define the memory elements of an object. 3. CAST - provide a context for determining which method to use. METHOD is used to define a method of dealing with an object. In OOP, like English, one word may be used in many different contexts. This means that the word OPEN could be a method to open windows and files; + could be a method to operate on floating point or complex numbers or as many objects as defined. In fact, it might be possible to create a smaller set of words to work with, for programming, by applying OOP to the whole dictionary (imagine a one screen WORDS). ( ==== Object internals ==== ) 0 VARIABLE object ( points to current object ) : +BYTES ( n -- ) object @ +! ; : #BYTES ( -- n ) object @ @ ; ( ==== Properties of Objects ==== ) : CAST ( object -- ) object ! ; : INSTANCE ( object -- ) ( inst -- a ) @+ \ LITERAL CAST ; : ELEMENT ( object -- ) ( a \ element -- a+ ) @ DUP CAST @ \ LITERAL ' + ?COMPILE ; ( ==== Object Builder ==== ) NO VARIABLE in-object ( flags whether an object is being built ) : OBJECT ( -- ) YES in-object ! ( object -- ) compile @ IF CAST ELSE in-object @ IF ELEMENT ELSE INSTANCE THEN ENDIF ; : END-OBJECT ( -- ) NO in-object ! ; ( ==== Method Builder ==== ) : METHOD ( default \ method -- ) ( handle -- ) @+ SWAP object @ = IF @ ?COMPILE ELSE 4 + @ EXECUTE ENDIF ; ( ===== Object definitions ===== ) ( ==== No method error message ==== ) : NO-METHOD ( -- ) ." Sorry, method not defined for current object. " ERROR ; ( ==== Memory Objects ==== ) OBJECT BYTE> 1 +BYTES ' NO-METHOD ' C@ METHOD GET ' NO-METHOD ' C! METHOD PUT ' NO-METHOD ' C+! METHOD +PUT END-OBJECT OBJECT WORD> BYTE> >UPPER ( motorola-ish ) BYTE> >LOWER ' GET ' @ METHOD GET ' PUT ' ! METHOD PUT ' +PUT ' +! METHOD +PUT END-OBJECT ( ==== Mathematical objects ==== ) OBJECT INTEGER> 2 +BYTES ' NO-METHOD ' + METHOD ADD ' NO-METHOD ' - METHOD SUB ' NO-METHOD ' * METHOD MUL ' NO-METHOD ' / METHOD DIV END-OBJECT OBJECT FLOAT> INTEGER> >MANTISSA INTEGER> >EXPONENT ' ADD ' F+ METHOD ADD ' SUB ' F- METHOD SUB ' MUL ' F* METHOD MUL ' DIV ' F/ METHOD DIV ' NO-METHOD ' FSIN METHOD SIN END-OBJECT ( ==== Environmental Objects ==== ) OBJECT TIME-STAMP> 6 +BYTES ' ADD ' TSTAMP_ADD METHOD ADD ' SUB ' TSTAMP_SUB METHOD SUB END-OBJECT OBJECT WINDOW> BYTE> >COL BYTE> >ROW ' NO-METHOD ' OPEN_WINDOW METHOD OPEN END-OBJECT OBJECT FILE> ... ' OPEN ' OPEN-FILE METHOD OPEN END-OBJECT ( ==== Excerpt from botForth Glossary: 32-bit figForth interface ==== ) : compile ( -- a ) STATE ; : COMPILE ( cfa -- ) , ; : ?COMPILE ( cfa -- ) compile @ IF COMPILE ELSE EXECUTE ENDIF ; : \ ( -- ) [COMPILE] [COMPILE] ; IMMEDIATE : ' ( -- cfa ) \ ' ' CFA CFA ?COMPILE ; IMMEDIATE : @+ ( a -- n \ a+ ) DUP @ SWAP 4 + ; Note to the casual user of [COMPILE] (or \): I prefer to use \ to force a compile on the next word. But I find it clearer to do the equivelant using ' and EXECUTE. For instance: I prefer \ LITERAL but to explain what that phrase means, its becomes clear when written as ' LITERAL EXECUTE.