340 likes | 529 Views
בדיקת טיפוסים. Aho, Sethi, Ullman – Chapter 6. בדיקת טיפוסים (type checking). המטרות העיקריות של בדיקת הטיפוסים בדיקת תקינות פתרון של בעיות overloading ו- polymorphism בדיקת שקילות של טיפוסים. בדיקת טיפוסים (type checking). ההקשר הכללי – בדיקות סטטיות דוגמאות בדיקת טיפוסים
E N D
בדיקת טיפוסים Aho, Sethi, Ullman – Chapter 6
בדיקת טיפוסים (type checking) • המטרות העיקריות של בדיקת הטיפוסים • בדיקת תקינות • פתרון של בעיות overloadingו- polymorphism • בדיקת שקילות של טיפוסים
בדיקת טיפוסים (type checking) • ההקשר הכללי – בדיקות סטטיות • דוגמאות • בדיקת טיפוסים • בדיקת תקינות של זרימת הבקרה • goto ליעד לא מוגדר? • בדיקת יחידוּת • שני משתנים עם אותו השם? • בדיקות הקשורות במופעים של שמות בתכנית • begin A … end B? • בדיקות המתבצעות בזמן ריצה נקראות דינאמיות
front end – שלב הניתוח - תזכורת תוכנית מקור תוכנית מטרה scanner lexical analysis token stream parser syntax analysis syntax tree semantic analysis decorated syntax tree היכן מוסיפים את בדיקות הטיפוסים?
front end – שלב הניתוח - תזכורת תוכנית מקור תוכנית מטרה scanner lexical analysis token stream parser syntax analysis syntax tree semantic analysis Type Checking decorated syntax tree
front end – שלב הניתוח - תזכורת תוכנית מקור תוכנית מטרה scanner lexical analysis token stream parser syntax analysis syntax tree semantic analysis Type Checking decorated syntax tree
בדיקת טיפוסים – למה זה טוב? (דיון בכתה)
type systems • יחוס של טיפוס לתוצאה של פעולה “If both operands of the operators of additions, subtraction and multiplication are of type integer, then the result is of type integer” [The Pascal Report] “The result of the unary & operator is a pointer to the object referred to by the operand. If the type of the operand is ‘…’, the type of the result is ‘pointer to …’.” [The C Reference Manual]
type systems • ביטויי טיפוסים (type expressions) • טיפוס בסיסי boolean, character, integer, real,… enumerated types…, void , type error • שמות של ביטויי טיפוסים • תוצאת ההפעלה של type constructor • ביטויי טיפוס יכולים להכיל משתנים מטיפוס "ביטוי טיפוס".
type constructor • מערכים • מכפלה קרטזית () • רשומות (record או struct או class) • כמו מכפלה קרטזית, אבל עם שמות • מחוונים (pointers) • פונקציות
→ → pointer pointer char char integer char integer ייצוג כעץ ייצוג כגרף חסר מעגלים ייצוג ביטויי טיפוס כגרף • עבור char x char → pointer (integer) • עלים – טיפוסים בסיסיים • שאר הצמתים – תוצאה של הפעלה של type constructors
type systems • מערכת טיפוסים היא אוסף חוקים להצמדת ביטויי טיפוס לחלקים שונים של התוכנית • מימוש מערכת הטיפוסים של שפת תכנות – באמצעות type checkers • במערכת טיפוסים שהיא sound ניתן לוודא תקינות בזמן קומפילציה • שפה עבורה מערכת הטיפוסים היא sound נקראת – strongly typed • באופן מעשי, בדיקות מסוימות ניתן לבצע רק בזמן ריצה • דוגמא:חריגה מגבולות מערך.
הסקת טיפוסים וטיפול בשגיאות • דוגמא – מהביטוי 5 + x ניתן להסיק ש- x הוא integer • הערה – גם בשפות בהן הטיפוסים דינאמיים, ידיעה טובה של הטיפוסים מסייעת ליצירת קוד יעיל יותר / לאינטרפרטציה יעילה יותר • הערה – שפות מסוימות מחייבות מערכת משוכללת של הסקת טיפוסים • טיפול בשגיאות • באמצעות הסקת טיפוסים וזיהוי שגיאות • על ידי הגדרת טיפוס שגיאה, על מנת למנוע התפשטות של שגיאות
דוגמא ל- type checker • תוכנית היא הכרזות + ביטוי P →D ; E • משפטי הכרזה D → D ; D D →id : T T →char T →integer T → ↑T T →array [ num ] of T • הכרזה על פונקציות T → T →T
דוגמא ל- type checker • ביטויים E →literal E →num E →id E → E mod E E → E [ E ] E →↑E • הפעלה של פונקציות E → E ( E )
דוגמא ל- type checker • תוכנית היא הכרזות + ביטוי P →D ; E • משפטי הכרזה D → D ; D D →id : T { addtype (id.entry, T.type) } T →char{ T.type := char } T →integer{ T.type := int } T → ↑T1{ T.type := pointer (T1.type) } T →array [ num ] of T1{ T.type := array (1..num.val, T1.type) } • הכרזה על פונקציות T → T1→T2{ T.type := T1.type →T2.type }
דוגמא ל- type checker • ביטויים E →literal{ E.type := char } E →num{ E.type := int } E →id{ E.type := lookup (id.entry) } E → E1mod E2{ E.type := if E1.type = int and E2.type = int then int elsetype_error } E → E1 [ E2 ] {E.type := if E2.type = int and E1.type = array (s, t) then t elsetype_error } E →↑E1{E.type := if E1.type=pointer(t) then t elsetype_error } • הפעלה של פונקציות E → E1 ( E2 ) { E.type := if E2.type = s and E1.type = s → t then t elsetype_error }
הרחבת השפה • נוסיף לשפה משפטים. • תוכנית היא כעת: P → D;S • הכללים שהגדרנו עבור ביטויים עדיין שימושיים, משום שמשפטים כוללים בתוכם ביטויים.
משפטים • משפטים S →id := E S →if E then S S →while E do S S → S ; S
משפטים איך נראים משפטי השמה בשפת C? • משפטים S →id := E { S.type := ifid.type = E.type then void elsetype_error } S →if E then S1{ S.type := if E.type = boolean then S1.type elsetype_error } S →while E do S1{ S.type := if E.type = boolean then S1.type elsetype_error } S → S1 ; S2{ S.type := if S1.type = void and S2.type = void then void elsetype_error } הרעיון: error propagation
equivalence of type expressions • מושג השקילות הכרחי להגדרת נכונות של תכנית • תמונת השקילות של ביטויים לא תמיד מובנת מאליה בשפות בהן יש user defined types • הערה: בדיקת השקילות היא לפעמים חלקית, למשל • האם מערכים בעלי תחומי הגדרה שונים שקולים?
structural equivalence function sequiv (s, t): boolean; begin if s and t are the same basic type then return true else if s = array(s1, s2) and t = array(t1, t2) then return sequiv (s1, t1) and sequiv (s2, t2) else if s = s1 x s2 and t = t1 t2 then return sequiv (s1, t1) and sequiv (s2, t2) else if s = pointer (s1) and t = pointer (t1) then return sequiv (s1, t1) else if s = s1→s2 and t = t1→t2 then return sequiv (s1, t1) and sequiv (s2, t2) else return false end;
הערות • אפשר להרחיב את האלגוריתם על מנת שיטפל בסוגים נוספים של טיפוסים • האלגוריתם מסוגל לטפל בעצים או בגרפים חסרי מעגלים • הערה: נתבונן בכלל העוסק בגבולות של מערכים else if s = array(s1, s2) and t = array(t1, t2) then return sequiv (s1, t1) and sequiv (s2, t2) על ידי ויתור על המרכיב הזה נוותר על זהות גדלי המערך
equivalence of type expressions • user defined types typelink =↑cell; var next: link; last: link; p: ↑ cell; q, r: ↑ cell; • בפסקל לא הוגדר המושג identical type ולכן לא ברור האם p ו– next שווים • ובאופן כללי name equivalence ≠ structural equivalence
cell = record cell = record x x x x x x info integer next pointer info integer next pointer cell על ידי הצבה על ידי הצבה + הצבעה equivalence of type expressions • הגדרות מעגליות -- בעיה אופיינית לטיפול ב- records typelink =↑cell; cell = record info: integer; next: link; end;
cell = struct x x x info int next pointer cell equivalence of type expressions • הגדרות מעגליות -- בעיה אופיינית לטיפול ב- C struct cell { int info; struct cell *next; }; • הגישה –structural equivalence עבור כל הטיפוסים חוץ מ-struct • כל ה- type names צריכים להיות מוגדרים לפני השימוש, חוץ ממצביעים ל- struct שעדיין לא הוכרז
המרת טיפוסים • המרת טיפוסים יכולה להיות מפורשת. • למשל, בפסקל משתמשים בפונקציות ord ו-chr כדי להמיר מ-char ל-integer ולהיפך. • המרת טיפוסים יכולה להיות גם משתמעת (implicit, נקרא לעיתים coercion). • המרה משתמעת מתבטאת לעיתים קרובות בקוד כקריאה לפונקציה פנימית. • מומלץ לבצע המרות משתמעות של קבועים בזמן הידור ולא בזמן ריצה...
המרת טיפוסים כללים להמרה משתמעת מ-integer ל-real
overloading • יתכן overloading הן של פונקציות והן של אופרטורים • overloaded symbol – מקבל משמעות שונה בתלות בהקשר • resolution –קביעת משמעות יחידה • דוגמא – פעולות אריתמטיות הן overloaded
קבוצת אפשרויות לטיפוסים עבור תת ביטויים • דוגמא:הרחבה של פעולת ה- * ב- Ada function “*” (i, j : integer) return complex; function “*” (x, y : complex) return complex; • האפשרויות: integer integer → integer integer integer → complex complex complex → complex • הטיפוס של 3 *5 מוגדר על פי ההקשר • אם 2*(5*3) הוא כל הביטוי אזי 5*3 מוגדר כ- integer. אם הביטוי הוא z*(5*3) באשר z מטיפוס complex, אזי 5*3 הוא מטיפוס complex
המרת טיפוסים – overloading • type checking rules for coercion from integer to real • אם E.types ריק – type_error • ב- Ada צריך בסופו של דבר להקבע טיפוס יחיד; התהליך נקרא narrowing
דברים שמסבכים type systems • ירושה • generics • הסקת טיפוסים
הסקת טיפוסים • פונקציה ב-Haskell: length [] = 0 length (first:rest) = 1 + length rest • הסקת הטיפוס: list → int