hubris 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +31 -0
- data/.rvmrc +2 -0
- data/Gemfile +11 -0
- data/Haskell/Hubrify.hs +69 -0
- data/Haskell/LICENSE +22 -0
- data/Haskell/Language/Ruby/Foo.hs +20 -0
- data/Haskell/Language/Ruby/Hubris/Binding.hsc +214 -0
- data/Haskell/Language/Ruby/Hubris/GHCBuild.hs +46 -0
- data/Haskell/Language/Ruby/Hubris/Hash.hs +27 -0
- data/Haskell/Language/Ruby/Hubris/Interpolator.hs +22 -0
- data/Haskell/Language/Ruby/Hubris/LibraryBuilder.hs +181 -0
- data/Haskell/Language/Ruby/Hubris/ZCode.hs +68 -0
- data/Haskell/Language/Ruby/Hubris.hs +254 -0
- data/Haskell/Language/Ruby/Wrappers.hs +32 -0
- data/Haskell/Language/Ruby/testLib.hs +9 -0
- data/Haskell/Setup.hs +31 -0
- data/Haskell/cbits/rshim.c +46 -0
- data/Haskell/cbits/rshim.h +50 -0
- data/Haskell/hubris.cabal +53 -0
- data/INSTALL +21 -0
- data/Manifest.txt +22 -0
- data/PostInstall.txt +1 -0
- data/README.markdown +107 -0
- data/Rakefile +46 -43
- data/VERSION +1 -0
- data/doc/CommonErrors.txt +18 -0
- data/doc/CommonErrors.txt~HEAD +18 -0
- data/doc/don_feedback.txt +25 -0
- data/doc/haskell-hubris.tex +242 -0
- data/doc/new_interface.rb +74 -0
- data/doc/ruby-hubris.tex +176 -0
- data/doc/wisdom_of_ancients.txt +55 -0
- data/ext/hubris.rb +4 -0
- data/ext/stub/extconf.rb +5 -0
- data/ext/{HubrisStubLoader.c → stub/stub.c} +1 -1
- data/hubris.gemspec +31 -0
- data/lib/Makefile +181 -0
- data/lib/hubris/version.rb +3 -0
- data/lib/hubris.rb +16 -13
- data/rspec.rake +21 -0
- data/sample/Fibonacci.hs +2 -2
- data/sample/config.ru +3 -1
- data/script/ci.sh +25 -0
- data/script/console +10 -0
- data/spec/hubris_spec.rb +173 -47
- data/tasks/extconf/stub.rake +43 -0
- data/tasks/extconf.rake +13 -0
- metadata +118 -27
- data/ext/extconf.rb +0 -5
data/README.markdown
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
# Hubris
|
2
|
+
|
3
|
+
## Description
|
4
|
+
|
5
|
+
Hubris is a bridge between Ruby and Haskell, between love and bondage,
|
6
|
+
between slothful indolence and raw, blazing speed. Hubris will wash
|
7
|
+
your car, lie to your boss, and salvage your love life. If you are
|
8
|
+
very, very lucky, it might also let you get some functional goodness
|
9
|
+
into your ruby programs through the back door.
|
10
|
+
|
11
|
+
I probably don't have to say this, but patches are very much
|
12
|
+
welcome. If you have trouble installing it, tell me, and help me
|
13
|
+
improve the docs.
|
14
|
+
|
15
|
+
## Synopsis
|
16
|
+
|
17
|
+
The best docs, as ever, are in the tests, but as a quick precis, you
|
18
|
+
can use it a little like this:
|
19
|
+
|
20
|
+
require 'hubris' # best line ever
|
21
|
+
|
22
|
+
class Target
|
23
|
+
hubris :inline =>"triple::Int->Int; triple n = 3*n"
|
24
|
+
end
|
25
|
+
|
26
|
+
t = Target.new
|
27
|
+
puts t.triple(10)
|
28
|
+
=> 30
|
29
|
+
|
30
|
+
There are a few restrictions. All functions take one argument and
|
31
|
+
return one value: this shouldn't be a major problem because you can
|
32
|
+
pass arrays of arguments in if you need more. Hubris can currently
|
33
|
+
handle numbers, strings, basic types (like nil, true and false),
|
34
|
+
arrays and hashes. There will probably be some Ruby structures
|
35
|
+
(modules, regular expressions, etc) that won't ever be handled
|
36
|
+
natively unless someone can convince me it's a sensible thing to do.
|
37
|
+
|
38
|
+
Hubris will refuse to compile Haskell code that produces any
|
39
|
+
warnings. You can suppress this admittedly fairly strict behaviour by
|
40
|
+
passing the ":no_strict => true" flag, but in your heart of hearts
|
41
|
+
you'll know you've done the wrong thing.
|
42
|
+
|
43
|
+
There are also two other modes:
|
44
|
+
|
45
|
+
hubris :source => "MyCoolModule.hs"
|
46
|
+
|
47
|
+
which loads a source file on disk (in the same directory as your ruby),
|
48
|
+
and
|
49
|
+
|
50
|
+
hubris :module => "Data.ByteString", :packages => ["bytestring"]
|
51
|
+
|
52
|
+
which will load the Data.ByteString module which is installed on the
|
53
|
+
system. In this case, we also need to let the Haskell side know that
|
54
|
+
we'll be using the "bytestring" package, so we pass that too: You may
|
55
|
+
need to load extra packages with :inline and :source as well, and
|
56
|
+
that's supported.
|
57
|
+
|
58
|
+
|
59
|
+
## Requirements
|
60
|
+
|
61
|
+
* ghc 6.10 (to bootstrap 6.12) and cabal-install. This comes with the
|
62
|
+
Haskell Platform
|
63
|
+
* ruby 1.8.6 or higher (most heavily tested on 1.9.1)
|
64
|
+
* Linux or Mac. See
|
65
|
+
<http://www.shimweasel.com/2009/09/14/unprincipled-skulduggery-with-ghc-6-12-dylibs-on-mac-os-x>
|
66
|
+
and the following entry for more info on the Mac build.
|
67
|
+
* zsh or bash
|
68
|
+
* git
|
69
|
+
|
70
|
+
## Install
|
71
|
+
|
72
|
+
Better instructions for [Linux](http://wiki.github.com/mwotton/Hubris/installation-of-ghc-6121-on-ubuntu-910) and [Mac](http://wiki.github.com/mwotton/Hubris/installation-of-ghc-6121-on-mac-os-x)
|
73
|
+
|
74
|
+
## Contributors
|
75
|
+
|
76
|
+
* Mark Wotton
|
77
|
+
* James Britt
|
78
|
+
* Josh Price
|
79
|
+
* Tatsuhiro Ujihisa
|
80
|
+
|
81
|
+
## License
|
82
|
+
|
83
|
+
(The MIT License)
|
84
|
+
|
85
|
+
Copyright (c) 2009 Mark Wotton
|
86
|
+
|
87
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
88
|
+
a copy of this software and associated documentation files (the
|
89
|
+
'Software'), to deal in the Software without restriction, including
|
90
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
91
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
92
|
+
permit persons to whom the Software is furnished to do so, subject to
|
93
|
+
the following conditions:
|
94
|
+
|
95
|
+
The above copyright notice and this permission notice shall be
|
96
|
+
included in all copies or substantial portions of the Software.
|
97
|
+
|
98
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
99
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
100
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
101
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
102
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
103
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
104
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
105
|
+
|
106
|
+
|
107
|
+
[haskell_platform]: http://hackage.haskell.org/platform/
|
data/Rakefile
CHANGED
@@ -1,51 +1,54 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
|
2
|
+
|
3
|
+
require 'bundler'
|
4
|
+
Bundler::GemHelper.install_tasks
|
5
|
+
require 'rake'
|
4
6
|
require 'fileutils'
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
# self.developer 'Mark Wotton', 'mwotton@gmail.com'
|
15
|
-
# self.rubyforge_name = "hubris"
|
16
|
-
# self.summary = 'tool to help build .so files from haskell code for use in Ruby via dl'
|
17
|
-
# self.post_install_message = 'PostInstall.txt'
|
18
|
-
# self.readme_file = "README.markdown"
|
19
|
-
# self.history_file = "HISTORY.markdown"
|
20
|
-
#end
|
21
|
-
|
22
|
-
#require 'newgem/tasks'
|
23
|
-
# Dir['tasks/**/*.rake'].each { |t| load t }
|
24
|
-
|
25
|
-
|
26
|
-
#file "lib/RubyMap.hs" => ["lib/RubyMap.chs"] do
|
27
|
-
# str = "c2hs -v --cppopts='-I" + Hubris::RubyHeader + "' --cpp=gcc --cppopts=-E --cppopts=-xc lib/RubyMap.chs"
|
28
|
-
# # print str
|
29
|
-
# system(str)
|
30
|
-
#end
|
31
|
-
|
32
|
-
require 'spec'
|
33
|
-
require 'spec/rake/spectask'
|
34
|
-
|
35
|
-
# desc "Run the specs under spec/"
|
36
|
-
# all_examples = Spec::Rake::SpecTask.new do |t|
|
37
|
-
# t.spec_opts = ['--options', "spec/spec.opts"]
|
38
|
-
# t.spec_files = FileList['spec/*.rb']
|
7
|
+
|
8
|
+
# require 'rake-compiler'
|
9
|
+
require 'rake/extensiontask'
|
10
|
+
# require 'rake/extensiontesttask'
|
11
|
+
|
12
|
+
|
13
|
+
# task "build:native" => [:no_extconf, :native, :build] do
|
14
|
+
# file = "pkg/stub-#{`cat VERSION`.chomp}.gem"
|
15
|
+
# mv file, "#{file.ext}-i686-linux.gem"
|
39
16
|
# end
|
40
17
|
|
41
|
-
|
18
|
+
|
19
|
+
Rake::ExtensionTask.new('stub')
|
20
|
+
|
21
|
+
# intended to be called by the gem builder
|
22
|
+
task :haskell_compile => [:compile] do
|
23
|
+
ghc_version='/usr/local/bin/ghc' # FIXME, should be able to pick
|
24
|
+
# this out from somewhere
|
25
|
+
# write the Includes file
|
26
|
+
pwd =`pwd`.strip
|
27
|
+
arch_headers = "#{RbConfig::CONFIG['rubyhdrdir']}/#{RbConfig::CONFIG['arch']}"
|
28
|
+
lib_dir = RbConfig::CONFIG['libdir']
|
29
|
+
headers = RbConfig::CONFIG['rubyhdrdir']
|
30
|
+
File.open("#{pwd}/Haskell/Language/Ruby/Hubris/Includes.hs","w") do |file|
|
31
|
+
file.write "module Language.Ruby.Hubris.Includes where
|
32
|
+
extraIncludeDirs = [\"#{headers}\", \"#{arch_headers}\"]"
|
33
|
+
end
|
34
|
+
# command="cd Haskell; cabal update; cabal install
|
35
|
+
# --extra-include-dirs=#{RbConfig::CONFIG['rubyhdrdir']}
|
36
|
+
# --extra-include-dirs=#{RbConfig::CONFIG['rubyhdrdir']}/#{RbConfig::CONFIG['arch']} --extra-lib-dirs=#{RbConfig::CONFIG['libdir']} --user --enable-shared --with-ghc=#{ghc_version}"
|
37
|
+
command="cd Haskell; cabal install --extra-include-dirs=#{arch_headers} --extra-include-dirs=#{headers} --extra-lib-dirs=#{lib_dir} --user --enable-shared --with-ghc=#{ghc_version}"
|
38
|
+
result=%x{#{command}}
|
39
|
+
raise "ERROR: ran #{command}, got #{result}" unless $?.success?
|
40
|
+
end
|
41
|
+
|
42
|
+
task :no_extconf do
|
43
|
+
$gemspec.extensions = []
|
44
|
+
end
|
45
|
+
|
46
|
+
task :default => :haskell_compile
|
42
47
|
|
43
48
|
task :clean do
|
44
49
|
FileList[File.expand_path("~/.hubris_cache/*"),
|
45
|
-
'lib*.so', 'lib/*.o'
|
46
|
-
|
47
|
-
File.delete(f)
|
48
|
-
rescue
|
49
|
-
end
|
50
|
+
'lib*.so', 'lib/*.o' ].each do |f|
|
51
|
+
File.delete(f) rescue nil
|
50
52
|
end
|
51
53
|
end
|
54
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.3
|
@@ -0,0 +1,18 @@
|
|
1
|
+
this is a quick guide to diagnosing what could be wrong.
|
2
|
+
|
3
|
+
This:
|
4
|
+
"""
|
5
|
+
/var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/working_source.hs:7:7:
|
6
|
+
Could not find module `Foreign':
|
7
|
+
Perhaps you haven't installed the "dyn" libraries for package
|
8
|
+
`base'?
|
9
|
+
"""
|
10
|
+
|
11
|
+
indicates that GHC HEAD was not installed correctly. Run something
|
12
|
+
like "find /usr/local -iname '*dyn_hi'" to check that the GHC you are
|
13
|
+
using has all its dynamic library header files installed. If it
|
14
|
+
doesn't, you probably didn't build GHC the right way: check
|
15
|
+
http://www.shimweasel.com/2009/09/16/another-awful-hack-to-ghc-6-11
|
16
|
+
and
|
17
|
+
http://www.shimweasel.com/2009/09/14/unprincipled-skulduggery-with-ghc-6-12-dylibs-on-mac-os-x
|
18
|
+
for more info.
|
@@ -0,0 +1,18 @@
|
|
1
|
+
this is a quick guide to diagnosing what could be wrong.
|
2
|
+
|
3
|
+
This:
|
4
|
+
"""
|
5
|
+
/var/folders/Dz/Dz5WpFSZGUaFLA8jp8kT5E+++TM/-Tmp-/working_source.hs:7:7:
|
6
|
+
Could not find module `Foreign':
|
7
|
+
Perhaps you haven't installed the "dyn" libraries for package
|
8
|
+
`base'?
|
9
|
+
"""
|
10
|
+
|
11
|
+
indicates that GHC HEAD was not installed correctly. Run something
|
12
|
+
like "find /usr/local -iname '*dyn_hi'" to check that the GHC you are
|
13
|
+
using has all its dynamic library header files installed. If it
|
14
|
+
doesn't, you probably didn't build GHC the right way: check
|
15
|
+
http://www.shimweasel.com/2009/09/16/another-awful-hack-to-ghc-6-11
|
16
|
+
and
|
17
|
+
http://www.shimweasel.com/2009/09/14/unprincipled-skulduggery-with-ghc-6-12-dylibs-on-mac-os-x
|
18
|
+
for more info.
|
@@ -0,0 +1,25 @@
|
|
1
|
+
------------------------------------------------------------------------
|
2
|
+
|
3
|
+
Hubris
|
4
|
+
Ruby calling Haskell
|
5
|
+
- inline, dynamically compiled Haskell
|
6
|
+
- call precompiled stuff
|
7
|
+
|
8
|
+
Dream
|
9
|
+
Haskell to code would be Cabal package.
|
10
|
+
Ruby would be application.
|
11
|
+
|
12
|
+
FFI preprocessor:
|
13
|
+
Does Haskell foreign export
|
14
|
+
Generates marshalling boilerplate
|
15
|
+
|
16
|
+
Haskell code in Ruby
|
17
|
+
|
18
|
+
------------------------------------------------------------------------
|
19
|
+
|
20
|
+
Grammar, parsing, type-driven.
|
21
|
+
|
22
|
+
Killer demo:
|
23
|
+
- Rails site,
|
24
|
+
- super clever/ fast/ multicore Haskell code
|
25
|
+
|
@@ -0,0 +1,242 @@
|
|
1
|
+
% Local Variables:
|
2
|
+
% compile-command: "/opt/local/bin/pdflatex fp-syd.tex && open fp-syd.pdf"
|
3
|
+
% End:
|
4
|
+
|
5
|
+
\documentclass{beamer}
|
6
|
+
\usepackage{listings}
|
7
|
+
\usepackage{beamerthemesplit}
|
8
|
+
|
9
|
+
\title{Hubris}
|
10
|
+
\subtitle{A Trojan Horse for Haskell}
|
11
|
+
\author{Mark Wotton \textless mwotton@shimweasel.com\textgreater}
|
12
|
+
\date{\today}
|
13
|
+
|
14
|
+
\begin{document}
|
15
|
+
\lstset{language=Haskell}
|
16
|
+
\section{Two cultures}
|
17
|
+
\frame{\titlepage}
|
18
|
+
|
19
|
+
% \subsection
|
20
|
+
\begin{frame}
|
21
|
+
\frametitle{I \ding{170} Ruby}
|
22
|
+
\begin{itemize}
|
23
|
+
\item concise and flexible
|
24
|
+
\item Big web community, many libraries
|
25
|
+
\item Fun
|
26
|
+
\end{itemize}
|
27
|
+
\end{frame}
|
28
|
+
|
29
|
+
\begin{frame}
|
30
|
+
\frametitle{I \ding{170} Haskell}
|
31
|
+
\begin{itemize}
|
32
|
+
\item<1-> Fast (optimised native code, multicore, etc)
|
33
|
+
\item<2-> Expressive - type systems don't have to suck.
|
34
|
+
\item<3-> Provably safe at compile time
|
35
|
+
\end{itemize}
|
36
|
+
\end{frame}
|
37
|
+
|
38
|
+
|
39
|
+
\begin{frame}
|
40
|
+
\frametitle{So, why do I care?}
|
41
|
+
\begin{itemize}
|
42
|
+
\item<1-> Make it easier to slap up a quick web interface to cool
|
43
|
+
haskell code.
|
44
|
+
\item<2-> Get more web-savvy devs into the Haskell community
|
45
|
+
\end{itemize}
|
46
|
+
\end{frame}
|
47
|
+
|
48
|
+
\subsection{problems with Haskell}
|
49
|
+
\begin{frame}
|
50
|
+
\frametitle{heresies}
|
51
|
+
\setlength\parskip{0.1in}
|
52
|
+
|
53
|
+
Haskell web frameworks are still niche.
|
54
|
+
|
55
|
+
It's an engineering problem, and pretty boring.
|
56
|
+
|
57
|
+
Haskell devs aren't exactly hard to find, but they don't seem to be
|
58
|
+
web guys.
|
59
|
+
|
60
|
+
\end{frame}
|
61
|
+
|
62
|
+
\subsection{problems with Ruby}
|
63
|
+
\begin{frame}
|
64
|
+
\frametitle{lies, damn lies, benchmarks}
|
65
|
+
\center{JRuby vs GHC}
|
66
|
+
\begin{tabular}{l l l l}
|
67
|
+
Program & Time &Memory & Source Size\\ \hline
|
68
|
+
reverse-complement &5 &1 &1/4\\
|
69
|
+
regex-dna &7 &3 &1/5\\
|
70
|
+
binary-trees &8 &7 &1 \\
|
71
|
+
k-nucleotide &10 &1 &1/7 \\
|
72
|
+
pidigits &18 &18 &2 \\
|
73
|
+
n-body &26 &53 &1 \\
|
74
|
+
chameneos-redux &30 &24 &1 \\
|
75
|
+
fasta &31 &142 &1 \\
|
76
|
+
fannkuch &45 &22 &1/4 \\
|
77
|
+
spectral-norm &227 &56 &1/3 \\
|
78
|
+
mandelbrot &319 &3 &1/2\\
|
79
|
+
\end{tabular}
|
80
|
+
\end{frame}
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
\section{Hubris}
|
85
|
+
\begin{frame}
|
86
|
+
\frametitle{Peanut butter, meet chocolate}
|
87
|
+
Ruby has a heap of web frameworks, convenience libraries, well-tested
|
88
|
+
integration with javascript + CSS.
|
89
|
+
|
90
|
+
\setlength\parskip{0.25in}
|
91
|
+
|
92
|
+
Haskell is smoking fast with rock solid type safety but a relatively tiny
|
93
|
+
community
|
94
|
+
|
95
|
+
Hubris is my bridge between the two
|
96
|
+
\end{frame}
|
97
|
+
|
98
|
+
\begin{frame}
|
99
|
+
\frametitle{Again, WHY?}
|
100
|
+
There are seventy bazillion ways of talking between languages.
|
101
|
+
\begin{itemize}
|
102
|
+
\item Web services
|
103
|
+
\item text over pipes
|
104
|
+
\item Protocol buffers, Thrift
|
105
|
+
\item COM, HOC, etc (binary interfaces)
|
106
|
+
\end{itemize}
|
107
|
+
|
108
|
+
Reasons to do it this way:
|
109
|
+
\begin{itemize}
|
110
|
+
\item it's fun (for me, anyway)
|
111
|
+
\item low fuss - no explicit mapping of function interfaces
|
112
|
+
\item easy to explore a library
|
113
|
+
\item few dependencies
|
114
|
+
\end{itemize}
|
115
|
+
\end{frame}
|
116
|
+
|
117
|
+
\lstset{language=Haskell}
|
118
|
+
\subsection{Haskell example}
|
119
|
+
\begin{frame}[fragile]
|
120
|
+
\frametitle{lazy, statically typed, and pure}
|
121
|
+
Collatz.hs
|
122
|
+
\begin{lstlisting}
|
123
|
+
module Collatz where
|
124
|
+
clMax lim = maximumBy (comparing snd) (assocs arr)
|
125
|
+
where arr = listArray (1,lim)
|
126
|
+
(0:(map depth [2..]))
|
127
|
+
step x = if even x
|
128
|
+
then div x 2
|
129
|
+
else 3 * x + 1
|
130
|
+
depth x = 1 + if n <= lim
|
131
|
+
then arr ! n
|
132
|
+
else depth n
|
133
|
+
where n = step x
|
134
|
+
\end{lstlisting}
|
135
|
+
Hubrify Collatz collatz.dylib Collatz.hs
|
136
|
+
|
137
|
+
\end{frame}
|
138
|
+
|
139
|
+
\subsection{wrap it in Ruby}
|
140
|
+
\begin{frame}[fragile]
|
141
|
+
\frametitle{actually using it}
|
142
|
+
\lstset{language=Ruby}
|
143
|
+
\begin{lstlisting}
|
144
|
+
require Hubris # my favourite line
|
145
|
+
module Collatz
|
146
|
+
hubris :module => 'collatz'
|
147
|
+
end
|
148
|
+
puts Collatz.clMax(1000000)
|
149
|
+
>> 837799
|
150
|
+
\end{lstlisting}
|
151
|
+
\end{frame}
|
152
|
+
|
153
|
+
\subsection{beneath the covers}
|
154
|
+
\begin{frame}[fragile]
|
155
|
+
\frametitle{on the Haskell side}
|
156
|
+
Hubrify loads the given source files and attempts to find the
|
157
|
+
passed-in module using the GHC API.
|
158
|
+
\lstset{language=Haskell}
|
159
|
+
\begin{lstlisting}
|
160
|
+
data RValue = T_NIL | T_FIXNUM Int | ...
|
161
|
+
type Value = CULong -- imported from Ruby
|
162
|
+
class Haskellable a where
|
163
|
+
toHaskell :: RValue -> Maybe a
|
164
|
+
|
165
|
+
class Rubyable a where
|
166
|
+
toRuby :: a -> RValue
|
167
|
+
|
168
|
+
wrap :: (Haskellable a, Rubyable b) ->
|
169
|
+
(a -> b) -> (Value -> Value)
|
170
|
+
\end{lstlisting}
|
171
|
+
\end{frame}
|
172
|
+
|
173
|
+
\begin{frame}[fragile]
|
174
|
+
\frametitle{blah}
|
175
|
+
For each top level definition f, we then typecheck.
|
176
|
+
\begin{lstlisting}
|
177
|
+
(wrap f) T_NIL == T_NIL
|
178
|
+
\end{lstlisting}
|
179
|
+
if it fits, it's exportable.
|
180
|
+
|
181
|
+
create a Haskell file exporting each valid function, add a top level
|
182
|
+
manifest, and compile into a self-contained dylib.
|
183
|
+
|
184
|
+
\end{frame}
|
185
|
+
|
186
|
+
\begin{frame}
|
187
|
+
\frametitle{On the ruby side}
|
188
|
+
No Haskell-specific information at all.
|
189
|
+
|
190
|
+
We have a manifest function we need to call to find the names of
|
191
|
+
wrapped functions. (Also gives us a convenient point to initialise
|
192
|
+
the Haskell runtime)
|
193
|
+
|
194
|
+
attach all passed functions as methods on the surrounding module
|
195
|
+
|
196
|
+
\end{frame}
|
197
|
+
|
198
|
+
|
199
|
+
% \frametitle{Predictive}
|
200
|
+
\section{Making it less sucky}
|
201
|
+
\begin{frame}
|
202
|
+
\setlength\parskip{0.1in}
|
203
|
+
\frametitle{What's been done}
|
204
|
+
caching of Haskell binaries
|
205
|
+
|
206
|
+
transparent mapping - no boilerplate
|
207
|
+
|
208
|
+
separation of concerns - no compiler on server
|
209
|
+
|
210
|
+
ported to GHC
|
211
|
+
\end{frame}
|
212
|
+
|
213
|
+
\begin{frame}
|
214
|
+
\frametitle{Still to do}
|
215
|
+
one-way bridge, no callbacks to Ruby
|
216
|
+
|
217
|
+
autoconf support to find ruby libs and includes
|
218
|
+
|
219
|
+
more serious hammering to find bugs - is it legitimate to dlopen
|
220
|
+
multiple haskell dylibs?
|
221
|
+
|
222
|
+
performance testing
|
223
|
+
|
224
|
+
\end{frame}
|
225
|
+
|
226
|
+
|
227
|
+
\begin{frame}
|
228
|
+
\frametitle{Try it out!}
|
229
|
+
install GHC 6.12 release candidate
|
230
|
+
|
231
|
+
git clone git://github.com/mwotton/HaskellHubris.git
|
232
|
+
|
233
|
+
git clone git://github.com/mwotton/Hubris.git
|
234
|
+
|
235
|
+
follow the README
|
236
|
+
|
237
|
+
tell me what's missing
|
238
|
+
|
239
|
+
patches very much welcome (thanks to Josh Price, James Britt and Tatsuhiro Ujihisa)
|
240
|
+
\end{frame}
|
241
|
+
|
242
|
+
\end{document}
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# IDEAS for new interface
|
2
|
+
|
3
|
+
# option 1 (implicit method name from haskell function)
|
4
|
+
class MyClass
|
5
|
+
include Hubris
|
6
|
+
def_haskell(code)
|
7
|
+
end
|
8
|
+
|
9
|
+
# option 2 (explicit method name)
|
10
|
+
class MyClass
|
11
|
+
def_haskell(method_name,code)
|
12
|
+
end
|
13
|
+
|
14
|
+
# option 3 ()
|
15
|
+
class Module
|
16
|
+
include Hubris
|
17
|
+
end
|
18
|
+
|
19
|
+
class MyClass
|
20
|
+
inline_haskell "haskell function"
|
21
|
+
end
|
22
|
+
|
23
|
+
# option 4 (more humourous)
|
24
|
+
class Module
|
25
|
+
include Hubris
|
26
|
+
end
|
27
|
+
|
28
|
+
class MyClass
|
29
|
+
hubris "haskell function"
|
30
|
+
end
|
31
|
+
|
32
|
+
#-----------------------------------------
|
33
|
+
# include at the module or package level
|
34
|
+
#=========================================
|
35
|
+
# does importing as_class make sense? no, just include the module
|
36
|
+
# when interpreting Haskell module names replace . with ::
|
37
|
+
|
38
|
+
# importing std module as a ruby module/class
|
39
|
+
hubris :package => "containers", :module => "Data.Map", :as => "Data::Map"
|
40
|
+
|
41
|
+
# importing your own module (defaults to module)
|
42
|
+
hubris :package => "mypackage", :module => "MyModule" [, :as => "MyModule"]
|
43
|
+
|
44
|
+
# implicit package handling (haskell file in my directory)
|
45
|
+
hubris :module => "haskell/shit/MyModule"
|
46
|
+
|
47
|
+
# simpler to implement option, allows more flexibility in Ruby land
|
48
|
+
module MyRubyModule
|
49
|
+
# :packages is optional, just brings in external packages.
|
50
|
+
hubris :module => "Data.Map", :packages => ["containers","foo"]
|
51
|
+
# or
|
52
|
+
hubris :source => "MyHaskellCode.hs" # , :packages => [ ... ]
|
53
|
+
# or
|
54
|
+
hubris :inline => "foo x = x * 2"
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# alternative
|
59
|
+
|
60
|
+
Hubris.import :package => "containers", :module => "Data.Map"
|
61
|
+
|
62
|
+
module MyRubyModule
|
63
|
+
include Hubris::Data::Map
|
64
|
+
end
|
65
|
+
|
66
|
+
# alternative2
|
67
|
+
|
68
|
+
module MyRubyModule
|
69
|
+
hubris :package => "containers", :module => "Data.Map"
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
6:34:58 PM Josh Price: class Module; def hubris; self.class_eval { def self.h;"hubrified!";end };end;end
|
74
|
+
6:35:10 PM Josh Price: class B;hubris;end
|