Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of git@github.com:johang88/haskellinjavascript

  • Loading branch information...
commit 831dacf3dafb41ff9c3317d83d73e85e671ede0c 2 parents d0b05d1 + c5a6d7a
Mikael Bung authored
View
6 haskell.ast.js
@@ -108,7 +108,7 @@
this.expr = expr;
this.eval = function(env) {
var newEnv = interpreter.loadDeclarations(this.declr, env.derive());
- return this.expr.eval(newEnv);
+ return new interpreter.Closure(newEnv, this.expr);
};
this.stringify = function() {
return "let {" + this.declr.map(function (d) {
@@ -127,7 +127,7 @@
for (var i in this.cases) {
var newEnv = env.derive();
if (this.cases[i][0].match(newEnv, expr)) {
- return this.cases[i][1].eval(newEnv);
+ return new interpreter.Closure(newEnv, this.cases[i][1]);
};
};
throw new Error("No matching clause");
@@ -202,7 +202,7 @@
var funname = 'enumFrom';
if (this.e2) funname = funname + 'Then';
if (this.e3) funname = funname + 'To';
- var application = new ast.Application(ast.VariableLookup(funname), this.e1);
+ var application = new ast.Application(new ast.VariableLookup(funname), this.e1);
if (this.e2) application = new ast.Application(application, this.e2);
if (this.e3) application = new ast.Application(application, this.e3);
return application;
View
6 haskell.hiji.js
@@ -115,12 +115,12 @@ commands[":help"] = "HELP";
for (var i = 0; i < result.ptrs.length; i++) {
if (str.length == 0 && first) {
str = showResult(result.ptrs[i].dereference());
- if (str.str)
+ if (typeof str.str != "undefined")
str = str.str;
first = false;
} else {
var res = showResult(result.ptrs[i].dereference());
- if (res.str)
+ if (typeof res.str != "undefined")
res = res.str;
str = str + op + res;
}
@@ -142,7 +142,7 @@ commands[":help"] = "HELP";
result = result.str;
result = result.substring(0, result.length - 3);
result = "[" + result + "]";
- } else if (result.str) {
+ } else if (typeof result.str != "undefined") {
result = result.str;
}
View
8 haskell.interpreter.js
@@ -228,8 +228,8 @@
this.pattern = pattern;
this.expression = expression;
this.apply = function(argument) {
- var substitution = this.env.substitute(this.pattern, argument);
- return this.expression.eval(substitution);
+ var newEnv = this.env.substitute(this.pattern, argument);
+ return new interpreter.Closure(newEnv, this.expression);
};
this.stringify = function() {
@@ -260,11 +260,11 @@
var expression = matchedFunc.expression[j][1];
var guardResult = guard.eval(newEnv);
if (guardResult.identifier == "True") {
- return expression.eval(newEnv);
+ return new interpreter.Closure(newEnv, expression);
}
}
} else {
- return matchedFunc.expression.eval(newEnv);
+ return new interpreter.Closure(newEnv, matchedFunc.expression);
}
}
}
View
7 haskell.parser.js
@@ -406,7 +406,10 @@
}
var aexp_arithmetic_action = function(p) {
- return action(p, function(ast) {
+ return action(p, function(ast) {
+ if (ast[1]) {
+ ast[1] = ast[1][0];
+ }
return new haskell.ast.ArithmeticSequence(ast[0], ast[1], ast[2]);
});
}
@@ -431,7 +434,7 @@
aexp_tuple_action(sequence(expectws('('), ws(exp), repeat1(sequence(ws(','), ws(exp))) , expectws(')'))), // tuple
list_action(sequence(expect(ws('[')), optional(wlist(exp, ',')), expect(ws(']')))), // list constructor
left_section_action(sequence(expect(ws('(')), ws(infixexp), ws(qop), expect(ws(')')))), // left section
- right_section_action(sequence(expect(ws('(')), ws(qop), ws(infixexp), expect(ws(')')))), // right section, todo: look into resolution of infixexp in this case, see Haskell Report Chapter 3
+ right_section_action(sequence(expect(ws('(')), ws(qop), ws(infixexp), expect(ws(')')))), // right section, todo: look into resolution of infixexp in this case, see Haskell Report Chapter 3
aexp_arithmetic_action(sequence(expectws('['), ws(exp), optional(sequence(expectws(','), ws(exp))), expectws('..'), optional(ws(exp)), expectws(']'))), // arithmetic sequence
aexp_list_comp_action(sequence(expectws('['), ws(exp), expectws('|'), list(qual, ws(',')), expectws(']'))) // list comprehension
// Todo:
View
39 hs/Prelude.hs
@@ -47,8 +47,11 @@ foldr1 f xs = case xs of
filter _ [] = []
filter f (x:xs ) | f x = x : filter f xs
| otherwise = filter f xs
+
+iterate f x = f x : iterate f (f x)
-iterate f x = f x : iterate f x
+zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
+zipWith _ _ _ = []
head xs = case xs of
(x:_) -> x
@@ -73,6 +76,16 @@ data Int = I# Int#
(==) (I# i1) (I# i2) = i1 ==# i2
+(>) (I# i1) (I# i2) = i1 ># i2
+
+(<) (I# i1) (I# i2) = i1 <# i2
+
+(<=) (I# i1) (I# i2) = i1 <=# i2
+
+(>=) (I# i1) (I# i2) = i1 >=# i2
+
+(%) (I# i1) (I# i2) = I# (remInt# i1 i2)
+
stepDebug = stepDebug#
data Maybe a = Just a | Nothing
@@ -108,3 +121,27 @@ double m = do
let doubleFunc = (*2)
x <- m
return (doubleFunc x)
+
+
+take 0 _ = []
+take n (x:xs) = x : take (n-1) xs
+take _ [] = []
+
+length [] = 0
+length (_:xs) = 1 + length xs
+
+
+const r _ = r
+
+-- Enum functions only for int so far, awaiting type classes
+enumHelper i p n = case p n of
+ True -> []
+ False -> n : enumHelper i p (n+i)
+
+enumFrom e1 = enumHelper 1 (const False) e1
+
+enumFromThen e1 e2 = enumHelper (e2-e1) (const False) e1
+
+enumFromTo e1 e3 = enumHelper 1 (>e3) e1
+
+enumFromThenTo e1 e2 e3 = enumHelper (e2-e1) (>e3) e1
View
250 rapport/MasterThesis.tex
@@ -0,0 +1,250 @@
+% USE PDFLATEX WITH THIS DOCUMENT. If you wish to use ordinary latex (why?) then convert the figures in figures/ to eps.
+% If you are using Chalmers linux system, you might need to change to a newer tex dist.
+% Do so with: vcs-what latex
+% look up the newest version and select it, a.t.m that would be: vcs-select -p texlive-20080816
+% I recommend using kile in linux. Make it available by adding the unsup software
+% echo unsup ~/.vcs4/pathsetup
+\documentclass[a4paper,12pt]{article}
+
+\usepackage[T1]{fontenc}
+\usepackage[swedish]{babel}
+%\usepackage[latin1]{inputenc} % Use the same as the encoding of the textfile
+\usepackage[utf8]{inputenc} % But this is probably the best choice. This doument is currently in utf8 (so is all other files)
+\usepackage{amsmath,amsfonts,amsthm,mathtools} % Math. Look up the amsmath manual (google) for many great examples.
+\usepackage{graphicx,placeins,float} % Figures and placements, float must be loaded before hypperref
+\usepackage[colorlinks,citecolor=blue]{hyperref} % Warning this package conflicts with the package algorithm
+\usepackage{fancyhdr,url,tikz} % Other usefull stuff. tikz is good for making drawings (but difficult)
+\usepackage{listings} % Source code
+% \usepackage{a4wide} % Gives a wider page
+\usepackage{mycommands} % Here you can define your personal favourites. See mycommands.cls
+\usepackage{pgfplots} % Anoth nice library for plots
+
+\usepackage{natbib} % ger Harvard-referenser
+
+
+%mina andringar för att få riktiga paragrafer vid radbrytning
+\setlength{\parskip}{12pt}
+\setlength{\parindent}{0pt}
+
+
+
+% mysubtitle, cover* and divisionnameB may be uncommented if nonexistant.
+\newcommand{\mytitle}{Haskell in Javascript}
+%\newcommand{\mysubtitle}{Some subtitle}
+\newcommand{\writtenmonth}{May}
+\newcommand{\writtenyear}{2010}
+\newcommand{\authors}{Adam Bengtsson\\Mikael Bung\\Johan Gustafsson\\Mattis Jeppsson}
+\newcommand{\authorsc}{ Adam Bengtsson, Mikael Bung, Johan Gustafsson, \\Mattis Jeppsson} % again with comma
+\newcommand{\YYYYNN}{2010:05}
+%\newcommand{\ISSN}{1652-8557}
+%\newcommand{\covercaption}{Haskell 98 implementerat i Javascript för att köras i en webbläsare}
+% \newcommand{\coverfigure}{figures/COVER_93_iso.png}
+\newcommand{\departmentname}{Computer Science and Engineering}
+\newcommand{\divisionnameA}{Computer Engineering}
+%\newcommand{\divisionnameB}{Fluid Mechanics}
+% \newcommand{\nameofprinters}{Chalmers Reproservice}
+\newcommand{\nameofprogramme}{Computer Science and Engineering Programme}
+\newcommand{\keywords}{Javascript, Haskell, Parser, Interpreter, Type Checker}
+% This is just to keep the swedish letters at one place in case there are problems with encoding
+\newcommand{\city}{Göteborg}
+\newcommand{\country}{Sweden}
+\newcommand{\university}{Chalmers University of Technology\\ Gothenburg University}
+\newcommand{\thesis}{Bachelor's thesis}
+\newcommand{\telephone}{+ 46 (0)31-772 1000}
+\newcommand{\postcode}{SE-412 96}
+% End of input.
+
+% Use section number first in numbering
+\numberwithin{equation}{section}
+\numberwithin{figure}{section}
+\numberwithin{table}{section}
+
+% Setting up the marginals a bit larger
+%\textheight=730pt % default 609pt, ~710 if you dont use a4wide
+%\headsep=0pt % default 25pt, since we have no headers in this document
+%\headheight=0pt% 12 pt
+%\voffset=-0.4in % default 0
+
+% Set up headers to match styleguide
+\pagestyle{fancy}
+\renewcommand{\headrulewidth}{0pt}
+\fancyhead{}
+\fancyfoot{}
+\fancyfoot[C]{\footnotesize \includegraphics[height=2.5mm]{figures/Logo.pdf}, \textit{\departmentname}, \thesis\ \YYYYNN}
+\fancyfoot[RO,LE]{\thepage}
+
+% To use code use \lstinputlisting[langauge=matlab,style=mystyle]{somematlabfile.m}
+% Here is a suitable style for code.
+
+%\lstset{language=Haskell}
+%\lstset{keywordstyle=\color{blue}\textbf}
+%\lstset{stringstyle=\color{red}}
+
+\lstdefinestyle{mystyle}{showstringspaces=false, basicstyle=\scriptsize\ttfamily,
+ frame=shadowbox, breaklines=true, numbers=left, commentstyle=\color{gray},
+ keywordstyle=\color{blue}\textbf, stringstyle=\color{red}}
+
+% Metadata ion the PDF file (makes it searchable)
+\hypersetup{pdfauthor={\authorsc},pdftitle={\mytitle},pdfsubject={\thesis},pdfkeywords={\keywords}}
+
+% The following part is automatically generated, go to document start
+\begin{document}
+\thispagestyle{empty}
+\begin{tikzpicture}[remember picture,overlay]
+ \node[yshift=-6.4cm] at (current page.north west)
+ {\begin{tikzpicture}[remember picture, overlay]
+ % First draw the grid and then the Logo and avancez logo.
+ \draw[clip] (0cm,6.4cm)--(\paperwidth,6.4cm)--(\paperwidth,0cm)--(0.725\paperwidth,0cm)
+ .. controls (0.703\paperwidth,0) and (0.703\paperwidth,0.8cm)..
+ (0.68\paperwidth,0.8cm)--(0cm,0.8cm)--cycle;
+ \draw[step=5mm,black] (0,0) grid (\paperwidth,6.4cm);
+ \node[anchor=west,xshift=2.05cm,yshift=3.27cm,rectangle]{\includegraphics[width=13.2cm]{figures/Logo.pdf}};
+ \node[anchor=west,xshift=15.65cm,yshift=3.3cm,rectangle]{\includegraphics[width=3.6cm]{figures/Avancez.pdf}};
+ % \node[anchor=west,xshift=1.15cm,yshift=0.1cm,rectangle]{\includegraphics[width=13.2cm]{figures/gulogga.png}};
+
+ \end{tikzpicture}};
+\end{tikzpicture}
+\ \vfill
+\makeatletter\@ifundefined{coverfigure}{}{
+ \begin{center}
+ \includegraphics[width=\textwidth,height=0.4\paperheight,keepaspectratio]{\coverfigure}
+ \end{center}
+}\makeatother
+{\huge\noindent \mytitle\par} % title, 21
+{\large\noindent \ \par} % subtitle, 16
+%{\normalsize\noindent\textit{Master of Science Thesis}\par};
+{\normalsize\noindent\textit{\thesis\ in \nameofprogramme}\par} % 14
+\vskip 5mm
+{\Large\noindent \uppercase\expandafter{\authors}\par}% 18
+\vskip 6mm
+{\small\noindent
+Department of \departmentname\\
+\textit{Division of \divisionnameA}
+\makeatletter\@ifundefined{divisionnameB}{}{\textit{and Division of \divisionnameB}}\makeatother\\
+\uppercase\expandafter{\university}\\
+\city, \country\ \writtenyear\\
+\thesis\ \YYYYNN\par}
+
+ \newpage
+\thispagestyle{empty}
+\mbox{}
+
+\newpage
+\thispagestyle{empty}
+\begin{center}
+ {\uppercase\expandafter{\thesis}\ \YYYYNN\par}
+ \vskip 40mm
+ {\Large \mytitle\par}
+ \vskip 5mm
+ \makeatletter\@ifundefined{mysubtitle}{}{{\mysubtitle\par}}\makeatother
+ \vskip 5mm
+ {\thesis\ in \nameofprogramme\par} % (if applicable) (if applicable)
+ {\uppercase\expandafter{\authors}\par}
+ \vfill
+ {Department of Computer Science\par}
+ {\textit{Division of \divisionnameA}
+ \makeatletter\@ifundefined{divisionnameB}{}{\textit{and Division of \divisionnameB}}\makeatother
+ \par}
+ {\uppercase\expandafter{\university}\par}
+ \vskip 2mm
+ {\city, \country\ \writtenyear\par}
+\end{center}
+
+\newpage
+{\noindent \mytitle\\
+\makeatletter\@ifundefined{mysubtitle}{}{\mysubtitle\\}\makeatother
+{\uppercase\expandafter{\authors}}\par}
+\vskip 10mm
+{\noindent \copyright {\uppercase\expandafter{\authorsc}}, \writtenyear\par}
+\vskip 20mm
+{\noindent \thesis\ \YYYYNN\\
+Department of \departmentname\\
+\makeatletter\@ifundefined{divisionnameB}{}{ and Division of \divisionnameB}\makeatother
+\\
+\university\\
+\postcode\ \city\\
+\country\\
+Telephone: \telephone\par}
+\vfill
+\makeatletter\@ifundefined{covercaption}{}{{\noindent Cover:\\\covercaption\par}\vskip 5mm}\makeatother
+{\noindent \nameofprinters
+%/ Department of \departmentname
+\\\city, \country\ \writtenyear\par}
+\thispagestyle{empty}
+
+\newpage
+%\thispagestyle{justpage}
+\setcounter{page}{1}
+\pagenumbering{Roman}
+%{\noindent \mytitle\\
+%\makeatletter\@ifundefined{mysubtitle}{}{\mysubtitle\\}\makeatother
+%\thesis\ in \nameofprogramme\\ % (if applicable)
+%{\uppercase\expandafter{\authors}}\\
+%Department of \departmentname\\
+%Division of \divisionnameA
+%\makeatletter\@ifundefined{divisionnameB}{}{ and Division of \divisionnameB}\makeatother\\
+%\university\par}
+
+
+\hyphenpenalty=10000
+\tolerance=5000
+
+%\hyphenation{dereference,heapptr,expression} %, typcheckaren, miss-lyckande, ghci, haskelltolk, haskell, typinformation, javascript, interpreter, programmering, interpretatorn, functions, haskell-kompilator, lambda, modul, exempelvis, grammatik, interpreteringen, pekar, av-sockrar, upp-byggnad, funktions-defenitioner, returnera, av-sockrade, skickas }
+
+\phantomsection\addcontentsline{toc}{section}{Abstract}\input{kapitel/abstract}
+%\noindent Keywords: \keywords
+
+% Either a swedish translation, or an emtpy page.
+\newpage
+\phantomsection\addcontentsline{toc}{section}{Sammanfattning}\input{kapitel/sammanfattning}
+
+\newpage
+\mbox{}
+
+%\newpage
+\phantomsection\addcontentsline{toc}{section}{Innehåll}
+\tableofcontents
+
+% Here you can add preface and notations
+%\cleardoublepage
+%\phantomsection\addcontentsline{toc}{section}{Preface}\input{Preface}
+%\vskip 1cm
+%\noindent \city\ \writtenmonth\ \writtenyear\\
+%\authorsc
+%\newpage
+%\phantomsection\addcontentsline{toc}{section}{Notations}\input{Notations}
+
+\cleardoublepage
+\setcounter{page}{1}
+\pagenumbering{arabic}
+
+
+% Real contents of report starts here
+% Splitting it up to several files help when working together.
+% Floatbarriers prevent figures from beeing placed into the next chapter.
+\input{kapitel/inledning}\FloatBarrier
+\newpage
+%\input{kapitel/teori}\FloatBarrier
+%\newpage
+\input{kapitel/metod.tex}\FloatBarrier
+\newpage
+\input{kapitel/resultat.tex}\FloatBarrier
+\newpage
+\input{kapitel/diskussion.tex}\FloatBarrier
+\newpage
+\input{kapitel/slutsatser.tex}\FloatBarrier
+\newpage
+% \input{Method}\FloatBarrier
+% \input{Results}\FloatBarrier
+% \input{Conclusions}
+% \input{Recommendations}
+
+% And the bilbiography saved as mybib.bib
+\bibliographystyle{plainnat}
+\bibliography{kallor}
+
+% Appendices
+\appendix
+\input{kapitel/appendix.tex}\FloatBarrier
+\end{document}
+
View
BIN  rapport/hiji_screen3.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
33 rapport/kallor.bib
@@ -1,14 +1,16 @@
@misc{csharp,
- author = "Anders Hejlsberg, Mads Torgersen",
+ author = "A. Hejlsberg, M. Torgersen",
title = "Overview of C# 3.0",
year = 2007,
- url = "http://msdn.microsoft.com/en-us/library/bb308966.aspx"
+ url = "http://msdn.microsoft.com/en-us/library/bb308966.aspx",
+ note = "Hämtad 2010-05-15"
}
@misc{ghc,
title = "Glasgow Haskell Compiler",
url = "http://www.haskell.org/ghc/",
- year = 2010
+ year = 2010,
+ note = "Hämtad 2010-05-18"
}
@misc{json,
@@ -22,40 +24,51 @@ @misc{json
@misc{jsparse,
title = "JSParse - Javascript Parser Combinators",
url = "http://www.bluishcoder.co.nz/2007/10/javascript-parser-combinators.html",
- author = "Chris Double",
- year = 2010
+ author = "C. Double",
+ year = 2010,
+ note = "Hämtad 2010-05-18"
}
@misc{jquery,
author = "The jQuery Project",
title = "jQuery",
url = "http://jquery.com/",
- year = 2010
+ year = 2010,
+ note = "Hämtad 2010-05-18"
}
@book{jones87,
- author = "Jones, S. P.",
+ author = "Peyton-Jones, S.",
year = 1987,
title = "The Implementation of Functional Programming Languages",
publisher = "Prentice Hall",
- howpublished = "\url{http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/}"
+ howpublished = "\url{http://research.microsoft.com/en-us/um/people/simonpj/papers/slpj-book-1987/}",
+ note = "Hämtad 2010-05-18"
}
@book{haskell98,
title = "Haskell 98 language and libraries: the Revised Report",
- editor = "S. P. Jones",
+ editor = "S. Peyton-Jones",
year = 2003,
publisher = "Cambridge University Press"
}
@inbook{haskell98chap3,
title = "Haskell 98 Language and Libraries: The Revised Report",
- editor = "S. P. Jones",
+ editor = "S. Peyton-Jones",
year = 2003,
publisher = "Cambridge Univeristy Press",
chapter = 3
}
+@inbook{haskell98chap9,
+ title = "Haskell 98 Language and Libraries: The Revised Report",
+ editor = "S. Peyton-Jones",
+ year = 2003,
+ publisher = "Cambridge Univeristy Press",
+ chapter = 9
+}
+
@unpublished{haskell2010,
title = "Haskell 2010 Language Report",
author = "S. Marlow",
View
6 rapport/kapitel/abstract.tex
@@ -1,13 +1,13 @@
\renewcommand{\abstractname}{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 the Glasgow Haskell Compiler (GHC).
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.
-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 processes the text input, creating an internal structure called abstract syntax tree (AST). The type checker then analysis 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 interprets the AST in a well defined way.
\\
\\
-The results shows that it's possible to successfully implement Haskell in Javascript, but a lot of more work need to be done for making a newbie-friendly environment for learning Haskell.
+The results show that it is possible to successfully implement Haskell in Javascript, but a lot of more work needs to be done for making a beginner-friendly environment for learning Haskell.
\end{abstract}
View
3  rapport/kapitel/appendix.tex
@@ -0,0 +1,3 @@
+\appendix
+\section{Bidragsrapport}
+Alla gruppmedlemmar var delaktiga i likvärdig utsträckning under planeringsfasen. Större delen av projektet har genomdrivits gemensamt men varje person har haft en inriktning enligt projektets olika delar. Johan Gustafsson har haft ansvar över parsern, Mikael Bung har ansvarat för interpretatorn och det abstrakta syntaxträdet, Mattis Jeppsson för typcheckaren och Adam Bengtsson för HIJi. Rapporten har skrivits enligt samma uppdelning men med ett övergripande ansvar av Adam Bengtsson. Arbetet har i så stor utsträckning som möjligt skett gemensamt och vi har därför både bidragit till och tagit del av varandras respektive ansvarsområde.
View
48 rapport/kapitel/diskussion.tex
@@ -1,32 +1,54 @@
\section{Diskussion}
-Vi har skapat en javascriptapplikation som kan parsa, typchecka och interpretera stora delar av Haskell 98. Det som saknas är fullständigt stöd för typklasser där stödet endast finns i typcheckaren men fortfarande behöver implementeras i interpretatorn. Detta handlar främst om förmågan att välja rätt instanser av typklasser vid applicering av överlagrade funktioner.
+Vi har skapat en javascriptapplikation som kan parsa, typchecka och interpretera stora delar av Haskell 98. Det som saknas är fullständigt stöd för typklasser där stödet endast finns i typcheckaren och parsern men fortfarande behöver implementeras i interpretatorn. Detta handlar främst om förmågan att välja rätt instanser av typklasser vid applicering av överlagrade funktioner.
Sett till planeringen har vi lyckats uppfylla alla milstolpar utom typklasser, dock inte enligt den ordning och tidsplan som ursprungligen planerades.
-Vi insåg att det var enklast att utveckla parsern, typcheckaren och interpertatorn parallelt och bestämma individuellt vad som skulle implementeras och i
+Vi insåg att det var enklast att utveckla parsern, typcheckaren och interpretatorn parallellt och bestämma individuellt vad som skulle implementeras och i
vilken ordning för att senare, oftast en gång i veckan, samordna och implementera det som behövdes i flera delar.
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 i den slutgiltliga versionen. Ö:
-
-
+\subsection{Val av språk för implementering}
+Tidigt i planeringen tvingades vi välja vilket språk vår implementation skulle
+bestå av. Det första alternativet var att först skriva en kompilator för att
+kompilera Haskell till Javascript. Därefter skulle så kallad boot-strapping
+tillämpas där kompilatorn används för att kompilera sig själv till
+Javascript. Eftersom det redan finns parsers och typcheckare för Haskell
+skrivna i Haskell skulle projektet mestadels handla om att finna en lämplig
+målrepresentation för Haskell i javascriptkod och sedan implementering av en
+kodgenerator för denna. Haskells statiska typcheckning och referentiella
+transparens skulle också förenkla verifiering av projektets komponenter.
+
+Dock finns även en del nackdelar med en sådan implementation. Utan särskilda
+optimeringar i kompilatorn skulle en målrepresentation nödvändigtvis innehålla
+strukturer liknande dem som kan finnas i en interpretator för ett lat evaluerat
+språk. Det är ett rimligt antagande att sådana optimeringar på grund av sin komplexitet vore alltför stora för att genomföra i den aktuella tidsramen. Därför anser vi att denna typ av implementation lämpar sig bäst inom
+ramarna för ett existerande kompilatorprojekt såsom GHC där nödvändiga optimeringar redan finns inbyggda.
+
+Det andra alternativet var att skriva allt i Javascript och detta är den
+implementationsstrategi som vi till slut bestämde oss för.
+En fördel med en sådan implementation är att integrering med annan
+javascriptkod blir enkel.
+Det har också fördelen att i en interpretator bevaras kodstrukturen och en framtida interaktiv läromiljö får tillgång till mellanliggande körningsdata.
+Det första alternativet skulle däremot kräva ett
+särskilt integrationslager för att få samma möjligheter.
+
+
+%stor del av vår projekts potentiella användare redan har viss erfarenhet av Javascript och liknande språk och att användande av vårt bibliotek därför blir enklare för dessa än vad motsvarande haskellimplementation skulle bli. Eftersom detta alternativ krävde att vi själva implementerar parser, typcheckare och interpreterare ansåg vi också att det gav oss större möjligheter till lärande.
\subsection{Framtida förbättringar}
-Syftet med projektet, att skapa en fungerande Haskelltolk i javascript, har vi lyckats implementera om man tar hänsyn till de avgränsningar som är uppsatta. Dock om man ser till motivationen bakom projektet, att vår Haskelltolk ska kunna användas som grund för att skapa en webbaserad interaktiv läroplattform, så finns det fortfarande mycket kvar att utveckla. Framförallt handlar det om att göra Haskelltolken och HIJi mer lättanvänd för nybörjare inom funktionell programmering.
+Syftet med projektet, att skapa en fungerande Haskelltolk i Javascript, har vi lyckats implementera om hänsyn tas till de avgränsningar som är uppsatta. Dock sett till motivationen bakom projektet, att vår Haskelltolk ska kunna användas som grund för att skapa en webbaserad interaktiv läroplattform, så finns det fortfarande mycket kvar att utveckla. Framförallt handlar det om att göra Haskelltolken och HIJi mer lättanvänd för nybörjare inom funktionell programmering.
-I parsern har vi identifierat två förbättringsmöjligheter. För det första, bättre felmeddelanden
-Hjälpsamma och förklarande felmeddelanden är en viktigt del av ett utvecklingsverktyg och det generars för tillfället inte av parsern.
+I parsern har vi identifierat två förbättringsmöjligheter. För det första, hjälpsamma och förklarande felmeddelanden är en viktigt del av ett utvecklingsverktyg och det generars för tillfället inte av parsern.
Om parsern stöter på ett fel rapporterar den endast att ett fel har inträffat och avslutar parsningsprocessen.
-Att förbättra dessa felmeddelanden med exempelivs rad- och kolumnnummer och specifik information om vad för fel som har inträffat skulle göra parsern mer användbar.
-För att implentera detta behöver man kombinera steg 1 och 2 i parsningen för att rad- och kolumn-nummer ska bevaras korrekt då borttagning av nästlade kommentarer kan påverka dessa.
+Att förbättra dessa felmeddelanden med exempelvis rad- och kolumnnummer och specifik information om vad för fel som har inträffat skulle göra parsern mer användbar.
+För att implementera detta behöver parsern kombinera steg 1 och 2 i parsningen för att rad- och kolumn-nummer ska bevaras korrekt då borttagning av nästlade kommentarer kan påverka dessa.
JSParse behöver modifieras så att det rapporterar var ett fel uppstod och i vilken parser.
För det andra, konverteringen av icke kontextfri Haskellkod till kontextfri kan förbättras
för att klara av att expandera måsvingar i \emph{[x | let x = 5]}.
-För att klara av detta behövs en parser som räknar antal måsvingar, paranteser,
-komman och hakparanteser efter \emph{let} och avgöra när det är korrekt att sätta in avslutande måsvingar.
+För att klara av detta behövs en parser som räknar antal måsvingar, parenteser,
+komman och hakparenteser efter \emph{let} och avgöra när det är korrekt att sätta in avslutande måsvingar.
Även i HIJi finns det förbättringar att göra.
Det som framförallt behöver utvecklas är, för det första, erbjuda en interaktiv tutorial där användaren får instruktioner vad som ska skrivas in i HIJi. Om användaren skriver in rätt uttryck fortsätter tutorialen till nästa nivå.
View
33 rapport/kapitel/inledning.tex
@@ -1,37 +1,32 @@
\section{Inledning}
-\subsection{Bakgrund och motivation}
-På vissa av Chalmers och Göteborgs Universitets datorvetenskapliga program är den första programmeringskursen i Haskell \citep{haskell98} och för en del av de nya eleverna är inlärningströskeln hög. De studenter som börjar på de datavetenskapliga programmen på Chalmers och Göteborgs Universitet är allt från nybörjare till mycket kompetenta inom programmering. De flesta saknar dock kunskaper kring funktionell programmering. Skillnaden mellan ett funktionellt och ett objektorienterat programmeringsspråk är stora och omställningen hur programmeringsrelaterade problem behöver angripas är inte enkelt för de flesta nybörjare. Vi tror att ett interaktivt webbverktyg skulle kunna sänka tröskeln och underlätta undervisningen. Ett webbverktyg medför även att extra verktyg som Glasgow Haskell Compiler \citep{ghc} ej behöver installeras. Webbens stöd för interaktivitet gör det möjligt att snabbt visa funktionsdeklarationerna för de inbyggda funktionerna och att enkelt evaluera funktionerna och testa sig fram till olika resultat.
+På vissa av Chalmers och Göteborgs Universitets datorvetenskapliga program är den första programmeringskursen i Haskell \citep{haskell98} och för en del av de nya eleverna är inlärningströskeln hög. De studenter som börjar på de datavetenskapliga programmen på Chalmers och Göteborgs Universitet är allt från nybörjare till mycket kompetenta inom programmering. De flesta saknar dock kunskaper kring funktionell programmering. Skillnaden mellan ett funktionellt och ett objektorienterat programmeringsspråk är stora och omställningen hur programmeringsrelaterade problem behöver angripas är inte enkelt för de flesta nybörjare. Vi tror att ett interaktivt webbverktyg skulle kunna sänka tröskeln och underlätta undervisningen. Ett webbverktyg medför även att en kompilator som \emph{Glasgow Haskell Compiler} (GHC) \citep{ghc} ej behöver installeras. Webbens stöd för interaktivitet gör det möjligt att snabbt visa funktionsdeklarationerna för de inbyggda funktionerna och att enkelt evaluera funktionerna och testa sig fram till olika resultat.
-Många programmerare kommer inte i kontakt med funktionell programmering och med hjälp av ett interaktivt webbbverktyg som är enkelt för användaren att använda är vår förhoppning att fler programmerare och studenter ska komma i kontakt med funktionell programmering, och i synnerhet Haskell. Då flera moderna objektorienterade programmeringsspråk börjar ta funktionalitet och begrepp från funktionella programmeringsspråk så är det extra viktigt att programmerare kommer i kontakt med funktionell programmering. Ett exempel på detta är C\# som i senare versioner har fått stöd för bland annat lambdafunktioner \citep{csharp}.
+Många programmerare kommer inte i kontakt med funktionell programmering och med hjälp av ett interaktivt webbverktyg som är enkelt för användaren att använda är vår förhoppning att fler programmerare och studenter ska komma i kontakt med funktionell programmering, och i synnerhet Haskell. Då flera moderna objektorienterade programmeringsspråk börjar ta funktionalitet och begrepp från funktionella programmeringsspråk så är det extra viktigt att programmerare kommer i kontakt med funktionell programmering. Ett exempel på detta är \emph{C\#} som i senare versioner har fått stöd för bland annat lambda-funktioner (anonyma funktioner) \citep{csharp}.
-En fördel med att ha tolken på webben är att det enda som behövs för att använda den är en javascriptkompatibel webbläsare, något som följer med i princip i alla moderna operativsystem. Detta betyder att de användare som befinner sig inom vår målgrupp redan har den programvaran som behövs på sina hemdatorer för att använda sig av vårt program.
+En fördel med att ha tolken på webben är att det enda som behövs för att använda den är en javascriptkompatibel webbläsare, något som följer med i alla moderna operativsystem. Detta betyder att de användare som befinner sig inom vår målgrupp redan har den programvaran som behövs på sina hemdatorer för att använda sig av vårt program.
% TODO detta e out of context`
-Haskell är ett starkt statiskt typcheckat och funktionellt programmeringsspråk med lat evaluering. % TODO: Citera, skriv om ifall det är direktöversatt
+Det som gör Haskell speciellt är att det är ett starkt statiskt typcheckat och funktionellt programmeringsspråk med lat evaluering. % TODO: Citera, skriv om ifall det är direktöversatt
% jag bytte från strikt semantik till lat evaluering:p
Att språket är funktionellt innebär bland annat att funktioner är \emph{first-class citizens} och kan därmed användas som parametrar och returneras från andra funktioner precis som vilken annan typ som helst.
-Lat evaluering innebär mer konkret att evalueringen av ett uttryck inte kommer utföras förrän resultatet av uttrycket behövs. Om uttrycket inte behövs kommer interpretatorn att ignorera det.
+Lat evaluering innebär att evalueringen av ett uttryck inte kommer utföras förrän resultatet av uttrycket behövs. Om uttrycket inte behövs kommer interpretatorn att ignorera det.
Lat evaluering gör att programmeraren inte behöver bry sig om exekveringsordningen av ett program. Detta ger prestandaförbättringar eftersom ett uttryck inte evalueras alls om det inte behövs \citep{hudak89}.
Lat evaluering gör det också möjligt att använda sig av oändliga datastrukturer, till exempel oändliga listor. Språket blir därmed mer uttrycksfullt.
-%Funktionella programmeringsspråk såsom Haskell anses också vara det naturliga steget att ta när man vill nå en högre abstraktionsnivå än den som imperativa programmeringsspråk tillåter. % TODO: citera
-John Hughes argumenterar för att funktionella språk som stödjer lat evaluering erbjuder större möjligheter än imperativa språk att skriva modulära program. Detta för att funktionella språk som Haskell stödjer higher order functions och lat evaluering vilket är tekniker som kan användas för att binda samman olika moduler.
-Dessa två programspråksegenskaper bidrar till att program skrivna i Haskell är generellt sätt kortare och går fortare att skriva än motsvarande program skrivet i ett imperativt programmeringsspråk \citep{why}.
+John Hughes argumenterar för att funktionella språk som stödjer lat evaluering erbjuder större möjligheter än imperativa språk att skriva modulära program. Detta för att funktionella språk som Haskell stödjer \emph{higher order functions}, en funktion som tar en annan funktion som argument, och lat evaluering vilket är tekniker som kan användas för att binda samman olika moduler.
+Dessa två programspråksegenskaper bidrar till att program skrivna i Haskell generellt sett är kortare och går fortare att skriva än motsvarande program skrivet i ett imperativt programmeringsspråk \citep{why}.
Med ovan nämnda resonemang ser vi det som ovärderligt för programmerare att komma i kontakt och lära sig funktionell programmering.
Förhoppningen är att vår haskelltolk i Javascript ska kunna användas som grund för att i framtiden göra en interaktiv läroplattform för nybörjare i funktionell programmering.
\subsection{Syfte}
-Syftet är en implementera en fungerande haskelltolk i Javascript. Den ska kunna tolka en delmängd av haskell-specifikationen så den kan användas för att göra exempelvis interaktiva tutorials för nybörjare.
+Syftet är en implementera en fungerande haskelltolk i Javascript. Den ska kunna tolka en delmängd av haskellspecifikationen så den kan användas för att göra exempelvis interaktiva tutorials för nybörjare.
Meningen är att dessa ska kunna köras i en vanlig webbläsare utan att ladda ner en haskellkompilator, till exempel GHC, eller behöva lära sig svårbegripliga kommandon.
-\subsection{Problembeskrivning}
-%% WHAT THE FACK SKA VI SKRIVE HEAR?!!Ö!
-
\subsection{Metod}
-Projektet består av planera, designa och implementera haskelltolken. Vi arbetade efter en iterativ modell där nya funktioner lades till undan för undan. Detta fungerar bra eftersom vi får en tidigt fungerande prototyp att utgå från. Arbetet delades upp i separata moduler som utvecklades relativt frånskillt från varandra för att undan för undan fasas ihop till det slutgiltliga resultatet.
+Projektet bestod av att planera, designa och implementera haskelltolken. Vi arbetade efter en iterativ modell där nya funktioner lades till undan för undan. Detta fungerade bra eftersom vi tidigt fick en fungerande prototyp att utgå ifrån. Arbetet delades upp i separata moduler som utvecklades relativt frånskilt från varandra för att undan för undan fasas ihop till det slutgiltiga resultatet.
%I vårt arbete har vi implementerat parser, typcheckare och interpretator parallellt med varandra och utökar de olika modulernas funktionalitet iterativt.
%Vi hade tänkt följa den här planen genom varje milstolpe genom att utöka parsern, typcheckaren och interpretatorn med ny funktionalitet.
@@ -44,15 +39,15 @@ \subsection{Metod}
%En interaktiv kommandotolk som kan köras i en webbläsare kommer att utvecklas. Den ska ge användaren möjlighet att skriva Haskell-funktioner och exekvera dem på ett liknande sätt som i GHCi.
%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}
+\subsection{Avgränsningar}
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:
- \begin{enumerate}
+ \begin{itemize}
\item{Lambda-funktioner, namngivna funktioner}
\item{Typer, generella typer, algebraiska datatyper}
\item{Typklasser}
\item{Pattern matching}
\item{Guards}
- \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 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.
-SLutligen beslutades det att inte optimera haskelltolken utan målet är att göra en fungerande implementation.
+ \end{itemize}
+Med dessa delar implementerade kan de flesta enklare haskellprogram köras och bör vara tillräckligt för de flesta 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.
+Slutligen beslutades det att inte optimera haskelltolken utan målet var att göra en fungerande implementation. Detta för att en nybörjare sällan behöver eller kommer skriva program som behöver hög prestanda.
View
40 rapport/kapitel/metod.tex
@@ -1,21 +1,14 @@
\section{Metod}
-Nedan följer en beskrivning av de arbetsmetoder vi använt oss av och de mjukvaror och kodbibliotek som vi använt oss av i projektet.
+Nedan följer en beskrivning av de arbetsmetoder, mjukvaror och kodbibliotek som vi använt oss av i projektet.
\subsection{Genomförande}
% modulbaserat arbete..
-För att implementera en tolk för Haskell behövs en parser för den aktuella syntaxen, en typcheckare för språkets definerade typregler och tillsist en interpretator som tolkar språket efter dess specifikation.
-Det upptäcktes tidigt att de tre modulerna, parser, interpretator och typcheckare, inte behövde utvecklas sekvensiellt. De tre modulerna intergrerar enbart med varandra genom det abstrakta syntaxträdet vilket medför att det är lätt att utveckla de olika modulerna helt frånskilt från varandra. Figur \ref{fig:parser_steg} visar hur denna interaktion mellan de olika modulerna är tänkt att gå till. Figur \ref{fig:parser_steg} visar även att webbläsaren kommunicerar genom ett Javascript API och det abstrakta syntaxträdet och inte direkt med de olika komponenterna.
+För att implementera en tolk för Haskell behövs en parser för den aktuella syntaxen, en typcheckare för språkets definierade typregler och tillsist en interpretator som tolkar språket efter dess specifikation.
+Det upptäcktes tidigt att de tre modulerna, parser, interpretator och typcheckare inte behövde utvecklas sekvensiellt. De tre modulerna integrerar enbart med varandra genom det abstrakta syntaxträdet, vår interna representation av Haskell, vilket medför att det är lätt att utveckla de olika modulerna helt frånskilt från varandra. Figur \ref{fig:tolkens_struktur} visar hur denna interaktion mellan de olika modulerna är tänkt att gå till. Figuren visar även hur webbläsaren kommunicerar genom ett Javascript API och det abstrakta syntaxträdet och inte direkt med de olika komponenterna.
-Det första delmålet var att göra en haskelliknande implementation av lambda calculus då mer avancerade funktionella programspråksegenskaper kan implementeras som detta \citep{jones87}.
-Parsern implementerades med hjälp av ett parser combinator bibliotek kallat JSParse \citep{jsparse}. Det gav oss möjlighet att att på ett enkelt sätt implementera både den kontextfria och icke kontextfria delen av Haskell. Parsern skapar ett syntaxträd som skickas vidare till typcheckaren. I typcheckaren dekoreras syntaxträdet med typinformation innan det slutligen skickas till interpretatorn.
-
-En interaktiv kommandotolk som kan köras i en webbläsare utvecklades. Den ska ge användaren möjlighet att skriva Haskell-funktioner och exekvera dem på ett liknande sätt som i GHCi.
-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.
-
-
-\begin{figure}[h]
+\begin{figure}[H]
\begin{center}
\includegraphics[width=1.0\textwidth]{image1.png}
\caption{Överblick över tolkens struktur och interaktion}
@@ -23,21 +16,26 @@ \subsection{Genomförande}
\end{center}
\end{figure}
+Det första delmålet var att göra en haskelliknande implementation av lambda calculus då mer avancerade funktionella programspråksegenskaper kan implementeras som detta \citep{jones87}.
+Parsern implementerades med hjälp av ett \emph{parser combinator}-bibliotek kallat JSParse \citep{jsparse}. Det gav oss möjlighet att på ett enkelt sätt implementera både den kontextfria och icke kontextfria delen av Haskell. Parsern skapar ett syntaxträd som skickas vidare till typcheckaren. I typcheckaren dekoreras syntaxträdet med typinformation innan det slutligen skickas till interpretatorn.
+
+En interaktiv kommandotolk som kan köras i en webbläsare utvecklades. Den gav användaren möjlighet att skriva haskellfunktioner och exekvera dem på ett liknande sätt som i GHCi.
+Vi integrerade jQuery \citep{jquery} för att få ett unisont stöd för samtliga webbläsare. jQuery underlättade även arbetet med att skapa ett enkelt och stilrent interaktivt gränssnitt.
-Arbetssättet präglades av en iterativ utvecklingsmetodik med korta utvecklingscyklar. Arbetet delades upp med huvudansvarstagande över var sin modul och utfördes parallellt med varandra. Arbetet skedde dock framförallt i samlad grupp på grund av att det var många designrelaterade problem vi var tvugna att ta ställning till under projektet, till exempel hur vårat abstrakta syntaxträd skulle se ut, och för att det skulle bli enklare när vi skulle börja sammanfoga våra olika moduler med varandra.
-Det var också ett bra sätt att snabbt få hjälp av varandra eftersom vi ej visste exakt hur modulerna skulle se ut när vi påbörjade arbetet. Vi fann det därför praktiskt att använda en iterativ modell för att bit för bit utvigda våra moduler. Dock valde vi att implementera typcheckaren i ett steg då vi ansåg att det skulle vara enklare. Detta främst för att vi trodde typklasser var så centralt i typcheckaren att det skulle vara svårt att lägga till det i en andra iteration.
+Arbetssättet präglades av en iterativ utvecklingsmetodik med korta utvecklingscyklar. Arbetet delades upp med huvudansvarstagande över var sin modul och utfördes parallellt med varandra. Arbetet skedde dock framförallt i samlad grupp på grund av att det var många designrelaterade problem vi var tvungna att ta ställning till under projektet, till exempel hur vårt abstrakta syntaxträd skulle se ut, och för att det skulle bli enklare när vi skulle börja sammanfoga de olika modulerna med varandra.
+Det var också ett bra sätt att snabbt få hjälp av varandra eftersom vi ej visste exakt hur modulerna skulle se ut när vi påbörjade arbetet. Vi fann det därför praktiskt att använda en iterativ modell för att bit för bit utvidga våra moduler. Dock valde vi att implementera typcheckaren i ett steg då vi ansåg att det skulle vara enklare. Detta främst för att vi trodde typklasser var så centralt i typcheckaren att det skulle vara svårt att lägga till det i en andra iteration.
-Eftersom vi arbetade parallellt med olika moduler var vi beroende av ett bra versionshanteringssystem. Bra i vårt fall innebar att det skulle vara enkelt att arbeta i olika grenar, en gren för varje modul, och att det skulle gå snabbt och enkelt att slå ihop dessa förgreningar när vi behövde länka samman två utvecklares arbeten. I början av projektet använda vi oss av SVN (Subversion). Detta berodde framförallt på att det var det versionshanteringssystem som alla i gruppen hade erfarenhet från tidigare. Dock insåg vi att SVN inte var praktiskt att använda när man arbetar i flera olika grenar i projektet samtidigt. Därför gick valet till att använda Git som är designat från grunden för att på ett enkelt sätt skapa nya och slå samman förgreningar under utvecklingens gång. Vi kunde därmed skapa en förgrening för varje modul och under arbetets gång sammanlänka allas arbeten på ett effektivt sätt.
+Eftersom vi arbetade parallellt med olika moduler var vi beroende av ett bra versionshanteringssystem. Bra i vårt fall innebar att det skulle vara enkelt att arbeta i olika grenar, en gren för varje modul, och att det skulle gå snabbt och enkelt att slå ihop dessa förgreningar när vi behövde länka samman två utvecklares arbeten. I början av projektet använda vi oss av Subversion (SVN). Detta berodde framförallt på att det var det versionshanteringssystem som alla i gruppen hade erfarenhet från tidigare. Dock insåg vi att SVN inte var praktiskt att använda när vi arbetade i flera olika grenar i projektet samtidigt. Därför gick valet till att använda Git som är designat från grunden för att på ett enkelt sätt skapa nya och slå samman förgreningar under utvecklingens gång. Vi kunde därmed skapa en förgrening för varje modul och under arbetets gång sammanlänka allas arbeten på ett effektivt sätt.
-På grund av vår parallella arbetsmetod ansåg vi det nödvändigt att arbeta fram en kodstandard så att de olika modulerna skulle stilmässigt likna varandra. Kodstandarden beskriver hur indentering, namngivning av variabler och funktioner ska se ut. Innan ny kod skickas till Git så måste denna kodstandard följas.
+På grund av vår parallella arbetsmetod ansåg vi det nödvändigt att arbeta fram en kodstandard så att de olika modulerna skulle stilmässigt likna varandra. Kodstandarden beskriver hur indentering och namngivning av variabler och funktioner ska se ut. Innan ny kod skickades till Git så krävdes det att koden uppfyllde kraven i kodstandarden.
%\subsection{Javascript}
%Javascript \citep{javascript} är ett programmeringsspråk som framförallt används på klientsidan på webben. Javascript är ett dynamiskt objektorienterat skriptspråk.
%Javascript är det programmeringsspråk som används uteslutande i detta projektet.
\subsection{Kodbibliotek}
-I projektet använder vi oss av kodbibliotek för att snabbare kunna utveckla haskelltolken. Nedan följer en kort beskrivning av dessa.
-
+I projektet använder vi oss av tre kodbibliotek för att snabbare kunna utveckla haskelltolken. Nedan följer en kort beskrivning av dessa.
+
\subsubsection{JSParse}
Parsern implementeras med hjälp av ett parser combinator bibliotek kallat JSParse.
En parser combinator består av olika funktioner som parsar exempelvis strängar, listor eller blanksteg.
@@ -46,11 +44,11 @@ \subsubsection{JSParse}
\subsubsection{jQuery}
%jQuery är ett öppet kodbibliotek till Javascript som är dubeellicenserat under MIT License och GPL version 2.
-jQuery är designat för att underlätta för utvecklare att modifiera DOM-träd och göra asynkrona javascript-anrop. JQuery används i projektet för att få enkelt cross browser stöd i den kommandotolk vi kommer utveckla.
-jQuery ger även möjlighet att skapa ett enkelt och stilrent interaktivt gränssnitt utan att behöva göra allt från grunden.
-JQuery.Cookie, ett tillägg till jQuery, används för att förenkla användandet av kakor.
+jQuery är designat för att underlätta för utvecklare att modifiera DOM-träd och göra asynkrona javascriptanrop. jQuery användes i projektet för att få likartat stöd i samtliga webbläsare i kommandotolken som utvecklades.
+jQuery gav oss även möjlighet att skapa ett enkelt och stilrent interaktivt gränssnitt utan att behöva göra allt från grunden.
+jQuery.Cookie, ett tillägg till jQuery, används för att förenkla användandet av kakor.
\subsubsection{JSON}
JSON \citep{json} är en delmängd av Javascript och används för att utbyta data mellan olika format och programmeringsspråk.
-JSON är idag inbyggt i de senaste versionerna av de moderna webbläsarna men för att få stöd i äldre versioner har vi valt att inkludera JSON som ett externt bibliotek.
+JSON är idag inbyggt i de senaste versionerna av de moderna webbläsarna, men för att få stöd i äldre versioner har vi valt att inkludera JSON som ett externt bibliotek.
View
412 rapport/kapitel/resultat.tex
@@ -1,18 +1,19 @@
\section{Resultat}
% TODO
-Projektets resultat är ett kodbibliotek för en haskelltolk. Här presenterar vi de olika modulerna som tolken består av. Koden finns att tillgå på GitHub: \url{http://github.com/johang88/haskellinjavascript}.
+Projektets resultat är ett kodbibliotek för en haskelltolk. Den nuvarande statusen av projektet är att parser och interpretator är fullt integrerade med varandra. Typcheckaren är inte integrerad, dock är den färdigutvecklad. För att integrera typcheckaren måste det abstrakta syntaxträdet utvidgas för att ta hänsyn till typinformation.
+Koden finns att tillgå på GitHub: \url{http://github.com/johang88/haskellinjavascript}. Nedan följer en mer noggrann genomgång av projektets olika delar.
\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.
+som är lättare att hantera internt. Denna datastruktur kallas \emph{Abstract Syntax Tree} (AST).
+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 användardefinierade 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.
+För att parsa indatan använder vi ett bibliotek för att bygga parsers kallat JSParse.
+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.
@@ -61,15 +62,15 @@ \subsection{Parser}
\subsubsection{Steg 1 - Ta bort kommentarer}
Det första steget använder en parser som identifierar och tar bort kommentarer.
-Haskell har två olika kommentarsstiler, enkelradiga börjar med \emph{--} och slutar vid första radbytet och
+Haskell har två olika kommentarsstilar, enkelradiga som börjar med \emph{--} och slutar vid första radbytet, och
nästlade som kan gå över flera rader börjar med \emph{\{-} och slutar med \emph{-\}}.
-\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
+\subsubsection{Steg 2 - Applicera layoutregler}
+Det andra steget applicerar Haskells layoutregler enligt två algoritmer som är definierade i haskellstandarden \citep{haskell98chap9}. Den första delar upp koden i dess ord och symboler samtidigt som den dekoreras med indenteringsnivåer.
+Därefter användas den andra för att sätta in måsvingar och semikolon på rätt platser.
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:
+Ett exempel på en layoutregel är att ett inre block inte får vara mer indenterat än ett omslutande block.
\begin{lstlisting}
case x of
True -> ...
@@ -86,10 +87,10 @@ \subsubsection{Steg 2 - Konvertera till kontextfri}
\begin{lstlisting}
let { x = 5; y = 4 } in x + y
\end{lstlisting}
-För att översätta detta korrekt kommer parsern ihåg den aktuella nästlingsnivån av "let"-uttryck och var deras repsektive "in"-uttryck befinner sig.
-Den avslutande måsvingen sätts in där ett matchande "in"-uttryck påträffas.
+För att översätta detta korrekt kommer parsern ihåg den aktuella nästlingsnivån av \emph{let}-uttryck och var deras respektive \emph{in}-uttryck befinner sig.
+Den avslutande måsvingen sätts in där ett matchande \emph{in}-uttryck påträffas.
-Ett exempel som inte översätts korrekt:
+Det finns även uttryck som inte översätts korrekt, exempelvis:
\begin{lstlisting}
[x | let x = 2]
\end{lstlisting}
@@ -97,214 +98,58 @@ \subsubsection{Steg 2 - Konvertera till kontextfri}
\begin{lstlisting}
[x | let { x = 2 }]
\end{lstlisting}
-Men det blir:
+Men i parsern blir det:
\begin{lstlisting}
[ x | let { x = 2 ] }
\end{lstlisting}
Anledningen är att endast nästlingen av \emph{let} och \emph{in} sparas, men här finns inget \emph{in}.
-För att lösa felet måste parsern hålla reda på antalet paranteser, måsvingar, hakparanteser och komman efter ett let-uttryck och när en symbol som gör det ogiltligt
+För att lösa felet måste parsern hålla reda på antalet parenteser, måsvingar, hakparenteser och komman efter ett \emph{let}-uttryck och när en symbol som gör det ogiltigt
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
-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.
+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 slutgiltiga parsern. Det resulterar i ett träd av parsers, en parser för hela programmet som har flera mindre parsers under sig.
-Exempel:
-Definitionen i haskellstandarden:
+Exempel på grammatik definierad i Haskellstandarden:
\begin{lstlisting}
gdrhs -> gd = exp [gdrhs]
-rhs -> exp [where decls]
- | gdrhs [where decls]
\end{lstlisting}
-Dess respektive parsers:
+Dess motsvarande parser:
\begin{lstlisting}
var gdrhs = gdrhs_action(
repeat1(gdrhs_fix_list_action(sequence(ws(gd),
expectws('='), ws(exp)))));
-
-var rhs = choice(
- decl_rhs_action(sequence(expect(ws('=')), ws(exp),
- optional(sequence(expect(ws("where")), ws(decls))))),
- sequence(ws(gdrhs), optional(sequence(expect(ws("where")),
- ws(decls))))
-);
\end{lstlisting}
-Här används \emph{choice} för att tolka de två olika alternativen i \emph{rhs} och om vi tittar närmare på \emph{gdrhs}
-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.
+Tittar vi närmare på \emph{gdrhs} ser vi att det är en rekursiv deklaration. Vilket vi implementerar med \emph{repeat1} för att få en lista med minst en upprepning.
+\emph{gdrhs\_action} och \emph{gdrhs\_fix\_list\_action} används för att generera det abstrakta syntaxträdet.
-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 specificerad i Haskell 2010 \citep{haskell2010} för att lösa företrädesreglerna (precedence levels) för operatorer då den här metoden är enklare än den som är definierad i Haskell 98.
+Anledningen till att företrädesreglerna inte kan definieras 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.
+operatorer och uttryck skapas. Till sist används trädet för att generera en AST för uttrycken.
\subsubsection{JSParse}
-Vi använder en modifierad version av JSParse där vi har korrigerat två fel och lagt till fler parsers. Felen vi korrigerade var i butnot-parsern och i choice-parserns cachefunktion.
-Choice-parsern cachade resultat från parsers som misslyckades och det cachade resultatet användes i senare parsers,
-vi löste det med en stackbaserad cache där cachen för en parser som misslyckas raderas.
+Vi använder en modifierad version av JSParse där vi har korrigerat två fel och lagt till fler parsers. Felen vi korrigerade var i \emph{butnot}-parsern och i \emph{choice}-parserns cachefunktion.
+\emph{Choice}-parsern cachade resultat från parsers som misslyckades och det cachade resultatet användes i senare parsers,
+vi löste det med en stackbaserad cache där cachen för en parser som misslyckas raderas.
+JSParse har andra problem som vi inte löst, exempelvis att det inte rapporterar rad- och kolumn-nummer eller parsningsfel korrekt, detta gör att vi inte får bra felmeddelanden.
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}
-
-
-\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.
-
-\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}
-En Thunk är en avstannad beräkning, en continuation. En Thunk består av en Env och en Expression.
-
-\begin{lstlisting}
-data Thunk = Closure Env Expression
-\end{lstlisting}
-
-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.
-
-\begin{lstlisting}
-data WeakHead
- = Data Identifier [HeapPtr]
- | LambdaAbstraction Env Pattern Expression
- | DelayedApplication Env Int [Declaration] [HeapPtr]
- | Primitive
-\end{lstlisting}
-
-En Data är resultatet av att applicera en algebraisk datakonstruktor på dess argument. Argumenten ges som en lista av HeapPtr, det vill säga en lista av evaluerade eller icke evaluerade uttryck. Exemplevis resulterar Just 1 i en Data med Identifiern Just och en HeapPtr till det icke evaluerade uttrycket 1.
-
-En LambdaAbstraction är körningsrepresentationen av en lambdafunktion, en Env är bunden till lambdafunktionen.
-
-En DelayedApplication är ett specialfall av en LambdaAbstraction. Vi avsockrar inte Haskells funktionsdeklarationer vilket innebär att pattern matching sker även vid funktionsapplikation och inte bara i Case satser. Detta betyder att vi måste samla alla argument till en funktion innan vi kan avgöra vilket funktionsalternativ som skall användas. En vidare beskrivning finns i kapitlet Declaration.
-
-En Primitiv är ett Javascript-värde, till exempel en integer eller en double.
-
-\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.
-
-\begin{lstlisting}
-Env {
- a => ([a, b, 3], [1,2,3])
- b => ([a, b, 3], [1,2,3])
-}
-Env.find(a)
-Env {
- a => 1
- b => 2
-}
-\end{lstlisting}
-
-\subsection{Abstrakt syntaxträd och evaluering}
-Vår AST representeras av javascript-objekt men dess strukturella uppbyggnad ges här av Haskells datadefinitioner.
-
-\subsubsection{Declaration}
-Den första datatypen av intresse är Declaration. En Declaration representerar en namnbindning antigen i en moduls globala definitionsområde eller i en let eller where bindning.
-
-\begin{lstlisting}
-data Declaration
- = Variable pattern Expression
- | Data Identifier [Constructor]
- | Function Identifier [Pattern]
- (Either [(Guard, Expression)] Expression)
-\end{lstlisting}
-
-Variable är en bindning av typen p = e där p är en Pattern och e en Expression. En Variable kan därför binda flera olika symboler på en gång. Till exempel (1:a:b:[]) = [1,2,3] binder variabeln a och b.
-
-Function är en representation av Haskells sockrade funktionsdefinitioner. Det är möjligt att avsockra dessa till en Variable binding med hjälp av Lambda och Case men vi har valt att införa en speciell representation av funktionsdefinitioner. Till skillnad från traditionella kompilatorer så avsockras Function aldrig utan håller samma form även under interpreteringen. Tanken bakom detta är att det skall vara lättare att se sammanhanget mellan datan under körning och källkoden vilket gör det lättare att knyta samman den statiska källkoden med den dynamiska körningsdatan.
-
-En Data definierar en algebraisk datatyp med konstruktorerna definierade som nedan
-\begin{lstlisting}
-data Constructor = Constructor Identifier Int
-\end{lstlisting}
-Värt att notera här är avsaknaden av typvariabler och typargument, detta kommer att åtgärdas när typchekaren är integrerad.
-
-Under interpreteringen av en Declaration binds de namn (Identifiers) som definieras av Declaration till Env-objektet. Vilken typ av binding som används beror på typen av Declaration. En Variable ger en Identifier => (Pattern, Expression) bindning medan en Function eller Data ger en Identifier => Expression bindning.
-
-\subsubsection{Expression}
-En Expression är representationen av ett haskelluttryck.
-
-\begin{lstlisting}
-data Expression
- = Constant Value
- | Lambda Pattern Expression
- | Let [Declaration] Expression
- | Case Expression [(Pattern, Expression)]
- | VariableLookup Identifier
- | Do [DoNotation]
- | List [Expression]
- | ArithmeticSequence Expression (Maybe Expression)
- (Maybe Expression)
- | Primitive JavascriptFunction
-\end{lstlisting}
-
-När en Expression evalueras under en Env är resultatet antingen en Thunk (continuation, closure) eller en WHNF. Evaluering av en Constant resulterar antigen i en primitiv eller en avsockring av konstanten. I interpretatorn så är konstanta nummer, till exempel 1, egentligen en algebraisk datatyp (I\# 1\#) och denna avsockring sker först under körning. När en Lambda evalueras returneras en LambdaAbstraction med evalueringens Env bunden. En Let evalueras genom att binda dess Declarations till Env-objektet och returnera en Closure över det nya Env-objektet och Let-uttryckets Expression. En Case evalueras genom att den första Expression i tuppellistan vars Pattern matchar evalueras under den Env som resulterar från pattern matchen.
-\begin{lstlisting}
-this.eval = function(env) {
- var expr = new interpreter.HeapPtr(
- new interpreter.Closure(env, this.expr));
- for (var i in this.cases) {
- var newEnv = env.derive();
- if (this.cases[i][0].match(newEnv, expr)) {
- return this.cases[i][1].eval(newEnv);
- }
- }
- throw new Error("No matching clause");
-};
-\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.
-
-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}.
-
-En Primitive är en wrapper runt en Javascript-funktion. Att evaluera en Primitive är det samma som att evaluera funktionen med Env som argument.
-
-\subsubsection{Pattern}
-Vi har implementerat fem stycken olika pattern matches från Haskell.
-\begin{lstlisting}
-data Pattern = Constructor Identifier [Pattern]
- | VariableBinding Identifier
- | Combined Identifier Pattern
- | ConstantPattern Value
- | Wildcard
-\end{lstlisting}
-Under en pattern match händer två saker. Dels så kontrolleras att uttrycket som matchas verkligen stämmer överens med dess pattern, dels så binds de variabler som definieras i Pattern till Env.
-
-En VariableBinding matchar alla uttryck och binder uttrycket till Identifier. En Constructor matchar de uttryck vars WHNF är en Data med samma Identifier (samt samma typ, detta tvingas dock av typcheckaren) och alla sub-patterns matchar Data argumenten. Combined är en sammanslagning av en VariableBinding och en annan Pattern, i källkoden så har de formen \emph{v@p}. Combined matchar de uttryck som matchar dess Pattern och binder ett matchat uttryck till Identifier. En ConstantPattern matchar de uttryck som är exakt lika med värdet. Till sist så matchar en Wildcard alla uttryck.
-
\subsection{Typcheckare}
Typcheckarens uppgift är att analysera det abstrakta syntaxträdet, inferera typerna på dess olika
beståndsdelar och avgöra om sättet på vilket de används och interagerar med
andra beståndsdelar är konsekvent. Om så inte är fallet sägs programmet ha
typfel.
-Vår implementation av typcheckaren är starkt influerad av den implementation i Haskell som beskrivs i \citep{jones99} men är omdesignad för att göra sig bättre i JavaScript. Det följande avsnittet förutsätter viss förkunskap om typinferens och polymorfiska typer. För en bra introduktion till detta referera till \citep{dragonbookchap6} och för en djupare genomgång \citep{pierce02}.
+Vår implementation av typcheckaren är starkt influerad av den implementation i Haskell som beskrivs i \citep{jones99} men är omdesignad för att göra sig bättre i Javascript. Det följande avsnittet förutsätter viss förkunskap om typinferens och polymorfiska typer. För en bra introduktion till detta referera till \citep{dragonbookchap6} och för en djupare genomgång \citep{pierce02}.
\subsubsection{Haskells typsystem}
Jämfört med mer konventionella språk (C, C++, Java etc) skiljer sig Haskell
@@ -329,7 +174,7 @@ \subsubsection{Haskells typsystem}
\subsubsection{Representation av kinds, typer, typscheman och typklasser}
För att representera typsystemets olika beståndsdelar använder typcheckaren ett antal olika datastrukturer. Här ger vi en snabb genomgång av dessa för att sedan kunna fokusera på själva typcheckningsprocessen i de sedan följande avsnitten.
-Kinds kan liknas vid en motsvarighet till typer för typkonstruktorer. \emph{*} (uttalas ``stjärna'', eng. ``star'') representerar enkla (nullary) typer som Integer och \emph{Integer -> Bool} medan komplexa typer som tar argument representeras med applicering av kinds \emph{k1 -> k2}. Exempelvis har \emph{Maybe} kind \emph{*->*} medan \emph{Maybe Bool} har kind \emph{*}.
+Kinds kan liknas vid en motsvarighet till typer för typkonstruktorer. \emph{*} (uttalas ``stjärna'', eng. ``star'') representerar enkla (nullary) typer som \emph{Integer} och \emph{Integer -> Bool} medan komplexa typer som tar argument representeras med applicering av kinds \emph{k1 -> k2}. Exempelvis har \emph{Maybe} kind \emph{*->*} medan \emph{Maybe Bool} har kind \emph{*}.
\begin{lstlisting}
data Kind = Star
@@ -344,7 +189,7 @@ \subsubsection{Representation av kinds, typer, typscheman och typklasser}
| TGen Int
\end{lstlisting}
-TVar representerar typvariabler. Dessa har namn som vanligtvis tilldelas internt i typcheckaren. TAp representerar applicering av typer och TCon representerar typkonstruktorer för konkreta typer. TGen representerar
+\emph{TVar} representerar typvariabler. Dessa har namn som vanligtvis tilldelas internt i typcheckaren. \emph{TAp} representerar applicering av typer och \emph{TCon} representerar typkonstruktorer för konkreta typer. \emph{TGen} representerar
generiska typer och används enbart i samband med kvantifiering av
typer internt i typcheckaren
@@ -366,12 +211,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)) ]
@@ -384,7 +229,7 @@ \subsubsection{Representation av kinds, typer, typscheman och typklasser}
\begin{lstlisting}
data Scheme = Scheme [Kind] Qual
\end{lstlisting}
-Eftersom typvariabler (\emph{TVar id kind}) endast skapas internt i typcheckaren representeras här alla generiska typer med \emph{TGen n} där \emph{n} helt enkelt anger att det är den \emph{n}:te generiska typen i typschemat och dess kind finns lagrat på position \emph{n} i \emph{[Kind]}
+Eftersom typvariabler (\emph{TVar id kind}) endast skapas internt i typcheckaren representeras här alla generiska typer med \emph{TGen n} där \emph{n} helt enkelt anger att det är den \emph{n}:te generiska typen i typschemat och dess kind finns lagrat på position \emph{n} i \emph{[Kind]}
För att representera det tidigare exemplet på detta sätt byter vi ut alla identiska förekomster av \emph{TVar id kind} mot identiska \emph{TGen i}:
\begin{lstlisting}
@@ -397,17 +242,15 @@ \subsubsection{Representation av kinds, typer, typscheman och typklasser}
(TGen 1))))
\end{lstlisting}
-För att hålla reda på vilka typklasser och instanser som finns används datatypen \emph{Klass} (\emph{class} är ett reserverat ord i JavaScript) som representerar enskilda typklasser och deras instanser samt datatypen \emph{KlassEnvironment} som representerar den totala klassmiljön.
+För att hålla reda på vilka typklasser och instanser som finns används datatypen \emph{Klass} (\emph{class} är ett reserverat ord i Javascript) som representerar enskilda typklasser och deras instanser samt datatypen \emph{KlassEnvironment} som representerar den totala klassmiljön.
-
-\subsubsection{Substitueringar}
-Substitueringar är mappningar \emph{typvariabel -> typ} och används av typcheckaren
+\subsubsection{Substitutioner}
+Substitutionerna ä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.
+\emph{Unifiering} är processen att finna en substitution 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 typen för \emph{e2} och \emph{e3} måste gå att unifiera. Om någon av dessa unifieringar inte är möjliga betyder det att typfel finns.
\subsubsection{Typinferens}
Typinferens är den sammanfogande delen av typcheckningsprocessen och går ut på att typcheckaren traverserar abstrakta syntaxträdet och samlar de kriterier som måste vara uppfyllda för att programmet ska vara korrekt.
@@ -417,8 +260,8 @@ \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.
-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:
+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 substitutionernas \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 konceptet väljer vi här ändå att använda den:
\begin{lstlisting}
ast.If.prototype.infer = function(env) {
@@ -435,22 +278,171 @@ \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 unifieras då dessa måste vara av samma typ. 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.
\subsubsection{Defaulting}
Ofta förekommer situationer där tvetydigheter gör att typcheckaren inte kan bestämma en typ. För att förenkla för programmeraren finns därför förbestämda standardtyper att använda i dessa situationer för en del inbyggda typer. Detta användande av förbestämda standartyper kallas för defaulting.
+\subsubsection{Typcheckarens nuvarande status}
+I sitt nuvarande tillstånd klarar typcheckaren av att typchecka och typinferera haskellprogram. Detta inkluderar program som använder polymorfiska typer och typklasser. Vi har även stöd för \emph{defaulting}. Dock behöver typcheckaren integreras med interpretatorn för att kunna ladda rätt instans av typklassser vid applicering av överlagrade funktioner under körning.
+
+\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.
+
+\subsubsection{Thunk}
+En \emph{Thunk} är en avstannad beräkning, en \emph{continuation}. En \emph{Thunk} består av en \emph{Env} och en \emph{Expression}.
+
+\begin{lstlisting}
+data Thunk = Closure Env Expression
+\end{lstlisting}
+
+Haskell måste använda sig av \emph{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 \emph{Thunks} för de delar av beräkningen som ännu inte behövs. När värdet av en \emph{Thunk} behövs kommer den att tvingas till en \emph{Weak Head Normal Form} (WHNF) eller en ny \emph{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 returnerar något typ av värde, alltså något som inte är \emph{undefined}. Ofta innehåller en WHNF referenser till ännu icke evaluerade uttryck, om de inte gör det sägs uttrycket vara i \emph{Normal Form}.
+
+\begin{lstlisting}
+data WeakHead
+ = Data Identifier [HeapPtr]
+ | LambdaAbstraction Env Pattern Expression
+ | DelayedApplication Env Int [Declaration] [HeapPtr]
+ | Primitive
+\end{lstlisting}
+
+En \emph{Data} är resultatet av att applicera en algebraisk datakonstruktor på dess argument. Argumenten ges som en lista av \emph{HeapPtr}, det vill säga en lista av evaluerade eller icke evaluerade uttryck. Exempelvis resulterar \emph{Just 1} i en \emph{Data} med Identifiern \emph{Just} och en \emph{HeapPtr} till det icke evaluerade uttrycket 1.
+
+En \emph{LambdaAbstraction} är körningsrepresentationen av en lambda-funktion, en \emph{Env} är bunden till lambda-funktionen.
+
+En \emph{DelayedApplication} är ett specialfall av en \emph{LambdaAbstraction}. Vi avsockrar inte Haskells funktionsdeklarationer, vilket innebär att \emph{pattern matching} sker även vid funktionsapplikation och inte bara i \emph{Case-satser}. Detta betyder att vi måste samla alla argument till en funktion innan vi kan avgöra vilket funktionsalternativ som skall användas. En vidare beskrivning finns i kapitlet Declaration.
+
+En \emph{Primitive} är ett Javascript-värde, till exempel en \emph{integer} eller en \emph{double}.
+
+\subsubsection{HeapPtr}
+De flesta implementationer av Haskell använder sig av lat evaluering, vilket innebär att en \emph{Thunk}, ett uttryck, kommer att tvingas maximalt en gång. I vår implementation används \emph{HeapPtr} som en wrapper runt en \emph{Thunk}, när en \emph{HeapPtr} dereferensera kommer \emph{Thunk} att tvingas till en WHNF och \emph{HeapPtr} uppdateras att peka till denna. Eftersom att tvingandet av en \emph{Thunk} kan resultera i en ny \emph{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 \emph{HeapPtr} är ett vanligt Javascript-objekt som innehåller funktionen \emph{dereference}. \emph{Dereference} körs när anroparen vill använda den WHNF som \emph{HeapPtr} pekar mot. Om \emph{HeapPtr} inte har blivit dereferenserad innan så kommer dess \emph{Thunk} att tvingas tills det att resultatet är en WHNF och \emph{HeapPtr}-objektet uppdateras till att peka mot denna.
+
+\subsubsection{Env}
+Env är en stack av \emph{Javascript hashes}. Hasharna består av en bindning mellan en \emph{Identifier} och antingen en \emph{HeapPtr} eller ett (\emph{Pattern}, \emph{HeapPtr}) par. Den andra bindningstypen är resultatet av en \emph{VariableDeclaration} där interpretatorn måste utföra en \emph{pattern match} för att avgöra vilken \emph{HeapPtr} som hör till vilken \emph{Identifier}. När interpretatorn läser ut en \emph{Identifier} som är bunden enligt den andra typen av bindning, kommer en \emph{pattern match} att utföras och alla \emph{identifiers} i det \emph{pattern} som matchas kommer att bindas om som den första typen alternativt en \emph{pattern match fail} inträffar och ett \emph{exception} genereras.
+
+\begin{lstlisting}
+Env {
+ a => ([a, b, 3], [1,2,3])
+ b => ([a, b, 3], [1,2,3])
+}
+Env.find(a)
+Env {
+ a => 1
+ b => 2
+}
+\end{lstlisting}
+
+\subsection{Abstrakt syntaxträd och evaluering}
+Vår AST representeras av javascriptobjekt men dess strukturella uppbyggnad ges här av Haskells datadefinitioner.
+
+\subsubsection{Declaration}
+Den första datatypen av intresse är \emph{Declaration}. En \emph{Declaration} representerar en namnbindning antigen i en moduls globala definitionsområde eller i en \emph{let}- eller \emph{where}-bindning.
+
+\begin{lstlisting}
+data Declaration
+ = Variable Pattern Expression
+ | Data Identifier [Constructor]
+ | Function Identifier [Pattern]
+ (Either [(Guard, Expression)] Expression)
+\end{lstlisting}
+
+\emph{Variable} är en bindning av typen \emph{p = e} där p är en \emph{Pattern} och e en \emph{Expression}. En \emph{Variable} kan därför binda flera olika symboler på en gång. Till exempel \emph{(1:a:b:[]) = [1,2,3]} binder variabeln a och b.
+
+\emph{Function} är en representation av Haskells sockrade funktionsdefinitioner. Det är möjligt att avsockra dessa till en \emph{VariableBinding} med hjälp av \emph{Lambda} och \emph{Case} men vi har valt att införa en speciell representation av funktionsdefinitioner. Till skillnad från traditionella kompilatorer så avsockras \emph{Function} aldrig utan håller samma form även under interpreteringen. Tanken bakom detta är att det skall vara lättare att se sammanhanget mellan datan under körning och källkoden vilket gör det lättare att knyta samman den statiska källkoden med den dynamiska körningsdatan.
+
+En \emph{Data} definierar en algebraisk datatyp med konstruktorerna definierade som nedan
+\begin{lstlisting}
+data Constructor = Constructor Identifier Int
+\end{lstlisting}
+Värt att notera här är avsaknaden av typvariabler och typargument, detta kommer att åtgärdas när typcheckaren är integrerad.
+
+Under interpreteringen av en \emph{Declaration} binds de namn (Identifiers) som definieras av \emph{Declaration} till \emph{Env}-objektet. Vilken typ av bindning som används beror på typen av \emph{Declaration}. En \emph{Variable} ger en \emph{Identifier => (Pattern, Expression)}-bindning medan en \emph{Function} eller \emph{Data} ger en \emph{Identifier => Expression}-bindning.
+
+\subsubsection{Expression}
+En \emph{Expression} är representationen av ett haskelluttryck.
+
+\begin{lstlisting}
+data Expression
+ = Constant Value
+ | Lambda Pattern Expression
+ | Let [Declaration] Expression
+ | Case Expression [(Pattern, Expression)]
+ | VariableLookup Identifier
+ | Do [DoNotation]
+ | List [Expression]
+ | ListComprehension Expression [ListNotation]
+ | ArithmeticSequence Expression (Maybe Expression)
+ (Maybe Expression)
+ | Primitive JavascriptFunction
+\end{lstlisting}
+
+När en \emph{Expression} evalueras under en \emph{Env} är resultatet antingen en \emph{Thunk} (continuation, closure) eller en WHNF. Evaluering av en \emph{Constant} resulterar antigen i en primitiv eller en avsockring av konstanten. I interpretatorn så är konstanta nummer, till exempel 1, egentligen en algebraisk datatyp (I\# 1\#) och denna avsockring sker först under körning. När en \emph{Lambda} evalueras returneras en \emph{LambdaAbstraction} med evalueringens \emph{Env} bunden. En \emph{Let} evalueras genom att binda dess \emph{Declarations} till \emph{Env}-objektet och returnera en \emph{Closure} över det nya \emph{Env}-objektet och \emph{Let}-uttryckets \emph{Expression}. En \emph{Case} evalueras genom att den första \emph{Expression} i tuppellistan vars \emph{Pattern} matchar evalueras under den \emph{Env} som resulterar från \emph{pattern matchen}.
+\begin{lstlisting}
+this.eval = function(env) {
+ var expr = new interpreter.HeapPtr(
+ new interpreter.Closure(env, this.expr));
+ for (var i in this.cases) {
+ var newEnv = env.derive();
+ if (this.cases[i][0].match(newEnv, expr)) {
+ return this.cases[i][1].eval(newEnv);
+ }
+ }
+ throw new Error("No matching clause");
+};
+\end{lstlisting}
+Detta är \emph{eval}-metoden för ett \emph{Case}-uttryck. Här syns hur en ny \emph{Env} används vid varje alternativ i \emph{Case}-satsen och hur granskaren delas mellan de olika alternativen.
+
+Att evaluera en \emph{VariableLookup} under en \emph{Env} är det samma som att leta upp en \emph{Identifier} i \emph{Env}-objektet.
+
+\emph{Do}, \emph{List} och \emph{ArithmeticSequence} är inte evaluerade direkt utan de är avsockrade och sedan evalueras det avsockrade uttrycket. Avsockringsreglerna ges i Haskell 98 standarden \citep{haskell98chap3}.
+
+En \emph{Primitive} är en wrapper runt en Javascript-funktion. Att evaluera en \emph{Primitive} är det samma som att evaluera funktionen med \emph{Env} som argument.
+
+\subsubsection{Pattern}
+Vi har implementerat fem stycken olika \emph{pattern matches} från Haskell.
+\begin{lstlisting}
+data Pattern = Constructor Identifier [Pattern]
+ | VariableBinding Identifier
+ | Combined Identifier Pattern
+ | ConstantPattern Value
+ | Wildcard
+\end{lstlisting}
+Under en \emph{pattern match} händer två saker. Dels så kontrolleras att uttrycket som matchas verkligen stämmer överens med dess pattern, dels så binds de variabler som definieras i \emph{Pattern} till \emph{Env}.
+
+En \emph{VariableBinding} matchar alla uttryck och binder uttrycket till \emph{Identifier}. En \emph{Constructor} matchar de uttryck vars WHNF är en \emph{Data} med samma \emph{Identifier} (samt samma typ, detta tvingas dock av typcheckaren) och alla sub-patterns matchar \emph{Data}-argumenten. \emph{Combined} är en sammanslagning av en \emph{VariableBinding} och en annan \emph{Pattern}, i källkoden så har de formen \emph{v@p}. \emph{Combined} matchar de uttryck som matchar dess \emph{Pattern} och binder ett matchat uttryck till \emph{Identifier}. En \emph{ConstantPattern} matchar de uttryck som är exakt lika med värdet. Till sist så matchar en \emph{Wildcard} alla uttryck.
+
\subsection{HIJi}
-HIJi är ett program som ger användaren ett GHCi-liknande användargränssnitt till haskelltolken i webläsaren.
-HIJi tar indata genom att funktioner skrivs in i HIJi som sedan tolkas av parsern och i sin tur bygger upp det abstrakta syntaxträdet. Därefter evalueras uttrycket av interpretern och resultatet blir synligt i HIJi.
+HIJi är ett program som ger användaren ett GHCi-liknande användargränssnitt till haskelltolken i en webbläsare.
+HIJi tar indata genom att funktioner skrivs in i HIJi som sedan tolkas av parsern och i sin tur bygger upp det abstrakta syntaxträdet. Därefter evalueras uttrycket av interpretatorn och resultatet blir synligt i HIJi.
-HIJi har stöd för att ladda externa moduler. Det görs genom att skriva :l \emph{namn-på-modul}. Användaren får då tillgång till alla de funktioner som är skrivna i den modulen. Modulerna måste vara placerade på servern som HIJi laddades ifrån. Modulerna kan ej laddas direkt från användarens hårddisk på grund av att javascript av säkerhetsskäl ej har skriv och läsrättigheter av användarens filsystem. HIJi har även en förladdad modul, Prelude, som innehåller en delmängd av de funktioner som finns i GHCis motsvarighet.
+HIJi har stöd för att ladda externa moduler. Det görs genom att skriva :l \emph{namn-på-modul}. Användaren får då tillgång till alla de funktioner som är skrivna i den modulen. Modulerna måste vara placerade på servern som HIJi laddades ifrån. Modulerna kan ej laddas direkt från användarens hårddisk på grund av att Javascript av säkerhetsskäl ej har läs- och skrivrättigheter av användarens filsystem. HIJi har även en förladdad modul, Prelude, som innehåller en delmängd av de funktioner som GHCi har i sin motsvarighet.
Den indata som användaren skriver till HIJi sparas i ett objekt för att hantera historiken. För att bläddra i historiken används piltangenterna Upp och Ner. Hela historik-objektet sparas även i en kaka som ett JSON-objekt. Av detta skäl är det möjligt att få tillgång till historiken när en ny session av webbläsaren startas.
+%
\begin{figure}[H]
\begin{center}
\includegraphics[width=1\textwidth]{hiji_screen3.png}
@@ -459,16 +451,16 @@ \subsection{HIJi}
\end{center}
\end{figure}
-Figur \ref{fig:hiji} visar hur HIJi ser ut. De första raderna visar, precis som i GHCi, vilka moduler som för närvarande är laddade. I det här exemplet är den förladdade modulen Prelude laddad. Därefter följer en kommandotolk där användaren fritt kan skriva in egna funktioner. I figuren är en lambda-funktion inskriven.
+Figur \ref{fig:hiji} visar hur HIJi ser ut. De första raderna visar, precis som i GHCi, vilka moduler som för närvarande är laddade. I det här exemplet är den förladdade modulen Prelude laddad. Därefter följer en kommandotolk där användaren fritt kan skriva in egna funktioner. Figuren visar ett antal olika exempel på hur HIJi kan användas.
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.
\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}.
-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}.
+I HIJis förladdade modul, Prelude, har vi definierad upp ett antal funktioner som visar på att vi har implementerat dessa egenskaper från specifikationen.
+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 definierat 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.
\begin{lstlisting}
View
4 rapport/kapitel/sammanfattning.tex
@@ -2,12 +2,12 @@
\begin{abstract}
-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.
+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 \emph{Glasgow Haskell Compiler} (GHC).
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.
- 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.
+ Parsern tar användarens indata och konverterar den till en intern 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äldefinierat 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.
View
12 rapport/kapitel/slutsatser.tex
@@ -1,9 +1,9 @@
\section{Slutsatser}
-Vi har visat hur en Haskelltolk kan implenteras i Javascript,
-
-Vi har implementerat namngivna och anonyma funktioner, algebraiska datatyper och pattern matchning.
-Vi har dock inte implementerat typklasser, men stöd för det finns i typcheckaren och parsern.
-
-Vi har demonstrerat hur man med parser combinators kan implementera haskells layoutregler och grammatik.
+I den här rapporten har vi visat hur vi har implementerat en haskelltolk Javascript.
+Vi har implementerat namngivna och anonyma funktioner, algebraiska datatyper och pattern matching.
+Vi har dock inte implementerat typklasser, men stöd för det finns i typcheckaren och parsern.
+Vi har beskrivit hur vi med parser combinators har implementerat Haskells layoutregler och grammatik, en typcheckare som kan typchecka Haskell enligt de regler som haskellstandarden föreskriver samt en interpretator som tolkar Haskell med lat evaluering. Slutligen beskriver vi HIJi, ett enkelt användargränssnitt till haskelltolken.
+En rad förbättringsåtgärder har identifierats för att göra tolken mer användbar för nybörjare. Främst handlar det om att göra ett snyggt interaktivt användargränssnitt till HIJi, men även att generera bättre felmeddelanden i parsern.
+Totalt sett har projektet visat sig vara lyckat, även om vi är medvetna om att mycket finns kvar att förbättra.
Please sign in to comment.
Something went wrong with that request. Please try again.