CSE 131B – Compiler Construction II
description
Transcript of CSE 131B – Compiler Construction II
CSE 131B – Compiler Construction II
Discussion 4: Project 1
1/31/2007
Overview
Arrays
Pointers
Records
Topics/Questions you may have
Array Declaration
Syntax:VAR List1 : ARRAY Index OF Type;
VAR List2 : ARRAY Index OF ARRAY Index OF Type;
What to check in the declaration: Index must be an INTEGER Index > 0 (known at compile time ConstSTO)
Array Usage
Syntax:myArray[index];
myArray[index][index];(myArray[index])[index]; (* notice how this still
works *)
What to check: myArray must be a variable (VarSTO) and of
ArrayType index must be equivalent to INTEGER
a0
Multidimensional Arrays
b0
Given:
VAR x : ARRAY 4 OF ARRAY 3 OF INTEGER;
b1 b2
a1
b0 b1 b2
a2
b0 b1 b2
a3
b0 b1 b2
Because of this, the following is valid:
TYPE myArr = ARRAY 3 OF INTEGER;
VAR x : ARRAY 4 OF myArr;
VAR y : myArr;
y := x[2];
Remember:
The result of an array element is ADDRESSIBLE
Implementation?
How can one encapsulate the information from the array declaration for later use?
Remember the Type Hierarchy: One possibility is to store information such as
elementType, dimSize. In order to do this, you have to add these fields
into the ArrayType definition and provide ways to set and read the information from them.
Further Analysis of Arrays
VAR myArray : ARRAY 20 OF INTEGER;VAR x, y : INTEGER;
BEGINmyArray[x] := myArray[4]; myArray[x+2-y] := 15; myArray := 10; (* error, not assignment compatible *)
END.
Pointer Declaration
Syntax:VAR x : POINTER TO Type;
TYPE ptr = POINTER TO Type;VAR y : ptr;
What to check in the declaration: Type must be a RECORD
Pointer Usage
Syntax:ptr. (* pointer dereference, like “ *ptr ” in C *) -- T_DOT
NEW ptr;
What to check: For a dereference (check 15), only things that are variables
of pointer to records can be dereferenced. For New (check 18), you must check to see if the
argument is also of PointerType.
Further Analysis of Pointers
TYPE ptr = POINTER TO RECORD a : REAL; END;VAR x, y : ptr;VAR z : REAL;
BEGINNEW x; (* like malloc, no actual allocation in Proj 1 *)x.a := 7; (* assign value of 7 into where x’s a field *)y := x; (* assign y to point where x points *)z := y.a; (* get y’s a field and put it into z *)
END.Remember, no actual assignment of data here – that’s the next proj
Record Declaration
Syntax (think of C structs):VAR r : POINTER TO RECORD
a, b : INTEGER;b : REAL;
END;
What to check in the declaration: Check for duplicate fields (field r.b in this case) If a field is duplicated multiple times, an error is reported
for each duplicate instance.
Record Usage
Syntax:myRec.myField
What to check: myRec must be a VarSTO of some pointer to a record myRec must contain the field (myField, in this case) After checking, your result may be a VarSTO of the type
of myField, since you want something ADDRESSIBLE
Further Analysis of Records
TYPE rec = RECORD a, b : REAL; END;VAR myRec : POINTER TO rec;
BEGINmyRec := myRec; (* fine – assignable pointers *)myRec.b := 3.6; (* assign 3.6 into b field *)myRec.a := myRec.b; (* assign b field into a field *)
END.
Recursive Records
Recursive types are easily possible, since there will always be at least one POINTER type in a cycle.
When you encounter a Type declaration, you want that Type to be in scope immediately, even if you are not finished with the Type declaration (ie, it isn’t fully complete, but can still be referenced from the Symbol Table).
Recursive Record Examples
TYPE linkedList = POINTER TO RECORD
a : INTEGER;
next : linkedList;
END;
TYPE rec = RECORD
a : POINTER to rec;
END;
Recursive Records
Think more about this – it is an important concept (not just for this class).
Some ideas: Put a partially complete/empty TypeAliasSTO
onto the SymTab before the actual type is know. Have a stack of items that need to be re-checked
at the end of the TypeDecl, and assume everything is fine until you reach the end of the declaration, then go through and re-check based on the stack.
Refresher on Type Equivalence
Remember the following rules: All basic types use structural equivalence Arrays and Records use strict name equivalence Pointers use whatever the type they point to Type aliases use loose name equivalence
Illustrative Example
TYPE int = INTEGER;TYPE month = INTEGER;VAR i : int;VAR m : month;VAR r : REAL;TYPE rec = POINTER TO RECORD a : REAL; END;VAR r1 : POINTER TO RECORD a : REAL; END;VAR r2 : rec;FUNCTION f(VAR a : rec); (* ... *) END f;FUNCTION ff(a : rec); (* … *) END ff;VAR a1 : ARRAY 5 OF REAL;VAR a2 : ARRAY 5 OF REAL;FUNCTION g(a : ARRAY 5 OF REAL); (* ... *) END
g;VAR p4 : POINTER TO RECORD a : REAL; END;
BEGIN i := m; (* okay, loose name equivalent *) i := r; (* error, not assignable *) r := i; (* okay, assignable *) f(r2); (* okay, same type *) f(r1); (* error, not strict name equivalent *) ff(r2); (* okay, same type *) ff(r1); (* error, not strict name equivalent *) g(a1); (* error, not strict name equivalent
*) gg(a1); (* error, not strict name equivalent
*) a1 := a1; (* okay, strict name equivalent *) a1 := a2; (* error, not strict name equivalent
*) r1 := r1; (* okay, strict name equivalent *) r2 := p4; (* error, not strict name equivalent
*) END.
For more info, see Appendix A of the Oberon spec
What to do Next!
1. Finish up Project 1!
2. Write more test programs to verify correctness.
3. Come to lab hours and ask questions.
Topics/Questions you may have
Anything else you would like me to go over now?
Anything in particular you would like to see next week?