CSC 330 Lecture Notes Week 4
Type Systems and Semantics
SymbolTable <>---------------------------------------* SymbolTableEntry
-----------                                            ----------------
parent                                                 String name
entries                                                TreeNode type
level                                                  ----------------
-----------                                            SymbolTableEntry
SymbolTable(int)                                       SymbolTableEntry(
SymbolTable newLevel(FunctionEntry fe, int size)         String name, TreeNode type)
SymbolTableEntry lookup(String name)                   toString
SymbolTableEntry lookupLocal(String name)                   ^
boolean enter(SymbolTableEntry)               |-------------|----|
SymbolTable ascend()                          |                  |
SymbolTable descend(String name)              |                  |
void dump(SymbolTable st)               VariableEntry       FunctionEntry
String toString(int level)              -------------       -------------
                                        boolean isRef       TreeNodeList formals
                                        int memoryLoc       TreeNode body
                                                            SymbolTable scope
program
    var i,j,k: integer;
begin
    i := j + k * 10;
end.
int i,j,k;
void main() {
    i = j + k * 10;
}
PROGRAM
  BEGIN
    VAR
      i
        ;
      j
        ;
      k
      IDENT
        integer
    ASSMNT
      i
      PLUS
        j
        TIMES
          k
          10
      ;
Level 0 Symtab Contents:
  Symbol: i, Type: IDENT, is ref: false, mem loc: 0
  Symbol: k, Type: IDENT, is ref: false, mem loc: 0
  Symbol: j, Type: IDENT, is ref: false, mem loc: 0
vardecl         ::= VAR vars:vs COLON type:t
                        {: RESULT = new TreeNode2(sym.VAR, vs, t);
                           parser.enterVars(vs, t); :}
                ;
vars            ::= var:v
                        {: RESULT = new TreeNodeList(v, null); :}
                | var:v COMMA vars:vs
                        {: RESULT = new TreeNodeList(v, vs); :}
                ;
var             ::= identifier:i
                        {: RESULT = i; :}
                ;
    protected void enterVars(TreeNodeList vars, TreeNode type) {
        TreeNode node;
        TreeNodeList rest;
        boolean done  = false;
        for (node = vars.node, rest = vars.siblings; !done; ) {
            symtab.enter(new VariableEntry(
                (String) (((LeafNode) node).value), type, false, 0));
            if (rest == null) {
                done = true;
            }
            else {
                node = rest.node;
                rest = rest.siblings;
            }
        }
    }
procdecl : ph:prochdr SEMI b:block
               {: RESULT = ph; RESULT.child4 = b;
                  symtab = symtab.newLevel(
                      new FunctionEntry(ph.child1.value, ph.child3,
                          ph.child2, b, null), PROC_SYMTAB_SIZE); :}
procdecl ::= ph:prochdr ';' b:block
                {: RESULT = ph; RESULT.child4 = b;
                   parser.entry.body = b;
                   symtab = symtab.ascend; :}
prochdr  ::= PROC identifier:i L_PAREN formals:fs R_PAREN COLON ident:rt
                {: RESULT = new TreeNode4(sym.PROC, i, fs, rt, null); :}
                   symtab = symtab.newLevel(parser.entry =
                       new FunctionEntry(i.value, rt, fs, null, null)
                               parser.PROC_SYMTAB_SIZE); :}
********************  Running JFlex  ********************
Reading "pascal.jflex"
Constructing NFA : 194 states in NFA
Converting NFA to DFA :
86 states before minimization, 81 states in minimized DFA
Old file "PascalLexer.java" saved as "PascalLexer.java~"
Writing code to "PascalLexer.java"
********************  Running Cup  ********************
Opening files...
Parsing specification from standard input...
Checking specification...
Warning: Terminal "UNY_PLUS" was declared but never used
Warning: Terminal "UNY_MINUS" was declared but never used
Building parse tables...
  Computing non-terminal nullability...
  Computing first sets...
  Building state machine...
  Filling in tables...
*** Shift/Reduce conflict found in state #77
  between ifstmt ::= IF expr THEN stmt (*)
  and     ifstmt ::= IF expr THEN stmt (*) ELSE stmt
  under symbol ELSE
  Resolved in favor of shifting.
  Checking for non-reduced productions...
Writing parser...
Closing files...
------- CUP v0.10k Parser Generation Summary -------
  0 errors and 3 warnings
  41 terminals, 33 non-terminals, and 70 productions declared,
  producing 121 unique parse states.
  2 terminals declared but not used.
  0 non-terminals declared but not used.
  0 productions never reduced.
  1 conflict detected (1 expected).
  Code written to "PascalParser.java", and "sym.java".
---------------------------------------------------- (v0.10k)
********************  Running the Test Program  ********************
PROGRAM
  BEGIN
    VAR
      i
        ;
      j
        ;
      k
      IDENT
        integer
      ;
    VAR
      x
        ;
      y
        ;
      z
      IDENT
        real
    ASSMNT
      i
      10
      ;
    ASSMNT
      j
      20
      ;
Level 0 Symtab Contents:
  Symbol: z, Type: IDENT, is ref: false, mem loc: 0
  Symbol: y, Type: IDENT, is ref: false, mem loc: 0
  Symbol: x, Type: IDENT, is ref: false, mem loc: 0
  Symbol: i, Type: IDENT, is ref: false, mem loc: 0
  Symbol: k, Type: IDENT, is ref: false, mem loc: 0
  Symbol: j, Type: IDENT, is ref: false, mem loc: 0
PascalParserBuggy.java:696: cannot resolve symbol
symbol  : variable child1
location: class TreeNode
                 RESULT = op; op.child1 =
                                ^
PascalParserBuggy.java:697: cannot resolve symbol
symbol  : variable child2
location: class TreeNode
                           e1; op.child2 = e2;
                                 ^
2 errors
          case 42: // expr ::= expr relop expr
gamma = {<i, 154>, <j, 155>}
mu = {}
gamma = {<i, INT, 154>, <j, INT, 155>}
mu = {}
tm = {<i, INT>, <j, INT>}
gamma = {<i, 154>, <j, 155>}
int i,j,k;
float x,y;
int f(float x, string s) {
    boolean b1,b2;
    int[10] a;
    float z;
    // ...
}
int[10] g() {
    int x,y;
    struct {int i; float j;} s;
    float z;
    // ...
}
gamma= {<i, INT, 0>,
<j, INT, 1>
<k, INT, 2>
<x, FLOAT, 3>
<y, FLOAT, 4>
<f, INT,
{<x, FLOAT, 0>, <s, STRING, 1>},
{<b1, BOOLEAN, 2>, <b2, BOOLEAN, 3>,
<a, INT ARRAY[10], 4>, <z, FLOAT, 5>}
<g, INT,
{},
{<x, INT, 0>, <s, INT, 1>,
<s, STRUCT {<i, INT, 0>, <j FLOAT, 1>}, 2>
<z, FLOAT, 3>}
}
sigma = {<x, 1>, <y, 2>, <z, 3>}
gamma = {<x, INT, 0>, <y, INT, 1>, <z, INT, 1>}
mu = {<0, 1>, <1, 2>, <2, 3>}- This, in turn, is an abstract version of a concrete symbol table and memory:
 Level 0 Symtab Contents: Symbol: y, Type: INT, mem loc: 1 Symbol: z, Type: INT, mem loc: 2 Symbol: main, Type: VOID Symbol: x, Type: INT, mem loc: 0 Memory Dump: Location 0: 1 Location 1: 2 Location 2: 3- And all of this traces to the following EJay and Pascal programs (which are equivalent semantically):
 
EJay:
int x,y,z;
void main () {
x = 1;
y = 2;
z = 3;
}
Pascal:
program
var x,y,z: integer;
begin
x := 1;
y := 2;
z := 3;
end.
- So, getting back to state transformations, the meaning of every PL construct can be defined in terms of its state transition effects.
 - E.g., the meaning of assignment can be defined in terms of its affect on a particular program state.
 
- Specifically, the meaning is:
 An assignment statement transforms a pre-assignment state into a post- assignment state where the bound value of the assigned variable is replaced by the value of the expression on the RHS of the assignment.- There's a less bulky notation for the preceding mouthful, coming right up.
 - Consider the preceding state
 sigma = {<x, 1>, <y, 2>, <z, 3>}and the assignment statementy = 2 * z + 3;
- The resulting transformed state is
 sigma = {<x, 1>, <y, 9>, <z, 3>}- The value of 9 comes from computing the RHS expression in the pre-assignment state.
 - In our simplified memory model, the semantics of assigning to a not-yet-bound variable has the effect of adding a binding to the pre-assignment state.
 
- E.g., consider the assignment statement
 given the preceding value of sigmaW = 4- The resulting transformed state is
 sigma = {<x, 1>, <y, 9>, <z, 3>, <w, 4>}- The less bulky notation referred to above uses an overriding union operator, denoted U-bar
 
- U-bar is defined for two sets X and Y as follows:
 X U-bar Y = replace in X all bindings <x, v> whose first member matches a binding <x, w> in Y with <x, w>, and then add to X any additional bindings in Y that are not in X.
- E.g., if
 sigma1 = {<x, 1>, <y, 2>, <z, 3>}andsigma2 = <y, 9>, <w, 4>},thensigma 1 U-bar sigma 2 = {<x, 1>, <y, 9>, <z, 3>, <w, 4>}
M: Assignment, Env, Store -> Env', Store'where e' = e and s' = s such that the value binding for var is replaced with the value of expr, i.e,
M("var = expr", e, s) = e', s'
int x,y,z; z = x + 2*y;