The Department of Computer Science & Engineering
cse@buffalo

CSE 305
Programming Languages
Lecture Notes
Stuart C. Shapiro


Operational Semantics

Operational Semantics describes the meaning of some programming language construct by translating it into a low-level language that is the "machine language" for some virtual machine. We will use operational semantics in this course.

Here, I will describe the virtual machine we will use and its programming language, though there may be modifications later in the course.

Hardware
CPU
  • A set of active registers, including one that can execute instructions, and some that can perform arithmetic, logical, and other operations, as necessary;
  • A program counter (PC) whose value is the address of the word in RAM containing the next instruction to be executed.

Random Access Memory (RAM)
A linear collection of addressable words each big enough to hold an instruction, an address, or a primitive data element (integer, real, boolean, etc.) Mostly used to store instructions. RAM is allocated by the compiler (in the load phase).

Stack
A collection of machine words, of the same size as words in RAM, but arranged as a stack. When the stack is used, it is used during run-time.

Heap
A collection of addressable machine words, of the same size as words in RAM. At the beginning of a program run, they are linked into a linear linked list. When the heap is used, it is used for dynamically-allocated data.

We will assume that the CPU, RAM, the stack, and the heap are always kept separate from each other, and that the addresses of RAM and the heap are distinct.

The Fetch Execute Cycle (the basic machine operation):

     When the program is loaded,
       the address of the first instruction is placed in the PC.
     Repeat {
       Fetch instruction at PC;
       Increment PC;
       Execute the fetched instruction;}
     until the executed instructed is Stop;

LOSL: The Lower-level Operational Semantics Language
For use for the semantics of constructs at and below the level of the statement.
<program> -> {[<label> >] <instruction>}
InstructionSemantics
<variable> push the address, <variable> on the stack
<literal value> push the <literal value> on the stack; use nil for "no value"
fetch replace the top of the stack with the value stored in that location
store store the value on the top of the stack into the location on the 2nd element of the stack, and replace both with the value stored
swap switch the positions of the top 2 elements of the stack
go pop the top element of the stack into the PC
condgo if the 2nd element of the stack is true, put the top element of the stack into the PC; in either case, pop off the top and 2nd elements
pop pop the stack
stop terminate the program
<operator> -> + | - | * | / | = | /= | > | < | >= | <=
  replace the top 2 elements of the stack with the value of (2nd <operator> top)
Instructions may be written left-to-right if no label intervenes.

Example:
The semantics of C's

x = y + (z = 3);
is
x y fetch z 3 store + store pop
How is that obtained?
  1. Start with the statement.
    x = y + (z = 3)
  2. Fully parenthesize it.
    (x = (y + (z = 3)))
  3. Put each operator after its second operand.
    (x (y (z 3 =) +) =)
  4. Delete parentheses. (This is now Polish postfix notation.)
    x y z 3 = + =

    Alternate route to here. Draw expression tree and output by postorder traversal. x y z 3 = + =

  5. Put fetch after a variable whose r-value is wanted.
    x y fetch z 3 = + =
  6. Replace = with store.
    x y fetch z 3 store + store
  7. Append pop because you don't need to retain data on the stack for another operation.
    x y fetch z 3 store + store pop

Trace:
Data:x: 4y: 5z: 6
Program:xyfetchz3store+storepop
PC:^
Stack Top:
------------------------------------------------------
Data:x: 4y: 5z: 6
Program:xyfetchz3store+storepop
PC:^
Stack Top:x
------------------------------------------------------
Data:x: 4y: 5z: 6
Program:xyfetchz3store+storepop
PC:^
Stack Top:yx
------------------------------------------------------
Data:x: 4y: 5z: 6
Program:xyfetchz3store+storepop
PC:^
Stack Top:5x
------------------------------------------------------
Data:x: 4y: 5z: 6
Program:xyfetchz3store+storepop
PC:^
Stack Top:z5x
------------------------------------------------------
Data:x: 4y: 5z: 6
Program:xyfetchz3store+storepop
PC:^
Stack Top:3z5x
------------------------------------------------------
Data:x: 4y: 5z: 3
Program:xyfetchz3store+storepop
PC:^
Stack Top:35x
------------------------------------------------------
Data:x: 4y: 5z: 3
Program:xyfetchz3store+storepop
PC:^
Stack Top:8x
------------------------------------------------------
Data:x: 8y: 5z: 3
Program:xyfetchz3store+storepop
PC:^
Stack Top:8
------------------------------------------------------
Data:x: 8y: 5z: 3
Program:xyfetchz3store+storepop
PC:^
Stack Top:

A LOSL interpreter is available. Here is an example run:

 composer
International Allegro CL Enterprise Edition
8.1 [Linux (x86)] (Aug 21, 2009 10:13)
Copyright (C) 1985-2007, Franz Inc., Oakland, CA, USA.  All Rights Reserved.

This development copy of Allegro CL is licensed to:
   [4549] University at Buffalo

; Autoloading for package "asdf":
;   Fast loading /util/acl81/code/asdf.fasl
;; Optimization settings: safety 1, space 1, speed 1, debug 2.
;; For a complete description of all compiler switches given the
;; current optimization settings evaluate (explain-compiler-settings).
;;---
;; Current reader case mode: :case-sensitive-lower
cl-user(1): :ld /projects/shapiro/CSE305/losl
; Fast loading /projects/shapiro/CSE305/losl.fasl
cl-user(2): :pa losl
losl(3): (run '( x y fetch z 3 store + store pop stop x> 4 y> 5 z> 6) :trace t)
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 0
Stack: nil
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 4
11: 5
12: 6
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 1
Stack: (10)
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 4
11: 5
12: 6
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 2
Stack: (11 10)
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 4
11: 5
12: 6
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 3
Stack: (5 10)
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 4
11: 5
12: 6
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 4
Stack: (12 5 10)
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 4
11: 5
12: 6
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 5
Stack: (3 12 5 10)
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 4
11: 5
12: 6
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 6
Stack: (3 5 10)
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 4
11: 5
12: 3
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 7
Stack: (8 10)
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 4
11: 5
12: 3
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 8
Stack: (8)
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 8
11: 5
12: 3
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 9
Stack: nil
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 8
11: 5
12: 3
============
============
Symbol Table
------------
x: 10
y: 11
z: 12
PC: 10
Stack: nil
RAM
---
0: x
1: y
2: fetch
3: z
4: 3
5: store
6: +
7: store
8: pop
9: stop
10: 8
11: 5
12: 3
============
DONE
losl(4): :ex
; Exiting
<timberlake:Test:1:212>
HOSL: The Higher-level Operational Semantics Language
For use for the semantics of constructs at and above the level of the statement.
<program> -> {[<label>:] <statement>}

<statement> -> goto <label>

              | if <boolean expression> goto <label>

              | <variable> := <expression>

              | <foreign non-control statement>
We will assume that:

Example:
Some programming languages have a for loop like,

for i in min .. max {statements}
where min and max can be any integers such that min <= max,and whose semantics is
i := min loop: statements if i = max goto out i := i + 1 goto loop out:
Those programming languages also have a while loop like,
while <boolean expression> {statements}
whose semantics is
loop: if not <boolean expression> goto out statements goto loop out:
Question: Can every for loop in this language be replaced by a while loop?
What I mean by replacing one control structure by another:
  • without duplicating code as in:
         i := min;
         while (i < max) {
            statements
            i := i +1;
         }
         statements
    
  • without using an additional control structure as in:
         i := min;
         done := false;
         while (i <= max and not done) {
            statements
            if (i = max) {done := true}
            else {i := i +1;}
         }
    

First Previous Next

Copyright © 2003-2010 by Stuart C. Shapiro. All rights reserved.

Last modified: Sat Mar 27 13:44:24 2010
Stuart C. Shapiro <shapiro@cse.buffalo.edu>