Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

fixed spelling errors

  • Loading branch information...
commit 28dd2dc6b03ea7b9765907125305be50f7b101a1 1 parent 763d95f
Johan Gustafsson authored
Showing with 17 additions and 18 deletions.
  1. +17 −18 rapport/kapitel/resultat.tex
View
35 rapport/kapitel/resultat.tex
@@ -6,13 +6,13 @@ \section{Resultat}
\subsection{Parser}
Parserns uppgift är att ta användarens indata och konvertera den till en datastruktur
som är lättare att hantera internt. Denna datastruktur kallas Abstract Syntax Tree (AST).
-Haskellstandarden har definerat upp en grammatik, ett antal regler, som definerar hur korrekt haskellkod ser ut och hur den ska tolkas.
+Haskellstandarden har definierat upp en grammatik, ett antal regler, som definierar hur korrekt haskellkod ser ut och hur den ska tolkas.
Haskell är ett svårt språk att parsa då det inte är kontextfritt på grund av att kodens mening beror på blanksteg,
-Haskell tillåter även egendefinerade operatorer vilket också kan påverka kodens mening.
+Haskell tillåter även egendefinierade operatorer vilket också kan påverka kodens mening.
För att parsa indatan använder vi ett bibliotek för att bygga parsers kallat JSParse \citep{jsparse}.
-JSParse ger oss ett antal funktioner som vi använder för att definera grammatiken och konvetera den till vår interna struktur.
+JSParse ger oss ett antal funktioner som vi använder för att definiera grammatiken och konvertera den till vår interna struktur.
Som figur \ref{fig:parser_steg} visar, består parsern av tre mindre parsers, den första är en parser som hittar kommentarer och tar bort dessa.
Det andra tar hand om kodens layout och gör om den till kontextfri kod. Den tredje gör om den kontextfria koden till vår AST.
@@ -66,7 +66,7 @@ \subsubsection{Steg 1 - Ta bort kommentarer}
\subsubsection{Steg 2 - Konvertera till kontextfri}
Det andra steget delar upp koden i dess ord och symboler samtidigt som den dekoreras med indenteringsnivåer enligt en algoritm % TODO vilken algoritm, k'a'lla
-som är specifierad i haskellstandarden. Därefter användads en annan algoritm från standarden för att sätta in måsvingar och semikolon på rätt platser. % samma, vilken algoritm, TODO
+som är specificerad i haskellstandarden. Därefter användads en annan algoritm från standarden för att sätta in måsvingar och semikolon på rätt platser. % samma, vilken algoritm, TODO
När de två algoritmerna är klara sätts koden ihop igen och skickas vidare till nästa steg.
En regel är att ett inre block inte får vara mindre indenterat än det omslutande blocket, exempelivs:
@@ -106,8 +106,8 @@ \subsubsection{Steg 2 - Konvertera till kontextfri}
med en avslutande måsvinge påträffas sätts måsvingen in precis innan symbolen.
\subsubsection{Steg 3 - Skapa AST}
-Det tredje steget är en parser för den kontextfria varianten av Haskell som den är definerad i standarden.
-Samtidigt som koden tolkas byggs en AST upp. Parsern består av en liten parser för varje grammatisk regel som är definerad i haskellstandarden
+Det tredje steget är en parser för den kontextfria varianten av Haskell som den är definierad i standarden.
+Samtidigt som koden tolkas byggs en AST upp. Parsern består av en liten parser för varje grammatisk regel som är definierad i haskellstandarden
dessa parsers kombineras ihop för att bilda den slutgiltliga parsern. Det resulterar i ett träd av parsers, en parser för hela programmet som har flera mindre parsers under sig.
Exempel:
@@ -135,8 +135,8 @@ \subsubsection{Steg 3 - Skapa AST}
ser vi att det är en rekursiv funktionen vilket vi implementerar med \emph{repeat1} för att få en lista med minst en uppreprning,
\emph{gdrhs\_action}, \emph{gdrhs\_fix\_list\_action} och \emph{decl\_rhs\_action} används för att generera AST.
-Parsern använder den metod som är specifierad i Haskell 2010 \citep{haskell2010} för att lösa företrädesreglerna (precedence levels) för operatorer då denna metoden är enklare än den som är definerad i Haskell 98.
-Anledningen till att företrädesreglerna inte kan defineras direkt i parsern är att Haskell använder sig av användardefinerade företrädesregler.
+Parsern använder den metod som är specifierad i Haskell 2010 \citep{haskell2010} för att lösa företrädesreglerna (precedence levels) för operatorer då denna metoden är enklare än den som är definierad i Haskell 98.
+Anledningen till att företrädesreglerna inte kan defineras direkt i parsern är att Haskell använder sig av användardefinierade företrädesregler.
Metoden fungerar så att den löser företrädesreglerna först efter ett uttryck har parsats till en lista med operatorer
och uttryck, när en operator påträffas i listan slås dess företrädesnivå upp i en tabell och ett träd med
operatorer och uttryck skapas. Sista används trädet för att generera en AST för uttrycken.
@@ -149,7 +149,7 @@ \subsubsection{JSParse}
Parsers som vi har lagt till:
\begin{enumerate}
\item{\emph{repeatn}: en parser som upprepar en parser minst \emph{n} antal gånger}
- \item{\emph{expectws}: en parser som tillåter blanksteg och inte retunerar någon ast, är en kombination av JSParse inbyggda parsers \emph{expect} och \emph{whitespace}}
+ \item{\emph{expectws}: en parser som tillåter blanksteg och inte returnerar någon ast, är en kombination av JSParse inbyggda parsers \emph{expect} och \emph{whitespace}}
\end{enumerate}
@@ -175,7 +175,7 @@ \subsubsection{HeapPtr}
return this.weakHead;
};
\end{lstlisting}
-En HeapPtr är ett vanligt Javascript-objekt som innehåller funktionen dereference. Dereference körs när anroparen vill använda den WHNF som HeapPtr pekar mot. Om HeapPtr inte har blivit dereferenserad innan så kommer dess Thunk att tvingas tills det att resultatet är en WHNF och HeapPtr objectet uppdateras till att peka mot denna.
+En HeapPtr är ett vanligt Javascript-objekt som innehåller funktionen dereference. Dereference körs när anroparen vill använda den WHNF som HeapPtr pekar mot. Om HeapPtr inte har blivit dereferenserad innan så kommer dess Thunk att tvingas tills det att resultatet är en WHNF och HeapPtr-objektet uppdateras till att peka mot denna.
\subsubsection{Thunk}
En Thunk är en avstannad beräkning, en continuation. En Thunk består av en Env och en Expression.
@@ -187,7 +187,7 @@ \subsubsection{Thunk}
Haskell måste använda sig av non-strict evaluation vilket innebär att en uträkning inte får köras ifall den inte behövs. När en uträkning körs så innebär det att den resulterar i flertalet Thunks för de delar av beräkningen som ännu inte behövs. När värdet av en Thunk behövs kommer den att tvingas till en \emph{weak head normal form} (WHNF) eller en ny Thunk. Anledningen till detta är att vi på så sätt minskar användandet av rekursion vilket minskar risken att vi får ett runtime error.
\subsubsection{Weak Head Normal Form}
-En WHNF är ett partiellt evaluerat uttryck. Uttrycket har blivit evaluerat så långt att vi är säkra på att det retunerar något typ av värde, alltså något som inte är undefined. Ofta innehåller en WHNF referenser till ännu icke evaluerade uttryck, om de inte gör det sägs uttrycket vara i Normal Form.
+En WHNF är ett partiellt evaluerat uttryck. Uttrycket har blivit evaluerat så långt att vi är säkra på att det returnerar något typ av värde, alltså något som inte är undefined. Ofta innehåller en WHNF referenser till ännu icke evaluerade uttryck, om de inte gör det sägs uttrycket vara i Normal Form.
\begin{lstlisting}
data WeakHead
@@ -366,12 +366,12 @@ \subsubsection{Representation av kinds, typer, typscheman och typklasser}
\end{lstlisting}
Ett predikat \emph{Pred className type} säger att typen \emph{type} tillhör typklassen \emph{className}.
-Ofta består typer av flera sammansatta enklare typer där olika typer kan tillhöra olika typklasser. För att modellera detta används kvalifierade typer:
+Ofta består typer av flera sammansatta enklare typer där olika typer kan tillhöra olika typklasser. För att modellera detta används kvalificerade typer:
\begin{lstlisting}
data Qual = Qual [Pred] Type
\end{lstlisting}
-Den kvalifierade typen \emph{Monad m => m a} modelleras som:
+Den kvalificerade typen \emph{Monad m => m a} modelleras som:
\begin{lstlisting}
(Qual
[ Pred "Monad" (TVar "m" (Kfun Star Star)) ]
@@ -404,8 +404,7 @@ \subsubsection{Substitueringar}
Substitueringar är mappningar \emph{typvariabel -> typ} och används av typcheckaren
för att hålla typer uppdaterade efterhand som den får ny
information. Typcheckaren innehåller flera funktioner som opererar på
-substitutioner, bland annat komponering och sammanfogning av
-substitutioner.
+substitutioner, bland annat sammansättning av substitutioner. %% TODO var ursprungligen "komponering och sammanfognin" ska det vara två olika begrepp?
\emph{Unifiering} är processen att finna en substituering som gör två typer ekvivalenta. Detta är viktigt exempelvis i uttryck {\bf if} \emph{e1} {\bf then} \emph{e2} {\bf else} \emph{e3}. Här måste typen för \emph{e1} gå att unifiera med typen \emph{Bool} och \emph{e2} och \emph{e3} måste gå att unifiera till en och samma typ. Om någon av dessa unifieringar inte är möjliga betyder det att typfel finns.
@@ -417,7 +416,7 @@ \subsubsection{Typinferens}
data Assump = Assump Id Scheme
\end{lstlisting}
-Typinferensen är beroende av att en antal komponenter finns tillgängliga. Dessa är registret över typklasser och instanser \emph{KlassEnv}, listan över antagna variabeltyper, en generator för unika typvariabler med funktionen \emph{newTVar} och substitueringas \emph{Subst}. Dessa samlas i objektet \emph{Environment} som skickas som argument till funktionerna i typinferensen.
+Typinferensen är beroende av att en antal komponenter finns tillgängliga. Dessa är registret över typklasser och instanser \emph{KlassEnv}, listan över antagna variabeltyper, en generator för unika typvariabler med funktionen \emph{newTVar} och substitueringarnas \emph{Subst}. Dessa samlas i objektet \emph{Environment} som skickas som argument till funktionerna i typinferensen.
För att bättre illustrera hur typinfereringsprocessen går till ger vi ett konkret exempel. Koden nedan visar hur typinferering av \emph{if}-uttryck går till. Eftersom vårt projekt avsockrar \emph{if}-uttryck till \emph{case} använder det inte exempelkoden men då den på ett bra sätt illustrerar konceptett väljer vi här ändå att använda den:
\begin{lstlisting}
@@ -435,7 +434,7 @@ \subsubsection{Typinferens}
};
};
\end{lstlisting}
-Först infereras typen på vilkoret. Detta unifieras med typen \emph{Bool} på raden under. Sedan infereras typerna på \emph{then}- respektive \emph{else}-delarna och då dessa måste vara va samma typ unifieras deras typer. Om typerna inte går att unifiera innebär det att dess returtyper är distinkta och att det därför finns typfel. Till sist returneras de insamlade predikaten från både \emph{then}- och \emph{else}-delarna tillsammans med den unifierade typen.
+Först infereras typen på villkoret. Detta unifieras med typen \emph{Bool} på raden under. Sedan infereras typerna på \emph{then}- respektive \emph{else}-delarna och då dessa måste vara va samma typ unifieras deras typer. Om typerna inte går att unifiera innebär det att dess returtyper är distinkta och att det därför finns typfel. Till sist returneras de insamlade predikaten från både \emph{then}- och \emph{else}-delarna tillsammans med den unifierade typen.
Av detta exempel kan ett antal slutsatser dras. Typinfereringen sker rekursivt från sammansatta uttryck ner till de alla enklaste literalerna. Att misslyckande av unifiering betyder typfel innebär att inferera-unifiera-cykeln har en roll liknande den infer-check har vid typcheckning i exempelvis C.
@@ -467,7 +466,7 @@ \subsection{HIJi}
\subsection{Prelude}
I våra avgränsningar angav vi vilka delar av haskellspecifikationen vi skulle fokusera på. De delar som vi har fullt stöd för är lambda-funktioner, namngivna funktioner, algebraiska datatyper, pattern matching och guards.
I HIJis förladdade modul, Prelude, har vi definerat upp ett antal funktioner som visar på att vi har implementerat dessa egenskaper från specifikationen.
-Alla funktioner som är definerade i Prelude är namngivna funktioner. Ett exempel på en namngiven funktion är \emph{id}.
+Alla funktioner som är definierade i Prelude är namngivna funktioner. Ett exempel på en namngiven funktion är \emph{id}.
Algebraiska datatyper stöds och i Prelude har vi definerat upp datatypen Bool och ett par funktioner, däribland (||), som använder sig utav den här datatypen. Funktionen (||) använder sig av pattern matching. Resultatet av \emph{case x of} kommer matcha antingen mot \emph{True} eller \emph{False}.
Funktionen \emph{filter} från Prelude är ett exempel på att guards fungerar. Filter är också ett exempel på att pattern matching och rekursiva funktioner är implementerade.
Please sign in to comment.
Something went wrong with that request. Please try again.