yet_another_webdev(blog)           2023-12-15           yet_another_webdev(blog)

PROJECT
       Starting FORTH

POST
       Chapter 02 - How to get results

DESCRIPTION
       Forth arithmetics and stack manipulation words




FORTH Arithmetic -- Calculator Style
       Here are four simples integer-arithmetic operators in FORHT:

+      (n1 n2 -- sum)            Adds.                    pronounced "plus"

-      (n1 n2 -- diff)           Subtracts (n1 - n2).     pronounced "minus"

*      (n1 n2 -- prod)           Multiplies.              pronounced "star"

/      (n1 n2 -- qout)           Divides (n1/n2).         pronounced "slash"
       

       In  the  first  chapter, we learned that we can add two number by putting
       them both on the stack, then  executing  the  word  +   ,  then  finnaly
       executing the word . to get the result printed at our terminal.

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

17 5 + . 22    ok
Stack<10>
       

       We can use thie method with all of FORTH's arithmetic operators. In other
       words,  we  can use FORTH like a calculator to get answers, event without
       writing a "program". Try a multiplication problem:

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

7 8 * . 56    ok
Stack<10>
       

       By now we've see that the operator comes after the numbers. In  the  case
       of  subtraction  and division, though, we must also consider the order of
       numbers ("7 - 4" is not the same as "4 - 7").

       Just remember this rule: To convert to postfix, simple move the  operator
       to the end of the expression:

Infix                    Postfix

3 + 4                    3 4 +

500 - 300           500 300 -

6 X 5                    6 5 *

20 /  4                  20 4 /

       

       So to do this subtraction problem: 7 - 4 = 

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

7 4 - . 3    ok
Stack<10>
       

       Example of division:

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

20 4 - . 5    ok
Stack<10>
       

       What do you do if you have more that one operator in an expression, like:
       4  + (17 * 12) you ask? Let's take it step-by-step: the parentheses tell
       you to first multiply 17 by 12, then add 4. So in FORTH you would write:

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

17 12 * 4 + . 208    ok
Stack<10>
       

       17 and 12 go onto the stack.  * miltiplies them and returns  the  result
       to  the stack. Then the 4 goes onto the stack, on top of 204. + adds the
       two numbers returning 208 to the stack.

       No there's an interesting problem: (3 + 9) * (4 + 6) 

       To solve it  we have to add 3 to 9 first, then add 4 to 6,  then  finally
       multiply the two sums. In FORTH, we can write:

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

3 9 + 4 6 + * . 120    ok
Stack<10>
       

For Adventuresome Newcomers Sitting at a Terminal
       If  you're  on of those people who likes to fool around and figure things
       out for themselves  without  reading  the  book,  then  you're  bount  to
       discover  a  copule  of  weird  things.  First off, as we told you, these
       operators are integer operators .  That not only means that you can't  do
       calculations with decimal values, like

10.00 2.25 +
       

       if also means that you van only get integer results, as in

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

21 4 / . 5    ok
Stack<10>
       

       Another thing is that if you try to multiply:

10000 10 *
       

       or  some  suck large numbers, you'll get a crazy answer. So we're telling
       you up front that with the operators introduced so far and  with  .   to
       print  the results, you can't have any numbers that are higher than 32767
       and lower than -32768. Numbers within  this  range  are  called  "single-
       lenght signed numbers".

       Notice,  in  the  list  of  FORTH words a few pages back, the letter "n",
       which stands for "number". Since FORTH uses  single-length  numbers  more
       often than other types of numbers, the "n" signifies that the number must
       be  single-length.  And  yes,  there are other operators that extend this
       range ("double-length" operatores, which are indicated by "d").

   pForth integers
$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

: 2^10   1024 ;    ok
Stack<10>
       

       Define the word 2^10 to put 1024 (which is 2 to the 10th  power)  on  the
       stack.

: 2^62   2^10 2^10 2^10 2^10 2^10 2^10 2 2 * * * * * * * ;    ok
Stack<10>
       

       2^62 is 1 followed by 62 0s.

: 2^62-1   2^62 1 - ;    ok
Stack<10>
       

       Subtracting 1 from 2^62 is 0 followed by 62 1s.

: 2^63-1   2^62 2^62-1 + ;    ok
Stack<10>
       

       Adding the two numbers results in 2^63 - 1 which is 0 followed by 63 1s.

2^63-1    ok
Stack<10> 9223372036854775807
1 +    ok
Stack<10> -9223372036854775808
       

       Adding  1  results in 2^63 which is 1 followed by 63 zeroes. The negative
       integer on the stack is the minimum value for a signed 64-bit integer.

FORTH Arithmetic -- Definition Style
       In chpater #1 we saw that we could define new words in terms  of  numbers
       and  other  pre-defined  words. Let's explore some further possibilities,
       usign some of our newly-learned math operators.

       Let's say we want to convert various measurements to inches. We know that
       1 yard = 36 inches and 1 foot = 12 inches so we can  define  these  two
       words  where  the names symbolize "yards-to-inches" and "feet-to-inches".
       Here' what they do:

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

: YARDS>IN   36 * ;    ok
Stack<10>
: FT>IN   12 * ;    ok
Stack<10>
10 YARDS>IN . 360    ok
Stack<10>
2 FT>IN . 24    ok
Stack<10>
       

       If we always want our result to be in inches, we can do the following:

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

: YARDS 36 * ;    ok
Stack<10>
: FEET   12 * ;    ok
Stack<10>
: INCHES ;    ok
Stack<10>
10 YARDS 2 FEET 9 INCHES + + . 393    ok
Stack<10>
       

       Notice that the word INCHES doesn't do anything except remind the  human
       user  what the 9 is there for. If we really want to get fancy, we can add
       these three definitions:

: YARD YARDS ;    ok
Stack<10>
: FOOT   FEET ;    ok
Stack<10>
: INCH ;    ok
Stack<10>
1 YARD 2 FEET 1 INCH + + . 61    ok
Stack<10>
2 YARDS 1 FOOT + . 84    ok
Stack<10>
       

       So far we have only defined words whose definitions contain a single math
       operator. But it's perfectly possible to  put  many  operators  inside  a
       definition, if that's what you need to do.

       Let's  say  we  want  a word that computes the sum of five numbers on the
       stack. A few pages back we summed five numbers like this: 17 20 + 132 + 3
       + 9 + . 181    ok But we ca also enter 17 20 132 3 9 + + + + . 181    ok
       We get the same answer, even though we've clustered all the numbers into
       one group and  all  operators  into  another  group.  We  can  write  out
       definition like this:

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

: 5#SUM   + + + + ;    ok
Stack<10>
17 20 132 3 9 5#SUM . 181    ok
Stack<10>
       

       If  we  were  going to keep 5#SUM for future use, we could enter it into
       our ever-growing glossary, along  with  a  note  that  it  "expects  five
       arguments" on the stack, which it will add together.

       Here's  another  equation to write a definition for: (a + b) * c Thus we
       would write the following definition, this will work as long as  we  make
       sure to push the numbers to the stack in the proper order:

: SOLUTION  + * ;
c a b SOLUTION
       

The Division Operators
       The  word  /  is FORTH'S simplest division operator. Slash supplies only
       the quotient; any remainder is lost:

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

22 4 / . 5    ok
Stack<10>
       

       If you're thinking of a pocket calculator's per-cent operator, then  five
       is not the full answers.

       But  /   is  only one of several division operators supplied by FORTH to
       give you the flexability to tell the computer exactly what you want it to
       do.

       For example, let's say you want to solve this problem: "How  many  dollar
       bills can I get in exchange for 22 quarters". The real answer, of course,
       is  exactly  5, not 5.5. A computerized money changer, for example, would
       not know howto give you 5.5 dollar bills.

       Here are two more FORTH division operators:

/MOD   (u1 u2 -- u-rem u-quot)   Divides. Returns the     pronounced "slash-mod"
                                 remainder and the
                                 quotient.

MOD    (u1 u2 -- u-rem)          Returns the remainder    pronounced "mod"
                                 from division.
       

       The "u" stands for "unsigned". We'll see what this means in  the  chapter
       on  cumputer  numbers. For now though, it means that the numbers can't be
       negative.

       gives both the remainder and quotient; MOD  gives  the  remainder  only.
       (For  /MOD , the stack notation in the table indicates that the quotient
       will  be  on the top of the stack, and the remainder below. Remember, the
       rightmost represents the topmost).

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

22 4 /MOD . . 5 2    ok
Stack<10>
: QUARTERS   4 /MOD . ." ONES AND " . ." QUARTERS " ;    ok
Stack<10>
22 QUARTERS 5 ONES AND 2 QUARTERS    ok
Stack<10>
       

Stack Maneuvers
       If you worked Prob. 6 int the last set, you  discovered  that  the  infix
       equation  (a  -  b)/c cannot be solved with a definition unless there is
       some way to rearrange values on the stack.

       Well, there is a way: by using a  "stack  manipulation  operator"  called
       SWAP 

       The word SWAP is defined to switch the order of the top two stack items.
       As  with  other  stack manipulation operators, you can test SWAP at your
       terminal in "calculator style"; that is, it doesn't have to be  contained
       within a definition. Using SWAP we can define a solution for (a - b)/c 

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

1 2 . . 2 1    ok
Stack<10>
1 2 SWAP . . 1 2    ok
Stack<10>
: SOLVE6b   - SWAP / ;    ok
Stack<10>
2 10 4 SOLVE6b . 3    ok
Stack<10>
       

       Here is a list of several stack manipulation operators, including SWAP .

SWAP   (n1 n2 -- n2 n1)          Reverse the top two      pronounced "swap"
                                 stack items.

DUP    (n -- n n)                Duplicates the top       pronounced "dupe"
                                 stack items.

OVER   (n1 n2 -- n1 n2 n1)       Makes a copy of the      pronounced "over"
                                 second item and pushes
                                 it on the top.

ROT    (n1 n2 n3 -- n2 n3 n1)    Rotates the third item   pronounced "rote"
                                 to the top.

DROP   (n -- )                   Discards the top stack   pronounced "drop"
                                 item.
       

   DUP operator
       the  next  stack manipulation operator on the list, DUP , simply makes a
       second copy (duplicated) of the top stack item. For example, if  we  have
       "a" on the stack, we can compute a^2 as follows

$ forth
PForth V2.0.1, LE/64, built May 12 2023 10:51:31 (static)

3    ok
Stack<10> 3
DUP * . 9    ok
       

   OVER operator
       Now somebody tells you to evaluate the expression: a * (a + b) given the
       following  stack  order: (a b -- ) But, you say, I'm going to need a new
       manipulation operator: I want two copies of the "a", and the "a" is under
       the "b". Here's the word you need: OVER . OVER simply makes a  copy  of
       the  "a" and leapfrogss it over the "b": (a b -- a b a) . The expression
       a * (a + b) can be solved with: OVER + * 

       When writing equations in FORTH, it's best to "factor  them  out"  firts.
       For  example,  if  somebody  asks  you  to evaluate: a^2 + a*b is FORTH,
       you'll find it quite complicated (and maybe even  impossible)  using  the
       words we've introduced so for ... unless you factor out the expression to
       read: a * (a + b) which is the expression we just evalutated.

   ROT operator
       The  fourth  stack  manipulator  on the list is ROT (pronounced "rote"),
       which is short for "rotate". Here's what ROT does to the top three stack
       values: (a b c -- b c a) 

       For example, if we need to evaluate the expression: ab - bc   we  should
       first  factor  out the "b"s: b * (a - c) Now if our starting-stack order
       is this: (c b a -- ) we can use: ROT - * 

   DROP operator
       The final stack manipulation operator on the list is DROP . All it  does
       is discard the top stack value.

   A Handy Hint
       Use  the  word .S for a non-destructive stack print. This will print the
       state of the current stack without removing the values from it.

Playing Doubles
       The next four stack manipulation operators should look vaguely familiar:

2SWAP  (d1 d2 -- d2 d1)          Reverse the top two      pronounced "two-swap"
                                 pairs of numbers.

2DUP   (d -- d d)                Duplicates the top       pronounced "two-dupe"
                                 pair of numbers.

2OVER  (d1 d2 -- d1 d2 d1)       Makes a copy of the      pronounced "two-over"
                                 second pair of numbers
                                 and pushes it on top.

2DROP  (d -- )                   Discards the top pair    pronounced "two-drop"
                                 of numbers.
       

       the prefix "2" indicates that these stack manipulation  operators  handle
       numbers  in  pairs. The letter "d" in the stack effects column stands for
       "double". "Double" has a special significance that we will  discuss  when
       we discess "n" and "u".

       The  "2"-manipulators  listed above are so straightforward, we won't even
       bore you with examples.

       One more thing: there are still some stack manipulators we haven't talked
       about yet, so don't go crazy by trying too much  fancy  footwork  on  the
       stack.

FORTH words covered in this chpater:
+      (n1 n2 -- sum)            Adds.                    pronounced "plus"

-      (n1 n2 -- diff)           Subtracts (n1 - n2).     pronounced "minus"

*      (n1 n2 -- prod)           Multiplies.              pronounced "star"

/      (n1 n2 -- qout)           Divides (n1/n2).         pronounced "slash"

/MOD   (u1 u2 -- u-rem u-quot)   Divides. Returns the     pronounced "slash-mod"
                                 remainder and the
                                 quotient.

MOD    (u1 u2 -- u-rem)          Returns the remainder    pronounced "mod"
                                 from division.

SWAP   (n1 n2 -- n2 n1)          Reverse the top two      pronounced "swap"
                                 stack items.

DUP    (n -- n n)                Duplicates the top       pronounced "dupe"
                                 stack items.

OVER   (n1 n2 -- n1 n2 n1)       Makes a copy of the      pronounced "over"
                                 second item and pushes
                                 it on the top.

ROT    (n1 n2 n3 -- n2 n3 n1)    Rotates the third item   pronounced "rote"
                                 to the top.

DROP   (n -- )                   Discards the top stack   pronounced "drop"
                                 item.

2SWAP  (d1 d2 -- d2 d1)          Reverse the top two      pronounced "two-swap"
                                 pairs of numbers.

2DUP   (d -- d d)                Duplicates the top       pronounced "two-dupe"
                                 pair of numbers.

2OVER  (d1 d2 -- d1 d2 d1)       Makes a copy of the      pronounced "two-over"
                                 second pair of numbers
                                 and pushes it on top.

2DROP  (d -- )                   Discards the top pair    pronounced "two-drop"
                                 of numbers.
       

Review of Terms
   Double-length numbers
       integers  which  encompass  a range of over -2 billion to +2 billion (and
       which we'll introduce officially in Chapter 7).

   Single-length numbers
       integers which fall within the rane of -32768 to +32767: the only numbers
       which are valid as the arguments or results of any of the operators we've
       discussed so far. (This seemingly arbitrary  range  comes  from  the  way
       computers are designed, as we'll see later on.)

toolsV2                                                 yet_another_webdev(blog)