home .. forth .. colorforth mail list archive ..

Re: [colorforth] DOES> How is colorForth different from other Forths?


----- Original Message -----
>From: "Jeffrey Massung" <jma@xxxxxxxxx>
>To: <colorforth@xxxxxxxxxxxxxxxxxx>
>Sent: Friday, December 12, 2003 1:37 PM
>Subject: Re: [Re: [colorforth] (state) How is colorForth different from
>other Forths? / reply II private]

>If anyone with significant experience with colorForth could cover a >specific topic, I'd love one done on DOES> . While I haven't programmed >in colorForth yet, and perhaps won't, I do enjoy the theory behind it >and Machine Forth.

>DOES> is a word that I use throughout my Forth code and I feel is one >of the most powerful aspects of the language. colorForth doesn't have >it, but perhaps something equally as powerful?

I'm not an expert in ColorForth but I know some about DOES> .

Every DOES> child does the following: It puts an address on the stack, and it calls a routine. That's all it ever does, those two things are what all DOES> children do.

There are three things that would make it hard to code this efficiently in ANS Forth. The first is that you need the xt for the routine before the routine has been coded. The second is that you need the address that HERE will have later, before the code that uses it has been completed. The third is that you need a name, preferably the name of the latest CREATEd command. Preferably you want to patch the old header instead of make a new command with the same name, and there's no standard way to do that, except by using DOES> .

But the end result is just a child that essentially does

 LITERAL command ;

It won't be hard in general for you to do that, and easier than DOES> does it.

Make the routine first. That costs you nothing extra except the name which you might have a use for.

Collect the stack item however you like and save it as a literal. Compile the routine. End the definition. Would you like some syntactic sugar with that?

Say you want to make an array.

: ITEM ( u addr -- addr' )
   SWAP CELLS + ;  \ find a better way than SWAP ?  \   >R CELLS R> + ?

Now you pick the base address for your array and maybe give it a name.

: MY-ARRAY 2EF8 ;

And whenever you want to use it you can do ( n ) MY-ARRAY ITEM and you're set. Or if you want to save space you can do

: MY-ITEM ( u -- addr )
   MY-ARRAY ITEM ;

and then you have the same result you'd get from DOES> except that you got rid of all the syntactic sugar. You don't re-use the name (which means you don't need >BODY ) and you pick the address yourself. It isn't quite as simple to write as CREATE DOES> but you get to use whatever address you want, and you can use whatever routine you want without the extra overhead of DOES> ITEM ; . You don't even have to use an address. If you only want one constant instead of a data structure, you can do

: MY-CHILD ( i*x -- j*y )
   15 MY-ACTION ;

and you have something just like the result of DOES> except you don't need the @ to get the value. You can apply MY-ACTION to as many constants as you want.

You can of course make a deferred DOES> equivalent if you don't mind the late binding.

: MY-POINTER 19AD ;
: MY-LATE-BOUND-CHILD
   MY-POINTER @ MY-ACTION ;

You can point to any data structure you want to before you do MY-ACTION to it.

And for complete generality you can do

: MY-LATE-BOUND-ANYTHING
  MY-POINTER 2@ EXECUTE ;

You can point to any ( xt x ) pair and perform the xt with the x (usually an address) on the stack. I have never actually used this. It may be too powerful to have any actual use.

Anyway, if you want a word to make it easier to do "value routine" "literal compile," I expect you'll find something simpler and more flexible than DOES> . DOES> was optimised for an old Forth.

Sorry for all the ANSisms, I hope they make sense.


---------------------------------------------------------------------
To unsubscribe, e-mail: colorforth-unsubscribe@xxxxxxxxxxxxxxxxxx
For additional commands, e-mail: colorforth-help@xxxxxxxxxxxxxxxxxx
Main web page - http://www.colorforth.com