Løsningsforslag til eksamen i IN 211 høsten 2002

Like dokumenter
UNIVERSITETET I OSLO

Fiktiv eksamensbesvarelse IN 211 høsten 2001

Løsningsforslag til eksamen i IN 211 høsten 2001

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

UNIVERSITETET I OSLO

Om oppgaveteksten på noe punkt er uklar eller upresis, kan du gjøre egne presiseringer. Formulér i så fall disse tydelig i oppgavebesvarelsen din.

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

Anatomien til en kompilator - I

Anatomien til en kompilator - I

Hjemmeeksamen 2 i INF3110/4110

Syntaksanalyse. Skanner (repetisjon) Parsering top-down bottom-up LL(1)-parsering Recursive descent Forutsetninger. IN 211 Programmeringsspråk

Variable Man kan bruke variable i ML. ML (kap 5 og 6) Nye datatyper INF3110/4110 INF3110/4110 INF3110/4110 INF3110/4110. Variable i ML.

Runtimesystemer - II. Funksjoner som parametere. Virtuelle metoder

Litt om kompilering og interpretering. Dagens tema Syntaks (kapittel Komp. 47, kap. 1 og 2) Syntaks og semantikk

Plan. Fortsetter med ML: lister og rekursive typer/funksjoner unntak let-uttrykk moduler og abstrakte datatyper høyere-ordens funksjoner

Dagens tema Syntaks (kapittel Komp. 47, kap. 1 og 2)

Semantisk Analyse del III

Dagens tema Innføring i ML - del IV

1/28. Forelesning Forelesning / fun f (_,0) = true. 2 f(0,_)=true. 3 f_ =false; 4 val f = fn : int * int -> bool

Dagens tema: Sjekking

UNIVERSITETET I OSLO

Skal bindes opp til en deklarasjon av samme navn

Runtimesystemer - II. Parameteroverføring Call by value Call by reference Call by value-result Call by name INF 3110/ INF

Ark 1 av 18. programmeringsspråkenes. Velkommen til IN 211. verden. IN 211 Programmeringsspråk

Løsningsforslag til hjemmeeksamen 2 i INF3110/4110

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme

INF3110 Programmeringsspråk. Dagens tema. Typer (Kapittel 3 frem til ) Innføring i ML (Kapittel & ML-kompendiet.) 1/19

Typer. 1 Type: boolean. 2 Verdimengde: {true, false} 3 Operatorer: NOT, AND, OR... 1/19. Forelesning Forelesning

Dagens tema. Innføring i ML - del III (Kapittel & ML-kompendiet.) Unntak Abstrakte datatyper i ML Høyere-ordens funksjoner

Fortsetter med ML: Repetisjon av lister Typer Unntak Moduler og abstrakte datatyper Introduksjon til høyere-ordens funksjoner

Dagens tema Grundig repetisjon og utdyping: Syntaks kontra semantikk

Runtime-omgivelser Kap 7 - II

Plan. Fortsetter med ML: lister og rekursive typer/funksjoner unntak let-uttrykk moduler og abstrakte datatyper høyere-ordens funksjoner

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

INF2810: Funksjonell Programmering. En metasirkulær evaluator, del 2

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

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme

INF2810: Funksjonell Programmering. En metasirkulær evaluator, del 2

Semantisk Analyse del I

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

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

INF2810: Funksjonell Programmering. En metasirkulær evaluator

Plan. funksjoner som funksjonsverdi funksjoner som datastruktur. funksjoner som parametre. Høyere-ordens funksjoner. ufullstendige kall.

UNIVERSITETET I OSLO

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

INF5110, onsdag 19. februar, Dagens tema: Parsering ovenfra-ned (top-down)

UNIVERSITETET I OSLO

Skal bindes opp til en deklarasjon av samme navn

INF2810: Funksjonell Programmering. En metasirkulær evaluator

Del 3: Evaluere uttrykk

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

MED SVARFORSLAG UNIVERSITETET I OSLO. Det matematisk-naturvitenskapelige fakultet

Språktyper og syntaksanalyseteknikker. Dagens temaer. Hvordan lage en deterministisk automat? Fra jernbanediagram til ID-automat

Datatyper og typesjekking

INF2810: Funksjonell Programmering. En Scheme-evaluator i Scheme, del 2

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

INF3110 Programmeringsspråk. Velkommen til kurset INF 3110/4110. Programmeringsspråk 1/24

INF 3110/4110. Velkommen til kurset. Programmeringsspråk. Først det praktiske

Kap. 4: Ovenfra-ned (top-down) parsering

UNIVERSITETET I OSLO

Hva er syntaks? En overskrift i en norsk avis: Dagens tema Grundig repetisjon og utdyping:

Kap.4 del 2 Top Down Parsering INF5110 v2005. Arne Maus Ifi, UiO

Med Svarforslag UNIVERSITETET I OSLO. Det matematisk-naturvitenskapelige fakultet. 3 sider (side 6, 7 og 8, rives ut, fylles ut og leveres)

Datatyper og typesjekking

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

INF1010 notat: Binærsøking og quicksort

INF2810: Funksjonell Programmering

INF2810: Funksjonell Programmering

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

Hjemmeeksamen 1 i INF3110/4110

Datatyper og typesjekking

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

Datatyper og typesjekking

UNIVERSITETET I OSLO

Kompilering Statiske Syntaksanalyse Feilsjekking Eksempel Oppsummering

Oversikt Kompilering Syntaksanalyse Java Feilsjekking Oppsummering

INF2810: Funksjonell Programmering

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

Dagens tema: Regulære språk og uttrykk

Dagens tema. Funksjonelle språk Fortsetter med ML: Typer Unntak Introduksjon til høyere-ordens funksjoner. ML avsluttes etter planen neste uke.

ML (kap 5 og 6) INF3110/4110. Variable i ML. Nye datatyper. Currying. Avanserte listeoperatorer. Typeanalyse

Forelesere. Velkommen til programmeringsspråkenes verden IN211. Praktiske opplysninger. Faglige forutsetninger. Ragnhild Kobro Runde

INF2810: Funksjonell Programmering

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

TDT Øvingsforelesning 1. Tuesday, August 28, 12

UNIVERSITETET I OSLO

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

Runtimesystemer Kap 7 - I

Diverse eksamensgaver

Kapittel 1 En oversikt over C-språket

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

Feilmeldinger, brukerinput og kontrollflyt


Eksamen i SLI230, vår 2003.

Rekursjon og lister. Stephan Oepen & Erik Velldal. 1. februar, Universitetet i Oslo

Plan. funksjoner som funksjonsverdi funksjoner som datastruktur. funksjoner som parametre. Høyere-ordens funksjoner. ufullstendige kall.

INF Logikk og analysemetoder Forslag til løsning på oppgave fra læreboken

Runtime-omgivelser Kap 7 - I

MED SVARFORSLAG UNIVERSITETET I OSLO

Transkript:

Løsningsforslag til eksamen i IN 211 høsten 2002 Ragnhild Kobro Runde og Gerhard Skagestein 4. desember 2002 Oppgave 1: Kjøresystemer 1a: Statisk skop Print-setningen vil skrive ut 2, da det i C er main sin y som gjelder og denne ikke har fått endret sin verdi underveis. SL x = 0 y = 2 DL main A x = 2 y = 3 y = 4 D B B C 1b: Dynamisk skop 1. Statisk link er ikke lenger nødvendig, siden den nettopp brukes for å finne ikkelokale variable når vi har statisk skop. Dynamisk link er fortsatt nødvendig. Både for å kunne returnere til forrige aktiveringsblokk på stakken, og fordi det nå er denne vi vil følge for å finne ikke-lokale variable. 2. Print-setningen vil nå skrive ut 4, da C er kalt fra B og denne nettopp har satt sin y-verdi til å være 4. 1

x = 1 y = 2 x = 2 y = 4 DL main A D B C 1c: Parameteroverføring 1. Det enkleste her er kanskje å la kalleren og den kalte metoden ha variable med samme navn, for eksempel: void main() { void P(int x) { int a = 2; print(x); } void Q { int a = 5; P(a); } } Q(); Ved call-by-name vil variabelen x som skrives ut i P være bundet til Q.a, og verdien 5 skrives ut. Ved call-by-text vil derimot x være bundet til den lokale P.a, og verdien 2 vil bli skrevet ut. 2. Den mest nærliggende løsningen er kanskje å ha en egen run-time rutine som evaluerer uttrykket hver gang det brukes tilsvarende thunk-rutinen ved nameoverføring (se læreboken side 101 102). En alternativ løsning vil være å se på call-by-text som en makro, der kompilatoren starter med å tekstlig substituere alle parametrene. Ved ulike kall på samme metode, vil vi da få substitusjon til flere ulike metoder. Senere variabel-aksess vil da gå akkurat som normalt. Dette vil også si at kompilatoren kan gjøre statisk sjekking av disse parametrene på samme måte som for vanlige variable. 2

Oppgave 2: ML-map 2a: Liste-implementasjon av map structure Map_impl: Map_def = struct type ( key, val) Map = ( key * val) list; exception novalue; val empty = []; fun size(m) = case m of [] => 0 x :: r => 1 + size(r); fun containskey(m, k) = case m of [] => false (x,v) :: r => x = k orelse containskey(r,k); fun containsvalue(m, v) = case m of [] => false (k,x) :: r => x = v orelse containsvalue(r,v); fun get(m, k) = case m of [] => raise novalue (x,v) :: r => if x = k then v else get(r,k); fun put(m,k,v) = case m of [] => [(k,v)] (k,v )::r => if k = k then (k,v) :: r else (k,v ) :: put(r,k,v); fun remove(m,k) = case m of [] => [] (x,v) :: r => if k = x then r else (x,v)::remove(r,k); fun union(m1,m2) = case m2 of [] => m1 (k,v) :: r => put(union(m1,r),k,v); end; 2b: Bruk av map Dette kan selvsagt gjøres på flere måter. Mitt forslag er basert på følgende ide: 1. Bruk values for å få ut en liste med lister av de som har fått besøk. 2. Hjelpefunksjonen flatut konverterer denne til en enkel liste med samme verdier. 3. Funksjonen konverter går gjennom den utflatede listen. For hvert navn x brukes hjelpefunksjonen antall til å telle opp hvor mange denne har fått besøk av. Hvert slikt (navn,antall)-par settes så inn i det konverterte map et. Merk at alle som har fått besøk mer enn en gang vil puttes inn i map et flere ganger, først med verdien 1, deretter med verdien 2 og så videre. En mer effektiv løsning kunne brukt let-konstruksjonen og latt antall også returnere listen med alle forekomster av navnet x fjernet. 3

fun flatut(l) = case l of [] => [] x :: r => x @ flatut(r); fun antall(x,l) = case l of [] => 0 y :: r => if x = y then 1 + antall(x,r) else antall(x,r); fun konverter(l) = case l of [] => empty x :: r => put(konverter(r), x, antall(x,r) + 1); fun antallbesok(besoktmap) = konverter(flatut(values(besoktmap))); 2c: Map implementert som funksjonsrom type ( key, val) Map = key -> val; De eneste Map-funksjonene som ikke kan implementeres med funksjonsrom er funksjonene size og containsvalue, siden disse krever at vi kan løpe gjennom hele strukturen. Dette er som kjent ikke mulig med funksjonsrom. (Det er heller ikke mulig å lage funksjonene keys og values som nevnt i oppgave 2b, men dette var det ikke spurt om her.) Implementasjon av resten av funksjonene: val empty = fn x => raise novalue; fun containskey(m, k) = m(k)=m(k) handle novalue => false; fun get(m,k) = m(k); fun put(m,k,v) = fn x => if x = k then v else m(x); fun remove(m,k) = fn x => if x = k then raise novalue else m(k); fun union(m1,m2) = fn x => m2(x) handle novalue => m1(x); Forklaring: containskey skal returnere false hvis nøkkelen ikke finnes. Siden oppslag med ikke-eksisterende nøkkel gir unntaket novalue kan vi enkelt fange opp dette og gi false istedenfor. Problemet er hvordan returnere true. Dette har jeg her løst ved å teste om m(x) er lik seg selv. Hvis nøkkelen finnes vil dette alltid slå til, finnes ikke nøkkelen får vi unntaket som nevnt over. I union(m1,m2) skal mappingene i m2 gis prioritet. Dette gjøres her ved å slå opp i denne først, og så slå opp i m1 kun hvis m2 gir unntak. 4

Oppgave 3: Hypervektorer: Grammatikk 3a: Typing 1. Vi går ut fra at språket ikke har eksplisitte deklarasjoner slike er i alle fall ikke vist i eksemplene og i grammatikken gitt i oppgaven. Da er den eneste muligheten strukturell kompatibilitet se læreboka side 140. 2. Operatoren virker både som et hypervektor skalarprodukt og som et heltalls (og antagelig også flytende talls) skalarprodukt, avhengig av operandene. Altså har vi operator-overlasting (som er en ad-hoc-polymorfisme, se læreboka side 147, figur 3.10) 3. Et språk er sterkt typet dersom kompilatoren kan garantere at utførelsen ikke kan gi typefeil (se læreboka side 138). Dette er åpenbart ikke tilfelle, siden grammatikken tillater [3, 5] 7. I forelesningene er gitt en noe videre definisjon: "Et programmeringsspråk er sterkt typet dersom alle typefeil blir diagnostisert. Hvis alle bindinger er statiske, kan mesteparten av typesjekkingen også gjøres statisk. Hvis bindingen er dynamisk, må typesjekkingen også være dynamisk." Språket kan ansees som sterkt typet i henhold til den videre definisjonen (dvs. at det er typesikkert), siden korrekt typing kan sjekkes ved hjelp av typebeskrivelser i operandene under utførelsen. Oppgaveteksten spesifiserer ikke semantikken i bruk av skalarmultiplikasjonsoperatoren mellom vektorer av ulik lengde. Det er nærliggende å tolke manglende elementer som 0 eller en tom vektor, men dersom dette ikke gjøres, vil vi få en kjøretidsfeil. Om dette er en typefeil, er avhengig av om vektorlengden anses som en del av typen eller ikke. 3b: LL(1) 1. LL(1)-grammatikk: prog assign assignlist assignlist assign assignlist ε assign var expr ; expr var factor [ expr exprlist ] factor tall factor factor expr ε exprlist, expr exprlist ε 2. Bevis for LL(1): MTT Startmengde Etterfølgermengde prog Nei var assignlist Ja var assign Nei var var expr Nei var [ tall ; ], factor Ja ; ], exprlist Ja, ] 5

Produksjon Utvidet startmengde Disjunkt? prog assign assignlist var JA assignlist assign assignlist var assignlist ε (tom) JA assign var expr ; var JA expr var factor var expr [ expr exprlist ] factor [ JA expr tall factor tall factor expr factor ε ; ], JA exprlist, expr exprlist, exprlist ε ] JA Alle utvidede startmengder er disjunkte, altså er grammatikken LL(1). 3c: Regulære uttrykk 1. Regulært uttrykk (merk at [ og ] er grunnsymboler, mens ( og ) er metaparenteser): [ (tall var) ( (tall var)) (, (tall var) ( (tall var)) ) ] Regulær grammatikk (basert på den ikke-deterministiske automaten i neste punkt): UTTRYKK [ FL FL tall EE1 var EE1 EE1 ED EL ED tall EE var EE EE ED EL EL, FL ] Betydningen av metasymbolene er som følger: FL Før liste EE1 Etter første element EE Etter element ED Etter EL Etter liste 2. Ikke-deterministisk automat: 6

3. Deterministisk automat: Denne automaten kan forenkles videre ved å slå sammen FL og ED, samt (EE1,EL) med (EE,EL). Oppgave 4: Hypervektorer: Prolog 4a: Spørringer 1. Søketre: 2. Det finnes en løsning til. Den ene løsningen baserer seg på regelen dotprod(_,[],0), den andre på dotprod([],_,0). I begge tilfellene bindes verdien 50 til R. 3. Cut-varianten: dotprod([],_,0). dotprod(_,[],0). dotprod([h1 T1],[H2 T2],Result) :- dotprod(t1,t2,r), Result is R + (H1*H2),!. 7

Uten prosedurelle aspekter: dotprod([],[],0). dotprod([],l,0):- L \==[]. dotprod(l,[],0):- L \==[]. dotprod([h1 T1],[H2 T2],Result) :- dotprod(t1,t2,r), Result is R + (H1*H2). 4. Intuitivt kan man hevde at dotprod([1,2],x, 50) vil kunne gi uendelig mange løsninger (for eksempel X=[10,20] og X=[30,10]), og at spørringen derfor er uten mening. Men det egentlige problemet er at is-predikatet ikke unifiserer på vanlig måte. Vi kan i uttrykket Result is R + (H1*H2) ikke binde en verdi til Result og forvente at Prolog binder verdier til R, H1 og H2. 4b: Hypervektorer Det går an å tenke på to måter: Enten å beregne skalarproduktverdiene for alle vektorene og deretter summere skalarene, eller å akkumulere opp skalarproduktverdiene for alle vektorene etter hvert i samme akkumulator. Den følgende løsningen bygger på den siste tenkemåten. hyperdotprod([],[],0). hyperdotprod([],l,0):- L \==[]. hyperdotprod(l,[],0):- L \==[]. hyperdotprod([h1 T1],[H2 T2],Result) :- hyperdotprod(h1,h2,resa), hyperdotprod(t1,t2,resb), Result is ResA + ResB. hyperdotprod(h1, H2, Result) :- number(h1), number(h2), Result is H1 * H2. Oppgave 5: Hypervektorer: ML 1. type hyperelement = tall of int liste of hyperelement list; type hypervektor = hyperelement list; 2. ((1,2),(3,4,5)) vil med representasjonen over skrives som: [liste([tall(1),tall(2)]), liste([tall(3),tall(4),tall(5)])] ((10,20),(30,40,50)) vil tilsvarende bli skrevet som: [liste([tall(10),tall(20)]), liste([tall(30),tall(40),tall(50)])]; 3. Min versjon av hyperdotprod takler tomme lister, ved at disse tolkes som en nullvektor (som forklart i innledningen om hypervektorer). Den takler også lister av ulik lengde, ved å fylle ut med null-elementer der det er nødvendig. Oppgaveteksten legger opp til at tomme lister skal takles, men ikke nødvendigvis lister av ulik lengde. I praksis vil begge deler føre til at produktet alltid blir null. 8

Det å ta produktet av et tall og en liste er derimot ikke definert, og gir her unntaket syntaksfeil. exception syntaksfeil; fun hyperdotprod(v1:hypervektor, v2:hypervektor):int = case v1 of [] => ( case v2 of [] => 0 y :: s => 0 ) x :: r => ( case v2 of [] => 0 y :: s => (* Hovedtilfellet. v1 er listen x::r, mens v2 er listen y::s *) case (x,y) of (tall(i),tall(j)) => i*j + hyperdotprod(r,s) (liste(l),liste(k)) => hyperdotprod(l,k) + hyperdotprod(r,s) _ => raise syntaksfeil ); 4. Det er ikke mulig å erstatte typen hypervektor med a list av to grunner: For det første kan vi ha ulik nesting innenfor samme hypervektor. For eksempel vil hypervektoren [[1,2],[[3,4,5]]] være en liste bestående av en int list og en int list list. Dette er ikke mulig i ML, heller ikke med typen a list. For det andre trenger vi i funksjonen hyperdotprod å vite om elementene vi skal ta produktet av er tall eller lister, for å vite om vi skal bruke vanlig multiplikasjon eller et rekursivt kall på hyperdotprod. Oppgave 6: Hypervektorer: Språkvalg Det viktigste her er at kriteriene er fornuftige, og at det er konsistens mellom kriteriene, språkvalget og begrunnelsen. Siden det at man behersker et språk ofte er den viktigste begrunnelsen for språkvalget, har jeg tatt dette kriteriet med i mitt forslag til kriterieliste: Jeg kan språket Språket må tillate rekursjon Språket må tillate overlasting av operatorer og dynamisk binding Det er lite bruk for tilordning (assignment) Lite behov for eksplisitte løkkekonstruksjoner bedre om iterasjonene er implisitte... hvilket peker i retning av et funksjonelt språk, for eksempel ML! 9