From: hawley@adobe.com (Steve Hawley)
Subject: Re: Stand-alone code segments in Forth
Followup-To: comp.lang.forth.mac
Organization: Adobe Systems Inc.
Date: Sat, 19 Dec 1992 19:27:58 GMT

In article <BzH7AK.5s7@news.cso.uiuc.edu>, schalk@symcom.math.uiuc.edu (Ken
Schalk) wrote:
> 
> 
>     I'm new to Forth and enjoying it immensely, but I have a question
> about stand-alone code segments, such as WDEFs and XCMDs.  Let me just
> say that I experienced in other languages (Pascal, C, C++, ...) and
> the Mac Toolbox, and have written both WDEFs and XCMDs in the past.
>     What I'm wondering is, is it possible to build such things with
> any of the Mac Forth incarnations?

>     My guess is that it probably hasn't been done, as I think it might
> be kind of painful to turn a Forth dictionary (or some subset thereof)
> into a stand-alone code resource.  However, I think it would be
> wonderful if it were possible.  Having written these things in the
> past, I think the concept of a WDEF in Forth is a beautiful thing.
> (Heck, once you had the basics laid out, you could churn out WDEF
> after WDEF all the time, leading to a distinctive look for your apps,
> albeit a degeneration of the interface standard. :-)

Actually, it's not really that hard depending on your architecture.
When I wrote SteveFORTH for the Mac several years ago, my main goal
was to produce a FORTH that had a kernel that was stand-alone and I/O
that was completely abstracted from the language.

The way I did this was to write a shell operating system in Think C.
The main() of SteveFORTH looks like this:

main()
{	
    MacInits();      /* InitGraf() etc. */
    GetDictionary(); /* load dictionary resource */
    MakeStack();     /* build the parameter stack */

    boot();          /* start execution */
    CleanUp();
}

Now imagine that we are writing a window definition function.  We could
just
do this:

pascal long main(varCode, theWindow, message, param)
short varCode;
WindowPtr theWindow;
short message;
long param;
{
    static short neverBeenCalled;
    long retval;

    SetUpRegisters(); /* do all the nasty a4/a5 mucking for globals */
    if (neverBeenCalled) {
        GetDictionary();
        MakeStack();
    }
    Push(varCode);
    PushLong(theWindow);
    PushLong(param);
    Push(message);

    boot();
    retval = PopLong();
    CleanUpRegisters();
    return retval;
}

In SteveFORTH there was a variable which was the address of the FORTH
function
to call on booting.  By default, it was a routine to make a window and
attach
standard input and output and call the interpretter, but you could easily
just
point it to your WDEF entry point:

ok ' myWDEF bootval !

and then execute the build application command from SteveFORTH's menu which
will build an application that you can extract the DICT resource and attach
to the application that will contain the above WDEF stub.

Here's how boot is defined:

boot()
{
    char *a; /* address of FORTH boot function */

    /* extract the address and add it to the base of the
     * dictionary.
     */
    a = DStart + *((short *)(DStart + BOOTVAL));
    asm {
        movem.l d0-d7/a0-a6,-(sp) /* save the world */
        move.l a,a0         /* copy the boot vector into A0 (scratch) */
        move.l stack,a6     /* set up parameter stack (and blow away a6) */
        move.l DStart,a3    /* set up dictionary base */
        move.l here,a2      /* load here */
        jsr (a0)            /* call boot function */
        move.l a6,stack     /* save stack */
        move.l a3,DStart    /* save dict base (could've moved!!) */
        move.l a2,here      /* save here */
        movem.l (sp)+,d0-d7/a0-a6 /* restore the world */
    }
}


Steve Hawley
hawley@adobe.com
--
"Did you know that a cow was *MURDERED* to make that jacket?"
"Yes.    I didn't think there were any witnesses, so I guess I'll have to
kill
 you too." -Jake Johansen
Newsgroups: comp.lang.forth.mac