Forth like interpreter

Samuel A. Falvo II kc5tja at garnet.armored.net
Sun Mar 12 05:37:12 EST 2000


In article <kcPy4.21122$W5.318062 at typhoon.nyroc.rr.com>, Darrell wrote:
>Nothing like graphics and a cool subject to really impress! Wonder if Forth
>interpreters are like one of the first software life forms to take hold in
>new environments?

Almost unanimously, they are.  Want to see a great Forth interpretter?  Here
it is, in x86 assembly:

	LODSD
	JMP	EAX

You sure can't beat that.  And if you're a real speed demon, you could do
something like this:

	MOV	EAX,[ESI]
	ADD	ESI,4
	JMP	EAX

More memory used, but faster too.  Now, a Forth definition becomes the
following:

	; : MyWord word1 word2 word3 ;

MyWord:	CALL	Do_Colon
	DD	word1
	DD	word2
	DD	word3
	DD	__exit__

Since the "virtual" instruction pointer is kept in the ESI register, and not
the PC, we implement Do_Colon as follows:

Do_Colon:
	; new virtual PC is already on the stack for us because of the
	; subroutine call in the word being executed.
	
	MOV	-4[EBP],ESI
	SUB	EBP,4
	POP	ESI
	MOV	EAX,[ESI]
	ADD	ESI,4
	JMP	EAX

And finally,

__exit__:
	MOV	ESI,[EBP]
	ADD	EBP,4
	MOV	EAX,[ESI]
	ADD	ESI,4
	JMP	EAX

And there you have it.  A complete threaded, interpretted environment with
which you can run most any Forth code with.  This, of course, all assumes
Direct Threaded code forms.  There are also minor variations on this
technique, such as indirect threaded, and for those which allow intermixing
of assembly language and Forth compiled code within a colon-definition
(e.g., "in-line assembly"), there's subroutine threading.

Contrary to popular belief, subroutine threading is slower than direct
threading on most processor architectures (at least it WAS -- modern CPUs
probably narrow, or even eliminate, the gap with their branch prediction
logic).  For a detailed reason as to why this is/was, feel free to ask the
question in comp.lang.forth.

>I think Forth hackers have be dealing with continuations for years. Task
>schedulers swap out the (dataStack, returnStack, pc) and you have threads.

Well, they swap pointers to these data structures -- they don't actually
swap out the structures themselves.  :)  And many task switchers also swap
out the CPU registers too.

>Want a continuation, make a copy of these data structures and save them.

>From what I've learned of continuations on this group and elsewhere, not
quite.  A continuation represents a flow of control, NOT DATA STATE.  So
really what you'd be doing is swapping out the return stack and the CPU
registers ONLY -- the data stack is left untouched.

Also, implementing continuations in a language like Forth would be a living
hell so severe that Satan wouldn't want to approach it.  The reason is that
continuations require the use of garbage collection.  Forth, being a static
and typeless language, and incapable of distinguishing pointers from normal
integers, does not retain enough state to offer garbage collection.  A
conservative garbage collector has been written by Anton Ertl for Forth
(GForth in particular), based on a Boehm collector.  He says that the
results are, "So so."  The very nature of the Forth dictionary itself makes
it very difficult to garbage collect things.

-- 
KC5TJA/6, DM13, QRP-L #1447
Samuel A. Falvo II
Oceanside, CA



More information about the Python-list mailing list