These lecture notes are my own notes that I made in order to use during the lecture, and it is approximately what I will be saying in the lecture. These notes may be brief, incomplete and hard to understand, not to mention in the wrong language, and they do not replace the lecture or the book, but there is no reason to keep them secret if someone wants to look at them.
Idag: Datatyper. Typsystem. Typkontroll.
int main() { int i; *i = 2; // invalid type argument of `unary *' break; // break statement not within loop or switch e: e: // duplicate label `e' return 0; }
Type tree:
-> / \ x pointer / \ \ char char integerType DAG:
-> / \ x pointer || \ char integer
cdecl> declare a as pointer to int
int *a
cdecl> declare a as array 10 of pointer to function returning double
double (*a[10])()
cdecl> explain int *(*foo)[8]
declare foo as pointer to array 8 of pointer to int
class Djur { public: int x; virtual void f() { } }; class Hund : public Djur { public: int y; }; class Katt : public Djur { public: int z; }; void f(Djur* djur) { Hund* hund = dynamic_cast<Hund*>(djur); if (hund != 0) hund->y = 4711; } int main() { f(new Djur()); f(new Hund()); f(new Katt()); }
Strongly typed language = the compiler can guarantee that the program will execute without type errors.
Grammar (slighly modified from the one on ASU-86 page 349):
Program --> Declarations ; ExprA literal is a character constant, for example 'a'.
Declarations --> Declarations ; Declarations | id : Type
Type --> char | integer | array [ num ] of Type | *Type
Expr --> literal | num | id | Expr + Expr | Expr [ Expr ] | *Expr
Example program (with a type error?):
Idea: Add an attribute type to each node in the parse tree!n : integer; i : integer; a : array [256] of char; n + a[i] + 7
A translation scheme, with semantic actions, can be used for type checking. This part of the translation scheme saves the type of a variable in the symbol table (ASU-86 Fig 6.4):
Type --> char { Type.type := char; }
Type --> integer { Type.type := integer; }
Type --> *Type1 { Type.type := pointer(Type1.type); }
Type --> array [ num ] of Type1 { Type.type := array(1..num.val, Type1.type); }
Declarations --> id : Type { addtype(id.entry, T.type); }
Program --> Declarations ; Expr
Declarations --> Declarations ; Declarations
Expr --> num { Expr.type := integer; }Variables have the type they were declared as:
Expr --> literal { Expr.type := char; }
Expr --> id { Expr.type := lookup(id.entry); }Adding two integers gives an integer, anything else is a type error:
Indexing into an array:Expr --> Expr1 + Expr2 { if (Expr1.type == integer and Expr2.type == integer) Expr.type = integer; else Expr.type = type_error; }
Expr --> Expr1 [ Expr2 ] { if (Expr2.type == integer and Expr1.type == array(s, t)) Expr.type = t; else Expr.type = type_error; }
The while statement:
The expression statement from C:Stmt --> while ( Expr ) Stmt1 { if (Expr.type == integer and Stmt1.type == void) Stmt.type == void; else Stmt.type == type_error; }
Stmt --> Expr ; { if (Expr.type != type_error) Stmt.type == void; else Stmt.type == type_error; }
Expr --> Expr1 ( Expr2 )Add function declarations to the declaration part, for example with the type syntax int -> int:
f : int -> int;Grammar for the function type:
f(7) + 3;
Type --> Type1 "->" Type2Translation scheme for the function type:
Translation scheme for type checking a function call:Type --> Type1 "->" Type2 { Type.type = function(Type1.type, Type2.type); }
Expr --> Expr1 ( Expr2 ) { if (Expr1.type == function(s, t) and Expr2.type == s) Expr.type == t; else Expr.type == type_error; }
More structural equivalence in C:double m1[14][17]; double m2[14][17];
Checking type equivalence:typedef int A[10]; typedef int B[10]; typedef int C[11]; int main() { A a; B b; C c; A* ap; B* bp; C* cp; ap = &a; ap = &b; ap = bp; ap = cp; /* warning: assignment from incompatible pointer type */ ap = &c; /* warning: assignment from incompatible pointer type */ return 0; }
C uses structural equivalence for all types except records ("structs"):
This is to aviod cycles in the type representation:struct A { int foo; double fum; }; struct B { int blaj; double urko; }; struct A a; struct B b; a = b; /* error: incompatible types in assignment */
But note that TA1 and TA2 are the same type (since both are A):struct L { int foo; struct L* next; };
typedef struct A TA1; typedef struct A TA2; TA1 ta1; TA2 ta2; ta1 = ta2; // ok
The course Compilers and interpreters | Lectures: 1 2 3 4 5 6 7 8 9 10 11 12