Dagens tema: Sjekking (obligatorisk oppgave 3)

Like dokumenter
Dagens tema: Sjekking

Del 3: Evaluere uttrykk

Dagens tema: Mer av det dere trenger til del 1

Dagens tema: 12 gode råd for en kompilatorskriver. Sjekking av navn. Lagring av navn. Hvordan finne et navn?

Dagens tema: INF2100. Syntaksanalyse. Hva annet gjør en kompilator? Sjekking av navnebruk. Testutskrifter

Syntaksanalyse. Dagens tema: Språkdiagrammene Jernbanediagrammene er et ypperlig utgangspunkt for å analysere et program: INF2100 INF2100 INF2100

Kompilering Statiske Syntaksanalyse Feilsjekking Eksempel Oppsummering

Dagens tema: 12 gode råd for en kompilatorskriver

Oversikt Kompilering Syntaksanalyse Java Feilsjekking Oppsummering

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen Oppsummering

Dagens tema: Resten av det dere trenger til del 1

INF Repetisjon: Hvordan bygge treet og analysere? 8. september Typisk situasjon. De problematiske syntaks-diagrammene

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

Oversikt Kodegenerering Variabler Setninger Uttrykk While-setningen

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

Dagens tema: Resten av det dere trenger til del 1

Oversikt Deklarasjoner Typesjekk Programmering Datamaskinhistorie x86 Kodegenerering

Beskrivelse av programmeringsspråket Compila15 INF Kompilatorteknikk Våren 2015

Dagens tema. Hva er kompilering? Anta at vi lager dette lille programmet doble.rusc (kalt kildekoden): Hva er kompilering?

Dagens tema: 12 gode råd for en kompilatorskriver. Prosjektet. Koblingen mellom grammatikken og klasser. Utifra dette RusC-programmet:

Anatomien til en kompilator - I

Viktig. Rettet i koden. Oppgaven. Obligatorisk oppgave 2 - Kort om oppgaven og litt informasjon. Fredrik Sørensen OMS-gruppen, IfI

UNIVERSITETET I OSLO

Dagens tema. Hva er kompilering? Anta at vi lager dette lille programmet (kalt kildekoden): Hva er kompilering?

Oversikt Kodegenerering Variable Setninger Uttrykk While-setningen

Obligatorisk Innlevering 2

INF april, 2013 Kap. 8 Noen oppgaver som er meget relevante for Oblig 2

Kompilering Statiske Syntaksanalyse Feilsjekking Eksempel Oppsummering

Diverse eksamensgaver

Konstruktører. Bruk av konstruktører når vi opererer med "enkle" klasser er ganske ukomplisert. Når vi skriver. skjer følgende:

Eivind Gard Lund. 24. Mars 2009 Foilene bygger på 2009 utgaven av Andreas Svendsen

Beskrivelse av programmeringsspråket Simpila INF Kompilatorteknikk Våren 2012

Dagens tema: Mer av det dere trenger til del 1

2 Parser. 1 Skanner. 4 Kodegenerator. 3 Sjekker. Oversikt Datamaskinhistorie x86 Kodegenerering Setninger Uttrykk.

Dagens tema: 12 gode råd for en kompilatorskriver. Prosjektet. Modifikasjon av grammatikken. Utifra dette RusC programmet:

IN2030. Oppgave 1. Løsningsforslag. Uke (Disse filene finnes også i mappen ~inf2100/e/e2/.)

Semantisk Analyse del I

Kap 6.3: Symboltabellen Foiler ved Birger Møller-Pedersen Forelest av Stein Krogdahl 17. mars Dagens tema:

Kap 6.4: Typesjekking Foiler ved Birger Møller-Pedersen Forelest av Stein Krogdahl 19. og 23. mars Dagens tema: Typer og typesjekking

Hva er kompilering? Dagens tema. En kompilator En kompilator leser Minila koden og lager Flok koden.

INF5110 Obligatorisk Oppgave 2 del 2. Andreas Svendsen SINTEF. 23. April Oversikt

Datatyper og typesjekking

Skal bindes opp til en deklarasjon av samme navn

Datatyper og typesjekking

Datatyper og typesjekking

Datatyper og typesjekking

Skal bindes opp til en deklarasjon av samme navn

Hjemmeeksamen 2 i INF3110/4110

Oblig 2 - Simpila. INF Kompilatorteknikk. Våren Typesjekking, sjekking av bruk av navn og blokkstrtuktur i språk.

Oppsummering. Kort gjennomgang av klasser etc ved å løse halvparten av eksamen Klasser. Datastrukturer. Interface Subklasser Klasseparametre

Anatomien til en kompilator - I

Semantisk Analyse del III

INF2100. Oppgave 1. Oppgave 2 4. Løsningsforslag til oppgaver uke 40 og Se figur 1 på neste side.

1- og 2-veis Innkapsling Java Stabel Kø Prio-kø Iterator. Enveis- og toveislister Innkapsling («boxing») (Big Java 6.8.5)

Oversikt. Introduksjon Kildekode Kompilering Hello world Hello world med argumenter. 1 C programmering. 2 Funksjoner. 3 Datatyper. 4 Pekere og arrays

Plan: Parameter-overføring Alias Typer (Ghezzi&Jazayeri kap.3 frem til 3.3.1) IN 211 Programmeringsspråk

INF Oblig 2 semantikksjekk og kodegenerering

1- og 2-veis Innkapsling Java Stabel Kø Prio-kø Iterator. Enveis- og toveislister Innkapsling («boxing») (Big Java 6.8.5)

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister

INF april, 2015 Stein Krogdahl Ifi, UiO. Svar på oppgaver til kap. 8. Ble lagt ut 24. april

Dagens tema: Mer av det dere trenger til del 2

Repitisjonskurs. Arv, Subklasser og Grensesnitt

MED SVARFORSLAG UNIVERSITETET I OSLO. Det matematisk-naturvitenskapelige fakultet

INF1000 EKSTRATILBUD. Stoff fra uke 1-5 (6) 3. oktober 2012 Siri Moe Jensen

Hvordan skrive Flok og Flass kode? I mange tilfelle er det svært enkelt:

Hva er verdien til variabelen j etter at følgende kode er utført? int i, j; i = 5; j = 10; while ( i < j ) { i = i + 2; j = j - 1; }

En kompilator for Pascal. Kompendium for INF2100

INF2100. Oppgaver 9. oktober 2012 C 100 X 10

UNIVERSITETET I OSLO

Hovedstoffet i kap 4: 16. Februar Ifi, UiO

Oversikt. Praktisk. Litt om meg. Obligatorisk oppgave 1 - Kort om oppgaven og verktøyene. Fredrik Sørensen OMS-gruppen, IfI.

Repetisjon: Statiske språk uten rekursive metoder (C1 og C2) Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

Dagens tema Kjøresystemer (Ghezzi&Jazayeri 2.6, 2.7)

UNIVERSITETET I OSLO

INF2100. Oppgaver uke 40 og

class Book { String title; } class Dictionary extends Book { int wordcount; } class CartoonAlbum extends Book { int stripcount; }

Enkle generiske klasser i Java

Velkommen til INF2100

Arv. Book book1 = new Book(); book1. title = "Sofies verden" class Book { String title; } class Dictiona ry extends Book {

INF2100. Oppgaver 23. og 24. september 2010

Array&ArrayList Lagring Liste Klasseparametre Arrayliste Testing Lenkelister Videre

INF5110. Oblig 2 presentasjon

Kort om meg. INF1000 Uke 2. Oversikt. Repetisjon - Introduksjon

IN1010 våren januar. Objektorientering i Java

UNIVERSITETET I OSLO

Gjennomgang av eksamen H99

2 Om statiske variable/konstanter og statiske metoder.

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

2012 2a. C rc; void main() { rc = new C (); rc.m2(); } } INF 3110/ INF /28/13 1

INF Seminaroppgaver til uke 3

INF2100. Oppgaver 6. og 11. oktober 2011 C 100 X 10

Runtimesystemer - II. Funksjoner som parametere. Virtuelle metoder

Eksekveringsrekkefølgen (del 1) Oppgave 1. Eksekveringsrekkefølgen (del 2) Kommentar til oppgave 1. } // class Bolighus

Runtime-omgivelser Kap 7 - I

UNIVERSITETET I OSLO

i=0 Repetisjon: arrayer Forelesning inf Java 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker 0*0 0*2 0*3 0*1 0*4

Forelesning inf Java 4

Runtimesystemer Kap 7 - I

UNIVERSITETET I OSLO

Transkript:

Dagens tema Dagens tema: Sjekking (obligatorisk oppgave 3) Navnebinding Biblioteket Logging Riktig bruk av navn Typesjekking Utregning av konstanter

Hele prosjektet Strukturen til kompilatoren vår f.pas f.s 1 Skanner :Token :Token :Token 2 Parser <program> <var decl> 4 Kodegenerator 3 Sjekker

Hva skal gjøres? Navnebinding program A; var : ; Gitt følgende program: Oppgaven er: Alle navneforekomster skal bindes til sin deklarasjon. procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := + F(V) end; { A } := 1; A(10); write(, =,, eol) end.

Syntakstreet program A; var : ; procedure A (V: ); function F (V: ): ; <program> := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. <var decl part> <proc decl> <var decl> <param decl list> <proc call> <proc call> <type name> <param decl> <func decl> <variable> <type name> <param decl list> <type name> <simple expr> <simple expr> <simple expr> <simple expr> <simple expr> <simple expr> <param decl> <variable> <term> <term> <term> <term> <term> <term> <type name> <simple expr> <numeric lit> <numeric lit> <char lit> <char lit> <variable> <variable> <variable> <variable> <term> <term opr> <term> <simple expr> <simple expr> <variable> <func call> <term> <term> <numeric lit> <factor opr> <variable> <variable> <simple expr> <term> <variable>

Syntakstreet La oss se på et forenklet bilde av syntakstreet: program A; var : ; procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. Prog A library Type boolean Type char Const eol Const false Type integer Const true Proc write Var Proc A Param V A write Func F 1 10 = eol Param V F F 2 V V

Hvilke noder har vi? Grønne noder er deklarasjoner. program A; var : ; procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. Prog A library Type boolean Type char Const eol Const false Type integer Const true Proc write Var Proc A Param V A write Func F 1 10 = eol Param V F F 2 V V

Hvilke noder har vi? Blå noder er navneforekomster. program A; var : ; procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. Prog A library Type boolean Type char Const eol Const false Type integer Const true Proc write Var Proc A Param V A write Func F 1 10 = eol Param V F F 2 V V

Navnebindingen Forekomsten av a bindes slik: program A; var : ; procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. Prog A library Type boolean Type char Const eol Const false Type integer Const true Proc write Var Proc A Param V A write Func F 1 10 = eol Param V F F 2 V V

Navnebindingen Navnet x bindes slik: program A; var : ; procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. Prog A library Type boolean Type char Const eol Const false Type integer Const true Proc write Var Proc A Param V A write Func F 1 10 = eol Param V F F 2 V V

Navnebindingen Navnet v må bindes til den riktige deklarasjonen: program A; var : ; procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. Prog A library Type boolean Type char Const eol Const false Type integer Const true Proc write Var Proc A Param V A write Func F 1 10 = eol Param V F F 2 V V

Navnebindingen Predefinerte navn bindes til biblioteket: program A; var : ; procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. Prog A library Type boolean Type char Const eol Const false Type integer Const true Proc write Var Proc A Param V A write Func F 1 10 = eol Param V F F 2 V V

Hvordan gjør vi det? Hvordan kan vi foreta navnebindingen? Alle deklarasjonene er i en block : konstanter (const pi = 3;) variabler (var teller: integer;) funksjoner (function f: char;...) prosedyrer (procedure p;...) parametre

Hvordan gjør vi det? Et forslag La klassen Block inneholde en oversikt over alle dens deklarasjoner, for eksempel i form av en HashMap<String,PascalDecl>. En slik struktur ar en ekstra fordel: Det er enkelt å sjekke om noen navn er deklarert flere ganger i samme blokk. Dette skal i så fall gi en feilmelding.

Hvordan gjør vi det? Sjekkingen For å sjekke hele programmet, må vi skrive en rekursiv metode void check(block curscope, Library lib) som traverserer det.

Hvordan gjør vi det? Deler av Block kan se slik ut: public class Block extends PascalSyntax { ConstDeclPart constdeclpart = null; : HashMap<String,PascalDecl> decls = new HashMap<>(); void adddecl(string id, PascalDecl d) { if (decls.containskey(id)) d.error(id + " declared twice in same block!"); decls.put(id, d); } @Override void check(block curscope, Library lib) { if (constdeclpart!= null) { constdeclpart.check(this, lib); } :

Leting i lokalt skop Leting etter navn 1 Det enkleste først: Anta at navnet finnes i den lokale blokken: Derfor sender vi en peker til den som parameter til check. Eksempel class ProcCallStatm extends Statement { String procname; ArrayList<Expression> actparams = new ArrayList<>(); ProcDecl procref; @Override void check(block curscope, Library lib) { PascalDecl d = curscope.finddecl(procname,this); : procref = (ProcDecl)d; :

Leting i ytre skop 2 Hvis deklarasjonen ikke er lokal, kan vi finne den ved å lete i ytre skop. Derfor bør Block inneholde en peker Block outerscope som peker på blokken utenfor. Den kan initieres av check.

Leting i ytre skop program A; var : ; procedure A (V: ); function F (V: ): ; := 2*V; F := end; { F } := 1; := + F(V) A(10); end; { A } write(, =,, eol) end. Prog A library Type boolean Type char Const eol Const false Type integer Const true Proc write Var Proc A Param V A write Func F 1 10 = eol Param V F F 2 V V

Leting i ytre skop Klassen Block kan da ha en metode finddecl: PascalDecl finddecl(string id, PascalSyntax where) { PascalDecl d = decls.get(id); if (d!= null) { Main.log.noteBinding(id, where, d); return d; } if (outerscope!= null) return outerscope.finddecl(id,where); } where.error("name " + id + " is unknown!"); return null; // Required by the Java compiler.

Biblioteket Biblioteket Noen navn som integer og write er predefinert. Hvordan bør vi håndtere dem? Løsning Lag et «kunstig» Block-objekt med disse predefinerte deklarasjonene og legg det ytterst. Da vil de bli funnet om ikke brukeren har deklarert noe med samme navn. Hint Lag en subklasse Library av Block for dette formålet. Da er det greit å initiere den med innholdet av biblioteket.

Sjekk hva loggen sier Kontroll For å sjekke navnebindingen brukes opsjonen -logb. Kallet på Main.log.noteBinding i Block.findDecl gir oss den informasjonen vi trenger. 1 program A; 2 var : ; 3 4 procedure A (V: ); 5 function F (V: ): ; 6 7 := 2*V; 8 F := 9 end; { F } 10 11 12 := + F(V) 13 end; { A } 14 15 16 := 1; 17 A(10); 18 write(, =,, eol) 19 end. Binding on line 2: integer was declared as <type decl> integer in the library Binding on line 4: integer was declared as <type decl> integer in the library Binding on line 5: integer was declared as <type decl> integer in the library Binding on line 5: integer was declared as <type decl> integer in the library Binding on line 7: x was declared as <var decl> x on line 2 Binding on line 7: v was declared as <param decl> v on line 5 Binding on line 8: f was declared as <func decl> f on line 5 Binding on line 8: x was declared as <var decl> x on line 2 Binding on line 12: x was declared as <var decl> x on line 2 Binding on line 12: x was declared as <var decl> x on line 2 Binding on line 12: f was declared as <func decl> f on line 5 Binding on line 12: v was declared as <param decl> v on line 4 Binding on line 16: x was declared as <var decl> x on line 2 Binding on line 17: a was declared as <proc decl> a on line 4 Binding on line 18: write was declared as <proc decl> write in the library Binding on line 18: x was declared as <var decl> x on line 2 Binding on line 18: eol was declared as <const decl> eol in the library

Brukes navnet riktig? Navnebruk Etter å ha funnet hvor et navn er deklarert, må en kompilator sjekke at det brukes rett, for eksempel at vi ikke har procedure P; P := 17 end; {P}

Brukes navnet riktig? Hvordan sjekke dette? Det er mange måter å sjekke navnebruken på; jeg skal vise at oo-programmering kan gjøre dette enkelt og oversiktlig. 1 Deklarer en virtuell funksjon i klassen PascalDecl: abstract void checkwhetherassignable(pascalsyntax where); 2 I alle deklarasjoner som kan stå til venstre i en tilordning (f eks VarDecl og FuncDecl), implementeres denne som en tom metode: @Override void checkwhetherassignable(pascalsyntax where) {} 3 I alle andre deklarasjoner lager vi i stedet en @Override void checkwhetherassignable(pascalsyntax where) { where.error("you cannot assign to a constant."); }

Brukes navnet riktig? Ved alle navneforekomster der det skal skje en tilordning (f eks i AssignStatm), kan vi bruke denne metoden: class AssignStatm extends Statement { Variable var; Expression expr; @Override void check(block curscope, Library lib) { var.check(curscope, lib); var.vardecl.checkwhetherassignable(this); expr.check(curscope, lib); :

Hvor mange trenger vi? Hvilke checkwhether-metoder trenger vi? Selv har jeg brukt disse: checkwhetherassignable for tilordning (i AssignStatm) checkwhetherfunction for funksjonskall checkwhetherprocedure for prosedyrekall checkwhethervalue for uttrykk

Hvordan sjekke riktig bruk av typer? Typesjekking Det er også viktig å sjekke at programmereren overholder typereglene og ikke skriver slikt som var A: ; B: Char; C: array [1.. z ] of Boolean; if A then B := C + 1; :

Hvordan gjøre det i praksis? Hvordan kan dette implementeres? Det er også her mange mulige måter å ordne seg på. I pakken types finnes det fem klasser: Type er en abstrakt superklasse ArrayType er for arrayer brukeren deklarerer BoolType er for standardtypen Boolean CharType er for standardtypen Char IntType er for standardtypen NB! Nå har vi to klasser Type: parser.type og types.type. Bruk pakkeprefikset når du mener den som ikke er i samme pakke.

Hvordan gjøre det i praksis? Alt som kan ha type (dvs expression, simple expr etc) definerer et element types.type type; Her settes elementets type inn av den enkelte check-metode; her er vist for expression. @Override void check(block curscope, Library lib) { leftop.check(curscope, lib); type = leftop.type; } if (rightop!= null) { rightop.check(curscope, lib); String oprname = relopr.opr.kind.tostring(); type.checktype(rightop.type, oprname+" operands", this, "Operands to "+oprname+" are of different type!"); type = lib.booleantype; }

Hvordan gjøre det i praksis? I klassen types.type deklareres en metode public void checktype(type tx, String op, PascalSyntax where, String mess) { Main.log.noteTypeCheck(this, op, tx, where); if (this!= tx) where.error(mess); } Parametrene er: tx er typen som «vår» type skal sammenlignes med op er en angivelse av hvordan typen brukes where angir hvor i programmet typen forekommer message inneholder meldingen som skal gis om det er typefeil (For types.arraytype er testen mer komplisert, så den er redefinert.)

Hvordan gjøre det i praksis? Metoden Main.log.noteTypeCheck gir logging av typesjekkingen om vi angir opsjonen -logt. 1 program A; 2 var : ; 3 4 procedure A (V: ); 5 function F (V: ): ; 6 7 := 2*V; 8 F := 9 end; { F } 10 11 12 := + F(V) 13 end; { A } 14 15 16 := 1; 17 A(10); 18 write(, =,, eol) 19 end. Type check left * operand on line 7: type vs type Type check right * operand on line 7: type vs type Type check := on line 7: type vs type Type check := on line 8: type vs type Type check param #1 on line 12: type vs type Type check left + operand on line 12: type vs type Type check right + operand on line 12: type vs type Type check := on line 12: type vs type Type check := on line 16: type vs type Type check param #1 on line 17: type vs type

Hvordan gjøre det i praksis? Nå har vi testapparatet vi trenger. I WhileStatm kan vi for eksempel skrive class WhileStatm extends Statement { Expression expr; Statement body; @Override void check(block curscope, Library lib) { expr.check(curscope, lib); expr.type.checktype(lib.booleantype, "while-test", this, "While-test is not Boolean."); body.check(curscope, lib); } (Her ser vi at parameteren lib til check-metoden er nyttig.)

Konstantverdier kan regnes ut av kompilatoren Konstanter Kompilatoren må vite hva alle konstanter er allerede under kompileringen, for eksempel for å sette av plass. var A: array [ 1.. 10 ] of Boolean; Noen ganger krever det litt beregning: const size = 45; var Ax: array [ -1.. +size] of Char; array-type array [ constant.. constant ] of type unsigned constant constant prefix opr + name numeric literal prefix opr unsigned constant - char literal

Konstantverdier kan regnes ut av kompilatoren Alle elementer i syntakstreet som inneholder en konstant (dvs CharLiteral, Constant, ConstDecl etc), deklarerer en «int constval» og denne kan beregnes av check som allikevel går gjennom hele treet. class Constant extends PascalSyntax { PrefixOperator prefix = null; UnsignedConstant uconst; types.type type; int constval; @Override void check(block curscope, Library lib) { uconst.check(curscope, lib); type = uconst.type; constval = uconst.constval; if (prefix!= null) { String oprname = prefix.opr.kind.tostring(); uconst.type.checktype(lib.integertype, "Prefix "+oprname, this, "Prefix + or - may only be applied to s."); if (prefix.opr.kind == subtracttoken) constval = -constval; } }