Forth

Concepts of Programming Languages

Sebastian Macke

Rosenheim Technical University

Last lecture

2

Some thoughts about this lecture

3

Prefix notation, Infix notation, and Postfix notation

Infix Notation
Prefix Notation
Postfix Notation

These notations are named as how they use operator in expressions.

4

Infix Notation

a - b + c
+ First: ( 2 + 3 ) * 5 = 5 * 5 = 25
* First:  2 + ( 3 * 5 ) = 2 + 15 = 17
5

Prefix Notation

+ 2 * 3 5 = + 2 15 = 17
* + 2 3 5 = * 5 5 = 25
6

Postfix Notation

2 3 5 * + = 2 15 + = 17
2 3 + 5 * = 5 5 * = 25
7

Examples

a * b + c              =>
c * (a + b)            =>
(3 * a - b) / 4 + c    =>
(0.5 * a * b) / 100    =>
(n + 1) / n            =>
x * (7 * x + 5)        =>
8

Examples

a * b + c              =>  a b * c +
c * (a + b)            =>  c a b + *
(3 * a - b) / 4 + c    =>  3 a * b - 4 / c +
(0.5 * a * b) / 100    =>  0.5 a b * * 100 /
(n + 1) / n            =>  n 1 + n /
x * (7 * x + 5)        =>  x 7 x * 5 + *
9

Postfix via a stack machine

Evaluate

3 9 + 4 6 + *
3  push 3 onto stack
9 push 9 onto stack
  + pop 3 and 9 from stack, add them, push result onto stack
  4 push 4 onto stack
  6 push 6 onto stack
    + pop 4 and 6 from stack, add them, push result onto stack
      * pop 12 and 15 from stack, multiply them, push result onto stack
10

Postfix via a stack machine

Evaluate

16 20 132 3 9 + + + +
11

Stack machines are rather simple to implement

func main() {
    var s stack
    fields := strings.Fields("2 3 5 * +")
    for _, expr := range fields {
        fmt.Println("Parse ", expr)
        switch expr {
        case "+":
            s.Push(s.Pop() + s.Pop())
        case "*":
            s.Push(s.Pop() * s.Pop())
        default:
            v, err := strconv.Atoi(expr)
            if err != nil {
                fmt.Println("Unknown expr", expr)
                return
            }
            s.Push(v)
        }
    }
    println("result:", s.Pop())
}
12

Forth - Easier than Assembler

13

History

14

Forth doesn't show up in this benchmark

15

Features

16

Features

17

Websites to experiment with Forth

Online tutorial

18

Components of the Language

." Hello World!" cr - prints "Hello World" and a newline (carriage return)
.                   - pops the top of the stack and prints its value
.s                  - shows the content of the stack
words               - shows all the available words in the dictionary

e. g.

3 9 + 4 6 + * .
19

Stack operations

As a stack machine, there are a few operations that on manipulating the stack.

20

Constants

constant <name>

The constant <name> word adds a new word into the dictionary which pushes the constant value of <name> onto the stack.

42 constant fourtytwo
fourtytwo .   ( outputs 42 )

What is the output of the following code?

2 constant 3
3 4 + .

Comments

( This is a comment )

"(" and ")" are words in the dictionary. They are used to mark the beginning and end of a comment. The word "(" searches for the next ")" word and jumps to it.

21

Store and fetch variables

variable <name>
variable x    ( equivalent to var x int )
1 x !         ( equivalent to x = 1 )
x @ .         ( equivalent to print(x) )
x @ 1 + x !   ( equivalent to x = x + 1 )
22

Functions: Adding a word

: <name> <body> ;
: square dup * ;
2 square .  ( outputs 4 )

2 is placed on the stack, duped, then the result is multiplied by itself.

23

Conditionals

false invert .  ( outputs true )
1 2 < .         ( outputs true )
1 2 = .         ( outputs false )
1 2 and .       ( outputs true )

other words: <, >, =, <>, <=, >=, 0=, and, or, xor

24

Control Structures

25

If then else

Absolute value:

: absolute  ( returns the absolute value )
  dup 0 < if -1  *  then ;

-100 absolute . ( outputs 100 )

Boolean output:

: .bool ( prints the boolean )
  -1 = if ." true" else ." false" then ;

false .bool
26

do loop

do loop copies these two values onto the call stack

: countdown  ( count down from ten to zero )
  11 0 do
         10 i - .
       loop ;
countdown
27

begin until

begin <body> <condition> until

begin <condition> while <body> repeat

: countdown
  0
  begin
      dup 10 swap - . cr
      1 +
  dup 10 = until ;

  countdown
28

strings

s" <string>"
: printEachChar
0 do    ( the length of the string is already on the stack )
    dup i +
    c@ emit cr
loop
;

s" This is a string"
2dup type               ( outputs the string )
printEachChar           ( outputs each character )
29

Exercise

variable a   1 a !   ( a = 1 )
variable b   2 b !   ( b = 2 )
a b swapv
a @ .  ( outputs 2 )
b @ .  ( outputs 1 )
30

Arrays

array with initialization

create [myarray] 10 , 20 , 30 ,
[myarray] @ .  ( outputs 10 )
[myarray] cell+ @ .  ( outputs 20 )
[myarray] cell+ cell + @ .  ( outputs 30 )
[myarray] 2 cells + @ .  ( outputs 30 )

alloc 12 bytes

create [myarray] 12 allot
[myarray] 4 + c@  ( access byte number 4 )
31

Extending Forth

Forth has a lot of built-in words. But most of them are just made of other words.

: variable   create  0 , ;
: constant   create  ,  DOES> @ ;

Only 215 lines of C code and 2800 lines of bootstrap Forth code.

32

Summary

33

Java bytecode is actually a stack machine

public int Add(int a, int b, int c) {
    return a + b + c;
}

compiles into

public int Add(int, int, int);
  Code:
     0: iload_1  // push parameter 1 onto the stack
     1: iload_2  // push parameter 2 onto the stack
     2: iadd     // pop the two parameters, add them, and push the result
     3: iload_3  // push parameter 3 onto the stack
     4: iadd     // pop the two parameters, add them, and push the result
     5: ireturn  // return the result
34

Exercise: Write a calculator

35

Lexer and Parser and Interpreter

Lexer

Parser

Interpreter

36

Shunting Yard algorithm - Conversion from Infix to Postfix

Infix: ( ( ( A + B ) * C ) - ( ( D + E ) / F ) )
Postfix: A B + C * D E + F / -

Operand order does not change!
Operators are in order of evaluation!

Algorithm:

- Initialize a stack for operators and output list
- Split the input string into a list of tokens
- For each token in the token list:
  - If the token is a number, push it onto the output list
  - If the token is an operator:
      - Pop operators from the stack and push them onto the output list until you find an operator
        with lower precedence
      - Push the current operator onto the stack
37

Shunting Yard algorithm - Conversion from Infix to Postfix

1 + 2 * 3 + 4
↑

stack: <empty>
output: []
38

Shunting Yard algorithm - Conversion from Infix to Postfix

+ 2 * 3 + 4
↑

stack: <empty>
output: [1]
39

Shunting Yard algorithm - Conversion from Infix to Postfix

2 * 3 + 4
↑

stack: [+]
output: [1]
40

Shunting Yard algorithm - Conversion from Infix to Postfix

* 3 + 4
↑

stack: [+]
output: [1 2]
41

Shunting Yard algorithm - Conversion from Infix to Postfix

3 + 4
↑

stack: [+ *]
output: [1 2]
42

Shunting Yard algorithm - Conversion from Infix to Postfix

+ 4
↑

stack: [+ *]
output: [1 2 3]
43

Shunting Yard algorithm - Conversion from Infix to Postfix

4
↑

stack: [+]
output: [1 2 3 * +]
44

Shunting Yard algorithm - Conversion from Infix to Postfix

stack: [+]
output: [1 2 3 * + 4]
45

Shunting Yard algorithm - Conversion from Infix to Postfix

stack: []
output: [1 2 3 * + 4 +]
46

Shunting Yard algorithm - Conversion from Infix to Postfix

( ( ( A + B ) * ( C - E ) ) / ( F + G ) )
↑

stack: <empty>
output: []
47

Shunting Yard algorithm - Conversion from Infix to Postfix

( ( A + B ) * ( C - E ) ) / ( F + G ) )
↑

stack: (
output: []
48

Shunting Yard algorithm - Conversion from Infix to Postfix

( A + B ) * ( C - E ) ) / ( F + G ) )
↑

stack: ( (
output: []
49

Shunting Yard algorithm - Conversion from Infix to Postfix

A + B ) * ( C - E ) ) / ( F + G ) )
↑

stack: ( ( (
output: []
50

Shunting Yard algorithm - Conversion from Infix to Postfix

+ B ) * ( C - E ) ) / ( F + G ) )
↑

stack: ( ( (
output: [A]
51

Shunting Yard algorithm - Conversion from Infix to Postfix

B ) * ( C - E ) ) / ( F + G ) )
↑

stack: ( ( ( +
output: [A]
52

Shunting Yard algorithm - Conversion from Infix to Postfix

) * ( C - E ) ) / ( F + G ) )
↑

stack: ( ( ( +
output: [A B]
53

Shunting Yard algorithm - Conversion from Infix to Postfix

* ( C - E ) ) / ( F + G ) )
↑

stack: ( (
output: [A B +]
54

Shunting Yard algorithm - Conversion from Infix to Postfix

( C - E ) ) / ( F + G ) )
↑

stack: ( ( *
output: [A B +]
55

Shunting Yard algorithm - Conversion from Infix to Postfix

C - E ) ) / ( F + G ) )
↑

stack: ( ( * (
output: [A B +]
56

Shunting Yard algorithm - Conversion from Infix to Postfix

- E ) ) / ( F + G ) )
↑

stack: ( ( * (
output: [A B + C]
57

Shunting Yard algorithm - Conversion from Infix to Postfix

E ) ) / ( F + G ) )
↑

stack: ( ( * ( -
output: [A B + C]
58

Shunting Yard algorithm - Conversion from Infix to Postfix

) ) / ( F + G ) )
↑

stack: ( ( * ( -
output: [A B + C E]
59

Shunting Yard algorithm - Conversion from Infix to Postfix

) / ( F + G ) )
↑

stack: ( ( *
output: [A B + C E -]
60

Shunting Yard algorithm - Conversion from Infix to Postfix

/ ( F + G ) )
↑

stack: (
output: [A B + C E - *]
61

Shunting Yard algorithm - Conversion from Infix to Postfix

( F + G ) )
↑

stack: ( /
output: [A B + C E - *]
62

Shunting Yard algorithm - Conversion from Infix to Postfix

F + G ) )
↑

stack: ( / (
output: [A B + C E - *]
63

Shunting Yard algorithm - Conversion from Infix to Postfix

+ G ) )
↑

stack: ( / (
output: [A B + C E - * F]
64

Shunting Yard algorithm - Conversion from Infix to Postfix

G ) )
↑

stack: ( / ( +
output: [A B + C E - * F]
65

Shunting Yard algorithm - Conversion from Infix to Postfix

) )
↑

stack: ( / ( +
output: [A B + C E - * F G]
66

Shunting Yard algorithm - Conversion from Infix to Postfix

)
↑

stack: ( /
output: [A B + C E - * F G +]
67

Shunting Yard algorithm - Conversion from Infix to Postfix

↑

stack: <empty>
output: [A B + C E - * F G + /]
68

Exercise

69

Last lecture

70

Thank you

Sebastian Macke

Rosenheim Technical University

Use the left and right arrow keys or click the left and right edges of the page to navigate between slides.
(Press 'H' or navigate to hide this message.)