איתן אביאור תורת הקומפילציה 1 טיפוסים – ניתוח המשמעות ניתוח ( )analysis מנתח לקסיקאלי lexical analyser מנתח תחביר syntax analyser מנתח משמעות semantic analyser מייצר קוד ביניים intermediate code generator מייעל קוד חיבור ( )synthesis איתן אביאור מייצר קוד code.

Download Report

Transcript איתן אביאור תורת הקומפילציה 1 טיפוסים – ניתוח המשמעות ניתוח ( )analysis מנתח לקסיקאלי lexical analyser מנתח תחביר syntax analyser מנתח משמעות semantic analyser מייצר קוד ביניים intermediate code generator מייעל קוד חיבור ( )synthesis איתן אביאור מייצר קוד code.

Slide 1

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 2

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 3

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 4

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 5

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 6

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 7

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 8

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 9

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 10

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 11

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 12

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 13

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 14

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 15

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 16

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 17

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 18

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 19

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 20

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 21

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 22

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 23

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 24

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 25

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 26

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 27

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 28

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 29

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 30

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬


Slide 31

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪1‬‬

‫טיפוסים – ניתוח המשמעות‬
‫ניתוח‬
‫(‪)analysis‬‬

‫מנתח לקסיקאלי‬

‫‪lexical analyser‬‬

‫מנתח תחביר‬

‫‪syntax analyser‬‬

‫מנתח משמעות ‪semantic analyser‬‬

‫מייצר קוד ביניים‬
‫‪intermediate code generator‬‬
‫מייעל קוד‬

‫חיבור‬
‫(‪)synthesis‬‬
‫איתן אביאור‬

‫מייצר קוד‬

‫‪code optimizer‬‬
‫‪code generator‬‬
‫תורת הקומפילציה‬

‫‪2‬‬

‫סוגי בדיקות‬
‫בדיקות סטטיות (‪ )static checks‬‬
‫בדיקות הנערכות ע"י המהדר בזמן התרגום‬
‫בדיקות דינמיות (‪ )dynamic checks‬‬
‫בדיקות הנערכות ע"י התוכנית עצמה תוך כדי ריצה‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪3‬‬

‫בדיקות סטטיות‬
‫(‪)Static Checks‬‬
‫‪.1‬‬
‫‪.2‬‬

‫‪.3‬‬
‫‪.4‬‬

‫בדיקות טיפוסים (‪ )type checks‬‬
‫התאמת טיפוסי ביטויים ע"פ חוקי השפה‬
‫בדיקות הזרימה (‪ )flow-of-control checks‬‬
‫בדיקת מבני בקרת הזרימה‬
‫למשל ‪ break ‬שלא נמצא בתוך הלולאה‬
‫בדיקות יחידּות (‪ )uniqueness checks‬‬
‫בדיקה שעצם לא מוגדר יותר מפעם אחת בניגוד לחוקי השפה‬
‫בדיקות הקשורות לשמות (‪ )name related checks‬‬
‫וידוא ששם שמופיע פעמיים זהה בשני המופעים‬
‫למשל בשפת עדה ‪ ‬שם הלולאה בתחילתה ובסופה זהה‬
‫להלן נתמקד בבדיקות טיפוסים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪4‬‬

‫מיקום בודק הטיפוסים בתוך המהדר‬
‫ייצוג‬
‫ביניים‬

‫מייצר‬
‫קוד ביניים‬

‫בודק‬
‫עץ‬
‫תחביר טיפוסים‬

‫זרם‬
‫עץ‬
‫פורס‬
‫התמניות‬
‫תחביר‬

‫המידע הנאסף ע"י מערכת בדיקות הטיפוסים עשוי לשמש בהמשך‪,‬‬
‫למשל‬
‫• לצורך יצירת קוד הביניים‬
‫• או לצורך תרגום פעולות שיש להן העמסת יתר (‪)overloading‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪5‬‬

‫דרישות להתאמת טיפוסים‬
)Pascal report( ‫מתוך הגדרת פסקל‬
“If both operands of the arithmetic operators of addition,
subtraction and multiplication are of type integer,
then the result is of type integer.”
)C reference manual( C ‫מתוך הגדרת‬
“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 …’ .”
‫ ע"מ שנוכל להשוות טיפוסים של ביטויים שונים‬:‫מסקנה‬
"‫עלינו להגדיר "ביטויי טיפוסים‬
6

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוי טיפוסים‬
‫(‪)Type Expressions‬‬
‫‪boolean, char, integer, real, void‬‬
‫‪ .1‬טיפוסים בסיסיים כגון‪:‬‬
‫‪type-err‬‬
‫וכן טיפוס שגיאה מיוחד‪:‬‬
‫‪ .2‬שם שניתן לעיל לטיפוס כלשהו‬
‫‪ .3‬בנאי טיפוסים (‪:)type constructor‬‬
‫א‪ .‬מערך (‪  )array‬אם ‪ I‬הינה קבוצת אינדקסים ו‪ T-‬הינה טיפוס‬
‫אזי )‪ array(I, T‬הינו טיפוס "מערך ‪ I‬של ‪"T‬‬
‫ב‪ .‬מכפלה (‪  )product‬אם ‪ T1‬ו‪ T2-‬הינם טיפוסים‬
‫אזי ‪ T1  T2‬הינו טיפוס מכפלה‬
‫(לאופרטור ‪ ‬אסוציאטיביות שמאלית)‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪7‬‬

2  ‫ביטוי טיפוסים‬
‫ ההבדל בין רשומה למכפלה היא‬ )record( ‫ רשומה‬.‫ג‬
‫שלשדות של רשומה ישנם שמות‬
:‫למשל‬
type row = record
address: integer;
lexeme: array [1..15] of char
end;
var table: array [1..101] of row;
:‫ הינו‬row ‫ואז הטיפוס‬
record ((address  integer) 
(lexeme  array(1..15, char)))
8

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫ביטוים טיפוסיים ‪3 ‬‬
‫ד‪ .‬מצביע (‪  )pointer‬אם ‪ T‬הינו טיפוס‬
‫אזי ‪ T‬הינו טיפוס "מצביע ל‪"T-‬‬
‫ה‪ .‬פונקציה (‪  )function‬אם ‪ T1‬הינו טיפוס הערך שהפונקציה מקבלת‬
‫ו‪ T2-‬הינו טיפוס הערך שהיא מחזירה‬
‫אזי ‪ T1  T2‬הינו טיפוס "פונקציה המקבלת ‪ T1‬ומחזירה ‪“T2‬‬
‫(לאופרטור ‪ ‬אסוציאטיביות ימנית‪ ,‬ועדיפות נמוכה מאשר ‪)‬‬
‫הערה‪ :‬כאשר פונקציה מקבלת מספר פרמטרים נשתמש באופרטור‬
‫המכפלה ע"מ להגדיר את טיפוס הערך שהיא מקבלת‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪9‬‬

‫הצגת ביטויי טיפוסים‬
‫דוגמה‪:‬‬
‫פונקציה המקבלת שני ‪ char‬ומחזירה מצביע ל‪integer-‬‬
‫) ‪char  char  pointer( integer‬‬
‫ניתן לייצג את הטיפוס בתור גרף בשני אופנים‪:‬‬
‫‪‬‬

‫‪‬‬
‫‪pointer‬‬

‫‪‬‬

‫‪pointer‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪integer‬‬

‫‪char‬‬

‫‪char‬‬

‫עץ‬

‫‪DAG‬‬
‫איתן אביאור‬

‫‪‬‬

‫תורת הקומפילציה‬

‫‪10‬‬

‫מערכת טיפוסים‬
‫(‪)Type System‬‬
‫אוסף חוקים הקובעים עד כמה יש לבדוק התאמת טיפוסים‬
‫למשל‪:‬‬
‫• האם להשוות אינדקסים של מערך המועבר כפרמטר?‬
‫• האם להשוות את טיפוסי הפרמטרים של פונקציה המועברת כפרמטר?‬
‫• האם לבדוק התאמה של טיפוסי עצמים המועברים ע"י כתובת ?‬
‫יכולים להיות כל מיני חוקי בדיקה‬
‫ובודק טיפוסים מיישם מערכת טיפוסים מסוימת‬
‫יישומים שונים עשויים להוביל לתוצאות שונות‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪11‬‬

‫עוד הגדרות‬
‫מערכת בטוחה (‪ )sound‬‬
‫מערכת טיפוסים שבה ניתן לוודא את כל ההתאמות הנחוצות‬
‫ע"פ חוקי השפה בבדיקות סטטיות בלבד‬

‫שפה ‪  strongly typed‬כאשר המהדר יכול להבטיח שתוכנית‬
‫שהוא מקבל לא תיכשל בעת הביצוע בשל שגיאות טיפוס‬
‫כלומר – שפה שעבורה ניתן לבנות מערכת טיפוסים בטוחה‪.‬‬

‫באופן מעשי ישנן בדיקות שניתן לבצע רק בזמן ריצה‬
‫למשל – בדיקה לוידוא אי‪-‬חריגה מגבולות מערך‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪12‬‬

‫בודק טיפוסים פשוט‬
‫דקדוק‬
PD;E
D  D ; D  id : T
T  char

 integer  array [ num ] of T  T

E  literal  num  id  E mod E  E [ E ]

 E

‫תוכנית לדוגמה‬

key : integer;
key mod 1999
13

‫תורת הקומפילציה‬

‫איתן אביאור‬

2  ‫בודק טיפוסים פשוט‬
‫סכמת התרגום לפסוקי הגדרה‬
PD;E
DD;D
D  id : T

{ addtype (id.entry, T.type) }

T  char

{ T.type := char }

T  integer

{ T.type := integer }

T  T1

{ T.type := pointer(T1.type) }

T  array [ num ] of T1
{ T.type := array(1..num.val, T1.type) }
14

‫תורת הקומפילציה‬

‫איתן אביאור‬

3  ‫בודק טיפוסים פשוט‬
‫סכמת תרגום לביטויים‬
E  literal

{ E.type := char }

E  num

{ E.type := integer }

E  id

{ E.type := lookup (id.entry) }

E  E1 mod E2

{ E.type := ( E1.type = integer &&
E2.type = integer ? integer : type_err) }

E  E1 [ E2 ]

{ E.type := ( E2.type = integer &&
E1.type = array(s, t) ? t : type_err ) }

E  E1 

{ E.type := ( E1.type = pointer( t ) ?
t : type_err ) }

15

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫הרחבת השפה‬
‫• הוספת טיפוסים נוספים כגון ‪boolean, real‬‬
‫• הוספת אופרטורים נוספים‪:‬‬
‫– אריתמטיים‬

‫‪+/‬‬

‫– השוואה‬

‫=> > >< = =< <‬

‫– בוליאנים‬

‫‪and not or‬‬

‫• מעבר מביטויים לפסוקים‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪16‬‬

‫בדיקת טיפוסים פשוטה לפסוקים‬
S  id := E

‫הסכמה לפסוקים‬
{ S.type := ( id.type = E.type ?
void : type_err ) }

S  if E then S1

{ S.type := ( E.type = boolean ?

S1.type : type_err ) }
S  while E do S1 { S.type := ( E.type = boolean ?
S1.type : type_err ) }

S  S1 ; S2

17

{ S.type := ( S1.type = void &&
S2.type = void ? void : type_err ) }
‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת טיפוסים פשוטה לפונקציות‬
‫סכמה להגדרת טיפוסי פונקציות‬
‫} ‪{ T.type := T1.type  T2.type‬‬

‫‪T  T1 -> T2‬‬

‫סכמה להגדרת קריאה לפונקציות‬
‫&& ‪{ E.type := ( E2.type = S‬‬

‫) ‪E  E1 ( E2‬‬

‫} ) ‪E1.type = S  t ? t : type_err‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪18‬‬

‫שקילות טיפוסים‬
‫(‪)Type Equivalence‬‬
‫לצורך בדיקת נכונות התוכנית יש להשוות ביטויי טיפוסים‪,‬‬
‫למשל בפסוק ‪ x := y‬צריך לבדוק שהטיפוס של ‪ x‬ושל ‪ y‬זהים‬
‫(או שקולים)‬

‫קיימים שני סוגי שקילות‬
‫• שקילות מבנה (‪)structural equivalence‬‬
‫• שקילות שם (‪)name equivalence‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪19‬‬

‫שקילות מבנה‬
‫שני טיפוסים יהיו שקולים אם הם בעלי אותו מבנה‬
‫דוגמה‬
‫; ‪typedef cell link‬‬
‫; ‪link next‬‬
‫; ‪link last‬‬
‫; ‪cell p‬‬
‫; ‪cell q, r‬‬
‫כל חמשת המשתנים ‪ r ,q ,p ,last ,next‬הם מטיפוס מאותו מבנה‬
‫ועל כך הם שקולי מבנה‬

‫בשפת ‪ C‬משמעות הדבר שהם טיפוסים זהים‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪20‬‬

‫אלגוריתם לבדיקת שקילות מבנה‬
boolean sequiv(type s, type t) {
if
( s and t are the same basic type )
return true ;
elseif ( s = array(s1, s2) && t = array(t1, t2) )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
elseif ( s = pointer(s1) && t = pointer(t1) )
return sequiv(s1, t1) ;
elseif ( s = s1  s2 && t = t1  t2 )
return sequiv(s1, t1) && sequiv(s2, t2) ;
else
return false ;
}
21

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫בדיקת שקילות מבנה ראשונית‬
‫• לכל ביטוי טיפוס נתאים מספר שלם‬
‫• שני ביטויים יהיו בלתי שקולים אם המספר שלהם שונה‬
‫• מאחר וההתאמה איננה חד‪-‬חד ערכית ומזניחה חלק מהפרטים‬
‫לביטויי טיפוסים קרובים יהיה אותו מספר‪,‬‬
‫ואזי יש להפעיל את האלגוריתם הנ"ל ע"מ לוודא סופית‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪22‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס‬
‫ע"פ השיטה של מהדר ‪ C‬שכתב ‪D. M. Ritchie‬‬
‫הטיפוסים היסודים‬
‫‪boolean ,char ,integer ,real‬‬

‫הבנאים‬
‫מצביע ל‪t-‬‬
‫פונקציה שמקבלת פרמטרים כלשהם ומחזירה ‪t‬‬
‫מערך של גודל כלשהו שאיבריו מטיפוס ‪t‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫) ‪pointer ( t‬‬
‫) ‪freturns ( t‬‬
‫) ‪array ( t‬‬

‫‪23‬‬

‫שיטה להתאמת מספרים‬
‫לביטויי טיפוס ‪ ‬המשך‬
‫נתאים את הקודים הבאים‬
‫‪pointer 01‬‬
‫‪boolean 0000‬‬
‫‪array 10‬‬
‫‪char‬‬
‫‪0001‬‬
‫‪freturns 11‬‬
‫‪integer 0010‬‬
‫‪real‬‬
‫‪0011‬‬
‫רשומה (‪ )struct‬מקבלת קוד של טיפוס בסיסי חדש‬
‫דוגמאות‬
‫‪char‬‬
‫‪000000 0001‬‬
‫)‪freturns(char‬‬
‫‪000011 0001‬‬
‫))‪pointer(freturns(char‬‬
‫‪000111 0001‬‬
‫)))‪array(pointer(freturns(char‬‬
‫‪100111 0001‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪24‬‬

‫שקילות שמות‬
‫• בפסקל זהות מבנה איננה מספיקה‪,‬‬
‫;‪type link =  cell‬‬
‫ויש צורך בזהות שמות‪.‬‬
‫;‪var next : link‬‬
‫• על כן‪ next ,‬ו‪ last-‬הם מאותו טיפוס‪last : link; ,‬‬
‫וכן ‪ q‬ו‪r-‬‬
‫‪p‬‬
‫;‪:  cell‬‬
‫• אולם ‪ next‬ו‪ p-‬הם מטיפוס שונה‬
‫;‪q, r :  cell‬‬
‫• יתר על כן‪ p ,‬ו‪ q-‬הם מטיפוס שונה‬
‫;‪type link =  cell‬‬
‫‪np‬‬
‫;‪=  cell‬‬
‫כאילו ההגדרה היתה‪:‬‬
‫;‪nqr =  cell‬‬
‫;‪var next : link‬‬
‫;‪last : link‬‬
‫‪p‬‬
‫;‪: np‬‬
‫‪q‬‬
‫;‪: nqr‬‬
‫‪r‬‬
‫;‪: nqr‬‬
‫‪25‬‬
‫תורת הקומפילציה‬
‫איתן אביאור‬

‫ייצוג הטיפוסים‬
‫לשקילות שמות‬
‫• נייצג את הטיפוסים ע"י גרף‬
‫• כל פעם שטיפוס בסיסי חדש נראה ‪ ‬נייצר צומת עלה‬
‫• כל פעם שבנאי טיפוסים נראה ‪ ‬נייצר צומת חדש המקושר לעץ‬
‫• כל פעם שמוגדר שם חדש ‪ ‬נייצר צומת עלה עם מצביע מיוחד‬
‫לביטוי המגדיר אותו‬
‫• שני טיפוסים יהיו זהים אם"ם הם מיוצגים ע"י אותו צומת בגרף‬
‫דוגמה‬
‫‪next‬‬
‫‪last‬‬
‫‪p‬‬
‫‪q‬‬
‫‪r‬‬
‫‪pointer‬‬

‫‪pointer‬‬

‫‪pointer‬‬

‫‪link‬‬

‫‪cell‬‬
‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪26‬‬

‫מעגליות בייצוג טיפוסים‬
:‫נתבונן בקטע הבא‬

link =  cell;
cell = record
info : integer;
next : link
end;
‫ מעגליות‬ cell-‫ הינו רשומה המכילה שדה שהינו מצביע ל‬cell ‫הטיפוס‬

type

cell = record

cell = record









info integer next pointer
27

‫ייצוג רקורסיבי‬





info integer next pointer

cell ‫תורת הקומפילציה‬

‫ייצוג מעגלי‬

‫איתן אביאור‬

‫פתרון המעגליות‬
‫• בשפת ‪ C‬שקילות טיפוסים נעשית ע"פ שקילות מבנה‪,‬‬
‫למעט כאשר מדובר במבנים ‪( union ,struct‬או ‪ class‬ב‪)C++-‬‬
‫• מבנים אלה יהיו שקולים ע"פ שם‬

‫• ב‪ C-‬חייבים כל השמות להיות מוגדרים לפני שמשתמשים בהם‪,‬‬
‫למעט תגים של מבנים בהם מותר להשתמש רק לצורך מצביעים‬
‫• המעגליות ב‪ C-‬אפשרית אם כן‪ ,‬רק במצביעים למבנים שבהם כאמור‬
‫מוגדרת שקילות שם‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪28‬‬

‫המרת טיפוסים‬
‫(‪)Type Conversions‬‬
‫• שפה יכולה לספק שיטות שונות להמרת טיפוסים‬
‫– ב‪ 4 C++-‬סוגים‬
‫• לעיתים יש צורך בהמרה אוטומטית ע"י המהדר הנקראת המרה‬
‫בכפיה (‪)coercions‬‬
‫– כאשר האופרנדים של פעולה אינם תואמים‬
‫– כאשר ערך מטיפוס אחד מוצב למשתנה מטיפוס אחר‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪29‬‬

‫המרה בכפיה של טיפוסים‬
‫סכמות להמרה בכפיה‬
E  num

E.type := integer

E  num . num E.type := real
E  id

E.type := lookup( id.entry )

E  E1 op E2

E.type :=
(E1.type = integer && E2.type = integer ) ? integer :
(E1.type = integer && E2.type = real ) ? real :
(E1.type = real && E2.type = integer ) ? real :
(E1.type = real && E2.type = real ) ? real : type_err

30

‫תורת הקומפילציה‬

‫איתן אביאור‬

‫תום פרק ‪6‬‬

‫איתן אביאור‬

‫תורת הקומפילציה‬

‫‪31‬‬