Skip to content

Commit

Permalink
Merge branch 'master' of git@github.com:johang88/haskellinjavascript
Browse files Browse the repository at this point in the history
  • Loading branch information
Johan Gustafsson committed May 17, 2010
2 parents 7884526 + b205e21 commit bddc88d
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 31 deletions.
1 change: 1 addition & 0 deletions hs/Prelude.hs
Expand Up @@ -29,6 +29,7 @@ otherwise = True


id x = x id x = x



map f xs = case xs of map f xs = case xs of
[] -> [] [] -> []
(x:xs) -> f x : map f xs (x:xs) -> f x : map f xs
Expand Down
2 changes: 1 addition & 1 deletion rapport/kapitel/abstract.tex
@@ -1,9 +1,9 @@
\renewcommand{\abstractname}{Abstract} \renewcommand{\abstractname}{Abstract}
\begin{abstract} \begin{abstract}
Haskell is not a widely used programming language, nor very known to the average programmer. By implementing a subset of the Haskell 98 specification in Javascript our intention is to make it possible to run Haskell in a web browser, thus making it easier for beginners to try Haskell by eliminating the need of downloading Haskell compilers such as GHC. Haskell is not a widely used programming language, nor very known to the average programmer. By implementing a subset of the Haskell 98 specification in Javascript our intention is to make it possible to run Haskell in a web browser, thus making it easier for beginners to try Haskell by eliminating the need of downloading Haskell compilers such as GHC.
In this paper we describe the process and result from the project of implementing Haskell in Javascript.
\\ \\
\\ \\
In this paper we describe the process and result from the project of implementing Haskell in Javascript.
Our result consists of a parser, type checker, interpreter and a front end similar to GHCi. Our result consists of a parser, type checker, interpreter and a front end similar to GHCi.
The parser process the text input, creating an internal structure called abstract syntax tree (AST). The type checker then analyse the AST to confirm that there are no type errors. If no errors have been detected, the AST is sent to the interpreter. The interpreter then interpret the AST in an well defined way. The parser process the text input, creating an internal structure called abstract syntax tree (AST). The type checker then analyse the AST to confirm that there are no type errors. If no errors have been detected, the AST is sent to the interpreter. The interpreter then interpret the AST in an well defined way.
\\ \\
Expand Down
4 changes: 3 additions & 1 deletion rapport/kapitel/diskussion.tex
Expand Up @@ -9,7 +9,9 @@ \section{Diskussion}
Vi har inte implementerat NPlusK-pattern i parsern och då de är borttagna i Haskell 2010 \citep{haskell2010} känner vi att det inte behövs. Vi har inte implementerat NPlusK-pattern i parsern och då de är borttagna i Haskell 2010 \citep{haskell2010} känner vi att det inte behövs.




% TODO typcheckaren kom aldrig in.. % TODO typcheckaren kom aldrig in i den slutgiltliga versionen. Ö:




\subsection{Framtida förbättringar} \subsection{Framtida förbättringar}


Expand Down
7 changes: 3 additions & 4 deletions rapport/kapitel/inledning.tex
Expand Up @@ -45,15 +45,14 @@ \subsection{Metod}
%Vi kommer att integrera jQuery \citep{jquery} för att få ett unisont stöd för samtliga webbläsare. jQuery kommer även underlätta arbetet med att skapa ett enkelt och stilrent interaktivt gränssnitt. %Vi kommer att integrera jQuery \citep{jquery} för att få ett unisont stöd för samtliga webbläsare. jQuery kommer även underlätta arbetet med att skapa ett enkelt och stilrent interaktivt gränssnitt.


\subsubsection{Avgränsningar} \subsubsection{Avgränsningar}
Att tolka Haskell i Javascript är inget trivialt projekt och därför kommer inte hela Haskell att implementeras. Vi kommer implementera en delmängd av den version av Haskell som kallas Haskell 98. Att tolka Haskell i Javascript är inget trivialt projekt och därför valde vi att avgränsa implementationen till de mest centrala och viktiga delarna i haskellspecifikationen. De delar vi valde att fokusera på är:
De delar som prioriteras är
\begin{enumerate} \begin{enumerate}
\item{Lambda-funktioner, namngivna funktioner} \item{Lambda-funktioner, namngivna funktioner}
\item{Typer, generella typer, algebraiska datatyper} \item{Typer, generella typer, algebraiska datatyper}
\item{Typklasser} \item{Typklasser}
\item{Pattern matching} \item{Pattern matching}
\item{Guards} \item{Guards}
\end{enumerate} \end{enumerate}
Med dessa delar implementerade kan de flesta enklare haskellprogram köras och bör vara tillräckligt för det stora flertalet nybörjare. Vi kommer ej lägga någon tid på att skapa en användarvänlig webbsida utan fokus kommer ligga på att skapa haskelltolken. Dock kommer en kommandotolk som körs på en webbsida utvecklas för att kunna kommunicera med haskelltolken. Med dessa delar implementerade kan de flesta enklare haskellprogram köras och bör vara tillräckligt för det stora flertalet nybörjare. Vi beslutade att ej lägga någon större tid på att skapa en användarvänlig webbsida, utan fokus låg på att skapa haskelltolken. Dock valde vi att utveckla en kommandotolk som skulle köras på en webbsida för att kunna kommunicera med haskelltolken.
Vi kommer inte lägga någon nämnvärd tid på att optimera haskelltolken utan målet är att göra en fungerande implementation. SLutligen beslutades det att inte optimera haskelltolken utan målet är att göra en fungerande implementation.


68 changes: 47 additions & 21 deletions rapport/kapitel/resultat.tex
Expand Up @@ -154,9 +154,29 @@ \subsubsection{JSParse}






\subsection{Interpretator} \subsection{Interpretatorns struktur}
Interpretatorns uppgift är att tolka det abstrakta syntaxträdet. Under interpreteringen används flera datastrukturer vars uppgift och struktur anges här. Interpretatorns uppgift är att tolka det abstrakta syntaxträdet. Under interpreteringen används flera datastrukturer vars uppgift och struktur anges här.


\subsubsection{HeapPtr}
De flesta implementationer av Haskell använder sig av Lazy Evaluation vilket innebär att en Thunk, ett uttryck, kommer att tvingas maximalt en gång. I vår implementation används HeapPtr som en wrapper runt en Thunk, när en HeapPtr dereferenceras kommer Thunk att tvingas till en Weak Head Normal Form (WHNF) och HeapPtr uppdateras att peka till denna. Eftersom att tvingandet av en Thunk kan resultera i en ny Thunk så tvingas thunken i en loop till dess att resultatet är en WHNF.

\begin{lstlisting}
this.dereference = function() {
if (this.weakHead == undefined) {
// We'll drive the execution here instead of recursing
// in the force method
var continuation = this.thunk;
while (continuation instanceof interpreter.Thunk) {
continuation = continuation.force();
}
this.weakHead = continuation;
this.thunk = null;
}
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.

\subsubsection{Thunk} \subsubsection{Thunk}
En Thunk är en avstannad beräkning, en continuation. En Thunk består av en Env och en Expression. En Thunk är en avstannad beräkning, en continuation. En Thunk består av en Env och en Expression.


Expand Down Expand Up @@ -185,25 +205,6 @@ \subsubsection{Weak Head Normal Form}


En Primitiv är ett Javascript-värde, till exempel en integer eller en double. En Primitiv är ett Javascript-värde, till exempel en integer eller en double.


\subsubsection{HeapPtr}
De flesta implementationer av Haskell använder sig av Lazy Evaluation, vilket innebär att en Thunk kommer att tvingas maximalt en gång. I vår implementation används HeapPtr som en wrapper runt en Thunk, när en HeapPtr dereferenceras kommer Thunk att tvingas till en WHNF och HeapPtr uppdateras att peka till denna. Eftersom att tvingandet av en Thunk kan resultera i en ny Thunk så tvingas thunken i en loop till dess att resultatet är en WHNF.

\begin{lstlisting}
this.dereference = function() {
if (this.weakHead == undefined) {
// We'll drive the execution here instead of recursing
// in the force method
var continuation = this.thunk;
while (continuation instanceof interpreter.Thunk) {
continuation = continuation.force();
}
this.weakHead = continuation;
this.thunk = null;
}
return this.weakHead;
};
\end{lstlisting}

\subsubsection{Env} \subsubsection{Env}
Env är en stack av Javascript hashes, hasharna består av en bindning mellan en Identifier och antingen en HeapPtr eller ett (Pattern, HeapPtr) par. Den andra bindingstypen är resultatet av en VariableDeclaration där man måste utföra en pattern match för att avgöra vilken HeapPtr som hör till vilken Identifier. När man läser ut en Identifier som är bunden enligt den andra typen av binding, kommer en pattern match att utföras och alla identifiers i det pattern som matchas kommer att bindas om som den första typen alternativt en pattern match fail inträffar och ett exception genereras. Env är en stack av Javascript hashes, hasharna består av en bindning mellan en Identifier och antingen en HeapPtr eller ett (Pattern, HeapPtr) par. Den andra bindingstypen är resultatet av en VariableDeclaration där man måste utföra en pattern match för att avgöra vilken HeapPtr som hör till vilken Identifier. När man läser ut en Identifier som är bunden enligt den andra typen av binding, kommer en pattern match att utföras och alla identifiers i det pattern som matchas kommer att bindas om som den första typen alternativt en pattern match fail inträffar och ett exception genereras.


Expand All @@ -219,7 +220,7 @@ \subsubsection{Env}
} }
\end{lstlisting} \end{lstlisting}


\subsection{Abstrakt syntaxträd} \subsection{Abstrakt syntaxträd och evaluering}
Vår AST representeras av javascript-objekt men dess strukturella uppbyggnad ges här av Haskells datadefinitioner. Vår AST representeras av javascript-objekt men dess strukturella uppbyggnad ges här av Haskells datadefinitioner.


\subsubsection{Declaration} \subsubsection{Declaration}
Expand Down Expand Up @@ -276,6 +277,8 @@ \subsubsection{Expression}
throw new Error("No matching clause"); throw new Error("No matching clause");
}; };
\end{lstlisting} \end{lstlisting}
Detta är eval metoden för en Case expression. Här syns hur en ny Env används vid varje alternativ i Case satsen och hur granskaren delas mellan de olika alternativen.

Att evaluera en VariableLookup under en Env är det samma som att leta upp en Identifier i Env-objektet. Att evaluera en VariableLookup under en Env är det samma som att leta upp en Identifier i Env-objektet.


Do, List och ArithmeticSequence är inte evaluerade direkt utan de är avsockrade och sedan evalueras det avsockrade uttrycket. Avsockringsreglerna ges i Haskell 98 standarden \citep{haskell98chap3}. Do, List och ArithmeticSequence är inte evaluerade direkt utan de är avsockrade och sedan evalueras det avsockrade uttrycket. Avsockringsreglerna ges i Haskell 98 standarden \citep{haskell98chap3}.
Expand Down Expand Up @@ -464,3 +467,26 @@ \subsection{HIJi}


HIJi är skapat för att likna GHCi i så stor utsträckning som möjligt. HIJi är skapat för att likna GHCi i så stor utsträckning som möjligt.
Genom att efterlikna GHCi kommer användare känna igen sig när de tar steget från HIJi till GHCi. Det blir för dem ett naturligt steg och kortar inlärningströskeln. Även för haskellprogrammerare som är vana användare av GHCi blir det lättare att använda sig av HIJi, de behöver inte fundera hur verktyget ska användas. Genom att efterlikna GHCi kommer användare känna igen sig när de tar steget från HIJi till GHCi. Det blir för dem ett naturligt steg och kortar inlärningströskeln. Även för haskellprogrammerare som är vana användare av GHCi blir det lättare att använda sig av HIJi, de behöver inte fundera hur verktyget ska användas.

\subsection{Language feutoeeras}

I våra avgränsningar angav vi vilka delar av haskellspecifikationen vi valde att fokusera på.
I vår modul Prelude har vi definerat upp en rad funktioner som visar på exempel på att vi lyckats implemetera det vi fokuserat på.

Vi har stöd för namngivna funktioner och lambda-funktioner. Ett exempel på en namngiven funktion är id.
\begin{lstlisting}
id x = x
\end{lstlisting}

Algebraiska datatyper stöds också. I Prelude har vi definerat upp datatypen Bool och ett par exempel på när vi använder den. I funktionen \emph{(||) x y} har vi också ett exempel på pattern matching. Resultatet av x \emph{case x of} kommer matcha antingen mot \emph{True} eller \emph{False}.
\begin{lstlisting}
data Bool = True | False

(||) x y = case x of
True -> True
False -> y
\end{lstlisting}


Guards %TODO filter från johan

8 changes: 4 additions & 4 deletions rapport/kapitel/sammanfattning.tex
Expand Up @@ -2,14 +2,14 @@


\begin{abstract} \begin{abstract}


Haskell är ett programmeringsspråk med hög inlärningströskel med en begränsad användarbas. Vår förhoppning är att göra det enklare för programmerare att lära sig Haskell genom att implementera språket I Javascript. På så vis blir det möjligt att köra Haskell I en webbläsare utan att behöva ladda ner en haskellkompilator som till exempel GHC. Haskell är ett programmeringsspråk med en begränsad användarbas. Vår förhoppning är att göra det enklare för programmerare att lära sig Haskell genom att implementera språket i Javascript. På så vis blir det möjligt att köra Haskell i en webbläsare utan att behöva ladda ner en haskellkompilator, som till exempel GHC.
I den här rapporten beskriver vi vårt arbete och resultat av att implementera Haskell I Javascript. I den här rapporten beskriver vi vårt arbete och resultat av att implementera Haskell i Javascript.
\\ \\
\\ \\
Resultatet består av en parser, typcheckare, interpretator och ett användargränssnitt liknande GHCi. Resultatet består av en parser, typcheckare, interpretator och ett användargränssnitt liknande GHCi.
Parsern tar användaren indata och konverterar den till en intärn datastruktur, kallat abstrakt syntaxträd. Typcheckaren analyserar sedan det abstrakta syntaxträdet för att kontrollera att det ej förekommer några syntaxfel. Om inga fel påträffats så skickas det trädet vidare till interpretatorn som tolkar trädet på ett väldefinerat vis. Parsern tar användaren indata och konverterar den till en intärn datastruktur, kallat abstrakt syntaxträd. Typcheckaren analyserar sedan det abstrakta syntaxträdet för att kontrollera att det ej förekommer några typfel. Om inga fel har påträffats så skickas trädet vidare till interpretatorn som tolkar trädet på ett väldefinerat vis.
\\ \\
\\ \\
Resultatet visar att det är möjligt att implementera Haskell I Javascript, men det behövs mycket mer arbete för att skapa en nybörjarvänlig miljö att lära sig Haskell I. Resultatet visar att det är möjligt att implementera Haskell i Javascript, men det behövs mycket mer arbete för att skapa en nybörjarvänlig miljö att lära sig Haskell i.


\end{abstract} \end{abstract}

0 comments on commit bddc88d

Please sign in to comment.