summaryrefslogtreecommitdiff
path: root/cleansmurf.tex
diff options
context:
space:
mode:
Diffstat (limited to 'cleansmurf.tex')
-rw-r--r--cleansmurf.tex123
1 files changed, 123 insertions, 0 deletions
diff --git a/cleansmurf.tex b/cleansmurf.tex
new file mode 100644
index 0000000..24011bf
--- /dev/null
+++ b/cleansmurf.tex
@@ -0,0 +1,123 @@
+% vim: set spelllang=nl:
+\section{CleanSmurf}
+\label{sec:cleansmurf}
+
+Semantiekregels vertalen zich uiterst gemakkelijk naar een implementatie van
+een interpreter in een functionele taal. \emph{CleanSmurf}~\cite{cleansmurf} is
+een interpreter voor Smurf, geschreven in Clean, dat onze semantiekregels
+volgt. Omdat het de semantiekregels volgt, was het niet lastig dit uit te
+breiden naar een programma dat een afleidingsboom genereert. In dit hoofdstuk
+beschrijven we de globale opzet van dit programma.
+
+\subsection{Types}
+\label{sec:cleansmurf:types}
+Het programma houdt de expressieve syntax uit \autoref{sec:def:syn} aan. Het
+type \CI{Stm} is dus:
+
+\lstinputlisting[firstline=15,lastline=20]{CleanSmurf/Smurf.dcl}
+
+We gebruiken lijsten als stacks en implementeren de store met behulp van een
+tabel van naam-waarde paren:
+
+\lstinputlisting[firstline=22,lastline=27]{CleanSmurf/Smurf.dcl}
+
+Ten slotte definiëren we transities. Aangezien alle semantiekregels hooguit één
+premisse hebben, kunnen we een afleidingsboom als lijstje transities zien:
+
+\lstinputlisting[firstline=35,lastline=36]{CleanSmurf/Smurf.dcl}
+
+Met deze definities kunnen we een \CI{step :: Program State -> Maybe (Program,
+State)} definiëren. Dit komt bijna overeen met de structuur van transities. We
+moeten een \CI{Program} teruggeven, omdat we slechts één stap zetten. Wat dit
+betreft lijken de regels van \emph{CleanSmurf} meer op regels in structurele
+operationele semantiek. We hebben al laten zien dat deze regels erg veel lijken
+op die in natuurlijke semantiek.
+
+Het type van \CI{step} neemt nog geen Input/Output mee. We maken er een
+overloaded functie van, zodat hij voor meerdere inputmethodes kan worden
+gebruikt. Het uiteindelijke type is:
+
+\lstinputlisting[firstline=56,lastline=56]{CleanSmurf/Smurf.dcl}
+
+Hoe dit precies werkt is niet belangrijk voor de beschrijving hier. Het derde
+argument, van type \CI{io}, is de `IO-toestand'. Het vierde argument, van type
+\CI{IO io}, omvat een input-functie die strings oplevert (gegeven de
+IO-toestand) en een output-functie die strings opneemt (in de IO-toestand).
+
+\medskip
+Verder definiëren we een aantal hulpfuncties:
+
+\lstinputlisting[firstline=232,lastline=245]{CleanSmurf/Smurf.icl}
+
+De partiële functies zijn hier gesimuleerd met het \CI{Maybe}-type. Dit laat
+ons monadische operatoren gebruiken in het uitwerken van de interpreter.
+
+\subsection{Semantiekregels}
+\label{sec:cleansmurf:regels}
+Iedere semantiekregel vertaalt min of meer direct naar een functiealternatief
+voor \CI{step}. Echter, omdat we geen \CI{run}- maar een \CI{step}-functie
+schrijven, moeten we compositie expliciet maken.
+
+Als voorbeeld zullen we de implementatie van $\StmHead$ bekijken. Aangezien
+\CI{pop} en \CI{head} allebei een \CI{Maybe} opleveren, kunnen we de resultaten
+gemakkelijk binden. Vervolgens wordt de stack geüpdate en wordt de rest van het
+programma (\CI{p}) teruggegeven. De IO-toestand wordt zonder gebruik
+doorgegeven. Het vierde argument hebben we niet nodig en kan dus worden
+genegeerd.
+
+\lstinputlisting[firstline=213,lastline=215]{CleanSmurf/Smurf.icl}
+
+Andere regels, voor $\StmPush$, $\StmTail$, $\StmCat$, $\StmQuotify$ en ook
+$\StmPut$ en $\StmGet$ gaan op soortgelijke wijze. Ook $\StmInput$ en
+$\StmOutput$ kunnen op dezelfde manier worden geschreven, afgezien van het feit
+dat de IO-toestand en -functies gebruikt moeten worden.
+
+In het geval van $\StmExec$ kunnen we handig gebruik maken van het feit dat
+\CI{step} een nieuw programma oplevert:
+
+\lstinputlisting[firstline=228,lastline=230]{CleanSmurf/Smurf.icl}
+
+Zoals te zien wordt een nieuwe toestand gemaakt (\CI{zero}) waarin dit nieuwe
+programma (\CI{p}) wordt uitgevoerd. De compositie \CI{parse o fromString}
+parseert een String van de stack en levert een \CI{Maybe Program} op. Dus ook
+deze wat afwijkende regel levert geen problemen op.
+
+\subsection{Afleidingsbomen}
+Door herhaaldelijk gebruik te maken van \CI{step} kunnen we gemakkelijk een
+afleidingsboom genereren. We maken hierbij gebruik van een aantal handige
+eigenschappen van afleidingsbomen voor Smurf:
+
+\begin{itemize}
+ \item Alle semantiekregels hebben ten hoogste één premisse, waardoor we een
+ boom als lijst van transities kunnen representeren.
+ \item Ieder commando heeft precies één regel. Hierdoor is aan het eerste
+ statement van een programma te herkennen welke regel wordt toegepast. Dit
+ hoeven we dus niet in de types \CI{Transition} en \CI{DerivationTree} op te
+ slaan.
+ \item Doordat condities van de semantiekregels enkel afhangen van de
+ linkerkant van de conclusie (het programma, de input en de toestand), en
+ deze informatie beschikbaar is op het moment dat de boom gemaakt wordt,
+ hoeven we geen backtracking toe te passen. Wanneer het niet lukt de regel
+ die bij het eerste commando van het programma hoort toe te passen, weten we
+ zeker dat er geen afleidingsboom bestaat.
+\end{itemize}
+
+De functie \CI{tree} is als volgt geïmplementeerd:
+
+\lstinputlisting[firstline=274]{CleanSmurf/Smurf.icl}
+
+Bij het genereren van bomen leggen we de input van te voren vast in een lijst.
+We slaan de output op in een andere lijst. Dit is wat het type \CI{ListIO}
+inhoudt --- de implementatie hiervan is irrelevant hier.
+
+Het eerste dat \CI{tree} doet is het berekenen van de volgende stap. Lukt dat
+niet (\CI{isNothing mbPgmSt}), dan kunnen we ook geen boom maken.
+
+Omdat \CI{step} voor een leeg programma een nieuw leeg programma oplevert,
+moeten we in deze functie controleren of het nieuwe programma leeg is. Is dit
+het geval, dan zetten we de $\lambda$-regel zelf in de boom als \CI{([],
+io.input, st) --> (io.input, [], st)}.
+
+Is dit niet het geval, dan maken we recursief een boom voor de premisse
+(\CI{tree pgm st io iof}). Lukt dit niet, dan kunnen we geen boom maken.
+Anders, dan voegen we de boom en de transitie gevonden met \CI{step} samen.