Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Conklin E.K.Forth programmer's handbook.2000.pdf
Скачиваний:
321
Добавлен:
23.08.2013
Размер:
2.04 Mб
Скачать

 

 

Forth Programmer’s Handbook

 

lowing BEGIN.

 

UNTIL

( x — )

Core

 

At compile time, compile a conditional backward branch to the location on the

 

control-flow stack (usually left there by BEGIN). At run time, if x is zero, take

 

the backwards branch; otherwise, continue execution beyond the UNTIL.

WHILE

( x — )

Core

At compile time, place a new unresolved forward reference origin on the control stack, under the topmost item (which is usually a destination left by BEGIN). At run time, if x is zero, take the forward branch to the destination that will have been supplied (e.g., by REPEAT) to resolve WHILE’s origin; otherwise, continue execution beyond the WHILE.

References BEGIN UNTIL for the Assembler word list, Section 5.8 Logic operations, Section 2.2.2

Control-flow stack, Section 4.4.2

2.5.2 Counting (Finite) Loops

Forth provides words to allow looping in a manner similar to most other highlevel languages. The words associated with counting loops are given in the glossary at the end of this section.

The possible forms of a counting loop in Forth are as follows:

<limit> <initial> DO <words to repeat> LOOP

or <limit> <initial> DO <words to repeat> <value> +LOOP

A DO LOOP increments by one and always runs in the positive direction. A DO +LOOP increments by the given integer value, which may be positive or negative.

To illustrate the use of loops, the word SUM is defined to sum the values of the integers 1 to 100 and to leave the result on the stack:

: SUM

0 101 1 DO I + LOOP ;

The limit value is specified as 101, not 100, because the loop index is incre-

Forth Fundamentals 63

Forth Programmer’s Handbook

mented before the termination test, and the loop will terminate when the index is equal to the limit. The word I returns the current loop index on the stack.

Loops may be nested to any depth, limited only by the capacity of the return stack. At each point in a nested loop, the word I returns the index of the innermost active loop, and the word J returns the index of the next outer loop.

+LOOP allows descending index values to be used. When an index value is descending, however, the loop is terminated when the limit is passed (not merely reached). When the index value is ascending (i.e., the increment value specified for +LOOP is positive), the loop terminates when the index value is reached, as for LOOP.

To illustrate the use of +LOOP with descending index values, the following definition is equivalent to the first definition of SUM:

: SUM

0 1 100 DO I + -1 +LOOP ;

Here the initial value of the index is 100 and the final value is 1.

Loop parameters usually are kept on the return stack (see glossary entry for DO, below), and are not affected by structures other than DO LOOP.

Because loop parameters are checked at the end of the loop, any loop will always be executed at least once, regardless of the initial values of the parameters. Because a DO loop with equal input parameters will execute not once but a very large number of times—equal to the largest possible single-cell unsigned number—the word ?DO should be used in preference to DO if the loop parameters are being calculated and might be equal (e.g., both zero).

Glossary

 

 

DO

( n1 n2 — )

Core

 

Establish the loop parameters. This word expects the initial loop index n2 on top

 

of the stack, with the limit value n1 beneath it. These values are removed from

 

the stack and stored elsewhere, usually on the return stack, when DO is executed.

?DO

( n1 n2 — )

Core Ext

Like DO, but check whether the limit value and initial loop index are equal. If they are, continue execution after the LOOP; otherwise, set up the loop values

64 Forth Fundamentals

 

Forth Programmer’s Handbook

 

and continue execution immediately following ?DO. This word should be used

 

in preference to DO whenever the parameters may be equal. “question-do”

 

LOOP

( — )

Core

 

Increment the index value by one and compare it with the limit value. If the

 

index value is equal to the limit value, the loop is terminated, the parameters

 

are discarded, and execution resumes with the next word. Otherwise, control

 

returns to the word that follows the DO or ?DO that opened the loop.

 

+LOOP

( n — )

Core

 

Like LOOP, but increment the index by the specified signed value n. After

 

incrementing, if the index crossed the boundary between the loop limit minus

 

one and the loop limit, the loop is terminated as with LOOP. “plus-loop”

 

I

( — n )

Core

 

Push a copy of the current value of the index onto the data stack. This word

 

may only be used for this purpose within the definition that opened the loop,

 

not in definitions the loop invokes, because nested colon definitions may cause

 

a return address to be put on the stack on top of the loop index. If the code in

 

the body of the loop places any values explicitly on the return stack, they must

 

be removed before I is executed; otherwise, an erroneous index value may

 

result. On many systems, I is identical to R@, but this may not be relied on

 

because some systems calculate I from other values kept on the return stack.

J

( — n )

Core

 

Push a copy of the next-outer loop index onto the data stack. When two DO

 

LOOPs are nested, this obtains the value of the outer index from inside the inner

 

loop. On many systems, J is kept directly on the return stack; but in others, J is

 

a calculated value, so you should not attempt to obtain the outer loop index

 

except by using J.

 

LEAVE

( — )

Core

 

Discard loop parameters and continue execution immediately following the

 

innermost LOOP or +LOOP containing this LEAVE.

 

UNLOOP

( — )

Core

 

Discard the loop parameters for the current nesting level. This word is not

 

needed when a DO LOOP completes normally, but it is required before leav-

 

ing a definition by calling EXIT. One UNLOOP call for each level of loop nest-

 

ing is required before leaving a definition.

 

Forth Fundamentals 65

Forth Programmer’s Handbook

References EXIT and un-nesting definitions, Section 2.5.5

Control-flow stack, Section 4.4.2

2.5.3 Conditionals

These words allow conditional execution of words within a single definition. They may only appear within a definition and may not be used in interpretive text or in text executed by direct entry from a terminal. There are similar conditional words that can be used interpretively (see Section 4.1.6).

The general usage of these words is:

<test value> IF <true clause> ELSE <false clause> THEN or <test value> IF <true clause> THEN

When IF is executed, the item on top of the stack is removed and examined. If test value is true (non-zero), execution continues with the words after IF (the true clause). If test value is false (zero), execution resumes with the words after ELSE (the false clause) or, if ELSE is not present, with the words after THEN.

Execution of the true clause terminates with the word ELSE, if present, and resumes with the word after THEN.

Both the true clause and the false clause may be any group of previously defined Forth words. Either clause may contain DO LOOPs, BEGIN UNTIL loops, and/or other IF ELSE THEN structures, so long as the entire structure is contained within the clause. Similarly, one IF structure may be nested inside another structure of any kind, so long as the THEN that terminates the structure appears within the same clause.

Glossary

 

 

ELSE

( — )

Core

At compile time, originate the true clause branch and resolve the false clause branch. It is assumed that there is a branch origin on the control stack, usually left there by IF. Provide the location following ELSE as the destination address for the forward conditional branch originated by IF. Place a new forward reference origin on the control stack, marking the beginning of an unconditional

66 Forth Fundamentals

Соседние файлы в предмете Электротехника