Home

Thinking Forth - pdf

image

Contents

1. How quickly things get complicated In this situation if both the current and the old version of a variable belong only to your application and not part of your system and if this same situation comes up more than once apply a technique of factoring BURY a DUP 2 2 CMOVE EXHUME a DUP 2 SWAP 2 CMOVE Then instead of de ning two variables such as CONDITION and OLD CONDITION de ne one double length variable 2VARIABLE CONDITION Use BURY and EXHUME to save and restore the original value DIDDLE CONDITION BURY 17 CONDITION diddle CONDITION EXHUME BURY saves the old version of condition at CONDITION 2 You still have to be careful Going back to our DUMP DUMP DUMP DUMP DUMP example suppose you decided to add the friendly feature of letting the user exit the dump at any time by pressing the escape key So inside the loop you build the test for a key being pressed and if so execute QUIT QUIT QUIT QUIT QUIT But what happens The user starts in decimal then types DUMP DUMP DUMP DUMP DUMP He exits DUMP DUMP DUMP DUMP DUMP midway through and nds himself strangely in hexadecimal In the simple case at hand the best solution is to not use QUIT QUIT QUIT QUIT QUIT but rather a controlled exit from the loop via LEAVE LEAVE LEAVE LEAVE LEAVE etc to the end of the de nition where BASE BASE BASE BASE BASE is reset In very complex applications a contr
2. where you rst compute the address 204 Handling Data Stacks and States Figure 7 1 Example of a stack commentary Tip Where possible keep the number of return arguments the same in all possible cases 7 6 You ll often nd a de nition which does some job and if something goes wrong returns an error code identifying the problem Here s one way the stack inter face might be designed error code f t If the ag is true the operation was successful If the ag is false it was unsuccessful and there s another value on the stack to indicate the nature of the error Stack Tips 205 You ll nd stack manipulation easier though if you redesign the interface to look like this error code O no error One value serves both as a ag and in case of an error the error code Note that reverse logic is used non zero indicates an error You can use any values for the error codes except zero The Stylish Return Stack What about this use of the return stack to hold temporary arguments Is it good style or what Some people take great o ense to its use But the return stack o ers the simplest solution to certain gnarly stack jams Witness the de nition of CMOVE gt CMOVE gt CMOVE gt CMOVE gt CMOVE gt in the previous section If you decide to use the return stack for this purpose remember that you are using a component of Forth for a purpose other than that intended
3. speed limit FREEWAY IF 55 ELSE 25 THEN We might eliminate the IF IF IF IF IF THEN THEN THEN THEN THEN by using a hybrid value with AND AND AND AND AND SPEED LIMIT 25 FREEWAY 30 AND But this approach doesn t match our conceptual model of the problem and therefore isn t very readable Let s try a data table This is a one dimensional table with only two elements so there s not much to it CREATE LIMITS 25 55 Using Decision Tables 243 The word SPEED LIMIT now must apply the boolean to o set into the data table SPEED LIMIT speed limit LIMITS FREEWAY 2 AND Have we gained anything over the IF IF IF IF IF THEN THEN THEN THEN THEN approach Probably not with so simple a problem What we have done though is to factor out the decision making process from the data itself This becomes more cost e ective when we have more than one set of data related to the same decision Suppose we also had CREATE LANES 4 10 representing the number of lanes on a city street and on a freeway We can use identical code to compute the current number of lanes LANES lanes LANES FREEWAY 2 AND Applying techniques of factoring we simplify this to ROAD for freeway for city CREATE DOES gt data FREEWAY 2 AND 55 25 ROAD SPEED LIMIT 10 4 ROAD LANES Another example of the one di
4. DELETE SLIDE lt BLANK END To copy the text leftwards and rightwards we had to invent two new names as we went along SLIDE lt and SLIDE gt pronounced slide backwards and slide forwards respectively Both of them will certainly use POSITION but they also must rely on an element we ve deferred considering a way to know the length of the eld We can tackle that aspect when we get to writing the third component But look at what we found out already we can describe Insert as simply SLIDE gt OVERWRITE In other words Insert actually uses Overwrite even though they ap pear to exist on the same level at least to a Structured Programmer Instead of probing deeper into the third component let s lay out what we know about the rst component the key interpreter First we must solve the problem of insert mode It turns out that insert is not just something Example A Tiny Editor 77 that happens when you press a certain key as delete is Instead it is a di erent way of interpreting some of the possible keystrokes For instance in overwrite mode an ordinary character gets stored into the current cursor position but in insert mode the remainder of the line must rst be shifted right And the backspace key works di erently when the editor is in Insert Mode as well Since there are two modes inserting and not inserting the keystroke interpreter
5. It takes arrogance to go back and say You didn t really mean this or Would you mind if I took o this page and replaced it with this expression They get annoyed They want you to do what they told you to do LaFarr Stuart took this attitude when he redesigned Forth 3 He didn t like the input bu er so he implemented Forth without it and discovered he didn t really need an input bu er If you can improve the problem it s a great situation to get into It s much more fun redesigning the world than implementing it Achieving Simplicity 63 An overgeneralized solution E ective programmers learn to be tactful and to couch their approaches in non threatening ways What would be the consequences of replacing that with this etc Yet another way to simplify a problem is this Tip To simplify keep the user out of trouble 2 15 Suppose you re designing part of a word processor that displays a directory of stored documents on the screen one per line You plan that the user can move the cursor next to the name of any document then type a one letter command indicating the chosen action p for print e for edit etc Initially it seems all right to let the user move the cursor anywhere on the screen This means that those places where text already appears must be protected from being overwritten This implies a concept of protected elds and special handling A simpler approach co
6. Tip Choose names according to what not how 5 15 A de nition should hide the complexities of implementation from other de ni tions which invoke it The name too should hide the details of the procedure and instead should describe the outward appearance or net e ect For instance the Forth word ALLOT ALLOT ALLOT ALLOT ALLOT simply increments the dictionary pointer called DP DP DP DP DP or HHHHH in most systems But the name ALLOT ALLOT ALLOT ALLOT ALLOT is better than DP because the user is thinking of reserving space not incrementing a pointer The 83 Standard adopted the name CMOVE gt CMOVE gt CMOVE gt CMOVE gt CMOVE gt instead of the previous name for the same function lt CMOVE lt CMOVE lt CMOVE lt CMOVE lt CMOVE The operation makes it possible to copy a region of memory forward into overlapping memory It accomplishes this by starting with the last byte and working backward In the new name the forwardness of the what supersedes the backwardness of the how Tip Find the most expressive word 5 16 Choosing Names The Art 163 A powerful agent is the right word Whenever we come upon one of those intensely right words in a book or a newspaper the resulting e ect is physical as well as spiritual and electrically prompt Mark Twain The di erence between the right word and the almost right word is like the di erence between lightning and the lightning
7. color value EXECUTE 8 OR in g Forth LIGHT COMPILE CFA EXECUTE 8 OR For novices The apostrophe in the de nition of LIGHT is a Forth word called tick Tick is a dictionary search word it takes a name and looks it up in the dictionary returning the address where the de nition resides Used in this de nition it will nd the address of the word following LIGHT for instance BLUE and pass this address to the word EXECUTE EXECUTE EXECUTE EXECUTE EXECUTE which will execute BLUE pushing a one onto the stack Having sucked up the operation of BLUE LIGHT now or s an 8 into the 1 producing a 9 This de nition will work when invoked in the input stream but special handling is required if we want to let LIGHT be invoked within a colon de nition as in EDITING LIGHT BLUE BORDER Even in the input stream the use of EXECUTE here will cause a crash if LIGHT is accidentally followed by something other than a de ned word The preferred technique if you re forced to use this particular syntax is to have LIGHT set a ag and have BLUE determine whether that ag was set as we ll see later on There will be times when looking ahead in the input stream is desirable even necessary The proposed TO solution is often implemented this way 3 But generally avoid expectations You re setting yourself up for disap pointment 4 21 Tip Let commands perform them
8. current balance DO IF withdrawal available cash DO vend currency debit account ELSE message terminate session ELSE message terminate session ELSE message terminate session ELSE IF authorization code is valid DO query for amount accept envelope through hatch credit account ELSE message terminate session ELSE eat card ELSE message END But even with this improvement the design of each word depends com pletely on the sequence in which the tests must be performed The supposedly highest level procedure is burdened with eliminating the worst case most trivial kind of event And each test becomes responsible for invoking the next test The third version comes closest to the promise of Forth The highest level word expresses exactly what s happening conceptually showing only the main path Each of the subordinate words has its own error exit not cluttering the reading of the main word One test does not have to invoke the next test Also TRANSACT is designed around the fact that the user will make re quests by pressing buttons on a keypad No conditions are necessary One button will initiate a withdrawal another a deposit This approach readily ac commodates design changes later such as the addition of a feature to transfer funds And this approach does not thereby become dependent on hardware 230 Minimizing Control Structures Figure 8 2 Nesting conditionals within named procedures AUTOMATIC TELLER
9. lt DUMP gt a O DO I 16 MOD O IF CR DUP I 5 U R 2 SPACES THEN DUP I UNIT UNIT UNIT UNIT UNIT LOOP DROP Using DOER MAKE 221 Figure 7 8 Multiple MAKEs in parallel using AND DOER SAM ok DOER BIFF ok SAM BIFF Creates two DOER words that do nothing TESTB MAKE SAM 2 AND MAKE BIFF 3 ok TESTB MAKE SAM 2 AND MAKE BIFF 3 De nes a new word called TESTB TESTB ok SAM BIFF TESTB MAKE SAM 2 AND MAKE BIFF 3 The rst MAKE redirects SAM so that it points to the code after it SAM BIFF CONTINUE TESTB MAKE SAM 2 AND MAKE BIFF 3 The AND continues execution of TESTB The second MAKE redirects BIFF SAM 2 ok BIFF 3 ok Two DOER words have been redirected at the same time by the single word TESTB SAM s code stops at AND BIFF s code stops at semicolon DUMP a MAKE UNIT 6 U R 2 AND lt DUMP gt CDUMP a MAKE UNIT C 4 U R 1 AND lt DUMP gt Notice how DUMP and CDUMP set up the vector then go on to execute the shell the word lt DUMP gt 3 To change the state of related functions by invoking a single command For instance DOER TYPE DOER EMIT DOER SPACES 222 Handling Data Stacks and States Figure 7 9 Multiple MAKEs in series TESTC MAKE JOE 4 MAKE JOE 5 ok TESTC MAKE JOE 4 MAKE JOE 5 De nes a new word called TESTC TESTC
10. nd a design aw redesign recode nd a bug in the new code recode again Total 10 You see how the thing snowballs 5 Now you have to document your new feature Add two hours to the above Total 12 6 After you ve spent anywhere from 2 to 12 hours installing and debugging your new feature you suddenly nd that element Y of your application bombs out Worst yet you have no idea why You spend two hours reading memory dumps trying to divine the reason Once you do you spend as many as 12 additional hours redesigning element Y Total 26 Then you have to document the syntax change you made to element Y Total 27 66 Analysis Conventional wisdom reveres complexity That s a total of over three man days If all these mishaps befell you at once you d call for the men with the little white coats It rarely gets that bad of course but the odds are decidedly against any project being as easy as you think it will be How can you improve your chances of judging time requirements cor rectly Many ne books have been written on this topic notably The Mythical Man Month by Frederick P Brooks Jr 4 I have little to add to this body of knowledge except for some personal observations 1 Don t guess on a total Break the problem up into the smallest possible pieces then estimate the time for each piece The sum of the pieces is always greater than what you d have guessed the total would be The whole
11. 11 Peter M Kogge An Architectural Trail to Threaded Code Systems Computer March 1982 12 Randy Dumse The R65F11 Forth Chip Forth Dimensions Vol 5 No 2 p 25 References 35 TWO Analysis Anyone who tells you there is some de nite number of phases to the software development cycle is a fool Nevertheless The Nine Phases of the Programming Cycle As we ve seen Forth integrates aspects of design with aspects of implementation and maintenance As a result the notion of a typical development cycle makes as much sense as a typical noise But any approach is better than no approach and indeed some ap proaches have worked out better than others Here is a development cycle that represents an average of the most successful approaches used in software projects Analysis 1 Discover the Requirements and Constraints 2 Build a Conceptual Model of the Solution 3 Estimate Cost Schedule Performance Engineering 4 Preliminary Design 5 Detailed Design 6 Implementation Usage 7 Optimization 8 Validation and Debugging 9 Maintenance In this book we ll treat the rst six stages of the cycle focusing on analysis design and implementation In a Forth project the phases occur on several levels Looking at a project from the widest perspective each of these steps could take a month or more One step follows the next like seasons 38 Analysis But Forth program
12. At the same time the programmer can if he or she wants deliberately seal any commands including Forth itself from being accessed by the end user once the application is complete Now Forth s methodology becomes clear Forth programming consists of extending the root language toward the application providing new commands that can be used to describe the problem at hand Programming languages designed especially for particular applications such as robotics inventory control statistics etc are known as application oriented languages Forth is a programming environment for creating app lication oriented languages That last sentence may be the most succinct description of Forth that you ll nd In fact you shouldn t write any serious application in Forth as a lan guage it s simply not powerful enough What you should do is write your own language in Forth lexicons to model your understanding of the problem in which you can elegantly describe its solution Hide From Whom Because modern mainstream languages give a slightly di erent meaning to the phrase information hiding we should clarify From what or whom are we hiding information The newest traditional languages such as Modula 2 bend over back wards to ensure that modules hide internal routines and data structures from other modules The goal is to achieve module independence a minimum cou pling The fear seems to be that modules strive to at
13. NOTHING gt BODY COMPILE gt BODY 12 13 The code in this screen is in the public domain 14 15 Screen 23 0 DOER MAKE FORTH 83 Lab Micro PC FORTH 2 0 LPB 12 05 83 1 NOTHING 2 DOER CREATE NOTHING gt BODY DOES gt gt R 3 VARIABLE MARKER 4 MAKE R gt DUP 2 DUP 2 SWAP gt BODY 5 DUP IF gt R THEN 6 MAKE STATE IF compiling 7 COMPILE MAKE HERE MARKER 0 8 ELSE HERE COMPILE gt BODY 9 COMPILE UNSMUDGE THEN IMMEDIATE 10 AND COMPILE EXIT HERE MARKER IMMEDIATE 11 UNDO NOTHING gt BODY COMPILE gt BODY 12 13 The code in this screen is in the public domain 14 15 De ning DOER MAKE 273 Screen 24 0 DOER MAKE FIG model LPB 12 05 83 1 NOTHING 2 DOES PFA pfa pfa of child of lt BUILD DOES gt 2 3 DOER lt BUILDS NOTHING DOES gt gt R 4 0 VARIABLE MARKER 5 MAKE R gt DUP 2 DUP 2 SWAP 2 DOES PFA 6 DUP IF gt R THEN 7 MAKE STATE IF compiling 8 COMPILE MAKE HERE MARKER 0 9 ELSE HERE COMPILE DOES PFA 10 SMUDGE COMPILE THEN IMMEDIATE 11 AND COMPILE S HERE MARKER IMMEDIATE 12 UNDO NOTHING COMPILE DOES PFA 13 S 14 The code in this screen is in the public domain 15 Screen 25 0 DOER MAKE 79 Standa
14. Third they focus your attention on the interfaces to the system and between modules Forth programmers however rarely use DFDs except for the customer s bene t Forth encourages you to think in terms of the conceptual model and Forth s implicit use of a data stack makes the passing of data among modules so simple it can usually be taken for granted This is because Forth used properly approaches a functional language For anyone with a few days familiarity with Forth simple de nitions convey at least as much meaning as the diagrams REQUEST quantity part ON HAND IF TRANSFER ELSE REORDER THEN REORDER AUTHORIZATION IF P O THEN P O BOOKKEEPING COPY RECEIVING COPY VENDOR MAIL COPY This is Forth pseudocode No e ort has been made to determine what values are actually passed on the stack because that is an implementation detail The stack comment for REQUEST is used only to indicate the two items of data needed to initiate the process If I were designing this application I d suggest that the user interface be a word called NEED which has this syntax De ning the Interfaces 51 NEED 50 AXLES NEED converts the quantity into a numeric value on the stack translates the string AXLES into a part number also on the stack then calls REQUEST Such a command should be de ned only at the outer most level Johnson of Moore Products Co has a few words on Forth pseudocode IBM use
15. it s hardly worth making into a separate de nition You could though But we won t Let s focus on the code for the special case To state its algorithm If the digit is four print a ONER and a FIVER If the digit is nine print a ONER and a TENER We can assume that the digit will be one or the other or else we d never be executing this de nition The question is how do we tell which one Again we can use the quotient of division by ve If the quotient is zero the digit must have been four otherwise it was nine So we ll play the same trick and use the quotient as a boolean ag We ll write ALMOST quotient IF ONER TENER ELSE ONER FIVER THEN In retrospect we notice that we re printing a ONER either way We can simplify the de nition to ALMOST quotient ONER IF TENER ELSE FIVER THEN We ve assumed that we have a quotient on the stack to use Let s go back to our de nition of DIGIT and make sure that we do in fact DIGIT n 5 MOD OVER 4 IF ALMOST ALMOST ALMOST ALMOST ALMOST ELSE IF FIVER THEN ONERS THEN 128 Detailed Design Problem Solving It turns out that we have not only a quotient but a remainder underneath as well We re keeping both on the stack in the event we execute the ELSE ELSE ELSE ELSE ELSE clause The word ALMOST ALMOST ALMOST ALMOST ALMOST however only needs the quotient So for symmetry we must DROP DROP DROP DRO
16. will generally prove easiest to implement because of the stack Forth Syntax 111 In some cases this word order sounds unnatural For instance suppose we have a le named INVENTORY One thing we can do with that le is SHOW it that is format the information in pretty columns If INVENTORY passes a pointer to SHOW which acts upon it the syntax becomes INVENTORY SHOW If your spec demands the English word order Forth o ers ways to achieve it But most involve new levels of complexity Sometimes the best thing to do is to choose a better name How about INVENTORY REPORT We ve made the pointer an adjective and the actor a noun If the requirements insist on the syntax SHOW INVENTORY we have several options SHOW might set a ag and INVENTORY would act ac cording to the ag Such an approach has certain disadvantages especially that INVENTORY must be smart enough to know all the possible actions that might be taken on it We ll treat these problems in Chapters Seven and Eight Or SHOW might look ahead at the next word in the input stream We ll discuss this approach in a tip Avoid expectations later in this chapter Or the recommended approach SHOW might set an execution variable that INVENTORY will then execute We ll discuss vectored execution in Chapter Seven Tip Let text follow names 4 15 If the Forth interpreter nds a string of text that is neither a num
17. Again the spec writers will model the analog solution which was modeling the electromechanical solution and they re several models away from reality In 62 Analysis fact you can replace it all with two or three coe cients in a digital lter for a much cleaner simpler and more e cient solution Tip Go back to what the problem was before the customer tried to solve it Exploit the don t cares 2 13 Moore continues Sometimes the possibilities for simpli cation aren t immediately obvious There s this problem of zooming in a digitized graphics display such as CAD systems You have a picture on the screen and you want to zoom in on a portion to see the details I used to implement it so that you move the cursor to the position of interest then press a button and it zooms until you have a window of the desired size That was the way I ve always done it Until I realized that that was stupid I never needed to zoom with such ne resolution So instead of moving the cursor a pixel at a time I jump the cursor by units of say ten And instead of increasing the size of box I jump the size of the box You don t have a choice of sizes You zoom by a factor of four The in between sizes are not interesting You can do it as many times as you like By quantizing things fairly brutally you make it easier to work with more responsive and simpler Tip To simplify quantize 2 14 Moore concludes
18. Of course we have one already BLK BLK BLK BLK BLK So we try BLK 1 SWAP BLK Now it s more readable but it s still rather long and redundant too BLK BLK BLK BLK BLK appears twice BLK BLK BLK BLK BLK That sounds familiar Finally our neurons connect We look back at the source for LOAD just de ned LOAD offset BLK LOAD This word LOAD should be doing the work All we have to write is THRU lo hi 1 SWAP DO I LOAD LOOP We haven t created a more e cient version here because the work of BLK BLK BLK BLK BLK will be done on every pass of the loop But we have created a cleaner concep tually simpler and more readable piece of code In this case the ine ciency is unnoticeable because it only occurs as each block is loaded Redesigning or rethinking the problem was the path we should have taken as soon as things got ugly Local Variables Most of the time problems can be arranged so that only a few arguments are needed on the stack at any one time Occasionally however there s nothing you can do Here s an example of a worst case Assume you have a word called LINE which draws a line between any two points speci ed as coordinates in this order x1 y1 x2 y2 where x1 y1 represent the x y coordinates for the one end point and x2 y2 represent the opposite end point Now yo
19. This is bad because you re deciding which function to perform every time you type a string A preferable implementation would use vectored execution For instance DOER TYPE a VIDEO MAKE TYPE code for video PRINTER MAKE TYPE code for printer This is better because TYPE doesn t have to decide which code to use it already knows On a multi tasked system the printer and monitor tasks would each have their own copies of an execution vector for TYPE stored in a user variable The above example also illustrates the limitation of this tip In our second version we have no simple way of knowing whether our current device is the printer or the video screen We might need to know for instance to decide whether to clear the screen or issue a formfeed Then we re making an additional use of the state and our rule no longer applies A ag would in fact allow the simplest implementation of additional state dependent operations In the case of TYPE however we re concerned about speed We type strings so often we can t a ord to waste time doing it The best solution here might be to set the function of TYPE and also set a ag 256 Minimizing Control Structures DOER TYPE VIDEO O DEVICE MAKE TYPE code for video PRINTER 1 DEVICE MAKE TYPE code for printer Thus TYPE already knows which code to execute but other de nitions will refer to the ag Anot
20. adr of no match row these are the routines for any key not in the table We use these names to supply the addresses passed to DO DO DO DO DO NOMATCH FUNCTION DO to set up a loop that runs from the rst row of the table to the last We don t have to know how many rows lie in the table We could even delete a row or 246 Minimizing Control Structures Figure 8 5 Implementation of the Tiny Editor Screen 30 0 Tiny Editor 1 2 CONSTANT NORMAL offset in FUNCTIONS 2 4 CONSTANT INSERTING 3 6 CONSTANT KEY bytes in table for each key 4 VARIABLE MODE current offset into table 5 NORMAL MODE 6 INSERT OFF NORMAL MODE 7 INSERT ON INSERTING MODE 8 9 VARIABLE ESCAPE t time to leave loop 10 ESCAPE TRUE ESCAPE 11 12 13 14 15 Screen 31 0 Tiny Editor function table 07 29 83 1 IS function for 83 standard 2 CREATE FUNCTIONS 3 keys normal mode insert mode 4 4 ctrl D IS DELETE IS INSERT OFF 5 9 ctrl I IS INSERT ON IS INSERT OFF 6 8 backspace IS BACKWARD IS INSERT lt 7 60 left arrow IS BACKWARD IS INSERT OFF 8 62 right arrow IS FORWARD IS INSERT OFF 9 27 return IS ESCAPE IS INSERT OFF 10 O no match IS OVERWRITE IS INSERT 11 HERE KEY CONSTANT NOMATCH adr of no match key 12 13 14 15 Screen 32 0 Tin
21. clich s They stick together as meaningful functions You don t have to remember how the phrase works just what it does And you don t have to remember an extra name Compile Time Factoring In the last section we looked at many techniques for organizing code and data to reduce redundancy We can also apply limited redundancy during compilation by letting Forth do some of out dirty work 6 17 Tip For maximum maintainability limit redundancy even at compile time Suppose in our application we must draw nine boxes as shown in Figure 6 1 In our design we need to have constants that represent values such as the size of each box the size of the gap between boxes and the left most and top most coordinates of the rst box Naturally we can de ne 188 Factoring Figure 6 1 What we re supposed to display 8 CONSTANT WIDE 5 CONSTANT HIGH 4 CONSTANT AVE 2 CONSTANT STREET Streets run east and west avenues run north and south Now to de ne the left margin we might comput
22. ning word PORT offset CREATE does gt port BASE PORT ADDRESS 0 PORT SPEAKER 2 PORT FLIPPER A 4 PORT FLIPPER B 6 PORT WIN LIGHT In this solution we re performing the o set calculation at run time every time we invoke one of these names It would be more e cient to perform the calcu lation at compile time like this PORT offset BASE PORT ADDRESS CONSTANT does gt port 0 PORT SPEAKER 2 PORT FLIPPER A 4 PORT FLIPPER B 6 PORT WIN LIGHT Here we ve created a de ning word PORT that has a unique compile time be havior namely adding the o set to BASE PORT ADDRESSand de ning a CONSTANT We might even go one step further Suppose that all port addresses are two bytes apart In this case there s no reason we should have to specify these o sets The numeric sequence 0 2 4 6 is itself redundant In the following version we begin with the BASE PORT ADDRESS on the stack The de ning word PORT duplicates this address makes a constant out of it then adds 2 to the address still on the stack for the next invocation of PORT PORT port next port DUP CREATE 2 does gt port BASE PORT ADDRESS PORT SPEAKER PORT FLIPPER A PORT FLIPPER B PORT WIN LIGHT DROP port address Compile Time Factoring through De ning Words 191 Notice we must supply the initial port address on the stack before de ning the rst port then invo
23. powerful than assembly languages in the sense that each instruction might compile dozens of machine instructions But more signi cantly high level languages eliminate the linear correspondence between source code and the resulting machine instructions The actual instructions depend on each entire statement of source code taken as a whole Operators such as and have no meaning by themselves They are merely part of a complex symbology that depends upon syntax and the operator s location in the statement This nonlinear syntax dependent correspondence between source and ob ject code is widely considered to be an invaluable step in the progress of pro gramming methodology But as we ll see the approach ultimately o ers more restriction than freedom Manageability Most computer programs involve much more than lists of instructions to work down from start to nish They also involve testing for various conditions and then branching to the appropriate parts of the code depending upon the outcome They also involve looping over the same sections of code repeatedly usually testing for the moment to branch out of the loop Both assembler and high level languages provide branching and looping capabilities In assembly languages you use jump instructions in some high level languages you use GO TO commands When these capabilities are used in the most brute force way programs tend to look like the jumbl
24. ran out of room Application load Screen 139 Skip Commands Two commands make it easy to control what gets loaded in each screen and what gets ignored They are S S S S S also called EXIT EXIT EXIT EXIT EXIT is pronounced skip line It causes the Forth interpreter to ignore everything to the right of it on the same line Since is a Forth word it must be followed by a space It does not require a delimiter In Figure 5 1 you see used in two ways to begin the screen comment line Line 0 and to begin comments on individual lines which have no more code to the right of the comment During testing also serves to temporarily paren out lines that already contain a right parenthesis in a name or comment For instance these two skip line s keep the de nition of NUTATE from being compiled without causing problems in encountering either right parenthesis NUTATE x y z SWAP ROT NUTATE S S S S S is pronounced skip screen It causes the Forth interpreter to stop inter preting the screen entirely as though there were nothing else in the screen beyond S S S S S In many Forth systems this function is the same as EXIT EXIT EXIT EXIT EXIT which is the run time routine for semicolon In these systems the use of EXIT EXIT EXIT EXIT EXIT is acceptable Some Forth systems however require for internal reasons a di erent routine for the sk
25. 144 Implementation Elements of Forth Style Figure 5 4 Example of a disk partitioning scheme within one department Screen 0 is the title screen showing the name of the application the current release number and primary author Screen 1 is the application load block Screen 2 is reserved for possible continuation from Screen 1 Screen 4 and 5 contain system messages Screens 9 thru 29 incorporate general utilities needed in but not re stricted to this application Screen 30 begins the application screens The reason By convention Forth screens are printed three to a page with the top screen always evenly divisible by three Such a page is called a triad most Forth systems include the word TRIAD to produce it given as an argument the number of any of the three screens in the triad For instance if you type 77 TRIAD you ll get a page that includes 75 76 and 77 The main bene t of this convention is that if you change a single screen you can slip the new triad right into your binder containing the current listing replacing exactly one page with no overlapping screens Similarly the word INDEX lists the rst line of each screen 60 per page on boundaries evenly divisible by 60 Tip Begin sections or lexicons on screen numbers evenly divisible by three Begin applications or chapters on screen numbers evenly divisible by thirty 5 3 Electives Vendors of Forth systems have a problem If they w
26. 76 C 67 C 68 C 77 C We can select a particular symbol from the table by applying two di erent o sets at the same time One dimension represents the decimal place ones tens hundreds etc This dimension is made current that is its state stays the same until we change it The other dimension represents the kind of symbol we want ONER FIVER TENER within the current decimal column This dimension is incidental that is we ll specify which symbol we want each time Let s start by implementing the current dimension We need some way to point to the current decimal column Let s create a variable called COLUMN pronounced column number and have it contain an o set into the table VARIABLE COLUMN current offset ONES O COLUMN TENS 2 COLUMN HUNDREDS 4 COLUMN THOUSANDS 6 COLUMN Now we can nd our way to any arm position by adding the contents of COLUMN to the beginning address of the table given by ROMANS COLUMN adr of column ROMANS COLUMN Algorithm 131 Let s see if we can implement one of the words to display a symbol We ll start with ONER The thing we want to do in ONER is EMIT EMIT EMIT EMIT EMIT a character ONER EMIT Working backward EMIT EMIT EMIT EMIT EMIT requires the ASCII character on the stack How do we get it there With C C C C C ONER C EMIT C C C C C requires the
27. Case statements 175 237 238 Chapter load screens 140 143 Chapters 138 Clich s 188 CODE 266 Code factoring out from within con trol structures 174 175 repetition of 180 181 Coincidental binding 14 Commands reducing number of 184 187 Comment conventions 150 159 Comment line 146 147 Commenting style 285 286 Communicational binding 14 Compile time factoring 188 192 Compilers 34 117 119 Compiling words comments for 158 159 Component programming 20 23 Components decomposition by 72 88 sharing 213 215 Composition 138 Conceptual model 46 59 68 131 data structure de nition 59 60 de ned 46 interface de nition 49 52 rule de nition 52 59 Conditionals nesting and combin ing 235 236 CONSTANT 266 Constraints 46 Control ags 174 Control ow 5 Control structure minimization 228 259 calculating results 240 242 case statements 237 238 decision tables 243 249 dictionary 232 234 looping structures 238 240 nesting and combining condi tionals 235 236 reasons for 228 229 redesigning 249 252 simpli cation 258 259 structured exits 252 254 timing 254 257 tricks 242 Control structures choosing 237 de ned 268 factoring out 174 175 factoring out code from within 174 175 minimization of see Control struc ture minimization Counted strings 176 177 Counts vs term
28. If you have a link eld you have to fetch it anyway You might as well test for zero You don t need to keep a counter of how many records there are Choosing Control Structures 239 If you decrement a counter to decide whether to terminate you re making more work for yourself This is the technique used to implement Forth s dictionary as a linked list Calculating Results 8 9 Tip Don t decide calculate Many times conditional control structures are applied mistakenly to situations in which the di erence in outcome results from a di erence in numbers If numbers are involved we can calculate them In Chapter Four see the section called Calculations vs Data Structures vs Logic 8 10 Tip Use booleans as hybrid values This is a fascinating corollary to the previous tip Don t decide calculate The idea is that booleans which the computer represents as numbers can e ciently be used to e ect numeric decisions Here s one example found in many Forth systems S gt D n d sign extend s to d DUP O lt IF 1 ELSE O THEN The purpose of this de nition is to convert a single length number to double length A double length number is represented as two 16 bit values on the stack the high order part on top Converting a positive integer to double length merely means adding a zero onto the stack to represent its high order part But converting a negative integer to do
29. TOP 10 Figure 7 6 Implementation of alternating states mechanism VARIABLE POINTERS pointer to state table POINTERS adr of current table POINTERS POSITION o o 2 CREATE DUP 2 DOES gt a POINTERS 0 initial offset POSITION TOP POSITION BOTTOM POSITION LEFT POSITION RIGHT POSITION INSIDE POSITION OUT CONSTANT POINTERS final computed offset CREATE REAL POINTERS ALLOT real state table CREATE PSEUDO POINTERS ALLOT temporary state table WORKING REAL POINTERS WORKING PRETENDING PSEUDO POINTERS 218 Handling Data Stacks and States PRETENDING 20 TOP TOP 20 WORKING TOP 10 PRETENDING TOP 20 The major di erence with this latter approach is that names go through an extra level of indirection POINTERS has been changed from a constant to a colon de nition The eld names can be made to point to either of two state tables Thus each name has slightly more work to do Also in the former approach the names refer to xed locations a CMOVE CMOVE CMOVE CMOVE CMOVE is required each time we save or restore the values In this approach we have only to change a single pointer to change the current table Vectored Execution Vectored execution extends the ideas of currentness and indirection beyond data to functions Just as we can save values and ags in variables we can also save functions because functions can be referred to by a
30. Usually abbreviations are used Some standard abbrevia tions appear in Table 5 2 Whether abbreviations or fully spelled out words are used each stack item should be separated by a space If a stack item is described with a phrase such as address of latest link the words in the phrase should be joined by hyphens For example the stack picture Stack Notation 151 address current count max count shows three elements on the stack Stack E ect A stack e ect shows two stack pictures one picture of any items that may be consumed by a de nition and another picture of any items returned by the de nition The before picture comes rst followed by two hyphens then the after picture For instance the stack e ect for Forth s addition operator is n n sum where consumes two numbers and returns their sum Remember that the stack e ect describes only the net result of the opera tion on the stack Other values that happen to reside on the stack beneath the arguments of interest don t need to be shown Nor do values that may appear or disappear while the operation is executing If the word returns any input arguments unchanged they should be re peated in the output picture e g 3rd 2nd top input 3rd 2nd top output Conversely if the word changes any arguments the stack comment must use a di erent descriptor nl n2 n n A stack e ect might appear in a formatted
31. height weight This is di erent from the comment that would be used if MEASUREMENTS were de ned by CREATE CREATE CREATE CREATE CREATE CREATE MEASUREMENTS 4 ALLOT 2weight 2height While both statements produce the same result in the dictionary the use of 2VARIABLE 2VARIABLE 2VARIABLE 2VARIABLE 2VARIABLE implies that the values will normally be 2 fetched and 2 stored together thus we use a stack comment The high order part appearing on top of the stack is listed to the right The use of CREATE CREATE CREATE CREATE CREATE implies that the values will normally be fetched and stored separately thus we use a data structure comment The item in the 0th position is listed to the left Data Structure Comments 155 Input stream Comments The input stream comment indicates what words and or strings are presumed to be in the input stream Table 5 3 lists the designations used for input stream arguments Table 5 3 Input stream comment designations c single character blank delimited name sequence of characters blank delimited text sequence of characters delimited by non blank Follow text with the actual delimiter required e g text or text The input stream comment appears before the stack comment and is not encapsulated between its own pair of parentheses but simply surrounded by three spaces on each side For instance here s one way to comment the de nition of tick sho
32. ideas were involved The iterative approach places highest value on producing a good solution to the real problem It may not always give you the most predictable software costs The route to a solution may depend upon your priorities Remember Good Fast Cheap Pick any two As Starling observes you don t know completely what you re doing till you ve done it once In my own experience the best way to write an application is to write it twice Throw away the rst version and chalk it up to experience Peter Kogge is Senior Technical Sta in the IBM Federal Systems Division Oswego New York One of the key advantages I nd in Forth is that it allows me to very quickly prototype an application without all the bells and whistles and often with signi cant limitations but enough to wring out the human interface by hands on trial runs When I build such a prototype I do so with the rm constraint that I will use not a single line of code from the prototype in the nal program This enforced do over almost always results in far simpler and more elegant nal programs even when those programs are written in something other than Forth 44 Analysis Our conclusions In the Forth environment planning is necessary But it should be kept short Testing and prototyping are the best ways to discover what is really needed A word of caution to project managers If you re supervising any experi enced Fo
33. it may even hide a few bugs In building a conceptual model for this system we must describe the rate structure in an unambiguous useful way The rst step towards cleaning up the clutter involves factoring out irrelevant pieces of information that is applying the rules of limited redundancy We can improve this statement a lot by splitting it into two statements First there s the time of day rule Calls during weekdays between 8 A M and 5 P M are charged at full rate Calls during weekdays between 5 P M and 11 P M are charged at lower rate Calls placed during weekdays between 11 P M or anytime on Saturday Sundays or holidays are charged at the lowest rate Then there s the rate structure itself which should be described in terms of rst minute rate additional minute rate distance rate and operator assistance rate Tip Factor the fruit Don t confuse apples with oranges 2 9 These prose statements are still di cult to read however System analysts use several techniques to simplify these statements structured English decision trees and decision tables Let s study each of these techniques and evaluate their usefulness in the Forth environment Structured English Structured English is a sort of structured pseudocode in which our rate state ment would read something like this IF full rate IF direct dial IF first minute 30 12 100miles ELSE add
34. most e cient and reliable way 22 The Philosophy of Forth Figure 1 9 The entire application consists of components By the way Forth itself doesn t support components It doesn t need to Components are the product of the program designer s decomposition Forth does have screens however small units of mass storage for saving source code A component can usually be written in one or two screens of Forth It s important to understand that a lexicon can be used by any and all of the components at higher levels Each successive component does not bury its supporting components as is often the case with layered approaches to design Instead each lexicon is free to use all of the commands beneath it The robot movement command relies on the root language with its variables constants stack operators math operators and so on as heavily as any other component An important result of this approach is that the entire application em ploys a single syntax which makes it easy to learn and maintain This is why I use the term lexicon and not language Languages have unique syntaxes Component Programming 23 This availability of commands also makes the process of testing and de bugging a whole lot easier Because Forth is interactive the programmer can type and test the primitive commands such as RIGHT SHOULDER 20 PIVOT from the outside as easily as the more powerful ones like LIFT COFFEE POT
35. n DUP 3999 gt ABORT Too large ROMAN Moore There s a de nite sense of rightness when you ve done it right It may be that feeling that distinguishes Forth from other languages where you never feel you ve really done well In Forth it s the Aha reaction You want to run o and tell somebody Of course nobody will appreciate it like you do Summary In this chapter we ve learned to develop a single component starting rst with deciding on its syntax then proceeding with determining its algorithm s and data structure s and concluding with an implementation in Forth With this chapter we complete our discussion of design The remainder of the book will discuss style and programming techniques References 1 G Polya How To Solve It A New Aspect of Mathematical Method Princeton New Jersey Princeton University Press 2 Leslie A Hart How the Brain Works c 1975 by Leslie A Hart New York Basic Books Inc 1975 3 Evan Rosen High Speed Low Memory Consumption Structures 1982 FORML Conference Proceedings p 191 4 Michael Stolowitz A Compiler for Programmable Logic in FORTH 1982 FORML Conference Proceedings p 257 For Further Thinking Design the components and describe the algorithm s necessary to simulate shu ing a deck of cards Your algorithm will produce an array of numbers 0 51 arranged in random order The special constraint of this prob
36. performed by a function de ned much later in the listing decomposition by sequential complexity Increased complexity of the earlier code is limited solely to de ning the hook and invoking it at the right spot Employing Good Timing 257 Simplifying I ve saved this tip for last because it exempli es the rewards of opting for sim plicity While other tips concern maintainability performance compactness etc this tip relates to the sort of satisfaction that Thoreau sought at Walden Pond 8 25 Tip Try to avoid altogether saving ags in memory A ag on the stack is quite di erent from a ag in memory Flags on the stack can simply be determined by reading the hardware calculating or whatever pushed onto the stack then consumed by the control structure A short life with no complications But save a ag in memory and watch what happens In addition to having the ag itself you now have the complexity of a location for the ag The location must be created initialized even before anything actually changes reset otherwise passing a ag to a command leaves the ag in that current state Because ags in memory are variables they are not reentrant An example of a case in which we might reconsider the need for a ag is one we ve seen several times already In our colors example we made the assumption that the best syntax would be LIGHT BLUE that is the adjectiv
37. playing around we never saw a unit like two But we did see a di erence of one and one from four is three Let s go with version b Now comes the real trick We must make ourselves believe without doubt that we have arrived at the situation described We have just poured o three gallons into the small container Suspending all disbelief we concentrate on how we did it How can we pour o three gallons into the small container If there had already been one gallon in the small container Suddenly we re over the hump The simple question now is how do we get one gallon in the small container We must have started with a full nine gallon container poured o four gallons twice leaving one gallon Then we transferred the one gallon to the small container Problem Solving Techniques 103 Figure 4 3 Achieving the end result Our nal step should be to check our logic by running the problem for wards again Here s another bene t of working backward If the problem is unsolvable working backward helps you quickly prove that it has no solution 4 8 Tip Recognize the auxiliary problem Before we ve solved a problem we have only a hazy notion of what steps or even how many steps may be required As we become more familiar with the problem we begin to recognize that our problem includes one or more subproblems that somehow seem di erent from the main outline of the proposed procedure In the problem we just s
38. procedures take over simultaneously automatically outside of the attention zone It seems apparent that a search is going on during the interval though not necessarily continuously much as in a large computer I would hazard the guess that the search rami es starts and stops reaches dead ends and begins afresh and eventually assembles an answer that is evaluated and then popped into conscious attention often in astonishingly full blown detail Tip Evaluate your solution Look for other solutions 4 11 You may have found one way of skinning the cat There may be other ways and some of them may be better Don t invest too much e ort in your rst solution without asking yourself for a second opinion Interview with a Software Inventor Interview with a Software Inventor 107 I m not just sleeping I m using my neocortex Donald A Burgess owner and president of Scientek Instrumentation Inc I have a few techniques I ve found useful over the years in designing anything to keep myself exible My rst rule is Nothing is impossible My second rule is Don t forget the object is to make a buck First examine the problem laying out two or three approaches on paper Then try the most appealing one to see if it works Carry it through Then deliber ately go all the way back to the beginning and start over Starting over has two values First it gives you a fresh approac
39. s going on For instance with SNAP invoked inside the main loop of a keystroke interpreter I can set it up to let me watch what s happening to a data structure as I enter keys And I can change what SNAP does without having to recompile the loop The situations in which it s preferable to use the tick and execute ap proach are those in which you need control over the address of the vector such as when vectoring through an element in a decision table or attempting to save restore the contents of the vector Summary In this chapter we ve examined the tradeo s between using the stack and using variables and other data structures Using the stack is preferable for testing and reusability but too many values manipulated on the stack by a single de nition hurts readability and writeability We also explored techniques for saving and restoring data structures and concluded with a study of vectored execution using DOER MAKE References 1 Michael Ham Why Novices Use So Many Variables Forth Dimensions vol 5 no 4 November December 1983 2 Daniel Slater A State Space Approach to Robotics The Journal of Forth Application and Research 1 1 September 1983 17 226 Handling Data Stacks and States EIGHT Minimizing Control Structures Control structures aren t as important in Forth as they are in other languages Forth programmers tend to write very complex applications in terms of short words with
40. source code but may continue to engulf the next line totally if needed 2 There should be more comment characters than source characters The company encourages long descriptive names greater than ten characters and allows the names to be counted as comment characters 3 Any conditional structure or application word should appear on a sepa rate line Noise words can be grouped together Indentation is used to show nested conditionals 160 Implementation Elements of Forth Style There are some di culties with this format however For one thing line by line commenting is time consuming even with a good screen editor Productivity can be sti ed especially when stopping to write the comments breaks your chain of thought Also you must also carefully ensure that the comments are up to date Very often code is corrected the revision is tested the change works and the programmer forgets to change the comments The more comments there are the more likely they are to be wrong If they re wrong they re worse than useless This problem can be alleviated if the project supervisor carefully reviews code and ensures the accuracy of comments Finally line by line commenting can allow a false sense of security Don t assume that because each line has a comment the application is well com mented Line by line commenting doesn t address the signi cant aspects of a de nition s operation What for instance is the th
41. the object is usually designed to stand alone It can t take ad vantage of tools provided by supporting components As a result it tends to duplicate code inside itself that will appear elsewhere in the application Some objects are even required to parse text in order to interpret their parameters Each may even use its own syntax A shameless waste of time and energy Finally because the object is constructed to recognize a nite set of pos sibilities it s di cult to make additions to the row of buttons when a new function is needed The tools inside the object have not been designed for reuse The idea of levels pervades the design of my own personal computer the IBM Personal Computer Besides the processor itself with its own machine instruction set of course there are these software levels the set of utilities written in assembler and burned into the system s ROM the disk operating system which invokes the utilities the high level language of choice which invokes the operating system and the utilities and nally any application using the language The ROM utilities provide the hardware dependent routines those that han dle the video screen disk drives and keyboard You invoke them by placing a control code in a certain register and generating the appropriate software interrupt For instance software interrupt 10H causes entry to the video routines There are 16 of these routines You load r
42. this process is much more di cult than it would seem If you don t know the problem till you solve it how can you possibly know how long it will take to solve it Careful planning is essential because things always take longer than you expect I have a theory about this based on the laws of probability 2 17 Tip The mean time for making a two hour addition to an application is approxi mately 12 hours Imagine the following scenario You re in the middle of writing a large appli cation when suddenly it strikes you to add some relatively simple feature You think it ll take about two hours so without further planning you just do it Consider That s two hours coding time The design time you don t count because you perceived the need and the design in a ash of brilliance while working on the application So you estimate two hours But consider the following possibilities 1 Your implementation has a bug After two hours it doesn t work So you spend another two hours recoding Total 4 2 OR before you implemented it you realized your initial design wouldn t work You spend two hours redesigning These two hours count Plus another two hours coding it Total 4 3 OR you implement the rst design before you realize the design wouldn t work So you redesign two more hours and reimplement two more Total 6 4 OR you implement the rst design code it nd a bug rewrite the code
43. we made the de nition more useful 7 8 Tip Unless it involves cluttering up the stack to the point of unreadability try to pass arguments via the stack rather than pulling them out of variables Kogge Most of the modularity of Forth comes from designing and treating Forth words as functions in the mathematical sense In my experience a Forth programmer usually tries quite hard to avoid de ning any but the most essential global variables I have a friend who has the sign Help stamp out variables above his desk and tries to write words with what is called referential transparency i e given the same stack inputs a word will always give the same stack outputs regardless of the more global context in which it is executed In fact this property is exactly what we use when we test words in isolation Words that do not have this property are signi cantly harder to test In a sense a named variable whose value changes frequently is the next worst thing to the now forbidden GOTO Earlier we suggested the use of local variables especially during the design phase to eliminate stack tra c It s important to note that in doing so the variables were referred to only within the one de nition In our example BOX receives four arguments from the stack and immediately loads them into local variables for its own use The four variables are not referred to outside of this de nition and the word behaves
44. 16 bit cell n represents a 16 bit number if the system uses a 32 bit cell n represents a 32 bit number Notation of Flags Table 5 2 shows three ways to represent a boolean ag To illustrate here are three versions of the same stack comment for the word TEXT at u a2 at u a2 t no match at u a2 f match The equal sign after the symbols t and f equates the ag outcome with its meaning The result side of the second version would be read true means no match Notation of Variable Possibilities Some de nitions yield a di erent stack e ect under di erent circumstances If the number of items on the stack remains the same under all conditions but the items themselves change you can use the vertical bar to mean or The following stack e ect comment describes a word that returns either the address of a le or if the requested le is not found zero address O undefined file If the number of items in a stack picture can vary in either the before or after picture you must write out both versions of the entire stack picture along with the double hyphen separated by the or symbol For instance Stack Abbreviation Standards 153 Table 5 2 Stack comment abbreviations n single length signed number d double length signed number u single length unsigned number ud double length unsigned number t triple length q quadruple
45. 2 the Regional bit in BITS as follows 3 4 1 Regional Satellite 5 2 Data Survey Satellite 6 7 For the location of the Regional bit 8 in BITS see the Design Specification 9 Section 3 2 7 5 4 1 2 10 10 11 HISTORY 12 13 14 15 Following that will come the lexicons loaded in uses order The nal lines of the chapter load screen normally invoke any needed initialization commands Some of the more style conscious Forthwrights begin each chapter with a preamble that discusses in general terms the theory of operation for the components described in the chapter Figure 5 3 is a sample preamble screen which demonstrates the format required at Moore Products Co Charles Moore no relation to Moore Products Co places less importance on the well organized hierarchical listing than I do Moore I structure applications hierarchically but not necessarily listings My listings are organized in a fairly sloppy way not at all hierarchically in the sense of primitives rst 142 Implementation Elements of Forth Style I use LOCATE LOCATE LOCATE LOCATE LOCATE also known as VIEW VIEW VIEW VIEW VIEW see the Handy Hint in Starting Forth Chapter Nine As a result the listing is much less carefully organized because I have LOCATE LOCATE LOCATE LOCATE LOCATE to nd things for me I never look at listings gt vs THRU On the subject of relative loading one popular way
46. Approach 39 4 The program is tested to determine if the functions were implemented correctly Mr Harris adds Software development in Forth seeks rst to nd the simplest solution to a given problem This is done by implementing selected parts of the problem separately and by ignoring as many constraints as possible Then one or a few constraints are imposed and the program is modi ed An excellent testimonial to the development testing model of design is evo lution From protozoa to tadpoles to people each species along the way has consisted of functional living beings The Creator does not appear to be a top down designer 2 1 Tip Start simple Get it running Learn what you re trying to do Add complexity gradually as needed to t the requirements and constraints Don t be afraid to restart from scratch The Value of Planning In the nine phases at the start of this chapter we listed ve steps before im plementation Yet in Chapter One we saw that an overindulgence in planning is both di cult and pointless Clearly you can t undertake a signi cant software project regardless of the language without some degree of planning Exactly what degree is ap propriate More than one Forth programmer has expressed high regard for Dave John son s meticulous approach to planning Johnson is supervisor at Moore Prod ucts Co in Springhouse Pennsylvania The rm specializes in industrial in stru
47. Despite Teleska s preference for a well planned project he suggests that the choice between a top down and bottom up approach may depend on the situ ation On two recent projects involving a lot of technical interface work I did the whole thing bottom up I milled around in a bunch of data sheets and technical descriptions of little crannies of the operating system I was dealing with I felt lost most of the time wondering why I ever took the job on Then nally I reached a critical mass of some sort and began putting small programs together that made small things happen I continued bottom up until I matched the target application 42 Analysis My top down sense was appalled at this procedure But I ve seen me go through this process successfully too many times to discount it for any pedagogical reasons And there is always this di cult phase which it seems no amount of linear thinking will penetrate Programming seems a lot more intuitive than we in this business tell each other it ought to be I think if the application elicits this sense of being lost I proceed bottom up If the application is in familiar territory then I ll probably use a more traditional by the book approach And here s another view At the time I interviewed him Michael Starling of Union Carbide was putting the nal touches on two applications involving user con gurable labo ratory automation and process control automation systems For the p
48. HUE BLACK 1 HUE BLUE 2 HUE GREEN 3 HUE CYAN 4 HUE RED 5 HUE MAGENTA 6 HUE BROWN 7 HUE GRAY De ning words are explained in Starting Forth Chapter Eleven By using a de ning word we save memory because each compiled colon de nition needs the address of EXIT EXIT EXIT EXIT EXIT to conclude the de nition In de ning eight words the use of a de ning word saves 14 bytes on a 16 bit Forth Also in a colon de nition each reference to a numeric literal requires the compilation of LIT LIT LIT LIT LIT or literal literal literal literal literal another 2 bytes per de nition If 1 and 2 are prede ned constants this costs another 10 bytes 24 total In terms of readability the de ning word makes it absolutely clear that all the colors it de nes belong to the same family of words The greatest strength of de ning words however arises when a series of de nitions share the same compile time behavior This topic is the subject of a later section Compile Time Factoring Factoring Out Functions into De ning Words 177 Factoring Criteria Armed with an understanding of factoring techniques let s now discuss several of the criteria for factoring Forth de nitions They include 1 Limiting the size of de nitions 2 Limiting repetition of code 3 Nameability 4 Information hiding 5 Simplifying the command interface 6 5 Tip Keep de nitions short We asked Moore How l
49. NOT valid IF eat card QUIT THEN CHECK CODE code entered MISmatches owner s code IF message QUIT THEN READ BUTTON adr of button s function device dependent primitive TRANSACT READ BUTTON EXECUTE 1 BUTTON WITHDRAW 2 BUTTON DEPOSIT WITHDRAW Query request current balance IF DISBURSE THEN DISBURSE disbursement available cash IF vend currency debit account ELSE message THEN DEPOSIT accept envelope credit account Using the Dictionary 8 1 Tip Give each function its own de nition By using the Forth dictionary properly we re not actually eliminating condi tionals we re merely factoring them out from our application code The Forth dictionary is a giant string case statement The match and execute functions are hidden within the Forth system 232 Minimizing Control Structures Moore In my accounting package if you receive a check from somebody you type the amount the check number the word FROM and the person s name 200 00 127 FROM ALLIED The word FROM takes care of that situation If you want to bill someone you type the amount the invoice number the word BILL and the person s name 1000 00 280 BILL TECHNITECH One word for each situation The dictionary is making the decision This notion pervades Forth itself To add a pair of single length numbers we use the command To add a pair of double length numbers we use
50. PROCEDURE READ CARD IF card is readable THEN CHECK OWNER ELSE eject card END PROCEDURE CHECK OWNER IF owner is valid THEN CHECK CODE ELSE eat card END PROCEDURE CHECK CODE IF code entered matches owner THEN TRANSACT ELSE message terminate session END PROCEDURE TRANSACT IF requests withdrawal THEN WITHDRAW ELSE DEPOSIT END PROCEDURE WITHDRAW Query If request current balance THEN DISBURSE END PROCEDURE DISBURSE IF disbursement available cash THEN vend currency debit account ELSE message END PROCEDURE DEPOSIT accept envelope credit account Details of the interface to the keypad may be hidden within the keypad lexicon READ BUTTON and BUTTON Of course Forth will allow you to take any of the three approaches Which do you prefer How to Eliminate Control Structures In this section we ll study numerous techniques for simplifying or avoiding conditionals Most of them will produce code that is more readable more maintainable and more e cient Some of the techniques produce code that is more e cient but not always as readable Remember therefore Not all of the tips will be applicable in all situations How to Eliminate Control Structures 231 Figure 8 3 Refactoring and or eliminating conditionals AUTOMATIC TELLER RUN READ CARD CHECK OWNER CHECK CODE TRANSACT READ CARD valid code sequence NOT readable IF eject card QUIT THEN CHECK OWNER owner is
51. STEPPERS 150 TESTING 1 AND LOAD This approach works here because conceptually we want to either load Screen 150 or if testing the next screen past it A Note on Tricks This sort of approach is often labeled a trick In the computing industry at large tricks have a bad rep A trick is simply taking advantage of certain properties of operation Tricks are used widely in engineering applications Chimneys eliminate smoke by taking advantage of the fact that heat rises Automobile tires provide trac tion by taking advantage of gravity Arithmetic Logic Units ALUs take advantage of the fact that subtract ing a number is the same as adding its two s complement These tricks allow simpler more e cient designs What justi es their use is that the assumptions are certain to remain true The use of tricks becomes dangerous when a trick depends on something likely to change or when the thing it depends on is not protected by information hiding Also tricks become di cult to read when the assumptions on which they re based aren t understood or explained In the case of replacing con ditionals with AND once this technique becomes part of every programmer s vocabulary code can become more readable In the case of a trick that is spe ci c to a speci c application such as the order in which data are arranged in a table the listing must clearly document the assumption used by the trick 8 12 Tip Use MI
52. See the section called Sharing Components later in this chapter Here s some suggestions to keep you from shooting yourself in the foot 7 7 Tip 1 Keep return stack operators symmetrical 2 Keep return stack operators symmetrical under all control ow condi tions 3 In factoring de nitions watch out that one part doesn t contain one return stack operator and the other its counterpart 4 If used inside a DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP return stack operators must by symmetrical within the loop and IIIII is no longer valid in code bounded by gt R gt R gt R gt R gt R and R gt R gt R gt R gt R gt For every gt R gt R gt R gt R gt R there must be a R gt R gt R gt R gt R gt in the same de nition Sometimes the operators will appear to be symmetrical but due to the control structure they aren t For instance BEGIN gt R WHILE R gt REPEAT If this construction is used in the outer loop of your application everything will run ne until you exit perhaps hours later when you ll suddenly blow up The problem The last time through the loop the resolving R gt R gt R gt R gt R gt has been skipped 206 Handling Data Stacks and States The Problem With Variables Although we handle data of immediate interest on the stack we depend on much information tucked away in variables ready for recurring access A piece of code can c
53. Ventura California I m no expert but it s clear that the methodology has much to o er With all this I believe that many of the ideas in Thinking Forth are as valid today as they were back then Certainly Charles Moore s comments remain a telling insight on the philosophy that triggered the development of Forth I with to thank Marlin Ouverson for his excellent job patiently strug gling against incompatible le formats and OCR errors to bring this reprint to life PREFACE Programming computers can be crazy making Other professions give you the luxury of seeing tangible proof of your e orts A watchmaker can watch the cogs and wheels a seamstress can watch the seams come together with each stitch But programmers design build and repair the stu of imagination ghostly mechanisms that escape the senses Our work takes place not in RAM not in an editor but within our own minds Building models in the mind is both the challenge and the joy of program ming How should we prepare for it Arm ourselves with better debuggers decompilers and disassemblers They help but our most essential tools and techniques are mental We need a consistent and practical methodology for Thinking about software problems That is what I have tried to capture in this book Thinking Forth is meant for anyone interested in writing software to solve problems It focuses on design and implementation deciding what you want to accomplish designi
54. a set of words to describe the room s attributes by building unseen data structures associated with the room EAST OF DRAGON LAIR WEST OF BRIDGE CONTAINING POT O GOLD etc 118 Detailed Design Problem Solving The commands of this game building language can simply be Forth words with Forth as the interpreter 2 If you re working with Programmable Array Logic PAL devices you d like a form of notation that lets you describe the behavior of the output pins in logical terms based on the states of the input pins A PAL programmer was written with wonderful simplicity in Forth by Michael Stolowitz 4 3 If you must create a series of user menus to drive your application you might want to rst develop a menu compiling language The words of this new language allow an application programmer to quickly program the needed menus while hiding information about how to draw borders move the cursor etc All of these examples can be coded in Forth as lexicons using the normal Forth interpreter without having to write a special purpose interpreter or compiler Moore A simple solution is one that does not obscure the problem with irrelevancies It s conceivable that something about the problem requires a unique interpreter But every time you see a unique interpreter it implies that there is something particularly awkward about the problem And that is almost never the case If you write your own interpreter the interpret
55. address of the slot that contains the symbol we want How do we get that address The ONER is the rst hand on the movable arm the position that COLUMN is already pointing to So the address we want is simply the address returned by COLUMN ONER COLUMN C EMIT Now let s write FIVER It computes the same slot address then adds one to get the next slot before fetching the symbol and emitting it FIVER COLUMN 1 C EMIT And TENER is TENER COLUMN 2 C EMIT These three de nitions are redundant Since the only di erence between them is the incidental o set we can factor the incidental o set out from the rest of the de nitions SYMBOL offset COLUMN C EMIT Now we can de ne ONER O SYMBOL FIVER 1 SYMBOL TENER 2 SYMBOL All that remains for us to do now is to decompose our complete decimal number into a series of decimal digits Based on the observations we ve already made this should be easy Figure 4 9 shows our completed listing Voila From problem to conceptual model to code Note this solution is not optimal The present volume does not address the optimization phase One more thought Depending on who uses this application we may want to add error checking Fact is the highest symbol we know is M the highest value we can represent is 3 999 or MMMCMXCIX 132 Detailed Design Problem Solving We might rede ne ROMAN as follows ROMAN
56. address where we found it if we don t nd a match we want the address of the last row of the functions table We can introduce the word LEAP see Appendix C which will work like EXIT EXIT EXIT EXIT EXIT it will simulate a semicolon Now we can write FUNCTION key adr of match NOMATCH FUNCTIONS DO DUP I IF DROP I LEAP THEN KEY LOOP DROP NOMATCH If we nd a match we LEAP not to LOOP LOOP LOOP LOOP LOOP but right out of the de nition leaving I the address at which we found it on the stack If we don t nd a match we fall through the loop and execute DROP NOMATCH which drops the key being searched for then leaves the address of the last row As we ve seen there may be times when a premature exit is appropriate even multiple exit points and multiple continue points Remember though this use of EXIT EXIT EXIT EXIT EXIT and R gt DROP R gt DROP R gt DROP R gt DROP R gt DROP is not consistent with structured programming in the strictest sense and requires great care For instance you may have a value on the stack at the beginning of a de nition which is consumed at the end A premature EXIT EXIT EXIT EXIT EXIT will leave the unwanted value on the stack Fooling with the return stack is like playing with re You can get burned But how convenient it is to have re Employing Good Timing 8 20 Tip Take the action when you know you ne
57. algorithm to cover this exception Print as many ONERS as necessary to add up to the value but if the digit is 4 print a ONER then a FIVER Hence 40 is XL 4 is IV This new rule works until the digit is 5 As we noticed before digits of ve and above begin with a FIVER symbol So we expand our rule again If the digit is 5 or more begin with a FIVER and subtract ve from the value otherwise do nothing Then print as many ONERS as necessary to add up to the value But if the digit is 4 print only a ONER and a FIVER This rule works until the digit is 9 In this case we must print a ONER preceding a what A ONER from the next higher decimal place the next row below Let s call this a TENER Our complete model then is If the digit is 5 or more begin with a FIVER and subtract ve from the value otherwise do nothing Then print as many ONERS as necessary to add up to the value But if the digit is 4 print only a ONER and a FIVER or if it s 9 print only a ONER and a TENER We now have an English language version of our algorithm But we still have some steps to go before we can run it on our computer In particular we have to be more speci c about the exceptions We can t just say Do a b and c But in such and such a case do something di erent because the computer will do a b and c before it knows any better Instead we have to check whether the exceptions apply before we do anything
58. appears to be less than the sum of the parts 2 In itemizing the pieces separate those you understand well enough to hazard a guess from those you don t For the second category give the customer a range 3 A bit of psychology always give your client some options Clients like options If you say This will cost you 6 000 the client will probably respond I d really like to spend 4 000 This puts you in the position of either accepting or going without a job But if you say You have a choice for 4 000 I ll make it walk through the hoop for 6 000 I ll make it jump through the hoop For 8 000 I ll make it dance through the hoop waving ags tossing confetti and singing Roll Out the Barrel Most customers opt for jumping through the hoop 2 18 Tip Everything takes longer than you think including thinking Reviewing the Conceptual Model The nal box on our iterative analytic wheel is labeled Show Model to Cus tomer With the tools we ve outlined in this chapter this job should be easy to do In documenting the requirements speci cation remember that specs are like snowmen They may be frozen now but they shift slip and melt away when the heat is on Whether you choose data ow diagrams or straight Forth pseudocode prepare yourself for the great thaw by remembering to apply the concepts of limited redundancy Show the documented conceptual model to the customer When the
59. authorship is important the programmer s initials three characters to the left of the date e g Chapter name Screen Name pg JPJ 06 10 83 Some Forth editors will enter the stamp for you at the press of a key A common form for representing dates is mm dd yy that is February 6 1984 would be expressed 02 06 84 An increasingly popular alternative uses ddMmmyy where Mmm is a three letter abbreviation of the month For instance 22Oct84 This form requires fewer characters than 10 22 84 and eliminates possible confusion between dates and months If your system has skip line see Appendix C you can write the comment line like this Chapter name Screen Name pg JPJ 06 10 83 146 Implementation Elements of Forth Style As with all comments use lower case or a mixture of lower and upper case text in the comment line One way to make the index of an application reveal more about the organization of the screens is to indent the comment line by three spaces in screens that continue a lexicon Figure 5 5 shows a portion of a list produced by INDEX INDEX INDEX INDEX INDEX in which the comment lines for the continuing screens are indented Tip Begin all de nitions at the left edge of the screen and de ne only one word per lines 5 5 Bad ARRIVING HELLO DEPARTING GOODBYE Good ARRIVING HELLO DEPARTING GOODBYE This rule makes
60. be normal most of the time With this syntax the programmer need merely precede the emphasized string with the simple word BRIGHT INSERT DISK IN BRIGHT LEFT DRIVE The 83 Standard now speci es a dumb and for those cases where an in terpretive version is wanted the new word has been added Happily in this new standard we re using the dictionary to make a decision by having two separate words The word tick has a similar history It was STATE STATE STATE STATE STATE dependent in g Forth and is now dumb in the 83 Standard Tick shares with dot quote the characteristic that a programmer might want to reuse either of these words in a higher level de nition and have them behave in the same way they do normally 8 3 Tip Words should not depend on STATE STATE STATE STATE STATE if a programmer might ever want to invoke them from within a higher level de nition and expect them to behave as they do interpretively ASCII ASCII ASCII ASCII ASCII works well as a STATE dependent word and so does MAKE MAKE MAKE MAKE MAKE See Appendix C 234 Minimizing Control Structures Nesting and Combining Conditionals Tip Don t test for something that has already been excluded 8 4 Take this example please PROCESS KEY KEY DUP LEFT ARROW IF CURSOR LEFT THEN DUP RIGHT ARROW IF CURSOR RIGHT THEN DUP UP ARROW IF CURSOR UP THEN DOWN ARROW IF CURSOR DOWN T
61. be very small usually smaller than equivalent assembly language programs The reason again is threaded code Each reference to a previously de ned word no matter how powerful uses only two bytes One of the most exciting new territories for Forth is the production of Forth chips such as the Rockwell R65F11 Forth based microprocessor 12 The chip includes not only hardware features but also the run time portions of the Forth language and operating system for dedicated applications Only Forth s architecture and compactness make Forth based micros possible Summary Forth has often been characterized as o beat totally unlike any other popular language in structure or in philosophy On the contrary Forth incorporates many principles now boasted by the most contemporary languages Structured design modularity and information hiding are among the buzzwords of the day 34 The Philosophy of Forth Some newer languages approach even closer to the spirit of Forth The language C for instance lets the programmer de ne new functions either in C or in assembly language as does Forth And as with Forth most of C is de ned in terms of functions But Forth extends the concepts of modularity and information hiding further than any other contemporary language Forth even hides the manner in which words are invoked and the way local arguments are passed The resulting code becomes a concentrated interplay of words the purest expression
62. bug Mark Twain Suit the action to the word the word to the action Shakespeare Hamlet Act III Henry Laxen a Forth consultant and author suggests that the most impor tant Forth development tool is a good thesaurus 4 Sometimes you ll think of an adequate word for a de nition but it doesn t feel quite right It may be months later before you realize that you fell short of the mark In the Roman numeral example in Chapter Four there s a word that handles the exception case numbers that are one less than the next symbol s value My rst choice was 4 0R 9 That s awkward but it was much later that I thought of ALMOST Most g Forth systems include the word VLIST which lists the names of all the words in the current vocabulary After many years someone realized that a nicer name is WORDS Not only does WORDS sound more pleasant by itself it also works nicely with vocabulary names For instance EDITOR WORDS or ASSEMBLER WORDS On the other hand Moore points out that inappropriate names can become a simple technique for encryption If you need to provide security when you re forced to distribute source you can make your code very unreadable by deliber ately choosing misleading names Of course maintenance becomes impossible 5 17 Tip Choose names that work in phrases Faced with a de nition you don t know what to call think about how the word will be used in context For instance SHUTTE
63. cally for source code It s possible in Forth to chain every screen of code to the next linking the entire listing together linearly like a lengthy parchment scroll This is not a useful approach Instead 5 1 Tip Structure your application listing like a book hierarchically An application may consist of Screens the smallest unit of Forth source Lexicons one to three screens enough to implement a component Chapters a series of related lexicons and Load screens analogous to a table of contents a screen that loads the chapters in the proper sequence Application load Screen Figure 5 1 is an example of an application load screen Since it resides in Screen 1 you can load this entire application by entering 1 LOAD 138 Implementation Elements of Forth Style Figure 5 1 Example of an application load screen Screen 1 0 QTF Load Screen 07 09 83 1 RELEASE 2 01 2 9 LOAD compiler tools language primitives 3 12 LOAD video primitives 4 21 LOAD editor 5 39 LOAD line display 6 48 LOAD formatter 7 69 LOAD boxes 8 81 LOAD deferring 9 90 LOAD framing 10 96 LOAD labels figures tables 11 102 LOAD table of contents generator 12 13 14 15 The individual load commands within this screen load the chapters of the application For instance Screen 12 is the load screen for the video primitives chapter As a reference tool the appli
64. changes as we move further from machine code Let s examine each of these misconceptions one by one Where to Begin I asked Moore how he would go about developing a particular application a game for children As the child presses the digits on the numeric keypad from zero to nine that same number of large boxes would appear on the screen Moore I don t start at the top and work down Given that exact problem I would write a word that draws a box I d start at the bottom and I d end up with a word called GO which monitored the keyboard How much of that is intuitive 90 Preliminary Design Decomposition Perhaps some degree of it I know where I m going so I don t have to start there But also it s more fun to draw boxes than to program a keyboard I ll do the thing that s most fun in order to get into the problem If I have to clean up all those details later that s the price I pay Are you advocating a fun down approach Given that you re doing it in a free spirit fashion yes If we were giving a demonstration to a customer in two days I d do it di erently I would start with the most visible thing not the most fun thing But still not in that hierarchical sequence top down I base my approach on more immediate considerations such as impressing the customer getting something to work or showing other people how it s going to work to get them interested If you de ne a level as ne
65. indicated with hex FF which is the signed number 1 all bits set WITHIN WITHIN WITHIN WITHIN WITHIN can be de ned in high level like this WITHIN n lo hi 1 gt R 1 OVER lt SWAP R gt lt AND From Chapter Eight The implementation of LEAP LEAP LEAP LEAP LEAP will depend on how your system implements DO DO DO DO DO LOOP LOOP LOOP LOOP LOOPs If DO DO DO DO DO keeps two items on the return stack the index and the limit LEAP LEAP LEAP LEAP LEAP must drop both of them plus one more return stack item to exit LEAP R gt R gt 2DROP R gt DROP If DO DO DO DO DO keeps three items on the return stack it must be de ned LEAP R gt R gt 2DROP R gt R gt 2DROP From Chapter Eight 277 APPENDIX D Answers to Further Thinking Problems Chapter Three 1 The answer depends on whether you believe that other components will need to know the numeric code associated with each key Usually this would not be the case The simpler more compact form is therefore preferable Also in the rst version to add a new key would require a change in two places 2 The problem with the words RAM ALLOT and THERE are that they are time dependent we must execute them ina particular order Our solution then will be to devise an interface to the RAM allocation pointer that is not dependent on order the way to do this is to have a single word which does both functions transpar
66. interdepen dence The principle of component programming applies to team management as well as to software design We ll call the set of words which describe a com ponent a lexicon One meaning of lexicon is a set of words pertaining to a particular eld of interest The lexicon is your interface with the component from the outside Figure 1 8 In this book the term lexicon refers only to those words of a component that are used by name outside of a component A component may also contain de nitions written solely to support the externally visible lexicon We ll call the supporting de nitions internal words The lexicon provides the logical equivalents to the data objects and algo rithms in the form of names The lexicon veils the component s data structures and algorithms the how it works It presents to the world only a conceptual model of the component described in simple words the what it does These words then become the language for describing the data structures and algorithms of components written at a a higher level The what of one component becomes the how of a higher component Written in Forth an entire application consists of nothing but compo nents Figure 1 9 show show a robotics application might be decomposed You could even say that each lexicon is a special purpose compiler writ ten solely for the purpose of supporting higher level application code in the
67. interface Because of Forth s dictionary structure control is not an issue De nitions are invoked by being named In this section when we use the term interface we re referring to data When it comes to data interfaces between modules traditional wisdom says only that interfaces should be carefully designed with a minimum of complexity The reason for the care of course is that each module must implement its own end of the interface Figure 3 8 This means the presence of redundant code As we ve seen redundant code brings at least two problems bulky code and poor maintainability A change to the interface of one module will a ect the interface of the opposite module Figure 3 8 Traditional view of the interface as a junction There s more to good interface design than that Allow me to introduce a design element which I call the interface component The purpose an interface component is to implement and hide information about the data interface between two or more other components Figure 3 9 The Interface Component 85 Figure 3 9 Use of the interface component 3 4 Tip Both data structures and the commands involved in the communication of data between modules should be localized in an interface component Let me give an example from my own recent experience One of my hobbies is writing text formatter editors I ve written two of them including the one on which I am writing this
68. is most likely areas that give the most satisfying feedback get the juices owing areas in which the approach decided upon will greatly a ect other areas or which will determine whether the stated problem can be solved at all things you should show the customer for mutual understanding things you can show the investors if necessary for the rent 3 6 Where to Begin 91 No Segregation Without Representation The second way in which levels can interfere with optimal solutions is by encour aging segregation of the levels A popular design construct called the object typi es this dangerous philosophy An object is a portion of code that can be invoked by a single name but that can perform more than one function To select a particular function you have to invoke the object and pass it a parameter or a group of parameters You can visualize the parameters as representing a row of buttons you can push to make the object do what you want The bene t of designing an application in terms of objects is that like a component the object hides information from the rest of the application making revision easier There are several problems though First the object must contain a complicated decision structure to determine which function it must perform This increases object size and decreases performance A lexicon on the other hand provides all usable functions by name for you to invoke directly Second
69. it easier to nd a de nition in the listing When de ni tions continue for more than one line the subsequent lines should always be indented VARIABLE VARIABLE VARIABLE VARIABLE VARIABLEs and CONSTANT CONSTANT CONSTANT CONSTANT CONSTANTs should also be de ned one per line See Sam ples of Good Commenting Style in Appendix E This leaves room for an ex planatory comment on the same line The exception is a large family of words de ned by a common de ning word which do not need unique comments Figure 5 5 The output of INDEX showing indented comment lines 90 Graphics Chapter load JPJ 06 10 83 91 Dot drawing primitives JPJ 06 10 83 92 Line drawing primitives JPJ 06 11 83 93 Line drawing primitives JPJ 06 10 83 94 Line drawing primitives JPJ 09 02 83 95 Scaling rotation JPJ 06 10 83 96 Scaling rotation JPJ 02 19 84 97 Scaling rotation JPJ 02 19 84 98 Scaling rotation JPJ 02 19 84 99 Boxes JPJ 06 10 83 100 Circles JPJ 06 10 83 101 Circles JPJ 06 10 83 102 Circles JPJ 06 10 83 Screen Layout 147 0 HUE BLACK 1 HUE BLUE 2 HUE GREEN 3 HUE CYAN 4 HUE RED 5 HUE MAGENTA 5 6 Tip Leave lots of room at the bottom of the screen for later additions On your rst pass ll each screen no more than half with code The iterative approach demands that you sketch out the components of your application rst then iteratively esh them out until a
70. language would allow Make Breakfast to be written Structured programming languages include control structure operators such as IF and THEN to ensure a modularity of control ow As you can see indentation is important for readability since all the instructions within Figure 1 4 Using a structured language INSTRUCTION INSTRUCTION Decide in a hurry IF HURRIED THEN INSTRUCTION INSTRUCTION Make eggs INSTRUCTION ELSE INSTRUCTION INSTRUCTION Make cereal INSTRUCTION ENDIF INSTRUCTION INSTRUCTION Clean up 8 The Philosophy of Forth each module are still written out rather than being referred to by name e g MAKE CEREAL The nished program might take ten pages with the ELSE on page ve Designing from the Top How does one go about designing these modules A methodology called top down design proclaims that modules should be designed in order starting with the most general overall module and working down to the nitty gritty modules Proponents of top down design have witnessed shameful wastes of time due to lack of planning They ve learned through painful experience that trying to correct programs after they ve been written a practice known as patching is like locking the barn door after the horse has bolted So they o er as a countermeasure this o cial rule of top down program ming Write no code until you have planned every last detail Because programs are
71. length c 7 bit character value b 8 bit byte boolean ag or t true f false a or adr address acf address of code eld apf address of parameter eld as pre x address of s d as a pair source destination lo hi lower limit upper limit inclusive count 0 o set i index m mask x don t care data structure notation An o set is a di erence expressed in absolute units such as bytes An index is a di erence expressed in logical units such as elements or records FIND apf len t found f not found This comment indicates that if the word is found three arguments are returned with the ag on top otherwise only a false ag is returned Note the importance of the second Its omission would indicate that the de nition always returned three arguments the top one being a ag If you prefer you can write the entire stack e ect twice either on the same line separated by three spaces DUP if zero n n if non zero n n n or listed vertically FIND found apf len t not found f 154 Implementation Elements of Forth Style Data Structure Comments A data structure comment depicts the elements in a data structure For example here s the de nition of an insert bu er called INSERT CREATE INSERT 64 ALLOT 1 63text The faces curly brackets begin and end the structure comment th
72. ling algorithms Calculations vs Data Structures vs Logic We ve stated before that the best solution to a problem is the simplest adequate one for any problem we should strive for the simplest approach Suppose we must write code to ful ll this speci cation if the input argument is 1 the output is 10 if the input argument is 2 the output is 12 if the input argument is 3 the output is 14 There are three approaches we could take Calculation n 1 2 10 120 Detailed Design Problem Solving Data Structure CREATE TABLE 10 C 12 C 14 C n 1 TABLE C Logic n CASE 1 OF 10 ENDOF 2 OF 12 ENDOF 3 OF 14 ENDOF ENDCASE In this problem calculation is simplest Assuming it is also adequate speed is not critical calculation is best The problem of converting angles to sines and cosines can be implemented more simply at least in terms of lines of code and object size by calculating the answers than by using a data structure But for many applications requiring trig it s faster to look up the answer in a table stored in memory In this case the simplest adequate solution is using the data structure In Chapter Two we introduced the telephone rate problem In that prob lem the rates appeared to be arbitrary so we designed a data structure Full Rate Lower Rate Lowest Rate First Min 30 22 12 Add 1 Mins 12 10 06 Using a data structure was simpler than trying to inve
73. long as that number 14 remains a secret to the component and won t be used elsewhere you don t need to de ne it as constant Just use the number 14 in both de nitions RECORD 14 RECORDS RECORD 14 RECORD On the other hand if the value will be needed outside of the component or if it s used several times within the component and there s a good chance that it will change you re better o hiding it behind a name 14 CONSTANT RECORD RECORD RECORD RECORD RECORD RECORD NEGATE RECORD The name RECORD by convention means bytes per record Example A Tiny Editor Let s apply decomposition by component to a real problem It would be nice to design a large application right here in Chapter Three but alas we don t 74 Preliminary Design Decomposition have the room and besides we d get sidetracked in trying to understand the application Instead we ll take a component from a large application that has already been decomposed We ll design this component by decomposing it further into subcomponents Imagine that we must create a tiny editor that will allow users to change the contents of input elds on their terminal screen For instance the screen might look like this Name of Member Justine Time The editor will provide three modes for users to change the contents of the input eld Overwrite Typing ordinary characters overwrites any characters t
74. looking ahead the other to indicate we re printing the table of contents The word DISPLAY requires that both ags be false in order to actually display anything There are two ways to accomplish the latter approach depending on how you want to decompose the problem First we could nest one condition within the other DISPLAY the original definition always does the output VARIABLE LOOKAHEAD t looking ahead lt DISPLAY gt LOOKAHEAD NOT IF DISPLAY THEN VARIABLE TOC t setting table of contents DISPLAY TOC NOT IF lt DISPLAY gt THEN DISPLAY checks that we re not setting the table of contents and invokes lt DISPLAY gt which in turn checks that we re not looking ahead and invokes DISPLAY In the development cycle the word DISPLAY that always does the out put was originally called DISPLAY Then a new DISPLAY was de ned to include the lookahead check and the original de nition was renamed DISPLAY thus 214 Handling Data Stacks and States adding a level of complexity backward without changing any of the code that used DISPLAY Finally when the table of contents feature was added a new DISPLAY was de ned to include the table of contents check and the previous DISPLAY was renamed lt DISPLAY gt That s one approach to the use of two variables Another is to include both tests within a single word DISPLAY LOOKAHEAD TOC OR NOT IF DISP
75. merely have to rede ne two of these words perhaps like this CREATE FRAME 1024 ALLOT VARIABLE CURSOR The rest of your code can remain intact 6 13 Tip Factor calculations algorithms out of de nitions that display results 182 Factoring This is really a question of decomposition Here s an example The word de ned below pronounced people to paths computes how many paths of communication there are between a given number of people in a group This is a good thing for managers of programmer teams to know the number of communication paths increases drastically with each new addition to the team PEOPLE gt PATHS people paths DUP 1 2 This de nition does the calculation only Here s the user de nition that invokes PEOPLE gt PATHS to perform the calculation and then displays the result PEOPLE people PEOPLE gt PATHS PATHS This produces 2 PEOPLE 1 PATHS 3 PEOPLE 3 PATHS 5 PEOPLE 10 PATHS 10 PEOPLE 45 PATHS Even if you think you re going to perform a particular calculation only once to display it in a certain way believe me you re wrong You will have to come back later an factor out the calculation part Perhaps you ll need to display the information in a right justi ed column or perhaps you ll want to record the results in a data base you never know But you ll always have to factor it so you might as well do it right
76. must associate the keys with two possible sets of named procedures We can write our keystroke interpreter as a decision table worrying about the implementation later Key Not inserting Inserting Ctrl D DELETE INSERT OFF Ctrl I INSERT ON INSERT OFF backspace BACKWARD INSERT lt left arrow BACKWARD INSERT OFF right arrow FORWARD INSERT OFF return ESCAPE INSERT OFF any printable OVERWRITE INSERT We ve placed the possible types of keys in the left column what they do nor mally in the middle column and what they do in insert mode in the right column To implement what happens when backspace is pressed while in Insert Mode we add a new procedure INSERT lt BACKWARD SLIDE lt move the cursor backwards on top of the last character typed then slide everything to the right leftward covering the mistake This table seems to be the most logical expression of the problem at the current level We ll save the implementation for later Chapter Eight Now we ll demonstrate the tremendous value of this approach in terms of maintainability We ll throw ourselves a curve a major change of plans Maintaining a Component based Application How well will our design fare in the face of change Envision the following scenario We originally assumed that we could refresh the video display simply by retyping the eld every time a key is pressed We even implemented the code on our personal computer with
77. new section I chose to refactor LETTER to a ner resolution taking out the C The usage was then either LETTER C or LETTER C This change required me to search through the listing changing all instances of LETTER to LETTER C But I should have done that in the rst place separating the computation of the letter s address from the operation to be performed on the address Similar to our injunction against repetition of code Tip Look for repetition of patterns 6 10 If you nd yourself referring back in the program to copy the pattern of previously used words then you may have mixed in a general idea with a speci c application The part of the pattern you are copying perhaps can be factored out as an independent de nition that can be used in all the similar cases Tip Be sure you can name what you factor 6 11 Moore If you have a concept that you can t assign a single name to not a hyphenated name but a name it s not a well formed concept The ability to assign a name is a necessary part of decomposition Certainly you get more con dence in the idea Factoring Criteria 181 Compare this view with the criteria for decomposing a module espoused by structured design in Chapter One According to that method a module should exhibit functional binding Which can be veri ed by describing its function in a single non compound sentence Forth s atom a name is an order of magnitude more r
78. of abstract thought As a result Forth programmers tend to be more productive and to write tighter more e cient and better maintainable code Forth may not be the ultimate language But I believe the ultimate language if such a thing is possible will more closely resemble Forth than any other contemporary language References 1 O J Dahl E W Dijkstra and C A R Hoare Structured Program ming London Academic Press 1972 2 Niklaus Wirth Program Development by Stepwise Re nement Com munications of ACM 14 No 4 1971 221 27 3 W P Stevens G J Myers and L L Constantine Structured De sign IBM Systems Journal Vol 13 No 2 1974 4 David L Parnas On the Criteria To Be Used in Decomposing Systems into Modules Communications of the ACM December 1972 5 Barbara H Liskov and Stephen N Zilles Speci cation Tech niques for Data Abstractions IEEE Transactions on Software Engineer ing March 1975 6 David L Parnas Designing Software for Ease of Extension and Con traction IEEE Transactions on Software Engineering March 1979 7 Dewey Val Shorre Adding Modules to Forth 1980 FORML Pro ceedings p 71 8 Mark Bernstein Programming in the Laboratory unpublished paper 1983 9 James R Bell Threaded Code Communications of ACM Vol 16 No 6 370 72 10 Robert B K DeWar Indirect Threaded Code Communications of ACM Vol 18 No 6 331
79. of subroutines inhibits performance Second Forth allows you to de ne words either in high level or in machine language Either way no special calling sequence is needed You can write a new de nition in high level and having veri ed that it is correct rewrite it in assembler without changing any of the code that uses it In a typical application perhaps 20 of the code will be running 80 of the time Only the most often used time critical routines need to be machine coded The Forth system itself is largely implemented in machine code de nitions so you ll have few application words that need to be coded in assembler Third Forth applications tend to be better designed than those written entirely in assembler Forth programmers take advantage of the language s prototyping capabilities and try out several algorithms before settling on the one best suited for their needs Because Forth encourages change it can also be called the language of optimization Forth doesn t guarantee fast applications It does give the programmer a creative environment in which to design fast applications Capability Forth can do anything any other language can do usually easier 32 The Philosophy of Forth The best top down designs of mice and young men At the low end nearly all Forth systems include assemblers These sup port control structure operators for writing conditionals and loops using struc tured programming techniques They u
80. on the relative sizes of a and b Since adding 45 or not is the same as adding 45 or adding 0 the di erence between the two outcomes is purely numeric We can rid ourselves of a decision and simply compute n a b lt 45 AND Moore The 45 AND is faster than the IF and certainly more graceful It s simpler If you form a habit of looking for instances where you re calculating this value from that value then usually by doing arithmetic on the logic you get the same result more cleanly I don t know what you call this It has no terminology it s merely doing arithmetic with truth values But it s perfectly valid and someday boolean algebra and arithmetic expressions will accommodate it In books you often see a lot of piece wise linear approximations that fail to express things clearly For instance the expression Choosing Control Structures 241 x O for t lt O x 1 for t O This would be equivalent to t O lt 1 AND as a single expression not a piece wise expression I call these ags hybrid values because they are booleans truth values being applied as data numeric values Also I don t know what else to call them We can eliminate numeric ELSE clauses as well where both results are non zero by factoring out the di erence between the two results For instance STEPPERS TESTING IF 150 ELSE 151 THEN LOAD can be simpli ed to
81. only initializing a few variables to anything other than zero Saving and Restoring a State Variables have the characteristic that when you change their contents you clobber the value that was there before Let s look at some of the problems this can create and some of the things we can do about them BASE BASE BASE BASE BASE is a variable that indicates the current number radix for all numeric input and output The following words are commonly found in Forth systems DECIMAL 10 BASE HEX 16 BASE Suppose we ve written a word that displays a dump of memory Ordinarily we work in decimal mode but we want the dump in hexadecimal So we write 210 Handling Data Stacks and States DUMP a HEX code for the dump DECIMAL This works most of the time But there s a presumption that we want to come back to decimal mode What if it had been working in hexadecimal and wants to come back to hexadecimal Before we change the base to HEX HEX HEX HEX HEX we have to save its current value When we re done dumping we restore it This means we have to tuck away the saved value temporarily while we format the dump The return stack is one place to do this DUMP a BASE gt R HEX code for dump R gt BASE If things get too messy we may have to de ne a temporary variable VARIABLE OLD BASE DUMP a BASE OLD BASE HEX code for dump OLD BASE BASE
82. our rst pass design when we add refresh Part b shows our optimized design with the refresh modules ex panded Notice that we re now testing the Insert ag twice within this single leg of the outer loop But worse there s a bug in this design Can you nd it In both cases overwriting and inserting the pointer is incremented before the refresh In the case of overwrite we re displaying the new character in the wrong position In the case of insert we re typing the remainder of the line but not the new character Granted this is an easy problem to x We need only move the refresh modules up before Increment Pointer The point here is How did we miss it By getting preoccupied with control ow structure a super cial element of program design 84 Preliminary Design Decomposition In contrast in our design by components the correct solution fell out nat urally because we used the refresh component inside the editing component Also we used OVERWRITE inside INSERT By decomposing our application into components which use one another we achieved not only elegance but a more direct path to correctness The Interface Component In computer science terminology interfacing between modules has two aspects First there s the way other modules invoke the module this is the control interface Second there s the way other modules pass and receive data to and from the module this is the data
83. positive or zero You can use CHOOSE to produce a ag the phrase Summary 259 2 CHOOSE produces a random ag of zero or one false or true Write a phrase to choose a number at random between 0 and 19 inclusive or between 20 and 0 260 Minimizing Control Structures EPILOGUE Forth s Effect on Thinking Forth is like the Tao it is a Way and is realized when followed Its fragility is its strength its simplicity is its direction Michael Ham winning entry in Mountain View Press s contest to describe Forth in twenty ve words or less To help extract something of the Forth philosophy I conducted a poll among several Forth users in which I asked How has Forth a ected your thinking Have you found yourself applying Forth like principles in other areas Here are some of the replies Mark Bernstein is president of Eastgate Systems Inc in Cambridge Mas sachusetts and holds a doctorate from the department of chemistry at Harvard University I rst met Forth while working in laser chemistry I was trying to build a rather complicated controller for a new laser spectrometer The original plans called for a big green box full of electronics The Interface Nobody had built this particular kind of instrument before that s why we were doing it and the list of things we wanted the computer to handle changed every couple of weeks After a few months I had hundreds of pages of assembly langua
84. problem Because Forth is small and because Forth gives its users control over their machines Forth lets humans control their applications It s just silly to expect scientists to sit in front of a lab computer playing twenty questions with packaged software Forth used properly lets a scientist instruct the computer instead of letting the computer instruct the scientist In the same sense that in baseball a batter is supposed to feel the bat as an extension of himself Forth is human scaled and helps convince you that the computer s achievements and its failures are also your own Raymond E Dessy is Professor of Chemistry at Virginia Polytechnic Institute and State University Blacksburg Virginia As I attempted to understand the nature and structure of the language C I found myself drawing upon the knowledge I had of the organization and approach of Forth This permitted me to understand convoluted or high fog coe cient sections describing C I have found the Forth approach is an ideal platform upon which to build an understanding and an educational framework for other languages and operating system concepts Jerry Boutelle is owner of Nautilus Systems in Santa Cruz California which markets the Nautilus Cross compiler Forth has changed my thinking in many ways Since learning Forth I ve coded in other languages including assembler BASIC and FORTRAN I ve found that I used the same kind of decomposition w
85. s run time behavior in the usual way comment its compile time behavior separately beginning with the label Compile 5 13 For instance IF Compile address of unresolved branch IMMEDIATE In the case of compiling words the rst comment describes the run time be havior which is usually the syntax for using the word The second comment describes what the word actually does in compiling which is of less importance to the user Other examples ABORT Compile text Occasionally a compiling word may exhibit a di erent behavior when it is invoked outside a colon de nition Such words to be fastidious about it require three comments For instance ASCII c Compile c Interpret c c IMMEDIATE Appendix E includes two screens showing good commenting style Vertical Format vs Horizontal Format The purpose of commenting is to allow a reader of your code to easily determine what s going on But how much commenting is necessary To determine the level of commenting appropriate for your circumstances you must ask yourself two questions Who will be reading my code Comments for Compiling Words 159 How readable are my de nitions There are two basic styles of commenting to choose from The rst style often called the vertical format includes a step by step description of the process in the manner
86. safely as a function Programmers unaccustomed to a language in which data can be passed implicitly don t always utilize the stack as fully as they should Michael Ham suggests the reason may be that beginning Forth users don t trust the stack 1 He admits to initially feeling safer about storing values into variables than leaving them on the stack No telling what might happen with all that thrashing about on the stack he felt It took some time for him to appreciate that if words keep properly to themselves using the stack only for their expected input and output and cleaning up after themselves they can be looked upon as sealed systems I could put the count on the stack at the beginning of the loop go through the complete routine for each group and at the end the count would emerge back on top of the stack not a hair out of place 208 Handling Data Stacks and States Shot from a cannon on a fast moving train hurtling between the blades of a windmill and expecting to grab a trapeze dangling from a hot air balloon I told you Ace there were too many variables Local and Global Variables Initialization As we saw earlier a variable that is used exclusively within a single de nition or single lexicon hidden from other code is called a local variable A variable used by more than one lexicon is called a global variable As we ve seen in an earlier chapter a set of global variables that collecti
87. second We have to get up to answer the phone anyway The repetition of UP GET is ugly not nearly as readable as the solution using OR but in some cases desirable 236 Minimizing Control Structures Choosing Control Structures Tip The most elegant code is that which most closely matches the problem Choose the control structure that most closely matches the control ow problem 8 7 Case Statements A particular class of problem involves selecting one of several possible paths of execution according to a numeric argument For instance we want the word SUIT to take a number representing a suit of playing cards 0 through 3 and display the name of the suit We might de ne this word using nested IF IF IF IF IF ELSE ELSE ELSE ELSE ELSE THEN THEN THEN THEN THENs like this SUIT suit DUP O IF HEARTS ELSE DUP 1 IF SPADES ELSE DUP 2 IF DIAMONDS ELSE CLUBS THEN THEN THEN DROP We can solve this problem more elegantly by using a case statement Here s the same de nition rewritten using the Eaker case statement format named after Dr Charles E Eaker the gentleman who proposed it 1 SUIT suit CASE O OF HEARTS ENDOF 1 OF SPADES ENDOF 2 OF DIAMONDS ENDOF 3 OF CLUBS ENDOF ENDCASE The case statement s value lies exclusively in its readability and writeability There s no e ciency improvement either in obj
88. that helps you test debug and interact with your code is a waste If your application is large try using a default width of three with the ability to switch 178 Factoring to a full length name to avoid a speci c collision Width refers to a limit on the number of characters stored in the name eld of each dictionary header If the application is still too big switch to a Forth with multiple dictio naries on a machine with extended memory or better yet a 32 bit Forth on a machine with 32 bit addressing A related fear is that over factoring will decrease performance due to the overhead of Forth s inner interpreter Again it s true that there is some penalty for each level of nesting But ordinarily the penalty for extra nesting due to proper factoring will not be noticeable If you timings are that tight the real solution is to translate something into assembler Tip Factor at the point where you feel unsure about your code where complexity approaches the conscious limit 6 6 Don t let your ego take over with an I can lick this attitude Forth code should never feel uncomfortably complex Factor Moore Feeling like you might have introduced a bug is one reason for factoring Any time you see a doubly nested DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP that s a sign that something s wrong because it will be hard to debug Almost always take the inner DO DO DO DO DO LOOP LOOP LOOP L
89. the rst time The few times you might get away with it aren t worth the trouble The word dot is a prime example Dot is great 99 of the time but occasionally it does too much Here s what it does in fact in Forth 83 n DUP ABS 0 lt S ROT SIGN gt TYPE SPACE But suppose you want to convert a number on the stack into an ASCII string and store it in a bu er for typing later Dot converts it but also types it Or suppose you want to format playing cards in the form 10C for ten of clubs You can t use dot to display the 10 because it prints a nal space Here s a better factoring found in some Forth systems n a DUP ABS 0 lt S ROT SIGN gt n TYPE SPACE We nd another example of failing to factor the output function from the calculation function in our own Roman numeral example in Chapter Four Given our solution we can t store a Roman numeral i8n a bu er or even center it in a eld A better approach would have been to use HOLD HOLD HOLD HOLD HOLD instead of EMIT EMIT EMIT EMIT EMIT Information hiding can also be a reason not to factor For instance if you factor the phrase Factoring Criteria 183 SCR BLOCK into the de nition FRAME SCR BLOCK remember you are doing so only because you may want to change the location of the editing frame Don t blindly replace all occurrences of the phrase with the new word FR
90. the application by words that incremented the number of apples when shipments arrive decremented the number when apples are sold and checked the cur rent number for inventory control When it became necessary to handle a second type of apples the wrong approach would have been to add that complexity to all the shipment sales inventory words The right approach was the one we took to add the com plexity at the bottom that is to APPLES itself This principle can be realized in many ways In Chapter Seven under The State Table we used state tables to implement the words WORKING and PRETENDING which changed the meaning of a group of variables Later in that chapter we used vectored execution to de ne VISIBLE and INVISIBLE to change the meanings of TYPE EMIT SPACES and CR and thereby easily change all the formatting code that uses them Tip Don t test for something that can t possibly happen 8 15 Many contemporary programmers are error checking happy There s no need for a function to check an argument passed by another component in the system The calling program should bear the responsibility for not exceeding the limits of the called component Tip Reexamine the algorithm 8 16 Moore Redesigning 249 A lot of conditionals arise from fuzzy thinking about the problem In servo control theory a lot of people think that the algorithm for the servo ought to be di erent when the
91. the simplest thing is to factor the condition CONDITIONS A B OR C AND ACTIVE CONDITIONS IF TUMBLE JUGGLE JUMP THEN LAZY CONDITIONS IF SIT EAT SLEEP THEN Depending on the number of repetitions of the same condition and control structure you may even want to factor out both Watch this CONDITIONALLY A B OR C AND NOT IF R gt DROP THEN ACTIVE CONDITIONALLY TUMBLE JUGGLE JUMP LAZY CONDITIONALLY SIT EAT SLEEP The word CONDITIONALLY CONDITIONALLY CONDITIONALLY CONDITIONALLY CONDITIONALLY may depending on the condition alter the control ow so that the remaining words in each de nition will be skipped This approach has certain disadvantages as well We ll discuss this technique pros and cons in Chapter Eight More benign examples of factoring out control structures include case statements which eliminate nested IF IF IF IF IF ELSE ELSE ELSE ELSE ELSE THEN THEN THEN THEN THENs and multiple exit loops the BEGIN BEGIN BEGIN BEGIN BEGIN WHILE WHILE WHILE WHILE WHILE WHILE WHILE WHILE WHILE WHILE WHILE WHILE WHILE WHILE WHILE REPEAT REPEAT REPEAT REPEAT REPEAT construct We ll also discuss these topics in Chapter Eight Factoring Out Control Structures Themselves 175 Factoring Out Names It s even good to factor out names when the names seem almost but not quite the same Examine the following terrible example of
92. the command D A less e cient more complex approach would be a single command that somehow knows which type of numbers are being added Forth is e cient because all these words FROM and BILL and and D can be implemented without any need for testing and branching Tip Use dumb words 8 2 This isn t advice for TV writers It s another instance of using the dictionary A dumb word is one that is not state dependent but instead has the same behavior all the time referentially transparent A dumb word is unambiguous and therefore more trustworthy A few common Forth words have been the source of controversy recently over this issue One such word is which prints a string In its simplest form it s allowed only inside a colon de nition TEST THIS IS A STRING Actually this version of the word does not print a string It compiles a string along with the address of another de nition that does the printing at run time This is the dumb version of the word If you use it outside a colon de nition it will uselessly compile the string not at all what a beginner might expect To solve this problem the FIG model added a test inside that de termined whether the system was currently compiling or interpreting In the rst case would compile the string and the address of the primitives in the second case it would TYPE it became two completely di erent words housed together
93. the conceptual model by describing the algorithm s and data structure s 3 Recognize auxiliary de nitions 4 Determine what auxiliary de nitions and techniques are already available 5 Describe the algorithm with pseudocode 6 Implement it by working backwards from existing de nitions to the in puts 7 Implement any missing auxiliary de nitions 8 If the lexicon contains many names with strong elements in common design and code the commonalities as internal de nitions then implement the external de nitions We ll discuss the rst two steps in depth Then we ll engage in an extended example of designing a lexicon Forth Syntax At this point in the development cycle you must decide how the words in your new lexicon will be used in context In doing so keep in mind how the lexicon will be used by subsequent components 4 13 Tip In designing a component the goal is to create a lexicon that will make your later code readable and easy to maintain 110 Detailed Design Problem Solving Each component should be designed with components that use it in mind You must design the syntax of the lexicon so that the words make sense when they appear in context Hiding interrelated information within the component will ensure maintainability as we ve seen At the same time observe Forth s own syntax Rather than insisting on a certain syntax because it seems familiar you may save yourself from writin
94. the speed penalty for checking some of the conditions is too great We might write CHOW MEIN BEAN SPROUTS CHOW MEIN RECIPE AND IF CHOW MEIN PREPARE THEN But suppose it s going to take us a long time to hunt through our recipe le to see if there s anything on chow mein Obviously there s no point in undertaking the search if we have no bean sprouts in the fridge It would be more e cient to write CHOW MEIN BEAN SPROUTS IF CHOW MEIN RECIPE IF CHOW MEIN PREPARE THEN THEN We don t bother looking for the recipe if there are no sprouts Another exception arises if any term is probably not true By eliminating such a condition rst you avoid having to try the other conditions 8 6 Tip When multiple conditions have dissimilar weights in likelihood or calculation time nest conditionals with the term that is least likely to be true or easiest to calculate on the outside Trying to improve performance in this way is more di cult with the OR con struct For instance in the de nition RISE PHONE RINGS ALARM RINGS OR IF UP GET THEN we re testing for the phone and the alarm even though only one of them needs to ring for us to get up Now suppose it were much more di cult to determine that the alarm clock was ringing We could write RISE PHONE RINGS IF UP GET ELSE ALARM CLOCK RINGS IF UP GET THEN THEN If the rst condition is true we don t waste time evaluating the
95. the stack but it is by no means the best solution What s nasty about it is the expense of creating four named variables headers and all solely for use within this one routine If you re target compiling an application that will not require headers in the dictionary the only loss will be the 8 bytes in RAM for the variables In Forth systems of the future headers may be separated into other pages of memory anyway again the loss will be only 8 bytes Let me repeat This example represents a worst case situation and occurs rarely in most Forth applications If words are well factored then each word is designed to do very little Words that do little generally require few arguments In this case though we are dealing with two points each represented by two coordinates Can we change the design First LINE may be too primitive a primitive It requires four arguments because it can draw lines between any two points diagonally if necessary In drawing our box we may only need perfectly vertical and horizontal lines In this case we can write the more powerful but less speci c words VERTICAL and HORIZONTAL to draw these lines Each requires only three ar guments the starting position s x and y and the length This factoring of function simpli es the de nition of BOX Or we might discover that this syntax feels more natural to the user 10 10 ORIGIN 30 30 BOX where ORIGIN sets a two element pointer to the origin th
96. to load a series of adjacent screens is with the word gt pronounced next block This word causes the interpreter to immediately cease interpreting the current screen and begin interpreting the next higher numbered screen If your system provides gt you must choose between using the THRU THRU THRU THRU THRU command in your chapter load screen to load each series of screens or linking each series together with the arrows and LOADing only the rst in the series You can t do both you d end up loading most of the screens more than once The nice thing about the arrows is this suppose you change a screen in the middle of a series then reload the screen The rest of the series will automatically get loaded You don t have to know what the last screen is That s also the nasty thing about the arrows There s no way to stop the loading process once it starts You may compile a lot more screens than you need to test this one screen To get analytical about it there are three things you might want to do after making the change just described 1 load the one screen only to test the change 2 load the entire section in which the screen appears or 3 load the entire remainder of the application The use of THRU THRU THRU THRU THRU seems to give you the greatest control Some people consider the arrow to be useful for letting de nitions cross screen boundaries In fact gt is the only way to compile a
97. uence and use BLUE LIGHT Summary The use of logic and conditionals as a signi cant structural element in program ming leads to overly complicated di cult to maintain and ine cient code In this chapter we ve discussed several ways to minimize optimize or eliminate unnecessary conditional structures As a nal note Forth s downplaying of conditionals is not shared by most contemporary languages In fact the Japanese are basing their fth generation computer project on a language called PROLOG for PROgram ming in LOGic in which one programs entirely in logic It will be interesting to see the battle lines forming as we ponder the question To IF IF IF IF IF or not to IF IF IF IF IF In this book we ve covered the rst six steps of the software development cycle exploring both the philosophical questions of designing software and practical considerations of implementing robust e cient readable software We have not discussed optimization validation debugging document ing project management Forth development tools assembler de nitions uses and abuses of recursion developing multiprogrammed applications or target compilation But that s another story References 1 Charles Eaker Just in Case Forth Dimensions II 3 p 37 For Further Thinking You have the word CHOOSE which takes an argument n and returns a random number between 0 and n 1 The result is always
98. value name SHORT returns reversed boolean name SHORT address of boolean name SHORT operates conditionally name DUP maybe DUP enable name CLOCK or absence of symbol name BLINKING disable name CLOCK BLINKING Memory save value of name CURSOR restore value of name CURSOR store into name SECONDS fetch from name INDEX name of bu er name INSERT address of name name S address of pointer to name name TYPE exchange especially bytes gt name lt gt MOVE lt Numeric Types byte length Cname C 2 cell size 2 s complement Dname D integer encoding mixed 16 and 32 bit operator Mname M 3 cell size Tname T 4 cell size Qname Q unsigned encoding Uname U Naming Conventions 287 Meaning Form Example Output Printing print item name S print numeric name denotes type name D U print right justi ed name R U R Quantity per name SIDE Sequencing start lt name lt end name gt gt Text string follows delimited by name ABORT text text or string operator name COMPARE similar to pre x in BASIC superstring array name COLORS How to Pronounce the Symbols store fetch sharp or number as in RECORDS dollar percent caret amp ampersand star left paren paren right paren paren dash not plus equals faces traditionally c
99. write DOER ANNOUNCE LONG MAKE ANNOUNCE CR You re in a large hall with a huge throne CR covered with a red velvet canopy MAKE ANNOUNCE CR You re in the throne room The word ANNOUNCE will display either message First we say LONG to initialize ANNOUNCE to the long message Now we can test ANNOUNCE and nd that it prints the long message Having done that however it continues to make ANNOUNCE display the short message If we test ANNOUNCE a second time it prints the short message And it will for ever more until we say LONG again In e ect we re queuing behaviors We can queue any number of behaviors letting each one set the next The following example though not terribly practical illustrates the point DOER WHERE VARIABLE SHIRT VARIABLE PANTS VARIABLE DRESSER VARIABLE CAR ORDER specify search order MAKE WHERE SHIRT MAKE WHERE PANTS MAKE WHERE DRESSER MAKE WHERE CAR MAKE WHERE O HUNT a O find location containing 17 ORDER 5 O DO WHERE DUP O OVER 17 OR IF LEAVE ELSE DROP THEN LOOP 224 Handling Data Stacks and States In this code we ve created a list of variables then de ned an ORDER in which they are to be searched The word HUNT looks through each of them looking for the rst one that contains a 17 HUNT returns either the address of the correct variable or a zero if none have the value It does this by simply executing WHE
100. 0K le or worse a 20K de ni tion Perhaps a nice compromise would be a le based system that allows nested loading and encourages the use of very small named les Most likely though the more experienced Forth programmers would not use named les longer than 5K to 10K So what s the bene t Some might answer that rhetorical question It s easier to remember names than numbers If that s so then prede ne those block numbers as constants e g 90 CONSTANT FRAMING Then to load the framing section enter FRAMING LOAD Or to list the section s load block enter FRAMING LIST It s a convention that names of sections end in ING Of course to minimize the hassle of the screen based approach you need good tools including editor commands that move lines of source from one screen to another and words that slide a series of screens forward or back within the listing Disk Partitioning The nal aspect of the well organized listing involves standardizing an arrange ment for what goes where on the disk These standards must be set by each shop or department or individual programmer depending on the nature of the work Figure 5 4 shows a typical department s partitioning scheme In many Forth shops it s considered desirable to begin sections of code on screen numbers that are evenly divisible by three Major divisions on a disk should be made on boundaries evenly divisible by thirty
101. 0b By being able to change the root s ca pability the user can change the capability of all the commands that use the root Returning to the word processor for an example a fairly primitive routine is the one that starts a new page It s used by the word that starts a new line when we run out of lines we must start a new page The word that starts a new line in turn is used by the routine that formats words on the line when the next word won t t on the current line we invoke NEWLINE This uses hierarchy demands that we de ne NEWPAGE early in the application The problem One of the advanced components includes a routine that must be invoked by NEWPAGE Speci cally if a gure or table appears in the 88 Preliminary Design Decomposition Figure 3 10 Two ways to add advanced capabilities middle of text but at format time won t t on what s left of the page the formatter defers the gure to the next page while continuing with the text This feature requires somehow getting inside of NEWPAGE so that when NEWPAGE is next executed it will format the deferred gure at the top of the new page NEWPAGE terminate page with footer start new page with header HOLDOVER How can NEWPAGE invoke HOLDOVER if HOLDOVER is not de ned until much later Decomposition by Sequential Complexity 89 While it s theoretically possible to organize the listing so that the advance capabil
102. 4 PICK to fetch its contents But you must write n 5 PICK because with n on the stack the address is now in the fth position Code like this is hard to read and harder to modify Make Stack Drawings When you do have a cumbersome stack situation to solve it s best to work it out with paper and pencil Some people even make up forms such as the one in Figure 7 1 Done formally like this instead of on the back of your phone bill stack commentaries serve as nice auxiliary documentation Stack Tips 7 4 Tip Make sure that stack e ects balance out under all possible control ows In the stack commentary for CMOVE gt CMOVE gt CMOVE gt CMOVE gt CMOVE gt in Figure 7 1 the inner brace represents the contents of the DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP The stack depth upon exiting the loop is the same as upon entering it one element Within the outer braces the stack result of the IF IF IF IF IF clause is the same as that of the ELSE ELSE ELSE ELSE ELSE clause one element left over What that leftover element represents doesn t matter as symbolized by the x next to THEN THEN THEN THEN THEN 7 5 Tip When doing two things with the same number perform the function that will go underneath rst For example COUNT a a 1 DUP C SWAP 1 SWAP where you rst get the count is more e ciently written COUNT a a 1 DUP 1 SWAP C
103. 5 18 I once saw some Forth code published in a magazine in which the author seemed hell bent on purging all vowels from his names inventing such eyesores as DSPL BFR for display bu er Other writers seem to think that three characters magically says it all coining LEN for length Such practices re ect thinking from a bygone age Forth words should be fully spelled out Feel proud to type every letter of INITIALIZE or TERMINAL or BUFFER These are the words you mean The worst problem with abbreviating a word is that you forget just how you abbreviated it Was that DSPL or DSPLY Another problem is that abbreviations hinder readability Any program ming language is hard enough to read without compounding the di culty Still there are exceptions Here are a few 1 Words that you use extremely frequently in code Forth employs a hand ful of commands that get used over and over but have little or no intrinsic meaning Choosing Names The Art 165 But there are so few of them and they re used so often they become old friends I would never want to type on a regular basis DEFINE END DEFINITION FETCH STORE PRINT COMPILE Interestingly most of these symbols don t have English counterparts We use the phrase colon de nition because there s no other term we say comma a number into the dictionary because it s not exactly compiling and there s no other term 2 Words tha
104. AME because you may change the de nition of FRAME and there will certainly be times when you really want SCR SCR SCR SCR SCR BLOCK BLOCK BLOCK BLOCK BLOCK 6 14 Tip If a repeated code fragment is likely to change in some cases but not others factor out only those instances that might change If the fragment is likely to change in more than one de nition Knowing when to hide information requires intuition and experience Having made many design changes in your career you ll learn the hard way which things will be most likely to change in the future You can never predict everything though It would be useless to try as we ll see in the upcoming section called The Iterative Approach in Implemen tation 6 15 Tip Simplify the command interface by reducing the number of commands It may seem paradoxical but good factoring can often yield fewer names In Chapter Five we saw how six simple names LEFT RIGHT MOTOR SOLENOID ON and OFF could do the work of eight badly factored hyphenated names As another example I found two de nitions circulating in one department in which Forth had recently introduced Their purpose was purely instructional to remind the programmer which vocabulary was CURRENT and which was CONTEXT CONTEXT CONTEXT 8 NFA ID CURRENT CURRENT 8 NFA ID If you typed CONTEXT the system would respond CONTEXT FORTH 184 Factoring They w
105. BN 0 13 917568 7 It is impossible to disassociate language from science or science from language because every natural science always involves three things the sequence of phenomena on which the science is based the abstract concepts which call these phenomena to mind and the words in which the concepts are expressed To call forth a concept a word is needed to portray a phenomenon a concept is needed All three mirror one and the same reality Antoine Lavoisier 1789 Contents Contents vii Preface to the 1994 Edition xi Preface xiii The Philosophy of Forth 1 An Armchair History of Software Elegance 2 The Super ciality of Structure 18 Looking Back and Forth 19 Component Programming 20 Hide From Whom 24 Hiding the Construction of Data Structures 25 But Is It a High Level Language 27 The Language of Design 31 The Language of Performance 32 Summary 34 References 35 Analysis 37 The Nine Phases of the Programming Cycle 38 The Iterative Approach 39 The Value of Planning 40 The Limitations of Planning 42 The Analysis Phase 45 De ning the Interfaces 49 De ning the Rules 52 De ning the Data Structures 59 Achieving Simplicity 60 Budgeting and Scheduling 66 Reviewing the Conceptual Model 68 References 69 Preliminary Design Decomposition 71 Decomposition by Component 72 Example A Tiny Editor 74 Maintaining a Component based Applicatio
106. CES or SPACES spaces to type This de nition takes as its incoming argument a number that represents the number of spaces to type ELEMENT element element 2 TABLE This de nition converts an index which it consumes into an address within a table of 2 byte elements corresponding to the indexed element PAD scratch pad HERE 80 This de nition returns an address of a scratch region of memory Occasionally readability is best served by including both types of com ment In this case the purpose comment should appear last For instance BLOCK n a ensure block n in buffer at a Tip Indicate the type of comment by ordering input stream comments rst stack e ect comments second purpose comments last 5 11 For example GET name a get first match If you prefer to use then write GET name a get first match If necessary you can put the purpose comment on a second line WORD name c a scan for string delimt d by c leave at a Purpose Comments 157 Comments for De ning Words The de nition of a de ning word involves two behaviors that of the de ning word as it de nes its child compile time behavior and that of the child itself run time behavior These two behaviors must be commented separately 5 12 Tip Comment a de ning word
107. CES THEN DUP I 6 U R 2 LOOP 6 U R 2 LOOP 6 U R 2 LOOP 6 U R 2 LOOP 6 U R 2 LOOP DROP The problem arises when you write a de nition called CDUMP designed to format the output according to bytes not cells 220 Handling Data Stacks and States Figure 7 7 DOER and MAKE DOER JOE ok JOE Creates a DOER word called JOE that does nothing TEST MAKE JOE 1 ok JOE TEST MAKE JOE 1 De nes a new word called TEST TEST ok JOE TEST MAKE JOE 1 MAKE redirects JOE so that it points to the code after MAKE JOE and stops execution of the rest of TEST JOE 1 ok Executes the code that JOE points to 1 CDUMP a O DO I 16 MOD O IF CR DUP I 5 U R 2 SPACES THEN DUP I C 4 U R LOOP C 4 U R LOOP C 4 U R LOOP C 4 U R LOOP C 4 U R LOOP DROP The code within these two de nitions is identical except for the fragments in boldface But factoring is di cult because the fragments occur inside the DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP Here s a solution to this problem using DOER DOER DOER DOER DOER MAKE MAKE MAKE MAKE MAKE The code that changes has been replaced with the word UNIT whose behavior is vectored by the code in DUMP and CDUMP Recognize that 11111 LOOP LOOP LOOP LOOP LOOP has the same e ect as LOOP LOOP LOOP LOOP LOOP DOER UNIT a increment display byte or cell
108. DUP STACK gt BAD POP n STACK 2 STACK STACK STACK lt BAD The word PUSH takes a value from o of your data stack and pushes it onto this new stack POP is the opposite popping a value from o the new stack and onto Forth s data stack In a real application you might want to change the names PUSH and POP to better match their conceptual purposes Sharing Components Tip It s legal to use a component for an additional purpose besides its intended one provided 1 All uses of the component are mutually exclusive 2 Each interrupting use of the component restores the component to its previous state when nished Otherwise you need an additional component or level of complexity 7 9 We ve seen a simple example of this principle with the return stack The return stack is a component of the Forth system designed to hold return addresses and thereby serve as an indication of where you ve been and where you re going To use the return stack as a holder for temporary values is possible and in many cases desirable Problems occur when one of the above restrictions is ignored In my text formatter the output can go invisible This feature has two purposes 1 for looking ahead to see whether something will t and 2 for formatting the table of contents the entire document is formatted and page numbers are calculated without anything actually being displayed Applicati
109. FTWING serves for both LEFTWING and for the bit of code after MAKE When MAKE redirects execution of the DOER DOER DOER DOER DOER word it also stops execution of the word in which it appears When you invoke LEFTWING for example MAKE redirects PLATFORM and exits Invoking LEFTWING does not cause proponent to be printed Figure 7 7 demonstrates this point using a conceptualized illustration of the dictionary If you want to continue execution you can use the word AND AND AND AND AND in place of semicolon AND AND AND AND AND terminates the code that the DOER DOER DOER DOER DOER word points to and resumes execution of the de nition in which it appears as you can see in Figure 7 8 Finally you can chain the making of DOER DOER DOER DOER DOER words in series by not using AND AND AND AND AND Figure 7 9 explains this better than I could write about it Using DOER MAKE There are many occasions when the DOER MAKE construct proves bene cial They are 1 To change the state of a function when external testing of the state is not necessary The words LEFTWING and RIGHTWING change the state of the word PLATFORM 2 To factor out internal phrases from similar de nitions but within control structures such as loops Consider the de nition of a word called DUMP designed to reveal the contents of a speci ed region of memory DUMP a O DO I 16 MOD O IF CR DUP I 5 U R 2 SPA
110. HEN This version is ine cient because all four tests must be made regardless of the outcome of any of them If the key pressed was the left arrow key there s no need to check if it was some other key Instead you can nest the conditionals like this PROCESS KEY KEY DUP LEFT ARROW IF CURSOR LEFT ELSE DUP RIGHT ARROW IF CURSOR RIGHT ELSE DUP UP ARROW IF CURSOR UP ELSE CURSOR DOWN THEN THEN THEN DROP Tip Combine booleans of similar weight 8 5 Many instances of doubly nested IF IF IF IF IF THEN THEN THEN THEN THEN structures can be simpli ed by com bining the ags with logical operators before making the decision Here s a doubly nested test PLAY SATURDAY IF WORK FINISHED IF GO PARTY THEN THEN The above code uses nested IF IF IF IF IFs to make sure that it s both Saturday and the chores are done before it boogies on down Instead let s combine the conditions logically and make a single decision PLAY SATURDAY WORK FINISHED AND IF GO PARTY THEN It s simpler and more readable The logical or situation when implemented with IF IF IF IF IF THEN THEN THEN THEN THENs is even clumsier Nesting and Combining Conditionals 235 RISE PHONE RINGS IF UP GET THEN ALARM CLOCK RINGS IF UP GET THEN This is much more elegantly written as RISE PHONE RINGS ALARM RINGS OR IF UP GET THEN One exception to this rule arises when
111. HO Good PUSH HEAVE HO Bad subsequent lines not indented three spaces RIDDANCE thing never to darken again DARKEN NEVER AGAIN Good RIDDANCE thing never to darken again DARKEN NEVER AGAIN Bad lack of phrasing GETTYSBURG 4 SCORE 7 YEARS AGO Good GETTYSBURG 4 SCORE 7 YEARS AGO Phrasing is a subjective art I ve yet to see a useful set of formal rules Simply strive for readability Comment Conventions Appropriate commenting is essential There are ve types of comments stack e ect comments data structure comments input stream comments purpose comments and narrative comments A stack e ect comment shows the arguments that the de nition consumes from the stack and the arguments it returns to the stack if any A data structure comment indicates the position and meaning of elements in a data structure For instance a text bu er might contain a count in the rst byte and 63 free bytes for text An input stream comment indicates what strings the word expects to see in the input stream For example the Forth word FORGET scans for the name of a dictionary entry in the input stream 150 Implementation Elements of Forth Style A purpose comment describes in as few words possible what the de ni tion does How the de nition works is not the concern of the purpose comment A narrative comment appears amidst a de nition to explain what i
112. IBM Systems Journal vol 13 no 2 1974 Copyright 1974 by International Business Machines Corporation 2 G A Miller The Magical Number Seven Plus or Minus Two Some Limits on our Capacity for Processing Information Psychol Rev vol 63 pp 81 97 Mar 1956 3 Kim R Harris De nition Field Address Conversion Operators Forth 83 Standard Forth Standards Team Summary 195 SEVEN Handling Data Stacks and States Forth handles data in one of two ways either on the stack or in data structures When to use which approach and how to manage both the stack and data structures are the topics of this chapter The Stylish Stack The simplest way for Forth words to pass arguments to each other is via the stack The process is simple because all the work of pushing and popping values to and from the stack is implicit Moore The data stack uses this idea of hidden information The arguments being passed between subroutines are not explicit in the calling sequence The same argument might ripple through a whole lot of words quite invisibly even below the level of awareness of the programmer simply because it doesn t have to be referred to explicitly One important result of this approach Arguments are unnamed They reside on the stack not in named variables This e ect is one of the reasons for Forth s elegance At the same time it s one of the reasons badly written Forth code can be un
113. ILEAGE charge MILES MILES 6 FIRST charge 1MINUTE ASSISTANCE MILEAGE 7 ADDITIONAL charge MINUTES MILEAGE 8 TOTAL minutes total charge 9 1 ADDITIONAL FIRST The current charge either rst minute additional minute or per mile is expressed as an o set into the table 0 2 or 4 An optimization note we ve implemented the two dimensional table as a set of three one dimensional tables each pointed to by RATE This approach eliminates the need for a multiplication that would otherwise be needed to im plement a two dimensional structure The multiplication can be prohibitively slow in certain cases Two Dimensional Decision Table We ll hark back to our Tiny Editor example in Chapter Three to illustrate a two dimensional decision table In Figure 8 5 we re constructing a table of functions to be performed when various keys are pressed The e ect is similar to that of a case statement but there are two modes Normal Mode and Insert Mode Each key has a di erent behavior depending on the current mode The rst screen implements the change of the modes If we invoke NORMAL MODE we ll go into Normal Mode Using Decision Tables 245 INSERTING MODE enters Inserting Mode The next screen constructs the function table called FUNCTIONS The table consists of the ASCII value of a key followed by the address of the routine to be performed when
114. ING ENDOF DELETEKEY OF DELETE ENDOF ENDCASE REPEAT Summary 95 b Keystroke interpreter EDITOR BEGIN MORE WHILE KEY CASE 72 OF CURSOR UP ENDOF 80 OF CURSOR DOWN ENDOF 77 OF CURSOR gt ENDOF 75 OF CURSOR lt ENDOF 82 OF INSERTING ENDOF 83 OF DELETE ENDOF ENDCASE REPEAT 2 This problem is an exercise in information hiding Let s suppose we have a region of memory outside of the Forth dictionary which we want to allocate for data structures for whatever reason The region of memory begins at HEX address C000 We want to de ne a series of arrays which will reside in that memory We might do something like this HEX C000 CONSTANT FIRST ARRAY 8 bytes C008 CONSTANT SECOND ARRAY 6 bytes C00C CONSTANT THIRD ARRAY 100 bytes Each array name de ned above will return the starting address of the appropriate array But notice we had to compute the correct starting address for each array based on how many bytes we had already allocated Let s try to automate this by keeping an allocation pointer called gt RAM showing where the next free byte is We rst set the pointer to the beginning of the RAM space VARIABLE gt RAM C000 gt RAM Now we can de ne each array like this x gt RAM CONSTANT FIRST ARRAY 8 gt RAM gt RAM CONSTANT SECOND ARRAY 6 gt RAM gt RAM CONSTANT THIRD ARRAY 100 gt RAM Notice that after de ning each array we increment the point
115. INTS computes the number of x y coordinates in the table this value becomes the constant POINTS used as the limit in DRAW s DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP This construct lets you add or subtract points from the table without worrying about the number of points there are Forth computes this for you Compile Time Factoring through De ning Words Let s examine a series of approaches to the same problem de ning a group of related addresses Here s the rst try HEX 01A0 CONSTANT BASE PORT ADDRESS BASE PORT ADDRESS CONSTANT SPEAKER BASE PORT ADDRESS 2 CONSTANT FLIPPER A BASE PORT ADDRESS 4 CONSTANT FLIPPER B BASE PORT ADDRESS 6 CONSTANT WIN LIGHT DECIMAL The idea is right but the implementation is ugly The only elements that change from port to port are the numeric o set and the name of the port being Figure 6 2 Another example of limiting compile time redundancy P x y C C CREATE POINTS 10 10 P 10 11 P 10 12 P 10 13 P 10 14 P 11 10 P 12 10 P 13 10 P 14 10 P 11 12 P 12 12 P 13 12 P 14 12 P HERE POINTS table 2 CONSTANT POINTS POINTS i x y 2 POINTS DUP 1 C SWAP C DRAW POINTS 0 DO I POINTS XY ASCII EMIT LOOP 190 Factoring de ned everything else repeats This repetition suggests the use of a de ning word The following approach which is more readable combines all the repeated code into the does part of a de
116. IT THEN Tip Don t set a ag set the data 8 23 If the only purpose to setting a ag is so that later some code can decide between one number and another you re better o saving the number itself The colors example in Chapter Six s section called Factoring Criteria illustrates this point The purpose of the word LIGHT is to set a ag which indicates whether we want the intensity bit to be set or not While we could have written LIGHT TRUE LIGHT to set the ag and LIGHT IF 8 OR THEN to use the ag this approach is not quite as simple as putting the intensity bit mask itself in the variable Employing Good Timing 255 LIGHT 8 LIGHT and then simply writing LIGHT OR to use it 8 24 Tip Don t set a ag set the function Vector This tip is similar to the previous one and lives under the same restriction If the only purpose to setting a ag is so that later some code can decide between one function and another you re better o saving the address of the function itself For instance the code for transmitting a character to a printer is di erent than for slapping a character onto a video display A poor implementation would de ne VARIABLE DEVICE O video 1 printer VIDEO FALSE DEVICE PRINTER TRUE DEVICE TYPE a DEVICE IF code for printer ELSE code for video THEN
117. LAY THEN But in this particular case yet another approach can simplify the whole mess We can use a single variable not as a ag but as a counter We de ne VARIABLE INVISIBLE t invisible DISPLAY INVISIBLE O IF DISPLAY THEN INVISIBLE 1 INVISIBLE VISIBLE 1 INVISIBLE The lookahead code begins by invoking INVISIBLE which bumps the counter up one Non zero is true so DISPLAY will not do the output After the lookahead the code invokes VISIBLE which decrements the counter back to zero false The table of contents code also begins with VISIBLE and ends with INVI SIBLE If we re running the table of contents while we come upon a lookahead the second invocation of VISIBLE raises the counter to two The subsequent invocation of INVISIBLE decrements the counter to one so we re still invisible and will remain invisible until the table of contents has been run Note that we must substitute 0 0 0 0 0 for NOT NOT NOT NOT NOT The 83 Standard has changed NOT NOT NOT NOT NOT to mean one s complement so that 1 NOT 1 NOT 1 NOT 1 NOT 1 NOT yields true By the way I think this was a mistake This use of a counter may be dangerous however It requires parity of command usage two VISIBLEs yields invisible That is unless VISIBLE clips the counter VISIBLE INVISIBLE 1 O MAX INVISIBLE The State Table A single variable can expre
118. LUE by itself will return a 1 on the stack but the phrase LIGHT BLUE will return a 9 The adjective LIGHT sets ag which is used by the hues then cleared If necessary for readability we still might want to de ne 8 HUE DARK GRAY 14 HUE YELLOW Again through this approach we ve achieved a more pleasant syntax and shorter object code Factoring Criteria 187 6 16 Tip Don t factor for the sake of factoring Use clich s The phrase OVER SWAP may seem commonly in certain applications I converts an address and count into an ending address and starting address appropriate for a DO LOOP DO LOOP DO LOOP DO LOOP DO LOOP Another commonly seen phrase is 1 SWAP It rearranges a rst number and last number into the last number plus one and rst number order required by DO DO DO DO DO It s a little tempting to seize upon these phrases and turn them into words such as for the rst phrase RANGE Moore That particular phrase OVER OVER OVER OVER OVER SWAP SWAP SWAP SWAP SWAP is one that s right on the margin of being a useful word Often though if you de ne something as a word it turns out you use it only once If you name such a phrase you have trouble knowing exactly what RANGE does You can t see the manipulation in your mind OVER OVER OVER OVER OVER SWAP SWAP SWAP SWAP SWAP has greater mnemonic value than RANGE I call these phrases
119. Leo Brodie THINKING FORTH A Language and Philosophy for Solving Problems Includes interviews with Forth s inventor CHARLES H MOORE and other Forth thinkers Leo Brodie is a writer programmer consultant teacher and world renowned authority on Forth He was a technical writer for Forth Inc and has been an independent consultant since 1981 for such clients as IBM NCR and Lockheed He is also the author of Starting Forth Prentice Hall 1982 Leo Brodie THINKING FORTH A Language and Philosophy for Solving Problems c 1984 1994 and 2004 by Leo Brodie Attribution NonCommercial ShareAlike 2 0 You are free to copy distribute display and perform the work to make derivative works Under the following conditions Attribution You must give the original author credit Noncommercial You may not use this work for commercial purposes Share Alike If you alter transform or build upon this work you may distribute the resulting work only under a license identical to this one For any reuse or distribution you must make clear to others the license terms of this work Any of these conditions can be waived if you get permission from the copyright holder Your fair use and other rights are in no way a ected by the above This is a human readable summary of the Legal Code the full license You can download the electronic version from http thinking forth sourceforge net IS
120. MARKER MARKER MARKER MARKER Now AND AND AND AND AND stores HERE HERE HERE HERE HERE the location of the second string of code be ginning with SPACE SPACE SPACE SPACE SPACE into the cell previously containing zero Now MAKE MAKE MAKE MAKE MAKE has a pointer to the place to resume execution The phrase IF gt R THEN will leave on the return stack the address of the code beginning with SPACE SPACE SPACE SPACE SPACE Thus execution will skip over the code between MAKE MAKE MAKE MAKE MAKE and AND AND AND AND AND and continue with the remainder of the de nition up to semicolon The word UNDO UNDO UNDO UNDO UNDO ticks the name of a DOER DOER DOER DOER DOER word and stores the address of NOTHING NOTHING NOTHING NOTHING NOTHING into it One nal note on some systems you may encounter a problem If you use MAKE MAKE MAKE MAKE MAKE outside of a colon de nition to create a forward reference you may not be able to nd the most recently de ned word For instance if you have REFRAIN DO DAH DO DAH MAKE SONG CHORUS REFRAIN your system might think that refrain has not been de ned The problem is due to the placement of SMUDGE As a solution try rearranging the order of de nitions or if necessary put MAKE code inside a de nition which you then execute SETUP MAKE SONG CHORUS REFRAIN SETUP In Laboratory Microsystems PC FORTH 2 0 the UNSMUDGE on line 9 h
121. N MIN MIN MIN MIN and MAX MAX MAX MAX MAX for clipping 242 Minimizing Control Structures Suppose we want to decrement the contents of the variable VALUE but we don t want the value to go below zero 1 VALUE VALUE 1 IF O VALUE THEN This is more simply written VALUE 1 O MAX VALUE In this case the conditional is factored within the word MAX MAX MAX MAX MAX Using Decision Tables Tip Use decision tables 8 13 We introduced these in Chapter Two A decision table is a structure that con tains either data a data table or addresses of functions a function table arranged according to any number of dimensions Each dimension represents all the possible mutually exclusive states of a particular aspect of the prob lem At the intersection of the true states of each dimension lies the desired element the piece of data or the function to be performed A decision table is clearly a better choice than a conditional structure when the problem has multiple dimensions One Dimensional Data Table Here s an example of a simple one dimensional data table Our application has a ag called FREEWAY which is true when we re referring to freeways false when we re referring to city streets Let s construct the word SPEED LIMIT which returns the speed limit depending on the current state Using IF IF IF IF IF THEN THEN THEN THEN THEN we would write SPEED LIMIT
122. OOP LOOP and make a word And having factored out a word for testing there s no reason for putting it back You found it useful in the rst place There s no guarantee you won t need it again Here s another facet of the same principle Tip Factor at the point where a comment seems necessary 6 7 Particularly if you feel a need to remind yourself what s on the stack this may be a good time to make a break Suppose you have BALANCE DUP xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx balance SHOW which begins by computing the balance and ends by displaying it In the meantime several lines of code use the balance for purposes of their own Since it s di cult to see that the balance is still on the stack when SHOW executes the programmer has interjected a stack picture This solution is generally a sign of bad factoring Better to write Factoring Criteria 179 REVISE balance xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx xxx BALANCE DUP REVISE SHOW No narrative stack pictures are needed Furthermore the programmer now has a reusable testable subset of the de nition 6 8 Tip Limit repetition of code The second reason for factoring to eliminate repeated fragments of code is even more important than reducing the size of de nitions Moore When a word is just a piece of something it s useful for clarity or debugging but not n
123. OT Our present concern is that each time we de ne an array we must RAM ALLOT before de ning it not after Twenty places in our code need nding and correcting The words THERE and RAM ALLOT are nice and friendly but they didn t succeed at hiding how the region is allocated If they had it wouldn t matter which order we invoked them in At long last our question What could we have done to THERE and RAM ALLOT to minimize the impact of this design change Again the answer I m looking for has nothing to do with de ning words For Further Thinking 97 FOUR Detailed Design Problem Solving Trivial I can see how to do this I just don t know how long it will take Non trivial I haven t a clue how to do this Operating philosophy developed at the Laboratory Automation and Instrumentation Design Group Chemistry Dept Virginia Polytechnic Institute and State University Once you ve decided upon the components in your application your next step is to design those components In this chapter we ll apply problem solving techniques to the detailed design of a Forth application This is the time for pure invention the part that many of us nd the most fun There s a special satisfaction in going to the mat with a non trivial problem and coming out the victor In English it s di cult to separate an idea from the words used to express the idea In writing a Forth application it s di cult to separate the d
124. P DROP the remainder like this DIGIT n 5 MOD OVER 4 IF ALMOST DROP DROP DROP DROP DROP ELSE IF FIVER THEN ONERS THEN There we have the complete coded de nition for producing a single digit of a Roman numeral If we were desperate to try it out before writing the needed auxiliary de nitions we could very quickly de ne a lexicon of words to print one group of symbols say the ONES row ONER I FIVER V TENER X ONERS of oners DUP IF 0 DO ONER LOOP THEN before loading our de nitions of ALMOST and DIGIT But we re not that desperate No we re anxious to move on to the problem of de ning the words ONER FIVER and TENER so that their symbols depend on which decimal digit we re formatting Let s go back to the symbol table we drew earlier ONERs FIVERs ones I V tens X L hundreds C D thousands M We ve observed that we also need a TENER which is the ONER in the next row below It s as if the table should really be written ONERs FIVERs TENERs ones I V X tens X L C hundreds C D M thousands M But that seems redundant Can we avoid it Perhaps if we try a di erent model perhaps a linear table like this Algorithm 129 Figure 4 8 A mechanical representation accessing the data structure ones I V tens X L hundreds C D thousands M Now we can imagine that each column name ones tens e
125. POINTERS At last we reserve room for the table itself patching its beginning address HERE into the constant POINTERS The word gt BODY gt BODY gt BODY gt BODY gt BODY converts the address returned by tick into the address of the constant s value Thus POINTERS returns the address of the table allotted later just as a name de ned by CREATE returns the address of a table allotted directly below the name s header Although it s valid to patch the value of a CONSTANT at compile time as we do here there is a restriction of style Tip A CONSTANT s value should never be changed once the application is compiled 7 11 The case of alternating states is slightly more involved In this situation we need to alternate back and forth between two or more states never clobbering The State Table 217 the conditions in each state when we jump to the other state Figure 7 5 shows the conceptual model for this kind of state table Figure 7 5 Conceptual model for alternating states tables In this model the names TOP BOTTOM etc can be made to point into either of two tables REAL or PSEUDO By making the REAL table the current one all the pointer names reference addresses in the REAL table by making the PSEUDO table current they address the PSEUDO table The code in Figure 7 6 implements this alternating states mechanism The words WORKING and PRETENDING change the pointer appropriately For instance WORKING 10 TOP
126. R OPEN OPEN is the appropriate name for a word that sets a bit in an I O address identi ed with the name SHUTTER 3 BUTTON DOES IGNITION DOES is a good choice for a word that vectors the address of the function IGNITION into a table of functions so that IGNITION will be executed when Button 3 is pushed 164 Implementation Elements of Forth Style SAY HELLO SAY is the perfect choice for vectoring HELLO into an execution variable When I rst wrote this example for Starting Forth I called it VERSION Moore reviewed the manuscript and suggested SAY which is clearly much better I M HARRY The word I M seems more natural than LOGON HARRY LOGIN HARRY or SESSION HARRY as often seen The choice of I M is another invention of Moore who says I detest the word LOGON There is no such word in English I was looking for a word that said I m It was a natural I just stumbled across it Even though it s clumsy with that apostrophe it has that sense of rightness All these little words are the nicest way of getting the Aha reaction If you think of the right word it is obviously the right word If you have a wide recall vocabulary you re in a better position to come up with the right word Another of Moore s favorite words is TH which he uses as an array indexing word For instance the phrase 5 TH returns the address of the fth element of the array Tip Spell names in full
127. RE ve times Each time WHERE returns a di erent address as de ned in ORDER then nally zero We can even de ne a DOER DOER DOER DOER DOER word that toggles its own behavior endlessly DOER SPEECH ALTERNATE BEGIN MAKE SPEECH HELLO MAKE SPEECH GOODBYE O UNTIL 5 To implement a forward reference A forward reference is usually needed as a hook that is a word invoked in a low level de nition but reserved for use by a component de ned later in the listing To implement a forward reference build the header of the word with DOER DOER DOER DOER DOER before invoking its name DOER STILL UNDEFINED Later in the listing use MAKE MAKE STILL UNDEFINED ALL THAT JAZZ Remember MAKE can be used outside a colon de nition 6 Recursion direct or indirect Direct recursion occurs when a word invokes itself A good example is the recursive de nition of greatest common denominator GCD of a b a if b O GCD of b a mod b if b gt O This translates nicely into DOER GCD a b gcd MAKE GCD DUP IF DUP ROT ROT MOD GCD THEN Indirect recursion occurs when one word invokes a second word while the second word invokes the rst This can be done using the form DOER B A B MAKE B A 7 Debugging I often de ne Using DOER MAKE 225 DOER SNAP short for SNAPSHOT then edit SNAP into my application at a point where I want to see what
128. S 1000 I TENOR 1 I UPSHOT LOOP That s all the code we need Even in the most innocent cases a little data structure can eliminate extra names By convention Forth handles text in counted strings i e with the count in the rst byte Any word that returns the address of a string actually returns this beginning address where the count is not only does use 176 Factoring of this two element data structure eliminate the need for separate names for string and count it also makes it easier to move a string in memory because you can copy the string and the count with a single CMOVE CMOVE CMOVE CMOVE CMOVE When you start nding the same awkwardness here and there you can combine things and make the awkwardness go away Factoring Out Functions into De ning Words Tip If a series of de nitions contains identical functions with variation only in data use a de ning word 6 4 Examine the structure of this code without worrying about its purpose you ll see the same example later on HUE color color LIGHT OR 0 LIGHT BLACK 0 HUE BLUE 1 HUE GREEN 2 HUE CYAN 3 HUE RED 4 HUE MAGENTA 5 HUE BROWN 6 HUE GRAY 7 HUE The above approach is technically correct but less memory e cient than the following approach using de ning words HUE color CREATE DOES gt color LIGHT OR 0 LIGHT 0
129. TRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION JUMP INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION TEST JUMP TEST JUMP For example Figure 1 2 shows a structured diagram of a module to Make Breakfast which consists of four submodules Within each submodule you ll nd a whole new level of complexity which needn t be shown at this level A branching decision occurs in this module to choose between the cold cereal module and the eggs module but control ow stays within the outer module Structured programming has three premises 1 Every program is described as a linear sequence of self contained func tions called modules Each module has exactly one entry point and one exit point 2 Each module consists of one or more functions each of which has exactly one entry point and one exit point and can itself be described as a module 6 The Philosophy of Forth Figure 1 2 Design for a structured program 3 A module can contain a operations or other modules b decision structures IF THEN statements c looping structures The idea of modules having one entry one exit is that you can unplug them change their innards and plug them back in without screwing up the connec tions with the rest of the program This means you can test each piece by itself That s only pos
130. able There are three reasons to avoid this cockiness First it s a pain to code that way Second the result is unreadable Third all your work becomes useless when a design change becomes necessary and the order of two arguments changes on the stack The DUP DUP DUP DUP DUPs OVER OVER OVER OVER OVERs and ROT ROT ROT ROT ROTs weren t really solving the problem just jockeying things into position With this third reason in mind I recommend the following 7 2 Tip Especially in the design phase keep on the stack only the arguments you re us ing immediately Create local variables for any others If necessary eliminate the variables during the optimization phase Fourth if the de nition is extremely time critical those tricky stack manipu lators e g ROT ROT ROT ROT ROT ROT ROT ROT ROT ROT can really eat up clock cycles Direct access to variables is faster If it s really time critical you may need to convert to assembler anyway In this case all your stack problems y out the door because all your data will be referenced either in registers or indirectly through registers Luckily the de nitions with the messiest stack arguments are often the ones written in code Our BOX primitive is a case in point CMOVE gt CMOVE gt CMOVE gt CMOVE gt CMOVE gt is another 202 Handling Data Stacks and States The approach we took with BOX certainly beats spending half an hour juggling items on
131. agment normally emits an ASCII character but if the character is a control code it emits a dot Either way an EMIT EMIT EMIT EMIT EMIT is performed Factor EMIT EMIT EMIT EMIT EMIT out of the conditional structure like this 174 Factoring c DUP BL 127 WITHIN NOT IF DROP ASCII THEN EMIT The messiest situation occurs when the di erence between two de nitions is a function within a structure that makes it impossible to factor out the half fragments In this case use stack arguments variables or even vectoring We ll see how vectoring can be used in a section of Chapter Seven called Using DOER MAKE Here s a reminder about factoring code from out of a DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP Tip In factoring out the contents of a DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP into a new de nition rework the code so that I the index is not referenced within the new de nition but rather passed as a stack argument to it 6 3 Factoring Out Control Structures Themselves Here are two de nitions whose di erences lies within a IF IF IF IF IF THEN THEN THEN THEN THEN construct ACTIVE A B OR C AND IF TUMBLE JUGGLE JUMP THEN LAZY A B OR C AND IF SIT EAT SLEEP THEN The condition and control structure remain the same only the event changes Since you can t factor the IF IF IF IF IF into one word and the THEN THEN THEN THEN THEN into another
132. ake in itself I should be using a ner unit of measurement the number of which remains constant for the line Changing type widths would mean changing the number of units per character But getting back to the mistake at hand Alas I was also using WALL inside the output component to determine how many characters to display My reasoning was that this value would change depending on what type width I was using I was right 99 of the time But one day I discovered that under a certain condition a line of condensed text was being somehow cut short The nal couple of words were just missing The reason turned out to be that WALL was getting changed before the output component had a chance to use it Originally I had seen nothing wrong with letting the output component blithely use the formatter s WALL as well Now I realized that the formatter had to leave a separate variable for the output component to indicate how many valid characters were in the bu ers This would leave any subsequent font commands free to change WALL It was important that the two bu ers the attribute commands and the new variable were the only elements that could be shared between the two modules Reaching into either module from the other one spells trouble A Design Mistake 87 The moral of this story is that we must distinguish between data struc tures that are validly used only within a single component and those that may be shared by more than on
133. ake to solve it Set a course for action and avoid the trap of fumbling about aimlessly The following tips suggest several approaches you might consider Tip Think of an analogous problem 4 4 Problem Solving Techniques 101 Does this problem sound familiar Have you written a de nition like it before Figure out what parts of the problem are familiar and in what ways this problem might di er Try to remember how you solved it before or how you solved something like it 4 5 Tip Work forward The normal obvious way to attack a problem is by beginning with the known and proceeding to the unknown In deciding which horse to bet on you d begin with their recent histories their current health and so on apply weights to these various factors and arrive at a favorite 4 6 Tip Work backward More complicated problems present many possible ways to go with the incoming data How do you know which route will take you closer to the solution You don t This class of problem is best solved by working backward Figure 4 1 Figure 4 1 A problem that is easier to solve backward than forward 4 7 Tip Believe Belief is a necessary ingredient for successfully working backward We ll illus trate with a famous mathematical problem Suppose we have two containers The containers have no graduation marks but one holds nine gallons and the other holds four gallons Our task is to measure out exactly six gallons
134. alled curly brackets square brackets quote as pre x tick as su x prime tilde bar backslash also under down and skip slash also up lt less than left dart gt greater than right dart question some prefer query comma dot 288 Summary of Style Conventions Index A Abbreviations 165 166 Abstraction 3 5 Address precedes counts syntax rule 115 Algorithms 12 20 21 119 120 122 125 127 133 249 250 Analogous problems 101 Analysis 38 45 49 budgeting 66 68 conceptual model 46 53 59 60 68 constraints 46 data structure de nition 59 60 decision table 55 59 decision tree 54 55 de ned 45 interface de nition 49 52 requirements 46 rule de nition 52 59 scheduling 66 68 simplicity 60 65 Structured English 53 54 AND 241 242 Arrays 193 194 ASCII 234 276 Assemblers 3 34 118 Assembly language 3 5 Auxiliary problems 104 106 B BASE 148 149 210 211 BASIC 3 5 7 Batch compile development sequence elimination of 31 Bernstein Mark 29 262 263 Blank space BL 169 277 Booleans as hybrid values 240 Boutelle Jerry 263 Branching 5 Brooks Fredrick P Jr 68 Budgeting 66 68 Bundling of names and numbers 167 Burgess Donald A 107 110 C Calculations 120 122 240 242 Calls implicit 19 Capability 32
135. allowing the immediate termination of a single word without quitting the entire application This technique should not be confused with the use of GOTO which is unstructured to the extreme With GOTO you can go anywhere inside or outside the current module With this technique you e ectively jump directly to the nal exit point of the module the semicolon and resume execution of the calling word The word EXIT EXIT EXIT EXIT EXIT terminates the de nition in which the word appears The phrase R gt DROP R gt DROP R gt DROP R gt DROP R gt DROP terminates the de nition that called the de nition in which the phrase appears thus it has the same e ect but can be used one level down Here are some examples of both approaches If you have an IF IF IF IF IF ELSE ELSE ELSE ELSE ELSE THEN THEN THEN THEN THEN phrase in which no code follows THEN THEN THEN THEN THEN like this HUNGRY IF EAT IT ELSE FREEZE IT THEN you can eliminate ELSE ELSE ELSE ELSE ELSE by using EXIT EXIT EXIT EXIT EXIT HUNGRY IF EAT IT EXIT THEN FREEZE IT If the condition is true we eat and run EXIT EXIT EXIT EXIT EXIT acts like a semicolon If the condition is false we skip to THEN THEN THEN THEN THEN and FREEZE IT The use of EXIT EXIT EXIT EXIT EXIT here is more e cient saving two bytes and extra code to perform but it is not as readable Moore comments on the value and danger of this t
136. ame for the address of video memory It s not that anything s wrong with the concept of a bit switch function in terface between components when it s necessary The problem here is that this video component was incompletely designed On the other hand if the system had been fully integrated operating system and drivers written in Forth the video component would not have to be designed to suit all needs An applica tion programmer could either rewrite the driver or write an extension to the driver using available tools from the video lexicon 3 7 Tip Don t bury your tools The Tower of Babble The nal deception perpetrated by level thinking is that programming lan guages should become qualitatively di erent the higher you go We tend to speak of high level code as something rare ed and low level code as something grubby and profane To some degree these distinctions have validity but this is only the result of certain arbitrary architectural constraints that we all accept as the norm We ve grown accustomed to assemblers with terse mnemonics and unnatural syntactical rules because they re low level The component concept rebels against the polarity of high level vs low level All code should look and feel the same A component is simply a set of commands that together transform data structures and algorithms into useful 94 Preliminary Design Decomposition functions These functions can be used wit
137. and algorithms It doesn t matter whether the data object is physical such as a hardware register or abstract such as a stack location or a eld in a data base It doesn t matter whether the algorithm is described in machine code or in problem oriented words such as CEREAL and EGGS Figure 1 7 contrasts the results of structured design with the results of de signing by components Instead of modules called READ RECORD EDIT RECORD and WRITE RECORD we re concerned with components that describe the struc ture of records provide a set of editor commands and provide read write routines to storage What have we done We ve inserted a new stage in the development process We decomposed by components in our design then we described the sequence hierarchy and input process output in our implementation Yes it s an extra step but we now have an extra dimension for decomposition not just slicing but dicing Component Programming 21 Figure 1 8 A lexicon describes a component Suppose that after the program is written we need to change the record structure In the sequential hierarchical design this change would a ect all three modules In the design by components the change would be con ned to the record structure component No code that uses this component needs to know of the change Aside from maintenance an advantage to this scheme is that program mers on a team can be assigned components individually with less
138. andles the problem This problem does not arise with the Laxen Perry Harris model The nal screen is an example of using DOER MAKE DOER MAKE DOER MAKE DOER MAKE DOER MAKE After loading the block enter RECITAL then enter WHY followed by return as many times as you like you ll get a di erent reason each time 272 De ning DOER MAKE Screen 21 0 DOER MAKE Shadow screen LPB 12 05 83 1 NOTHING A no opp 2 DOER Defines a word whose behavior is vectorable 3 MARKER Saves adr for optional continuation pointer 4 MAKE Stuffs the address of further code into the 5 parameter field of a doer word 6 MAKE Used interpretively MAKE doer name forth code 7 or inside a definition 8 def MAKE doer name forth code 9 Vectors the doer name word to the forth code 10 AND Allows continuation of the making definition 11 UNDO Usage UNDO doer name makes it safe to execute 12 13 14 15 Screen 22 0 DOER MAKE FORTH 83 Laxen Perry Harris model LPB 12 05 83 1 NOTHING 2 DOER CREATE NOTHING gt BODY DOES gt gt R 3 VARIABLE MARKER 4 MAKE R gt DUP 2 DUP 2 SWAP gt BODY 5 DUP IF gt R THEN 6 MAKE STATE IF compiling 7 COMPILE MAKE HERE MARKER 0 8 ELSE HERE COMPILE gt BODY 9 COMPILE THEN IMMEDIATE 10 AND COMPILE EXIT HERE MARKER IMMEDIATE 11 UNDO
139. ant to include every com mand that the customer might expect words to control graphics printers and other niceties they often nd that the system has swollen to more than half the memory capacity of the computer leaving less room for serious programmers to compile their applications The solution is for the vendor to provide the bare bones as a precompiled nucleus with the extra goodies provided in source form This approach allows the programmer to pick and choose the special routines actually needed These user loadable routines are called electives Double length arith metic date and time support CASE statements and the DOER MAKE construct Electives 145 described later are some of the features that Forth systems should o er as electives Screen Layout In this section we ll discuss the layout of each source screen 5 4 Tip Reserve Line 0 as a comment line The comment line serves both as a heading for the screen and also as a line in the disk INDEX It should describe the purpose of the screen not list the words de ned therein The comment line minimally contains the name of the screen In larger applications you may also include both the chapter name and screen name If the screen is one of a series of screens implementing a lexicon you should include a page number as well The upper right hand corner is reserved for the stamp The stamp includes the date of latest revision and when
140. ardware steadily dropped the cost of software soared It was no longer good enough for a program to run correctly It also had to be developed quickly and maintained easily A new demand began to share the spotlight with correctness The missing quality was called elegance In this section we ll outline a history of the tools and techniques for writing more elegant programs Memorability The rst computer programs looked something like this 00110101 11010011 11011001 2 The Philosophy of Forth Programmers entered these programs by setting rows of switches on if the digit was 1 o if the digit was 0 These values were the machine instruc tions for the computer and each one caused the computer to perform some mundane operation like Move the contents or Register B to Register A or Add the contents of Register C into the contents of Register A This proved a bit tedious Tedium being the stepmother of invention some clever programmers re alized that the computer itself could be used to help so they wrote a program that translated easy to remember abbreviations into the hard to remember bit patterns The new language looked something like this MOV B A ADD C A JMC REC1 The translator program was called an assembler the new language assembly language Each instruction assembled the appropriate bit pattern for that instruction with a one to one correspondence between ass
141. ast any language that depends on word order to understand a statement must know all legal words and all legal combinations Its chances of including all the constructs you d like are slim The language exists as determined by its manufacturer you can t extend its knowledge Laboratory researchers cite exibility and extensibility as among Forth s most important bene ts in their environment Lexicons can be developed to hide information about the variety of test equipment attached to the com puter Once this work has been done by a more experienced programmer the researchers are free to use their software toolbox of small words to write sim ple programs for experimentation As new equipment appears new lexicons are added Mark Bernstein has described the problem of using an o the shelf special purpose procedure library in the laboratory 8 The computer not the user dominates the experiment But with Forth he writes the computer actually encourages scientists to modify repair and improve the software to experiment with and characterize their equipment Initiative becomes once more the prerogative of the researcher For those purists who believe Forth isn t t to be called a high level lan guage Forth makes matters even worse While strong syntax checking and data typing are becoming one of the major thrusts of contemporary programming languages Forth does almost no syntax checking at all In
142. ast resort use a named variable 7 1 Some newcomers to Forth view the stack the way a gymnast views a trampoline as a fun place to bounce around on But the stack is meant for data passing not acrobatics So how deep is too deep Generally three elements on the stack is the most you can manage within a single de nition In double length arithmetic each element occupies two stack positions but is logically treated as a single element by operators such as 2DUP 2DUP 2DUP 2DUP 2DUP 2OVER 2OVER 2OVER 2OVER 2OVER etc In your ordinary lexicon of stack operators ROT ROT ROT ROT ROT is the only one that gives you access to the third stack item Aside from PICK PICK PICK PICK PICK and ROLL ROLL ROLL ROLL ROLL which we ll comment on soon there s no easy way to get at anything below that To stretch our analogy to the limit perhaps three elements on the stack corresponds to the three English pronouns this that and th other Redesign Let s witness a case where a wrong headed approach leads to a messy stack problem Suppose we re trying to write the de nition of THRU see Chapter Five Listing Organization section Relative Loading subsection We ve decided that our loop body will be DO I LOAD LOOP Redesign 199 that is we ll put LOAD LOAD LOAD LOAD LOAD in a loop then arrange for the index and limit to corre spond to the absolute screens b
143. ation of algorithm and data structure Data Structure Ones Table Tens Table 0 0 1 I 1 X 2 II 2 XX 3 III 3 XXX 4 IV 4 XL 5 V 5 L 6 VI 6 LX 7 VII 7 LXX 8 VIII 8 LXXX 9 IX 9 XC 124 Detailed Design Problem Solving Algorithm Divide n by 10 The quotient is the tens column digit the remainder is the ones column digit Look up the ten s digit in the tens table and print the corresponding symbol pattern Look up the ones digit in the one s table and print that corresponding symbol pattern For example if the number is 72 the quotient is 7 the remainder is 2 7 in the tens table corresponds to LXX so print that 2 in the ones column corresponds to II so print that The result LXXII We ve just constructed a model that works for numbers from one to 99 Any higher number would require a hundreds table as well along with an initial division by 100 The logical model just described might be satisfactory as long as it does the job But somehow it doesn t seem we ve fully solved the problem We avoided guring out how to produce the basic pattern by storing all possible combinations in a series of tables Earlier in this chapter we observed that calculating an answer if it s possible can be easier than using a data structure Since this section deals with devising algorithms let s go all the way Let s look for a general algorithm for producing a
144. ations I need to have a convenient set of words to e ect the change These words must also set a variable that contains the current number of columns 40 or 80 Here s the most straightforward way to ful ll the requirements Factoring Criteria 185 40 B amp W 40 COLUMNS 0 MODE 40 COLOR 40 COLUMNS 1 MODE 80 B amp W 80 COLUMNS 2 MODE 80 COLOR 80 COLUMNS 3 MODE By factoring to eliminate the repetition we come up with this version COL MODE columns mode MODE COLUMNS 40 B amp W 40 0 COL MODE 40 COLOR 40 1 COL MODE 80 B amp W 80 2 COL MODE 80 COLOR 80 3 COL MODE But by attempting to reduce the number of commands and also by following the injunctions against numerically pre xed and hyphenated names we realize that we can use the number of columns as a stack argument and calculate the mode B amp W cols DUP COLUMNS 20 2 MODE COLOR cols DUP COLUMNS 20 2 1 MODE This gives us this syntax 40 B amp W 80 B amp W 40 COLOR 80 COLOR We ve reduced the number of commands from four to two Once again though we have some duplicate code If we factor out this code we get COL MODE columns chroma SWAP DUP COLUMNS 20 2 MODE B amp W columns 0 COL MODE COLOR columns 1 COL MODE Now we ve achieved a nicer syntax and at the same time greatly reduced the si
145. ay which I submit as a more useful factoring requires a single word FH FH FH FH FH see Appendix C for its de nition The phrase 1 FH LOAD is read 1 from here LOAD and is equivalent to 1 LOAD Similarly 2 FH 5 FH THRU is read 2 from here 5 from here THRU Some programmers begin each chapter with a dummy word e g VIDEO IO and list its name in the comment on the line where the chapter is loaded in the application load screen This permits selectively FORGETting any chapter and reloading from that point on without having to look at the chapter itself Within a chapter the rst group of screens will usually de ne those vari ables constants and other data structures needed globally within the chapter Chapter load Screens 141 Figure 5 3 Moore Products Co s format for chapter preambles Screen 101 0 CHAPTER 5 ORIGIN DESTINATION MULTILOOP BIT ROUTINES 1 2 DOCUMENTS CONSOLE STRUCTURE CONFIGURATION 3 DESIGN SPECIFICATION 4 SECTIONS 3 2 7 5 4 1 2 8 5 3 2 7 5 4 1 2 10 6 7 ABSTRACT File control types E M T Q and R can all 8 originate from a Regional Satellite or a 9 Data Survey Satellite These routines allow 10 the operator to determine whether the control 11 originated from a Regional Satellite or not 12 13 14 15 Screen 102 0 CHAPTER NOTES Whether or not a point originates from 1 a Regional Satellite is determined by
146. because LOAD and AIM are cleaner They do what you expect them to do Should you have to de ne READY you can do it so READY pad DUP LOAD AIM and not READY pad LOAD AIM DROP 4 17 Tip Use zero relative numbering By habit we humans number things starting with one rst second third etc Mathematical models on the other hand work more naturally when starting with zero Since computers are numeric processors software becomes easier to write when we use zero relative numbering To illustrate suppose we have a table of eight byte records The rst record occupies the rst eight bytes of the table To compute its starting address we add 0 to TABLE To compute the starting address of the second record we add 8 to TABLE Figure 4 6 A table of 8 byte records 114 Detailed Design Problem Solving It s easy to derive a formula to achieve these results rst record starts at 0 8 0 second record starts at 1 8 8 third record starts at 2 8 16 We can easily write a word which converts a record into the address where that record begins RECORD record adr 8 TABLE Thus in computer terms it makes sense to call the rst record the 0th record If your requirements demand that numbering start at one that s ne Use zero relative numbering throughout your design and then only in the user lexicons the set of words
147. ber nor a prede ned word it will abort with an error message For this reason an unde ned string must be preceded by a de ned word An example is dot quote which precedes the text it will later print Another example is CREATE CREATE CREATE CREATE CREATE as well as all de ning words which precedes the name that is at the moment still unde ned The rule also applies to de ned words that you want to refer to but not execute in the usual way An example is FORGET FORGET FORGET FORGET FORGET as in FORGET TASK Syntactically FORGET FORGET FORGET FORGET FORGET must precede TASK so that TASK doesn t execute Tip Let de nitions consume their arguments 4 16 Forth Syntax 113 This syntax rule is more a convention of good Forth programming than a preference of Forth Suppose you re writing the word LAUNCH which requires the number of a launch pad and res the appropriate rocket You want the de nition to look roughly like this LAUNCH pad LOAD AIM FIRE Each of the three internal de nitions will require the same argument the launch pad number You ll need two DUP DUP DUP DUP DUPs somewhere The question is where If you put them inside LOAD and AIM then you can keep them out of LAUNCH as in the de nition above If you leave them out of LOAD and AIM you ll have to de ne LAUNCH pad DUP LOAD DUP AIM FIRE By convention the latter version is preferable
148. book In my latest design the formatter portion contains two components The rst component reads the source document and decides where to make line and page breaks etc But instead of sending the text directly to the terminal or printer it saves up a line s worth at a time in a line bu er Similarly instead of sending printer control commands for bold facing underlining etc as the text is being formatted it defers these commands until the text is actually sent To defer the control commands I have a second bu er called the attribute bu er It corresponds byte for byte with the line bu er except that each byte contains a set of ags that indicate whether the corresponding character should be underlined boldfaced or whatever The second component displays or prints the contents of the line bu er The component knows whether it is transmitting to the terminal or to the printer and outputs the text according to the attributes indicated by the at tribute bu er Here we have two well de ned components the line formatter and the output component each one shouldering part of the function of the formatter as a whole The data interface between these two components is fairly complex The interface consists of two bu ers a variable that indicates the current number of 86 Preliminary Design Decomposition valid characters and nally a knowledge of what all those attribute patterns mean In For
149. c proposals for new loop constructs Check your system s documentation to see what it o ers in the way of exotic looping structures Or depending on the needs of your application consider adding your own conditional constructs It s not that hard in Forth I m not even sure whether this use of multiple exits doesn t violate the doctrine of structured programming In a BEGIN BEGIN BEGIN BEGIN BEGIN WHILE WHILE WHILE WHILE WHILE REPEAT REPEAT REPEAT REPEAT REPEAT loop with mul tiple WHILE WHILE WHILE WHILE WHILEs all the exits bring you to a common continue point the REPEAT REPEAT REPEAT REPEAT REPEAT 238 Minimizing Control Structures But with Sanderson s construct you can exit the loop by jumping past the end of the loop continuing at an ELSE ELSE ELSE ELSE ELSE There are two possible continue points This is less structured if we can be permitted to say that And yet the de nition will always conclude at its semicolon and return to the word that invoked it In that sense it is well structured the module has one entry point and one exit point When you want to execute special code only if you did not leave the loop prematurely this approach seems the most natural structure to use We ll see an example of this in a later section Using Structured Exits Tip Favor counts over terminators 8 8 Forth handles strings by saving the length of the string in the rst byte Th
150. cation load screen tells you where to nd all of the chapters For instance if you want to look at the routines that do framing you can see that the section starts at Screen 90 Each chapter load screen in turn loads all of the screens comprising the chapter We ll study some formats for chapter load screens shortly The primary bene t of this hierarchical scheme is that you can load any section or any screen by itself without having to load the entire application Modularity of the source code is one of the reasons for Forth s quick turnaround time for editing loading and testing necessary for the iterative approach Like pages of a book each screen can be accessed individually and quickly It s a random access approach to source code maintenance You can also replace any passage of code with anew trial version by simply changing the screen numbers in the load screen You don t have to move large passages of source code around within a le In small applications there may not be such things as chapters The application load screen will directly load all the lexicons In larger applications however the extra level of hierarchy can improve maintainability A screen should either be a load screen or a code screen not a mixture Avoid embedding a LOAD LOAD LOAD LOAD LOAD or THRU THRU THRU THRU THRU command in the middle of a screen containing de nitions just because you need something or because you
151. code which is meant to initialize three variables associated with each of eight channels VARIABLE OSTS VARIABLE 1STS VARIABLE 2STS VARIABLE 3STS VARIABLE 4STS VARIABLE 5STS VARIABLE 6STS VARIABLE 7STS VARIABLE 0TNR VARIABLE 1TNR VARIABLE 2TNR VARIABLE 3TNR VARIABLE 4TNR VARIABLE 5TNR VARIABLE 6TNR VARIABLE 7TNR VARIABLE OUPS VARIABLE 1UPS VARIABLE 2UPS VARIABLE 3UPS VARIABLE 4UPS VARIABLE 5UPS VARIABLE 6UPS VARIABLE 7UPS INIT CHO 0 0STS 1000 0TNR 1 OUPS INIT CHO 0 1STS 1000 1TNR 1 1UPS INIT CH2 0 2STS 1000 2TNR 1 2UPS INIT CH3 0 3STS 1000 3TNR 1 3UPS INIT CH4 0 4STS 1000 4TNR 1 4UPS INIT CH5 0 5STS 1000 5TNR 1 5UPS INIT CH6 0 6STS 1000 6TNR 1 6UPS INIT CH7 0 7STS 1000 7TNR 1 7UPS INIT ALL CHS INIT CHO INIT CH1 INIT CH2 INIT CH3 INIT CH4 INIT CH5 INIT CH6 INIT CH7 First there s a similarity among the names of the variables then there s a similarity in the code used in all the INIT CH words Here s an improved rendition The similar variable names have been factored into three data structures and the lengthy recital of INIT CH words has been factored into a DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP ARRAY cells CREATE 2 ALLOT DOES gt i cell SWAP 2 8 ARRAY STATUS channel adr 8 ARRAY TENOR 8 ARRAY UPSHOT STABLE 8 0 DO 0 I STATU
152. cter in Fig ure 3 4 Let s consider just one of the seven possible execution paths the one that happens if a printable character is pressed In Figure 3 6 a we see the original structural path for a printable char acter Once we gure out the algorithms for overwriting and inserting charac ters we might re ne it as shown in Figure 3 6 b But look at that embarrassing 82 Preliminary Design Decomposition Figure 3 6 The same section re ned and optimized redundancy of code circled portions Most competent structured program mers would recognize that this redundancy is unnecessary and change the structure as shown in Figure 3 6 c Not too bad so far right Change in Plan Okay everyone now act surprised We ve just been told that this application won t run on a memory mapped display What does this change do to our design structure Well for one thing it destroys Refresh Display as a separate module The function of Refresh Display is now scattered among the various structural lines inside Process a Keystroke The structure of our entire application has changed It s easy to see how we might have spent weeks doing top down design only to nd we d been barking down the wrong tree What happens when we try to change the program Let s look again at the path for any printable character Change in Plan 83 Figure 3 7 Adding refresh Figure 3 7 a shows what happens to
153. customer is nally satis ed you re ready for the next big step the design 68 Analysis References 1 Kim Harris The Forth Philosophy Dr Dobb s Journal Vol 6 Iss 9 No 59 Sept 81 pp 6 11 2 Victor Weinberg Structured Analysis Englewood Cli s N J Prentice Hall Inc 1980 3 LaFarr Stuart LaFORTH 1980 FORML Proceedings p 78 4 Frederick P Brooks Jr The Mythical Man Month Reading Mas sachusetts Addison Wesley 1975 References 69 THREE Preliminary Design Decomposition Assuming you have some idea of what your program should accomplish it s time to begin the design The rst stage preliminary design focuses on shrink ing your mountainous problem into manageable molehills In this chapter we ll discuss two ways to decompose your Forth applica tion Decomposition by Component Has this sort of thing ever happened to you You ve been planning for three months to take a weekend vacation to the mountains You ve been making lists of what to bring and daydreaming about the slopes Meanwhile you re deciding what to wear to your cousin s wedding next Saturday They re informal types and you don t want to overdress Still a wedding s a wedding Maybe you should rent a tuxedo anyway For all this planning it s not until Thursday that you realize the two events coincide You have expletives for such moments How is such a mental lapse possible i
154. d how much will t on the graph After that we realized that not all the data taken will be of interest to experi menters So we added a zoom capability This iterative approach resulted in cleaner code and better thought out code We established a baseline set of goals and built a minimal system to the users The Limitations of Planning 43 known requirements Then we d crank in the programmer s experience to im prove it and determine what the users forgot they needed when they generated the specs The users did not invent most of the new ideas The programmers did and they would bounce these ideas o the users The problem de nition was a two way street In some cases they got things they didn t know they could do on such a small computer such as applying digital lters and signal processing to the data One of the things about Forth that makes this approach possible is that prim itives are easily testable It takes some experience with Forth to learn how to take advantage of this Guys from traditional environments want to write ten pages of code at their desk then sit down to type it in and expect it to work To summarize my approach I try to nd out from the users what they need but at the same time recognizing its incompleteness Then I keep them involved in the design during the implementation since they have the expertise in the application When they see the result they feel good because they know their
155. ddress The traditional techniques for implementing vectored execution are de scribed in Starting Forth Chapter Nine In this section we ll discuss a new syntax which I invented and which I think can be used in many circumstances more elegantly than the traditional methods The syntax is called DOER MAKE If your system doesn t include these words refer to Appendix B for code and implementation details It works like this You de ne the word whose behavior will be vectorable with the de ning word DOER DOER DOER DOER DOER as in DOER PLATFORM Initially the new word PLATFORM does nothing Then you can write words that change what PLATFORM does by using the word MAKE MAKE MAKE MAKE MAKE LEFTWING MAKE PLATFORM proponent RIGHTWING MAKE PLATFORM opponent When you invoke LEFTWING the phrase MAKE PLATFORM changes what PLATFORM will do Now if you type PLATFORM you ll see LEFTWING ok PLATFORM proponent ok RIGHTWING will make PLATFORM display opponent You can use PLATFORM within another de nition Vectored Execution 219 SLOGAN Our candidate is a longstanding PLATFORM of heavy taxation for business The statement LEFTWING SLOGAN will display one campaign statement while RIGHTWING SLOGAN will display another The MAKE code can be any Forth code as much or as long as you want just remember to conclude it with semicolon The semicolon at the end of LE
156. de nition of ASCII ASCII ASCII ASCII ASCII that will work in 83 Standard is ASCII c Compile c Interpret c c BL WORD 1 C STATE IF COMPILE LITERAL THEN IMMEDIATE From Chapter Five The word can be de ned as skip rest of line gt IN 64 1 64 gt IN IMMEDIATE If you decide not to use EXIT EXIT EXIT EXIT EXIT to terminate a screen you can de ne S S S S S as S 1024 gt IN The word FH FH FH FH FH can be de ned simply as FH offset offset block from here BLK This factoring allows you to use FH in many ways e g TEST 1 FH LITERAL LOAD or SEE 2 FH LITERAL LIST 276 Other Utilities Described in This Book A slightly more complicated version of FH also lets you edit or load a screen with a phrase such as 14 FH LIST relative to the screen that you just listed SCR FH offset offset block from here BLK DUP 0 IF SCR THEN BL BL BL BL BL is a simple constant 32 CONSTANT BL TRUE TRUE TRUE TRUE TRUE and FALSE FALSE FALSE FALSE FALSE can be de ned as 0 CONSTANT FALSE 1 CONSTANT TRUE Forth s control words such as IF and UNTIL interpret zero as false and any non zero value as true Before Forth 83 the convention was to indicate true with the value 1 Starting with Forth 83 however true is
157. de the number by ve the quotient will be zero false when the number is less than ve and one true when it s between 5 and 9 We can use it as the boolean ag to tell whether we want the leading FIVER n 5 IF FIVER THEN Algorithm 127 The quotient ag becomes the argument to IF Furthermore the remainder of modulo 5 division is always a number between 0 and 4 which means that except for our exception we can use the remainder directly as the argument to ONERS We revise our phrase to n 5 MOD MOD MOD MOD MOD IF FIVER THEN ONERS ONERS ONERS ONERS ONERS Getting back to that exception we now see that we can test for both 4 and 9 with a single test namely if the remainder is 4 This suggests that we can do our 5 MOD MOD MOD MOD MOD rst then test for the exception Something like this DIGIT n 5 MOD OVER 4 IF special case ELSE OVER 4 IF special case ELSE OVER 4 IF special case ELSE OVER 4 IF special case ELSE OVER 4 IF special case ELSE IF FIVER THEN ONERS THEN Notice that we OVER OVER OVER OVER OVERed the remainder so that we could compare it with 4 without consuming it So it turns out we do have a doubly nested IF THEN IF THEN IF THEN IF THEN IF THEN construct after all But it seems justi ed because the IF THEN IF THEN IF THEN IF THEN IF THEN is handling the special case The other is such a short phrase IF FIVER THEN
158. describes what the system would look like to the user you might call it the user s manual I nd I write more notes on the human interaction what it will look like on the outside than on the part that gets the job done For instance I ll include a whole error action listing to show what happens when a particular error occurs Oddly this is the part that takes the most time to implement anyway I m currently working on a solid state industrial washing machine timer In this case the user interface is not that complex What is complex is the interface to the washing machine for which I must depend on the customer and the documentation they can provide The signi cant interface is whatever is the arms and legs of the product I don t make the distinction between hardware and software at this early stage They can be interchanged in the implementation The process of designing hardware and the process of designing software are analogous The way I design hardware is to treat it as a black box The front panel is input and output You can do the same with software I use any techniques diagrams etc to show the customer what the inputs and outputs look like using his description of what the product has to do But in parallel in my own mind I m imagining how it will be implemented I m evaluating whether I can do this e ciently So to me it s not a black box it s a gray box The designer must be able to see inside t
159. distance is great than when it is close Far away you re in slew mode closer to the target you re in decelerate mode very close you re in hunt mode You have to test how far you are to know which algorithm to apply I ve worked out a non linear servo control algorithm that will handle full range This approach eliminates the glitches at the transitioning points between one mode and the other It eliminates the logic necessary to decide which algorithm to use It eliminates your having to empirically determine the transition points And of course you have a much simpler program with one algorithm instead of three Instead of trying to get rid of conditionals you re best to question the under lying theory that led to the conditionals 8 17 Tip Avoid the need for special handling One example we mentioned earlier in the book if you keep the user out of trouble you won t have to continually test whether the user has gotten into trouble Moore Another good example is writing assemblers Very often even though an opcode may not have a register associated with it pretending that it has a register say Register 0 might simplify the code Doing arithmetic by introducing bit patterns that needn t exist simpli es the solution Just substitute zeros and keep on doing arithmetic that you might have avoided by testing for zero and not doing it It s another instance of the don t care If you don t care t
160. ditionals aren t bad in themselves they are an essential construct But a program with a lot of conditionals is clumsy and unreadable All you can do is question each one Every conditional should cause you to ask What am I doing wrong What you re trying to do with the conditional can be done in a di erent way The long term consequences of the di erent way are preferable to the long term consequences of the conditional Before we introduce some detailed techniques let s look at three approaches to the use of conditionals in a particular example Figure 8 1 Figure 8 2 and Figure 8 3 illustrate three versions of a design for an automatic teller machine The rst example comes straight out of the School for Structured Pro grammers The logic of the application depends on the correct nesting of IF statements Easy to read Tell me under what condition the user s card gets eaten To answer you have to either count ELSEs from the bottom and match them with the same number of IFs from the top or use a straightedge The second version Figure 8 2 shows the improvement that using many small named procedures can have on readability The user s card is eaten if the owner is not valid What s So Bad about Control Structures 229 Figure 8 1 The structured approach AUTOMATIC TELLER IF card is valid DO IF card owner is valid DO IF request withdrawal DO IF authorization code is valid DO query for amount IF request
161. ds the time consuming burden of checking some undetermined number of slots on each pass of the loop Can you do so using only the one array 134 Detailed Design Problem Solving FIVE Implementation Elements of Forth Style Badly written Forth has been accused of looking like code that went through a trash compactor It s true Forth a ords more freedom in the way we write applications But that freedom also gives us a chance to write exquisitely readable and easily maintainable code provided we consciously employ the elements of good Forth style In this chapter we ll delve into Forth coding convention including listing organization screen layout spacing and indentation commenting choosing names I wish I could recommend a list of hard and fast conventions for everyone Unfortunately such a list may be inappropriate in many situations This chapter merges many widely adopted conventions with personal preferences commented with alternate ideas and the reasons for the preferences In other words TIP VALUE JUDGEMENT I d especially like to thank Kim Harris who proposed many of the conventions described in this chapter for his continuing e orts at unifying divergent views on good Forth style Listing Organization A well organized book has clearly de ned chapters with clearly de ned sec tions and a table of contents to help you see the organization at a glance A well organ
162. e TOTAL total charge FIRST first minute rate minutes 1 additional minutes PER ADDITIONAL times the rate added together We ve expressed the rules to this particular problem through a combination of simple tables and logical calculations Some nal notes on this example We ve written something very close to a running Forth application But it is only pseudocode We ve avoided stack manipulations by assuming that values will somehow be on the stack where the comments indicate Also we ve used hyphenated names because they might be more readable for the customer Short names are preferred in real code see Chapter Five We ll unveil the nished code for this example in Chapter Eight De ning the Data Structures After de ning the interfaces and sometimes de ning the rules occasionally you ll need to de ne certain data structures as well We re not referring here to the implementation of the data structures but rather to a description of their conceptual model If you re automating a library index for instance a crucial portion of your analysis will concern developing the logical data structure You ll have to De ning the Data Structures 59 decide what information will be kept for each book title author subject etc These attributes will comprise an entity set of related records called BOOKS Then you ll have to determine what other data structur
163. e rst letter dated later than your current letter 4 Insert your current letter just in front of the letter dated later If the folder is empty just insert the letter There may be several possible algorithms for the same job The algorithm given above would work ne for folders containing ten or fewer letters but for folders with a hundred letters you d probably resort to a more e cient algorithm such as this 1 same 2 same 3 If the date falls within the rst half of the month open the folder a third of the way in If the letter you nd there is dated later than your current letter search forward until you nd a letter dated the same or before your current letter Insert your letter at that point If the letter you nd is dated earlier than your current letter search backward You get the point This second algorithm is more complicated than the rst But in execution it will require fewer steps on the average because you don t have to search clear from the beginning of the folder every time and therefore can be performed faster A data structure is an arrangement of data or locations for data organized especially to match the problem In the last example the le cabinet containing folders and the folders containing individual letters can be thought of as data structures The new conceptual model includes the ling cabinets and folders data structures plus the steps for doing the
164. e ned 6 12 Tip Factor de nitions to hide details that may change We ve seen the value of information hiding in earlier chapters especially with regard to preliminary design It s useful to remember this criterion during the implementation stage as well Here s a very short de nition that does little except hide information gt BODY acf apf 2 This de nition allows you to convert an acf address of code eld to an apf address of parameter eld without depending on the actual structure of a dictionary de nition If you were to use 2 2 2 2 2 instead of the word gt BODY gt BODY gt BODY gt BODY gt BODY you would lose transportability if you ever converted to a Forth system in which the heads were separated from the bodies This is one of a set of words suggested by Kim Harris and included as an Experimental Proposal in the Forth 83 Standard 3 Here s a group of de nitions that might be used in writing an editor FRAME a SCR BLOCK CURSOR a R AT a FRAME CURSOR These three de nitions can form the basis for all calculations of addresses neces sary for moving text around Use of these three de nitions completely separates your editing algorithms from a reliance on Forth blocks What good is that If you should decide during development to create an editing bu er to protect the user from making errors that destroy a block you
165. e It s not enough merely to test for each exception as in this version DIGIT n 4 CASE IF ONER FIVER THEN 9 CASE IF ONER TENER THEN normal case because the normal case is never excluded There s no way to put an ELSE ELSE ELSE ELSE ELSE just before the normal case because ELSE ELSE ELSE ELSE ELSE must appear between IF IF IF IF IF and THEN THEN THEN THEN THEN If we insist on handling the 4 exception and the 9 exception separately we could arrange for each exception to pass an additional ag indicating that the exception occurred If either of these ags is true then we can exclude the normal case DIGIT n 4 CASE DUP DUP DUP DUP DUP IF ONER FIVER THEN 9 CASE DUP DUP DUP DUP DUP IF ONER TENER THEN OR NOT IF normal case THEN But this approach needlessly complicates the de nition by adding new control structures We ll leave it like it was Now we have a general idea of the structure of our main de nition We stated If the digit is 5 or more begin with a FIVER and subtract ve from the value otherwise do nothing Then print as many ONERS as necessary to add up to the value A direct translation of these rules into Forth would look like this n DUP 4 gt IF FIVER 5 THEN ONERS This is technically correct but if we re familiar with the technique of modulo division we ll see this as a natural situation for modulo division by 5 If we divi
166. e LIGHT preceding the color Fine But remember the code to implement that version Compare it with the simplicity of this approach O CONSTANT BLACK 1 CONSTANT BLUE 2 CONSTANT GREEN 3 CONSTANT CYAN 4 CONSTANT RED 5 CONSTANT MAGENTA 6 CONSTANT BROWN 7 CONSTANT GRAY LIGHT color color 8 OR In this version we ve reversed the syntax so that we now say BLUE LIGHT We establish the color then we modify the color We ve eliminated the need for a variable for code to fetch from the vari able and more code to reset the variable when we re done And the code is so simple it s impossible not to understand When I rst wrote these commands I took the English like approach BLUE LIGHT sounded backwards not at all acceptable That was before my conversations with Chuck Moore 258 Minimizing Control Structures Moore s philosophy is persuasive I would distinguish between reading nicely in English and reading nicely In other languages such as Spanish adjectives follow nouns We should be inde pendent of details like which language we re thinking in It depends on your intention simplicity or emulation of English English is not such a superb language that we should follow it slavishly If I were selling my colors words in a package for graphic artists I would take the trouble to create the ag But writing these words for my own use if I had to do it over again I d favor the Moore ish in
167. e additions you can write phrases such as TRUE STAMP to set a ag or FALSE STAMP to clear it I once used TTTTT and FFFFF but the words are needed so rarely I now heed the injunction against abbreviations As part of your application not necessarily part of your Forth system you can take this idea a step further and de ne ON a TRUE SWAP OFF a FALSE SWAP These words allow you to write STAMP ON or STAMP OFF Other names for these de nitions include SET and RESET although SET and RESET most commonly use bit masks to manipulate individual bits An often used word is WITHIN WITHIN WITHIN WITHIN WITHIN which determines whether a given value lies within two other values The syntax is n lo hi WITHIN More Tips for Readability 169 where n is the value to be tested and lo and hi represent the range WITHIN WITHIN WITHIN WITHIN WITHIN returns true if n is greater than or equal to lo and less than hi This use of the non inclusive upper limit parallels the syntax of DO DO DO DO DO LOOP LOOP LOOP LOOP LOOPs Moore recommends the word UNDER UNDER UNDER UNDER UNDER It s useful for adding a value to the number just under the top stack item instead of to the top stack item It could be implemented in high level as UNDER a b c a c b ROT SWAP Summary Maintainability requires readability In thi
168. e bars separate the various elements in the structure the numbers represent bytes per element In the comment above the rst byte contains the count and the remaining 63 bytes contain the text A bit comment uses the same format as a data structure comment to depict the meaning of bits in a byte or cell For instance the bit comment 1busy 1acknowledge 2x 6input device 6output device describes the format of a 16 bit status register of a communications channel The rst two bits are ags the second two bits are unused and the nal pair of six bit elds indicate the input and output devices which this channel is connected to If more than one data structure employs the same pattern of elements write out the comment only once possibly in the preamble and give a name to the pattern for reference in subsequent screens For instance if the preamble gives the above bit pattern the name status then status can be used in stack comments to indicate values with that pattern STATUS status If a 2VARIABLE 2VARIABLE 2VARIABLE 2VARIABLE 2VARIABLE contains one double length value the comment should be a stack picture that indicates the contents 2VARIABLE PRICE price in cents If a 2VARIABLE 2VARIABLE 2VARIABLE 2VARIABLE 2VARIABLE contains two single length data elements it s given a stack picture showing what would be on the stack after a 2 Thus 2VARIABLE MEASUREMENTS
169. e component A related point 3 5 Tip Express in objective units any data to be shared by components For example Module A measures the temperature of the oven Module B controls the burner Module C makes sure the door is locked if the oven is too hot The information of global interest is the temperature of the oven expressed objectively in degrees While Module A might receive a value representing the voltage from a heat sensor it should convert this value to degrees before presenting it to the rest of the application Decomposition by Sequential Complexity We ve been discussing one way to do decomposition according to components The second way is according to sequential complexity One of Forth s rules is that a word must already have been de ned to be invoked or referred to Usually the sequence in which words are de ned parallels the order of increasing capabilities which the words must possess This sequence leads to a natural organization of the source listing The powerful commands are simply added on top of the elementary application Figure 3 10a Like a textbook the elementary stu comes rst A newcomer to the project would be able to read the elementary parts of the code before moving on the advanced stu But in many large applications the extra capabilities are best imple mented as an enhancement to some private root function in the elementary part of the application Figure 3 1
170. e dictionary entry created when we enter DOER JOE JOE pfa of NOTHING header parameter eld Now suppose we de ne TEST MAKE JOE CR that is we de ne a word that can vector JOE to do a carriage return Here s a picture of the compiled de nition of TEST adr of adr of adr of adr of TEST MAKE 0 JOE CR EXIT header MARKER 270 De ning DOER MAKE Let s look at the code for MAKE MAKE MAKE MAKE MAKE Since we re using MAKE MAKE MAKE MAKE MAKE inside a colon de nition STATE STATE STATE STATE STATE will be true and we ll execute the phrase COMPILE MAKE HERE MARKER 0 We can see how MAKE MAKE MAKE MAKE MAKE has compiled the address of the run time routine MAKE MAKE MAKE MAKE MAKE followed by a zero We ll explain what the zero is for and why we save its address in a the variable MARKER MARKER MARKER MARKER MARKER later variable Now let s look at what MAKE MAKE MAKE MAKE MAKE does when we execute our new de nition TEST TEST TEST TEST TEST R gt Gets an address from the return stack This address points to the cell just past MAKE MAKE MAKE MAKE MAKE where the zero is DUP 2 Gets the address of the second cell after MAKE MAKE MAKE MAKE MAKE where the address of JOE JOE JOE JOE JOE is DUP 2 Gets the address of the third cell after MAKE MAKE MAKE MAKE MAKE where the cod w
171. e do in Forth in the sense of creating words and grouping them together For example in handling strings I would de ne subroutines analogous to CMOVE TRAILING FILL etc More fundamentally Forth has rea rmed my faith in simplicity Most people go out and attack problems with complicated tools But simpler tools are available and more useful I try to simplify all the aspects of my life There s a quote I like from Tao Te Ching by the Chinese philosopher Lao Tzu To attain knowledge add things every day to obtain wisdom remove things every day Forth s E ect on Thinking 263 APPENDIX A Overview of Forth For Newcomers The Dictionary Forth is expressed in words and numbers and is separated by spaces HAND OPEN ARM LOWER HAND CLOSE ARM RAISE Such commands may be typed directly from the keyboard or edited onto mass storage then LOAD LOAD LOAD LOAD LOAD ed All words whether included with the system or user de ned exist in the dictionary a linked list A de ning word is used to add new names to the dictionary One de ning word is pronounced colon which is used to de ne a new word in terms of previously de ned words Here is how one might de ne a new word called LIFT LIFT HAND OPEN ARM LOWER HAND CLOSE ARM RAISE The terminates the de nition The new word LIFT may now be used instead of the long sequence of words that comprise its de
172. e has nished being executed control returns back to the calling program at the point following the call Subroutines obey the rules of structured programming As you can see the e ect of the subroutine call is as if the subroutine code were written out in full within the calling module But unlike the code produced by the macro assembler the subroutine can be compiled elsewhere in memory and merely referenced It doesn t necessarily have to be compiled within the object code of the main program Figure 1 5 Over the years computer scientists have become more forceful in favoring the use of many small subroutines over long winded continuous programs Subroutines can be written and tested independently This makes it easier to reuse parts of previously written programs and easier to assign di erent parts of a program to di erent programmers Smaller pieces of code are easier to think about and easier to verify for correctness Figure 1 5 A main program and a subroutine in memory Subroutines 11 When subroutines are compiled in separate parts of memory and referred to you can invoke the same subroutine many times throughout a program without wasting space on repeated object code Thus the judicious use of subroutines can also decrease program size Unfortunately there s a penalty in execution speed when you use a sub routine One problem is the overhead in saving registers before jumping to the subroutine and restoring them aft
173. e it mentally We want to center all these boxes on a screen 80 columns wide To center something we subtract its width from 80 and divide by two to determine the left margin To gure the total width of all the boxes we add 8 4 8 4 8 32 three widths and two avenues 80 31 2 24 So we could crudely de ne 24 CONSTANT LEFTMARGIN and use the same approach for TOPMARGIN But what if we should later redesign the pattern so that the width changed or perhaps the gap between the boxes We d have to recompute the left margin ourselves In the Forth environment we can use the full power of Forth even when we re compiling Why not let Forth do the guring WIDE 3 AVE 2 80 SWAP 2 CONSTANT LEFTMARGIN HIGH 3 STREET 2 24 SWAP 2 CONSTANT TOPMARGIN Compile Time Factoring 189 6 18 Tip If a constant s value depends on the value of an earlier constant use Forth to calculate the value of the second None of these computations are performed when the application is running so run time speed is not a ected Here s another example Figure 6 2 shows the code for a word that draws shapes The word DRAW emits a star at every x y coordinate listed in the table called POINTS Note the word XY positions the cursor to the x y coordinate on the stack Notice the line immediately following the list of points HERE POINTS table 2 CONSTANT POINTS The phrase HERE PO
174. e method for pushing a value without also changing the method for popping a value The word uses plays an important role in this concept Parnas writes in a later paper 6 Systems that have achieved a certain elegance have done so by having parts of the system use other parts If such a hierarchical ordering exists then each level o ers a testable and usable subset of the system The design of the uses hierarchy should be one of the major milestones in a design e ort The division of the system into independently callable subpro grams has to go in parallel with the decisions about uses because they in uence each other A design in which modules are grouped according to control ow or sequence will not readily allow design changes Structure in the sense or control ow hierarchy is super cial A design in which modules are grouped according to things that may change can readily accommodate change 18 The Philosophy of Forth Looking Back and Forth In this section we ll review the fundamental features of Forth and relate them to what we ve seen about traditional methodologies Here s an example of Forth code BREAKFAST HURRIED IF CEREAL ELSE EGGS THEN CLEAN This is structurally identical to the procedure MAKE BREAKFAST on page 8 If you re new to Forth refer to Appendix A for an explanation The words HURRIED CEREAL EGGS and CLEAN are most likely also de ned a
175. e place where the box will start the upper left hand corner Then 30 30 BOX draws a box 30 units high and 30 units wide relative to the origin This approach reduces the number of stack arguments to BOX as part of the design Tip When determining which arguments to handle via data structures rather than via the stack choose the arguments that are the more permanent or that rep resent a current state 7 3 On PICK and ROLL Some folks like the words PICK PICK PICK PICK PICK and ROLL ROLL ROLL ROLL ROLL They use these words to access elements from any level on the stack We don t recommend them For one thing PICK PICK PICK PICK PICK and ROLL ROLL ROLL ROLL ROLL encourage the programmer to think of the stack as an array which it is not If you have so many elements on the stack that you need PICK PICK PICK PICK PICK and ROLL ROLL ROLL ROLL ROLL those elements should be in an array instead Second they encourage the programmer to refer to arguments that have been left on the stack by higher level calling de nitions without being explicitly On PICK and ROLL 203 passed as arguments This makes the de nition dependent on other de nitions That s unstructured and dangerous Finally the position of an element on the stack depends on what s above it and the number of things above it can change constantly For instance if you have an address at the fourth stack position down you can write
176. e stack prior to calling GRID These will remain on the stack unharmed until GRID has been executed and the calling de nition continues The Stack 267 Control Structures Forth provides all the control structuresneeded for structured GOTO less pro gramming The syntax of the IF THEN IF THEN IF THEN IF THEN IF THEN construct is as follows flag IF KNOCK THEN OPEN The ag is a value on the stack consumed by IF A non zero value indicates true zero indicates false A true ag causes the code after IF IF IF IF IF in this case the word KNOCK to be executed The word THEN THEN THEN THEN THEN marks the end of the conditional phrase execution resumes with the word OPEN A false ag causes the code between IF IF IF IF IF and THEN THEN THEN THEN THEN to not be executed In either case OPEN will be performed The word ELSE ELSE ELSE ELSE ELSE allows an alternate phrase to be executed in the false case In the phrase flag IF KNOCK ELSE RING THEN OPEN the word KNOCK will be performed if the ag is true otherwise the word RING will be performed Either way execution will continue starting with OPEN Forth also provides for indexed loops in the form limit index DO LOOP and inde nite loops in the forms BEGIN flag UNTIL and BEGIN flag WHILE REPEAT For the Whole Story For a complete introduction to the Forth command s
177. e two parts The main program called DOIT consists of three subordinate modules which in turn invoke the other modules shown below them As you can see the design emphasizes the transformation of input to output Coupling 15 Figure 1 6 The form of a structured chart from Structured Design IBM Systems Journal TO E TRANSFORM TRANSFORM 2 4 11 DOIT TRANSFORM TO D TO C TRANSFORM TRANSFORM TO B TO F GETC GETB PUTD PUTE WRITE 10 3 8 9 5 7 6 READ 1 IN OUT A 1 A B 2 3 4 5 6 7 8 9 10 11 B B C C C D D D E E E F F The tiny numbers of the hierarchy chart refer to the lines on the in out chart At point 1 the module READ the output is the value A At point 2 the module TRANSFORM TO B the input is A and the output is B Perhaps the greatest contribution of this approach is recognizing that decisions about control ow should not dominate the emerging design As we ll see control ow is a super cial aspect of the problem Minor changes in the requirements can profoundly change the program s control structures and deep six years of work But if programs are designed around other concerns such as the ow of data then a change in plan won t have so disastrous an e ect Information Hiding In a paper 4 published back in 1972 Dr David L Parnas showed that the criteria for decomposing m
178. e want to exe cute begins The stack now has marker joe code SWAP gt BODY Fetches the contents of the address point ing to JOE i e gets the address of JOE and computes JOE s pfa where the vec tor address goes Stores the address where the new code be gins CR CR CR CR CR etc into the vector address of JOE Now JOE points inside the de nition of TEST When we type JOE we ll do a carriage return DUP IF gt R THEN Fetches the contents of the cell contain ing zero Since the cell does contain zero the IF THEN statement is not per formed That s the basic idea But what about that cell containing zero That s for the use of AND AND AND AND AND Suppose we changed TEST to read TEST MAKE JOE CR AND SPACE That is when we invoke TEST we ll vector JOE to do a CR CR CR CR CR and we ll do a SPACE SPACE SPACE SPACE SPACE right now Here s what this new version of TEST will look like adr of adr of adr of adr of adr of adr of TEST MAKE adr JOE CR EXIT SPACE EXIT header MARKER De ning DOER MAKE 271 Here s the de nition of AND AND AND AND AND AND COMPILE EXIT HERE MARKER IMMEDIATE We can see that AND AND AND AND AND has compiled an EXIT EXIT EXIT EXIT EXIT just as semicolon would Next recall that MAKE MAKE MAKE MAKE MAKE saved the address of that cell in a variable called MARKER
179. e you see in Figure 1 1 This approach still widely used in languages like FORTRAN and BASIC su ers from being di cult to write and di cult to change if corrections need to be made In this bowl of spaghetti school of programming it s impossible to test a single part of the code or to gure out how something is getting executed that isn t supposed to be getting executed Di culties with spaghetti programs led to the discovery of ow charts These were pen and ink drawings representing the ow of execution used by the programmer as an aid to understanding the code being written Unfortu nately the programmer had to make the translation from code to ow chart and back by hand Many programmers found old fashioned ow charts less than useful Modularity A signi cant advance arose with the invention of Structured Programming a methodology based on the observation that large problems are more easily solved if treated as collections of smaller problems 1 Each piece is called a module Programs consist of modules within modules Structured programming eliminates spaghetti coding by insisting that control ow can be diverted only within a module You can t jump out from the middle of one module into the middle of another module Manageability 5 Figure 1 1 Unstructured code using jumps or GOTOs INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION INSTRUCTION TEST JUMP INS
180. early as good as a word that is used multiple times Any time a word is used only once you want to question its value Many times when a program has gotten too big I will go back through it looking for phrases that strike my eye as candidates for factoring The computer can t do this there are too many variables In looking over your work you often nd identical phrases or short passages duplicated several times In writing an editor I found this phrase repeated several times FRAME CURSOR Because it appeared several times I factored it into a new word called AT It s up to you to recognize fragments that are coded di erently but func tionally equivalent such as FRAME CURSOR 1 The 1 appears to make this phrase di erent from the one de ned as AT But in fact it can be written AT 1 On the other hand 6 9 Tip When factoring out duplicate code make sure the factored code serves a single purpose 180 Factoring Don t blindly seize upon duplications that may not be useful For instance in several places in one application I used this phrase BLK BLOCK gt IN C I turned it into a new word and called it LETTER since it returned the letter being pointed to by the interpreter In a later revision I unexpectedly had to write BLK BLOCK gt IN C I could have used the existing LETTER were it not for its C at the end Rather than duplicated the bulk of the phrase in the
181. echnique Especially if your conditionals are getting elaborate it s handy to jump out in the middle without having to match all your THEN THEN THEN THEN THENs at the end In one application I had a word that went like this TESTING SIMPLE 1CONDITION IF EXIT THEN 2CONDITION IF EXIT THEN 3CONDITION IF EXIT THEN SIMPLE handled the simple cases SIMPLE ended up with R gt DROP R gt DROP R gt DROP R gt DROP R gt DROP These other conditions were the more complex ones Everyone exited at the same point without having to painfully match all the IF IF IF IF IFs ELSE ELSE ELSE ELSE ELSEs and THEN THEN THEN THEN THENs The nal result if none of the conditions matched was an error condition It was bad code di cult to debug But it re ected the nature of the problem There wasn t any better scheme to handle it The EXIT EXIT EXIT EXIT EXIT and R gt DROP R gt DROP R gt DROP R gt DROP R gt DROP at least kept things manageable Using Structured Exits 253 Programmers sometimes also use EXIT EXIT EXIT EXIT EXIT to get out of a complicated BEGIN BEGIN BEGIN BEGIN BEGIN loop in a graceful way Or we might use a related technique in the DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP that we wrote for FUNCTION in our Tiny Editor earlier in this chapter In this word we are searching through a series of locations looking for a match If we nd a match we want to return the
182. ect comment Determine the rules review all the facts that you know In Chapter Two we described the rates for computing the cost of a phone call along with the rules for applying the rates Tip Picture the problem as a whole 4 2 In the analysis phase we separated the problem into its parts to clarify our understanding of each piece We are now entering the synthesis phase We must visualize the problem as a whole Try to retain as much information about the problem in your mind as possible Use words phrases gures and tables or any kind of graphic repre sentation of the data and or rules to help you see the maximum information at a glance Fill your mind to bursting with the requirements of the problem you need to solve the way you might ll your lungs with air Now hold that mental image the way you might hold your breath One of two things will happen You may see the solution in a ash of insight Great Exhale a sigh of relief and proceed directly to implementation Or the problem is too complex or too unfamiliar to be solved so easily In this case you ll have to turn your attention to analogies and partial solutions As you do so it s important that you have already concentrated on the problem s requirements all at once engraving these requirements on your mental retina Tip Develop a plan 4 3 If the solution didn t come at a glance the next step is to determine the ap proach that you will t
183. ect memory or in execution speed In fact the case statement compiles much the same code as the nested IF IF IF IF IF THEN THEN THEN THEN THEN statements A case statement is a good example of compile time factoring Should all Forth systems include such a case statement That s a matter of controversy The problem is twofold First the instances in which a case statement is actually needed are rare rare enough to question its value If there are only a few cases a nested IF IF IF IF IF ELSE ELSE ELSE ELSE ELSE THEN THEN THEN THEN THEN construct will work as well though perhaps not as readably If there are many cases a decision table is more exible Choosing Control Structures 237 Second many case like problems are not quite appropriate for the case structure The Eaker case statement assumes that you re testing for equality against a number on the stack In the instance of SUIT we have contiguous integers from zero to three It s more e cient to use the integer to calculate an o set and directly jump to the right code In the case of our Tiny Editor later in this chapter we have not but two dimensions of possibilities The case statement doesn t match that problem either Personally I consider the case statement an elegant solution to a mis guided problem attempting an algorithmic expression of what is more aptly described in a decision table A case statement ought to be part of the application w
184. ed to not later Any time you set a ag ask yourself why you re setting it If the answer is So I ll know to do such and such later then ask yourself if you can do such and such now A little restructuring can greatly simplify your design 8 21 Tip Don t put o till run time what you can compile today 254 Minimizing Control Structures Any time you can make a decision prior to compiling an application do Suppose you had two versions of an array one that did bounds check ing for your protection during development and one that ran faster though unprotected for the actual application Keep the two versions in di erent screens When you compile your ap plication load only the version you need By the way if you follow this suggestion you may go crazy editing paren theses in and out of your load blocks to change which version gets loaded each time Instead write throw away de nitions that make the decisions for you For instance as already previewed in another context STEPPERS 150 TESTING 1 AND LOAD Tip DUP DUP DUP DUP DUP a ag don t recreate it 8 22 Sometimes you need a ag to indicate whether or not a previous piece of code was invoked The following de nition leaves a ag which indicates that DO IT was done DID I t I did SHOULD I IF DO IT TRUE ELSE FALSE THEN This can be simpli ed to DID I t I did SHOULD I DUP IF DO
185. egister AH with the number of the video routine you want 92 Preliminary Design Decomposition No scrambled Unfortunately in all 16 routines there is not one that displays a text string To do that you must repeat the process of loading registers and gen erating a software interrupt which in turn must make a decision about which routine you want and do a few other things you don t need for every single character Try writing a text editor in which the entire screen may need to be re freshed with each keystroke Slow as mail You can t improve the speed be cause you can t reuse any of the information within the video routines except for what s provided on the outside The stated reason for this is to insulate the programmer from device addresses and other details of the hardware After all these could change with future upgrades The only way to e ciently implement video I O on this machine is to move strings directly into video memory You can do this easily because the reference manual tells you the address at which video memory starts But this defeats the intent of the system s designers Your code may no longer survive a hardware revision By supposedly protecting the programmer from details segregation has defeated the purpose of information hiding Components in contrast are not segregated modules but rather cumulative additions to the dictionary A video lexicon would at the very least give a n
186. eing loaded On the stack initially we have lo hi where lo and hi are the o sets from BLK BLK BLK BLK BLK We need to permute them for DO DO DO DO DO like this hi 1 blk lo blk Our biggest problem is adding the value of BLK to both o sets We ve already taken a wrong turn but we don t know it yet So let s proceed We try lo hi BLK lo hi blk SWAP lo blk hi OVER lo blk hi blk lo blk hi blk 1 lo blk hi blk 1 ROT ROT hi blk 1 lo blk hi blk 1 lo blk We made it but what a mess If we re gluttons for punishment we might make two more stabs at it arriving at BLK DUP ROT 1 ROT ROT and BLK ROT OVER ROT ROT 1 SWAP All three sequences do the same thing but the code seems to be getting blurrier not better With experience we learn to recognize the combination ROT ROT as a dan ger sign the stack is too crowded Without having to work out the alternates we recognize the problem once we make two copies of blk we have four elements on the stack 200 Handling Data Stacks and States At this point the rst resort is usually the return stack BLK DUP gt R 1 SWAP R gt See The Stylish Return Stack coming up next Here we ve DUP DUP DUP DUP DUPed blk saving one copy on the return stack and adding the other copy to hi Admittedly an improvement But readable Next we think Maybe we need a named variable
187. else 4 24 Tip In devising an algorithm consider exceptions last In writing code handle exceptions rst This tells us something about the general structure of our digit producing word It will have to begin with a test for the 4 9 exceptions In either of those cases it will respond accordingly If neither exception applies it will follow the normal algorithm Using pseudocode then DIGIT n 4 OR 9 IF special cases ELSE normal case THEN 126 Detailed Design Problem Solving An experienced Forth programmer would not actually write out this pseu docode but would more likely form a mental image of the structure for elimi nating the special cases A less experienced programmer might nd it helpful to capture the structure in a diagram or in code as we ve done here In Forth we try to minimize our dependence on logic But in this case we need the conditional IF IF IF IF IF because we have an exception we need to eliminate Still we ve minimized the complexity of the control structure by limiting the number of IF IF IF IF IF THEN THEN THEN THEN THENs in this de nition to one Yes we still have to distinguish between the 4 case and the 9 case but we ve deferred that structural dimension to lower level de nitions the test for 4 or 9 and the special case code What our structure really says is that either the 4 exception or the 9 exception must prohibit execution of the normal cas
188. embly instruction and machine instruction But names are easier for programmers to remember For this reason the new instructions were called mnemonics Power Assembly language programming is characterized by a one for one correspon dence between each command that the programmer types and each command that the processor performs In practice programmers found themselves often repeating the same se quence of instructions over and again to accomplish the same thing in di erent parts of the program How nice it would be to have a name which would represent each of these common sequences This need was met by the macro assembler a more complicated assem bler that could recognize not only normal instructions but also special names macros For each name the macro assembler assembles the ve or ten ma chine instructions represented by the name just as though the programmer had written them out in full Abstraction A major advance was the invention of the high level language Again this was a translator program but a more powerful one High level languages make it possible for programmers to write code like this X Y 456 A 2 which looks a lot like algebra Thanks to high level languages engineers not just bizarre bit jockeys could start writing programs BASIC and FORTRAN are examples of high level languages Power 3 So then I typed GOTO 500 and here I am High level languages are clearly more
189. ently Our word s syntax will be RAM ALLOT bytes to allot starting adr This syntax will remain the same whether we de ne it to allocate growing upward RAM ALLOT bytes to allot starting adr gt RAM DUP ROT gt RAM or to allocate growing downward RAM ALLOT bytes to allot starting adr gt RAM SWAP DUP gt RAM Chapter Four Our solution is as follows CARDS Shuffle 6 20 83 52 CONSTANT CARDS CREATE DECK CARDS ALLOT one card per byte 280 Answers to Further Thinking Problems INIT DECK CARDS 0 DO I DECK I C LOOP INIT DECK CSWAP a1 a2 swap bytes at a1 and a2 2DUP C SWAP C ROT C SWAP C SHUFFLE shuffle deck of cards CARDS 0 DO DECK I DECK CARDS CHOOSE CSWAP LOOP Chapter Eight This will work 20 CHOOSE 2 CHOOSE IF NEGATE THEN But this is simpler 40 CHOOSE 20 Chapter Eight 281 APPENDIX E Summary of Style Conventions The contents of this Appendix are in the public domain We encourage publi cation without restriction provided that you credit the source Spacing and Indentation Guidelines 1 space between the colon and the name 2 spaces between the name and the comment 2 spaces or a carriage return after the comment and before the de nition 3 spaces between the name and de nition if no comment is used 3 spaces indentation on each subsequent line
190. ept of information hiding to the development of subroutines ensuring that each module knows as little as Information Hiding 17 possible about the insides of other modules Contemporary programming lan guages such as C Modula 2 and Edison apply this concept to the architecture of their procedures But Parnas takes the idea much further He suggests that the con cept should be extended to algorithms and data structures In fact hiding information not decision structure or calling hierarchy should be the pri mary basis for design The Super ciality of Structure Parnas proposes two criteria for decomposition 1 possible though currently unplanned reuse and 2 possible though unplanned change This new view of a module is di erent than the traditional view This mod ule is a collection of routines usually very small which together hide infor mation about some aspect of the problem Two other writers describe the same idea in a di erent way using the term data abstraction 5 Their example is a push down stack The stack module consists of routines to initialize the stack push a value onto the stack pop a value from the stack and determine whether the stack is empty This multiprocedure module hides the information of how the stack is constructed from the rest of the application The procedures are considered to be a single module because they are interdependent You can t change th
191. er by the size of the new array to show that we ve allocated that much additional RAM To make the above more readable we might add these two de nitions THERE address of next free byte in RAM gt RAM RAM ALLOT bytes to allocate gt RAM 96 Preliminary Design Decomposition We can now rewrite the above equivalently as THERE CONSTANT FIRST ARRAY 8 RAM ALLOT THERE CONSTANT SECOND ARRAY 6 RAM ALLOT THERE CONSTANT THIRD ARRAY 100 RAM ALLOT An advanced Forth programmer would probably combine these opera tions into a single de ning word but that whole topic is not germane to what I m leading up to Finally suppose we have 20 such array de nitions scattered throughout our application Now the problem Somehow the architecture of our system changes and we decide that we must allocate this memory such that it ends at HEX address EFFF In other words we must start at the end allocating arrays backwards We still want each array name to return its starting address however To do this we must now write F000 gt RAM EFFF last byte plus one THERE address of next free byte in RAM gt RAM RAM ALLOT bytes to allocate NEGATE gt RAM 8 RAM ALLOT THERE CONSTANT FIRST ARRAY 6 RAM ALLOT THERE CONSTANT SECOND ARRAY 100 RAM ALLOT THERE CONSTANT THIRD ARRAY This time RAM ALLOT decrements the pointer That s okay it s easy to add NEGATE to the de nition of RAM ALL
192. er is almost certainly the most complex elaborate part of your entire application You have switched from solving a problem to writing an interpreter I think that programmers like to write interpreters They like to do these elaborate di cult things But there comes a time when the world is going to have to quit programming keypads and converting numbers to binary and start solving problems Algorithms and Data Structures In Chapter Two we learned how to describe a problem s requirements in terms of interfaces and rules In this section we ll re ne the conceptual model for each component into clearly de ned algorithms and data structures An algorithm is a procedure described as a nite number of rules for accomplishing a certain task The rules must be unambiguous and guaranteed to terminate after a nite number of applications The word is named for the ninth century Persian mathematician al Khowarizimi An algorithm lies halfway between the imprecise directives of human speech such as Please sort these letters chronologically and the precise direc tives of computer language such as BEGIN 2DUP lt IF etc The algorithm for sorting letters chronologically might be this 1 Take an unsorted letter and note its date Algorithms and Data Structures 119 2 Find the correspondence folder for that month and year 3 Flip through the letters in the folder starting from the front until you nd th
193. erwards Even more time consuming is the invisible but signi cant code needed to pass parameters to and from the subroutine Subroutines are also fussy about how you invoke them and particularly how you pass data to and from them To test them independently you need to write a special testing program to call them from For these reasons computer scientists recommend their use in moderation In practice subroutines are usually fairly large between a half page to a full page of source code in length Successive Re nement An approach that relies heavily on subroutines is called Successive Re nement 2 The idea is that you begin by writing a skeletal version of your program using natural names for procedures for data structures Then you write versions of each of the named procedures You continue this process to greater levels of detail until the procedures can only be written in the computer language itself At each step the programmer must make decisions about the algorithms being used and about the data structures they re being used on Decisions about the algorithms and associated data structures should be made in parallel If an approach doesn t work out the programmer is encouraged to back track as far as necessary and start again Notice this about successive re nement You can t actually run any part of the program until its lowest level components are written Typically this means you can t test the program until after y
194. es will be required to let the users search the BOOKS e ciently You may need another entity consisting of authors names in alphabetical order along with attribute pointers to the books each author has written Certain constraints will also a ect the conceptual model of the data struc ture In the library index example you need to know not only what information the users need but also how long they re willing to wait to get it For instance users can request listings of topics by year of publication say everything on ladies lingerie between 1900 and 1910 If they expect to get this information in the snap of a girdle you ll have to index on years and on topics If they can wait a day you might just let the computer search through all the books in the library Achieving Simplicity 2 11 Tip Keep it simple While you are taking these crucial rst steps toward understanding the problem keep in mind the old saying Given two solutions to a problem the correct one is the simpler This is especially true in software design The simpler solution is often more di cult to discover but once found it is easier to understand easier to implement easier to verify and debug easier to maintain more compact more e cient more fun One of the most compelling advocates of simplicity is Moore You need a feeling for the size of the problem How much code should it take
195. et read Starting Forth published by Prentice Hall 268 Overview of Forth For Newcomers APPENDIX B De ning DOER MAKE If your system doesn t have DOER and MAKE already de ned this appendix is meant to help you install them and if necessary understand how they work Because by its nature this construct is system dependent I ve included several di erent implementations at the end of this appendix in the hope that one of them will work for you If no and if this section doesn t give you enough information to get them running you probably have an unusual system Please don t ask me for help ask your Forth vendor Here s how it works DOER DOER DOER DOER DOER is a de ning word that creates an entry with one cell in its parameter eld That cell contains the vector address and is initialized to point to a no op word called NOTHING NOTHING NOTHING NOTHING NOTHING Children of DOER DOER DOER DOER DOER will execute that DOES gt DOES gt DOES gt DOES gt DOES gt code of DOER DOER DOER DOER DOER which does only two things fetch the vector address and place it on the return stack That s all Forth execution then continues with this address on the return stack which will cause the vectored function to be performed It s like saying in 83 Standard NOTHING gt BODY gt R lt return gt which executes NOTHING This trick only works with colon de nitions Here s an illustration of th
196. etailed design phase from implementation because we tend to design in Forth For this reason we ll get a bit ahead of ourselves in this chapter by not only presenting a problem but also designing a solution to it right on through to the coded implementation Problem Solving Techniques Even neophytes can solve programming problems without devoting any con scious thought to problem solving techniques So what s the point in studying techniques of problem solving To quicken the process By thinking about the ways in which we solve problems apart from the problems themselves we enrich our subconscious storehouse of techniques G Polya has written several books on problem solving especially of the mathematical problem The most accessible of these is How to Solve It 1 Although solving a mathematical problem isn t quite the same as solving a software problem you ll nd some valuable suggestions there The following series of tips summarize several techniques recommended by the science of problem solving 100 Detailed Design Problem Solving Tip Determine your goal 4 1 Know what you re trying to accomplish As we saw in Chapter Two this step can be detailed further Determine the data interfaces Know what data will be required to ac complish the goal and make sure those data are available input Know what data the function is expected to produce output For a single de nition this means writing the stack e
197. few tips back No decisions are necessary in the de nition of CHARACTER The graphics character is simply computed Note to use the same algorithm to translate a set of six adjoining pixels in a large grid we can merely rede ne PIXEL That s an example of adding indirection backwards and of good decomposition Unfortunately external components are not always designed well For instance The IBM Personal Computer uses a similar scheme for graphics char acters on its video display but without any discernible correspondence between Redesigning 251 the ASCII values and the pattern of pixels The only way to produce the ASCII value is by matching patterns in a lookup table Moore The 68000 assembler is another example you can break your heart over looking for a good way to express those op codes with the minimal number of operators All the evidence suggests there is no good solution The people who designed the 68000 didn t have assemblers in mind And they could have made things a lot easier at no cost to themselves By using properties of a component in this way your code becomes dependent on those properties and thus on the component itself This is excusable though because all the dependent code is con ned to a single lexicon which can easily be changed if necessary Using Structured Exits 8 19 Tip Use the structured exit In the chapter on factoring we demonstrated the possibility of factoring out a cont
198. g a lot of unnecessary code by choosing a syntax that Forth can support without any special e ort on your part Here are some elementary rules of Forth s natural syntax Tip Let numbers precede names 4 14 Words that require a numeric argument will naturally expect to nd that num ber on the stack Syntactically speaking then the number should precede the name For instance the syntax of the word SPACES which emits n number of spaces is 20 SPACES Sometimes this rule violates the order that our ear is accustomed to hearing For instance the Forth word expects to be preceded by both arguments as in 3 4 This ordering in which values precede operators is called post x Forth in its magnanimity won t insist upon post x notation You could rede ne to expect one number in the input stream like this 3 4 by de ning it so BL WORD NUMBER DROP where WORD WORD WORD WORD WORD is 79 83 Standard returning an address and NUMBER NUMBER NUMBER NUMBER NUMBER returns a double length value as in the 83 Standard Uncontrolled Reference Words Fine But you wouldn t be able to use this de nition inside other colon de nitions or pass it arguments thereby defeating one of Forth s major advan tages Frequently noun type words pass their addresses or any type of pointer as a stack argument to verb type words The Forth like syntax of noun verb
199. ge routines three big circuit boards lled with ICs and a 70 odd pin System Bus Day by day everything got more fragile and harder to x The wiring on the circuit boards frayed the connectors got loose the assembler code grew ever more tangled Forth was an obvious solution to the software problem since it provided a decent environment in which to build and maintain a complex and rapidly changing program But the essence of good Forth programming is the art of factoring procedures into useful free standing words The idea of the Forth word had unexpected implications for laboratory hardware design Instead of building a big monolithic all purpose Interface I found myself build ing piles of simple little boxes which worked a lot like Forth words they had a xed set of standard inputs and standard outputs they performed just one function they were designed to connect up to each other without much e ort 262 Forth s E ect on Thinking and they were simple enough that you could tell what a box did just by looking at its label The idea of human scale is I think today s seminal concept in software design This isn t speci cally a Forth development the great joy of UNIX in its youth at least was that you could read it since it was written in C understand it since it was small and modify it since it was simple Forth shares these virtues although it s designed to tackle a di erent sort of
200. glossary Stack E ect Comment A stack e ect comment is a stack e ect that appears in source code sur rounded by parentheses Here s the stack e ect comment for the word COUNT address of counted string address of text count or counted string text count The count is on top of the stack after the word has executed If a de nition has no e ect on the stack that is no e ect the user is aware of despite what gyrations occur within the de nition it needs no stack e ect comment BAKE COOKIES OVEN On the other hand you may want to use an empty stack comment i e 152 Implementation Elements of Forth Style BAKE COOKIES OVEN to emphasize that the word has no e ect on the stack If a de nition consumes arguments but returns none the double hyphen is optional For instance address count can be shortened to address count The assumption behind this convention is this There are many more colon de nitions that consume arguments and return nothing than de nitions that consume nothing and return arguments Stack Abbreviation Standards Abbreviations used in stack notation should be consistent Table 5 2 lists most of the commonly used abbreviations This table reappears in Appendix E The terms single length double length etc refer to the size of a cell in the particular Forth system If the system uses a
201. h You either gravitate back to the way you started or the way you started gravitates toward the new way Second the new approach may show all kinds of powerful possibilities Now you have a benchmark You can look at both approaches and compare the advantages of both You re in a better position to judge Getting stuck comes from trying too hard to follow a single approach Re member to say I want this kumquat crusher to be di erent Let s reject the traditional design as not interesting Let s try some crazy ideas The best thing is to start drawing pictures I draw little men That keeps it from looking like data and interfering with my thinking process The human mind works exceptionally well with analogies Putting things in context keeps you from getting stuck within the con nes of any language even Forth When I want to focus my concentration I draw on little pieces of paper When I want to think in broad strokes to capture the overall ow I draw on great big pieces of paper These are some of the crazy tricks I use to keep from getting stagnant When I program in Forth I spend a day just dreaming kicking around ideas Usually before I start typing I sketch it out in general terms No code just talk Notes to myself Then I start with the last line of code rst I describe what I would like to do as close to English as I can Then I use the editor to slide this de nition towards the bottom of t
202. hange the contents of a variable without necessarily having to know anything about how that data will be used who will use it or when and if it will be used Another piece of code can fetch the contents of a variable and use it without knowing where that value came from For every word that pushes a value onto the stack another word must consume that value The stack gives us point to point communication like the post o ce Variables on the other hand can be set by any command and accessed any number of times or not at all by any command Variables are available for anyone who cares to look like gra ti Thus variables can be used to re ect the current state of a airs Using currentness can simplify problems In the Roman numeral example of Chapter Four we used the variable COLUMN to represent the current decimal place the words ONER FIVER and TENER depended on this information to determine which type of symbol to display We didn t have to specify both descriptions every time as in TENS ONER TENS FIVER etc On the other hand currentness adds a new level of complexity To make something current we must rst de ne a variable or some type of data structure We also must remember to initialize it if there s any chance that part of our code will refer to it before another part has had a chance to set it A more serious problem with variables is that they are not reentrant On a multi tasked Forth system each task w
203. hat were there before Delete Pressing the combination of keys Ctrl D deletes the character under the cursor and slides the remaining characters leftwards Insert Pressing the combination of keys Ctrl I switches the editor into Insert Mode where subsequently typing ordinary characters inserts them at the cursor position sliding the remaining characters rightwards As part of the conceptual model we should also consider the error or exception handling for instance what is the limit of the eld what happens in insert mode when characters spill o the right etc That s all the speci cation we have right now The rest is up to us Let s try to determine what components we ll need First the editor will react to keys that are typed at the keyboard Therefore we ll need a keystroke interpreter some kind of routine that awaits keystrokes and matches them up with a list of possible operations The keystroke interpreter is one component and its lexicon will consist of a single word Since that word will allow the editing of a eld let s call the word EDIT The operations invoked by the keystroke interpreter will comprise a sec ond lexicon The de nitions in this lexicon will perform the various functions required One word might be called DELETE another INSERT etc Since each of these commands will be invoked by the interpreter each of them will process a single keystroke Below these commands should l
204. he black boxes When I design a system that s got di erent modules I try to make the coupling as rational and as little as possible But there s always give and take since you re compromising the ideal For the document itself I use DFDs data ow diagrams which we ll discuss later and any other kind of representation that I can show to my client I show them as many diagrams as I can to clarify my understanding I don t generally use these once it comes to implementation The prose must be complete even without reference to the diagrams De ning the Interfaces 49 2 7 Tip Decide on error and exception handling early as part of de ning the interface It s true that when coding for oneself a programmer can often concentrate rst on making the code run correctly under normal conditions then worry about error handling later When working for someone else however error handling should be worked out ahead of time This is an area often overlooked by the beginning programmer The reason it s so important to decide on error handling at this stage is the wide divergence in how errors can be treated An error might be ignored made to set a ag indicating that an error occurred while processing continues made to halt the application immediately designed to initiate procedures to correct the problem and keep the pro gram running There s room for a serious communications gap if t
205. he degree of complexity required in the error handling is not nailed down early Obviously the choice bears tremendous impact on the design and implementation of the application 2 8 Tip Develop the conceptual model by imagining the data traveling through and being acted upon by the parts of the model A discipline called structured analysis 2 o ers some techniques for describing interfaces in ways that your clients will easily understand One of these tech niques is called the data ow diagram DFD which Teleska mentioned A data ow diagram such as the one depicted in Figure 2 3 emphasizes what happens to items of data as they travel through the system The cir cles represent transforms functions that act upon information The arrows represent the inputs and outputs of the transforms The diagram depicts a frozen moment of the system in action It ignores initialization looping structures and other details of programming that relate to time Three bene ts are claimed for using DFDs First they speak in simple direct terms to the customer If your customer agrees with the contents of your data ow diagram you know you understand the problem Second they let you think in terms of the logical whats without getting caught up in the procedural hows which is consistent with the philosophy of hiding information as we discussed in the last chapter 50 Analysis Figure 2 3 A data ow diagram
206. he screen and begin coding the internal words Then I realize that s a lousy way to do it Maybe I split my top word into two and transfer one of them to an earlier block so I can use it earlier I run the hardware if I have it otherwise I simulate it Forth requires self discipline You have to stop diddling with the keyboard Forth is so willing to do what I tell it to I ll tell it to do all kinds of ridiculous things that have nothing to do with where I m trying to go At those times I have to get away from the keyboard Forth lets you play That s ne chances are you ll get some ideas As long as you keep yourself from playing as a habit Your head is a whole lot better than the computer for inventing things Interview with a Software Inventor 109 Detailed Design We re now at the point in the development cycle at which we ve decided we need a component or a particular word The component will consist of a number of words some of which those that comprise the lexicon will be used by other components and some of which the internal words will be only used within this component Create as many words as necessary to obey the following tip 4 12 Tip Each de nition should perform a simple well de ned task Here are the steps generally involved in designing a component 1 Based on the required functions decide on the names and syntax for the external de nitions de ne the interfaces 2 Re ne
207. hen give it a dummy value and use it anyway Anytime you run into a special case try to nd an algorithm for which the special case becomes a normal case 8 18 Tip Use properties of the component A well designed component hardware or software will let you implement a corresponding lexicon in a clean e cient manner The character graphics set from the old Epson MX 80 printer although now obsolete illustrates the point well Figure 8 6 shows the graphics characters produced by the ASCII codes 160 to 223 250 Minimizing Control Structures Figure 8 6 The Epson MX 80 graphics character set Each graphics character is a di erent combination of six tiny boxes either lled in or left blank Suppose in our application we want to use these characters to create a design For each character we know what we want in each of the six positions we must produce the appropriate ASCII character for the printer A little bit of looking will tell you there s a very sensible pattern involved Assuming we have a six byte table in which each byte represents a pixel in the pattern PIXELS 0 1 2 3 4 5 and assuming that each byte contains hex FF if the pixel is on zero if it is o then here s how little code it takes to compute the character CREATE PIXELS 6 ALLOT PIXEL i a PIXELS CHARACTER graphics character 160 6 O DO I PIXEL C I 2 AND LOOP We introduced 2 a
208. hen useful but not part of the system Looping Structures The right looping structure can eliminate extra conditionals Moore Many times conditionals are used to get out of loops That particular use can be avoided by having loops with multiple exit points This is a live topic because of the multiple WHILE WHILE WHILE WHILE WHILE construct which is in poly Forth but hasn t percolated up to Forth 83 It s a simple way of de ning multiple WHILE WHILE WHILE WHILE WHILEs in the same REPEAT REPEAT REPEAT REPEAT REPEAT Also Dean Sanderson of Forth Inc has invented a new construct that introduces two exit points to a DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP Given that construction you ll have fewer tests Very often I leave a truth value on the stack and if I m leaving a loop early I change the truth value to remind myself that I left the loop early Then later I ll have an IF IF IF IF IF to see whether I left the loop early and it s just clumsy Once you ve made a decision you shouldn t have to make it again With the proper looping constructs you won t need to remember where you came from so more conditionals will go away This is not completely popular because it s rather unstructured Or perhaps it is elaborately structured The value is that you get simpler programs And it costs nothing Indeed this is a live topic As of this writing it s too early to make any speci
209. her possibility is to write a word that fetches the parameter of the DOER DOER DOER DOER DOER word TYPE the pointer to the current code and compares it against the address of PRINTER If it s less than the address of PRINTER we re using the VIDEO routine otherwise we re using the PRINTER routine If changing the state involves changing a small number of functions you can still use DOER MAKE Here are de nitions of three memory move operators that can be shut o together DOER vectorable DOER CMOVE vectorable CMOVE DOER FILL vectorable FILL STORING MAKE AND MAKE CMOVE CMOVE AND MAKE FILL FILL STORING MAKE 2DROP AND MAKE CMOVE 2DROP DROP AND MAKE FILL 2DROP DROP But if a large number of functions need to be vectored a state table would be preferable A corollary to this rule introduces the structured exit hook a DOER DOER DOER DOER DOER word vectored to perform a structured exit DOER HESITATE the exit hook DISSOLVE HESITATE FILE DIVORCE Much later in the listing RELENT MAKE HESITATE SEND FLOWERS R gt DROP By default HESITATE does nothing If we invoke DISSOLVE we ll end up in court But if we RELENT before we DISSOLVE we ll send owers then jump clear to the semicolon canceling that court order before our partner ever nds out This approach is especially appropriate when the cancellation must be
210. hich requires local variables must have its own copies Forth s USER USER USER USER USER variables serve this purpose See Starting Forth Chapter Nine Forth Geography Even within a single task a de nition that refers to a variable is harder to test verify and reuse in a di erent situation than one in which arguments are passed via the stack Suppose we are implementing a word processor editor We need a routine that calculates the number of characters between the current cursor position and the previous carriage return line feed sequence So we write a word that employs a DO DO DO DO DO LOOP LOOP LOOP LOOP LOOP starting at the current position CURSOR and ending at the zeroth position searching for the line feed character Once the loop has found the character sequence we subtract its relative address from our current cursor position its position CURSOR SWAP to determine the distance between them Our word s stack e ect is distance to previous cr lf The Problem With Variables 207 But in later coding we nd we need a similar word to compute the distance from an arbitrary character not the current cursor position to the rst previous line feed character We end up factoring out the CURSOR and allowing the starting address to be passed as an argument on the stack resulting in starting position distance to previous cr lf By factoring out the reference to the variable
211. high level colon de nition that occupies more than one screen because gt is immediate But it s never good style to let a colon de nition cross screen boundaries They should never be that long On the other hand an extremely complicated and time critical piece of assembler coding might occupy several sequential screens In this case though normal LOAD LOAD LOAD LOAD LOADing will do just as well since the assembler does not use compilation mode and therefore does not require immediacy Finally the arrow wastes an extra line of each source screen We don t recommend it gt vs THRU 143 An Alternative to Screens Source in Named Files Some Forth practitioners advocate storing source code in variable length named text les deliberately emulating the approach used by traditional compilers and editors This approach may become more and more common but its usefulness is still controversial Sure it s nice not to have to worry about running out of room in a screen but the hassle of writing in a restricted area is compensated for by retaining control of discrete chunks of code In developing an application you spend a lot more time loading and reloading screens than you do rearranging their contents In nite length les allow sloppy disorganized thinking and bad factor ing De nitions become longer without the discipline imposed by the 1K block boundaries The tendency becomes to write a 2
212. hout knowledge of the structures and or algorithms within The distance of these structures from actual machine code is irrelevant The code written to toggle bits in an output port should in theory look no more intimidating than the code to format a report Even machine code should be readable A true Forth based engine would enjoy a syntax and dictionary identical and continuous with the high level dictionary we know today Summary In this chapter we ve seen two ways that applications can be decomposed into components and according to sequential complexity Special attention should be paid to those components that serve as inter faces between other components Now if you ve done preliminary design correctly your problem is lying at your feet in a heap of manageable pieces Each piece represents a problem to solve Grab your favorite piece and turn to the next chapter For Further Thinking Answers appear in Appendix D 1 Below are two approaches to de ning an editor s keyboard interpreter Which would you prefer Why a Define editor keys HEX 72 CONSTANT UPCURSOR 80 CONSTANT DOWNCURSOR 77 CONSTANT RIGHTCURSOR 75 CONSTANT LEFTCURSOR 82 CONSTANT INSERTKEY 83 CONSTANT DELETEKEY DECIMAL Keystroke interpreter EDITOR BEGIN MORE WHILE KEY CASE UPCURSOR OF CURSOR UP ENDOF DOWNCURSOR OF CURSOR DOWN ENDOF RIGHTCURSOR OF CURSOR gt ENDOF LEFTCURSOR OF CURSOR lt ENDOF INSERTKEY OF INSERT
213. hs integration and testing take another month This is the typical cycle One project took almost two years but six or seven months is reasonable When we started with Forth ve years ago it wasn t like that When I received a functional speci cation I just started coding I used a cross between top down and bottom up generally de ning a structure and as I needed it some of the lower level and then returning with more structure The reason for that approach was the tremendous pressure to show something to management We wound up never writing down what we were doing Three years later we would go back and try to modify the code without any doc umentation Forth became a disadvantage because it allowed us to go in too early It was fun to make the lights ash and disk drives hum But we didn t go through the nitty gritty design work As I said our free spirits have come back to haunt us Now for the new programmers we have an established requirement a thorough design spec that de nes in detail all the high level Forth words the tasks that your project is going to do No more reading a few pages of the functional speci cation answering that reading a few more answering that etc No living programmer likes to document By ensuring the design ahead of time we re able to look back several years later and remember what we did I should mention that during the design phase there is some amount of coding d
214. ichael 208 262 Hardware constraints 46 Harris Kim 39 136 Hart Leslie 107 Hierarchical input process output designing 15 16 High level languages development of 3 5 Forth as 27 31 How to Solve It Polya 100 Hybrid values 241 242 Hyphenated names 166 167 I Implementation 136 170 choosing names 163 168 comment conventions 150 159 factoring see Factoring listing organization 136 146 screen layout 146 150 vertical format vs horizontal format 159 163 Implicit calls 19 Implicit data passing 19 20 Indentation 150 284 INDEX 145 Information hiding 16 18 24 85 182 184 Input process output designing hi erarchical 15 16 Input stream comment 150 156 285 Interface component 85 88 Interface de nition 49 52 101 Interface lexicon 210 INTERPRET 239 Interpreters 118 119 Iterative approach 39 40 192 195 J Johnson Dave 40 41 52 160 Jump instructions 5 6 K Kogge Peter 44 45 208 L LaManna Michael 65 Laxen Henry 164 LEAP 277 Level thinking limits of 90 95 Lexicons 22 23 110 119 138 Line by line commenting 161 Listing organization 136 143 LIT 177 Load screens 138 143 application 138 140 chapter 140 143 Local variables 201 203 210 Logic 120 122 Logical binding 14 Loops 5 238 240 268 M Macro assembler 3 MAKE 234 Manageability 5 MAX 242 MIN 242 Mnemonic
215. iddle of the useful phrase we have to use stack manipulation For instance to center a piece of text ten characters long on an 80 column screen we would write 80 10 2 SPACES But text isn t always 10 characters long To make the phrase useful for any string you d factor out the length by writing CENTER length 80 SWAP 2 SPACES The data stack can also be used to pass addresses Therefore what s factored out may be a pointer to data rather than the data themselves The data can be numbers or even strings and still be factored out through use of the stack Sometimes the di erence appears to be a function but you can factor it out simply as a number on the stack For instance Segment 1 WILLY NILLY PUDDIN PIE AND Segment 2 WILLY NILLY 8 PUDDIN PIE AND How can you factor out the 8 operation By including in the factoring and passing it a one or eight NEW n WILLY NILLY PUDDIN PIE AND Segment 1 1 NEW Segment 2 8 NEW Of course if WILLY NILLY changes the stack you ll need to add appropriate stack manipulation operators If the operation involves addition you can nullify it by passing a zero Tip For simplicity try to express the di erence between similar fragments as a numeric di erence values or addresses rather than as a procedural di erence 6 1 Factoring Out Data 173 Factoring Out Functions On the other hand the di ere
216. idered implemented xed and changed with minimal consideration or e ect on the other pieces of the system By dividing a problem into simple modules programs were expected to be easier to write easier to change and easier to understand But what is a module and on what basis does one make the divisions Structured Design outlines three factors for designing modules Functional Strength One factor is something called functional strength which is a measure of the uniformity of purpose of all the statements within a module If all the statements inside the module collectively can be thought of as performing a single task they are functionally bound You can generally tell whether the statements in a module are functionally bound by asking the following questions First can you describe its purpose in one sentence If not the module is probably not functionally bound Next ask these four questions about the module 1 Does the description have to be a compound sentence 2 Does it use words involving time such as rst next then etc 3 Does it use a general or nonspeci c object following the verb 4 Does it use words like initialize which imply a lot of di erent functions being done at the same time If the answer to any of these four questions is yes you re looking at some less cohesive type of binding than functional binding Weaker forms of binding include Coincide
217. ie a third component the set of words that implement the data structure to be edited Finally we ll need a component to display the eld on the video screen For the sake of simplicity let s plan on creating one word only REDISPLAY to redisplay the entire eld after each key is pressed EDITOR BEGIN KEY REVISE REDISPLAY UNTIL Example A Tiny Editor 75 Figure 3 2 Generalized decomposition of the Tiny Editor problem This approach separates revising the bu er from updating the display For now we ll only concentrate on revising the bu er Let s look at each component separately and try to determine the words each will need We can begin by considering the events that must occur within the three most important editing functions overwriting deleting and insert ing We might draw something like the following on the back of an old pizza menu we won t pay much attention to exception handling in the present dis cussion To Overwrite Store new character into byte pointer to by pointer Advance pointer unless at end of eld F U N K T I O N A L I T Y F U N C T I O N A L I T Y F U N C T I O N A L I T Y To Delete Copy leftwards by one place the string beginning one place to the right of the pointer Store a blank into the last posi tion on the line F U N C T I O N S A L I T Y F U N C T I O N A L I T Y Y F U N C T I O N A L I T Y To Insert Copy rightwards by
218. ilot plant system Starling designed both the hardware and software to known require ments on the laboratory automation system he also de ned the requirements himself His e orts were extremely successful On one project the new system typically costs only 20 as much as the equivalent system and requires days instead of months to install and con gure I asked him what techniques of project management he employed On both of these projects much design was needed I did not follow the tradi tional analysis methods however I did employ these steps First I clearly de ned the boundaries of the problem Second I determined what the smaller functional pieces the software subsys tems had to be Third I did each piece put them together and the system ran Next I asked the users Does this meet your requirements Sometimes it didn t and in ways that neither the users nor the speci cation designers could have anticipated For instance the designers didn t realize that the original speci cation wouldn t produce pleasing human oriented graphics displays After working with the interactive graphics on the rst version users were applying arbitrary scales and coming up with oddball displays So even after the basic plot algorithm was designed we realized we needed auto scaling We went back in and analyzed how human beings plot data and wrote a rst level plot function that evaluates the x and y data an
219. in Normal Mode followed by the address of the routine to be performed when in Insert Mode when that key is pressed Then comes the second key followed by the next pair of addresses and so on In the third screen the word FUNCTION takes a key value searches through the FUNCTIONS table for a match then returns the address of the cell containing the match We preset the variable MATCHED to point to the last row of the table the functions we want when any character is pressed The word ACTION invokes FUNCTION then adds the contents of the vari able MODE Since MODE will contain either a 2 or a 4 by adding this o set we re now pointing into the table at the address of the routine we want to perform A simple EXECUTE will perform the routine or EXECUTE EXECUTE EXECUTE EXECUTE EXECUTE if you have it In g Forth change the de nition of IS to IS COMPILE CFA In 79 Standard Forths use IS COMPILE We ve also used non redundancy at compile time in the de nition just below the function table HERE KEY CONSTANT NOMATCH adr of no match key We re making a constant out of the last row in the function table At the moment we invoke HERE HERE HERE HERE HERE it s pointing to the next free cell after the last table entry has been lled in Six bytes back is the last row We now have two words FUNCTIONS adr of beginning of function table NOMATCH
220. in one de ni tion with an IF ELSE THEN structure The ag that indicates whether Forth Using the Dictionary 233 is compiling or interpreting is called STATE Since the depends on STATE it is said to be STATE dependent literally The command appeared to behave the same inside and outside a colon de nition This duplicity proved useful in afternoon introductions to Forth but the serious student soon learned there s more to it than that Suppose a student wants to write a new word called B B B B B for bright dot quote to display a string in bright characters on her display to be used like this INSERT DISK IN B LEFT DRIVE She might expect to de ne B as B BRIGHT NORMAL that is change the video mode to bright print the string then reset the mode to normal She tries it Immediately the illusion is destroyed the deception is re vealed the de nition won t work To solve her problem the programmer will have to study the de nition of in her own system I m not going to get sidetracked here with explaining how works my point is that smartness isn t all it appears to be Incidentally there s a di erent syntactical approach to our student s prob lem one that does not require having two separate words and B to print strings Change the system s so that it always sets the mode to normal after typing even though it will already
221. inators 239 240 Coupling 15 Cross compilers 34 Customer constraints 46 D Data abstraction 18 Data coupling 15 Data handling see Data stacks Data structures Data passing implicit 19 25 Data stacks 19 32 concept of 198 199 vs data structures 201 203 de ned 267 depth of 199 201 drawings 204 206 local variables and 201 203 PICK and ROLL 203 204 return 206 213 saving and restoring states 210 212 Data structures see also Vari ables vs calculation vs logic 120 122 vs data stacks 201 203 de ned 120 de ning 59 60 hiding construction of 25 27 operators 266 267 Data factoring out 172 173 Data ow diagrams 49 51 Data structure comment 150 155 Dates representation of 146 DECIMAL 148 149 Decision table 55 59 243 249 Decision tree 54 55 Decomposition 138 by component 72 88 290 INDEX by sequential complexity 88 90 De ning words comments for 158 compile time factoring through 190 length 178 180 procedure 266 De nitions consume arguments syn tax rule 114 Design see Detailed design Pre liminary design Dessy Raymond E 263 Detailed design 100 133 algorithms 119 120 calculations 120 122 data structures 120 122 demonstration of 122 133 Forth syntax 110 119 logic 120 122 problem solving techniques 100 107 steps in 110 Development cycle see Program
222. increased reliance on expressing calculations Now we re getting somewhere Let s go back to our de nition of PER MINUTE CHARGE PER MINUTE CHARGE per minute charge CONNECT CHARGE MILEAGE CHARGE Let s get more speci c about the rules for the connection charge and for the mileage charge The connection charge depends on whether the minute is the rst or an additional minute Since there are two kinds of per minute charges perhaps it will be easiest to rewrite PER MINUTE CHARGE as two di erent words 58 Analysis Let s assume we will build a component that will fetch the appropriate rates from the table The word 1MINUTE will get the rate for the rst minute MINUTES will get the rate for each additional minute Both of these words will depend on the time of day to determine whether to use the full lower or lowest rates Now we can de ne the pair of words to replace PER MINUTE CHARGE FIRST charge 1MINUTE ASSISTANCE MILEAGE CHARGE PER ADDITIONAL charge MINUTES MILEAGE CHARGE What is the rule for the mileage charge Very simple It is the rate per hundred miles times the number of miles in hundreds Let s assume we can de ne the word MILEAGE RATE which will fetch the mileage rate from the table MILEAGE CHARGE charge MILES MILEAGE RATE Finally if we know the total number of minutes for a call we can now calculate the total direct dial charg
223. ing an abort Finally when you encounter this situation of having to save restore a value make sure it s not just a case of bad factoring For example suppose we have written LONG 18 HOLES SHORT 9 HOLES GAME HOLES O DO I HOLE PLAY LOOP The current GAME is either LONG or SHORT Later we decide we need a word to play any number of holes So we invoke GAME making sure not to clobber the current value of HOLES HOLES n HOLES SWAP HOLES GAME HOLES Because we needed HOLES after we d de ned GAME it seemed to be of greater complexity we built HOLES around GAME But in fact perhaps you see it already rethinking is in order HOLES n O DO I HOLE PLAY LOOP GAME HOLES HOLES We can build GAME around HOLES and avoid all this saving restoring nonsense 212 Handling Data Stacks and States Application Stacks In the last section we examined some ways to save and restore a single previous value Some applications require several values to be saved and restored You may often nd the best solution to this problem in de ning your own stack Here is the code for a user stack including very simple error checking an error clears the stack CREATE STACK 12 ALLOT 2tos pointer 10stack 5 cells HERE CONSTANT STACK gt INIT STACK STACK STACK INIT STACK BAD IF STACK ERROR INIT STACK ABORT THEN PUSH n 2 STACK STACK
224. inking behind the checksum algorithm used Who knows from the narrative comments To properly describe in prose the implications of a given procedure usu ally requires many paragraphs not a single phrase Such descriptions properly belong in auxiliary documentation or in the chapter preamble Despite these cautions many companies nd the vertical format neces sary Certainly a team that is newly exposed to Forth should adopt it as should any very large team What about the horizontal format Perhaps it s an issue of art vs prac ticality but I feel compelled to defend the horizontal format as equally valid and in some ways superior If Forth code is really well written there should be nothing ambiguous about it This means that supporting lexicons have a well designed syntax stack inputs and outputs are commented the purpose is commented if it s not clear from the name or stack com ment de nitions are not too long not too many arguments are passed to a single de nition via the stack see The Stylish Stack in Chapter Seven Forth is simply not like other languages in which line by line commenting is one of the few things you can do to make programs more readable Skillfully written Forth code is like poetry containing precise meaning that both programmer and machine can easily read Your goal should be to write code that does not need commenting even if you choose to comment it Design your ap
225. ip screen function De nitions for and S S S S S can be found in Appendix C Chapter load Screens Figure 5 2 illustrates a typical chapter load screen The screens loaded by this screen are referred to relatively not absolutely as they were in the application load screen This is because the chapter load screen is the rst screen of the contiguous range of screens in the chapter You can move an entire chapter forward or backward within the listing the relative pointers in the chapter load screen are position independent All you have to change is the single number in the application load screen that points to the beginning of the chapter 5 2 Tip Use absolute screen numbers in the application load screen Use relative screen numbers in the chapter or section load screens 140 Implementation Elements of Forth Style Figure 5 2 Example of a chapter load screen Screen 100 0 GRAPHICS Chapter load 07 11 83 1 2 1 FH LOAD dot drawing primitive 3 2 FH 3 FH THRU line drawing primitives 4 4 FH 7 FH THRU scaling rotation 5 8 FH LOAD box 6 9 FH 11 FH THRU circle 7 8 9 10 CORNER initialize relative position to low left corner 11 12 13 14 15 There are two ways to implement relative loading The most common is to de ne LOAD offset BLK LOAD and THRU lo offset hi offset 1 SWAP DO I LOAD LOOP My own w
226. is makes it easier to type move or do practically anything with the string With the address and count on the stack the de nition of TYPE TYPE TYPE TYPE TYPE can be coded TYPE a OVER SWAP DO I C EMIT LOOP Although TYPE TYPE TYPE TYPE TYPE really ought to be written in machine code This de nition uses no overt conditional LOOP LOOP LOOP LOOP LOOP actually hides the con ditional since each loop checks the index and returns to DO DO DO DO DO if it has not yet reached the limit If a delimiter were used let s say ASCII null zero the de nition would have to be written TYPE a BEGIN DUP C DUP WHILE EMIT 1 REPEAT DROP An extra test is needed on each pass of the loop WHILE WHILE WHILE WHILE WHILE is a conditional operator Optimization note The use of DUP DUP DUP DUP DUP in this solution is expensive in terms of time because it contains an extra decision itself A faster de nition would be TYPE a BEGIN DUP C DUP WHILE EMIT 1 REPEAT 2DROP The 83 Standard applied this principle to INTERPRET INTERPRET INTERPRET INTERPRET INTERPRET which now accepts a count rather than looking for a terminator The ip side of this coin is certain data structures in which it s easiest to link the structures together Each record points to the next or previous record The last or rst record in the chain can be indicated with a zero in its link eld
227. ision table not only reads well to the client but actually bene ts the imple mentor in several ways Transferability to actual code This is particularly true in Forth where decision tables are easy to implement in a form very similar to the draw ing Ability to trace the logic upwards Find a condition and see what factors produced it Clearer graphic representation Decision tables serve as a better tool for understanding both for the implementor and the analyst Unlike decision trees these decision tables group the results together in a graphically meaningful way Visualization of ideas helps in understanding problems particularly those problems that are too complex to perceive in a linear way For instance Figure 2 5 clearly shows that the charge for additional min utes does not depend on whether an operator assisted or not With this new understanding we can draw a simpli ed table as shown in Figure 2 6 It s easy to get so enamored of one s analytic tools that one forgets about the problem The analyst must do more than carry out all possibilities of a problem to the nth degree as I have seen authors of books on structured analysis recommend That approach only increases the amount of available detail The problem solver must also try to simplify the problem 56 Analysis Figure 2 6 A simpli ed decision table Tip You don t understand a problem until you can simplify it 2 10 If the goal of analysis is
228. iting some test code and trying things out Finding out about the customer s constraints is usually a matter of asking the customer or of taking written surveys How fast do you need such and such on a scale of one to ten etc Building a Conceptual Model of the Solution A conceptual model is an imaginary solution to the problem It is a view of how the system appears to work It is an answer to all the requirements and constraints If the requirements de nition is for something to stand on to paint the ceiling then a description of the conceptual model is a device that is free standing so you can paint the center of the room with several steps spaced at convenient intervals so you can climb up and down and having a small shelf near the top to hold your paint can 46 Analysis Re ning the conceptual model to meet requirements and constraints A conceptual model is not quite a design however A design begins to describe how the system really works In design the image of a step ladder would begin to emerge Forth blurs the distinction a little because all de nitions are written in conceptual terms using the lexicons of lower level components In fact later in this chapter we ll use Forth pseudocode to describe conceptual model solutions Nevertheless it s useful to make the distinction A conceptual model is more exible than a design It s easier to t the requirements and constrai
229. its memory mapped video that refreshes an entire line in the blink of a scan cycle But now our customer wants the application to run on a telephone based network with all I O being done at a not so fast baud rate Since some of our input elds are almost as wide as the 78 Preliminary Design Decomposition video screen maybe 65 characters it just takes too long to refresh the entire line on every key stroke We ve got to change the application so that we only refresh that part of the eld that actually changes In insert and delete this would mean the text to the right of the cursor In overwrite it would mean changing just the single character being overwritten This change is signi cant The video refresh function which we cavalierly relegated to the key interpreter now must depend on which editing functions occur As we ve discovered the most important names needed to implement the key interpreter are FORWARD BACKWARD OVERWRITE INSERT DELETE lt INSERT None of their descriptions make any reference to the video refresh process because that was originally assumed to happen later But things aren t as bad as they seem Looking at it now the process OVERWRITE could easily include a command to type the new character where the terminal s cursor is And SLIDE lt and SLIDE gt could include commands to type everything to the right of and including POSITION then reset the terminal s cursor to its cur
230. ity is de ned before the root function that approach is bad news for two reasons First the natural organization by degree of capability is destroyed Sec ond the advanced routines often use code that is de ned amid the elementary capabilities If you move the advanced routines to the front of the application you ll also have to move any routines they use or duplicate the code Very messy You can organize the listing by degree of complexity using a technique called vectoring You can allow the root function to invoke point to any of various routines that have been de ned after the root function itself In our example only the name of the routine HOLDOVER need be created early its de nition can be given later Chapter Seven treats the subject of vectoring in Forth The Limits of Level Thinking Most of us are guilty of over emphasizing the di erence between high level and low level This notion is an arbitrary one It limits our ability to think clearly about software problems Level thinking in the traditional sense distorts our e orts in three ways 1 It implies that the order of development should follow a hierarchical struc ture 2 It implies that levels should be segregated from each other prohibiting the bene ts of reusability 3 It fosters syntactical di erences between levels e g assembler vs high level languages and a belief that the nature of programming somehow
231. ive numbering 114 115 INDEX 295
232. ized book is easy to read A badly organized book makes comprehen sion more di cult and makes nding information later on nearly impossible The necessity for good organization applies to an application listing as well Good organization has three aspects 1 Decomposition 136 Implementation Elements of Forth Style I still don t see how these programming conventions enhance readability 2 Composition 3 Disk partitioning Decomposition As we ve already seen the organization of a listing should follow the decom position of the application into lexicons Generally these lexicons should be sequenced in uses order Lexicons being used should precede the lexicons which use them On a larger scale elements in a listing should be organized by degree of complexity with the most complex variations appearing towards the end It s best to arrange things so that you can leave o the lattermost screens i e not load them and still have a self su cient running application working properly except for the lack of the more advanced features We discussed the art of decomposition extensively in Chapter Three Composition Composition is the putting together of pieces to create a whole Good compo sition requires as much artistry as good decomposition One of Forth s present conventions is that source code resides in screens which are 1K units of mass storage The term screen refers to a block used speci
233. ke DROP DROP DROP DROP DROP when we ve nished de ning all the ports to get rid of the port address that s still on the stack One nal comment The base port address is very likely to change and therefor should be de ned in only one place This does not mean it has to be de ned as a constant Provided that the base port address won t be used outside of this lexicon of port names it s just as well to refer to it by number here HEX 01A0 base port adr PORT SPEAKER PORT FLIPPER A PORT FLIPPER B PORT WIN LIGHT DROP The Iterative Approach in Implementation Earlier in the book we discussed the iterative approach paying particular at tention to its impact on the design phase Now that we re talking about im plementation let s see how the approach is actually used in writing code 6 19 Tip Work on only one aspect of a problem at a time Suppose we re entrusted with the job of coding a word to draw or erase a box at a given x y coordinate This is the same problem we introduced in the section called Compile Time Factoring At rst we focus our attention on the problem of drawing a box never mind erasing it We might come up with this LAYER WIDE 0 DO ASCII EMIT LOOP BOX upper left x upper left y HIGH 0 DO 2DUP I XY LAYER LOOP 2DROP Having tested this to make sure it works correctly we turn now to the problem of using the same code to undraw a box The sol
234. l minute 20 12 100miles ENDIF ELSE operator Structured English 53 IF first minute 1 20 12 100miles ELSE add l minute 20 12 100miles ENDIF ENDIF ELSE not full rate IF lower rate IF direct dial IF first minute 22 10 100miles ELSE add l minute 15 10 100miles END IF ELSE operator IF first minute 1 12 10 100miles ELSE add l minute 15 10 100miles ENDIF ENDIF ELSE lowest rate IF direct dial IF first minute 12 06 100miles ELSE add l minute 09 O6 100miles ENDIF ELSE operator IF first minute 1 02 O6 100miles ELSE add l minute 09 06 100miles ENDIF ENDIF ENDIF ENDIF This is just plain awkward It s hard to read harder to maintain and hardest to write And for all that it s worthless at implementation time I don t even want to talk about it anymore The Decision Tree Figure 2 4 illustrates the telephone rate rules by means of a decision tree The decision tree is the easiest method of any to follow down to determine the 54 Analysis Figure 2 4 Example of a decision tree result of certain conditions For this reason it may be the best representation to show the customer Unfortunately the decision tree is di cult to follow up to determine which conditions produce certain results This di culty inhibits seeing ways to simplify the problem The tree obscures the fact that additional minutes cost the sa
235. l changes this list would change This technique is very important in writing software Why would a pro gram ever need to change once it s running For any of a million reasons You might want to run an old program on new equipment the program must be changed just enough to accommodate the new hardware The program might not be fast enough or powerful enough to suit the people who are using it Most software groups nd themselves writing families of programs that is many versions of related programs in their particular application eld each a variant on an earlier program To apply the principle of information hiding to software certain details of the program should be con ned to a single location and any useful piece of information should be expressed only once Programs that ignore this maxim are guilty of redundancy While hardware redundancy backup computers etc can make a system more secure redundancy of information is dangerous As any knowledgeable programmer will tell you a number that a program uses and that might conceivably change should be made into a constant and referred to throughout the program by name not by value For instance the number of columns representing the width of your computer paper forms should be expressed as a constant Even assembly languages provide EQU s and labels for associating values such as addresses and bit patterns with names Any good programmer will also apply the conc
236. l out of it We know how to do it but we can t yet state the procedure as an algorithm So let s look at the rst ten Roman numerals 122 Detailed Design Problem Solving I II III IV V VI VII VIII IX X We make a few observations First there s the idea of a tally where we rep resent a number by making that many marks 3 III On the other hand special symbols are used to represent groups 5 V In fact it seems we can t have more than three I s in a row before we use a larger symbol Second there s a symmetry around ve There s a symbol for ve V and a symbol for ten X The pattern I II III repeats in the second half but with a preceding V One less than ve is written IV and one less than ten is written IX It seems that putting an I in front of a larger value symbol is like saying one less than These are vague hazy observations But that s alright We don t have the whole picture yet Let s study what happens above ten XI XII XIII XIV XV XVI XVII XVIII XIX XX This is exactly the pattern as before with an extra X in front So there s a repeating cycle of ten as well If we look at the twenties they re the same with two X s the thirties with three X s In fact the number of X is the same as the number in the tens column of the original decimal number This seems like an important observation we can decompose our decimal
237. ld ac cess the communication chip by simply invoking the OUT instruction to put an appropriate command byte into the command register This makes the entire application needlessly dependent on that particular chip very risky Instead Forth programmers would write a component to control the I O chip These commands would have logical names and a convenient interface usually Forth s stack to allow usage by the rest of the application For any iteration of your product s design you would implement only the commands needed so far not all the valid codes that could be sent to the control register If later in the project cycle you realize that you need an additional command say one to change the baud rate the new command would be added to the I O chip lexicon not to the code that needed to set the baud rate There s no penalty for making this change except the few minutes at most it takes to edit and recompile 3 3 Tip Within each component implement only the commands needed for the current iteration But don t preclude future additions What goes on inside a component is pretty much its own business It s not necessarily bad style for de nitions within the component to share redundant information For instance a record in a certain data structure is fourteen bytes long One de nition in the component advances a pointer 14 bytes to point to the next record another de nition decrements the pointer 14 bytes As
238. lem of course is that no one card may appear twice in the array You may assume you have a random number generator called CHOOSE It s stack argument is n it produces a random number between zero and n 1 inclusive See the Handy Hint Chapter Ten Starting Forth Summary 133 Figure 4 9 Roman numerals solved Screen 20 0 Roman numerals 8 18 83 1 CREATE ROMANS ones ASCII I C ASCII V C 2 tens ASCII X C ASCII L C 3 hundreds ASCII C C ASCII D C 4 thousands ASCII M C 5 VARIABLE COLUMN current offset 6 ONES O COLUMN 7 TENS 2 COLUMN 8 HUNDREDS 4 COLUMN 9 THOUSANDS 6 COLUMN 10 11 COLUMN address of column ROMANS COLUMN 12 Screen 21 0 Roman numerals cont d 8 18 83 1 SYMBOL offset COLUMN C EMIT 2 ONER O SYMBOL 3 FIVER 1 SYMBOL 4 TENER 2 SYMBOL 5 6 ONERS of oners 7 DUP IF O DO ONER LOOP THEN 8 ALMOST quotient of 5 9 ONER IF TENER ELSE FIVER THEN 10 DIGIT digit 11 5 MOD OVER 4 IF ALMOST DROP ELSE IF FIVER THEN 12 ONERS THEN 13 Screen 22 0 Roman numerals cont d 8 18 83 1 ROMAN number 1000 MOD THOUSANDS DIGIT 2 100 MOD HUNDREDS DIGIT 3 10 MOD TENS DIGIT 4 ONES DIGIT 5 Can you design the card shu ing algorithm so that it avoi
239. limited text sequence of characters delimited by non blank Follow text with the actual delimiter required e g text or text Samples of Good Commenting Style Here are two sample screens to illustrate good commenting style Screen 126 0 Formatter Data Structures p 2 06 06 83 1 6 CONSTANT TMARGIN line where body of text begins 2 55 CONSTANT BMARGIN line where body of text ends 3 4 CREATE HEADER 82 ALLOT 5 1left ent 1right cnt 80header 6 CREATE FOOTER 82 ALLOT 7 1left cnt 1right ent 80footer 8 9 VARIABLE ACROSS formatter s current horizontal position 10 VARIABLE DOWNWARD formatter s current vertical position 11 VARIABLE LEFT current primary left margin 12 VARIABLE WALL current primary right margin 13 VARIABLE WALL WAS WALL when curr line started being formt d 14 Input Stream Comment Designations 285 Screen 127 0 Formatter positioning p 1 06 06 83 1 SKIP n ACROSS 2 NEWLEFT reset left margin 3 LEFT PERMANENT TEMPORARY ACROSS 4 LINE begin new line 5 DOOR CR 1 DOWNWARD NEWLEFT WALL WALL WAS 6 AT TOP t at top TMARGIN DOWNWARD 7 gt TMARGIN move from crease to TMARGIN 8 O DOWNWARD BEGIN LINE AT TOP UNTIL 9 Naming Conventions Meaning Form Example Arithmetic integer 1 1name 1 integer 2 2name 2 takes relative inpu
240. ll It is therefore preferable unless we need an additional word called DONE as a ag for instance A nal tip on naming 5 24 Tip Begin all hex numbers with 0 zero to avoid potential collisions with names For example write 0ADD not ADD By the way don t expect your Forth system to necessarily conform to the above conventions The conventions are meant to be used in new applications Forth was created and re ned over many years by people who used it as a means to an end At that time it was neither reasonable nor possible to impose naming standards on a tool that was still growing and evolving Had Forth been designed by committee we would not love it so 168 Implementation Elements of Forth Style More Tips for Readability Here are some nal suggestions to make your code more readable De nitions appear in Appendix C One constant that pays for itself in most applications is BL the ASCII value for blank space The word ASCII ASCII ASCII ASCII ASCII is used primarily within colon de nitions to free you from having to know the literal value of an ASCII character For instance instead of writing 41 WORD DROP IMMEDIATE where 41 is the ASCII representation for right parenthesis you can write ASCII WORD DROP IMMEDIATE A pair of words that can make dealing with booleans more readable are TRUE TRUE TRUE TRUE TRUE and FALSE FALSE FALSE FALSE FALSE With thes
241. ll amplify on these ideas in the next chapter on Factoring Naming Standards The Science Tip Learn and adopt Forth s naming conventions 5 22 In the quest for short yet meaningful names Forth programmers have adopted certain naming conventions Appendix E includes a list of the most useful conventions developed over the years Naming Standards The Science 167 An example of the power of naming conventions is the use of dot to mean print or display Forth itself uses D U R for displaying various types of numbers in various formats The convention extends to application words as well If you have a variable called DATE and you want a word that displays the date use the name DATE A caution The overuse of pre xes and su xes makes words uglier and ulti mately less readable Don t try to describe everything a word does by its name alone After all a name is a symbol not a shorthand for code Which is more readable and natural sounding Oedipus complex which bears no intrinsic meaning or subconscious attachment to parent of opposite sex complex Probably the former even though it assumes you know the play 5 23 Tip Use pre xes and su ces to di erentiate between like words rather than to cram details of meaning into the name itself For instance the phrase DONE IF CLOSE THEN is just as readable as DONE IF CLOSE THEN and cleaner as we
242. ll the requirements are satis ed Usually this means adding new commands or adding special case handling to existing screens Not always though A new iteration may see a simpli cation of the code Or a new complexity may really belong in another component and should be factored out into another screen Leaving plenty of room at the outset makes later additions more pleasant One writer recommends that on the initial pass the screen should contain about 20 40 percent code and 80 60 percent whitespace 1 Don t skip a line between each de nition You may however skip a line between groups of de nitions 5 7 Tip All screens must leave BASE BASE BASE BASE BASE set to DECIMAL DECIMAL DECIMAL DECIMAL DECIMAL Even if you have three screens in a row in which the code is written in HEX HEX HEX HEX HEX three screens of assembler code for instance each screen must set BASE to HEX HEX HEX HEX HEX at the top and restore base to DECIMAL DECIMAL DECIMAL DECIMAL DECIMAL at the bottom This rule ensures that each screen could be loaded separately for purposes of testing without mucking up the state of a airs Also in reading the listing you know that values are in decimal unless the screen explicitly says HEX HEX HEX HEX HEX Some shops take this rule even further Rather than brashly resetting base to DECIMAL DECIMAL DECIMAL DECIMAL DECIMAL at the end they reset base to whatever it was at the beginni
243. mber of compiling words you can add at any time simply by making them immediate Thus even Forth s colon compiler is extensible Forth s text interpreter and Forth s address interpreter also adhere to this same rule The following tip is perhaps the most important in this chapter 4 22 Tip Don t write your own interpreter compiler when you can use Forth s One class of applications answers a need for a special purpose language a self contained set of commands for doing one particular thing An example is a machine code assembler Here you have a large group of commands the mnemonics with which you can describe the instructions you want assembled Here again Forth takes a radical departure from mainstream philosophy Traditional assemblers are special purpose interpreters that is they are complicated programs that scan the assembly language listing looking for rec ognized mnemonics such as ADD SUB JMP etc and assemble machine instruc tions correspondingly The Forth assembler however is merely a lexicon of Forth words that themselves assemble machine instructions There are many more examples of the special purpose language each speci c to individual applications For instance 1 If you re building an Adventure type game you d want to write a lan guage that lets you create and describe monsters and rooms etc You might create a de ning word called ROOM to be used like this ROOM DUNGEON Then create
244. me whether the operator assists or not You can t see the facts for the tree The Decision Table The decision table described next provides the most usable graphic represen tation of compound rules for the programmer and possibly for the customer as well Figure 2 5 shows our rate structure rules in decision table form In Figure 2 5 there are three dimensions the rate discount whether an operator intervenes and initial minute vs additional minute Drawing problems with more than two dimensions gets a little tricky As you can see these additional dimensions can be depicted on paper as sub dimensions within an outer dimension All of the subdimension s conditions appear within every condition of the outer dimension In software any number of dimensions can be easily handled as we ll see All the techniques we ve described force you to analyze which conditions apply to which dimensions In factoring these dimensions two rules apply The Decision Table 55 Figure 2 5 The decision table First all the elements of each dimension must be mutually exclusive You don t put rst minute in the same dimension as direct dial because they are not mutually exclusive Second all possibilities must be accounted for within each dimension If there were another rate for calls made between 2 A M to 2 05 A M the table would have to be enlarged But our decision tables have other advantages all to themselves The dec
245. mensional data table is the superstring Start ing Forth Chapter Ten Two Dimensional Data Table In Chapter Two we presented a phone rate problem Figure 8 4 gives one solution to the problem using a two dimensional data structure In this problem each dimension of the data table consists of three mu tually exclusive states Therefore a simple boolean true false is inadequate Each dimension of this problem is implemented in a di erent way The current rate which depends on the time of day is stored as an address representing one of the three rate structure sub tables We can say FULL RATE or LOWER RATE etc 244 Minimizing Control Structures Figure 8 4 A solution to the phone rate problem Screen 103 0 Telephone rates 03 30 84 1 CREATE FULL 30 20 12 2 CREATE LOWER 22 15 10 3 CREATE LOWEST 12 9 6 4 VARIABLE RATE points to FULL LOWER or LOWEST 5 depending on time of day 6 FULL RATE for instance 7 CHARGE o CREATE 8 DOES gt rate RATE 9 O CHARGE 1MINUTE rate for first minute 10 2 CHARGE MINUTES rate for each additional minute 11 4 CHARGE MILES rate per each 100 miles Screen 104 0 Telephone rates 03 30 84 1 VARIABLE OPERATOR 90 if operator assisted else O 2 VARIABLE MILES hundreds of miles 3 ASSISTANCE direct dial charge total charge 4 OPERATOR 5 M
246. mentation and process control applications Dave has been using Forth since 1978 He describes his approach Compared with many others that use Forth I suppose we take a more formal approach I learned this the hard way though My lack of discipline in the early years has come back to haunt me We use two tools to come up with new products a functional speci cation and a design speci cation Our department of Sales amp Applications comes up with the functional speci cation through customer contact Once we ve agreed on what we re going to do the functional speci cation is turned over to our department At that point we work through a design and come up with the design speci cation 40 Analysis Up to this point our approach is no di erent from programming in any language But with Forth we go about designing somewhat di erently With Forth you don t have to work 95 through your design before you can start coding but rather 60 before you can get into the iterative process A typical project would be to add a functional enhancement to one of our products For example we have an intelligent terminal with disk drives and we need certain protocols for communicating with another device The project to design the protocols come up with displays provide the operator interfaces etc may take several months The functional speci cation takes a month the design speci cation takes a month coding takes three mont
247. mers also apply these same phases toward de ning each word The cycle then repeats on the order of minutes Developing an application with this rapid repetition of the programming cycle is known as using the Iterative Approach The Iterative Approach The iterative approach was explained eloquently by Kim Harris 1 He begins by describing the scienti c method a never ending cycle of discovery and re nement It rst studies a natural system and gathers observations about its behavior Then the observations are modeled to produce a theory about the natural system Next analysis tools are applied to the model which produces predictions about the real system s behavior Experiments are devised to compare actual behavior to the predicted behavior The natural system is again studied and the model is revised The goal of the method is to produce a model which accurately predicts all observable behavior of the natural system Harris then applies the scienti c method to the software development cycle illustrated in Figure 2 1 1 A problem is analyzed to determine what functions are required in the solution 2 Decisions are made about how to achieve those functions with the avail able resources 3 A program is written which attempts to implement the design Figure 2 1 The iterative approach to the software development cycle from The Forth Philosophy by Kim Harris Dr Dobb s Journal The Iterative
248. ming Cycle Dicing 21 Dictionary control structure minimization with 232 234 de ned 266 267 Disk partitioning 144 DO LOOP 188 190 238 DOER MAKE 219 226 270 274 Dumb words 233 234 E Electives 145 146 ELSE 268 EMIT 174 175 Encryption 164 Engineering see Detailed design Preliminary design Error handling 50 Error code 205 206 EXIT 140 253 272 Expectations in input stream syn tax rule 115 116 Expecting 156 Expressive words 163 F Factoring 172 195 compile time 188 192 criteria 178 188 de ned 172 iterative approach 192 195 techniques 172 177 FALSE 169 277 FH 276 277 File based system 144 Flags 155 174 268 Flow charts 5 Forth 19 35 advantages of 29 32 capability of 32 component programming 20 23 data handling see Data stacks Data structures as design language 31 e ect on thinking 262 263 high level language issue 27 31 implicit calls 19 implicit data passing 19 20 information hiding 16 18 24 182 184 lexicon 22 23 overview of 266 268 performance of 32 34 programming cycle see Program ming cycle size of 34 speed of 32 style see Implementation syntax 110 119 FORTRAN 3 5 Functional strength 14 15 INDEX 291 Functions factoring out 174 177 vectored execution 219 220 Fun down approach 91 G Global variables 210 GO TO commands 5 6 H Ham M
249. mposition see Preliminary design value of planning 40 42 Prototyping 31 Pseudocode 51 52 Purpose comment 151 156 157 Q Quantization 63 R Redesigning to minimize control structures 249 252 Relative loading 140 143 Requirements 46 Return stack 206 211 Rockwell R65F11 Forth based mi croprocessor 34 ROLL 203 204 Roman numeral computation prob lem 122 133 Rule de nition 52 59 101 S Sanderson Dean 238 239 Scanning for 156 INDEX 293 Scheduling 66 68 Screens 23 layout 146 150 load see Load screens numbering 145 Sequential binding 15 Sequential complexity decompo sition by 88 90 Sharing components 213 215 Simplicity 60 65 258 259 Skip commands 140 276 Software development cycle see Programming cycle Software elegance history of 2 18 abstraction 3 5 manageability 5 mnemonics 2 3 power 3 structured programming see Struc tured programming Source precede destination syntax rule 115 Spacing 149 150 284 Spaghetti programs 5 Speed 32 Spelled out names 165 166 Stack abbreviation standards 153 284 285 Stack e ect 152 Stack notation 151 Stack picture 151 152 Stack e ect comment 150 152 154 Stacks see Data stacks Stamp 146 Starling Michael 43 44 STATE 234 State table 215 219 Stolowitz Michael 119 String input receiving 156 Structure super ciality of 18 Struc
250. ms an obvious action is a verb Words such as RED and GREEN in our example can only be called adjec tives since they modify the function of APPLES The phrase RED APPLES is di erent from GREEN APPLES Forth words can also serve as adverbs and prepositions There s little value in trying to determine what part of speech a particular word is since Forth doesn t care anyway We need only enjoy the ease of describing an application in natural terms But Is It a High Level Language In our brief technical overview we noted that traditional high level languages broke away from assembly language by eliminating not only the one for one correspondence between commands and machine operations but also the linear correspondence Clearly Forth lays claim to the rst di erence but regarding the second the order of words that you use in a de nition is the order in which those commands are compiled Does this disqualify Forth from the ranks of high level languages Before we answer let s explore the advantages of the Forth approach Here s what Charles Moore the inventor of Forth has to say You de ne each word so that the computer knows what it means The way it knows is that it executes some code as a consequence of being invoked The computer takes an action on every word It doesn t store the word away and keep it in mind for later In a philosophical sense I think this means that the computer under
251. n nes the cursor to certain elds possibly using reverse video to let the user see the size of the allowable eld Another example occurs when an application prompts the user for a nu meric value You often see such applications that don t check input until you press return at which time the system responds with an error message such as invalid number It s just as easy probably easier to check each key as it s typed and simply not allow non numeric characters to appear Tip To simplify take advantage of what s available 2 16 Michael LaManna a Forth programmer in Long Island New York com ments I always try to design the application on the most powerful processor I can get my hands on If I have a choice between doing development on a 68000 based system and a 6809 based system I d go for the 68000 based system The processor itself is so powerful it takes care of a lot of details I might otherwise have to solve myself If I have to go back later and rewrite parts of the application for a simpler processor that s okay At least I won t have wasted my time A word of caution If you re using an existing component to simplify your prototype don t let the component a ect your design You don t want the design to depend on the internals of the component Achieving Simplicity 65 Budgeting and Scheduling Another important aspect of the analysis phase is guring the price tag Again
252. n 78 Designing and Maintaining a Traditional Application 80 The Interface Component 85 Decomposition by Sequential Complexity 88 The Limits of Level Thinking 90 Summary 95 For Further Thinking 95 Detailed Design Problem Solving 99 Problem Solving Techniques 100 Interview with a Software Inventor 107 Detailed Design 110 Forth Syntax 110 Algorithms and Data Structures 119 Calculations vs Data Structures vs Logic 120 Solving a Problem Computing Roman Numerals 122 Summary 133 References 133 For Further Thinking 133 Implementation Elements of Forth Style 135 Listing Organization 136 An Alternative to Screens Source in Named Files 144 Screen Layout 146 Comment Conventions 150 Vertical Format vs Horizontal Format 159 Choosing Names The Art 163 Naming Standards The Science 167 More Tips for Readability 169 Summary 170 References 170 Factoring 171 Factoring Techniques 172 Factoring Criteria 178 Compile Time Factoring 188 The Iterative Approach in Implementation 192 viii Contents References 195 Handling Data Stacks and States 197 The Stylish Stack 198 The Stylish Return Stack 206 The Problem With Variables 207 Local and Global Variables Initialization 210 Saving and Restoring a State 210 Application Stacks 213 Sharing Components 213 The State Table 215 Vectored Execution 219 Using DOER MAKE 220 S
253. n one so intelligent as yourself Apparently the human mind actually makes links between memories New ideas are somehow added onto existing paths of related thoughts Figure 3 1 Pools of thought not yet linked 72 Preliminary Design Decomposition In the mishap just described no connection was ever made between the two separately linked pools of thought until Thursday The con ict probably occurred when some new input something as trivial as hearing Saturday s weather report got linked into both pools of thought A lightning ash of realization arced between the pools followed inexorably by thunderous panic A simple tool has been invented to avoid such disasters It s called a calendar If you had recorded both plans in the same calendar you would have seen the other event scheduled something your brain failed to do for all its intricate magni cence Tip To see the relationship between two things put them close together To remind yourself of the relationship keep them together 3 1 These truisms apply to software design particularly to the preliminary design phase This phase is traditionally the one in which the designer dissects a large application into smaller programmer sized modules In Chapter One we discovered that applications can be conveniently de composed into components Tip The goal of preliminary design is to determine what components are necessary to accomplish the requirements 3 2 For i
254. nce sometimes is a function Witness Segment 1 BLETCH A BLETCH B BLETCH C BLETCH C BLETCH C BLETCH C BLETCH C BLETCH D BLETCH E BLETCH F Segment 2 BLETCH A BLETCH B PERVERSITY PERVERSITY PERVERSITY PERVERSITY PERVERSITY BLETCH D BLETCH E BLETCH F Wrong approach BLETCHES t do BLETCH C f do PERVERSITY BLETCH A BLETCH B IF BLETCH C BLETCH C BLETCH C BLETCH C BLETCH C ELSE PERVERSITY PERVERSITY PERVERSITY PERVERSITY PERVERSITY THEN BLETCH D BLETCH E BLETCH F Segment 1 TRUE BLETCHES Segment 2 FALSE BLETCHES A better approach BLETCH AB BLETCH A BLETCH B BLETCH DEF BLETCH D BLETCH E BLETCH F Segment 1 BLETCH AB BLETCH C BLETCH C BLETCH C BLETCH C BLETCH C BLETCH DEF Segment 2 BLETCH AB PERVERSITY PERVERSITY PERVERSITY PERVERSITY PERVERSITY BLETCH DEF 6 2 Tip Don t pass control ags downward Why not First you are asking your running application to make a pointless decision one you knew the answer to while programming thereby reducing ef ciency Second the terminology doesn t match the conceptual model What are TRUE BLETCHES as opposed to FALSE BLETCHES Factoring Out Code from Within Control Structures Be alert to repetitions on either side of an IF IF IF IF IF ELSE ELSE ELSE ELSE ELSE THEN THEN THEN THEN THEN statement For in stance c DUP BL 127 WITHIN IF EMIT ELSE DROP ASCII EMIT THEN This fr
255. ng This extra bit of insurance can be accomplished in this fashion BASE HEX save original BASE on stack 0A2 CONSTANT BELLS 0A4 CONSTANT WHISTLES etc BASE restore it Sometimes an argument is passed on the stack from screen to screen such as the value returned by BEGIN BEGIN BEGIN BEGIN BEGIN or IF IF IF IF IF in a multiscreen assembler de nition or the base address passed from one de ning word to another see Compile Time Factoring in Chapter Six In these cases it s best to save the value of BASE on the return stack like this 148 Implementation Elements of Forth Style BASE gt R HEX etc R gt BASE Some folks make it a policy to use this approach on any screen that changes BASE BASE BASE BASE BASE so they don t have to worry about it Moore prefers to de ne LOAD LOAD LOAD LOAD LOAD to invoke DECIMAL DECIMAL DECIMAL DECIMAL DECIMAL after loading This approach simpli es the screen s contents because you don t have to worry about resetting Spacing and Indentation Tip Spacing and indentation are essential for readability 5 8 The examples in this book use widely accepted conventions of spacing and indenting style Whitespace appropriately used lends readability There s no penalty for leaving space in source screens except disk memory which is cheap For those who like their conventions in black and white Table 5 1 is a list of guidelines Bu
256. ng technique is perhaps the most important skill for a Forth programmer What is factoring Factoring means organizing code into useful frag ments To make a fragment useful you often must separate reusable parts from non reusable parts The reusable parts become new de nitions The non reusable parts become arguments or parameters to the de nitions Making this separation is usually referred to as factoring out The rst part of this chapter will discuss various factoring out techniques Deciding how much should go into or stay out of a de nition is an other aspect of factoring The second section will outline the criteria for useful factoring Factoring Techniques If a module seems almost but not quite useful form a second place in the system try to identify and isolate the useful subfunction The remainder of the module might be incorporated in its original caller from Structured Design 1 The useful subfunction of course becomes the newly factored de nition What about the part that isn t quite useful That depends on what it is Factoring Out Data The simplest thing to factor out is data thanks to Forth s data stack For instance to compute two thirds of 1 000 we write 1000 2 3 172 Factoring To de ne a word that computes two thirds of any number we factor out the argument from the de nition TWO THIRDS n1 n2 2 3 When the datum comes in the m
257. ng the components of the system and nally building the program The book stresses the importance of writing programs that not only work but that are also readable logical and that express the best solution in the simplest terms Although most of the principles described here can be applied to any language I ve presented them in the context of Forth Forth is a language an operating system a set of tools and a philosophy It is an ideal means for thinking because it corresponds to the way our minds work Thinking Forth is thinking simple thinking elegant thinking exible It is not restrictive not complicated not over general You don t have to know Forth to bene t from this book Thinking Forth synthesizes the Forth approach with many principles taught by modern computer science The marriage of Forth s simplicity with the traditional disciplines of analysis and style will give you a new and better way to look at software problems and will be helpful in all areas of computer application If you want to learn more about Forth another book of mine Starting Forth covers the language aspects of Forth Otherwise Appendix A of this book introduces Forth fundamentals A few words about the layout of the book After devoting the rst chap ter to fundamental concepts I ve patterned the book after the software de velopment cycle from initial speci cation up through implementation The appendixes in back include an ove
258. nition Forth words can be nested like this inde nitely Writing a Forth applica tion consists of building increasingly powerful de nitions such as this one in terms of previously de ned ones Another de ning word is CODE CODE CODE CODE CODE which is used in place of colon to de ne a command in terms of machine instructions for the native processor Words de ned with CODE CODE CODE CODE CODE are indistinguishable to the user from words de ned with colon CODE CODE CODE CODE CODE de nitions are needed only for the most time critical portions of an applications if at all Data Structures Still another de ning word is CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT which is used like this 17 CONSTANT SEVENTEEN The new word SEVENTEEN can now be used in place of the actual number 17 The de ning word VARIABLE creates a location for temporary data VARIABLE is used like this 266 Overview of Forth For Newcomers VARIABLE BANANAS This reserves a location which is identi ed by the name BANANAS Fetching the contents of this location is the job of the word pronounced fetch For instance BANANAS fetches the contents of the variable BANANAS Its counterpart is pronounced store which stores a value into the location as in 100 BANANAS Forth also provides a word to increment the current value by the given value for instance the phrase 2 BANANAS increment
259. not only understanding but simpli cation then per haps we ve got more work to do Our revised decision table Figure 2 6 shows that the per mile charge depends only on whether the rate is full lower or lowest In other words it s subject to only one of the three dimensions shown in the table What happens if we split this table into two tables as in Figure 2 7 Figure 2 7 The sectional decision table The Decision Table 57 Figure 2 8 The decision table without operator involvement depicted Now we re getting the answer through a combination of table look up and calculation The formula for the per minute charge can be expressed as a pseudoForth de nition PER MINUTE CHARGE per minute charge CONNECT CHARGE MILEAGE CHARGE The now appears once in the de nition not nine times in the table Taking the principle of calculation one step further we note or remember from the original problem statement that operator assistance merely adds a one time charge of 90 to the total charge In this sense the operator charge is not a function of any of the three dimensions It s more appropriately expressed as a logical calculation that is a function that combines logic with arithmetic ASSISTANCE direct dial charge total charge OPERATOR IF 90 THEN But remember this charge applies only to the rst minute This leaves us with the simpli ed table shown in Figure 2 8 and an
260. nstance you might have an application in which events must occur ac cording to some predetermined schedule To manage the scheduling you might rst design a few words to constitute a schedule building lexicon With these words you ll be able to describe the order of events that must occur within your application Thus within a single component you ll not only share information but also work out potential con icts The wrong approach would be to let each functional module know things about its schedule that could potentially con ict with another module s schedule How can you know in designing a component what commands the using components will need Admittedly this is something of a chicken vs egg problem But Forth programmers handle it the same way chickens and eggs do iteratively If the component is well designed completeness doesn t matter In fact a component need only su ce for the current iteration s design No component should be considered a closed book until the application has been completed which in the case of maintained applications is never As an example imagine that your product needs to talk to other ma chines in the outside world via a universal I O chip that is part of your sys tem This particular chip has a control register and a data register In a Decomposition by Component 73 badly designed application pieces of code throughout the program wou
261. nt a formula by which these values could be calculated And the formula might prove wrong later In this case table driven code is easier to maintain In Chapter Three we designed a keystroke interpreter for our Tiny Editor using a decision table Key Not Inserting Inserting Ctrl D DELETE INSERT OFF Ctrl I INSERT ON INSERT OFF backspace BACKWARD INSERT lt etc We could have achieved this same result with logic CASE CTRL D OF INSERTING IF INSERT OFF ELSE DELETE THEN ENDOF CTRL I OF INSERTING IF INSERT OFF ELSE INSERT ON THEN ENDOF BACKSPACE OF INSERTING IF INSERT lt ELSE BACKWARD THEN ENDOF ENDCASE Calculations vs Data Structures vs Logic 121 but the logic is more confusing And the use of logic to express such a multi condition algorithm gets even more convoluted when a table was not used in the original design The use of logic becomes advisable when the result is not calculable or when the decision is not complicated enough to warrant a decision table Chapter Eight is devoted to the issue of minimizing the use of logic in your programs 4 23 Tip In choosing which approach to apply towards solving a problem give preference in the following order 1 calculation except when speed counts 2 data structures 3 logic Of course one nice feature of modular languages such as Forth is that the actual implementation of a component whether it uses calculation data struc
262. ntal binding the statements just happen to appear in the same module Logical binding the module has several related functions and requires a ag or parameter to decide which particular function to perform Temporal binding the module contains a group of statements that hap pen at the same time such as initialization but have no other relationship Communicational binding the module contains a group of statements that all refer to the same set of data 14 The Philosophy of Forth Sequential binding where the output of one statement serves as input for the next statement Our MAKE CEREAL module exhibits functional binding because it can be thought of as doing one thing even though it consists of several subordinate tasks Coupling A second tenet of structured design concerns coupling a measure of how modules in uence the behavior of other modules Strong coupling is considered bad form The worst case is when one module actually modi es code inside another module Even passing control ags to other modules with the intent to control their function is dangerous An acceptable form of coupling is data coupling which involves passing data not control information from one module to another Even then systems are easiest to build and maintain when the data interfaces between modules are as simple as possible When data can be accessed by many modules for instance global vari ables there s s
263. nts into the model than into a design 2 5 Tip Strive to build a solid conceptual model before beginning the design Analysis consists of expanding the requirements de nition into a conceptual model The technique involves two way communication with the customer in successive attempts to describe the model Like the entire development cycle the analysis phase is best approach iteratively Each new requirement will tend to suggest something in your mental model Your job is to juggle all the requirements and constraints until you can weave a pattern that ts the bill Figure 2 2 illustrates the iterative approach to the analysis phase The nal step is one of the most important show the documented model to the customer Use whatever means of communication are necessary diagrams tables or cartoons to convey your understanding to the customer and get the needed feedback Even if you cycle through this loop a hundred times it s worth the e ort In the next three sections we ll explore three techniques for de ning and documenting the conceptual model Figure 2 2 An iterative approach to analysis 48 Analysis 1 de ning the interfaces 2 de ning the rules 3 de ning the data structures De ning the Interfaces Tip First and most importantly the conceptual model should describe the system s interfaces 2 6 Teleska The spec basically deals with WHAT In its most glorious form it
264. number into decimal digits and treat each digit separately For instance 37 can be written as XXX thirty Solving a Problem Computing Roman Numerals 123 followed by VII seven It may be premature but we can already see a method by which Forth will let us decompose a number into decimal digits with modulo division by ten For instance if we say 37 10 MOD we ll get a 7 and a 3 on the stack the three being the quotient is on top But these observations raise a question What about below ten where there is no decimal digit Is this a special case Well if we consider that each X represents ten then the absence of X represents zero So it s not a special case Our algorithm works even for numbers less than ten Let s continue our observations paying special attention to the cycles of ten We notice that forty is XL This is analogous to 4 being IV only shifted by the value of ten The X before the L says ten less than fty Similarly L 50 is analogous to V 5 LX 60 VI 6 LXX 70 VII 7 LXXX 80 VIII 8 XC 90 IX 9 C 100 X 10 Apparently the same patterns apply for any decimal digit only the symbols themselves change Anyway it s clear now that we re dealing with an essentially decimal system If pressed to do so we could even build a model for a system to display Roman numerals from 1 to 99 using a combin
265. ny digit using only the elementary set of symbols Our data structure should contain only this much information I V X L C D M In listing the symbols we ve also organized them in a way that seems right The symbols in the left column are all multiples of ten the symbols in the right column are multiples of ve Furthermore the symbols in each row have ten times the value of the symbols directly above them Another di erence the symbols in the rst column can all be combined in multiples as XXXIII But you can t have multiples of any of the right column symbols such as VVV Is this observation useful Who knows Let s call the symbols in the left column ONERS and in the right column FIVERS The ONERS represent the values 1 10 100 and 1 000 that is the value of one in every possible decimal place The FIVERS represent 5 50 and 500 that is the value of ve in every possible decimal place Using these terms instead of the symbols themselves we should be able to express the algorithm for producing any digit We ve factored out the actual symbols from the kind of symbols For instance we can state the following preliminary algorithm For any digit print as many ONERS as necessary to add up to the value Algorithm 125 Thus for 300 we get CCC for 20 we get XX for one we get I And for 321 we get CCCXXI This algorithm works until the digit is 4 Now we ll have to expand our
266. odules should not be steps in the process but rather pieces of information that might possibly change Modules should be used to hide such information 16 The Philosophy of Forth Let s look at this important idea of information hiding Suppose you are writing a Procedures Manual for your company Here s a portion Sales Dept takes order sends blue copy to Bookkeeping orange copy to Shipping Jay logs the orange copy in the red binder on his desk and completes packing slip Everyone agrees that this procedure is correct and your manual gets distributed to everyone in the company Then Jay quits and Marilyn takes over The new duplicate forms have green and yellow sheets not blue and orange The red binder lls up and gets replaced with a black one Your entire manual is obsolete You could have avoided the obsolescence by using the term Shipping Clerk instead of the name Jay the terms Book keeping Dept copy and Shipping Dept copy instead of blue and orange etc This example illustrates that in order to maintain correctness in the face of a changing environment arbitrary details should be excluded from proce dures The details can be recorded elsewhere if necessary For instance every week or so the personnel department might issue a list of employees and their job titles so anyone who needed to know who the shipping clerk was could look it up in this single source As the personne
267. of a well commented assembly language listing These line by line comments are called narrative comments CRC Checksum 07 15 83 ACCUMULATE oldcrc char newcrc 256 shift char to hi order byte XOR amp xor into previous crc 8 0 DO Then for eight repetitions DUP 0 lt IF if hi order bit is 1 16386 XOR xor it with mask and DUP shift it left one place 1 set lo order bit to 1 ELSE otherwise i e hi order bit is 0 DUP shift it left one place THEN LOOP complete the loop The other approach does not intersperse narrative comments between code phrases This is called the horizontal format ACCUMULATE oldcrc char newcrc 256 XOR 8 0 DO DUP 0 lt IF 16386 XOR DUP 1 ELSE DUP THEN LOOP The vertical format is preferred when a large team of programmers are coding and maintaining the application Typically such a team will include several junior level programmers responsible for minor corrections In such an envi ronment diligent commenting can save a lot of time and upset As Johnson of Moore Products Co says When maintaining code you are usually interested in just one small section and the more information written there the better your chances for a speedy x Here are several pertinent rules required of the Forth programmers at Moore Products Co I m paraphrasing 1 A vertical format will be used Comments will appear to the right of the
268. of the memory location where the tally of apples is kept The tally can be thought of as a thing while the words that set the tally read the tally or increment the tally can be considered as actions Forth conveniently separates things from actions by allowing addresses of data structures to be passed on the stack and providing the fetch and store commands We ve discussed the importance of designing around things that may change Suppose we ve written a lot of code using this variable APPLES And now at the eleventh hour we discover that we must keep track of two di erent kinds of apples red and green We needn t wring our hands but rather remember the function of APPLES to provide an address If we need two separate tallies APPLES can supply two di erent addresses depending on which kind of apple we re currently talking about So we de ne a more complicated version of APPLES as follows VARIABLE COLOR pointer to current tally VARIABLE REDS tally of red apples VARIABLE GREENS tally of green apples RED set apple type to RED REDS COLOR GREEN set apple type to GREEN GREENS COLOR APPLES adr of current apple tally COLOR Hiding the Construction of Data Structures 25 Figure 1 10 Changing the indirect pointer Here we ve rede ned APPLES Now it fetches the contents of a variable called COLOR COLOR is a pointer either to the variable REDS
269. of water from the nearby stream in one of the containers Figure 4 2 Try to solve this on your own before reading further How can we get a six out of a nine and a four We can start out working forward by mentally transferring water from one container to the 102 Detailed Design Problem Solving Figure 4 2 Two containers other For example if we ll the large container twice from the small container we ll get eight gallons If we ll the nine gallon container to the brim then empty enough water to ll the four gallon container we ll have exactly ve gallons in the large container These ideas are interesting but they haven t gotten us six gallons And it s not clear how they will get us six gallons Let s try working backward We assume we ve measured six gallons of water and it s sitting in the large container it won t t in the small one Now how did we get it there What was the state of our containers one step previously There are only two possibilities Figure 4 3 1 The four gallon container was full and we just added it to the large container This implies that we already had two gallons in the large container Or 2 The nine gallon container was full and we just poured o three gallons into the small container Which choice Let s make a guess The rst choice requires a two gallon measurement the second requires a three gallon measurement In our initial
270. ok JOE TESTC MAKE JOE 4 MAKE JOE 5 MAKE redirects JOE to the code after MAKE JOE JOE 4 ok TESTC MAKE JOE 4 MAKE JOE 5 Executes the code that JOE points to 4 MAKE etc JOE TESTC MAKE JOE 4 MAKE JOE 5 After execution of 4 the second MAKE redirects JOE to point to the ve There was no AND to stop it JOE 5 ok TESTC MAKE JOE 4 MAKE JOE 5 Typing JOE a second time executes the new code pointed to by JOE 5 Here the pointer will stay DOER CR VISIBLE MAKE TYPE TYPE AND MAKE EMIT EMIT AND MAKE SPACES SPACES AND MAKE CR CR INVISIBLE MAKE TYPE 2DROP AND MAKE EMIT DROP AND MAKE SPACES DROP AND MAKE CR Using DOER MAKE 223 Here we ve de ned a vectorable set of output words each name having a prime mark at the end VISIBLE sets them to their expected functions INVISIBLE makes them no ops eating up the arguments that would nor mally be passed to them Say INVISIBLE and any words de ned in terms of these four output operators will not produce any output 4 To change the state for the next occurrence only then change the state or reset it again Suppose we re writing an adventure game When the player rst arrives at a particular room the game will display a detailed description If the player returns to the same room later the game will show a shorter message We
271. olled exit is often impractical yet many variables must somehow be restored to a natural condition Saving and Restoring a State 211 Moore responds to this example You really get tied up in a knot You re creating problems for yourself If I want a hex dump I say HEX HEX HEX HEX HEX DUMP DUMP DUMP DUMP DUMP If I want a decimal dump I say DECIMAL DECIMAL DECIMAL DECIMAL DECIMAL DUMP DUMP DUMP DUMP DUMP I don t give DUMP DUMP DUMP DUMP DUMP the privilege of messing around with my environment There s a philosophical choice between restoring a situation when you nish and establishing the situation when you start For a long time I felt you should restore the situation when you re nished And I would try to do that con sistently everywhere But it s hard to de ne everywhere So now I tend to establish the state before I start If I have a word which cares where things are it had better set them If somebody else changes them they don t have to worry about resetting them There are more exits than there are entrances In cases in which I need to do the resetting before I m done I ve found it useful to have a single word which I call PRISTINE to perform this resetting I invoke PRISTINE at the normal exit point of the application at the point where the user may deliberately exit just before QUIT QUIT QUIT QUIT QUIT at any point where a fatal error may occur caus
272. olved we recognized two subproblems lling the small container with one gallon and then lling the large container with six gallons 104 Detailed Design Problem Solving Intent on a complicated problem Recognizing these smaller problems sometimes called auxiliary prob lems is an important problem solving technique By identifying the subprob lem we can assume it has a straightforward solution Without stopping to determine what that solution might be we forge ahead with our main prob lem Forth is ideally suited to this technique as we ll see 4 9 Tip Step back from the problem It s easy to get so emotionally attached to one particular solution that we forget to keep an open mind The literature of problem solving often employs the example of the nine dots It stumped me so I ll pass it along We have nine dots arranged as shown in Figure 4 4 The object is to draw straight lines that touch or pass through all nine dots without lifting the pen o the paper The constraint is that you must touch all nine dots with only four lines Figure 4 4 The nine dots problem You can sit a good while and do no better than the almost right Fig ure 4 5 If you concentrate really hard you may eventually conclude that the problem is a trick there s no solution Figure 4 5 Not quite right But if you sit back and ask yourself Am I cheating myself out a useful tack by being narrow minded Am I as
273. on Stacks 213 It was tempting to think that once having added the ability to make the output invisible I could use this feature to serve both purposes Unfortunately the two purposes are not mutually exclusive Let s see what would happen if I tried to violate this rule Imagine that the word DISPLAY does the output and it s smart enough to know whether to be visible or invisible The words VISIBLE and INVISIBLE set the state respectively My code for looking ahead will rst execute INVISIBLE then test format the upcoming text to determine its length and nally execute VISIBLE to restore things to the normal state This works ne Later I add the table of contents feature First the code executes INVI SIBLE then runs through the document determining page numbers etc then nally executes VISIBLE to restore things to normal The catch Suppose I m running a table of contents and I hit one of those places where I look ahead When I nish looking ahead I execute VISIBLE Suddenly I start printing the document when I was supposed to be running the table of contents The solution There are several One solution views the problem as being that the lookahead code is clobbering the visible invisible ag which may have been preset by table of contents Therefore the lookahead code should be responsible for saving and later restoring the ag Another solution involves keeping two separate variables one to indicate we re
274. one place the string beginning at the pointer Store new character into byte pointed to by pointer Advance pointer unless at end of eld F U N T I O N A L I T Y F U N T T I O N A L I T Y F U N C T I O N A L I T Y F U N T T I O N A L I T Y 76 Preliminary Design Decomposition We ve just developed the algorithms for the problem at hand Our next step is to examine these three essential procedures looking for useful names that is procedures or elements which can either 1 possibly be reused or 2 possibly change We discover that all three procedures use something called a pointer We need two procedures 1 to get the pointer if the pointer itself is relative this function will perform some computation 2 to advance the pointer Wait three procedures 3 to move the pointer backwards because we will want cursor keys to move the cursor forward and back without editing changes These three operators will all refer to a physical pointer somewhere in memory Where it is kept and how relative or absolute should be hidden within this component Let s attempt to rewrite these algorithms in code KEYS returns value of key last pressed POSITION returns address of character pointed to FORWARD advance pointer stopping at last position BACKWARD decrement pointer stopping at first position OVERWRITE KEY POSITION C FORWARD INSERT SLIDE gt OVERWRITE
275. one to test out certain ideas But this code may not be part of the nished product The idea is to map out your design Johnson advises us to complete the design speci cation before starting to code with the exception of needed preliminary tests The next interview backs up this point and adds some additional reasons John Teleska has been an independent software consultant since 1976 spe cializing in custom applications for academic research environments He enjoys providing research tools right at the edge of what technology is able to do Teleska works in Rochester New York I see the software development process as having two phases The rst is making sure I understand what the problem is The second is implementation including debugging veri cation etc The Value of Planning 41 My goal in Phase One is an operational speci cation I start with a problem description and as I proceed it becomes the operational speci cation My understanding of the problem metamorphoses into a solution The better the understanding the more complete the solution I look for closure a sense of having no more questions that aren t answered in print I ve found that on each project I ve been putting more time into Phase One much to the initial dismay of many of my clients The limiting factor is how much I can convince the client it s necessary to spend that time up front Customers generally don t know the speci ca
276. ong should a Forth de nition be A word should be a line long That s the target When you have a whole lot of words that are all useful in their own right perhaps in debugging or exploring but inevitably there s a reason for their existence you feel you ve extracted the essence of the problem and that those words have expressed it Short words give you a good feeling An informal examination of one of Moore s applications shows that he aver ages seven references including both words and numbers per de nition These are remarkably short de nitions Actually his code was divided about 50 50 between one line and two line de nitions Psychological tests have shown that the human mind can only focus its conscious attention on seven things plus or minus two at a time 2 Yet all the while day and night the vast amounts of data making connections and associations and solving problems Even if out subconscious mind knows each part of an application inside out our narrow viewed conscious mind can only correlate seven elements of it at once Beyond that our grasp wavers Short de nitions match our mental capabilities Something that many Forth programmers to write overly long de nitions is the knowledge that headers take space in the dictionary The coarser the factoring the fewer the names and the less memory that will be wasted It s true that more memory will be used but it s hard to say that anything
277. or multiples of 3 for nested in dentation 1 space between words numbers within a phrase 2 or 3 spaces between phrases 1 space between the last word and the semicolon 1 space between semicolon and IMMEDIATE IMMEDIATE IMMEDIATE IMMEDIATE IMMEDIATE if invoked No blank lines between de nitions except to separate distinct groups of de nitions Stack Comment Abbreviations n single length signed number d double length signed number u single length unsigned number ud double length unsigned number t triple length q quadruple length An often seen alternative calls for 1 space between the name and comment and 3 between the comment and the de nition A more liberal technique uses 3 spaces before and after the comment Whatever you choose be consistent 284 Summary of Style Conventions c 7 bit character value b 8 bit byte boolean ag or t true f false a or adr address acf address of code eld apf address of parameter eld as pre x address of s d as a pair source destination lo hi lower limit upper limit inclusive count o o set i index m mask x don t care data structure notation An o set is a di erence expressed in absolute units such as bytes An index is a di erence expressed in logical units such as elements or records Input Stream Comment Designations c single character blank delimited name sequence of characters blank de
278. or to the variable GREENS These two variables are the real tallies If we rst say RED then we can use APPLES to refer to red apples If we say GREEN we can use it to refer to green apples Figure 1 10 We didn t need to change the syntax of any existing code that uses APPLES We can still say 20 APPLES and 1 APPLES Look again at what we did We changed the de nition of APPLES from that of a variable to a colon de nition without a ecting its usage Forth allows us to hide the details of how APPLES is de ned from the code that uses it What appears to be thing a variable to the original code is actually de ned as an action a colon de nition within the component Forth encourages the use of abstract data types by allowing data struc tures to be de ned in terms of lower level components Only Forth which eliminates the CALLs from procedures which allows addresses and data to be implicitly passed via the stack and which provides direct access to memory locations with and can o er this level of information hiding Forth pays little attention to whether something is a data structure or an algorithm This indi erence allows us programmers incredible freedom in creating the parts of speech we need to describe our applications 26 The Philosophy of Forth I tend to think of any word which returns an address such as APPLES as a noun regardless of how it s de ned A word that perfor
279. order to provide the kind of freedom and exibility we have described it cannot tell you that you meant to type RED APPLES instead of APPLES RED You have just invented syntax Yet Forth more than makes up for its omission by letting you compile each de nition one at a time with turnaround on the order of seconds You discover your mistake soon enough when the de nition doesn t work In addition you can add appropriate syntax checking in your de nitions if you want to But Is It a High Level Language 29 Two solutions to the problem of security An artist s paintbrush doesn t notify the artist of a mistake the painter will be the judge of that The chef s skillet and the composer s piano remain simple and yielding Why let a programming language try to out think you So is Forth a high level language On the question of syntax checking it strikes out On the question of abstraction and power it seems to be of in nite level supporting everything from bit manipulation at an output port to business applications You decide Forth doesn t care The Language of Design Forth is a design language To the student of traditional computer science this statement is self contradictory One doesn t design with a language one implements with a language Design precedes implementation Experienced Forth programmers disagree In Forth you can write ab stract design level code and still be able to test it at any
280. orked at least on the system used there by backing up to the name eld of the vocabulary de nition and displaying it The obvious repetition of code struck my eye as a sign of bad factoring It would have been possible to consolidate the repeated passage into a third de nition VOCABULARY pointer 8 NFA ID shortening the original de nitions to CONTEXT CONTEXT VOCABULARY CURRENT CURRENT VOCABULARY But in this approach the only di erence between the two de nitions was the pointer to be displayed Since part of good factoring is to make fewer not more de nitions it seemed logical to have only one de nition and let it take as an argument either the word CONTEXT or the word CURRENT Applying the principles of good naming I suggested IS adr 8 NFA ID allowing the syntax CONTEXT IS ASSEMBLER ok or CURRENT IS FORTH ok The initial clue was repetition of code but the nal result came from attempting to simplify the command interface Here s another example The IBM PC has four modes four displaying text only 40 column monochrome 40 column color 80 column monochrome 80 column color The word MODE is available in the Forth system I use MODE takes an argument between 0 and 3 and changes the mode accordingly Of course the phrase 0 MODE or 1 MODE doesn t help me remember which mode is which Since I need to switch between these modes in doing present
281. ou ve completely designed it Also notice Successive re nement forces you to work out all details of control structure on each level before proceeding to the next lower level Structured Design By the middle of late 70s the computing industry had tried all the concepts we ve described and it was still unhappy The cost of maintaining software keeping it functional in the face of change accounted for more than half of the total cost of software in some estimates as much as ninety percent Everyone agreed that these atrocities could usually be traced back to incomplete analysis of the program or poorly thought out designs Not that there was anything wrong with structured programming per se When projects came in late incomplete or incorrect the designers took the blame for not anticipating the unforeseen 12 The Philosophy of Forth Tobias I think you ve carried the successive re nement of that module far enough Scholars naturally responded by placing more emphasis on design Next time let s think things out better About this time a new philosophy arose described in an article called Structured Design 3 One of its principles is stated in this paragraph Simplicity is the primary measurement recommended for evaluating alternative designs relative to reduced debugging and modi cation time Simplicity can be enhanced by dividing the system into separate pieces in such a way that pieces can be cons
282. out much emphasis on IF THEN constructs There are several techniques for minimizing control structures They include computing or calculating hiding conditionals through re factoring using structured exits vectoring redesigning In this chapter we ll examine these techniques for simplifying and eliminating control structures from your code What s So Bad about Control Structures Before we begin reeling o our list of tips let s pause to examine why condi tionals should be avoided in the rst place The use of conditional structures adds complexity to your code The more complex your code is the harder it will be for you to read and to maintain The more parts a machine has the greater are its chances of breaking down And the harder it is for someone to x Moore tells this story I recently went back to a company we had done some work for several years ago They called me in because their program is now ve years old and it s gotten very complicated They ve had programmers going in and patching things adding state variables and conditionals Every statement that I recall being a simple thing ve years ago now has gotten very complicated If this else if this else if this and then the simple thing 228 Minimizing Control Structures Reading that statement now it s impossible for me to gure out what it s doing and why I d have to remember what each va
283. plex the problem the less likely it will be that you ll nd a universally applicable data structure The number of instances in which a truly complex data structure has found universal use is very small One example of a successful complex data structure is the Forth dictionary Very rm structure great versatility It s used everywhere in Forth But that s rare If you choose to de ne the word ARRAY you ve done a decomposition step You ve factored out the concept of an array from all the words you ll later back in And you ve gone to another level of abstraction Building levels of abstraction is a dynamic process not one you can predict 6 22 Tip Today make it work Tomorrow optimize it Again Moore On the day of this interview Moore had been completing work on the design of a board level Forth computer using commercially available ICs As part of his toolkit for designing the board he created a simulator in Forth to test the board s logic This morning I realized I ve been mixing the descriptions of the chips with the placement of the chips on the board This perfectly convenient for my purposes at the moment but when I come up with another board that I want to use the same chips for I have arranged things very badly I should have factored it with the descriptions here and the uses there I would then have had a chip description language Okay At the time I was doing this I was not interested in
284. plication so that the code not the comments conveys the meaning If you succeed then you can eliminate the clutter of excessive comment ing achieving a purity of expression without redundant explanations Vertical Format vs Horizontal Format 161 Wiggins proud of his commenting technique Tip The most accurate least expensive documentation is self documenting code 5 14 Unfortunately even the best programmers given the pressure of a deadline may write working code that is not easily readable without comments If you are writing for yourself or for a small group with whom you can verbally communicate the horizontal format is ideal Otherwise consider the vertical format Choosing Names The Art Besides a mathematical inclination an exceptionally good mastery of one s native tongue is the most vital asset of a competent programmer Prof Edsger W Dijkstra 3 We ve talked about the signi cance of using names to symbolize ideas and objects in the application The choosing of names turns out to be an important part of the design process Newcomers tend to overlook the important of names After all they think the computer doesn t care what names I choose But good names are essential for readability Moreover the mental ex ercise of summoning a one word description bears a synergistic e ect on your perceptions of what the entity should or should not do Here are some rules for choosing good names
285. rd MVP FORTH LPB 12 05 83 1 NOTHING 2 DOER CREATE NOTHING DOES gt gt R 3 VARIABLE MARKER 4 MAKE R gt DUP 2 DUP 2 SWAP 2 pfa 5 DUP IF gt R THEN 6 MAKE STATE IF compiling 7 COMPILE MAKE HERE MARKER 0 8 ELSE HERE COMPILE 9 COMPILE THEN IMMEDIATE 10 AND COMPILE EXIT HERE MARKER IMMEDIATE 11 UNDO NOTHING COMPILE 12 13 238 14 The code in this screen is in the public domain 15 Screen 26 0 TODDLER Example of DOER MAKE 12 01 83 1 DOER WHY 2 RECITAL 3 CR Your daddy is standing on the table Ask him WHY 4 MAKE WHY To change the light bulb 5 BEGIN 6 MAKE WHY Because it s burned out 7 MAKE WHY Because it was old 8 MAKE WHY Because we put it in there a long time ago 9 MAKE WHY Because it was dark 10 MAKE WHY Because it was night time 11 MAKE WHY Stop saying WHY 12 MAKE WHY Because it s driving me crazy 13 MAKE WHY Just let me change this light bulb 14 F UNTIL 15 WHY CR WHY QUIT 274 De ning DOER MAKE APPENDIX C Other Utilities Described in This Book This appendix is here to help you de ne some of the words referred to in this book that may not exist in your system De nitions are given in Forth 83 Standard From Chapter Four A
286. readable Let s explore this paradox The invention of the stack is analogous to that of pronouns in English Consider the passage Take this gift wrap it in tissue paper and put it in a box Notice the word gift is mentioned only once The gift is referred to henceforth as it The informality of the it construct makes English more readable pro vided the reference is unambiguous So with the stack the implicit passing of arguments makes code more readable We emphasize the processes not the passing of arguments to the processes 198 Handling Data Stacks and States Our analogy to pronouns suggests why bad Forth can be so unreadable The spoken language gets confusing when too many things are referred to with pronouns Take o the wrapping and open the box Remove the gift and throw it away The problem with this passage is that we re using it to refer to too many things at once There are two solutions to this error The easiest solution is to supply a real name instead of it Remove the wrapping and open the box Take out the gift and throw the box away Or we can introduce the words former and latter But the best solution is to redesign the passage Remove the wrapping and open the present Throw away the box So in Forth we have analogous observations Tip Simplify code by using the stack But don t stack too deeply within any single de nition Redesign or as a l
287. rent position Here are our revised procedure names The commands just added are in boldface OVERWRITE KEY POSITION C KEY EMIT FORWARD RETYPE type from current position to end of field and reset cursor INSERT SLIDE gt RETYPE OVERWRITE DELETE SLIDE lt BLANK END RETYPE Since these are the only three functions which change memory they are the only three functions that need to refresh the screen This idea is critical We must be able to make such assertions to assure program correctness The assertion is intrinsic to the nature of the problem Note that the additional problem of video refresh adds an additional pointer the current cursor position on the screen But decomposition by component has encouraged us to view the OVERWRITE process as changing both the data eld and the video vision of it similarly with SLIDE lt and SLIDE gt For this reason it seems natural now to maintain only one real pointer a relative one from which we can compute either the data address in memory or the column number on the screen Maintaining a Component based Application 79 Figure 3 3 The traditional approach view from the top Since the nature of the pointer is wholly hidden within the three processes POSITION FORWARD and BACKWARD we can readily accommodate this approach even if it wasn t our rst approach This change may have seemed simple enough here even obvious If so it s because the technique ensu
288. res exible design If we had used a traditional approach if we had designed according to structure or according to data transformation through sequential processes our brittle design would have been shattered by the change To prove this assertion we ll have to start all over again from scratch Designing and Maintaining a Traditional Application Let s pretend we haven t studied the Tiny Editor problem yet and we re back with a minimal set of specs We ll also start with our initial assumption that we can refresh the display by retyping the entire eld after each keystroke According to the dictum of top down design let s take the widest angle view possible and examine the problem Figure 3 3 depicts the program in its simplest terms Here we ve realized that the editor is actually a loop which keeps getting keystrokes and performing some editing function until the user presses the return key Inside the loop we have three modules getting a character from the keyboard editing the data and nally refreshing the display to match the data Clearly most of the work will go on inside Process a Keystroke Applying the notion of successive re nement Figure 3 4 shows the editor problem redrawn with Process a Keystroke expanded We nd it takes several attempts before we arrive at this con guration Designing this level forces us 80 Preliminary Design Decomposition Figure 3 4 A structure for Proces
289. riable indicated why it was relevant in this case and then what was happening as a consequence of it or not happening It started innocently They had a special case they needed to worry about To handle that special case they put a conditional in one place Then they discovered that they also needed one here and here And then a few more Each incremental step only added a little confusion to the program Since they were the programmers they were right on top of it The net result was disastrous In the end they had half a dozen ags Test this one reset it set that one and so on As a result of this condition you knew you had other conditions coming up you had to look out for They created the logical equivalent of spaghetti code in spite of the opportunity for a structured program The complexity went far beyond what they had ever intended But they d committed themselves to going down this path and they missed the simple solution that would have made it all unnecessary having two words instead of one You either say GO or you say PRETEND In most applications there are remarkably few times when you need to test the condition For instance in a video game you don t really say If he presses Button A then do this if he presses Button B then do something else You don t go through that kind of logic If he presses the button you do something What you do is associated with the button not with the logic Con
290. rol structure using this technique CONDITIONALLY A B OR C AND IF NOT R gt DROP THEN ACTIVE CONDITIONALLY TUMBLE JUGGLE JUMP LAZY CONDITIONALLY SIT EAT SLEEP Forth allows us to alter the control ow by directly manipulating the return stack If in doubt see Starting Forth Chapter Nine Indiscreet application of this trick can lead to unstructured code with nasty side e ect But the disciplined use of the structured exit can actually simplify code and thereby improve readability and maintainability Moore More and more I ve come to favor R gt DROP to alter the ow of control It s similar to the e ect of an ABORT ABORT ABORT ABORT ABORT which has an IF IF IF IF IF THEN THEN THEN THEN THEN built in it But that s only one IF IF IF IF IF THEN THEN THEN THEN THEN in the system not at every error I either abort or I don t abort If I don t abort I continue If I do abort I don t have to thread my way through the path I short circuit the whole thing The alternative is burdening the rest of the application with checking whether an error occurred That s an inconvenience 252 Minimizing Control Structures The abort route circumvents the normal paths of control ow under special conditions Forth provides this capability with the words ABORT ABORT ABORT ABORT ABORT and QUIT QUIT QUIT QUIT QUIT The structured exit extends the concept by
291. rototyping Con structing a prototype is a more re ned way to plan just as breadboarding is in electronic design As we ll see in the next chapter experimentation proves more reliable in arriving at the truth than the guesswork of planning The Language of Design 31 The Language of Performance Although performance is not the main topic of this book the newcomer to Forth should be reassured that its advantages aren t purely philosophical Overall Forth outdoes all other high level languages in speed capability and compact ness Speed Although Forth is an interpretive language it executes compiled code There fore it runs about ten times faster than interpretive BASIC Forth is optimized for the execution of words by means of a technique known as threaded code 9 10 11 The penalty for modularizing into very small pieces of code is relatively slight It does not run as fast as assembler code because the inner interpreter which interprets the list of addresses that comprise each colon de nition may consume up to 50 of the run time of primitive words depending on the processor But in large applications Forth comes very close to the speed of assem bler Here are three reasons First and foremost Forth is simple Forth s use of a data stackgreatly reduces the performance cost of passing arguments from word to word In most languages passing arguments between modules is one of the main reasons that the use
292. rth programmers you won t have to worry about them spending too much time on planning Thus the following tip has two versions Tip For newcomers to Forth with traditional backgrounds Keep the analysis phase to a minimum For Forth addicts without a traditional background Hold o on coding as long as you can possibly stand it 2 2 Or as we observed in Chapter One Tip Plan for change by designing components that can be changed 2 3 Or simply Tip Prototype 2 4 The Analysis Phase In the remainder of this chapter we ll discuss the analysis phase Analysis is an organized way of understanding and documenting what the program should do With a simple program that you write for yourself in less than an hour the analysis phase may take about 250 microseconds At the other extreme some projects will take many man years to build On such a project the analysis phase is critical to the success of the entire project We ve indicated three parts to the analysis phase 1 Discovering the requirements and constraints 2 Building a conceptual model of the solution 3 Estimating cost scheduling and performance Let s brie y describe each part The Analysis Phase 45 Discovering the Requirements The rst step is to determine what the application should do The customer or whoever wants the system should supply a requirements speci cation This is a modest document that list
293. rview of Forth for those new to the language code for several of the utilities described answers to problems and a summary of style conventions Many of the ideas in this book are unscienti c They are based on subjective experience and observations of our own humanity For this reason I ve included interviews with a variety of Forth professionals not all of whom completely agree with one another or with me All these opinions are subject to change without notice The book also o ers suggestions called tips They are meant to be taken only as they apply to your situation Forth thinking accepts no inviolable rules To ensure the widest possible conformity to available Forth systems all coded examples in this book are consistent with the Forth 83 Standard One individual who greatly in uenced this book is the man who invented Forth Charles Moore In addition to spending several days interviewing him for this book I ve been privileged to watch him at work He is a master craftsman moving with speed and deftness as though he were physically altering the conceptual models inside the machine building tin kering playing He accomplishes this with a minimum of tools the result of an ongoing battle against insidious complexity and few restrictions other than those imposed by his own techniques I hope this book captures some of his wisdom Enjoy Acknowledgments Many thanks to all the good people who gave their time and ideas
294. s 3 Modularity see Structured pro gramming Moore Products Company 142 Moore Charles 27 52 60 63 90 91 119 133 142 143 149 164 166 170 178 181 292 INDEX 188 193 195 198 210 212 228 229 233 238 241 242 248 250 252 253 258 259 Multiple exit loops 175 Multiprocedure module 18 Mythical Man Month The Brooks 68 N Nameability 181 182 Named les storing source code in 144 Names choosing 163 167 factoring out 176 177 Naming conventions 167 168 286 288 Narrative comments 151 160 161 Nesting conditionals 235 236 Next block 143 Numbers precede names syntax rule 111 O Object 92 OFF 169 ON 169 One dimensional data table 243 244 P Parnas David 16 18 20 Pascal 8 Pattern repetition 181 Performance 32 34 Phrases 164 165 PICK 203 204 Planning limitations of 42 45 value of 40 42 Polya G 100 Post x notation 111 113 Pre xes 168 Preliminary Design 72 95 decomposition by component 72 88 decomposition by sequential com plexity 88 90 Presuming 156 Problem solving techniques see also Detailed design 100 107 Programmable Array Logic PAL 119 Programming cycle analysis see Analysis detailed design see Detailed de sign implementation see Implemen tation iterative approach 39 40 limitations of planning 42 45 phases 38 39 preliminary design deco
295. s a Keystroke to consider many things at once that we had deferred till later in the previous try For instance we must determine all the keys that might be pressed More signi cantly we must consider the problem of insert mode This realization forces us to invent a ag called INSERT MODE which gets toggled by the Ctrl I key It s used within several of the structural lines to determine how to process a type of key A second ag called ESCAPE seems to provide a nice structured way of escaping the editor loop if the user presses the return key while not in insert mode Having nished the diagram we re bothered by the multiple tests for Insert Mode Could we test for Insert Mode once at the beginning Following this notion we draw yet another chart Figure 3 5 Designing and Maintaining a Traditional Application 81 Figure 3 5 Another structure for Process a Keystroke As you can see this turns out even more awkward than the rst gure Now we re testing for each key twice It s interesting though how the two structures are totally di erent yet functionally equivalent It s enough to make one wonder whether the control structure is terribly relevant to the problem Having decided on the rst structure we ve nally arrived at the most important modules the ones that do the work of overwriting inserting and deleting Take another look at our expansion of Process a Chara
296. s a rigorously documented PDL program design language We use a PDL here as well although we call it FDL for Forth design language It s probably worthwhile having all those standards but once you re familiar with Forth Forth itself can be a design language You just have to leave out the so called noise words C DUP OVER etc and show only the basic ow Most Forth people probably do that informally We do it purposefully During one of our interviews I asked Moore if he used diagrams of any sort to plan out the conceptual model or did he code straight into Forth His reply The conceptual model is Forth Over the years I ve learned to think that way Can everyone learn to think that way I ve got an unfair advantage I codi ed my programming style and other people have adopted it I was surprised that this happened And I feel at a lovely advantage because it is my style that others are learning to emulate Can they learn to think like I think I imagine so It s just a matter of practice and I ve had more practice De ning the Rules Most of your e orts at de ning a problem will center on describing the interface Some applications will also require that you de ne the set of application rules All programming involves rules Usually these rules are so simple it hardly matters how you express them If someone pushes the button ring the bell Some applications however involve rules so complica
297. s chapter we ve enumerated various ways to make a source listing more readable We ve assumed a policy of making our code as self documenting as possible Techniques include listing organiza tion spacing and indenting commenting name choices and special words that enhance clarity We ve mentioned only brie y auxiliary documentation which includes all documentation apart from the listing itself We won t discuss auxiliary documentation further in this volume but it remains an integral part of the software development process References 1 Gregory Stevenson Documentation Priorities 1981 FORML Confer ence Proceedings p 401 2 Joanne Lee Quality Assurance in a Forth Environment Appendix A 1981 FORML Proceedings p 363 3 Edsger W Dijkstra Selected Writings on Computing A Personal Per spective New York Springer Verlag Inc 1982 4 Henry Laxen Choosing Names Forth Dimensions vol 4 no 4 Forth Interest Group 170 Implementation Elements of Forth Style SIX Factoring In this chapter we ll continue our study of the implementations phase this time focusing on factoring Decomposition and factoring are chips o the same block Both involve dividing and organizing Decomposition occurs during preliminary design fac toring occurs during detailed design and implementation Since every colon de nition re ects decisions of factoring an understand ing of good factori
298. s colon de nitions Up to a point Forth exhibits all the traits we ve studied mnemonic value abstraction power structured control operators strong functional binding limited coupling and modularity But regarding modularity we encounter what may be Forth s most signi cant breakthrough The smallest atom of a Forth program is not a module or a subroutine or a procedure but a word Furthermore there are no subroutines main programs utilities or executives each of which must be invoked di erently Everything in Forth is a word Before we explore the signi cance of a word based environment let s rst study two Forth inventions that make it possible Implicit Calls First calls are implicit You don t have to say CALL CEREAL you simply say CEREAL In Forth the de nition of CEREAL knows what kind of word it is and what procedure to use to invoke itself Thus variables and constants system functions utilities as well as any user de ned commands or data structures can all be called simply by name Implicit Data Passing Second data passing is implicit The mechanism that produces this e ect is Forth s data stack Forth automatically pushes numbers onto the stack words that require numbers as input automatically pop them o the stack words that produce numbers as output automatically push them onto the stack The words PUSH and POP do not exist in high level Forth Thus we can wri
299. s compile time behavior in the usual way comment its run time behavior separately following the word DOES gt DOES gt DOES gt DOES gt DOES gt or CODE CODE CODE CODE CODE For instance CONSTANT n DOES gt n The stack e ect comment for the run time child s behavior represents the net stack e ect for the child word Therefore it does not include the address returned by DOES gt DOES gt DOES gt DOES gt DOES gt even though this address is on the stack when the run time code begins Bad run time comment includes apf ARRAY name cells CREATE 2 ALLOT DOES gt i apf cell SWAP 2 Good ARRAY name cells CREATE 2 ALLOT DOES gt i cell SWAP 2 Words de ned by this word ARRAY will exhibit the stack e ect i cell If the de ning word does not specify the run time behavior there still exists a run time behavior and it may be commented VARIABLE name CREATE 2 ALLOT does gt adr 158 Implementation Elements of Forth Style Comments for Compiling Words As with de ning words most compiling words involve two behaviors 1 That of the compiling word as the de nition in which it appears is com piled 2 That of the run time routine which will execute when we invoke the word being de ned Again we must comment each behavior separately Tip Comment a compiling word
300. s going on usually line by line Narrative comments are used only in the vertical format which we ll describe in a later section Comments are usually typed in lower case letters to distinguish them from source code Most Forth words are spelled with upper case letters but lower case spellings are sometimes used in special cases In the following sections we ll summarize the standardized formats for these types of comments and give examples for each type Stack Notation Tip Every colon or code de nition that consumes and or returns any arguments on the stack must include a stack e ect comment 5 9 Stack notation refers to conventions for representing what s on the stack Forms of stack notation include stack pictures stack e ects and stack e ect comments Stack Picture A stack picture depicts items understood to be on the stack at a given time Items are listed from left to right with the leftmost item representing the bottom of the stack and the rightmost item representing the top For instance the stack picture nl n2 indicates two numbers on the stack with n2 on the top the most accessible position This is the same order that you would use to type these values in i e if n1 is 100 and n2 is 5000 then you would type 100 5000 to place these values correctly on the stack A stack picture can include either abbreviations such as n1 or fully spelled out words
301. s the count by two making it 102 Forth provides many other data structure operators but more impor tantly it provides the tools necessary for the programmer to create any time of data structure needed for the application The Stack In Forth variables and arrays are used for saving values that may be required by many other routines and or at unpredictable times They are not used for the local passing of data between the de nitions For this Forth employs a much simpler mechanism the data stack When you type a number it goes on the stack When you invoke a word which has numeric input it will take it from the stack Thus the phrase 17 SPACES will display seventeen blanks on the current output device 17 pushes the binary value 17 onto the stack the word SPACES SPACES SPACES SPACES SPACES consumes it A constant also pushes its value onto the stack thus the phrase SEVENTEEN SPACES has the same e ect The stack operates on a last in rst out LIFO basis This means that data can be passed between words in an orderly modular way consistent with the nesting of colon de nitions For instance a de nition called GRID might invoke the phrase 17 SPACES This temporary activity on the stack will be transparent to any other de nition that invokes GRID because the value placed on the stack is removed before the de nition of GRID ends The calling de nition might have placed some numbers of its own on th
302. s the minimum capabilities for the nished product The analyst may also probe further by conducting interviews and sending out questionnaires to the users Discovering the Constraints The next step is to discover any limiting factors How important is speed How much memory is available How soon do you need it No matter how sophisticated our technology becomes programmers will always be bucking limitations System capacities inexplicably diminish over time The double density disk drives that once were the answer to my stor age prayers no longer ll the bill The double sided double density drives I ll get next will seem like a vast frontier for a while I ve heard guys with 10 megabyte hard disks complain of feeling cramped Whenever there s a shortage of something and there always will be tradeo s have to be made It s best to use the analysis phase to anticipate most limitations and decide which tradeo s to make On the other hand you should not consider other types of constraints during analysis but should instead impose them gradually during implemen tation the way one stirs our into gravy The type of constraint to consider during analysis includes those that might a ect the overall approach The type of defer includes those that can be handled by making iterative re nements to the planned software design As we heard in our earlier interviews nding out about hardware con straints often requires wr
303. same length As you can see in Figure 7 3 we can save the state by copying the table called POINTERS into the second table called SAVED Figure 7 3 Conceptual model for saving a state table We ve implemented this approach with the code in Figure 7 4 216 Handling Data Stacks and States Figure 7 4 Implementation of save restorable state table 0 CONSTANT POINTERS address of state table PATCHED LATER POSITION o o 2 CREATE DUP 2 DOES gt a POINTERS 0 initial offset POSITION TOP POSITION BOTTOM POSITION LEFT POSITION RIGHT POSITION INSIDE POSITION OUT CONSTANT POINTERS final computed offset HERE POINTERS gt BODY POINTERS ALLOT real table CREATE SAVED POINTERS ALLOT saving place SAVE POINTERS SAVED POINTERS CMOVE RESTORE SAVED POINTERS POINTERS CMOVE Notice in this implementation that the names of the pointers TOP BOTTOM etc always return the same address There is only one location used to repre sent the current value of any state at any time Also notice that we de ne POINTERS the name of the table with CON STANT not with CREATE using a dummy value of zero This is because we refer to POINTERS in the de ning word POSITION but it s not until after we ve de ned all the eld names that we know how big the table must be and can actually ALLOT it As soon as we create the eld names we de ne the size of the table as a constant
304. se won t arise in practice or because you really don t care But the spec is often written by people who have no appreciation for program ming The designer may have carefully speci ed all the cases but hasn t told you the programmer which cases are really important If you are free to go back and argue with him and take advantage of the don t cares you can come up with a simpler solution Take an engineering application such as a 75 ton metal powder press stamping out things They want to install a computer to control the valves in place of the hydraulic control previously used What kind of spec will you get from the engineer Most likely the sensors were placed for convenience from an electromechanical standpoint Now they could be put somewhere else but the engineer has forgotten If you demand explanations you can come closer to the real world and further from their model of the world Another example is the PID proportional integration and di erentiation al gorithm for servos You have one term that integrates another term that di erentiates and a third term that smooths You combine those with 30 integration 10 di erentiation or whatever But it s only a digital lter It used to be convenient in analog days to break out certain terms of the digital lter and say This is the integrator and this is the di erentiator I ll make this with a capacitor and I ll make that with an inductor
305. selves 116 Detailed Design Problem Solving Figure 4 7 The traditional compiler vs the Forth compiler This rule is a corollary to Avoid expectations It s one of Forth s philosophical quirks to let words do their own work Witness the Forth compiler the function that compiles colon de nitions caricatured in Figure 4 7 It has very few rules Scan for the next word in the input stream and look it up in the dictionary If it s an ordinary word compile its address If it s an immediate word execute it If it s not a de ned word try to convert it to a number and compile it as a literal Forth Syntax 117 If it s not a number abort with an error message Nothing is mentioned about compiling words such as IF IF IF IF IF ELSE ELSE ELSE ELSE ELSE THEN THEN THEN THEN THEN etc The colon compiler doesn t know about these words It merely recognizes certain words as immediate and executes them letting them do their own work See Starting Forth Chapter Eleven How to Control the Colon Compiler The compiler doesn t even look for semicolon to know when to stop compiling Instead it executes semicolon allowing it to do the work of ending the de nition and shutting o the compiler There are two tremendous advantages to this approach First the com piler is so simple it can be written in a few lines of code Second there s no limit on the nu
306. sible and it isn t always advantageous But I suspect a hyphenated word of mixing two concepts 166 Implementation Elements of Forth Style Compare the following two strategies for saying the same thing ENABLE LEFT MOTOR LEFT MOTOR ON ENABLE RIGHT MOTOR RIGHT MOTOR ON DISABLE LEFT MOTOR LEFT MOTOR OFF DISABLE RIGHT MOTOR RIGHT MOTOR OFF ENABLE LEFT SOLENOID LEFT SOLENOID ON ENABLE RIGHT SOLENOID RIGHT SOLENOID ON DISABLE LEFT SOLENOID LEFT SOLENOID OFF DISABLE RIGHT SOLENOID RIGHT SOLENOID OFF The syntax on the left requires eight dictionary entries the syntax on the right requires only six and some of the words are likely to be reused in other parts of the application If you had a MIDDLE motor and solenoid as well you d need only seven words to describe sixteen combinations Tip Don t bundle numbers into names 5 21 Watch out for a series of names beginning or ending with numbers such as 1CHANNEL 2CHANNEL 3CHANNEL etc This bundling of names and numbers may be an indication of bad factor ing The crime is similar to hyphenation except that what should be factored out is a number not a word A better factoring of the above would be 1 CHANNEL 2 CHANNEL 3 CHANNEL In this case the three words were reduced to one Often the bundling of names and numbers indicates fuzzy naming In the above case more descriptive names might indicate the purpose of the channels as in VOICE TELEMETRY GUITAR We
307. sible if you know exactly where you stand when you start the module and where you stand when you leave it In Make Breakfast you ll either x cereal or make eggs not both And you ll always clean up Some programmers I know circumvent this last module by renting a new apartment every three months Structured programming was originally conceived as a design approach Modules were imaginary entities that existed in the mind of the programmer or designer not actual units of source code When structured programming design techniques are applied to non structured languages like BASIC the result looks something like Figure 1 3 Modularity 7 Figure 1 3 Structured programming with a non structured language 10 INSTRUCTION 20 INSTRUCTION Decide in a hurry 30 IF H TRUE THEN GOTO 80 If yes go to instr 80 40 INSTRUCTION 50 INSTRUCTION Make eggs 60 INSTRUCTION 70 GOTO 110 Go to instr 110 80 INSTRUCTION 90 INSTRUCTION Make cereal 00 INSTRUCTION 10 INSTRUCTION 20 INSTRUCTION Clean up 30 INSTRUCTION Writeability Yet another breakthrough encouraged the use of structured programs struc tured programming languages These languages include control structures in their command sets so you can write programs that have a more modular ap pearance Pascal is such a language invented by Niklaus Wirth to teach the principles of structured programming to his students Figure 1 4 shows how this type of
308. so di cult to change once they ve been written any design oversight at the preliminary planning stage should be revealed before the actual code level modules are written according to the top down design Otherwise man years of e ort may be wasted writing code that cannot be used Subroutines We ve been discussing modules as abstract entities only But all high level programming languages incorporate techniques that allow modules of design to be coded as modules of code discrete units that can be given names and in voked by other pieces of code These units are called subroutines procedures or functions depending on the particular high level language and on how they happen to be implemented Suppose we write MAKE CEREAL as a subroutine It might look some thing like this procedure make cereal get clean bowl open cereal box pour cereal open milk pour milk get spoon end We can also write MAKE EGGS and CLEANUP as subroutines Elsewhere we can de ne MAKE BREAKFAST as a simple routine that invokes or calls these subroutines Designing from the Top 9 Software patches are ugly and conceal structural weaknesses procedure make breakfast var h boolean indicates hurried test for hurried if h true then call make cereal else call make eggs end call cleanup end The phrase call make cereal causes the subroutine named make cereal to be executed When the subroutin
309. ss a single condition either a ag a value or the address of a function A collection of conditions together represent the state of the application or of a particular component 2 Some applications require the ability to save a current state then later restore it or perhaps to have a number of alternating states The State Table 215 7 10 Tip When the application requires handling a group of conditions simultaneously use a state table not separate variables The simple case requires saving and restoring a state Suppose we initially have six variables representing the state of a particular component as shown in Figure 7 2 Figure 7 2 A collection of related variables VARIABLE TOP VARIABLE BOTTOM VARIABLE LEFT VARIABLE RIGHT VARIABLE INSIDE VARIABLE OUT Now suppose that we need to save all of them so that further processing can take place and later restore all of them We could de ne STATE top bottom left right inside out TOP BOTTOM LEFT RIGHT INSIDE OUT STATE top bottom left right inside out OUT INSIDE RIGHT LEFT BOTTOM TOP thereby saving all the values on the stack until it s time to restore them Or we might de ne alternate variables for each of the variables above in which to save each value separately But a preferred technique involves creating a table with each element of the table referred to by name Then creating a second table of the
310. stands a word It understands the word DUP DUP DUP DUP DUP perhaps more profoundly than you do because there s never any question in its mind what DUP DUP DUP DUP DUP means The connection between words that have meaning to you and words that have meaning to the computer is a profound one The computer becomes the vehicle for communication between human being and concept But Is It a High Level Language 27 Two points of view One advantage of the correspondence between source code and machine exe cution is the tremendous simpli cation of the compiler and interpreter This simpli cation improves performance in several ways as we ll see in a later sec tion From the standpoint of programming methodology the advantage to the Forth approach is that new words and new syntaxes can easily be added Forth cannot be said to be looking for words it nds words and executes them If you add new words Forth will nd and execute them as well There s no di erence between existing words and words that you add What s more this extensibility applies to all types of words not just action type functions For instance Forth allows you to add new compiling words like IF IF IF IF IF and THEN THEN THEN THEN THEN that provide structured control ow You can easily add a case statement or a multiple exit loop if you need them or just as importantly take them out if you don t need them By contr
311. sting then yes it s a good way to decompose a problem But I ve never found the notion of level useful Another aspect of levels is languages metalanguages meta metalanguages To try and split hairs as to which level you are on assembler level rst integration level last integration level it s just tedious and not helpful My levels get all mixed up hopelessly Designing by components makes where you start less important You could start with the key interpreter for instance Its goal is to receive keystrokes and convert them to numbers passing these numbers to an internally invoked word If you substitute the Forth word dot which prints a number from the stack then we can implement the key interpreter test it and debug it without using routines that have anything to do with drawing squares On the other hand if the application required hardware support such as a graphics package that we didn t have or couldn t buy we might want to substitute something available such as displaying an asterisk just to get into the problem Thinking in terms of lexicons is like painting a huge mural that spans several canvases You work on all the canvases at once rst sketching in the key design elements then adding splashes of color here and there until the entire wall is complete Tip In deciding where to start designing look for areas where the most creativity is required the areas where change
312. sually allow you to write interrupts you can even write interrupt code in high level if desired Some Forth systems are multitasked allowing you to add as many fore ground or background tasks as you want Forth can be written to run on top of any operating system such as RT 11 CP M or MS DOS or for those who prefer it Forth can be written as a self su cient operating system including its own terminal drivers and disk drivers With a Forth cross compiler or target compiler you can use Forth to recreate new Forth systems for the same computer or for di erent computers Since Forth is written in Forth you have the otherwise unthinkable opportunity to rewrite the operating system according to the needs of your application Or you can transport streamlined versions of applications over to embedded systems Size There are two considerations here the size of the root Forth system and the size of compiled Forth applications The Forth nucleus is very exible In an embedded application the part of Forth you need to run your application can t in as little as 1K In a full development environment a multitasked Forth system including interpreter compiler assembler editor operating system and all other support utilities averages 16K This leaves plenty of room for applications And some Forths on the newer processors handle 32 bit addressing allowing unimaginably large programs Similarly Forth compiled applications tend to
313. suming any constraints not speci ed in the problem What constraints might they be 106 Detailed Design Problem Solving then you might think of extending some of the lines beyond the perimeter of the nine dots Tip Use whole brain thinking 4 10 When a problem has you stumped and you seem to be getting nowhere relax stop worrying about it perhaps even forget about it for a while Creative people have always noted that their best ideas seem to come out of the blue in bed or in the shower Many books on problem solving suggest relying on the subconscious for the really di cult problems Contemporary theories on brain functions explore the di erences between rational conscious thought which relies on the manipulation of symbols and subconscious thought which correlates perceptions to previously stored infor mation recombining and relinking knowledge in new and useful ways Leslie Hart 2 explains the di culty of solving a large problem by means of logic A huge load is placed on that one small function of the brain that can be brought into the attention zone for a period The feat is possible like the circus act but it seems more sensible to use the full resources of our glorious neocortex the multibillion neuron capacity of the brain The work aspect lies in providing the brain with raw input as in observing reading collecting data and reviewing what others have achieved Once in subconscious
314. t a terminal operator might use frequently to control an oper ation These words should be spelled as single letters as are line editor commands 3 Words in which familiar usage implies that they be abbreviated Forth assembler mnemonics are typically patterned after the manufacturer s suggested mnemonics which are abbreviations such as JMP and MOV Your names should be pronounceable otherwise you may regret it when you try to discuss the program with other people If the name is symbolic invent a pronunciation e g gt R is called to r R gt is called r from 5 19 Tip Favor short words Given the choice between a three syllable word and a one syllable word that means the same thing choose the shorter BRIGHT is a better name than INTENSE ENABLE is a better name than ACTIVATE GO RUN or ON may be better still Shorter names are easier to type They save space in the source screen Most important they make your code crisp and clean 5 20 Tip Hyphenated names may be a sign of bad factoring Moore There are diverging programming styles in the Forth community One uses hyphenated words that express in English what the word is doing You string these big long words together and you get something that is quite readable But I immediately suspect that the programmer didn t think out the words carefully enough that the hyphen should be broken and the words de ned separately That isn t always pos
315. t parameters name DRAW takes scaled input parameters name DRAW Compilation start of high level code name CASE end of high level code name CODE put something into dictionary name C executes at compile time name COMPILE slightly di erent name prime CR internal form or primitive name TYPE or lt name gt lt TYPE gt compiling word run time part systems with no folding lower case if systems with folding NAME IF de ning word name COLOR block number where overlay begins namING DISKING Data Structures table or array names EMPLOYEES total number of elements name EMPLOYEES current item number variable name EMPLOYEE sets current item n name 13 EMPLOYEE advance to next element name EMPLOYEE size of o set to item from name DATE beginning of structure size of bytes per name EMPLOYEE short for BYTES name index pointer gt name gt IN 286 Summary of Style Conventions Meaning Form Example convert address of structure to gt name gt BODY address of item le index name PEOPLE le pointer name JOB initialize structure 0name 0RECORD Direction Conversion backwards name lt SLIDE lt forwards name gt CMOVE gt from lt name lt TAPE to gt name gt TAPE convert to name gt name FEET gt METERS downward name LINE upward name LINE open name FILE close name FILE Logic Control return boolean
316. t remember Forth s interpreter couldn t care less about spacing or indentation The last position of each line should be blank except for 1 quoted strings that continue onto the next line or Table 5 1 Indentation and spacing guidelines 1 space between the colon and the name 2 spaces between the name and the comment 2 spaces or a carriage return after the comment and before the de nition 3 spaces between the name and de nition if no comment is used 3 spaces indentation on each subsequent line or multiples of 3 for nested indentation 1 space between words numbers within a phrase 2 or 3 spaces between phrases 1 space between the last word and the semicolon 1 space between semicolon and IMMEDIATE IMMEDIATE IMMEDIATE IMMEDIATE IMMEDIATE if invoked No blank lines between de nitions except to separate distinct groups of de nitions An often seen alternative calls for 1 space between the name and comment and 3 between the comment and the de nition A more liberal technique uses 3 spaces before and after the comment Whatever you choose be consistent Spacing and Indentation 149 2 the end of a comment A comment that begins with may continue right to the end of the line Also a comment that begins with may have its delimiting right parenthesis in the last column Here are some common errors of spacing and indentation Bad name not separated from the body of the de nition PUSH HEAVE
317. tack each other like alien antibodies Or else that evil bands of marauding modules are out to clobber the precious family data structures This is not what we re concerned about The purpose of hiding informa tion as we mean it is simply to minimize the e ects of a possible design change by localizing things that might change within each component Forth programmers generally prefer to keep the program under their own control and not to employ any techniques to physically hide data structures Nevertheless a brilliantly simple technique for adding Modula type modules to Forth has been implemented in only three lines of code by Dewey Val Shorre 7 24 The Philosophy of Forth Hiding the Construction of Data Structures We ve noted two inventions of Forth that make possible the methodology we ve described implicit calls and implicit data passing A third feature allows the data structures within a component to be described in terms of previously de ned components This feature is direct access memory Suppose we de ne a variable called APPLES like this VARIABLE APPLES We can store a number into this variable to indicate how many apples we currently have 20 APPLES We can display the contents of the variable APPLES 20 ok We can up the count by one 1 APPLES The newcomer can study the mechanics of these phrases in Appendix A The word APPLES has but one function to put on the stack the address
318. tc points to the ONER of that column From there we can also get each column s FIVER by reaching down one slot below the current ONER and the TENER by reaching down two slots It s like building an arm with three hands We can attach it to the ONES column as in Figure 4 8a or we can attach it to the tens column as in Figure 4 8b or to any power of ten An experienced Forth programmer is not likely to imagine arms hands or things like that But there must be a strong mental image the stu of 130 Detailed Design Problem Solving right brain thinking before there s any attempt to construct the model with code Beginners who are learning to think in this right brain way might nd the following tip helpful Tip If you have trouble thinking about a conceptual model visualize it or draw it as a mechanical device 4 25 Our table is simply an array of characters Since a character requires only a byte let s make each slot one byte We ll call the table ROMANS CREATE ROMANS ones ASCII I C ASCII V C tens ASCII X C ASCII L C hundreds ASCII C C ASCII D C thousands ASCII M C Note This use of ASCII ASCII ASCII ASCII ASCII requires that ASCII ASCII ASCII ASCII ASCII be STATE STATE STATE STATE STATE dependent see Ap pendix C If you don t have ASCII ASCII ASCII ASCII ASCII or if it is not state dependent use CREATE ROMANS 73 C 86 C 88 C
319. te DOIT GETC TRANSFORM TO DO PUT D con dent that GETC will get C and leave it on the stack TRANSFORM TO D will pick up C from the stack transform it and leave D on the stack Finally Looking Back and Forth 19 PUT D will pick up D on the stack and write it Forth eliminates the act of passing data from our code leaving us to concentrate on the functional steps of the data s transformation Because Forth uses a stack for passing data words can nest within words Any word can put numbers on the stack and take them o without upsetting the f1ow of data between words at a higher level provided of course that the word doesn t consume or leave any unexpected values Thus the stack sup ports structured modular programming while providing a simple mechanism for passing local arguments Forth eliminates from our programs the details of how words are invoked and how data are passed What s left Only the words that describe our problem Having words we can fully exploit the recommendations of Parnas to decompose problems according to things that may change and have each module consist of many small functions as many as are needed to hide infor mation about that module In Forth we can write as many words as we need to do that no matter how simple each of them may be A line from a typical Forth application might read 20 ROTATE LEFT TURRET Few other languages would encourage you
320. ted that they can t be expressed in a few sentences of English A few formal techniques can come in handy to help you understand and document these more complicated rules Here s an example Our requirements call for a system to compute the charges on long distance phone calls Here s the customer s explanation of its rate structure I made this up I have no idea how the phone company actually computes their rates except that they overcharge All charges are computed by the minute according to distance in hundreds of miles plus a at charge The at charge for direct dial calls during weekdays between 8 A M and 5 P M is 30 for the rst minute and 20 for each additional minute in addition each minute is charged 12 per 100 miles The at charge for direct calls during weekdays between 5 P M and 11 P M is 22 for the rst 52 Analysis minute and 15 for each additional minute the distance rate per minute is 10 per 100 miles The at charge for direct calls late during weekdays between 11 P M or anytime on Saturday Sundays or holidays is 12 for the rst minute and 09 for each additional minute the distance rate per minute is 06 per 100 miles If the call requires assistance from the operator the at charge increases by 90 regardless of the hour This description is written in plain old English and it s quite a mouthful It s hard to follow and like an attic cluttered with accumulated belongings
321. th I ve de ned these elements together in a single screen The bu ers are de ned with CREATE CREATE CREATE CREATE CREATE the count is an ordinary VARIABLE VARIABLE VARIABLE VARIABLE VARIABLE and the attribute patterns are de ned as CONSTANT CONSTANT CONSTANT CONSTANT CONSTANTs such as 1 CONSTANT UNDERNESS bit mask for underlining 2 CONSTANT BOLDNESS bit mask for boldface The formatting component uses phrases like UNDERNESS SET FLAG to set bits in the attribute bu er The output component uses phrases like UNDERNESS AND to read the attribute bu er A Design Mistake In designing an interface component you should ask yourself What is the set of structures and commands that must be shared by the communicating com ponents It s important to determine what elements belong to the interface and what elements should remain within a single component In writing my text formatter I failed to answer this question fully and found myself with a bug The problem was this I allow di erent type widths to be used condensed double widths etc This means not only sending di erent signals to the printer but changing the number of characters allowed per line I keep a variable called WALL for the formatter WALL indicates the right margin the point beyond which no more text can be set Changing to a di erent type width means changing the value of WALL proportionately Actually this turns out to be a mist
322. that level of optimization 194 Factoring Even if the thought had occurred to me then I probably would have said All right I ll do that later then gone right ahead with what I was doing Optimization wasn t the most important thing to me at the time Of course I try to factor things well But if there doesn t seem to be a good way to do something I say Let s just make it work My motivation isn t laziness it s knowing that there are other things coming down the pike that are going to a ect this decision in ways I can t predict Trying to optimize this now is foolish Until I get the whole picture in front of me I can t know what the optimum is The observations in this section shouldn t contradict what s been said before about information hiding and about anticipating elements that may change A good programmer continually tries to balance the expense of building in changeability against the expense of changing things later if necessary These decisions take experience But as a general rule Tip Anticipate things that may change by organizing information not by adding complexity Add complexity only as necessary to make the current iteration work 6 23 Summary In this chapter we ve discussed various techniques and criteria for factoring We also examined how the iterative approach applies to the implementation phase References 1 W P Stevens G J Myers and L L Constantine
323. that the end user will use include the conversion from zero to one relative numbering ITEM n adr 1 RECORD Tip Let addresses precede counts 4 18 Again this is a convention not a requirement of Forth but such conventions are essential for readable code You ll nd examples of this rule in the words TYPE TYPE TYPE TYPE TYPE ERASE ERASE ERASE ERASE ERASE and BLANK BLANK BLANK BLANK BLANK Tip Let sources precede destinations 4 19 Another convention for readability For instance in some systems the phrase 22 37 COPY copies Screen 22 to Screen 37 The syntax of CMOVE incorporates both this convention and the previous convention source destination count CMOVE CMOVE CMOVE CMOVE CMOVE Tip Avoid expectations in the input stream 4 20 Forth Syntax 115 Generally try to avoid creating words that presume there will be other words in the input stream Suppose your color computer represents blue with the value 1 and light blue with 9 You want to de ne two words BLUE will return 1 LIGHT may precede BLUE to produce 9 In Forth it would be possible to de ne BLUE as a constant so that when executed it always returns 1 1 CONSTANT BLUE And then de ne LIGHT such that it looks for the next word in the input stream executes it and ors it with 8 the logic of this will become apparent when we visit this example again later in the book LIGHT precedes a color
324. time by taking advantage of decomposition into lexicons A component can easily be rewrit ten as development proceeds underneath any components that use it At rst the words in a component may print numbers on your terminal instead of con trolling stepper motors They may print their own names just to let you know they ve executed They may do nothing at all Using this philosophy you can write a simple by testable version of your application then successively change and re ne it until you reach your goal Another factor that makes designing in code possible is that Forth like some of the newer languages eliminates the batch compile development se quence edit compile test edit compile test Because the feedback is instanta neous the medium becomes a partner in the creative process The program mer using a batch compiler language can seldom achieve the productive state of mind that artists achieve when the creative current ows unhindered For these reasons Forth programmers spend less time planning than their classical counterparts who feel righteous about planning To them not plan ning seems reckless and irresponsible Traditional environments force program mers to plan because traditional programming languages do not readily accom modate change Unfortunately human foresight is limited even under the best conditions Too much planning becomes counterproductive Of course Forth doesn t eliminate planning It allows p
325. tions for the job they want done And they don t have the capital or don t feel they do to spend on good specs Part of my job is to convince them it will end up costing more time and money not to Some of Phase One is spent on feasibility studies Writing the spec unearths uncertainties I try to be as uncertain about uncertainties as possible For instance they may want to collect 200 000 samples a second to a certain ac curacy I rst need to nd out if it s even possible with the equipment they ve got In this case I ve got to test its feasibility by writing a patch of code Another reason for the spec is to cover myself In case the application performs to the spec but doesn t fully satisfy the customer it s the customer s responsi bility If the customer wants more we ll have to renegotiate But I see it as the designer s responsibility to do whatever is necessary to generate an operational speci cation that will do the job to the customer s satisfaction I think there are consultants who bow to client pressure and limit the time they spend on specs for fear of losing the job But in these situations nobody ends up happy We ll return to the Teleska interview momentarily The Limitations of Planning Experience has taught us to map out where we re going before we begin coding But planning has certain limitations The following interviews give di erent perspectives to the value of planning
326. to concoct a subroutine called LEFT merely as a modi er or a subroutine called TURRET merely to name part of the hardware Since a Forth word is easier to invoke than a subroutine simply by being named not by being called a Forth program is likely to be decomposed into more words than a conventional program would be into subroutines Component Programming Having a larger set of simpler words makes it easy to use a technique we ll call component programming To explain let s rst reexamine these collections we have vaguely described as things that may change In a typical system just about everything is subject to change I O devices such as terminals and printers interfaces such as UART chips the operating system any data struc ture or data representation any algorithm etc The question is How can we minimize the impact of any such change What is the smallest set of other things that must change along with such a change The answer is The smallest set of interacting data structures and algo rithms that share knowledge about how they collectively work We ll call this unit a component A component is a resource It may be a piece of hardware such as a UART or a hardware stack Or the component may be a software resource such as a queue a dictionary or a software stack 20 The Philosophy of Forth Figure 1 7 Structured design vs component design All components involve data objects
327. to implement the thing One block Three I think this is a very useful design tool You want to gut feel whether it s a trivial problem or a major problem how much time and e ort you should spend on it 60 Analysis Given two adequate solutions the correct one is the simpler When you re done look back and say Did I come up with a solution that is reasonable If your solution lls six screens it may seem you ve used a sledgehammer to kill a mosquito Your mental image is out of proportion to the signi cance of the problem I ve seen nuclear physics programs with hundreds of thousands of lines of FOR TRAN Whatever that code does it doesn t warrant hundreds of thousands of lines of code Probably its writers have overgeneralized the problem They ve solved a large problem of which their real needs are a subset They have violated the principle that the solution should match the problem 2 12 Tip Generality usually involves complexity Don t generalize your solution any more than will be required instead keep it changeable Moore continues Given a problem you can code a solution to it Having done that and found certain unpleasantnesses to it you can go back and change the problem and end up with a simpler solution There s a class of device optimization minimizing the number of gates in a circuit where you take advantage of the don t care situation These occur either because a ca
328. to this book including Charles Moore Dr Mark Bernstein Dave Johnson John Teleska Dr Michael Starling Dr Peter Kogge Tom Dowling Donald Burgess Cary Campbell Dr Raymond Dessy Michael Ham and Kim Harris Another of the interviewees Michael LaManna passed away while this book was in production He is deeply missed by those of us who loved him xiv Preface ONE The Philosophy of Forth Forth is a language and an operating system But that s not all It s also the embodiment of a philosophy The philosophy is not generally described as something apart from Forth It did not precede Forth nor is it described anywhere apart from discussions of Forth nor does it even have a name other than Forth What is this philosophy How can you apply it to solve your software problems Before we can answer these questions let s take 100 steps backwards and examine some of the major philosophies advanced by computer scientists over the years After tracing the trajectory of these advances we ll compare and contrast Forth with these state of the art programming principles An Armchair History of Software Elegance In the prehistoric days of programming when computers were dinosaurs the mere fact that some genius could make a program run correctly provided great cause for wonderment As computers became more civilized the wonder waned Management wanted more from programmers and from their programs As the cost of h
329. tronger coupling between the modules If a programmer needs to change one module there s a greater danger that the other modules will exhibit side e ects The safest kind of data coupling is the passing of local variables as param eters from one module to another The calling module says to the subordinate module in e ect I want you to use the data I ve put in these variables named X and Y and when you re done I expect you to have put the answer in the variable named Z No one else will use these variables As we said conventional languages that support subroutines include elab orate methods of passing arguments from one module to another Hierarchical Input Process Output Designing A third precept of structured design concerns the design process Designers are advised to use a top down approach but to pay less attention initially to control structures Decision designing can wait until the later detailed design of modules Instead the early design should focus on the program s hierarchy which modules call which modules and to the passing of data from one module to another To help designers think along these new lines a graphic representation was invented called the structure chart A slightly di erent form is called the HIPO chart which stands for hierarchical input process output Structure charts include two parts a hierarchy chart and an input output chart Figure 1 6 shows thes
330. ture chart 15 16 Structured analysis 50 51 Structured English 53 54 Structured exits 252 254 Structured programming modularity 5 22 characteristics of 5 9 vs component programming 21 22 coupling 15 functional strength 14 15 hierarchical input process output designing 15 16 information hiding 16 18 new view of 18 premises of 6 subroutines 9 12 successive re nement 12 top down design 9 writeability 8 9 Stuart LaFarr 63 Subroutines 9 12 Successive re nement 12 Su xes 168 Symbols pronunciation of 288 Syntax Forth 110 119 T Target compilers 34 Teleska John 41 43 49 Terminators vs counts 239 240 Text follows names syntax rule 113 Thesaurus 164 THRU 143 Top down design 9 Tricks 242 TRUE 169 277 Two dimensional data table 244 245 Two dimensional decision table 245 248 V VARIABLE 266 294 INDEX Variable possibilities notation of 153 154 Variables global 210 local 201 203 210 problem with 207 208 saving and restoring states 210 212 state table 215 219 Vectored Execution 219 220 Vectored execution 90 Vertical format vs horizontal for mat 159 163 W Whole brain thinking 107 Wirth Niklaus 8 WITHIN 169 277 Words choosing names 163 168 de ning see De ning words ordering 113 Working backwards 103 104 Working forwards 102 Writeability 8 9 Z Zero relat
331. tures or logic doesn t have to be visible to the rest of the application Solving a Problem Computing Roman Numerals In this section we ll attempt to demonstrate the process of designing a lexi con Rather than merely present the problem and its solution I m hoping we can crack this problem together I kept a record of my thought processes as I solved this problem originally You ll see elements of the problem solving guidelines previously given but you ll also see them being applied in a seem ingly haphazard order just as they would be in reality Here goes The problem is to write a de nition that consumes a number on the stack and displays it as a Roman numeral This problem most likely represents a component of a larger system We ll probably end up de ning several words in the course of solving this problem including data structures But this particular lexicon will include only one name ROMAN and it will take its argument from the stack Other words will be internal to the component Having thus decided on the external syntax we can now proceed to devise the algorithms and data structures We ll follow the scienti c method we ll observe reality model a solution test it against reality modify the solution and so on We ll begin by recalling what we know about Roman numerals Actually we don t remember any formal rules about Roman numerals But if you give us a number we can make a Roman numera
332. u have to write a box drawing word called BOX which takes four arguments in this order x1 y1 x2 y2 Local Variables 201 where x1 y1 represent the x y coordinates for the upper left hand corner of the box and x2 y2 represent the lower right hand corner coordinates Not only do you have four elements on the stack they each have to be referred to more than once as you draw lines from point to point Although we re using the stack to get the four arguments the algorithm for drawing a box doesn t lend itself to the nature of the stack If you re in a hurry it would probably be best to take the easy way out VARIABLE TOP y coordinates top of box VARIABLE LEFT x left side VARIABLE BOTTOM y bottom VARIABLE RIGHT x right side BOX x1 y1 x2 y2 BOTTOM RIGHT TOP LEFT LEFT TOP RIGHT TOP LINE RIGHT TOP RIGHT BOTTOM LINE RIGHT BOTTOM LEFT BOTTOM LINE LEFT BOTTOM LEFT TOP LINE What we ve done is create four named variables one for each coordinate The rst thing BOX does is ll these variables with the arguments from the stack Then the four lines are drawn referencing the variables Variables such as these that are used only within a de nition or in some cases within a lexicon are called local variables I ve been guilty many times of playing hotshot trying to do as much as possible on the stack rather than de ne a local vari
333. uble length requires sign extension that is the high order part should be all ones The above de nition tests whether the single length number is negative If so it pushes a negative one onto the stack otherwise a zero But notice that the outcome is merely arithmetic there s no change in process We can take advantage of this fact by using the boolean itself S gt D n d sign extend s to d DUP O lt This version pushes a zero or negative one onto the stack without a moment s in decision In pre 1983 systems the de nition would be S gt D n d sign extend s to d DUP O lt NEGATE See Appendix C 240 Minimizing Control Structures We can do even more with hybrid values Tip To e ect a decision with a numeric outcome use AND AND AND AND AND 8 11 In the case of a decision that produces either zero or a non zero n the tradi tional phrase IF n ELSE O THEN is equivalent to the simpler statement n AND Again the secret is that false is represented by 1 all ones in 83 Forth systems AND AND AND AND ANDing n with the ag will either produce n all bits intact or 0 all bits cleared To restate with an example IF 200 ELSE O THEN is the same as 200 AND Take a look at this example n a b lt IF 45 THEN This phrase either adds 45 to n or doesn t depending
334. ummary 226 References 226 Minimizing Control Structures 227 What s So Bad about Control Structures 228 How to Eliminate Control Structures 231 A Note on Tricks 242 Decision Tables for Speed 248 Summary 259 References 259 For Further Thinking 259 Forth s E ect on Thinking 261 Appendix A Overview of Forth For Newcomers 265 Appendix B De ning DOER MAKE 269 Appendix C Other Utilities Described in This Book 275 Appendix D Answers to Further Thinking Problems 279 Appendix E Summary of Style Conventions 283 Index 289 Contents ix PREFACE TO THE 1994 EDITION I m honored that the Forth Interest Group is reprinting Thinking Forth It s gratifying to know that the book may have value to appreciators and users of Forth This edition is a reproduction of the original edition with only minor typographical corrections A lot has happened in the ten years since the book s original publication rendering some of the opinions obsolete or at best archaic A revised updated edition would have entrailed a rewrite of many sections a larger e ort than I m able to make at the time O all the opinions in the book the one that I most regret seeing gin print is my criticism of object oriented programming Since penning this book I ve had the pleasure of writing an application in a version of Forth with sup port for object oriented programming developed by Digalog Corp of
335. ution is simple instead of hard coding the ASCII ASCII ASCII ASCII ASCII we d like to change the emitted character from an asterisk to a blank This requires the addition of a variable and some readable words for setting the contents of the variable So VARIABLE INK DRAW ASCII INK UNDRAW BL INK LAYER WIDTH 0 DO INK EMIT LOOP 192 Factoring The de nition of BOX along with the remainder of the application remains the same This approach allows the syntax x y DRAW BOX or x y UNDRAW BOX By switching from an explicit value to a variable that contains a value we ve added a level of indirection In this case we ve added indirection backwards adding a new level of complexity to the de nition of LAYER without substan tially lengthening the de nition By concentrating on one dimension of the problem at a time you can solve each dimension more e ciently If there s an error in your thinking the problem will be easier to see if it s not obscured by yet another untried untested aspect of your code Tip Don t change too much at once 6 20 While you re editing your application adding a new feature or xing some thing it s often tempting to go and x several other things at the same time Our advice Don t Make as few changes as you can each time you edit compile Be sure to test the results of each revision before going on You d be ama
336. vely describe a common interface between several lexicons is called an interface lexicon Forth makes no distinction between local and global variables But Forth programmers do Moore We should be writing for the reader If something is referred to only locally a temporary variable just for accumulating a sum in we should de ne it locally It s handier to de ne it in the block where it s used where you can see its comment If it s used globally we should collect things according to their logical function and de ne them together on a separate screen One per line with a comment The question is where do you initialize them Some say on the same line immediately following its de nition But that messes up the comments and there isn t room for any decent comment And it scatters the initialization all over the application I tend to do all my initialization in the load screen After I ve loaded all my blocks I initialize the things that have to be initialized It might also set up color lookup tables or execute some initialization code If your program is destined to be target compiled then it s easy to write a word at the point that encompasses all the initialization It can get much more elaborate I ve de ned variables in ROM where the variables were all o in an array in high memory and the initial values are in ROM and I copy up the initial values at initialization time But usually you re
337. wing rst the input stream comment then the stack comment name a If you prefer to use the comment would look like this name a Incidentally there are three distinct ways to receive string input To avoid confusion here are the terms Scanning for means looking ahead in the input stream either for a word or number as in the case of tick or for a delimiter as in the case of and Expecting means waiting for EXPECT and KEY and de nitions that invoke them are ones that expect input Presuming indicates that in normal usage something will follow The word scans for the name to be de ned and presumes that a de nition will follow The input stream comment is only appropriate for input being scanned for Purpose Comments 5 10 Tip Every de nition should bear a purpose comment unless 1 its purpose is clear from its name or its stack e ect comment or 2 if it consists of three or fewer words 156 Implementation Elements of Forth Style The purpose comment should be kept to a minimum never more than a full line For example COLD restore system to start condition use the imperative mood set Foreground color not sets Foreground color On the other hand a word s purpose can often be described in terms of its stack e ect comment You rarely need both a stack comment and a purpose comment For instance SPA
338. y Editor cont d 07 29 83 1 VARIABLE MATCHED 2 FUNCTION key adr of match NOMATCH MATCHED 3 NOMATCH FUNCTIONS DO DUP I IF 4 I MATCHED LEAVE THEN KEY LOOP DROP 5 MATCHED 6 ACTION key FUNCTION MODE EXECUTE 7 GO FALSE ESCAPE BEGIN KEY ACTION ESCAPE UNTIL 8 9 10 11 12 13 14 15 add a row to the table without having to change any other piece of code even the code that searches through the table Similarly the constant KEY hides information about the number of columns in the table Incidentally the approach to FUNCTION taken in the listing is a quick and dirty one it uses a local variable to simplify stack manipulation A simpler solution that uses no local variable is FUNCTION key adr of match NOMATCH SWAP NOMATCH FUNCTIONS DO DUP I IF SWAP DROP I SWAP LEAVE THEN KEY LOOP DROP We ll o er still another solution later in this chapter under Using Structured Exits Decision Tables for Speed We ve stated that if you can calculate a value instead of looking it up in a table you should do so The exception is where the requirements for speed justify the extra complexity of a table Here is an example that computes powers of two to 8 bit precision CREATE TWOS 1 C 2 C 4 C 8 C 16 C 32 C 2 n 2 to the n TWOS C Instead of computing the answer b
339. y multiplying two times itself n times the answers are all pre computed and placed in a table We can use simple addition to o set into the table and get the answer In general addition is much faster than multiplication Moore provides another example If you want to compute trig functions say for a graphics display you don t need much resolution A seven bit trig function is probably plenty A table look up of 128 numbers is faster than anything else you re going to be able to do For low frequency function calculations decision tables are great But if you have to interpolate you have to calculate a function anyway You re probably better o calculating a slightly more complicated function and avoid ing the table lookup 248 Minimizing Control Structures Redesigning Tip One change at the bottom can save ten decisions at the top 8 14 In our interview with Moore at the beginning of the chapter he mentioned that much conditional testing could have been eliminated from an application if it had been redesigned so that there were two words instead of one You either say GO or you say PRETEND It s easier to perform a simple consistent algorithm while changing the context of your environment than to choose from several algorithms while keep ing a xed environment Recall from Chapter One our example of the word APPLES This was originally de ned as a variable it was referred to many times throughout
340. ze of the object code With only two commands as in this example the bene ts may be marginal But with larger sets of commands the bene ts increase geometrical Our nal example is a set of words to represent colors on a particular system Names like BLUE and RED are nicer than numbers One solution might be to de ne 186 Factoring 0 CONSTANT BLACK 1 CONSTANT BLUE 2 CONSTANT GREEN 3 CONSTANT CYAN 4 CONSTANT RED 5 CONSTANT MAGENTA 6 CONSTANT BROWN 7 CONSTANT GRAY 8 CONSTANT DARK GRAY 9 CONSTANT LIGHT BLUE 10 CONSTANT LIGHT GREEN 11 CONSTANT LIGHT CYAN 12 CONSTANT LIGHT RED 13 CONSTANT LIGHT MAGENTA 14 CONSTANT YELLOW 15 CONSTANT WHITE These colors can be used with words such as BACKGROUND FOREGROUND and BORDER WHITE BACKGROUND RED FOREGROUND BLUE BORDER But this solution requires 16 names and many of them are hyphenated Is there a way to simplify this We notice that the colors between 8 and 15 are all lighter versions of the colors between 0 and 7 In the hardware the only di erence between these two sets is the setting of the intensity bit If we factor out the lightness we might come up with this solution VARIABLE LIGHT intensity bit HUE color CREATE DOES gt color LIGHT OR 0 LIGHT 0 HUE BLACK 1 HUE BLUE 2 HUE GREEN 3 HUE CYAN 4 HUE RED 5 HUE MAGENTA 6 HUE BROWN 7 HUE GRAY LIGHT 8 LIGHT With this syntax the word B
341. zed how often you can make three innocent modi cations only to recompile and have nothing work Making changes one at a time ensures that when it stops working you know why Tip Don t try to anticipate ways to factor too early 6 21 Some people wonder why most Forth systems don t include the de nition word ARRAY This rule is the reason Moore I often have a class of things called arrays The simplest array merely adds a subscript to an address and gives you back an address You can de ne an array by saying CREATE X 100 ALLOT The Iterative Approach in Implementation 193 then saying X Or you can say X X One of the problems that s most frustrating for me is knowing whether it s worth creating a de ning word for a particular data structure Will I have enough instances to justify it I rarely know in advance if I m going to have more than one array So I don t de ne the word ARRAY After I discover I need two arrays the question is marginal If I need three then it s clear Unless they re di erent And odds are they will be di erent You may want it to fetch it for you You may want a byte array or a bit array You may want to do bounds checking or store its current length so you can add things to the end I grit my teeth and say Should I make the byte array into a cell array just to t the data structure into the word I already have available The more com

Download Pdf Manuals

image

Related Search

Related Contents

GE Infrastructure Sensing - GE Measurement & Control  Targus 15.4” Trademark Top Loading 200 Edition Laptop Case  Samsung MW7000J Solo Microwave Oven with Plate Warming. 1.1 Cu.ft. User Manual  Cantus 238 - G. Kisselbach  Classic Cantabile CP-A 320 Digital Piano Bedienungsanleitung  User Manual (LAN) - Reading Horizons  SPIS TREŚCI  dreamGEAR 4 in 1 Case Pack for PS VITA    Untitled  

Copyright © All rights reserved.
Failed to retrieve file