diff --git a/Hubrify.hs b/Hubrify.hs
new file mode 100644
--- /dev/null
+++ b/Hubrify.hs
@@ -0,0 +1,7 @@
+module Main where
+import Language.Ruby.Hubris.LibraryBuilder
+import System
+
+main = do
+   (mod:extra_src) <- getArgs
+   generateLib extra_src mod >>= print
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+(The MIT License)
+
+Copyright (c) 2009 Mark Wotton
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+'Software'), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+            permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Language/Ruby/Hubris.hs b/Language/Ruby/Hubris.hs
new file mode 100644
--- /dev/null
+++ b/Language/Ruby/Hubris.hs
@@ -0,0 +1,104 @@
+{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-} 
+module Language.Ruby.Hubris where
+
+import Data.Word
+import Data.Map as Map
+-- import Language.Ruby.Hubris.Binding
+import System.IO.Unsafe (unsafePerformIO)
+import Foreign.C.Types
+import Language.Ruby.Hubris.Binding
+import Control.Monad (forM)
+-- type Value = CULong
+
+
+
+wrap :: (Haskellable a, Rubyable b) => (a->b) -> (Value -> Value)
+wrap func ar = fromRVal $ case (toHaskell $ fromVal ar) of
+                Just a ->  toRuby $ func a
+                Nothing -> T_NIL
+
+-- fromVal :: Value -> RValue
+-- fromRVal ::RValue -> Value
+-- fromVal = undefined
+-- fromRVal = undefined
+
+class Haskellable a where
+  toHaskell :: RValue -> Maybe a
+
+class Rubyable a where
+  toRuby :: a -> RValue
+
+instance Haskellable Int where
+  toHaskell (T_FIXNUM i) = Just i
+  toHaskell _ = Nothing
+
+instance Rubyable Int where
+  toRuby i = T_FIXNUM i
+
+instance Haskellable Integer where
+  toHaskell (T_BIGNUM i) = Just i
+  toHaskell _ = Nothing
+
+instance Rubyable Integer where
+  toRuby i = T_BIGNUM i
+
+instance Haskellable Bool where
+  toHaskell T_TRUE  = Just True
+  toHaskell T_FALSE = Just False
+  toHaskell _       = Nothing
+
+instance Rubyable Bool where
+  toRuby True = T_TRUE
+  toRuby False = T_FALSE
+
+instance Rubyable Double where
+  toRuby d = T_FLOAT d
+
+instance Haskellable Double where
+  toHaskell (T_FLOAT f)  = Just f
+  toHaskell (T_FIXNUM i) = Just $ fromIntegral i -- does this make sense?
+  toHaskell _ = Nothing 
+
+instance Haskellable String where
+  toHaskell (T_STRING s) = Just s
+  toHaskell _ = Nothing
+instance Rubyable String where
+  toRuby s = (T_STRING s)
+
+
+-- This is a tricky case.
+-- The ruby FFI wants us to pass a C callback which it can apply to each key-value pair
+-- of the hash, so Haskell cannot be fully in control of the process - this makes building
+-- up a Data.Map object in the natural way a bit tricky.
+
+-- current thoughts:
+--  1. write a direct binding to the ruby API, include a C level function for getting the keys.
+--     just eat the cost of transferring through a keys call + looping over the elements.
+--     One big benefit - while iteration is expensive, using it as a hash table should be cheap
+--     (although probably needs to stay in the IO monad, which is less convenient.)
+--
+--  2. write a binding to the Judy library that creates a Judy object directly. If we can convince
+--     HsJudy to accept that, then we're golden - we still have to copy over, but keys operations
+--     should be cheap (and hopefully lazy, but test to make sure).
+--
+-- These are of course not mutually exclusive.
+--
+-- The first should probably be a part of the base package. The second needs access to internals,
+-- but should probably be an optional package. This means that in Hubris.Internals, we should expose
+
+-- > rb_foreach :: Value {- HASH -} -> (CFunction ((Key,Value,a) -> a)) -> a -> IO a 
+-- 
+-- 
+
+-- instance Haskellable (Map.Map a b ) where 
+--   toHaskell (T_HASH s) = unsafePerformIO $ 
+--                          get_each
+                         
+--   toHaskell _ = Nothing
+
+instance (Rubyable a, Rubyable b) => Rubyable (Map.Map a b) where
+  toRuby s = unsafePerformIO $ 
+             do hash <- rb_hash_new
+                forM (toList s)
+                     (\(k,v) -> rb_hash_aset hash (fromRVal $ toRuby k) (fromRVal $ toRuby v))
+                return $ T_HASH hash
diff --git a/Language/Ruby/Hubris/Binding.chs b/Language/Ruby/Hubris/Binding.chs
new file mode 100644
--- /dev/null
+++ b/Language/Ruby/Hubris/Binding.chs
@@ -0,0 +1,156 @@
+{-# LANGUAGE ForeignFunctionInterface, TypeSynonymInstances #-}
+
+{- TODO
+
+Rip the array trnaslation stuff out to a utility function. same with hashes.
+
+install as package. This is a bit iffy for GHC/JHC compatibility - if we commit to
+Cabal, that leaves JHC out in the cold.
+
+perhaps need cabal file for ghc and equivalent for jhc.
+
+also: do we want to support different versions of ruby? for the moment, you just get
+whichever ruby.h is first in the search place.
+
+-}
+
+
+module Language.Ruby.Hubris.Binding where
+#include "rshim.h"
+#include <ruby.h>
+
+-- import Control.Applicative
+-- import Control.Monad
+import Data.Word
+-- import Foreign.Ptr
+import Foreign.C.Types	
+import Foreign.C.String
+-- import Foreign.Storable
+import System.IO.Unsafe (unsafePerformIO)
+
+-- import Foreign.Marshal.Array
+
+{# context lib="rshim" #}
+
+{# enum RubyType {} deriving (Eq, Show) #} -- maybe Ord?
+#if RUBY_VERSION_CODE <= 187
+data RubyConsts = RUBY_Qfalse 
+                | RUBY_Qtrue  
+                | RUBY_Qnil   
+                | RUBY_Qundef 
+
+instance Enum RubyConsts where
+  fromEnum RUBY_Qfalse = 0
+  fromEnum RUBY_Qtrue = 2
+  fromEnum RUBY_Qnil = 4
+  fromEnum RUBY_Qundef = 6
+
+  toEnum 0 = RUBY_Qfalse
+  toEnum 2 = RUBY_Qtrue
+  toEnum 4 = RUBY_Qnil
+  toEnum 6 = RUBY_Qundef
+#else
+{# enum ruby_special_consts as RubyConsts {} deriving (Eq,Show) #}
+#endif
+type Value = CULong -- FIXME, we'd prefer to import the type VALUE directly
+foreign import ccall unsafe "ruby.h rb_str2cstr"    rb_str2cstr    :: Value -> CInt -> CString
+foreign import ccall unsafe "ruby.h rb_str_new2"    rb_str_new2    :: CString -> Value
+foreign import ccall unsafe "ruby.h rb_ary_new2"    rb_ary_new2    :: CLong -> IO Value
+foreign import ccall unsafe "ruby.h rb_ary_push"    rb_ary_push    :: Value -> Value -> IO ()
+foreign import ccall unsafe "ruby.h rb_float_new"   rb_float_new   :: Double -> Value
+foreign import ccall unsafe "ruby.h rb_big2str"     rb_big2str     :: Value -> Int -> Value
+foreign import ccall unsafe "ruby.h rb_str_to_inum" rb_str_to_inum :: Value -> Int -> Int -> Value
+foreign import ccall unsafe "ruby.h ruby_init" ruby_init :: IO ()
+
+-- we're being a bit filthy here - the interface is all macros, so we're digging in to find what it actually is
+foreign import ccall unsafe "rshim.h rb_ary_len" rb_ary_len :: Value -> CUInt
+foreign import ccall unsafe "rshim.h rtype"      rtype      :: Value -> Int
+foreign import ccall unsafe "rshim.h int2fix"    int2fix    :: Int -> Value
+foreign import ccall unsafe "rshim.h fix2int"    fix2int    :: Value -> Int
+foreign import ccall unsafe "rshim.h num2dbl"    num2dbl    :: Value -> Double  -- technically CDoubles, but jhc promises they're the same
+foreign import ccall unsafe "rshim.h keys"       rb_keys    :: Value -> IO Value
+
+-- this line crashes jhc
+foreign import ccall unsafe "intern.h rb_ary_entry" rb_ary_entry :: Value -> CLong -> IO Value
+
+foreign import ccall safe "ruby.h rb_raise" rb_raise :: Value -> CString -> IO ()
+foreign import ccall unsafe "ruby.h rb_eval_string" rb_eval_string :: CString -> Value
+
+foreign import ccall unsafe "intern.h rb_hash_aset" rb_hash_aset :: Value -> Value -> Value -> IO ()
+foreign import ccall unsafe "intern.h rb_hash_new" rb_hash_new :: IO Value
+foreign import ccall unsafe "intern.h rb_hash_aref" rb_hash_aref :: Value -> Value -> IO Value
+
+
+
+data RValue = T_NIL  
+            | T_FLOAT Double
+            | T_STRING String
+
+            -- List is non-ideal. Switch to uvector? Array? There's always going
+            -- to be an extraction step to pull the RValues out.
+            | T_ARRAY [RValue]
+            | T_FIXNUM Int 
+            | T_HASH  Value --  Int -- definitely FIXME - native ruby hashes, or going to transliterate into Data.Map?
+            | T_BIGNUM Integer    
+
+            -- technically, these are mapping over the types True and False,
+            -- I'm going to treat them as values, though.
+            | T_TRUE  
+            | T_FALSE      
+
+            | T_SYMBOL Word -- interned string
+              deriving (Eq, Show)
+-- These are the other basic Ruby structures that we're not handling yet.
+--          | T_REGEXP     
+--          | T_FILE
+--          | T_STRUCT     
+--          | T_DATA       
+--          | T_OBJECT 
+--          | T_CLASS      
+--          | T_MODULE     
+-- leaky as hell
+fromRVal :: RValue -> Value
+fromRVal r = case r of
+           T_FLOAT d -> rb_float_new d
+           -- need to take the address of the cstr, just cast it to a value
+           -- sadly no bytestrings yet - unpack it to a list. yeah it's ugly.
+           T_STRING str -> rb_str_new2 $ unsafePerformIO $ newCAString str
+           T_FIXNUM i -> int2fix i
+
+           -- so this is just bizarre - there's no boolean type. True and False have their own types
+           -- as well as their own values.
+           T_TRUE     -> fromIntegral $ fromEnum RUBY_Qtrue
+           T_FALSE    -> fromIntegral $ fromEnum RUBY_Qfalse
+           T_NIL      -> fromIntegral $ fromEnum RUBY_Qnil
+           T_HASH h   -> h
+           T_ARRAY l  -> unsafePerformIO $ do
+                           ary <- rb_ary_new2 $ fromIntegral $ length l
+                           mapM_ (rb_ary_push ary . fromRVal) l
+                           return ary
+           T_BIGNUM b -> rb_str_to_inum (rb_str_new2 $ unsafePerformIO $ newCAString $ show b) 10 1
+           _          -> error "sorry, haven't implemented that yet."
+
+fromVal :: Value -> RValue
+fromVal v = case target of
+               RT_NIL -> T_NIL
+               RT_FIXNUM -> T_FIXNUM $ fix2int v
+               RT_STRING -> T_STRING $ unsafePerformIO $ peekCString $ rb_str2cstr v 0
+               RT_FLOAT ->  T_FLOAT $ num2dbl v
+               RT_BIGNUM -> T_BIGNUM $ read  $ unsafePerformIO $ peekCString $ rb_str2cstr (rb_big2str v 10) 0
+               RT_TRUE -> T_TRUE
+               RT_FALSE -> T_FALSE
+               RT_HASH  -> T_HASH v
+               RT_ARRAY -> T_ARRAY $ map fromVal $ unsafePerformIO  $ mapM (rb_ary_entry v . fromIntegral) [0..(rb_ary_len v) - 1]
+
+               _ -> error "didn't work" -- (show target)
+      where target :: RubyType
+            target = toEnum $ rtype v
+
+
+unsafeThrow :: String -> a
+unsafeThrow s = unsafePerformIO $ throwException s >> undefined
+throwException :: String -> IO Value
+throwException s = do he <- newCAString "HaskellError"
+                      err <- newCAString s
+                      rb_raise (rb_eval_string he) err
+                      error "shouldn't ever get here"
diff --git a/Language/Ruby/Hubris/GHCBuild.hs b/Language/Ruby/Hubris/GHCBuild.hs
new file mode 100644
--- /dev/null
+++ b/Language/Ruby/Hubris/GHCBuild.hs
@@ -0,0 +1,51 @@
+module Language.Ruby.Hubris.GHCBuild (ghcBuild, defaultGHCOptions, GHCOptions(..)) where
+import Config
+import Debug.Trace
+import DynFlags
+import GHC
+import GHC.Paths
+import Outputable
+import StringBuffer
+import System.Time
+import Control.Monad(forM_)
+
+newtype GHCOptions = GHCOptions { strict :: Bool }
+defaultGHCOptions = GHCOptions { strict = True }
+type Filename = String
+
+
+sh = showSDoc . ppr
+-- this one's a bit tricky: we _could_ use the GHC api, but i don't care too much.
+-- let's keep it simple.
+--
+-- ok, new plan: handling it the filthy way is awful.
+ghcBuild :: Filename -> String -> String -> [Filename] -> GHCOptions -> IO Bool
+ghcBuild libFile immediateSource modName extra_sources options =
+       do srcBuffer <- stringToStringBuffer immediateSource
+          putStrLn ("modname is " ++ modName)
+          writeFile "/tmp/foo.hs" immediateSource
+          time <- getClockTime -- i suppose we've just made it now...
+          defaultErrorHandler defaultDynFlags $ do
+          res <- runGhc (Just libdir) $ do
+            dflags <- getSessionDynFlags
+
+            (newflags, leftovers, warnings) <- GHC.parseDynamicFlags dflags 
+                                               $ map noLoc $ (words $ "-shared -o " ++ libFile ++ " -optl-Wl,-rpath," ++ libdir 
+                                                      ++ " /Users/mwotton/projects/Hubris/lib/rshim.o -lHSrts-ghc" ++ Config.cProjectVersion)
+            trace ("left: " ++ sh leftovers) $ trace (sh warnings) $ setSessionDynFlags newflags
+            
+            forM_ ("/tmp/foo.hs":extra_sources)  (\file -> guessTarget file Nothing >>= addTarget) 
+
+            load LoadAllTargets
+            -- do something with c_sources and extra_sources
+--             setTargets [Target { targetContents = Just ( srcBuffer, time ), 
+--                                  targetAllowObjCode = True,
+--                                  targetId = TargetModule $ mkModuleName modName
+--                                } ]
+
+                              -- } ]
+       
+          return (case res of
+                  Succeeded -> True
+                  _ -> False)
+
diff --git a/Language/Ruby/Hubris/LibraryBuilder.hs b/Language/Ruby/Hubris/LibraryBuilder.hs
new file mode 100644
--- /dev/null
+++ b/Language/Ruby/Hubris/LibraryBuilder.hs
@@ -0,0 +1,80 @@
+{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
+module Language.Ruby.Hubris.LibraryBuilder (generateLib) where
+import Language.Ruby.Hubris.ZCode (zenc, zdec)
+import Language.Ruby.Hubris
+import Language.Haskell.Interpreter
+import Language.Haskell.Meta.QQ.HsHere
+import Language.Ruby.Hubris.GHCBuild
+
+import Debug.Trace
+import Control.Monad
+import Control.Monad.Error.Class
+
+import GHC(parseStaticFlags, noLoc)
+type Filename = String
+
+generateLib :: [Filename] -> ModuleName -> IO (Maybe Filename)
+generateLib sources moduleName = do
+  -- set up the static args once
+  GHC.parseStaticFlags $ map noLoc $ words "-dynamic -fPIC -package hubris"
+
+  let libFile = zenc ("libHubris_" ++ moduleName)
+  s <- generateSource sources moduleName
+  case s of
+    Left s -> putStrLn ("HINT error: " ++ show s) >> return Nothing
+    Right mod -> do
+       putStrLn mod
+       res <- ghcBuild libFile mod ("Language.Ruby.Hubris.Exports." ++ moduleName) sources defaultGHCOptions 
+       
+       return (if res 
+                   then Just libFile
+                   else Nothing)
+
+generateSource :: [Filename] ->   -- optional haskell source to load into the interpreter
+                   ModuleName ->   -- name of the module to build a wrapper for
+                   IO (Either InterpreterError String)
+generateSource sources moduleName = runInterpreter $ do
+         say $ show sources
+         loadModules sources
+         say "loaded"
+         -- setTopLevelModules [moduleName]
+         setImportsQ $ map (\x->(x,Just x)) $ ("Language.Ruby.Hubris"):("Language.Ruby.Hubris.Binding"):moduleName:[]
+
+
+         functions <- getFunctions moduleName
+         say $ "Candidates: " ++ (show functions)
+       -- ok, let's see if we can come up with an expression of the right type
+
+
+         exportable <- filterM (\func -> do let rubyVal ="(fromIntegral $ fromEnum $ Language.Ruby.Hubris.Binding.RUBY_Qtrue)"
+                                            let f = "Language.Ruby.Hubris.wrap " ++ moduleName ++"." ++func ++" " ++ rubyVal
+                                            say f
+                                            (typeOf f >>= \n -> say $ "type of wrap." ++ func ++ " is " ++ show n) 
+                                                 `catchError` (say . show)
+                                            typeChecks (f ++ "==" ++ rubyVal )) functions
+
+         say $ "Exportable: " ++ (show exportable)
+            -- withTypes <- mapM  (\x ->  typeOf x >>= \t -> return (x,t)) exportable
+         return $ unlines $
+         -- ideally, all this stuff would be using something like the Interpolator module,
+        -- but haskell-src-meta is not going on 6.12 yet, so let's do it traditionally instead.
+
+          ["{-# LANGUAGE ForeignFunctionInterface #-}", 
+           "module Language.Ruby.Hubris.Exports." ++ moduleName ++ " where",
+          "import Language.Ruby.Hubris",
+          "import qualified Prelude",
+          "import Language.Ruby.Hubris.Binding",
+          "import qualified " ++ moduleName] ++
+          [fun ++ " :: Value -> Value" | fun <- exportable ] ++
+          [fun ++ " = Language.Ruby.Hubris.wrap " ++ moduleName ++ "." ++  fun | fun <- exportable ] ++
+
+          ["foreign export ccall \"" ++  fun ++ "\" " ++ fun ++ " :: Value -> Value" | fun <- exportable ]
+
+say = liftIO . putStrLn
+
+getFunctions moduleName = do
+  exports <- getModuleExports moduleName
+  return $ map (\(Fun f) -> f) $ filter isFun exports
+
+isFun (Fun f) = True
+isFun _ = False
diff --git a/Language/Ruby/Hubris/ZCode.hs b/Language/Ruby/Hubris/ZCode.hs
new file mode 100644
--- /dev/null
+++ b/Language/Ruby/Hubris/ZCode.hs
@@ -0,0 +1,67 @@
+{-# LANGUAGE PatternGuards #-}
+
+module Language.Ruby.Hubris.ZCode (zenc,zdec) where
+
+import Data.Char
+import Data.Ix
+import qualified Data.Map as M
+import Numeric
+
+zemap :: M.Map Char String
+zemap = M.fromList $
+    [ ('(', "ZL")
+    , (')', "ZR")
+    , ('[', "ZM")
+    , (']', "ZN")
+    , (':', "ZC")
+    , ('Z', "ZZ")
+
+    , ('z', "zz")
+    , ('&', "za")
+    , ('|', "zb")
+    , ('^', "zc")
+    , ('$', "zd")
+    , ('=', "ze")
+    , ('>', "zg")
+    , ('#', "zh")
+    , ('.', "zi")
+    , ('<', "zl")
+    , ('-', "zm")
+    , ('!', "zn")
+    , ('+', "zp")
+    , ('\'', "zq")
+    , ('\\', "zr")
+    , ('/', "zs")
+    , ('*', "zt")
+    , ('_', "zu")
+    , ('%', "zv")
+    ]
+
+zdmap :: M.Map String Char
+zdmap = M.fromList . map (\(a, b) -> (b, a)) . M.toList $ zemap
+
+zenc, zdec :: String -> String
+
+zenc = concatMap (\c -> M.findWithDefault (z c) c zemap)
+    where
+    z c
+        | any (($ c) . inRange) [('a', 'y'), ('A', 'Z'), ('0', '9')] =
+            [c]
+        | otherwise =
+            let
+                s = showHex (ord c) "U"
+                p = if inRange ('0', '9') (head s) then id else ('0' :)
+            in
+            'z' : p s
+
+zdec "" = ""
+zdec [c] = [c]
+zdec (c : cs@(c' : cs'))
+    | c `elem` "zZ"
+    , Just x <- M.lookup [c, c'] zdmap
+    = x : zdec cs'
+    | c == 'z'
+    , (h@(_ : _), 'U' : t) <- span isHexDigit cs
+    , [(n, "")] <- readHex h
+    = chr n : zdec t
+    | otherwise = c : zdec cs
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/cbits/rshim.c b/cbits/rshim.c
new file mode 100644
--- /dev/null
+++ b/cbits/rshim.c
@@ -0,0 +1,34 @@
+
+#include "rshim.h"
+
+#include <ruby.h>
+#include <stdio.h>
+
+/* void Init_rshim() { */
+/*   printf("loaded, bitches\n"); */
+/* } */
+
+// did this really have to be a macro? BAD MATZ
+unsigned int rtype(VALUE obj) {
+  return TYPE(obj);
+}
+
+VALUE int2fix(int x) {
+  return INT2FIX(x);
+}
+
+int fix2int(VALUE x) {
+  return FIX2INT(x);
+}
+
+double num2dbl(VALUE x) {
+  return NUM2DBL(x);
+}
+
+unsigned int rb_ary_len(VALUE x) {
+  return RARRAY_LEN(x);
+}
+
+VALUE keys(VALUE hash) {
+  rb_funcall(hash, rb_intern("keys"), 0);
+}
diff --git a/cbits/rshim.h b/cbits/rshim.h
new file mode 100644
--- /dev/null
+++ b/cbits/rshim.h
@@ -0,0 +1,49 @@
+#ifndef __FOOSHIM__
+#define __FOOSHIM__ 1
+#define HAVE_STRUCT_TIMESPEC 1 
+#include <ruby.h>
+
+// did this really have to be a macro? BAD MATZ
+unsigned int rtype(VALUE obj);
+VALUE int2fix(int i);
+int fix2int(VALUE x);
+double num2dbl(VALUE x);
+unsigned int rb_ary_len(VALUE x);
+VALUE keys(VALUE hash);
+// argh, and again
+enum RubyType {
+ RT_NONE     = T_NONE,
+
+ RT_NIL      = T_NIL    ,
+ RT_OBJECT   = T_OBJECT ,
+ RT_CLASS    = T_CLASS  ,
+ RT_ICLASS   = T_ICLASS ,
+ RT_MODULE   = T_MODULE ,
+ RT_FLOAT    = T_FLOAT  ,
+ RT_STRING   = T_STRING ,
+ RT_REGEXP   = T_REGEXP ,
+ RT_ARRAY    = T_ARRAY  ,
+ RT_FIXNUM   = T_FIXNUM ,
+ RT_HASH     = T_HASH   ,
+ RT_STRUCT   = T_STRUCT ,
+ RT_BIGNUM   = T_BIGNUM ,
+ RT_FILE     = T_FILE   ,
+
+ RT_TRUE     = T_TRUE   ,
+ RT_FALSE    = T_FALSE  ,
+ RT_DATA     = T_DATA   ,
+ RT_MATCH    = T_MATCH  ,
+ RT_SYMBOL   = T_SYMBOL ,
+
+ // t_BLKTAG   = T_BLKTAG , // this one is broken in ruby 1.9
+
+ RT_UNDEF    = T_UNDEF  ,
+ // t_VARMAP   = T_VARMAP , // this one is broken in ruby 1.9
+ // t_SCOPE    = T_SCOPE  , // this one is broken in ruby 1.9
+ RT_NODE     = T_NODE   ,
+
+ RT_MASK     = T_MASK   ,
+};
+#endif
+
+
diff --git a/hubris.cabal b/hubris.cabal
new file mode 100644
--- /dev/null
+++ b/hubris.cabal
@@ -0,0 +1,46 @@
+Name:                hubris
+Version:             0.0.1
+Author:              Mark Wotton
+Maintainer:          mwotton@gmail.com
+Build-Type:          Simple
+Cabal-Version:       >=1.2
+License:        OtherLicense
+License-File:   LICENSE
+Build-Type:     Simple
+Author:         Mark Wotton <mwotton@gmail.com>
+Maintainer:     Mark Wotton <mwotton@gmail.com>
+bug-reports:    mailto:mwotton@gmail.com
+Category:       Language
+Stability:      Experimental
+extra-source-files: 
+Synopsis:       Support library for Hubris, the Ruby <=> Haskell bridge
+Description:    Support library for Hubris, the Ruby <=> Haskell bridge
+
+Library
+-- the ordering is critical, because Cabal doesn't do dependency analysis.
+        Exposed-Modules: Language.Ruby.Hubris.Binding, Language.Ruby.Hubris, Language.Ruby.Hubris.LibraryBuilder, Language.Ruby.Hubris.ZCode, Language.Ruby.Hubris.GHCBuild
+-- so this is a really filthy hack.
+        c-sources: cbits/rshim.c 
+        includes:  cbits/rshim.h
+        install-includes:  cbits/rshim.h
+
+-- a proper fix for this would involve autoconf and I'm not feeling up to it.
+        include-dirs: cbits /opt/local/include/ruby-1.9.1/ 
+        extra-lib-dirs: /opt/local/lib
+       -- c2hsoptions: --cpp=gcc --cppopts=-E --cppopts=-xc
+        extra-libraries: ruby
+        build-depends:  ghc, Cabal>=1.7.4 && < 1.8, base, haskell98, containers, bytestring, array, mtl, old-time, ghc-paths, haskell-src-meta, hint
+
+Executable Hubrify
+  Main-is:           Hubrify.hs
+  Build-Depends:     base >= 3 && < 5, ghc, Cabal>=1.7.4 && < 1.8, base, haskell98, containers, bytestring, array, mtl, old-time, ghc-paths, haskell-src-meta, hint
+  Other-Modules:     Language.Ruby.Hubris.Binding
+  c-sources: cbits/rshim.c 
+  include-dirs: cbits /opt/local/include/ruby-1.9.1/ 
+  extra-lib-dirs: /opt/local/lib
+  extra-libraries: ruby
+  -- This is bad form, apparently, and if i include it, ./Setup dist cries big fat tears,
+  --  but you _really_ want a dynamic lib with Hubrify, or you'll get a truly
+  -- huge binary (may not even link, I had problems with the iconv dependency from HSbase)
+  -- anyway, pass "--ghc-options=-dynamic" to ./Setup build, and you should be apples.
+  -- ghc-options: -dynamic
