Update documenation for new release
This commit is contained in:
parent
3697ba0fd1
commit
6997145d4e
@ -1,17 +1,18 @@
|
|||||||
.TH HS-PLUGINS 1 2005-03-26 "hs-plugins version 0.9.8" "User Manual"
|
.TH HS-PLUGINS 1 2005-07-06 "hs-plugins version 0.9.10" "User Manual"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
hs-plugins \- dynamic linker library for Haskell
|
hs-plugins \- dynamic linker library for Haskell
|
||||||
|
|
||||||
.SH DESCRIPTION
|
.SH DESCRIPTION
|
||||||
.ds c \fIhs-plugins\fP
|
.ds c \fIhs-plugins\fP
|
||||||
\*c is a library for loading plugins written in Haskell into an
|
\*c is a library for loading code written in Haskell into an
|
||||||
application at runtime. It also provides a mechanism for (re)compiling
|
application at runtime, in the form of plugins. It also provides a
|
||||||
Haskell source at runtime. Thirdly, a combination of runtime compilation
|
mechanism for (re-)compiling Haskell source at runtime. Thirdly, a
|
||||||
and dynamic loading provides a suite of eval functions. Values exported
|
combination of runtime compilation and dynamic loading provides a set
|
||||||
by plugins are transparently available to Haskell host applications, and
|
of eval functions. Values exported by plugins are transparently
|
||||||
bindings exist to use Haskell plugins from at least C and Objective C
|
available to Haskell host applications, and bindings exist to use
|
||||||
programs. hs-plugins requires ghc-6.2.2 or greater.
|
Haskell plugins from at least C and Objective C programs. hs-plugins
|
||||||
|
requires GHC 6.2.2 or later.
|
||||||
|
|
||||||
.SH DOCUMENTATION
|
.SH DOCUMENTATION
|
||||||
The hs-plugins user manual is distributed in html format, and may be
|
The hs-plugins user manual is distributed in html format, and may be
|
||||||
@ -33,4 +34,3 @@ LGPL.
|
|||||||
This manual page was written by Don Stewart, based on the man page for
|
This manual page was written by Don Stewart, based on the man page for
|
||||||
cpphs (written by Ian Lynagh).
|
cpphs (written by Ian Lynagh).
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,18 +44,19 @@ h2 {font-size: 15pt}
|
|||||||
\medskip
|
\medskip
|
||||||
%
|
%
|
||||||
{\htmlonly \textbf{Download \endhtmlonly
|
{\htmlonly \textbf{Download \endhtmlonly
|
||||||
\urlh{ftp://ftp.cse.unsw.edu.au/pub/users/dons/hs-plugins/hs-plugins-0.9.8.tar.gz}
|
\urlh{ftp://ftp.cse.unsw.edu.au/pub/users/dons/hs-plugins/hs-plugins-0.9.10.tar.gz}
|
||||||
{version 0.9.8}}
|
{version 0.9.10}}
|
||||||
%
|
%
|
||||||
\medskip
|
\medskip
|
||||||
|
|
||||||
\hsplugins{} is a library for loading plugins written in Haskell into an
|
\hsplugins{} is a library for loading code written in Haskell into an
|
||||||
application at runtime. It also provides a mechanism for (re)compiling
|
application at runtime, in the form of plugins. It also provides a
|
||||||
Haskell source at runtime. Thirdly, a combination of runtime compilation
|
mechanism for (re-)compiling Haskell source at runtime. Thirdly, a
|
||||||
and dynamic loading provides a suite of \code{eval} functions. Values
|
combination of runtime compilation and dynamic loading provides a set
|
||||||
exported by plugins are transparently available to Haskell host
|
of \code{eval} functions-- a form of runtime metaprogramming. Values
|
||||||
|
exported by Haskell plugins are transparently available to Haskell host
|
||||||
applications, and bindings exist to use Haskell plugins from at least C
|
applications, and bindings exist to use Haskell plugins from at least C
|
||||||
and Objective C programs. \hsplugins{} currently requires ghc-6.2.2.
|
and Objective C programs. \hsplugins{} requires GHC 6.2.2 or later.
|
||||||
|
|
||||||
\medskip
|
\medskip
|
||||||
|
|
||||||
@ -71,38 +72,56 @@ and Objective C programs. \hsplugins{} currently requires ghc-6.2.2.
|
|||||||
|
|
||||||
\item
|
\item
|
||||||
Download the latest stable release:\\
|
Download the latest stable release:\\
|
||||||
\url{ftp://ftp.cse.unsw.edu.au/pub/users/dons/hs-plugins/hs-plugins-0.9.8.tar.gz}
|
\url{ftp://ftp.cse.unsw.edu.au/pub/users/dons/hs-plugins/hs-plugins-0.9.10.tar.gz}
|
||||||
|
|
||||||
|
|
||||||
\item
|
\item
|
||||||
Nightly cvs src snapshots are available at:\\
|
Darcs repository of the latest code:\\
|
||||||
\url{ftp://ftp.cse.unsw.edu.au/pub/users/dons/hs-plugins/snapshots/}
|
\url{darcs get http://www.cse.unsw.edu.au/~dons/code/hs-plugins}
|
||||||
|
|
||||||
|
|
||||||
\item
|
\item
|
||||||
A tarball of the document you are reading:\\
|
A tarball of the document you are reading:\\
|
||||||
\url{http://www.cse.unsw.edu.au/~dons/hs-plugins/hs-plugins.html.tar.gz}
|
\url{http://www.cse.unsw.edu.au/~dons/hs-plugins/hs-plugins.html.tar.gz}
|
||||||
|
|
||||||
|
|
||||||
\item
|
\item
|
||||||
A postscript version of the document you are reading:\\
|
A postscript version of the document you are reading:\\
|
||||||
\url{http://www.cse.unsw.edu.au/~dons/hs-plugins/hs-plugins.ps.gz}
|
\url{http://www.cse.unsw.edu.au/~dons/hs-plugins/hs-plugins.ps.gz}
|
||||||
|
|
||||||
|
\item
|
||||||
|
Papers:
|
||||||
|
\begin{itemize}
|
||||||
|
\item A paper on interesting uses of \hsplugins{} to enable Haskell to be used
|
||||||
|
as an application extension language:\\
|
||||||
|
\url{http://www.cse.unsw.edu.au/~dons/papers/PSSC04.html}
|
||||||
|
|
||||||
\item
|
\item
|
||||||
A paper on interesting uses of \hsplugins{} to enable Haskell to be used
|
A paper on dynamic applications in Haskell, utilizing \hsplugins{}:\\
|
||||||
as an application extension language:\\
|
\url{http://www.cse.unsw.edu.au/~dons/papers/SC05.html}
|
||||||
\url{http://www.cse.unsw.edu.au/~dons/hs-plugins/paper}
|
\end{itemize}
|
||||||
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
It is known to run on \code{i386-\{linux,freebsd,openbsd\}},
|
It is known to run on \code{i386-\{linux,freebsd,openbsd\}},
|
||||||
\code{ia64-linux}, \code{sparc-solaris2} and \code{powerpc-\{macosx,linux\}}.
|
\code{sparc-solaris2}, \code{powerpc-\{macosx,linux\}} and flavours of
|
||||||
|
Windows.
|
||||||
|
|
||||||
\section{History}
|
\section{History}
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item v0.9.8
|
\item June 2005, v0.9.10
|
||||||
|
\begin{itemize}
|
||||||
|
\item Support for GHC 6.4, with help from Sean
|
||||||
|
Seefried for the package.conf parser.
|
||||||
|
\item Ported to Windows of various flavours thanks to Vivian McPhail and Shelarcy
|
||||||
|
\item Removed posix and unix dependencies
|
||||||
|
\item Now uses HSX parser, thanks to Niklas Broberg
|
||||||
|
\item Extended load interface, thanks to Lemmih
|
||||||
|
\item Source now in a darcs repository
|
||||||
|
\item Supports building with GNU make -jN
|
||||||
|
\item Simplified module hierarchy, moved under System.* namespace
|
||||||
|
\item Miscellaneous bug fixes
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\item February 2005, v0.9.8
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Fix bug in .hi parsing.
|
\item Fix bug in .hi parsing.
|
||||||
\item Add reloading of packages.
|
\item Add reloading of packages.
|
||||||
@ -119,7 +138,7 @@ It is known to run on \code{i386-\{linux,freebsd,openbsd\}},
|
|||||||
\item Better api.
|
\item Better api.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
\item Septemeber 2004.
|
\item September 2004.
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item makeAll
|
\item makeAll
|
||||||
\item Better return type for make.
|
\item Better return type for make.
|
||||||
@ -237,10 +256,10 @@ all the other code the \hsplugins{} depends on.
|
|||||||
\section{Overview}
|
\section{Overview}
|
||||||
|
|
||||||
\hsplugins{} is a library for compiling and loading Haskell code into a
|
\hsplugins{} is a library for compiling and loading Haskell code into a
|
||||||
program at runtime. It allows you to write a Haskell program (which may
|
program at runtime. It allows you to write Haskell code (which may
|
||||||
be spread over multiple modules) and have an application (implemented in
|
be spread over multiple modules), and have an application (implemented in
|
||||||
any language with a Haskell FFI binding, including Haskell) load your
|
any language with a Haskell FFI binding, including Haskell) load and use
|
||||||
code at runtime, and use the values found within.
|
your code at runtime.
|
||||||
|
|
||||||
\hsplugins{} provides 3 major features:
|
\hsplugins{} provides 3 major features:
|
||||||
%
|
%
|
||||||
@ -252,26 +271,25 @@ code at runtime, and use the values found within.
|
|||||||
|
|
||||||
The \emph{dynamic loader} loads objects into the address space of an
|
The \emph{dynamic loader} loads objects into the address space of an
|
||||||
application, along with any dependencies the plugin may have. The
|
application, along with any dependencies the plugin may have. The
|
||||||
loader is a binding to the GHC loader, which does single object
|
loader is a binding to the GHC runtime system's dynamic linker, which
|
||||||
loading. GHC also performs the necessary linking of new objects into
|
does single object loading. GHC also performs the necessary linking of
|
||||||
the running process. On top of the GHC loader is our Haskell layer
|
new objects into the running process. On top of the GHC loader is a
|
||||||
that arranges for module and package dependencies to be found prior to
|
Haskell layer that arranges for module and package dependencies to be
|
||||||
loading individual modules.
|
found prior to loading individual modules.
|
||||||
|
|
||||||
The \emph{compilation manager} is a \code{make}-like system for
|
The \emph{compilation manager} is a \code{make}-like system for
|
||||||
compiling Haskell source code into a form suitable for loading
|
compiling Haskell source code into a form suitable for loading. While
|
||||||
dynamically. While plugins are normally thought of as strictly object
|
plugins are normally thought of as strictly object code, there are a
|
||||||
code, there are a variety of scenarios where it is desirable to be
|
variety of scenarios where it is desirable to be able to inspect the
|
||||||
able to inspect the source code of a plugin, or to be able to
|
source code of a plugin, or to be able to recompile a plugin at runtime.
|
||||||
recompile a plugin at runtime. The compilation manager fills this
|
The compilation manager fills this role. It is particularly useful in
|
||||||
role. It is particularly useful in the implementation of \code{eval},
|
the implementation of \code{eval}.
|
||||||
and \code{printf}.
|
|
||||||
|
|
||||||
The \emph{evaluator}, \code{eval}, is a client of the loader and
|
The \emph{evaluator}, \code{eval}, utilizes the loader and compilation
|
||||||
compilation manager. When passed a string of Haskell code, it compiles
|
manager. When passed a string of Haskell code, it compiles the string to
|
||||||
the string to object code, loads the result, and returns a Haskell
|
object code, loads the result, and returns a Haskell value representing
|
||||||
value representing the compiled string to the caller. It can be
|
the compiled string to the caller. It can be considered a Haskell
|
||||||
considered a Haskell interpreter, implemented as a library.
|
interpreter, implemented as a library.
|
||||||
|
|
||||||
\section{Dynamic Loader}
|
\section{Dynamic Loader}
|
||||||
|
|
||||||
@ -287,6 +305,8 @@ The dynamic loader is available by using \code{-package plugins}.
|
|||||||
%
|
%
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
|
import System.Plugins
|
||||||
|
|
||||||
load :: FilePath
|
load :: FilePath
|
||||||
-> [FilePath]
|
-> [FilePath]
|
||||||
-> [PackageConf]
|
-> [PackageConf]
|
||||||
@ -371,7 +391,7 @@ distributed with \hsplugins{}, and the \hsplugins{}
|
|||||||
\code{Dynamic} refer to the \hsplugins{} reimplementation of these
|
\code{Dynamic} refer to the \hsplugins{} reimplementation of these
|
||||||
libraries. \code{AltData.Dynamic} is used at the moment, as there is a
|
libraries. \code{AltData.Dynamic} is used at the moment, as there is a
|
||||||
limitation in the existing Data.Dynamic library in the presence of
|
limitation in the existing Data.Dynamic library in the presence of
|
||||||
dynamic loading. This will be fixed soon).
|
dynamic loading).
|
||||||
|
|
||||||
The value wrapped up in the \code{Dynamic} must be an instance of
|
The value wrapped up in the \code{Dynamic} must be an instance of
|
||||||
\code{AltData.Typeable}. If the value exported by the plugin \emph{is}
|
\code{AltData.Typeable}. If the value exported by the plugin \emph{is}
|
||||||
@ -400,6 +420,16 @@ pdynload :: FilePath
|
|||||||
-> Symbol
|
-> Symbol
|
||||||
-> IO (LoadStatus a)
|
-> IO (LoadStatus a)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\scm{
|
||||||
|
pdynload_ :: FilePath
|
||||||
|
-> [FilePath]
|
||||||
|
-> [PackageConf]
|
||||||
|
-> [Arg]
|
||||||
|
-> Type
|
||||||
|
-> Symbol
|
||||||
|
-> IO (LoadStatus a)
|
||||||
|
}
|
||||||
\end{quote}
|
\end{quote}
|
||||||
%
|
%
|
||||||
Example:
|
Example:
|
||||||
@ -425,8 +455,14 @@ argument. This can be considered a type annotation on the value the plugin
|
|||||||
should be constrained to.
|
should be constrained to.
|
||||||
|
|
||||||
The type of the plugin's resource field must be equivalent to the
|
The type of the plugin's resource field must be equivalent to the
|
||||||
\code{Type}. Prior to loading the object, \code{pdynload} generates a
|
\code{Type}. There are some restrictions on the arguments that may be
|
||||||
tiny Haskell source file containing, for example:
|
passed to pdynload. Currently, we require:
|
||||||
|
\begin{itemize}
|
||||||
|
\item TODO
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
Prior to loading the object, \code{pdynload} generates a tiny Haskell
|
||||||
|
source file containing, for example:
|
||||||
%
|
%
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
@ -453,10 +489,15 @@ checkable using the standard Dyanmic type. The cost is that
|
|||||||
\scm{
|
\scm{
|
||||||
unload :: Module -> IO ()
|
unload :: Module -> IO ()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
\scm{
|
||||||
|
unloadAll :: Module -> IO ()
|
||||||
|
}
|
||||||
\end{quote}
|
\end{quote}
|
||||||
|
|
||||||
Unload an object, \emph{but not its dependencies} from the address
|
Unload an object, \emph{but not its dependencies} from the address
|
||||||
space.
|
space. \code{unloadAll} performs cascading unloading of a module
|
||||||
|
\emph{and} its dependencies.
|
||||||
|
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
@ -506,6 +547,8 @@ compiled to object code suitable for loading.
|
|||||||
|
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
|
import System.Plugins
|
||||||
|
|
||||||
make :: FilePath
|
make :: FilePath
|
||||||
-> [Arg]
|
-> [Arg]
|
||||||
-> IO MakeStatus
|
-> IO MakeStatus
|
||||||
@ -514,6 +557,10 @@ makeAll :: FilePath
|
|||||||
-> [Arg]
|
-> [Arg]
|
||||||
-> IO MakeStatus
|
-> IO MakeStatus
|
||||||
|
|
||||||
|
recompileAll :: Module
|
||||||
|
-> [Arg]
|
||||||
|
-> IO MakeStatus
|
||||||
|
|
||||||
data MakeStatus
|
data MakeStatus
|
||||||
= MakeSuccess MakeCode FilePath
|
= MakeSuccess MakeCode FilePath
|
||||||
| MakeFailure Errors
|
| MakeFailure Errors
|
||||||
@ -533,12 +580,17 @@ dependencies prior to loading the object itself. \code{makeAll} also
|
|||||||
recursively compiles any dependencies it can find using GHC's
|
recursively compiles any dependencies it can find using GHC's
|
||||||
\code{--make} flag.
|
\code{--make} flag.
|
||||||
|
|
||||||
|
\code{recompileAll} is like \code{makeAll}, but rather than relying on
|
||||||
|
\code{ghc --make}, we explicitly check a module's dependencies.
|
||||||
|
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
merge :: FilePath -> FilePath -> IO MergeStatus
|
merge :: FilePath -> FilePath -> IO MergeStatus
|
||||||
|
|
||||||
mergeTo :: FilePath -> FilePath -> FilePath -> IO MergeStatus
|
mergeTo :: FilePath -> FilePath -> FilePath -> IO MergeStatus
|
||||||
|
|
||||||
|
mergeToDir :: FilePath -> FilePath -> FilePath -> IO MergeStatus
|
||||||
|
|
||||||
data MergeStatus
|
data MergeStatus
|
||||||
= MergeSuccess MergeCode Args FilePath
|
= MergeSuccess MergeCode Args FilePath
|
||||||
| MergeFailure Errors
|
| MergeFailure Errors
|
||||||
@ -559,7 +611,12 @@ must be provided as a \code{-package} flag to GHC, they may specify
|
|||||||
this using the non-standard \code{GLOBALOPTIONS} pragma. Options
|
this using the non-standard \code{GLOBALOPTIONS} pragma. Options
|
||||||
specified in the source this way will be added to the command line.
|
specified in the source this way will be added to the command line.
|
||||||
This is useful for users who wish to use GHC flags that cannot be
|
This is useful for users who wish to use GHC flags that cannot be
|
||||||
specified using the conventional \code{OPTIONS} pragma.
|
specified using the conventional \code{OPTIONS} pragma. The merging
|
||||||
|
operation uses the HSX parser library to parse Haskell source files.
|
||||||
|
|
||||||
|
\code{mergeTo} behaves like \code{merge}, but we can specify the file in
|
||||||
|
which to place output. \code{mergeToDir} lets you specify a directory in
|
||||||
|
which to place merged files.
|
||||||
|
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
@ -615,6 +672,16 @@ names and types. Knowing the module name, in particular, is important
|
|||||||
for dynamic loading, which requires the module name be known when
|
for dynamic loading, which requires the module name be known when
|
||||||
searching for symbols.
|
searching for symbols.
|
||||||
|
|
||||||
|
\begin{quote}
|
||||||
|
\scm{
|
||||||
|
hasChanged :: Module -> IO Bool
|
||||||
|
}
|
||||||
|
\end{quote}
|
||||||
|
|
||||||
|
\code{hasChanged} returns \code{True} if the module or any of its
|
||||||
|
dependencies have older object files than source files. Defaults to
|
||||||
|
\code{True} if some files couldn't be located.
|
||||||
|
|
||||||
\subsection*{Levels of Safety}
|
\subsection*{Levels of Safety}
|
||||||
|
|
||||||
The normal dynamic loader, using \code{load} on object files only,
|
The normal dynamic loader, using \code{load} on object files only,
|
||||||
@ -645,19 +712,27 @@ of type safe plugin loading is available in the \hsplugins{} paper
|
|||||||
\section{Eval.Haskell}
|
\section{Eval.Haskell}
|
||||||
|
|
||||||
\code{eval}, and its siblings, provide a mechanism to compile and run
|
\code{eval}, and its siblings, provide a mechanism to compile and run
|
||||||
Haskell code at runtime, in the form of a String. It is provided as a
|
Haskell code at runtime, in the form of a String. The general framework
|
||||||
separate package to the plugins package, and needs to be linked
|
is that the string is used to create a plugin source file, which is
|
||||||
against using \code{-package eval}. The general framework is that the
|
compiled and loaded, and type checked against its use. The resulting
|
||||||
string is used to create a plugin source file, which is compiled and
|
value is returned to the caller. It resembles a runtime metaprogramming
|
||||||
loaded, and type checked against its use. The resulting value is
|
\code{run} operator for closed code fragments.
|
||||||
returned to the caller. It resembles the \code{eval} primitives of
|
|
||||||
scripting languages.
|
|
||||||
|
|
||||||
\subsection*{Interface}
|
\subsection*{Interface}
|
||||||
|
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
|
import System.Eval.Haskell
|
||||||
|
|
||||||
eval :: Typeable a => String -> [Import] -> IO (Maybe a)
|
eval :: Typeable a => String -> [Import] -> IO (Maybe a)
|
||||||
|
|
||||||
|
eval_ :: Typeable a =>
|
||||||
|
String -- code to compile
|
||||||
|
-> [Import] -- any imports
|
||||||
|
-> [String] -- extra ghc flags
|
||||||
|
-> [FilePath] -- extra package.conf files
|
||||||
|
-> [FilePath] -- include search paths
|
||||||
|
-> IO (Either [String] (Maybe a))
|
||||||
}
|
}
|
||||||
\end{quote}
|
\end{quote}
|
||||||
|
|
||||||
@ -666,15 +741,17 @@ returns a \code{Maybe} value. \code{Nothing} means the code did not
|
|||||||
compile. \code{Just v} gives you \code{v}, the result of evaluating
|
compile. \code{Just v} gives you \code{v}, the result of evaluating
|
||||||
your code. It is interesting to note that \code{eval} has the type of
|
your code. It is interesting to note that \code{eval} has the type of
|
||||||
an interpreter. The \code{Typeable} constraint is used to type check
|
an interpreter. The \code{Typeable} constraint is used to type check
|
||||||
the evaluated code when it is loaded, using \code{dynload}. The
|
the evaluated code when it is loaded, using \code{dynload}.
|
||||||
existing \code{Data.Dynamic} library requires that only monomorphic
|
As usual, \code{eval_} is a version of \code{eval} that lets you pass
|
||||||
|
extra flags to ghc and to the dynamic loader.
|
||||||
|
|
||||||
|
The existing \code{Data.Dynamic} library requires that only monomorphic
|
||||||
values are \code{Typeable}, so in order to evaluate polymorphic
|
values are \code{Typeable}, so in order to evaluate polymorphic
|
||||||
functions you need to wrap them up using rank-N types. Some
|
functions you need to wrap them up using rank-N types. Some examples:
|
||||||
examples:
|
|
||||||
%
|
%
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
import Eval.Haskell
|
import System.Eval.Haskell
|
||||||
|
|
||||||
main = do i <- eval "1 + 6 :: Int" [] :: IO (Maybe Int)
|
main = do i <- eval "1 + 6 :: Int" [] :: IO (Maybe Int)
|
||||||
if isJust i then putStrLn (show (fromJust i)) else return ()
|
if isJust i then putStrLn (show (fromJust i)) else return ()
|
||||||
@ -695,7 +772,7 @@ type of the polymorphic function:
|
|||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
import Poly
|
import Poly
|
||||||
import Eval.Haskell
|
import System.Eval.Haskell
|
||||||
|
|
||||||
main = do m_f <- eval "Fn (\\x y -> x == y)" ["Poly"]
|
main = do m_f <- eval "Fn (\\x y -> x == y)" ["Poly"]
|
||||||
when (isJust m_f) $ do
|
when (isJust m_f) $ do
|
||||||
@ -775,7 +852,7 @@ order for Haskell to type the usage of \code{fn}:
|
|||||||
%
|
%
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
import Eval.Haskell
|
import System.Eval.Haskell
|
||||||
|
|
||||||
main = do fn <- unsafeEval "(\\(x::Int) -> (x,x))" [] :: IO (Maybe (Int -> (Int,Int)))
|
main = do fn <- unsafeEval "(\\(x::Int) -> (x,x))" [] :: IO (Maybe (Int -> (Int,Int)))
|
||||||
when (isJust fn) $ putStrLn $ show $ (fromJust fn) 7
|
when (isJust fn) $ putStrLn $ show $ (fromJust fn) 7
|
||||||
@ -854,111 +931,6 @@ Be careful if you're calling eval from a forked thread. This can
|
|||||||
introduce races between the thread and the forked process used by eval
|
introduce races between the thread and the forked process used by eval
|
||||||
to compile its code.
|
to compile its code.
|
||||||
|
|
||||||
\subsection{Eval.Printf}
|
|
||||||
|
|
||||||
It has been noted that \code{printf} format strings are the concrete syntax
|
|
||||||
of a string formatting interpreter (over 1000 lines long in libc!). By
|
|
||||||
combining runtime generation of new Haskell code, with dynamic typing,
|
|
||||||
it becomes possible to implement a typesafe \code{printf} for Haskell.
|
|
||||||
|
|
||||||
This has already been achieved in at least 3 different ways. A standard
|
|
||||||
solution (Hinze, Danvey) begins by supplying printf with the abstract
|
|
||||||
syntax of the formatting string, resolving the issue of the lack of
|
|
||||||
typing in the raw fmt string. An alternative solution (see Ian Lynagh's
|
|
||||||
Printf library) uses Template Haskell to transform a printf format
|
|
||||||
string into a new Haskell function at compile time, however this
|
|
||||||
requires that the format string is known at compile time. By using
|
|
||||||
runtime compilation we can take a similar approach, but instead generate
|
|
||||||
the print function at runtime! To make this safe, we then need to use
|
|
||||||
dynamic typing to check the newly-generated print function against its
|
|
||||||
arguments.
|
|
||||||
|
|
||||||
\subsection*{Printf Interface}
|
|
||||||
|
|
||||||
The \code{Printf} library implements a reasonable amount of the C
|
|
||||||
printf's functionality.
|
|
||||||
|
|
||||||
\begin{quote}
|
|
||||||
\scm{
|
|
||||||
printf :: String -> [Dynamic] -> IO ()
|
|
||||||
}
|
|
||||||
\end{quote}
|
|
||||||
|
|
||||||
\begin{quote}
|
|
||||||
\scm{
|
|
||||||
sprintf :: String -> [Dynamic] -> IO String
|
|
||||||
}
|
|
||||||
\end{quote}
|
|
||||||
|
|
||||||
Because the arguments to printf are of differing types, and the number
|
|
||||||
of arguments is not known at compile time, we simulate variadic
|
|
||||||
functions by using a heterogenous list of arguments. A special list
|
|
||||||
constructor, \code{!}, is provided for this. An example, noting the
|
|
||||||
syntax for constructing a heterogenous argument list:
|
|
||||||
|
|
||||||
\begin{quote}
|
|
||||||
\scm{
|
|
||||||
import Eval.Printf
|
|
||||||
|
|
||||||
main = do printf "%d\n" $ (42::Int) ! []
|
|
||||||
printf "0x%X\n" $ (42::Int) ! []
|
|
||||||
printf "%f\n" $ (42.1234 :: Double) ! []
|
|
||||||
printf "%c:%c:%c\n" $ 'a' ! 'b' ! 'c' ! []
|
|
||||||
printf "%s\n" $ "haskell" ! []
|
|
||||||
printf "%010.4f\n" $ (42.1234 :: Double) ! []
|
|
||||||
printf "%10.4s\n" $ "haskell" ! []
|
|
||||||
printf "%-10.4s\n" $ "haskell" ! []
|
|
||||||
}
|
|
||||||
\end{quote}
|
|
||||||
|
|
||||||
Compiling this program against \code{-package eval}, and running it
|
|
||||||
produces the following output:
|
|
||||||
%
|
|
||||||
\begin{quote}
|
|
||||||
\begin{verbatim}
|
|
||||||
42
|
|
||||||
0x2A
|
|
||||||
42.123400
|
|
||||||
a:b:c
|
|
||||||
haskell
|
|
||||||
00042.1234
|
|
||||||
hask
|
|
||||||
hask
|
|
||||||
\end{verbatim}
|
|
||||||
\end{quote}
|
|
||||||
|
|
||||||
If you mismatch the types specified in the format string, and the
|
|
||||||
types you apply printf to, printf will generate an exception, like so:
|
|
||||||
|
|
||||||
\begin{quote}
|
|
||||||
\scm{
|
|
||||||
import Eval.Printf
|
|
||||||
|
|
||||||
main = printf "%d\n" ("badstring" ! [])
|
|
||||||
}
|
|
||||||
\end{quote}
|
|
||||||
|
|
||||||
The above code will generate this error, indicating that you attempted
|
|
||||||
to apply a string to a function that expected an Int:
|
|
||||||
%
|
|
||||||
\begin{quote}
|
|
||||||
\begin{verbatim}
|
|
||||||
paprika$ ./a.out
|
|
||||||
Fail: Type error in dynamic application.
|
|
||||||
Can't apply function <Int -> [Char]> to argument <[Char]>
|
|
||||||
\end{verbatim}
|
|
||||||
\end{quote}
|
|
||||||
|
|
||||||
Note that this isn't the fastest printf implementation in the world. A
|
|
||||||
call to printf invokes GHC to transform the printf format string into
|
|
||||||
a Haskell code fragment, which is compiled and dynamically linked back
|
|
||||||
into the application, and then applied to its arguments. If you need
|
|
||||||
to use the same printf function against multiple times, you can save
|
|
||||||
recompilation, in which case printf runs as fast as other native code.
|
|
||||||
|
|
||||||
Additionally, it only implements the most common modifiers to the
|
|
||||||
basic conversion specifiers, and they have not all been fully tested.
|
|
||||||
|
|
||||||
\section{RTS Binding}
|
\section{RTS Binding}
|
||||||
|
|
||||||
The low level interface is the binding to GHC's Linker.c. Therefore,
|
The low level interface is the binding to GHC's Linker.c. Therefore,
|
||||||
@ -1390,7 +1362,7 @@ exported by the plugin:
|
|||||||
%
|
%
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
import Plugins
|
import System.Plugins
|
||||||
import StringProcessorAPI
|
import StringProcessorAPI
|
||||||
import System.Console.Readline
|
import System.Console.Readline
|
||||||
import System.Exit
|
import System.Exit
|
||||||
@ -1572,7 +1544,7 @@ object file and \code{.hi} file with the application.
|
|||||||
%
|
%
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
import Plugins
|
import System.Plugins
|
||||||
import API
|
import API
|
||||||
|
|
||||||
main = do
|
main = do
|
||||||
@ -1723,8 +1695,8 @@ the prompt around twice as fast as \code{hi}.
|
|||||||
|
|
||||||
\begin{quote}
|
\begin{quote}
|
||||||
\scm{
|
\scm{
|
||||||
import Eval.Haskell
|
import System.Eval.Haskell
|
||||||
import Plugins.Load
|
import System.Plugins
|
||||||
|
|
||||||
import System.Exit ( ExitCode(..), exitWith )
|
import System.Exit ( ExitCode(..), exitWith )
|
||||||
import System.IO
|
import System.IO
|
||||||
|
Loading…
x
Reference in New Issue
Block a user