Implementazione di Linguaggi 2 PARTE 6 Testo: A.V. Aho, R. Sethi, J.D.Ullman Compilers Principles,Techniques and Tools, Addison Wesley.

Slides:



Advertisements
Presentazioni simili
Linguaggio C e C++.
Advertisements

Introduzione al linguaggio C++
Linguaggi di programmazione
Traduzione guidata dalla sintassi
Semantica di linguaggi di programmazione Ne esistono differenti stili a seconda di paradigma di programmazione uso (validazione, prototyping, verifica.
MATLAB. Scopo della lezione Programmare in Matlab Funzioni Cicli Operatori relazionali Esercizi vari.
Type Checking (1° parte)
Generazione di Codice Intermedio
Algoritmi e Programmazione
Differenze nei vari linguaggi di Elisa Trifirò e Barbara Tacchino
1 Astrazioni sui dati : Specifica ed Implementazione di Tipi di Dato Astratti in Java.
Informatica Generale Marzia Buscemi
Anno accademico Gli operatori e le espressioni in C.
Il linguaggio C Gli operatori e le espressioni C Language
Fondamenti di Informatica I a.a Il linguaggio C Il preprocessore La sostituzione di macro Le compilazioni condizionali Linclusione di file C.
1 Istruzioni, algoritmi, linguaggi. 2 Algoritmo per il calcolo delle radici reali di unequazione di 2 o grado Data lequazione ax 2 +bx+c=0, quali sono.
Semantiche dei linguaggi di programmazione
Indirizzi delle variabili A ogni variabile sono associati tre concetti fondamentali: il valore memorizzato; il tipo dati di appartenenza; lindirizzo. Il.
Argomenti dalla linea dei comandi Gli argomenti possono essere passati a qualsiasi funzione di un programma, compresa la main(), direttamente dalla linea.
Funzioni definite dall’utente
Linguaggio MATLAB: costrutti tipici (IF,WHILE…)
Informatica di base A.A. 2003/2004 Algoritmi e programmi
Introduzione al linguaggio C++ 5 lezioni
1 Corso di Laurea in Biotecnologie Informatica (Programmazione) Assegnamento di valore a una variabile Anno Accademico 2009/2010.
Specifiche senza JML: uso delle asserzioni. 2 Asserzioni in Java Dal jdk 1.4 (da Febbraio 2002) cè meccanismo per gestire asserzioni Asserzione: espressione.
Eliana minicozzi linguaggi L1 Lezione3.
Programmazione Un programma descrive al computer, in estremo dettaglio, la sequenza di passi necessari a svolgere un particolare compito L’attività di.
Il linguaggio Fortran 90: 2. Istruzioni di Controllo
Introduzione alla programmazione lll
Fondamentidi Programmazione Corso: Fondamenti di Programmazione Classe: PARI-DISPARI Docente: Prof. Luisa Gargano Testo: Aho, Ulman, Foundations of Computer.
1 Implementazione di Linguaggi 2 PARTE 6 Implementazione di Linguaggi 2 PARTE 6 Massimo Ancona DISI Università di Genova Testo: A.V. Aho, R. Sethi, J.D.Ullman.
1 Implementazione di Linguaggi 2 Implementazione di Linguaggi 2 Federico Bernardi Type checking 2° parte Type checking 2° parte - Equivalenza di type expressions.
Semantica Operazionale Strutturata
Procedure e funzioni nei linguaggi di alto livello Lab Programmazione - turno /2006.
Unità Didattica 2 I Linguaggi di Programmazione
nome: sequenza di caratteri usata per denotare un oggetto
mosaic manipola oggetti primitivi (ruota e unisci) regole:
Tipo di dato: collezione di valori omogenei ed effettivamente presentati, dotata di un insieme di operazioni che li manipolano – aiutano lorganizzazione.
memoria gestita staticamente:
Dichiarazioni e tipi predefiniti nel linguaggio C
CAPITOLO 7.
Il Linguaggio C.
Espressioni condizionali
AN FI Un denominatoe comune Comandi u notazioni che esprimono azioni che, una volta eseguite, comportano una modifica permanente dello stato interno.
Programmazione in Java Claudia Raibulet
CODIFICA Da flow-chart a C++.
PROBLEMA ALGORITMO PROGRAMMA LINGUAGGI di PROGRAMMAZIONE
Il linguaggio C Le funzioni C Language Il passaggio dei parametri
Lo sviluppo del software e i linguaggi di programmazione
ISTITUTO STATALE DI ISTRUZIONE SUPERIORE F. ENRIQUES CORSO JAVA – PROVA INTERMEDIA DEL 12 MARZO 2007 NOME: COGNOME: ________________________________________________________________________________.
1 Corso di Informatica (Programmazione) Lezione 8 (7 novembre 2008) Programmazione in Java: operatori aritmetici, operatori di assegnamento e cast.
Introduzione a Javascript
Fondamenti di Informatica II Ingegneria Informatica (A-I) Prof. M.T. PAZIENZA a.a – 3° ciclo.
PROVA INTERCORSO MOD.B a.a RICORSIONE ESERCIZI A1.1-A1.6.
Ugo de'Liguoro - Informatica 2 a.a. 03/04 Lez. 7 Tipi di dato e strutture dati Specifica e realizzazione di strutture informative come classi.
1 Tipi di Dato §descrittori, tipi, controllo e inferenza dei tipi §specifica (semantica) e implementazione di tipi di dato l implementazioni “sequenziali”
Tecnologie Informatiche ed Elettroniche per le Produzioni Animali
Algoritmi e Strutture Dati Strutture Dati Elementari.
1 Fabio Scotti – Università degli Studi di Milano Fabio Scotti ( ) Laboratorio di programmazione per la sicurezza Valentina Ciriani ( )
Lez. 11 (13/14)Elementi di Programmazione1 Lezione 11 Esercizi.
13 ottobre Decisioni F. Bombi 13 ottobre 2002.
1 Il linguaggio C Precisazioni sull’esperienza in laboratorio.
Elementi di semantica denotazionale ed operazionale
Concetti Fondamentali sulla Programmazione
1 Macchine astratte, linguaggi, interpretazione, compilazione.
FI - Algoritmi e Programmazione 1 Variabili Consentono di aumentare notevolmente la potenza espressiva. Una variabile è caratterizzata da:  Un nome 
Informatica e Informatica di Base
Cloud informatica V anno. Introduzione a PHP Lo scripting PHP PHP è un linguaggio di scripting lato server. Le caratteristiche di un linguaggio di scripting.
Parsing ricorsivo discendente Il parsing ricorsivo discendente (recursive descent parsing) è un metodo di tipo top-down che può essere facilmente codificato.
Basi di Java Strutture base di Java. Basi di java ▪Variabili ▪Operatori ▪Condizioni e Cicli ▪Array.
Transcript della presentazione:

Implementazione di Linguaggi 2 PARTE 6 Testo: A.V. Aho, R. Sethi, J.D.Ullman Compilers Principles,Techniques and Tools, Addison Wesley

Type Checking Si divide in statico se eseguito durante la compilazione e dinamico se eseguito durante l’esecuzione del programma. È affiancato da altri controlli: Flow-of-control: goto return exit … Unicità di definizione: identificatori nello stesso scope, label di switch/case stat. controlli contestuali dei nomi es. (Modula) PROCEDURE P;…END P;

Ruolo del Type Checker Sostanzialmente controllare che le operazioni vengano applicate a tipi compatibili.

Type Expressions (TE) Sono espressioni che servono per definire i tipi di dato di un linguaggio. usano operatori detti type constructors e operandi detti tipi base. usano operatori detti type constructors e operandi detti tipi base. Le TE denotano i tipi di un linguaggio e sono fortemente dipendenti da esso. Le TE denotano i tipi di un linguaggio e sono fortemente dipendenti da esso.

Type Expressions (TE) Formalmente: Un tipo base (int, float, integer, real, complex, …) è una type expression; Un tipo base (int, float, integer, real, complex, …) è una type expression; Un tipo può avere un nome, per cui il nome di un tipo è una type expression; Un tipo può avere un nome, per cui il nome di un tipo è una type expression; Un costruttore di tipo applicato ad una type expression genera una nuova type expression: Un costruttore di tipo applicato ad una type expression genera una nuova type expression:

Type Expressions (TE) Costruttori di tipo Costruttori di tipo 1. Array: se T è una TE allora array(I,T) è una TE che denota un tipo array con tipo base T e tipo indice I 2. Prodotti cartesiani: se T 1 e T 2 sono TE allora T 1  T 2 è una TE che denota l’insieme delle coppie (t 1,t 2 ) con t 1  T 1 e t 2  T 2 (  associa a sinistra) 3. Record: il prodotto del tipo dei suoi campi, differisce dal prodotto per la commutativitò degli elementi dovuta alla selezione mediante nome (field label) ES.   ES. {f 1 :  1 ;…; f n :  n } un record con campi f i di tipo  i

Type Expressions (TE) 4. Puntatori: se T è una TE allora pointer(T) è una TE che denota un riferimento (puntatore) ad un oggetto di tipo T 5. Funzioni: è il tipo di una funzione che mappa un tipo dominio D in un tipo rango R e denotato D  R. 6. Class: è un misto tra il concetto di modulo e di tipo. È modellabile come un record con campi di tipo procedura e di tipo funzione detti metodi.

Type System Un Type System è una collezione di regole per assegnare TE alle parti di un programma. Un Type System è una collezione di regole per assegnare TE alle parti di un programma. È interessante implementare type system con DGDS È interessante implementare type system con DGDS Un Type Checker (TC) è un programma che implementa un Type System. Un Type Checker (TC) è un programma che implementa un Type System. Ogni TC può essere applicato a run time purché il codice oggetto contenga informazioni che specificano il tipo di ogni dato. Ogni TC può essere applicato a run time purché il codice oggetto contenga informazioni che specificano il tipo di ogni dato.

Type System Un Type System è detto sound se elimina la necessità di type checking a run time, cioè se il TC assegna un tipo  type-error ad ogni dato del programma, elimina la necessità di type checking a run time, cioè se il TC assegna un tipo  type-error ad ogni dato del programma, allora nessun errore di tipo si può verificare durante l’esecuzione.

Type checking: Schema di traduzione DS Un semplice type checker: 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^ Esempio key: integer; key: integer; key mod 1999 key mod 1999

Type checking: Schema di traduzione DS Aggiungo il tipo base type_error: 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  array[num] of T 1  T.type:=array(1..num.val,T 1.type)  T  ^T 1  T.type:=pointer(T 1.type) 

Type Checking di Espressioni E  literal  E.type:=char  E  num  E.type:=integer  E  id  E.type:=lookup(id.entry)  E  E 1 mod E 2  E.type:= if E 1.type=integer & E 2.type=integer then integer else type_error  else type_error 

Type Checking di Espressioni E  E 1 [E 2 ] {E.type:= if E 2.type=integer & E 1.type=array(s,t) then t else type_error} else type_error} E  E 1 ^ {E.type:= if E 1.type=pointer(t) then t else type_error} else type_error}

Type Checking di Istruzioni S  id := E  S.type:= if id.type=E.type then void else type_error  else type_error  S  if E then S 1  S.type:= if E.type =boolean then S 1.type else type_error  else type_error  S  while E do S 1  S.type:= if E.type=boolean then S 1.type else type_error  else type_error  S  S 1 ; S 2  S.type:= if S 1.type=void & S 2.type=void then S.type=void then S.type=void else type_error  else type_error 

Type Checking di Funzioni T  T 1 ’  ’ T 2  T.type:=T 1.type  T 2.type  E  E 1 (E 2 )  E.type:=if E 2.type= s & E 1.type= s  t then t then t else type_error  else type_error  Le funzioni n-arie f(t 1 :T 1,t 2 :T 2,…,t n :T n ) vengono assimilate a funzioni unarie di tipo T=T 1  T 2  …  T n root: (real  real)  real  real

Equivalenza di Tipo I linguaggi usano diversi modi e definizioni per stabilire se due tipo sono equivalenti. Gli approcci principali sono: Equivalenza strutturale (Fortran, C, C++, …) Equivalenza strutturale (Fortran, C, C++, …) Equivalenza per nome (Modula, Oberon, Ada, Pascal, …) Equivalenza per nome (Modula, Oberon, Ada, Pascal, …) Misti. Misti.

Equivalenza di Tipo Esempio in Modula-2. Dati: TYPE A=ARRAY[0..n] OF REAL; B=ARRAY[0..n] OF REAL; Dati: TYPE A=ARRAY[0..n] OF REAL; B=ARRAY[0..n] OF REAL; Definiscono due tipi non equivalenti, perché dotati di nome diverso (equivalenza per nome). Tuttavia, A e B sono identici e quindi strutturalmente equivalenti.

Equivalenza di Tipo: per Nome Due variabili hanno tipo equivalente per nome: 1. se appartengono alla stessa dichiarazione, 2. se appaiono in dichiarazioni diverse ma abbinate allo stesso identificatore di tipo. 3. nei linguaggi Oberon-like si ha che due nomi di tipo T e T’ dichiarati uguali denotano due tipi T e T’ identici. NOTA: Linguaggi come PL/M considerano i tipi T e T’ definiti in 3. non equivalenti. Linguaggi come PL/M considerano i tipi T e T’ definiti in 3. non equivalenti.

Equivalenza di Tipo: per Nome Esempi: 1. VAR a, b: ARRAY[1..n] OF REAL; (*a  b stessa dichiarazione*) 2. PROCEDURE O(a:T); VAR b:T (* a e b sono equivalenti perché usano lo stesso type id T*) (* a e b sono equivalenti perché usano lo stesso type id T*) 3. TYPE T’ = T (* T e T’ denotano due tipi identici perché dichiarati uguali *)

Equivalenza di Tipo: per Nome Due tipi sono compatibili se: sono identici, oppure sono identici, oppure uno è sottorango dell’altro, oppure uno è sottorango dell’altro, oppure entrambi sono sottorango di uno stesso tipo. entrambi sono sottorango di uno stesso tipo. Un sottorango è definito restringendo ad un intervallo l’insieme dei valori possibili di un tipo ordinale discreto (es. integer o elencazione). Il concetto di sottorango è un caso particolare di sottotipo, un concetto che vedremo in seguito.

Equivalenza di Tipo: per Nome Esempi. TYPE link = ^cell; VAR next : link; last : link; last : link; p : ^cell; p : ^cell; q : ^cell; q : ^cell; Equivalenza per nome: 1. next e last hanno lo stesso tipo perché sono associati alla stessa type expression, 2. p, q, r hanno lo stesso tipo, 3. p e next non sono equivalenti perché associati a type expression diverse.

Compatibilità per Assegnamento Un’espressione E di tipo T 2 è detta compati- bile rispetto all’assegnamento ad un tipo T 1 sse: 1. T 1 e T 2 sono identici e nessuno è di tipo file, 2. T 1 è real e T 2 integer, 3. T 1 e T 2 sono tipi ordinali compatibili e il valo- re di E appartiene all’intervallo chiuso speci- ficato da T 1, 4. T 1 e T 2 sono tipi stringa compatibili.

Equivalenza di Tipo: Strutturale Due type expression E 1 e E 2 sono struttural-mente equivalenti se: 1. E 1 e E 2 sono lo stesso tipo base, oppure 2. E 1 e E 2 sono ottenute applicando lo stesso costruttore di tipo a tipi strutturalmente equivalenti. Quindi due tipi sono strutturalmente equivalenti se sono identici.

Equivalenza di Tipo: Strutturale Esempi. 1. la type expression integer è equivalente solo a integer 2. Pointer(integer) è equivalente solo a pointer(integer)

Equivalenza di Tipo: Strutturale Spesso è possibile codificare le type expression in modo da semplificare la verifica di equivalenza strutturale. Famosa è quella adottata nel compilatore C di Ritchie e Johnson. Costruttori di tipo: pointer(t), freturns(t) e array(t). Costruttori di tipo: pointer(t), freturns(t) e array(t).

Codifica delle type expression. Poiché tutti i costruttori di tipo considerati sono operatori unari le type expression formate applicando questi costruttori ai tipi base hanno una struttura molto uniforme: char char freturns(char) freturns(char) pointer(freturns(char)) pointer(freturns(char)) array(pointer(freturns(char))) array(pointer(freturns(char)))

Codifica delle type expression. TypeconstructorEncoding pointer pointer01 array array10 freturns freturns11 Basic Type Encoding boolean boolean0000 char char0001 integer0010 real real0011 Type Expression Encoding char char freturns(char) pointer(freturns(char)) array(pointer(freturns(char)))

Algoritmo Ricorsivo per Equivalenza Strutturale FUNCTION SEQ(s,t):BOOLEAN; BEGIN IF s & t are the same basic type THEN RETURN TRUE IF s & t are the same basic type THEN RETURN TRUE ELSIF s=array(s1,s2) & t=array(t1,t2) THEN ELSIF s=array(s1,s2) & t=array(t1,t2) THEN RETURN SEQ(s1,t1) & SEQ(s2,t2) RETURN SEQ(s1,t1) & SEQ(s2,t2) ELSIF s=s1  s2 & t=t1  t2 THEN ELSIF s=s1  s2 & t=t1  t2 THEN RETURN SEQ(s1,t1) & SEQ(s2,t2) RETURN SEQ(s1,t1) & SEQ(s2,t2) ELSIF s=pointer(s1) & t=pointer(t1) THEN ELSIF s=pointer(s1) & t=pointer(t1) THEN RETURN SEQ(s1,t1) RETURN SEQ(s1,t1) ELSIF s=s1  s2 & t=t1  t2 THEN ELSIF s=s1  s2 & t=t1  t2 THEN RETURN SEQ(s1,t1) & SEQ(s2,t2) RETURN SEQ(s1,t1) & SEQ(s2,t2) ELSE RETURN FALSE ELSE RETURN FALSEEND

Cicli nelle rappresentazioni di tipi Molte strutture dati sono definite ricorsivamente: Esempio. Linguaggi che permette di assegnare un nome a un tipo. TYPE link= ^cell: cell= RECORD cell= RECORD info:INTEGER; info:INTEGER; next: link next: link END; END;

Cicli nelle rappresentazioni di tipi I nomi di tipo definiti ricorsivamente possono esse- re sostituiti se siamo disposti ad introdurre i cicli nel type graph. Sostituendo link con pointer(cell) Sostituendo link con pointer(cell) cell = record x xx infointegernextpointer cell

Cicli nelle rappresentazioni di tipi Possiamo eliminare il riferimento a cell nel type graph: cell = record x xx infointegernextpointer

Cicli nelle rappresentazioni di tipi Esempio. Il C evita i cicli nei type graph usando l’equivalenza strutturale per tutti i tipi tranne i record. Struct cell{ int info; int info; struct cell *next; struct cell *next;};

Conversioni di Tipo Consideriamo l’espressione: Consideriamo l’espressione: x + i con x di tipo real e i di tipo integer x + i con x di tipo real e i di tipo integer i e x hanno rappresentazioni diverse, i e x hanno rappresentazioni diverse, le istruzioni macchina usate per real e integer sono diverse, le istruzioni macchina usate per real e integer sono diverse, il compilatore deve convertire gli operandi del + per renderli dello stesso tipo. il compilatore deve convertire gli operandi del + per renderli dello stesso tipo. Il type checker può inserire le conversioni nella rappresentazione intermedia del programma.

Conversioni di Tipo La conversione da un tipo ad un altro è detta implicita se è fatta in modo auto- matico dal compilatore. Le conversioni implicite vengono anche dette coercions. La conversione è detta esplicita se il programmatore deve scrivere qualcosa per causare la conversione.

Monomorfismo e Polimorfismo In molti linguaggi tipati staticamente (es. Modula) una variabile T può ricevere valori solo di tipo T. I tipi sottorango di Modula verificano banalmente questa proprietà detta monomorfismo. I linguaggi object-oriented sono polimorfi, nel senso che le variabili possono ricevere valori di più di un tipo.

Generi di Polimorfismo Cardelli e Wegner hanno classificato il polimorfismo in Universale suddiviso in   Parametrico (generici)   Inclusione (object-oriented) Ad Hoc suddiviso in OverloadingOverloading CoercionCoercion

Polimorfismo Parametrico e Ad Hoc Polimorfismo Parametrico e Ad Hoc Nel polimorfismo parametrico una funzione opera uniformemente su un insieme di tipi che hanno una struttura comune Nel polimorfismo ad hoc una funzione opera su tipi distinti e su ciascuno si comporta in maniera indipendente dagli altri

Polimorfismo Parametrico Polimorfismo Parametrico Nel polimorfismo parametrico l’uniformità è ottenuta mediante parametri di tipo. Il polimorfismo universale opera, in generale, su un insieme potenzialmente infinito di tipi. Nel polimorfismo di inclusione un oggetto appartiene a molte classi diverse ma legate tra loro da ua relazione di inclusione.

Sottotipazione E’ un concetto legato a quello di tipo e di polimorfismo che definisce molti aspetti del type checking. E’ una relazione di preordine su tipi basata sul principio di subsumption: se  è  allora un valore di tipo  è accettato in ogni contesto in cui è previsto un valore di tipo . In formule: E’ un concetto legato a quello di tipo e di polimorfismo che definisce molti aspetti del type checking. E’ una relazione di preordine su tipi basata sul principio di subsumption: se  è un sottotipo di  allora un valore di tipo  è accettato in ogni contesto in cui è previsto un valore di tipo . In formule:  ⊦ e:   :   ⊦ e:   <:  ___________ ___________  ⊦ e:   ⊦ e: 

Sottotipazione strutturale e per nome L’equivalenza di tipo adottata influisce anche sulla sottotipazione. Strutturalmente diciamo che  1   2 è un sottotipo di  1  2 se  1 :  1 e  2 :  2. Come detto per i record e le classi si adotta in genere una sottotipazione per nome basato sull’ idea di type extension: una classe C2 estende C1 se C2 ha i tutti i campi di C1 e ne cambia i tipi in modo compatibile L’equivalenza di tipo adottata influisce anche sulla sottotipazione. Strutturalmente diciamo che  1   2 è un sottotipo di  1  2 se  1 <:  1 e  2 <:  2. Come detto per i record e le classi si adotta in genere una sottotipazione per nome basato sull’ idea di type extension: una classe C2 estende C1 se C2 ha i tutti i campi di C1 e ne cambia i tipi in modo compatibile (  i  (  i)(i  [1,n]  i <:  i ) _________________________ _________________________  {f 1 :  1 ;…; f n :  n }<: {f 1 :  1 ;…; f n :  n }

Sottotipazione strutturale e per nome 2  i  (  i)(i  [1,n]  i <:  i ) _________________________ _________________________  {f 1 :  1 ;…; f n :  n }<: {f 1 :  1 ;…; f n :  n } n<m __________________________ __________________________  {f 1 :  1 ;…; f m :  m }<: {f 1 :  1 ;…; f n :  n }

Conversioni (coercions) Coercion: data l’espressione: x + i Con x reale e i intero, essendo le rappresentazioni interne di x e i diverse e diversi gli algoritmi aritmetici, occorre effettuare una conversione dal tipo piu’ ristretto a quello piu’ generale. In notazione postfissa l’espressione diviene: x i inttoreal real+ x i inttoreal real+ Le conversioni sono implicite se effettuate dal compilatore, esplicite se comandate dall’utente. FOR i:=1 TO N DO x[i]:=float(1) FOR i:=1 TO N DO x[i]:=1.0 Possono avere una differenza di 8.96 unità di tempo per iterazione

Conversioni (coercions) 2 E  numE.type:=integer E  num. numE.type:=real E  idE.type:=lookup(id.entry) E  E 1 op E 2 E.type:=IF E 1.type=int&E 2.type=int THEN int ELSIF E 1.type=int & E 2.type=real THEN real ELSIF E 1.type=real&E 2.type=int THEN real ELSIF E 1.type=real&E 2.type=real THEN real ELSE type.error

Overloading 2 L’espressione a+b può indicare somma tra interi, reali, doppia precisione, complessi, matrici o unione tra dati di tipo SET. In questo caso si dice che il simbolo + è overloaded. Un overloading è detto risolvibile se è possibile dedurre un unico tipo per una data espressione.

Overloading Ovviamente, questo non è sempre possibile function “*” (i,j:integer) return complex; function”*”(x,y:integer) return complex; Da cui si deducono I possibili tipi di “*”: int  int  int int  int  int int  int  complex int  int  complex complex  complex  complex complex  complex  complex Dati 2,3 e 5, il valore di 3*5 puo’ essere sia int che complex es: 2*(3*5)  3*5:int; mentre (3*5)*z & z:complex  3*5:complex

Overloading di funzioni Type checking di funzioni overloaded E’  E E’.types:=E.type E  id E.types:=lookup(id.entry) E  E 1 (E 2 ) E.types:={t|  s  E 2.types: s  t  E 1.types} La terza regola asserisce che se s è un tipo di E 2 e uno dei tipi di E 1 mappa s in t, allora t è uno dei tipi di E 1. Qualora si riscontri una incompatibilità che porti a E.types=  si avrà un messaggio di errore.

Overloading di funzioni 2 Type checking di funzioni overloaded E:{I,c} E:{i} *:{i  i  i, i  i  c, c  c  c} E:{i} 3:{i}5:{i} Come restringere l’insieme dei tipi possibili Ada e altri linguaggi richiedono un unico tipo per ogni espressione completa. Se questo non e’ possibile si dichiara un errore. Si usa un attributo types che un set di tipi possibili (feasible)

Overloading di funzioni 3 Type checking di funzioni overloaded E  EE’.types:=E.types E.uniq:=IF E’.types={t} THEN t ELSE typerr E’.cod:=E.cod E  id E.types:=lookup(id.entry) E.cod:=gen(id.lexeme’:’ E.uniq) E  E1(E2)E.types:={s’|  s  E2.types & s  s’  E1.types} t:=E.uniq; S:={s|s  E2.types& s  t  E1.types} E2.uniq:=IF S={s} THEN s ELSE typerr; E1.uniq:=IF S={s} THEN s  t ELSE typerr; E.cod:=E1.cod||E2.cod||gen(‘apply’)’:’,E.uniq); L’attributo erditato uniq (unique) e’ usato con l’attributo sintetizzato code. La definizione e’ implementata da due visite depth-first dell’albero sintattico nella prima si calcola types bottom upnella prima si calcola types bottom up nella seconda si propaga verso il basso uniq e al ritorno della visita si genera cod.nella seconda si propaga verso il basso uniq e al ritorno della visita si genera cod.

Ereditarietà e sottotipazione La procedura seguente implementa il concetto di record type extension di Wirth (Oberon) PROCEDURE RecordType(VAR typ: Struct) VAR adr,sise:INTEGER;fld,fld0,fld1:Object; ftyp,btyp:Struct;base:Item; ftyp,btyp:Struct;base:Item;BEGIN adr:=0; typ:=NewStr(record); typ.BaseTyp:=NIL; typ.n:=0;

Ereditarietà e sottotipazione 2 IF sym=lparen THEN Get(Sym); (*record extension*) IF sym=ident THEN qualident(base); IF sym=ident THEN qualident(base); IF (base.mode=Typ) & (base.typ.form=Record) THEN IF (base.mode=Typ) & (base.typ.form=Record) THEN typ.BaseTyp:=base.typ;typ.n:=base.typ.n+1 typ.BaseTyp:=base.typ;typ.n:=base.typ.n+1 adr:=base.typ.size adr:=base.typ.size ELSE Error(..) ELSE Error(..) END; END; ELSE Error(..); ELSE Error(..); END; END; CheckSym(rparen) CheckSym(rparen)END;

Ereditarietà e sottotipazione 3 OpenScope(0); fld:=NIL; fld1:=topScope; LOOP LOOP IF sym=ident THEN IF sym=ident THEN LOOP LOOP IF sym=ident THEN IF sym=ident THEN IF typ.BaseTyp # NIL THEN FindField(typ.BaseTyp, fld0); IF typ.BaseTyp # NIL THEN FindField(typ.BaseTyp, fld0); IF fld0 # NIL THEN Error(..) END IF fld0 # NIL THEN Error(..) END END; END; Insert(OCS.name,fld); CheckMark(fld.marked); Insert(OCS.name,fld); CheckMark(fld.marked); fld.mode:=Fld fld.mode:=Fld ELSE Error(..) ELSE Error(..) END; END; IF sym=comma THEN Get(sym) IF sym=comma THEN Get(sym) ELSIF sym=ident THEN Error(..) ELSIF sym=ident THEN Error(..) ELSE E XIT ELSE E XIT END; END;

Ereditarietà e sottotipazione 4 CheckSym(colon); Type(ftyp); CheckSym(colon); Type(ftyp); size:=ftyp.size; btyp:=ftyp; size:=ftyp.size; btyp:=ftyp; WHILE btyp.form=Array DO btyp:=btyp.BaseTyp END; WHILE btyp.form=Array DO btyp:=btyp.BaseTyp END; IF btyp.size>=4 THEN INC(adr, (-adr)MOD 4) IF btyp.size>=4 THEN INC(adr, (-adr)MOD 4) ELSIF btyp.size=2 THEN INC(adr, adr MOD 2) ELSIF btyp.size=2 THEN INC(adr, adr MOD 2) END; END; WHILE fld1.next #NIL DO fld1:=fld1.next; fld1.typ:=ftyp; fld1:=fld1.next; fld1.typ:=ftyp; fld1.a0:=adr; INC(adr,size) fld1.a0:=adr; INC(adr,size) END ENDEND;

Ereditarietà e sottotipazione 5 IF sym=semicolon THEN Get(sym) ELSIF sym=ident THEN Error(..) ELSIF sym=ident THEN Error(..) ELSE EXIT ELSE EXIT END ENDEND; typ.size:=(-adr) MOD 4 + 4; typ.link:=topScope.next; CheckUndefPointerTypes; CloseScope; END RecordType;

Fine Type checking Proseguire con gli argomenti del seminario sul type checking