Permalink
Browse files

Update to submitted version of TFP paper

  • Loading branch information...
1 parent 5c7e5b1 commit 421da3d271befff8017d5dd27e4736975894568e Edwin Brady committed Jul 6, 2011
@@ -137,19 +137,17 @@ \subsection{Compiling}
While Atuin is a different kind of language from the
$\lambda$-calculus, with complicating factors such as a global state
-(the turtle). imperative features, and dynamic type checking, the
+(the turtle), imperative features, and dynamic type checking, the
process of constructing a compiler follows the same general recipe, i.e.
define primitive operations as Epic functions, then convert each Atuin
definition into the corresponding Epic definition.
\subsubsection{Compiling Primitives}
-The first step in defining a compiler for Atuin is to define primitive
-operations as Epic functions.
-The language is dynamically
-typed, therefore we will need primitive operations to check that they
-are operating on the correct types. We define functions which
-construct Epic code for
+The first step is to define primitive operations as Epic functions.
+The language is dynamically typed, therefore we will need primitive
+operations to check dynamically that they are operating on values of
+the correct type. We define functions which construct Epic code for
building values, effectively using a single algebraic datatype to
capture all possible run-time values (i.e. values are
``uni-typed''~\cite{wadlerblame}).
@@ -166,21 +164,20 @@ \subsubsection{Compiling Primitives}
\noindent
Correspondingly, we can extract the concrete values safely from this
-structure, checking that the value is the required type:
+structure, checking that the value is the required type, e.g.:
\begin{SaveVerbatim}{epicgetval}
-getInt x = case_ x
- [con 0 (\ (x :: Expr) -> x),
- defaultcase (error_ "Not an Int")]
+getInt x = case_ x [con 0 (\ (x :: Expr) -> x),
+ defaultcase (error_ "Not an Int")]
\end{SaveVerbatim}
\useverb{epicgetval}
\noindent
Similarly, \texttt{getChar}, \texttt{getBool} and \texttt{getCol}
check and extract values of the appropriate type.
-Using these, it is simple to define primitve arithmetic operations
+Using these, it is simple to define primitive arithmetic operations
which check they are operating on the correct type, and report an
error if not.
@@ -190,7 +187,6 @@ \subsubsection{Compiling Primitives}
primMinus x y = mkint $ op_ minus_ (getInt x) (getInt y)
primTimes x y = mkint $ op_ times_ (getInt x) (getInt y)
primDivide x y = mkint $ op_ divide_ (getInt x) (getInt y)
-
\end{SaveVerbatim}
\useverb{primops}
@@ -204,9 +200,8 @@ \subsubsection{Graphics Operations}
\begin{SaveVerbatim}{sdlglue}
void* startSDL(int x, int y);
-void drawLine(void* surf,
- int x, int y, int ex, int ey,
- int r, int g, int b, int a);
+void drawLine(void* surf, int x, int y, int ex, int ey,
+ int r, int g, int b, int a);
\end{SaveVerbatim}
\useverb{sdlglue}
@@ -220,15 +215,14 @@ \subsubsection{Graphics Operations}
We represent colours as a 4-tuple $(\vr,\vg,\vb,\va)$. Drawing a line
in Epic involves extracting the red, green, blue and alpha components
-from this tuple, then calling the C \texttt{drawLine} function. Recall
-that to make a foreign function call, we give the types of each
-argument explicitly so that Epic will know how to convert from
-internal values to C values:
+from this tuple, then calling the C \texttt{drawLine} function. To
+make a foreign function call, we use \texttt{foreign\_}, giving the C
+function name and explicit types for each argument so that Epic
+will know how to convert from internal values to C values:
\begin{SaveVerbatim}{drawline}
-drawLine :: Expr -> Expr -> Expr ->
- Expr -> Expr -> Expr -> Term
+drawLine :: Expr -> Expr -> Expr -> Expr -> Expr -> Expr -> Term
drawLine surf x y ex ey col
= case_ (rgba col)
[tuple (\ r g b a ->
@@ -240,17 +234,17 @@ \subsubsection{Graphics Operations}
\end{SaveVerbatim}
\useverb{drawline}
-When we compile Atuin programs, we treat the turtle state as a tuple
+\noindent
+The turtle state is a tuple
$(\vs,\vx,\vy,\vd,\vc,\vp)$ where $\vs$ is a pointer to the SDL
-surface, $\vx$ and $\vy$ give the turtle's location, $\vd$ gives the
-turtle's direction, $\vc$ gives the colour and $\vp$ gives the pen
+surface, ($\vx$, $\vy$) gives the turtle's location, $\vd$ gives its
+direction, $\vc$ gives the colour and $\vp$ gives the pen
state (a boolean, false for up and true for down). Note that this
-state is not accessible by the programmer, so we do not need any
-dynamic type checking of each component.
-
+state is not accessible by Atuin programs, so we do not dynamically check
+each component.
To implement the \texttt{forward} operation, for example, we take the
-current turtle state, update the position according to the distance
-given and the current direction, and if the pen us down, draws a line
+current state, update the position according to the distance
+given and the current direction, and if the pen is down, draws a line
from the old position to the new position.
\begin{SaveVerbatim}{drawfwd}
@@ -277,32 +271,32 @@ \subsubsection{Graphics Operations}
\subsubsection{Compiling Programs}
-Programs return an updated turtle state, and possibly perform some
-side-effects such as drawing. We can think of Atuin definitions with
-arguments $\va_1$ to $\va_n$ as being translated to an Epic function
+Programs return an updated turtle state, and possibly perform
+side-effects such as drawing. An Atuin definition with
+arguments $\va_1\ldots\va_n$ is translated to an Epic function
with a type of the following form:
\DM{
\vf \Hab \VV{State} \to \va_1 \to \ldots \to \va_n \to \VV{State}
}
+\noindent
To compile a complete program, we add the primitive functions we have
defined above (line drawing, turtle movement, etc) to the list of
basic Epic definitions, and convert the user defined procedures to Epic.
\begin{SaveVerbatim}{prims}
-prims = basic_defs ++
- [EpicFn (name "initSDL") initSDL,
- EpicFn (name "drawLine") drawLine,
- EpicFn (name "forward") forward, ... ]
+prims = basic_defs ++ [EpicFn (name "initSDL") initSDL,
+ EpicFn (name "drawLine") drawLine,
+ EpicFn (name "forward") forward, ... ]
\end{SaveVerbatim}
\useverb{prims}
\noindent
-We will need to convert expressions, commands and full programs into
-Epic terms, so define a type class to capture all of these. Programs
+We define a type class to capture conversion of expressions, commands
+and full programs into Epic terms. Programs
maintain the turtle's state (an Epic \texttt{Expr}), and return a new
state, so we pass this state to the compiler.
@@ -314,6 +308,7 @@ \subsubsection{Compiling Programs}
\end{SaveVerbatim}
\useverb{compileclass}
+\noindent
In general, since we have set up all of the primitive operations as
Epic functions, compiling an Atuin program consists of directly
translating the abstract syntax to the Epic equivalent, making sure
@@ -324,8 +319,7 @@ \subsubsection{Compiling Programs}
\begin{SaveVerbatim}{compfn}
-compile state (Call i es)
- = app (fn fullId i) @@ state) es
+compile state (Call i es) = app (fn fullId i) @@ state) es
where app f [] = f
app f (e:es) = app (f @@ compile state e) es
@@ -371,9 +365,8 @@ \subsubsection{Compiling Programs}
\begin{SaveVerbatim}{runmain}
-init_turtle surf = tuple_ @@ surf @@
- int 320 @@ int 240 @@ int 180 @@
- col_white @@ bool True
+init_turtle surf = tuple_ @@ surf @@ int 320 @@ int 240 @@
+ int 180 @@ col_white @@ bool True
runMain :: Term
runMain = let_ (fn "initSDL" @@ int 640 @@ int 480)
@@ -384,6 +377,7 @@ \subsubsection{Compiling Programs}
\end{SaveVerbatim}
\useverb{runmain}
+\noindent
The full source code for Atuin and its compiler is available from
Hackage (\url{http://hackage.haskell.org/package/atuin}), which
covers the remaining technical details of linking compiled programs
@@ -12,11 +12,14 @@ \section{Related Work}
Epic uses techniques from other functional language back
ends~\cite{evalpush,stg,abc-machine} but deliberately exposes its core
language as an API to make it as reusable as possible. Although there
-is likely to always be a trade off between reusability and efficiency,
+is always likely to be a trade off between reusability and efficiency,
exposing the API will make it easier for other language researchers to
build a new compiler quickly. The Lazy Virtual Machine~\cite{lvm} has
similar goals but it designed as a lower level target language, rather
-than a high level API.
+than a high level API. C\texttt{--}~\cite{c--} and LLVM~\cite{llvm} are also
+tools for generating language back ends, but are similarly low level and
+do not provide direct support for functional features. We could
+nevertheless consider using these tools for Epic code generation.
%C--~\cite{c--} and LLVM~\cite{llvm}
%as possible code generation strategies. Supercompilation for
@@ -31,28 +34,42 @@ \section{Conclusion}
well-understood but difficult to implement problems such as lambda
lifting, code generation, interfacing with foreign functions and
garbage collection.
-
In this paper we have seen two examples of languages which can be
compiled via Epic, both functionally based, but with different
features. The high-level recipe for each is the same: define primitive
functions as run-time support, then translate the abstract syntax into
-concrete Epic functions, using a combinator style API.
+concrete Epic functions, using a combinator style API. In addition,
+we have implemented a compiler for \LamPi{}~\cite{simply-easy}, a
+dependently typed language, which shows how Epic can handle languages
+with more expressive type
+systems\footnote{\url{http://www.idris-lang.org/examples/LambdaPi.hs}}.
+
\subsubsection{Future work}
-Epic is currently used in practice by a dependently typed functional
-language, Idris~\cite{plpv11}, and experimentally by
-Agda~\cite{norell-thesis} and Epigram~\cite{levitation}. Future work
-will therefore have an emphasis on providing an efficient executable
-environment for these and related languages. An interesting research
-question, for example, is whether the rich type systems of these languages
-can be used to guide optimisation, and if so how to present the
-information gained by the type system to the compiler.
+%Epic is currently used in practice by a dependently typed functional
+%language, Idris~\cite{plpv11}, and experimentally by
+%Agda~\cite{norell-thesis} and Epigram~\cite{levitation}.
+
+Since Epic is currently used in practice by a number of dependently
+typed functional languages, future work will have an emphasis on
+providing an efficient executable environment for these and related
+languages. An interesting research question, for example, is whether
+the rich type systems of these languages can be used to guide
+optimisation, and if so how to present the information gained by the
+type system to the compiler.
Currently, Epic compiles to machine code via C, using the Boehm
conservative garbage collector~\cite{boehm-gc}. While this has been
reasonably efficient in practice, we believe that an LLVM based
implementation~\cite{llvm,llvm-haskell} with accurate garbage
-collection would be more appropriate. Of course, any language which
-uses Epic as a back end will stand to gain from future optimisation
-efforts!
+collection would be more appropriate as it could take advantage of
+functional language features such as immutability of data.
+
+Perhaps more importantly, as a very simple functional language Epic is
+a convenient platform with which to experiment with functional
+compilation techniques. For example, we are developing an evaluator
+which will be a starting point for experimenting with
+supercompilation~\cite{mitchell-super} and partial evaluation.
+Of course, any language which uses Epic as a back end will stand to
+gain from future optimisation efforts!
View
@@ -66,12 +66,12 @@
well understood, it remains difficult for a new functional language to
exploit these techniques without either implementing a compiler from
scratch, or attempting fit the new language around another existing
-compiler.
-Epic is a compiled functional language which exposes functional
-compilation techniques to a language implementor, with a Haskell
-API. In this paper we describe Epic and outline how it may
-be used to implement a high level language compiler, illustrating our
-approach using a dynamically typed graphics language.
+compiler. Epic is a compiled functional language which exposes
+functional compilation techniques to a language implementor, with a
+Haskell API. In this paper we describe Epic and outline how it may be
+used to implement a high level language compiler, illustrating our
+approach by implementing compilers for the $\lambda$-calculus and a
+dynamically typed graphics language.
\end{abstract}
@@ -3,23 +3,24 @@ \section{Example --- Compiling the $\lambda$-Calculus}
\label{sec:lc}
In this section we present a compiler for a simple high level
-language.
-This is a compiler for the untyped $\lambda$-calculus using Higher Order
-Abstract Syntax, which shows the fundamental features of Epic required
-to implement a complete compiler. We have also implemented compilers
-for \LamPi{}~\cite{simply-easy}, a dependently typed language, which
-shows how Epic can handle languages with more expressive type systems,
-and a dynamically typed graphics language\footnote{\url{http://hackage.haskell.org/package/atuin}}, which shows how Epic can be
-used for languages with run-time type checking and which require
-foreign function calls.
+language, the untyped $\lambda$-calculus using higher order abstract
+syntax. This shows the fundamental features of Epic required to
+implement a complete compiler.
+
+%We have also implemented compilers
+%for \LamPi{}~\cite{simply-easy}, a dependently typed language, which
+%shows how Epic can handle languages with more expressive type systems,
+%and a dynamically typed graphics language\footnote{\url{http://hackage.haskell.org/package/atuin}}, which shows how Epic can be
+%used for languages with run-time type checking and which require
+%foreign function calls.
\subsection{Representation}
Our example is an implementation of the untyped
$\lambda$-calculus, plus primitive integers and strings, and
-arithmetic and string operators. The language is represented in
-Haskell using higher order abstract syntax (HOAS). That is, we
-represent $\lambda$-bindings (\texttt{Lam}) as Haskell functions,
+arithmetic and string operators. The Haskell representation uses
+higher order abstract syntax (HOAS), i.e. we
+represent $\lambda$-bindings (\texttt{Lam}) as functions,
using a Haskell variable name to refer to the locally bound
variable. We also include global references (\texttt{Ref}) which refer
to top level functions, function application (\texttt{App}), constants
@@ -82,8 +83,6 @@ \subsection{Compilation}
\begin{SaveVerbatim}{eprogs}
data EpicDecl = forall e. EpicExpr e => EpicFn Name e
- | ...
-
type Program = [EpicDecl]
\end{SaveVerbatim}
@@ -168,16 +167,22 @@ \subsection{Compilation}
Given \texttt{build}, we can translate a collection of HOAS
definitions into an Epic program, add the built-in Epic definitions
and execute it directly. Recall that there must be a function called
-\texttt{"main"} or Epic will report an error.
+\texttt{"main"} or Epic will report an error --- we therefore add a
+main function which prints the value of an integer expression
+given at compile time.
\begin{SaveVerbatim}{lmain}
-mkProgram :: Defs -> Program
-mkProgram ds = basic_defs ++
- map (\ (n, d) -> EpicFn n (build d)) ds
+main_ exp = App (Ref (name "putStrLn"))
+ (App (Ref (name "intToString")) exp)
+
+mkProgram :: Defs -> Lang -> Program
+mkProgram ds exp = basic_defs ++
+ map (\ (n, d) -> EpicFn n (build d)) ds ++
+ [(name "main", main_ exp)]
-execute :: Defs -> IO ()
-execute p = run (mkProgram p)
+execute :: Defs -> Lang -> IO ()
+execute p exp = run (mkProgram p exp)
\end{SaveVerbatim}
\useverb{lmain}
@@ -188,8 +193,8 @@ \subsection{Compilation}
\begin{SaveVerbatim}{lcomp}
-comp :: Defs -> IO ()
-comp p = compile "a.out" (mkProgram p)
+comp :: Defs -> Lang -> IO ()
+comp p exp = compile "a.out" (mkProgram p exp)
\end{SaveVerbatim}
\useverb{lcomp}
Oops, something went wrong.

0 comments on commit 421da3d

Please sign in to comment.