TweetFollow Us on Twitter

Pocket Forth
Volume Number:5
Issue Number:4
Column Tag:Forth Forum

Pocket Forth

By örg Langowski, MacTutor Editorial Board

Note: Source code files accompanying article are located on MacTech CD-ROM or source code disks.

“Public Domain Pocket Forth”

Imagine: a compiler that creates applications or desk accessories from the same source code, with only a one or two line change. Impossible? Read on. That compiler will work interactively, so that you can create code as you go, typing in routine after routine and checking them out on the fly. The applications will be very small, they can be run in a 32K partition. And, of course, the code will be fast.

I’m not joking, such a development system does exist. Even more unbelievable, it’s free. It’s now been several months since I downloaded PocketForth from the GEnie Forth Roundtable, and had a lot of fun with it since then. Lately, we even received a letter requesting a review of PocketForth, so I thought this a good opportunity to introduce you to the public domain Forth for the Macintosh.

PocketForth has been written by Chris Heilman, and unfortunately all the author leaves in the documentation is his Compuserve address (70566,1474); no mail address, no phone number. Since I am not on Compuserve (can’t access from here), I wasn’t able to contact him. Therefore, Chris, when you read this: my apologies that we couldn’t warn you. I hope you’ll appreciate this review, and please contact us if you have any comments.

Although PocketForth is completely public domain - even the sources are available upon request - we’d like to have the author’s authorization before putting his system on the source code disk. We are working on it, but the Forth compiler might come on a later disk. Meanwhile, you can download the system from GEnie or Compuserve; the Stuffit file is about 150K long and contains ample documentation and examples.

PocketForth implementation

PocketForth is based on FIG-Forth and a Forth for the 68000 described in Dr. Dobb’s Journal (G. Y. Fletcher, DDJ no. 123, January 1987). It uses a 16-bit stack and base-relative addressing with 32K offset, therefore the total code size is restricted to 32K bytes. The implementation uses subroutine threading with JSRs relative to the base pointer, which is kept in A3. An example illustrates this. Our test routine simply adds 3 and 4, outputs the sum and a space:

: test 3 4 + . 32 emit ;

this compiles to

 move.w #3,-(a6) ; literal 3
 move.w #4,-(a6) ; literal 4
 jsr  $E94(a3) ; +
 jsr  $BF0(a3) ; .
 move.w #32,-(a6); literal 32 
 jsr  $9FA(a3) ; emit
 rts

As you see, the code is dependent on the correct setup of A3. PocketForth must therefore execute in a locked block of memory, which is allocated at startup. The initialization code makes all the standard calls (_MoreMasters, _InitGraf, _InitFonts, _InitWindows, _InitMenus, _InitDialogs, _TEInit, _FlushEvents, _InitCursor), gets the PocketForth main code from the resource DICT ID=257 and jumps to its beginning. DICT 257 is the PocketForth dictionary and contains the names and executable code of all the known Forth words (this is in contrast to Mach2, which creates headerless code and the names are kept in a separate vocabulary). The DICT resource is locked, so that the block won’t move while PocketForth is executing. The startup sequence sets A3 to point to the beginning of the DICT block, initializes stack pointers and other things, and enters the Forth interpreter.

The PocketForth Dictionary

PocketForth dictionary entries have a header consisting of a name field and a link field. The name field is 4 bytes long, the first byte containing the name length, and the next three bytes the first three characters of the name. This means that the words compile and compute will have the same dictionary entry (caution!). The upper bit of the name field’s first byte is the immediate bit; when set, it indicates an immediate execution word. The link field, after the name field, is 2 bytes long and points to the previous dictionary entry. The link field is followed by the definition’s executable code.

Applications vs. desk accessories

You might have already guessed why PocketForth separates the setup code and the DICT resource. This way, application and DA ‘shells’ can be made that set up the environment so that the Forth code in the dictionary can be executed without making big changes between the two versions.

The shell is a dumb terminal window with an Apple, File and Edit menu. The window will accept keyboard input, which is interpreted by the Forth system. Files can be loaded with the word -->, and they will be normal text files, no block file business here. Text pasted from the clipboard will be interpreted just like keyboard input.

The application and the DA look exactly the same, and behave almost exactly the same. Forth code that creates a turnkey application will, if done correctly, create a ‘turnkey DA’ with only minor changes. This is achieved by accessing PocketForth’s system variables through a table using the word +md, which adds the offset of a ‘Mac Data’ block to the top of stack. This block is located at different positions in the application and the DA, and using +md lets you access the system variables transparently.

Examples of the variables pointed to by +md are the main window pointer, vectors to activate, update and mousedown handlers, a vector to an idle routine which is run once on each pass through the event loop (for the APPL) or when the accRun message is received (for the DA). The +md data block also contains an event table, which is a jump table to the event handlers for event types 0 to 15 (APPL) or 0 to 8 (DA). To change default event handling one installs new vectors in this table.

The Example

I rewrote one example from Palo Alto Shipping’s source code disk in PocketForth (Listing 1) to show you some of the techniques used in this Forth implementation. First, we have to redefine a couple of useful Mach2 words which are not present in PocketForth. pick and roll, 16-bit versions of the corresponding Mach2 words, are implemented in 68000 code. PocketForth has no assembler, but can compile 16-bit hex constants inline using the word ,$.

Toolbox access is also done using inline code. Before calling the trap, we must set up the A7 stack; like Mach2, PocketForth uses A6 for the parameter stack and A7 for the return stack. The words >r, 2>r, r> and 2r> are provided for moving 16- and 32- bit quantities to and from the A7 stack. Addresses of PocketForth variables and words are always 16-bit relative to the start of the dictionary, before calling a trap they must be converted to 32-bit absolute addresses with >abs.

The central part of the example is pretty standard Forth; PocketForth has no local variables, so we have to dup swap drip flip flop a little more than usual.

The last part of the example sets up the PocketForth system to start up automatically with the example program, saves the changes to the dictionary and quits. Make sure you have made a backup before you execute the example, the changes are irreversible. The way we make PocketForth run our program on startup is through the activate handler. We install a new activate vector in the event table which will execute our program’s start sequence on the first activate event; thereafter activate events will be ignored. The start sequence calls the word reflect which installs a vector to an idle routine that does the graphical display, and disables keyboard input by storing the null event vector at the keydown position of the event table. In order to execute the idle routine, the DA has to have the accRun flag set in its header. The correct value for the drvrFlags is $6400; change with ResEdit if necessary.

Chris Heilman gives another method to patch the Forth system with an autostart vector. He patches a JMP instruction into the initialization code in the dictionary. However, I was not able to find the correct patch position for the desk accessory, so I used the method I just described, which works for APPL and DA in the same way.

Speed

No review is complete without the results of the Sieve benchmark (Listing 2), so I’ll give them to you: 3.3 seconds for ten iterations of the standard benchmark (1899 primes). MacForth Plus takes the same time, 3.3 seconds, while Mach2 takes 1.9 seconds; therefore PocketForth compares very well with the two major Macintosh Forth systems. Note in the code that the word to access the loop index is r, not i as in the other Forths.

Summary

PocketForth comes in a 150K Stuffit file that contains: the application, the desk accessory, a demo application that has been created under PocketForth, source code for that demo and various other examples, including a floating point package, a mini-paint program and the Sieve benchmark. A manual and a glossary of Forth words is also contained in the package.

PocketForth has been designed to create compact applications and DAs; the maximum code size is restricted to 32K, anyway. However, it is amazing what can be done in so little space, given the compactness of Forth code; each routine call requires only 4 bytes. The example application is only 9K long, including bundle, menu and window resources, and the corresponding desk accessory takes only 8K. You can decrease the application’s partition size in Multifinder down to 32k without any problems.

PocketForth has its limitations, of course: restricted maximum size, few utilities, no built-in editor (I used McSink when I wrote this). There is no assembler, and I used the Mach2 assembler to write the machine code words. Well, there must be something that makes it worth paying for Mach2 or MacForth, I guess if you have a major project in Forth, you have to get a full development system, of course. But for creating ‘instant’ desk accessories, or small applications, or for just fumbling around with the machine and producing interesting hacks (or bombs, for that matter), PocketForth is just the ideal system.

Listing 1: ‘Reflections’ demo rewritten for Pocket Forth

( Reflections demo from Mach2 demo disk; rewritten )
( for PocketForth v.3 )
( J. Langowski / MacTutor Feb. 1988 )

( Compile this demo with a COPY of Pocket Forth or the )
( Pocket Forth DA; the dictionary will be irreversibly )
( changed to create a turnkey application / DA. )

( Note that the change required to compile this example ) 
( with the DA version consists only of a 1 line deletion; )
( see at the bottom of the listing. )

forget task
: task ;

: pick ( n -- dup stack item n levels down )
        ,$ 301E ( move.w [a6]+,d0)
        ,$ E380 ( asl.l  #1,d0 )
        ,$ 3D36 ,$ 0 ( move.w [a6,d0.w],-[a6] )
;

: roll ( n -- move up stack item n levels down )
        ,$ 2F02  (     move.l d2,-[a7] )
        ,$ 301E  (     move.w [a6]+,d0 )
        ,$ 6F16  (     ble.s   @1 )
        ,$ 5380  (     subq.l  #1,d0 )
        ,$ 3200  (     move.w  d0,d1 )
        ,$ 3F1E  ( @2  move.w [a6]+,-[a7] )
        ,$ 51C8
        ,$ FFFC  (     dbf     d0,@2 )
        ,$ 341E  (     move.w  [a6]+,d2 )
        ,$ 3D1F  ( @3  move.w  [a7]+,-[a6] )
        ,$ 51C9
        ,$ FFFC  (     dbf     d1,@3 )
        ,$ 3D02  (     move.w  d2,-[a6] )
        ,$ 241F  (     move.l  [a7]+,d2 )
;                ( @1  rts )

: range ( value lo hi -- flag ) 
        2 pick <  rot rot < or 0=
;         

: 4dup ( n1 n2 n3 n4 - n1 n2 n3 n4 n1 n2 n3 n4 )
 3 pick 3 pick 3 pick 3 pick 
;

4 +md constant wrect ( Pocket Forth main window )

2variable myport
: getport >abs 2>r ,$ A874 ; ( _GetPort )
: setport 2@ 2>r ,$ A873 ; ( _SetPort )
: cls wrect >abs 2>r ,$ A8A3 ; ( _EraseRect )

( QuickDraw Equates )
hex
8      constant PatCopy
B      constant PatBic
10     constant PortRect
decimal

( Window Size Variables )
variable        WTop
variable        WLeft
variable        WBottom
variable        WRight
variable        WWidth
variable        WHeight

( Positions     Velocities )
variable xx1    variable xx1dot
variable yy1    variable yy1dot
variable xx2    variable xx2dot
variable yy2    variable yy2dot

: GetWCoords ( -- )
        wrect       @  WTop    !
        wrect 2+    @  WLeft   !
        wrect 4 +   @  WBottom !
        wrect 6 +   @  WRight  !

        ( Calculate the current window width and height. )
        WBottom @ WTop  @ - WHeight !
        WRight  @ WLeft @ - WWidth  !  
;

( Erase the window and set the initial pen positions and velocities. 
)
: SetupReflect (  -  )
        cls
        GetWCoords
        WWidth  @ 3 /    xx1 !   3 xx1dot !
        WHeight @        yy1 !  -4 yy1dot !
        WWidth  @ 3 / 2* xx2 !   4 xx2dot !
        WHeight @        yy2 !  -3 yy2dot ! ;

( Draws a newline and leaves coords on stack. )
: NewCoords ( -- xx1 yy1 xx2 yy2 )
        ( Increment the line position. )
        xx1dot @ xx1 +!
        yy1dot @ yy1 +!
        xx2dot @ xx2 +!
        yy2dot @ yy2 +!

        xx1 @ 1 WWidth @ range 0=
        if xx1dot @ negate xx1dot ! then

        yy1 @ 1 WHeight @ range 0=
        if yy1dot @ negate yy1dot ! then

        xx2 @ 1 WWidth @ range 0=
        if xx2dot @ negate xx2dot ! then

        yy2 @ 1 WHeight @ range 0=
        if yy2dot @ negate yy2dot ! then 

        xx1 @ yy1 @ xx2 @ yy2 @
;

( Leaves 40 coordinate pairs on the stack and draws the 1st ten lines. 
)
: First20Lines (  -  )
        20 0 do
                PatCopy >r ,$ A89C ( _PenMode )
                NewCoords 4dup
                !pen -to
        loop ;

20 +md constant idlevector
: LinesAdvance (  -  )
                PatCopy >r ,$ A89C ( _PenMode )
                NewCoords 4dup
                !pen -to

                83 roll 83 roll 83 roll 83 roll
                PatBic >r ,$ A89C ( _PenMode ) 
                        ( and white out the n-21st line)
                !pen -to
;

‘ LinesAdvance constant LAdv

12 +md constant actVect
actVect @ constant actDefault

24 +md constant nullevent
nullevent 6 + constant keyvector
nullevent @ constant rien

: Reflect (  -  )
        SetUpReflect
        First20Lines cls
        LAdv idlevector !
        rien keyvector !  ;

variable flag  1 flag !
: start drop ( act/deact flag) 
        cls
        flag @ if 
                reflect 0 flag !
                begin ?terminal drop again
                ( leave out in DA version )
        then  ;
‘ start actvect !   
 save   ( CAUTION: changes dictionary irreversibly )

: bye ,$ A9F4 ( _ExitToShell )  ; bye

Listing 2: Sieve benchmark for PocketForth

( © Chris Heilman )
( Sleeve of Erastothanes )
( optomized for Pocket Forth with inline machine code )
9000 room - grow  ( provide for 9000 dictionary bytes )
forget task : TASK ;  decimal

( timer )
: START ( -- d ) 362 0 dl@ ;  ( get ‘ticks’ )
: T. ( sec -- ) s>d <# # 46 hold #S #> type ;  ( print sec.tenths )
: STOP ( d -- ) start 2swap dnegate d+ drop  6 / t. .” Seconds” ;

8190 constant SIZE
variable FLAGS size allot

( compile these 2 byte words inline )
: [DUP] ( n -- n n ) [ ‘ dup @ literal ] , ; 
 IMMEDIATE  ( equal to:  dup )
: [DROP] ( n -- ) [ ‘ drop @ literal ] , ; 
 IMMEDIATE  ( equal to:  drop )
: [1+] ( n -- n+1 ) [ ‘ 1+ @ literal ] , ; 
 IMMEDIATE  ( equal to:  1+ )

( compile machine code inline routines )
: R+ ( n -- n+r ) 12311 , 53590 , ; 
 IMMEDIATE  ( equal to:  r + )
: 0RC! ( -- ) 12311 , 16947 , 0 , ; 
 IMMEDIATE  ( equal to:  0 r c! )

: PRIME  flags size 1 fill
    0 size 0 DO
      flags r+ c@ IF
        3 r+ r+ [dup] r+ size < IF
          size flags + over r+ flags +
          DO  0rc! [dup]  +LOOP
        THEN [drop] [1+]
      THEN
    LOOP . .” primes” cr ;

: SIEVE  page  .”        The Sieve of Erastothanes” decimal
    cr  start  10 0 DO prime LOOP  beep
    cr  stop  cr .” Not too shabby, eh?”  cr ;

sieve

 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Macs Fan Control 1.4.7.0 - Monitor and c...
Macs Fan Control allows you to monitor and control almost any aspect of your computer's fans, with support for controlling fan speed, temperature sensors pane, menu-bar icon, and autostart with... Read more
Boom 2 1.5.2 - $14.99
Boom 2 is a system-wide volume booster and equalizer app that is designed especially for OS X 10.10 Yosemite. It comes with a smart interface, self-calibrates itself according to your Mac, offers... Read more
MacFamilyTree 8.1.3 - Create and explore...
MacFamilyTree gives genealogy a facelift: modern, interactive, convenient and fast. Explore your family tree and your family history in a way generations of chroniclers before you would have loved.... Read more
WhiteCap 6.6 - Visual plug-in for iTunes...
WhiteCap is a sleek and sophisticated music visualizer and screensaver that features futuristic, wireframe mesh visuals with dynamic backgrounds and colors. WhiteCap contains thousands of visual... Read more
VOX 2.8.14 - Music player that supports...
VOX just sounds better! The beauty is in its simplicity, yet behind the minimal exterior lies a powerful music player with a ton of features and support for all audio formats you should ever need.... Read more
Paparazzi! 1.0b2 - Make user-defined siz...
Paparazzi! is a small utility for OS X that makes screenshots of webpages. This very simple tool takes screenshots of websites which do not fit on one screen. You specify the desired width, minimal... Read more
Carbon Copy Cloner 4.1.13 - Easy-to-use...
Carbon Copy Cloner backups are better than ordinary backups. Suppose the unthinkable happens while you're under deadline to finish a project: your Mac is unresponsive and all you hear is an ominous,... Read more
TrailRunner 3.8.832 - Route planning for...
TrailRunner is the perfect companion for runners, bikers, hikers, and all people wandering under the sky. Plan routes on a geographical map. Import GPS or workout recordings and journalize your... Read more
VueScan 9.5.65 - Scanner software with a...
VueScan is a scanning program that works with most high-quality flatbed and film scanners to produce scans that have excellent color fidelity and color balance. VueScan is easy to use, and has... Read more
Adobe Illustrator CC 2017 21.0.2 - Profe...
Illustrator CC 2017 is available as part of Adobe Creative Cloud for as little as $19.99/month (or $9.99/month if you're a previous Illustrator customer). Adobe Illustrator CC 2017 is the industry... Read more

Stickman Surfer rides in with the tide t...
Stickson is back and this time he's taken up yet another extreme sport - surfing. Stickman Surfer is out this Thursday on both iOS and Android, so if you've been following the other Stickman adventures, you might be interested in picking this one... | Read more »
Z-Exemplar (Games)
Z-Exemplar 1.4 Device: iOS Universal Category: Games Price: $3.99, Version: 1.4 (iTunes) Description: | Read more »
5 dastardly difficult roguelikes like th...
Edmund McMillen's popular roguelike creation The Binding of Isaac: Rebirth has finally crawled onto mobile devices. It's a grotesque dual-stick shooter that tosses you into an endless, procedurally generated basement as you, the pitiable Isaac,... | Read more »
Last week on PocketGamer
Welcome to a weekly feature looking back on the past seven days of coverage on our sister website, PocketGamer. It’s taken a while for 2017 to really get going, at least when it comes to the world of portable gaming. Thank goodness, then, for... | Read more »
ROME: Total War - Barbarian Invasion set...
To the delight of mobile strategy fans, Feral Interactive released ROME: Total War just a few months ago. Now the game's expansion, Barbarian Invasion is marching onto iPads as a standalone release. [Read more] | Read more »
Yuri (Games)
Yuri 1.0 Device: iOS iPhone Category: Games Price: $3.99, Version: 1.0 (iTunes) Description: It's night. Yuri opens his eyes. He wakes up in a strange forest.The small, courageous explorer rides on his bed on casters in this... | Read more »
Space schmup Xenoraid launches on the Ap...
10Tons Xenoraid is out today on the App Store, bringing some high-speed space action to your mobile gadgets just in time for the weekend. The company's last premium title, another sci-fi game titled Neon Chrome, did quite well for itself, so... | Read more »
Star Wars: Force Arena Beginner's G...
Star Wars: Force Arena joined the populous ranks of Star Wars games on mobile today. It's a two-lane MOBA starring many familiar faces from George Lucas's famed sci-fi franchise. As with most games of this nature, Force Arena can be a little obtuse... | Read more »
Mysterium: The Board Game (Games)
Mysterium: The Board Game 1.0 Device: iOS Universal Category: Games Price: $6.99, Version: 1.0 (iTunes) Description: The official adaptation of the famous board game Mysterium! | Read more »
Sonny (Games)
Sonny 1.0.4 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0.4 (iTunes) Description: Reimagined for iOS, cult-hit RPG Sonny brings challenging turn-based combat that requires strategy and mastery of each new skill to... | Read more »

Price Scanner via MacPrices.net

CalcTape for macOS 1.2 Adding Machine App for...
schoettler Software has announced CalcTape 1.2, an update to their desktop calculator for macOS. When it comes to adding long columns of numbers, doing complex calculations or playing around with... Read more
New MacBooks And MacBook Pros WIth Kaby Lake...
Digitimes’ Joseph Tsai cites a Chinese-language Economic Daily News (EDN) report that unnamed market watchers are predicting Apple MacBook shipments to grow 10 percent in 2017, and projecting 15... Read more
New 2016 13-inch MacBook Pros on sale for up...
B&H Photo has the new 2016 13″ MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 13″ 2.9GHz/512GB Touch Bar MacBook Pro... Read more
New 15-inch Touch Bar MacBook Pros in stock a...
B&H Photo has the new 2016 15″ Apple Touch Bar MacBook Pros in stock today and on sale for up to $150 off MSRP. Shipping is free, and B&H charges NY sales tax only: - 15″ 2.7GHz Touch Bar... Read more
Opera Announces Neon Concept Browser For Mac
Opera is inviting users to get a glimpse of what Opera for computers could become with its Opera Neon browser concept. Each Opera Neon feature is described as “an alternate reality” for the Opera... Read more
Tellini Releases TabView 3.0 Missing Tool fo...
Tellini has announced the release of TabView 3.0. TabView has been the first macOS viewer for PowerTab tablatures. PowerTab is a well-known and widely adopted tablature editor for Windows systems and... Read more
13-inch 1.6GHz/128GB MacBook Air on sale for...
Overstock.com has the 1.6GHz/128GB 13″ MacBook Air on sale for $130 off MSRP including free shipping: - 13″ 1.6GHz/128GB MacBook Air (MMGF2LL/A): $869.99 $130 off MSRP Their price is the lowest... Read more
12-inch 32GB Space Gray iPad Pro on sale for...
B&H Photo has 12″ Space Gray 32GB WiFi Apple iPad Pros on sale for $55 off MSRP including free shipping. B&H charges sales tax in NY only: - 12″ Space Gray 32GB WiFi iPad Pro: $744.44 $55 off... Read more
9-inch 32GB Space Gray iPad Pro on sale for $...
B&H Photo has the 9.7″ 32GB Space Gray Apple iPad Pro on sale for $549 for a limited time. Shipping is free, and B&H charges NY sales tax only. Read more
Apple iMacs on sale for up to $120 off MSRP,...
B&H Photo has 21″ and 27″ Apple iMacs on sale for up to $120 off MSRP, each including free shipping plus NY sales tax only: - 27″ 3.3GHz iMac 5K: $2199 $100 off MSRP - 27″ 3.2GHz/1TB Fusion iMac... Read more

Jobs Board

*Apple* Retail - Multiple Positions (Multi-L...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
*Apple* & PC Desktop Support Technician...
Apple & PC Desktop Support Technician job in Stamford, CT We have immediate job openings for several Desktop Support Technicians with one of our most well-known Read more
*Apple* macOS Systems Integration Administra...
…most exceptional support available in the industry. SCI is seeking an Junior Apple macOS systems integration administrator that will be responsible for providing Read more
*Apple* Premier Retailer - Service Technicia...
DescriptionSimply Mac is the largest premier retailer for Apple products and solutions. At Simply Mac we are all Apple , all the time. Same products. Same prices. Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.