Det här är ungefär vad jag tänker säga på föreläsningen. Använd det för förberedelser, repetition och ledning. Det är inte en definition av kursinnehållet, och det ersätter inte kursboken.
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
Kursen Kompilatorer och interpretatorer | Föreläsningar: 1 2 3 4 5 6 7 8 9 10 11 12