diff --git a/AUTHORS b/AUTHORS
--- a/AUTHORS
+++ b/AUTHORS
@@ -9,6 +9,7 @@
   Ricardo Lanziano <ricardo.lanziano@gmail.com>
   Saito Atsushi <https://github.com/SaitoAtsushi>
   sw2wolf <https://github.com/sw2wolf>
+  Satoshi Egi <egi@egison.org>
 
 References:
   Write Yourself a Scheme in 48 Hours <http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours>
diff --git a/ChangeLog.markdown b/ChangeLog.markdown
--- a/ChangeLog.markdown
+++ b/ChangeLog.markdown
@@ -1,3 +1,23 @@
+v3.17
+--------
+
+- Added support for [`define-record-type`](http://justinethier.github.io/husk-scheme/manual/node57.html) from R<sup>7</sup>RS and SRFI 9. This syntax allows creation of new disjoint types supporting access to multiple fields.
+- Added support for parameter objects from R<sup>7</sup>RS and SRFI 39. See [dynamic bindings](http://justinethier.github.io/husk-scheme/manual/node41.html) in the user manual for more information.
+- Added a `(scheme process-context)` library containing the following functions:
+     - [`emergency-exit`](http://justinethier.github.io/husk-scheme/manual/node86.html#emergency-exit)
+     - [`exit-fail`](http://justinethier.github.io/husk-scheme/manual/node86.html#exit-fail)
+     - [`exit-success`](http://justinethier.github.io/husk-scheme/manual/node86.html#exit-success)
+     - [`get-environment-variable`](http://justinethier.github.io/husk-scheme/manual/node86.html#get-environment-variable)
+     - [`get-environment-variables`](http://justinethier.github.io/husk-scheme/manual/node86.html#get-environment-variables)
+     - [`system`](http://justinethier.github.io/husk-scheme/manual/node86.html#system)
+
+Bug Fixes:
+
+- Fixed a macro bug where the last element of a pattern's improper list may not be matched correctly if there is an ellipsis earlier in the list.
+- Prevent infinite recursion when evaluating a pointer that contains a pointer to itself.
+- Fixed the compiler to add full support for splicing of `begin` definitions.
+- Updated `dynamic-wind` to return the value from the `during` thunk instead of the `after` thunk.
+
 v3.16.1
 --------
 
diff --git a/hs-src/Compiler/huskc.hs b/hs-src/Compiler/huskc.hs
--- a/hs-src/Compiler/huskc.hs
+++ b/hs-src/Compiler/huskc.hs
@@ -17,11 +17,12 @@
 import Language.Scheme.Types     -- Scheme data types
 import Language.Scheme.Variables -- Scheme variable operations
 import Control.Monad.Error
+import Data.Maybe (fromMaybe)
 import System.Cmd (system)
 import System.Console.GetOpt
 import System.FilePath (dropExtension)
 import System.Environment
-import System.Exit (ExitCode (..), exitWith)
+import System.Exit (ExitCode (..), exitSuccess, exitWith)
 import System.IO
 
 main :: IO ()
@@ -38,15 +39,10 @@
   if null nonOpts
      then showUsage
      else do
-        let inFile = nonOpts !! 0
+        let inFile = head nonOpts
             outHaskell = (dropExtension inFile) ++ ".hs"
-            outExec = case output of
-              Just inFile' -> inFile'
-              Nothing -> dropExtension inFile
-            extraOpts = case extra of
-              Just args' -> args'
-              Nothing -> ""
--- TODO: pass language revision
+            outExec = fromMaybe (dropExtension inFile) output
+            extraOpts = fromMaybe "" extra 
         process inFile outHaskell outExec lib dynamic extraOpts langrev debugOpt
 
 -- 
@@ -120,7 +116,7 @@
   putStrLn "                            (Requires libraries built via --enable-shared)"
   putStrLn "  -x, --extra args          Pass extra arguments directly to ghc"
   putStrLn ""
-  exitWith ExitSuccess
+  exitSuccess
 
 -- |Print debug information
 showDebug :: Options -> IO Options
@@ -128,13 +124,13 @@
   stdlib <- getDataFileName "lib/stdlib.scm"
   putStrLn $ "stdlib: " ++ stdlib
   putStrLn ""
-  exitWith ExitSuccess
+  exitSuccess
 
 -- |Print version information
 showVersion :: Options -> IO Options
 showVersion _ = do
   Language.Scheme.Core.showBanner
-  exitWith ExitSuccess
+  exitSuccess
 
 -- |High level code to compile the given file
 process :: String -> String -> String -> Bool -> Bool -> String -> String -> Bool -> IO ()
@@ -156,7 +152,7 @@
 
 -- |Compile a scheme file to haskell
 compileSchemeFile :: Env -> Maybe String -> String -> String -> String -> String -> Bool -> IOThrowsError LispVal
-compileSchemeFile env stdlib srfi55 filename outHaskell langrev debugOpt = do
+compileSchemeFile env stdlib srfi55 filename outHaskell langrev _ = do
   let conv :: LispVal -> String
       conv (String s) = s
       conv l = show l
@@ -191,7 +187,7 @@
   _ <- liftIO $ writeList outH headerModule
   _ <- liftIO $ writeList outH $ map (\modl -> "import " ++ modl ++ " ") $ headerImports ++ moreHeaderImports
   filepath <- liftIO $ getDataFileName ""
-  _ <- liftIO $ writeList outH $ header filepath compileLibraries langrev debugOpt
+  _ <- liftIO $ writeList outH $ header filepath compileLibraries langrev
   _ <- liftIO $ case compileLibraries of
     True -> do
       _ <- writeList outH $ map show libsC
diff --git a/hs-src/Interpreter/shell.hs b/hs-src/Interpreter/shell.hs
--- a/hs-src/Interpreter/shell.hs
+++ b/hs-src/Interpreter/shell.hs
@@ -14,16 +14,17 @@
 module Main where
 import qualified Language.Scheme.Core as LSC -- Scheme Interpreter
 import Language.Scheme.Types                 -- Scheme data types
-import qualified Language.Scheme.Util as LSU (countAllLetters, strip)
+import qualified Language.Scheme.Util as LSU (countAllLetters, countLetters, strip)
 import qualified Language.Scheme.Variables as LSV -- Scheme variable operations
 import Control.Monad.Error
 import qualified Data.Char as DC
 import qualified Data.List as DL
+import Data.Maybe (fromMaybe)
 import System.Console.GetOpt
 import qualified System.Console.Haskeline as HL
 import qualified System.Console.Haskeline.Completion as HLC
 import System.Environment
-import System.Exit (ExitCode (..), exitWith)
+import System.Exit (exitSuccess)
 import System.IO
 
 main :: IO ()
@@ -86,7 +87,7 @@
 --  putStrLn "                     5 - r5rs (default)"
 --  putStrLn "                     7 - r7rs small"
   putStrLn ""
-  exitWith ExitSuccess
+  exitSuccess
 
 --
 -- REPL Section
@@ -107,13 +108,13 @@
                            List $ map String $ drop 1 args)]
 
   result <- (LSC.runIOThrows $ liftM show $ 
-             LSC.evalLisp env (List [Atom "load", String (args !! 0)]))
+             LSC.evalLisp env (List [Atom "load", String (head args)]))
   _ <- case result of
     Just errMsg -> putStrLn errMsg
     _  -> do 
       -- Call into (main) if it exists...
       alreadyDefined <- liftIO $ LSV.isBound env "main"
-      let argv = List $ map String $ args
+      let argv = List $ map String args
       when alreadyDefined (do 
         mainResult <- (LSC.runIOThrows $ liftM show $ 
                        LSC.evalLisp env (List [Atom "main", List [Atom "quote", argv]]))
@@ -143,7 +144,7 @@
                         inputLines <- getMultiLine [input]
                         let input' = unlines inputLines
                         result <- liftIO (LSC.evalString env input')
-                        if (length result) > 0
+                        if not (null result)
                            then do HL.outputStrLn result
                                    loop env
                            else loop env
@@ -168,6 +169,13 @@
 -- |Auto-complete using scheme symbols
 completeScheme :: Env -> (String, String) 
                -> IO (String, [HLC.Completion])
+-- Right after a ')' it seems more useful to autocomplete next closed parenthesis
+completeScheme _ (lnL@(')':_), _) = do
+  let cOpen  = LSU.countLetters '(' lnL
+      cClose = LSU.countLetters ')' lnL
+  if cOpen > cClose
+   then return (lnL, [HL.Completion ")" ")" False])
+   else return (lnL, [])
 completeScheme env (lnL, lnR) = do
    complete $ reverse $ readAtom lnL
  where
@@ -176,6 +184,7 @@
     -- useful to autocomplete filenames
     liftIO $ HLC.completeFilename (lnL, lnR)
 
+
   complete pre = do
    -- Get list of possible completions from ENV
    xps <- LSV.recExportsFromEnv env
@@ -184,13 +193,11 @@
    let comps = map (\ (Atom a) -> HL.Completion a a False) allDefs'
 
    -- Get unused portion of the left-hand string
-   let unusedLnL = case DL.stripPrefix (reverse pre) lnL of
-                     Just s -> s
-                     Nothing -> lnL
+   let unusedLnL = fromMaybe lnL (DL.stripPrefix (reverse pre) lnL)
    return (unusedLnL, comps)
 
   -- Not loaded into an env, so we need to list them here
-  specialForms = map (\ s -> Atom s) [ 
+  specialForms = map Atom [ 
        "define"  
      , "define-syntax" 
      , "expand"
@@ -213,6 +220,6 @@
     | c == '"' = ['"'] -- Save to indicate file completion to caller
     | c == '(' = []
     | c == '[' = []
-    | DC.isSpace(c) = []
+    | DC.isSpace c = []
     | otherwise = (c : readAtom cs)
   readAtom [] = []
diff --git a/hs-src/Language/Scheme/Compiler.hs b/hs-src/Language/Scheme/Compiler.hs
--- a/hs-src/Language/Scheme/Compiler.hs
+++ b/hs-src/Language/Scheme/Compiler.hs
@@ -60,6 +60,7 @@
 import Control.Monad.Error
 import Data.Complex
 import qualified Data.List
+import Data.Maybe (fromMaybe)
 import Data.Ratio
 -- import Debug.Trace
 
@@ -95,6 +96,15 @@
 _compileBlock symThisFunc symLastFunc env result [c] = do
   compiled <- mcompile env c $ CompileOptions symThisFunc False False symLastFunc 
   return $ result ++ compiled
+-- A special case to splice in definitions from a (begin)
+_compileBlock symThisFunc symLastFunc env result 
+    (c@(List [Atom "%husk-switch-to-parent-environment"]) : cs)  = do
+  let parEnv = fromMaybe env (parentEnv env)
+  _ <- defineTopLevelVars parEnv cs
+  Atom symNextFunc <- _gensym "f"
+  compiled <- mcompile env c $ 
+                       CompileOptions symThisFunc False False (Just symNextFunc)
+  _compileBlock symNextFunc symLastFunc parEnv (result ++ compiled) cs
 _compileBlock symThisFunc symLastFunc env result (c:cs) = do
   Atom symNextFunc <- _gensym "f"
   compiled <- mcompile env c $ 
@@ -115,7 +125,7 @@
 compileLambdaList :: [LispVal] -> IOThrowsError String
 compileLambdaList l = do
   serialized <- mapM serialize l 
-  return $ "[" ++ concat (Data.List.intersperse "," serialized) ++ "]"
+  return $ "[" ++ Data.List.intercalate "," serialized ++ "]"
  where serialize (Atom a) = return $ (show a)
        serialize a = throwError $ Default $ 
                          "invalid parameter to lambda list: " ++ show a
@@ -156,7 +166,7 @@
 -- Experimenting with r7rs library support
 compile env 
         (List (Atom "import" : mods)) 
-        copts@(CompileOptions _ _ _ _) = do
+        copts@(CompileOptions {}) = do
     LispEnv meta <- getVar env "*meta-env*"
     LSCL.importAll env 
                    meta 
@@ -322,7 +332,7 @@
     return $ [createAstFunc copts f] ++ compPredicate ++ [compCheckPredicate] ++ 
               compConsequence ++ compAlternate)
 
-compile env ast@(List [Atom "set!", Atom var, form]) copts@(CompileOptions _ _ _ _) = do
+compile env ast@(List [Atom "set!", Atom var, form]) copts@(CompileOptions {}) = do
   compileSpecialFormBody env ast copts (\ _ -> do
     Atom symDefine <- _gensym "setFunc"
     Atom symMakeDefine <- _gensym "setFuncMakeSet"
@@ -348,7 +358,7 @@
             (show args) ++ "\"]") copts -- Cheesy to use a string, but fine for now...
     return [f])
 
-compile env ast@(List [Atom "define", Atom var, form]) copts@(CompileOptions _ _ _ _) = do
+compile env ast@(List [Atom "define", Atom var, form]) copts@(CompileOptions {}) = do
   compileSpecialFormBody env ast copts (\ _ -> do
     Atom symDefine <- _gensym "defineFuncDefine"
     Atom symMakeDefine <- _gensym "defineFuncMakeDef"
@@ -376,7 +386,7 @@
     return $ [createAstFunc copts f] ++ compDefine ++ [compMakeDefine])
 
 compile env ast@(List (Atom "define" : List (Atom var : fparams) : fbody)) 
-        copts@(CompileOptions _ _ _ _) = do
+        copts@(CompileOptions {}) = do
   _ <- validateFuncParams fparams Nothing
   compileSpecialFormBody env ast copts (\ _ -> do
     bodyEnv <- liftIO $ extendEnv env []
@@ -399,11 +409,11 @@
           AstValue $ "  _ <- defineVar env \"" ++ var ++ "\" result ",
           createAstCont copts "result" ""
           ]
-    return $ [createAstFunc copts f] ++ compiledBody)
+    return $ (createAstFunc copts f) : compiledBody)
 
 compile env 
         ast@(List (Atom "define" : DottedList (Atom var : fparams) varargs : fbody)) 
-        copts@(CompileOptions _ _ _ _) = do
+        copts@(CompileOptions {}) = do
   _ <- validateFuncParams (fparams ++ [varargs]) Nothing
   compileSpecialFormBody env ast copts (\ _ -> do
     bodyEnv <- liftIO $ extendEnv env []
@@ -424,10 +434,10 @@
                        compiledParams ++ ") " ++ symCallfunc,
       AstValue $ "  _ <- defineVar env \"" ++ var ++ "\" result ",
       createAstCont copts "result" "" ]
-    return $ [createAstFunc copts f] ++ compiledBody)
+    return $ (createAstFunc copts f) : compiledBody)
 
 compile env ast@(List (Atom "lambda" : List fparams : fbody)) 
-        copts@(CompileOptions _ _ _ _) = do
+        copts@(CompileOptions {}) = do
   _ <- validateFuncParams fparams Nothing
   compileSpecialFormBody env ast copts (\ _ -> do
     Atom symCallfunc <- _gensym "lambdaFuncEntryPt"
@@ -445,10 +455,10 @@
                      ") " ++ symCallfunc,
           createAstCont copts "result" ""
           ]
-    return $ [createAstFunc copts f] ++ compiledBody)
+    return $ (createAstFunc copts f) : compiledBody)
 
 compile env ast@(List (Atom "lambda" : DottedList fparams varargs : fbody)) 
-        copts@(CompileOptions _ _ _ _) = do
+        copts@(CompileOptions {}) = do
   _ <- validateFuncParams (fparams ++ [varargs]) Nothing
   compileSpecialFormBody env ast copts (\ _ -> do
     Atom symCallfunc <- _gensym "lambdaFuncEntryPt"
@@ -465,10 +475,10 @@
       AstValue $ "  result <- makeHVarargs (" ++ ast2Str varargs ++ ") env (" ++ 
          compiledParams ++ ") " ++ symCallfunc,
       createAstCont copts "result" "" ]
-    return $ [createAstFunc copts f] ++ compiledBody)
+    return $ (createAstFunc copts f) : compiledBody)
 
 compile env ast@(List (Atom "lambda" : varargs@(Atom _) : fbody)) 
-        copts@(CompileOptions _ _ _ _) = do
+        copts@(CompileOptions {}) = do
   compileSpecialFormBody env ast copts (\ _ -> do
     Atom symCallfunc <- _gensym "lambdaFuncEntryPt"
    
@@ -483,7 +493,7 @@
           AstValue $ "  result <- makeHVarargs (" ++ ast2Str varargs ++ ") env [] " ++ symCallfunc,
           createAstCont copts "result" ""
           ]
-    return $ [createAstFunc copts f] ++ compiledBody)
+    return $ (createAstFunc copts f) : compiledBody)
 
 compile env ast@(List [Atom "string-set!", Atom var, i, character]) copts = do
   compileSpecialFormBody env ast copts (\ _ -> do
@@ -883,7 +893,7 @@
 
   -- Only append module again if it is not already in the list
   List l <- getNamespacedVar env 't' {-"internal"-} "imports"
-  _ <- if not ((String moduleName) `elem` l)
+  _ <- if String moduleName `notElem` l
           then setNamespacedVar env 't' {-"internal"-} "imports" $ 
                                 List $ l ++ [String moduleName]
           else return $ String ""
@@ -900,7 +910,7 @@
 
 -- |Expand macros and compile the resulting code
 mcompile :: Env -> LispVal -> CompOpts -> IOThrowsError [HaskAST]
-mcompile env lisp copts = mfunc env lisp compile copts
+mcompile env lisp = mfunc env lisp compile
 
 -- |Expand macros and then pass control to the given function 
 mfunc :: Env
@@ -934,7 +944,7 @@
       Atom symNext <- _gensym "afterDivert"
       diverted <- compileDivertedVars symNext env vars copts
       rest <- func env expanded $ CompileOptions symNext uvar uargs nfnc
-      return $ [diverted] ++ rest
+      return $ diverted : rest
 
 -- |Take a list of variables diverted into env at compile time, and
 --  divert them into the env at runtime
@@ -1040,7 +1050,7 @@
        -- Keep track of any variables since we need to do a
        -- 'getRtVar' lookup for each of them prior to apply
        let pack (Atom p : ps) strs vars i = do
-             let varName = "v" ++ show i
+             let varName = 'v' : show i
              pack ps 
                   (strs ++ [varName]) 
                   (vars ++ [(p, varName)]) 
diff --git a/hs-src/Language/Scheme/Compiler/Libraries.hs b/hs-src/Language/Scheme/Compiler/Libraries.hs
--- a/hs-src/Language/Scheme/Compiler/Libraries.hs
+++ b/hs-src/Language/Scheme/Compiler/Libraries.hs
@@ -39,7 +39,7 @@
     -> IOThrowsError [HaskAST]
     -- ^ Compiled code
 importAll env metaEnv [m] lopts 
-          copts@(CompileOptions _ _ _ _) = do
+          copts@(CompileOptions {}) = do
     _importAll env metaEnv m lopts copts
 importAll env metaEnv (m : ms) lopts
           (CompileOptions thisFunc _ _ lastFunc) = do
@@ -151,7 +151,7 @@
     -> IOThrowsError [HaskAST]
     -- ^ Compiled code, or an empty list if the module was already compiled
     --   and loaded into memory
-loadModule metaEnv name lopts copts@(CompileOptions _ _ _ _) = do
+loadModule metaEnv name lopts copts@(CompileOptions {}) = do
     -- Get the module definition, or load it from file if necessary
     _mod' <- eval metaEnv $ List [Atom "find-module", List [Atom "quote", name]]
     case _mod' of
diff --git a/hs-src/Language/Scheme/Compiler/Types.hs b/hs-src/Language/Scheme/Compiler/Types.hs
--- a/hs-src/Language/Scheme/Compiler/Types.hs
+++ b/hs-src/Language/Scheme/Compiler/Types.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE CPP #-}
+
 {- |
 Module      : Language.Scheme.Compiler.Types
 Copyright   : Justin Ethier
@@ -77,7 +79,7 @@
     }
 
 -- |Runtime reference to module data structure
-moduleRuntimeVar :: [Char]
+moduleRuntimeVar :: String
 moduleRuntimeVar = " modules "
 
 -- |Create code for a function
@@ -86,12 +88,8 @@
   -> [HaskAST] -- ^ Body of the function
   -> HaskAST -- ^ Complete function code
 createAstFunc (CompileOptions thisFunc useVal useArgs _) funcBody = do
-  let val = case useVal of
-              True -> "value"
-              _ -> "_"
-      args = case useArgs of
-               True -> "(Just args)"
-               _ -> "_"
+  let val = if useVal then "value" else "_"
+      args = if useArgs then "(Just args)" else "_"
   AstFunction thisFunc (" env cont " ++ val ++ " " ++ args ++ " ") funcBody
 
 -- |Create code for a continutation
@@ -126,20 +124,23 @@
 showValAST (AstFunction name args code) = do
   let typeSig = "\n" ++ name ++ " :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal "
   let fheader = "\n" ++ name ++ args ++ " = do "
-  let fbody = unwords . map (\x -> "\n" ++ x ) $ map showValAST code
---  let appendArg arg = do
---        if Data.List.isInfixOf arg args
---           then " ++ \" \" ++ " ++ (show arg) ++ 
---                " ++ \" [\" ++ (show " ++ arg ++ ")" ++ 
---                " ++ \"] \""
---           else ""
---  let fdebug = "\n  _ <- liftIO $ (trace (\"" ++ 
---               name ++ "\"" ++ 
---               (appendArg "value") ++ 
---               (appendArg "args") ++ 
---               ") getCPUTime)"
---  typeSig ++ fheader ++ fdebug ++ fbody 
+  let fbody = unwords . map (\x -> '\n' : x ) $ map showValAST code
+#ifdef UseDebug
+  let appendArg arg = do
+        if Data.List.isInfixOf arg args
+           then " ++ \" \" ++ " ++ (show arg) ++ 
+                " ++ \" [\" ++ (show " ++ arg ++ ")" ++ 
+                " ++ \"] \""
+           else ""
+  let fdebug = "\n  _ <- liftIO $ (trace (\"" ++ 
+               name ++ "\"" ++ 
+               (appendArg "value") ++ 
+               (appendArg "args") ++ 
+               ") getCPUTime)"
+  typeSig ++ fheader ++ fdebug ++ fbody 
+#else
   typeSig ++ fheader ++ fbody 
+#endif
 showValAST (AstValue v) = v
 showValAST (AstContinuation nextFunc args) =
     "  continueEval env (makeCPSWArgs env cont " ++ 
@@ -152,7 +153,7 @@
   :: forall a. [[a]] -- ^ Original list-of-lists
   -> [a] -- ^ Separator 
   -> [a] -- ^ Joined list
-joinL ls sep = concat $ Data.List.intersperse sep ls
+joinL ls sep = Data.List.intercalate sep ls
 
 -- |Convert abstract syntax tree to a string
 ast2Str :: LispVal -> String 
@@ -217,12 +218,17 @@
  , " qualified Data.Map "
  , "Data.Ratio "
  , "Data.Word "
- , "System.IO "]
+ , "System.IO "
+#ifdef UseDebug
+ , "System.CPUTime "
+ , "Debug.Trace "
+#endif
+ ]
 
 -- |Block of code used in the header of a Haskell program 
 --  generated by the compiler.
-header :: String -> Bool -> String -> Bool -> [String]
-header filepath useCompiledLibs langRev debug = do
+header :: String -> Bool -> String -> [String]
+header filepath useCompiledLibs langRev = do
   let env = if useCompiledLibs
             then "primitiveBindings"
             else case langRev of
@@ -235,8 +241,6 @@
                , "  liftIO $ registerExtensions env getDataFileName' "
                , "  continueEval env (makeCPSWArgs env cont exec []) (Nil \"\")"]
   [ " "
-    , if debug then "import System.CPUTime " else ""
-    , if debug then "import Debug.Trace " else ""
     , " "
     , "-- |Get variable at runtime "
     , "getRTVar env var = do " 
diff --git a/hs-src/Language/Scheme/Core.hs b/hs-src/Language/Scheme/Core.hs
--- a/hs-src/Language/Scheme/Core.hs
+++ b/hs-src/Language/Scheme/Core.hs
@@ -62,6 +62,7 @@
 import Data.Array
 import qualified Data.ByteString as BS
 import qualified Data.Map
+import Data.Maybe (fromMaybe, isNothing)
 import Data.Version as DV
 import Data.Word
 import qualified System.Exit
@@ -93,8 +94,8 @@
     return [ Atom "r7rs"
            , Atom "husk"
            , Atom $ "husk-" ++ (DV.showVersion PHS.version)
-           , Atom $ SysInfo.arch
-           , Atom $ SysInfo.os
+           , Atom SysInfo.arch
+           , Atom SysInfo.os
            , Atom "full-unicode"
            , Atom "complex"
            , Atom "ratios"
@@ -102,7 +103,7 @@
 
 -- |Get the full path to a data file installed for husk
 getDataFileFullPath :: String -> IO String
-getDataFileFullPath s = PHS.getDataFileName s
+getDataFileFullPath = PHS.getDataFileName
 
 -- Future use:
 -- getDataFileFullPath' :: [LispVal] -> IOThrowsError LispVal
@@ -116,7 +117,7 @@
 --  libraries. If the file is not found in the current directory but exists
 --  as a husk library, return the full path to the file in the library.
 --  Otherwise just return the given filename.
-findFileOrLib :: [Char] -> ErrorT LispError IO String
+findFileOrLib :: String -> ErrorT LispError IO String
 findFileOrLib filename = do
     fileAsLib <- liftIO $ getDataFileFullPath $ "lib/" ++ filename
     exists <- fileExists [String filename]
@@ -186,7 +187,7 @@
         Left err -> do
             disp <- showLispError err
             return $ Just disp
-        Right _ -> return $ Nothing
+        Right _ -> return Nothing
 
 {- |Evaluate a string containing Scheme code
 
@@ -205,7 +206,7 @@
 -}
 evalString :: Env -> String -> IO String
 evalString env expr = do
-  runIOThrowsREPL $ liftM show $ (liftThrows $ readExpr expr) >>= evalLisp env
+  runIOThrowsREPL $ liftM show $ liftThrows (readExpr expr) >>= evalLisp env
 
 -- |Evaluate a string and print results to console
 evalAndPrint :: Env -> String -> IO ()
@@ -215,7 +216,7 @@
 evalLisp :: Env -> LispVal -> IOThrowsError LispVal
 evalLisp env lisp = do
   v <- meval env (makeNullContinuation env) lisp
-  recDerefPtrs v
+  safeRecDerefPtrs [] v
 
 -- |Evaluate a lisp data structure and return the LispVal or LispError
 --  result directly
@@ -304,7 +305,7 @@
             Continuation nEnv ncCont nnCont _ nDynWind ->
               -- Pass extra args along if last expression of a function, to support (call-with-values)
               continueEval nEnv (Continuation nEnv ncCont nnCont extraArgs nDynWind) val
-            _ -> return (val)
+            _ -> return val
         [lv] -> eval cEnv (Continuation cEnv (Just (SchemeBody [])) (Just cCont) Nothing dynWind) lv
         (lv : lvs) -> eval cEnv (Continuation cEnv (Just (SchemeBody lvs)) (Just cCont) Nothing dynWind) lv
 
@@ -353,18 +354,18 @@
 eval env cont val@(Pointer _ _) = continueEval env cont val
 eval env cont (Atom a) = do
   v <- getVar env a
-  val <- return $ case v of
+  let val = case v of
 -- TODO: this flag may go away on this branch; it may
 --       not be practical with Pointer used everywhere now
 #ifdef UsePointers
-    List _ -> Pointer a env
-    DottedList _ _ -> Pointer a env
-    String _ -> Pointer a env
-    Vector _ -> Pointer a env
-    ByteVector _ -> Pointer a env
-    HashTable _ -> Pointer a env
+              List _ -> Pointer a env
+              DottedList _ _ -> Pointer a env
+              String _ -> Pointer a env
+              Vector _ -> Pointer a env
+              ByteVector _ -> Pointer a env
+              HashTable _ -> Pointer a env
 #endif
-    _ -> v
+              _ -> v
   continueEval env cont val
 
 -- Quote an expression by simply passing along the value
@@ -477,7 +478,7 @@
   else meval env (makeCPS env cont cps) predic
  where cps :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
        cps e c result _ =
-            case (result) of
+            case result of
               Bool False -> meval e c alt
               _ -> meval e c conseq
 
@@ -576,13 +577,13 @@
  where
         cpsChar :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
         cpsChar e c chr _ = do
-            meval e (makeCPSWArgs e c cpsStr $ [chr]) i
+            meval e (makeCPSWArgs e c cpsStr [chr]) i
 
         cpsStr :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
         cpsStr e c idx (Just [chr]) = do
             value <- getVar env var
             derefValue <- derefPtr value
-            meval e (makeCPSWArgs e c cpsSubStr $ [idx, chr]) derefValue
+            meval e (makeCPSWArgs e c cpsSubStr [idx, chr]) derefValue
         cpsStr _ _ _ _ = throwError $ InternalError "Unexpected case in cpsStr"
 
         cpsSubStr :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
@@ -614,8 +615,8 @@
           o <- derefPtr obj
           cpsObj e c o x
         cpsObj _ _ obj@(List []) _ = throwError $ TypeMismatch "pair" obj
-        cpsObj e c obj@(List (_ : _)) _ = meval e (makeCPSWArgs e c cpsSet $ [obj]) argObj
-        cpsObj e c obj@(DottedList _ _) _ =  meval e (makeCPSWArgs e c cpsSet $ [obj]) argObj
+        cpsObj e c obj@(List (_ : _)) _ = meval e (makeCPSWArgs e c cpsSet [obj]) argObj
+        cpsObj e c obj@(DottedList _ _) _ =  meval e (makeCPSWArgs e c cpsSet [obj]) argObj
         cpsObj _ _ obj _ = throwError $ TypeMismatch "pair" obj
 
         cpsSet :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
@@ -644,19 +645,18 @@
  where
         cpsObj :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
         cpsObj _ _ pair@(List []) _ = throwError $ TypeMismatch "pair" pair
-        cpsObj e c pair@(List (_ : _)) _ = meval e (makeCPSWArgs e c cpsSet $ [pair]) argObj
-        cpsObj e c pair@(DottedList _ _) _ = meval e (makeCPSWArgs e c cpsSet $ [pair]) argObj
+        cpsObj e c pair@(List (_ : _)) _ = meval e (makeCPSWArgs e c cpsSet [pair]) argObj
+        cpsObj e c pair@(DottedList _ _) _ = meval e (makeCPSWArgs e c cpsSet [pair]) argObj
         cpsObj _ _ pair _ = throwError $ TypeMismatch "pair" pair
 
-        cpsSet :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsSet e c obj (Just [List (l : _)]) = do
-            l' <- recDerefPtrs l
-            obj' <- recDerefPtrs obj
-            (cons [l', obj']) >>= updateObject e var >>= continueEval e c
-        cpsSet e c obj (Just [DottedList (l : _) _]) = do
+        updateCdr e c obj l = do
             l' <- recDerefPtrs l
             obj' <- recDerefPtrs obj
             (cons [l', obj']) >>= updateObject e var >>= continueEval e c
+
+        cpsSet :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
+        cpsSet e c obj (Just [List (l : _)]) = updateCdr e c obj l
+        cpsSet e c obj (Just [DottedList (l : _) _]) = updateCdr e c obj l
         cpsSet _ _ _ _ = throwError $ InternalError "Unexpected argument to cpsSet"
 eval env cont args@(List [Atom "set-cdr!" , nonvar , _ ]) = do
  bound <- liftIO $ isRecBound env "set-cdr!"
@@ -675,19 +675,7 @@
  bound <- liftIO $ isRecBound env "list-set!"
  if bound
   then prepareApply env cont args -- if is bound to a variable in this scope; call into it
-  else meval env (makeCPS env cont cpsObj) i
- where
-        cpsObj :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsObj e c idx _ = meval e (makeCPSWArgs e c cpsList $ [idx]) object
-
-        cpsList :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsList e c obj (Just [idx]) = (meval e (makeCPSWArgs e c cpsUpdateList $ [idx, obj]) =<< getVar e var)
-        cpsList _ _ _ _ = throwError $ InternalError "Invalid argument to cpsList"
-
-        cpsUpdateList :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsUpdateList e c list (Just [idx, obj]) =
-            updateList list idx obj >>= updateObject e var >>= continueEval e c
-        cpsUpdateList _ _ _ _ = throwError $ InternalError "Invalid argument to cpsUpdateList"
+  else meval env (makeCPS env cont $ createObjSetCPS var object updateList) i
 
 eval env cont args@(List [Atom "list-set!" , nonvar , _ , _]) = do 
  bound <- liftIO $ isRecBound env "list-set!"
@@ -704,20 +692,7 @@
  bound <- liftIO $ isRecBound env "vector-set!"
  if bound
   then prepareApply env cont args -- if is bound to a variable in this scope; call into it
-  else meval env (makeCPS env cont cpsObj) i
- where
-        cpsObj :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsObj e c idx _ = meval e (makeCPSWArgs e c cpsVec $ [idx]) object
-
-        cpsVec :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsVec e c obj (Just [idx]) = (meval e (makeCPSWArgs e c cpsUpdateVec $ [idx, obj]) =<< getVar e var)
-        cpsVec _ _ _ _ = throwError $ InternalError "Invalid argument to cpsVec"
-
-        cpsUpdateVec :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsUpdateVec e c vec (Just [idx, obj]) =
-            updateVector vec idx obj >>= updateObject e var >>= continueEval e c
-        cpsUpdateVec _ _ _ _ = throwError $ InternalError "Invalid argument to cpsUpdateVec"
-
+  else meval env (makeCPS env cont $ createObjSetCPS var object updateVector) i
 eval env cont args@(List [Atom "vector-set!" , nonvar , _ , _]) = do 
  bound <- liftIO $ isRecBound env "vector-set!"
  if bound
@@ -733,19 +708,7 @@
  bound <- liftIO $ isRecBound env "bytevector-u8-set!"
  if bound
   then prepareApply env cont args -- if is bound to a variable in this scope; call into it
-  else meval env (makeCPS env cont cpsObj) i
- where
-        cpsObj :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsObj e c idx _ = meval e (makeCPSWArgs e c cpsVec $ [idx]) object
-
-        cpsVec :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsVec e c obj (Just [idx]) = (meval e (makeCPSWArgs e c cpsUpdateVec $ [idx, obj]) =<< getVar e var)
-        cpsVec _ _ _ _ = throwError $ InternalError "Invalid argument to cpsVec"
-
-        cpsUpdateVec :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsUpdateVec e c vec (Just [idx, obj]) =
-            updateByteVector vec idx obj >>= updateObject e var >>= continueEval e c
-        cpsUpdateVec _ _ _ _ = throwError $ InternalError "Invalid argument to cpsUpdateVec"
+  else meval env (makeCPS env cont $ createObjSetCPS var object updateByteVector) i
 
 eval env cont args@(List [Atom "bytevector-u8-set!" , nonvar , _ , _]) = do 
  bound <- liftIO $ isRecBound env "bytevector-u8-set!"
@@ -765,13 +728,13 @@
   else meval env (makeCPS env cont cpsValue) rkey
  where
         cpsValue :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
-        cpsValue e c key _ = meval e (makeCPSWArgs e c cpsH $ [key]) rvalue
+        cpsValue e c key _ = meval e (makeCPSWArgs e c cpsH [key]) rvalue
 
         cpsH :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
         cpsH e c value (Just [key]) = do
           v <- getVar e var
           derefVar <- derefPtr v
-          meval e (makeCPSWArgs e c cpsEvalH $ [key, value]) derefVar
+          meval e (makeCPSWArgs e c cpsEvalH [key, value]) derefVar
         cpsH _ _ _ _ = throwError $ InternalError "Invalid argument to cpsH"
 
         cpsEvalH :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
@@ -864,25 +827,52 @@
         Number byte -> do
 -- TODO: error checking
            let (h, t) = BS.splitAt (fromInteger idx) vec
-           return $ ByteVector $ BS.concat [h, BS.pack $ [fromInteger byte :: Word8], BS.tail t]
+           return $ ByteVector $ BS.concat [h, BS.pack [fromInteger byte :: Word8], BS.tail t]
         badType -> throwError $ TypeMismatch "byte" badType
 updateByteVector ptr@(Pointer _ _) i obj = do
   vec <- derefPtr ptr
   updateByteVector vec i obj
 updateByteVector v _ _ = throwError $ TypeMismatch "bytevector" v
 
+-- |Helper function to perform CPS for vector-set! and similar forms
+createObjSetCPS :: String
+                   -> LispVal
+                   -> (LispVal -> LispVal -> LispVal -> ErrorT LispError IO LispVal)
+                   -> Env
+                   -> LispVal
+                   -> LispVal
+                   -> Maybe [LispVal]
+                   -> IOThrowsError LispVal
+createObjSetCPS var object updateFnc = cpsIndex
+  where
+    -- Update data structure at given index, with given object
+    cpsUpdateStruct :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
+    cpsUpdateStruct e c struct (Just [idx, obj]) =
+        updateFnc struct idx obj >>= updateObject e var >>= continueEval e c
+    cpsUpdateStruct _ _ _ _ = throwError $ InternalError "Invalid argument to cpsUpdateStruct"
+
+    -- Receive index/object, retrieve variable containing data structure
+    cpsGetVar :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
+    cpsGetVar e c obj (Just [idx]) = (meval e (makeCPSWArgs e c cpsUpdateStruct [idx, obj]) =<< getVar e var)
+    cpsGetVar _ _ _ _ = throwError $ InternalError "Invalid argument to cpsGetVar"
+
+    -- Receive and pass index
+    cpsIndex :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
+    cpsIndex e c idx _ = meval e (makeCPSWArgs e c cpsGetVar [idx]) object
+
+
 {- Prepare for apply by evaluating each function argument,
    and then execute the function via 'apply' -}
 prepareApply :: Env -> LispVal -> LispVal -> IOThrowsError LispVal
 prepareApply env cont (List (function : functionArgs)) = do
-  eval env (makeCPSWArgs env cont cpsPrepArgs $ functionArgs) function
+  eval env (makeCPSWArgs env cont cpsPrepArgs functionArgs) function
  where cpsPrepArgs :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
        cpsPrepArgs e c func (Just args) =
 -- case (trace ("prep eval of args: " ++ show args) args) of
-          case (args) of
+          case args of
             [] -> apply c func [] -- No args, immediately apply the function
-            [a] -> meval env (makeCPSWArgs e c cpsEvalArgs $ [func, List [], List []]) a
-            (a : as) -> meval env (makeCPSWArgs e c cpsEvalArgs $ [func, List [], List as]) a
+            [a] -> meval env (makeCPSWArgs e c cpsEvalArgs [func, List [], List []]) a
+            (a : as) -> meval env (makeCPSWArgs e c cpsEvalArgs [func, List [], List as]) a
        cpsPrepArgs _ _ _ Nothing = throwError $ Default "Unexpected error in function application (1)"
         {- Store value of previous argument, evaluate the next arg until all are done
         parg - Previous argument that has now been evaluated
@@ -894,8 +884,8 @@
        cpsEvalArgs e c evaledArg (Just [func, List argsEvaled, List argsRemaining]) =
           case argsRemaining of
             [] -> apply c func (argsEvaled ++ [evaledArg])
-            [a] -> meval e (makeCPSWArgs e c cpsEvalArgs $ [func, List (argsEvaled ++ [evaledArg]), List []]) a
-            (a : as) -> meval e (makeCPSWArgs e c cpsEvalArgs $ [func, List (argsEvaled ++ [evaledArg]), List as]) a
+            [a] -> meval e (makeCPSWArgs e c cpsEvalArgs [func, List (argsEvaled ++ [evaledArg]), List []]) a
+            (a : as) -> meval e (makeCPSWArgs e c cpsEvalArgs [func, List (argsEvaled ++ [evaledArg]), List as]) a
 
        cpsEvalArgs _ _ _ (Just _) = throwError $ Default "Unexpected error in function application (1)"
        cpsEvalArgs _ _ _ Nothing = throwError $ Default "Unexpected error in function application (2)"
@@ -910,7 +900,7 @@
 -- case (trace ("calling into continuation. dynWind = " ++ show ndynwind) ndynwind) of
   case ndynwind of
     -- Call into dynWind.before if it exists...
-    Just ([DynamicWinders beforeFunc _]) -> apply (makeCPS env cont cpsApply) beforeFunc []
+    Just [DynamicWinders beforeFunc _] -> apply (makeCPS env cont cpsApply) beforeFunc []
     _ -> doApply env cont
  where
    cpsApply :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
@@ -945,9 +935,9 @@
     Continuation cEnv _ _ _ _ -> continueEval cEnv cont result
     _ -> return result
 apply cont (Func aparams avarargs abody aclosure) args =
-  if num aparams /= num args && avarargs == Nothing
+  if num aparams /= num args && isNothing avarargs
      then throwError $ NumArgs (Just (num aparams)) args
-     else (liftIO $ extendEnv aclosure $ zip (map ((,) varNamespace) aparams) args) >>= bindVarArgs avarargs >>= (evalBody abody)
+     else liftIO (extendEnv aclosure $ zip (map ((,) varNamespace) aparams) args) >>= bindVarArgs avarargs >>= (evalBody abody)
   where remainingArgs = drop (length aparams) args
         num = toInteger . length
         --
@@ -963,24 +953,24 @@
         -- See: http://icem-www.folkwang-hochschule.de/~finnendahl/cm_kurse/doc/schintro/schintro_142.html#SEC294
         --
         evalBody evBody env = case cont of
-            Continuation _ (Just (SchemeBody cBody)) (Just cCont) _ cDynWind -> if length cBody == 0
-                then continueWCont env (evBody) cCont cDynWind
+            Continuation _ (Just (SchemeBody cBody)) (Just cCont) _ cDynWind -> if null cBody
+                then continueWCont env evBody cCont cDynWind
 -- else continueWCont env (evBody) cont (trace ("cDynWind = " ++ show cDynWind) cDynWind) -- Might be a problem, not fully optimizing
-                else continueWCont env (evBody) cont cDynWind -- Might be a problem, not fully optimizing
-            Continuation _ _ _ _ cDynWind -> continueWCont env (evBody) cont cDynWind
-            _ -> continueWCont env (evBody) cont Nothing
+                else continueWCont env evBody cont cDynWind -- Might be a problem, not fully optimizing
+            Continuation _ _ _ _ cDynWind -> continueWCont env evBody cont cDynWind
+            _ -> continueWCont env evBody cont Nothing
 
         -- Shortcut for calling continueEval
         continueWCont cwcEnv cwcBody cwcCont cwcDynWind =
             continueEval cwcEnv (Continuation cwcEnv (Just (SchemeBody cwcBody)) (Just cwcCont) Nothing cwcDynWind) $ Nil ""
 
         bindVarArgs arg env = case arg of
-          Just argName -> liftIO $ extendEnv env [((varNamespace, argName), List $ remainingArgs)]
+          Just argName -> liftIO $ extendEnv env [((varNamespace, argName), List remainingArgs)]
           Nothing -> return env
 apply cont (HFunc aparams avarargs abody aclosure) args =
-  if num aparams /= num args && avarargs == Nothing
+  if num aparams /= num args && isNothing avarargs
      then throwError $ NumArgs (Just (num aparams)) args
-     else (liftIO $ extendEnv aclosure $ zip (map ((,) varNamespace) aparams) args) >>= bindVarArgs avarargs >>= (evalBody abody)
+     else liftIO (extendEnv aclosure $ zip (map ((,) varNamespace) aparams) args) >>= bindVarArgs avarargs >>= (evalBody abody)
   where remainingArgs = drop (length aparams) args
         num = toInteger . length
         evalBody evBody env = evBody env cont (Nil "") (Just [])
@@ -1013,7 +1003,7 @@
 --  probably be more useful.
 primitiveBindings :: IO Env
 primitiveBindings = nullEnv >>= 
-    (flip extendEnv $ map (domakeFunc IOFunc) ioPrimitives
+    flip extendEnv  ( map (domakeFunc IOFunc) ioPrimitives
                    ++ map (domakeFunc EvalFunc) evalFunctions
                    ++ map (domakeFunc PrimitiveFunc) primitives)
   where domakeFunc constructor (var, func) = 
@@ -1052,7 +1042,7 @@
   
   -- Load standard library
   features <- getHuskFeatures
-  _ <- evalString env $ "(define *features* '" ++ (show $ List features) ++ ")"
+  _ <- evalString env $ "(define *features* '" ++ show (List features) ++ ")"
   _ <- evalString env $ "(load \"" ++ (escapeBackslashes stdlib) ++ "\")" 
 
   -- Load (require-extension), which can be used to load other SRFI's
@@ -1073,8 +1063,6 @@
   timeEnv <- liftIO $ r7rsTimeEnv
   _ <- evalLisp' metaEnv $ List [Atom "add-module!", List [Atom "quote", List [Atom "scheme", Atom "time", Atom "posix"]], List [Atom "make-module", Bool False, LispEnv timeEnv, List [Atom "quote", List []]]]
 
-  processContextEnv <- liftIO $ r7rsProcessContextEnv
-  _ <- evalLisp' metaEnv $ List [Atom "add-module!", List [Atom "quote", List [Atom "scheme", Atom "process-context"]], List [Atom "make-module", Bool False, LispEnv processContextEnv, List [Atom "quote", List []]]]
   _ <- evalLisp' metaEnv $ List [
     Atom "define", 
     Atom "library-exists?",
@@ -1108,7 +1096,7 @@
   -- Load necessary libraries
   -- Unfortunately this adds them in the top-level environment (!!)
   features <- getHuskFeatures
-  _ <- evalString env $ "(define *features* '" ++ (show $ List features) ++ ")"
+  _ <- evalString env $ "(define *features* '" ++ show (List features) ++ ")"
   cxr <- PHS.getDataFileName "lib/cxr.scm"
   _ <- evalString env {-baseEnv-} $ "(load \"" ++ (escapeBackslashes cxr) ++ "\")" 
   core <- PHS.getDataFileName "lib/core.scm"
@@ -1130,8 +1118,6 @@
   timeEnv <- liftIO $ r7rsTimeEnv
   _ <- evalLisp' metaEnv $ List [Atom "add-module!", List [Atom "quote", List [Atom "scheme", Atom "time", Atom "posix"]], List [Atom "make-module", Bool False, LispEnv timeEnv, List [Atom "quote", List []]]]
 
-  processContextEnv <- liftIO $ r7rsProcessContextEnv
-  _ <- evalLisp' metaEnv $ List [Atom "add-module!", List [Atom "quote", List [Atom "scheme", Atom "process-context"]], List [Atom "make-module", Bool False, LispEnv processContextEnv, List [Atom "quote", List []]]]
   _ <- evalLisp' metaEnv $ List [
     Atom "define", 
     Atom "library-exists?",
@@ -1148,14 +1134,6 @@
      (flip extendEnv 
            [ ((varNamespace, "current-second"), IOFunc currentTimestamp)])
 
-r7rsProcessContextEnv :: IO Env
-r7rsProcessContextEnv = do
-    nullEnv >>= 
-     (flip extendEnv 
-           [ 
-           -- TODO: need a lot more here, this is just a stub
-           ((varNamespace, "exit"), IOFunc evalfuncExitFail)])
-
 -- Functions that extend the core evaluator, but that can be defined separately.
 --
 {- These functions have access to the current environment via the
@@ -1192,10 +1170,13 @@
                                             (Just (Continuation ce cc cnc ca
                                                                 Nothing))
                                              Nothing
-                                             (Just ([DynamicWinders beforeFunc afterFunc]))) -- FUTURE: append if existing winders
+                                             (Just [DynamicWinders beforeFunc afterFunc])) -- FUTURE: append if existing winders
                                thunkFunc []
    cpsThunk _ _ _ _ = throwError $ Default "Unexpected error in cpsThunk during (dynamic-wind)"
-   cpsAfter _ c _ _ = apply c afterFunc [] -- FUTURE: remove dynamicWinder from above from the list before calling after
+   cpsAfter _ c value _ = do
+    let cpsRetVals :: Env -> LispVal -> LispVal -> Maybe [LispVal] -> IOThrowsError LispVal
+        cpsRetVals e cc _ _ = continueEval e cc value
+    apply (makeCPS env c cpsRetVals) afterFunc [] -- FUTURE: remove dynamicWinder from above from the list before calling after
 evalfuncDynamicWind (_ : args) = throwError $ NumArgs (Just 3) args -- Skip over continuation argument
 evalfuncDynamicWind _ = throwError $ NumArgs (Just 3) []
 
@@ -1209,7 +1190,7 @@
 evalfuncCallWValues _ = throwError $ NumArgs (Just 2) []
 
 --evalfuncApply [cont@(Continuation _ _ _ _ _), func, List args] = apply cont func args
-evalfuncApply (cont@(Continuation _ _ _ _ _) : func : args) = do
+evalfuncApply (cont@(Continuation {}) : func : args) = do
   let aRev = reverse args
 
   if null args
@@ -1228,12 +1209,12 @@
 
 
 evalfuncMakeEnv (cont@(Continuation env _ _ _ _) : _) = do
-    e <- liftIO $ nullEnv
+    e <- liftIO nullEnv
     continueEval env cont $ LispEnv e
 evalfuncMakeEnv _ = throwError $ NumArgs (Just 1) []
 
 evalfuncNullEnv [cont@(Continuation env _ _ _ _), Number _] = do
-    nilEnv <- liftIO $ primitiveBindings
+    nilEnv <- liftIO primitiveBindings
     continueEval env cont $ LispEnv nilEnv
 evalfuncNullEnv (_ : args) = throwError $ NumArgs (Just 1) args -- Skip over continuation argument
 evalfuncNullEnv _ = throwError $ NumArgs (Just 1) []
@@ -1243,9 +1224,7 @@
 evalfuncInteractionEnv _ = throwError $ InternalError ""
 
 evalfuncUseParentEnv ((Continuation env a b c d) : _) = do
-    let parEnv = case parentEnv env of
-                      Just env' -> env'
-                      Nothing -> env
+    let parEnv = fromMaybe env (parentEnv env)
     continueEval parEnv (Continuation parEnv a b c d) $ LispEnv parEnv
 evalfuncUseParentEnv _ = throwError $ InternalError ""
 
@@ -1288,7 +1267,7 @@
         (LispEnv newEnv)
 
 -- This is just for debugging purposes:
-evalfuncImport ((Continuation _ _ _ _ _ ) : cs) = do
+evalfuncImport ((Continuation {} ) : cs) = do
     throwError $ TypeMismatch "import fields" $ List cs
 evalfuncImport _ = throwError $ InternalError ""
 
@@ -1310,12 +1289,11 @@
 
 evalfuncLoad [cont@(Continuation env _ _ _ _), String filename] = do
     filename' <- findFileOrLib filename
-    results <- load filename' >>= mapM (evaluate env (makeNullContinuation env))
+    results <- load filename' >>= mapM (meval env (makeNullContinuation env))
     if not (null results)
        then do result <- return . last $ results
                continueEval env cont result
        else return $ Nil "" -- Empty, unspecified value
-  where evaluate env2 cont2 val2 = meval env2 cont2 val2
 
 evalfuncLoad (_ : args) = throwError $ NumArgs (Just 1) args -- Skip over continuation argument
 evalfuncLoad _ = throwError $ NumArgs (Just 1) []
@@ -1330,15 +1308,15 @@
 evalfuncEval [cont@(Continuation env _ _ _ _), val] = do
     v <- derefPtr val -- Must deref ptrs for macro subsystem
     meval env cont v
-evalfuncEval [cont@(Continuation _ _ _ _ _), val, LispEnv env] = do
+evalfuncEval [cont@(Continuation {}), val, LispEnv env] = do
     v <- derefPtr val -- Must deref ptrs for macro subsystem
     meval env cont v
 evalfuncEval (_ : args) = throwError $ NumArgs (Just 1) args -- Skip over continuation argument
 evalfuncEval _ = throwError $ NumArgs (Just 1) []
 
-evalfuncCallCC [cont@(Continuation _ _ _ _ _), func] = do
+evalfuncCallCC [cont@(Continuation {}), func] = do
    case func of
-     Continuation _ _ _ _ _ -> apply cont func [cont] 
+     Continuation {} -> apply cont func [cont] 
      PrimitiveFunc f -> do
          result <- liftThrows $ f [cont]
          case cont of
@@ -1346,12 +1324,12 @@
              _ -> return result
      Func _ (Just _) _ _ -> apply cont func [cont] -- Variable # of args (pair). Just call into cont
      Func aparams _ _ _ ->
-       if (toInteger $ length aparams) == 1
+       if toInteger (length aparams) == 1
          then apply cont func [cont]
          else throwError $ NumArgs (Just (toInteger $ length aparams)) [cont]
      HFunc _ (Just _) _ _ -> apply cont func [cont] -- Variable # of args (pair). Just call into cont  
      HFunc aparams _ _ _ ->
-       if (toInteger $ length aparams) == 1
+       if toInteger (length aparams) == 1
          then apply cont func [cont]
          else throwError $ NumArgs (Just (toInteger $ length aparams)) [cont]
      other -> throwError $ TypeMismatch "procedure" other
@@ -1359,10 +1337,10 @@
 evalfuncCallCC _ = throwError $ NumArgs (Just 1) []
 
 evalfuncExitFail _ = do
-  _ <- liftIO $ System.Exit.exitFailure
+  _ <- liftIO System.Exit.exitFailure
   return $ Nil ""
 evalfuncExitSuccess _ = do
-  _ <- liftIO $ System.Exit.exitSuccess
+  _ <- liftIO System.Exit.exitSuccess
   return $ Nil ""
 
 {- Primitive functions that extend the core evaluator -}
diff --git a/hs-src/Language/Scheme/Environments.hs b/hs-src/Language/Scheme/Environments.hs
--- a/hs-src/Language/Scheme/Environments.hs
+++ b/hs-src/Language/Scheme/Environments.hs
@@ -67,7 +67,7 @@
                 ("read-bytevector", readByteVector),
                 ("read-string", readString),
                 ("peek-char", readCharProc hLookAhead),
-                ("write", writeProc (\ port obj -> hPrint port obj)),
+                ("write", writeProc hPrint),
                 ("write-char", writeCharProc),
                 ("write-bytevector", writeByteVector),
                 ("write-string", writeString),
@@ -99,6 +99,7 @@
               ("pair?", isDottedList),
               ("list?", unaryOp' isList),
               ("vector?", unaryOp' isVector),
+              ("record?", unaryOp' isRecord),
               ("null?", isNull),
               ("string?", isString),
 
@@ -152,6 +153,7 @@
                 ("read-all", readAll),
                 ("find-module-file", findModuleFile),
                 ("system", system),
+                ("get-environment-variables", getEnvVars),
 --                ("system-read", systemRead),
                 ("gensym", gensym)]
 
diff --git a/hs-src/Language/Scheme/Libraries.hs b/hs-src/Language/Scheme/Libraries.hs
--- a/hs-src/Language/Scheme/Libraries.hs
+++ b/hs-src/Language/Scheme/Libraries.hs
@@ -26,31 +26,9 @@
     :: [LispVal]
     -> IOThrowsError LispVal
 findModuleFile [p@(Pointer _ _)] = recDerefPtrs p >>= box >>= findModuleFile
-findModuleFile [String file] 
--- This is no longer required since load has been enhanced to
--- attempt to load a file from 'lib' if it does not exist
---    -- Built-in modules
---    | --file == "scheme/r5rs/base.sld" ||
---      --file == "scheme/r5rs/char.sld" ||
---      --file == "scheme/r5rs/complex.sld" ||
---      --file == "scheme/r5rs/cxr.sld" ||
---      --file == "scheme/r5rs/eval.sld" ||
---      --file == "scheme/r5rs/file.sld" ||
---      --file == "scheme/r5rs/inexact.sld" ||
---      --file == "scheme/r5rs/lazy.sld" ||
---      --file == "scheme/r5rs/load.sld" ||
---      --file == "scheme/r5rs/read.sld" ||
---      --file == "scheme/r5rs/write.sld" ||
---      --file == "scheme/base.sld" ||
---      file == "husk/pretty-print.sld" ||
----- TODO: scheme case-lambda (r7rs)
----- TODO: scheme process-context (r7rs)
----- TODO: scheme repl (r7rs)
---      file == "scheme/time.sld" ||
---      file == "scheme/write.sld" = do
---        path <- liftIO $ PHS.getDataFileName $ "lib/" ++ file
---        return $ String path
-    | otherwise = return $ String file
+findModuleFile [String file] = do
+    --- Good enough now that load searches 'lib' if file not found
+    return $ String file
 findModuleFile _ = return $ Bool False
 
 -- |Import definitions from one environment into another
@@ -82,9 +60,8 @@
     -> IOThrowsError LispVal
 divertBinding to from nameOrig nameNew = do
   isMacroBound <- liftIO $ isNamespacedRecBound from macroNamespace nameOrig
-  namespace <- liftIO $ case isMacroBound of
-                          True -> return macroNamespace
-                          _ -> return varNamespace
+  namespace <- liftIO $ if isMacroBound then return macroNamespace
+                                        else return varNamespace
   m <- getNamespacedVar from namespace nameOrig
   defineNamespacedVar to namespace nameNew m
 
diff --git a/hs-src/Language/Scheme/Macro.hs b/hs-src/Language/Scheme/Macro.hs
--- a/hs-src/Language/Scheme/Macro.hs
+++ b/hs-src/Language/Scheme/Macro.hs
@@ -145,7 +145,7 @@
   -- DEBUG: var <- (trace ("expand: " ++ x) getNamespacedVar') env macroNamespace x
   case var of
     -- Explicit Renaming
-    Just (SyntaxExplicitRenaming transformer@(Func _ _ _ _)) -> do
+    Just (SyntaxExplicitRenaming transformer@(Func {})) -> do
       renameEnv <- liftIO $ nullEnv -- Local environment used just for this
       expanded <- explicitRenamingTransform env renameEnv renameEnv 
                                           lisp transformer apply
@@ -174,7 +174,7 @@
     Nothing -> return lisp
 
 -- No macro to process, just return code as it is...
-_macroEval _ lisp@(_) _ = return lisp
+_macroEval _ lisp _ = return lisp
 
 {-
  - Given input and syntax-rules, determine if any rule is a match and transform it.
@@ -205,12 +205,12 @@
   localEnv <- liftIO $ nullEnv -- Local environment used just for this invocation
                                -- to hold pattern variables
   result <- matchRule defEnv env divertEnv dim identifiers localEnv renameEnv cleanupEnv rule input esym
-  case (result) of
+  case result of
     -- No match, check the next rule
     Nil _ -> macroTransform defEnv env divertEnv renameEnv cleanupEnv dim identifiers rs input apply esym
     _ -> do
         -- Walk the resulting code, performing the Clinger algorithm's 4 components
-        walkExpanded defEnv env divertEnv renameEnv cleanupEnv dim True False (List []) (result) apply
+        walkExpanded defEnv env divertEnv renameEnv cleanupEnv dim True False (List []) result apply
 
 -- Ran out of rules to match...
 macroTransform _ _ _ _ _ _ _ _ input _ _ = throwError $ BadSpecialForm "Input does not match a macro pattern" input
@@ -218,9 +218,7 @@
 -- Determine if the next element in a list matches 0-to-n times due to an ellipsis
 macroElementMatchesMany :: LispVal -> String -> Bool
 macroElementMatchesMany (List (_ : ps)) ellipsisSym = do
-  if not (null ps)
-     then (head ps) == (Atom ellipsisSym)
-     else False
+  not (null ps) && ((head ps) == (Atom ellipsisSym))
 macroElementMatchesMany _ _ = False
 
 {- Given input, determine if that input matches any rules
@@ -254,14 +252,14 @@
                                   (List $ ds ++ [d, Atom esym])
                                   (List is)
                                    0 []
-                                  (flagDottedLists [] (False, False) 0)
+                                  (flagDottedLists [] (False, False) $ 0 + (length $ filter (filterEsym esym) ds)) -- Mark any ellipsis we are passing over
                                   esym
        (List _ : _) -> do 
          loadLocal defEnv outerEnv divertEnv localEnv renameEnv identifiers 
                                   (List $ ds ++ [d, Atom esym])
                                   (List is)
                                    0 []
-                                  (flagDottedLists [] (True, False) 0)
+                                  (flagDottedLists [] (True, False) $ 0 + (length $ filter (filterEsym esym) ds)) -- Mark any ellipsis we are passing over
                                   esym
        _ -> loadLocal defEnv outerEnv divertEnv localEnv renameEnv identifiers (List ps) (List is) 0 [] [] esym
 
@@ -275,6 +273,7 @@
 in preparation for macro transformation. -}
 loadLocal :: Env -> Env -> Env -> Env -> Env -> LispVal -> LispVal -> LispVal -> Int -> [Int] -> [(Bool, Bool)] -> String -> IOThrowsError LispVal
 loadLocal defEnv outerEnv divertEnv localEnv renameEnv identifiers pattern input ellipsisLevel ellipsisIndex listFlags esym = do
+  --case (trace ("loadLocal [" ++ (show pattern) ++ "] [" ++ (show input) ++ "] flags = " ++ (show listFlags) ++ " ...lvl = " ++ (show ellipsisLevel) ++ " ...indx = " ++ (show ellipsisIndex)) (pattern, input)) of
   case (pattern, input) of
 
        ((DottedList ps p), (DottedList isRaw iRaw)) -> do
@@ -289,13 +288,13 @@
          result <- loadLocal defEnv outerEnv divertEnv localEnv renameEnv identifiers (List ps) (List is) ellipsisLevel ellipsisIndex listFlags esym
          case result of
             Bool True -> --  By matching on an elipsis we force the code 
-                         --  to match pagainst all elements in i. 
+                         --  to match p against all elements in i. 
                          loadLocal defEnv outerEnv divertEnv localEnv renameEnv identifiers 
                                   (List $ [p, Atom esym]) 
                                   (List i)
                                    ellipsisLevel -- Incremented in the list/list match below
                                    ellipsisIndex
-                                   (flagDottedLists listFlags (True, True) $ length ellipsisIndex)
+                                   (flagDottedLists listFlags (True, True) $ length ellipsisIndex) -- Do not think we need to flag ... that are passed over, since this is a direct comparison of both cdr's
                                    esym
             _ -> return $ Bool False
 
@@ -315,8 +314,8 @@
                       else ellipsisIndex
 
          -- At this point we know if the input is part of an ellipsis, so set the level accordingly 
-         status <- checkLocal defEnv outerEnv divertEnv (localEnv) renameEnv identifiers level idx p i listFlags esym
-         case (status) of
+         status <- checkLocal defEnv outerEnv divertEnv localEnv renameEnv identifiers level idx p i listFlags esym
+         case status of
               -- No match
               Bool False -> if nextHasEllipsis
                                 {- No match, must be finished with ...
@@ -397,7 +396,7 @@
 flagUnmatchedAtom defEnv outerEnv localEnv identifiers p improperListFlag = do
   isDefined <- liftIO $ isBound localEnv p
   isIdent <- findAtom (Atom p) identifiers
-  if isDefined 
+  if isDefined
      -- Var already defined, skip it...
      then continueFlagging
      else case isIdent of
@@ -427,12 +426,12 @@
 flagDottedLists listFlags status lengthOfEllipsisIndex
  | length listFlags == lengthOfEllipsisIndex = listFlags ++ [status]
    -- Pad the original list with False flags, and append our status flags at the end
- | otherwise = listFlags ++ (replicate ((lengthOfEllipsisIndex) - (length listFlags)) (False, False)) ++ [status]
+ | otherwise = listFlags ++ (replicate (lengthOfEllipsisIndex - (length listFlags)) (False, False)) ++ [status]
 
 -- Get pair of list flags that are at depth of ellipIndex, or False if flags do not exist (means improper not flagged)
 getListFlags :: [Int] -> [(Bool, Bool)] -> (Bool, Bool)
 getListFlags elIndices flags 
-  | length elIndices > 0 && length flags >= length elIndices = flags !! ((length elIndices) - 1)
+  | not (null elIndices) && length flags >= length elIndices = flags !! ((length elIndices) - 1)
   | otherwise = (False, False)
 
 -- ^ Check pattern against input to determine if there is a match
@@ -464,13 +463,13 @@
   -- its occurrence in the macro expression and its occurrence in the macro definition 
   -- have the same lexical binding, or the two identifiers are equal and both have no 
   -- lexical binding.
-  isRenamed <- liftIO $ isRecBound renameEnv (pattern)
+  isRenamed <- liftIO $ isRecBound renameEnv pattern
   doesIdentMatch <- identifierMatches defEnv outerEnv pattern
   match <- haveMatch isRenamed doesIdentMatch
 
   if match == 0 
      then return $ Bool False
-     else if (ellipsisLevel) > 0
+     else if ellipsisLevel > 0
              -- Var is part of a 0-to-many match, store up in a list...
              then do isDefined <- liftIO $ isBound localEnv pattern
                      if match == 1 -- Literal identifier
@@ -493,7 +492,7 @@
                         i' <- getOrigName renameEnv inpt
                         pl <- isLexicallyDefined outerEnv renameEnv pattern
                         il <- isLexicallyDefined outerEnv renameEnv inpt
-                        if (((pattern == inpt && (doesIdentMatch)) && (not isRenamed)) || 
+                        if (((pattern == inpt && doesIdentMatch) && (not isRenamed)) || 
                             -- Equal and neither have a lexical binding, per spec
                             (p' == i' && (not pl) && (not il)))
                            then return 1
@@ -514,7 +513,7 @@
       addPatternVar isDefined ellipLevel ellipIndex pat val
         | isDefined = do v <- getVar localEnv pat
 --                         case (trace ("addPV pat = " ++ show pat ++ " v = " ++ show v) v) of
-                         case (v) of
+                         case v of
                             Nil _ -> do
                               -- What's going on here is that the pattern var was found
                               -- before but not set as a pattern variable because it
@@ -554,13 +553,18 @@
                                   input
                                    ellipsisLevel -- Incremented in the list/list match below
                                    ellipsisIndex
-                                   (flagDottedLists flags (True, False) $ length ellipsisIndex) 
+                                   (flagDottedLists flags (True, False) $ (length ellipsisIndex) + (length $ filter (filterEsym esym) ps)) -- Mark any ellipsis in the list that we are passing over
                                    esym
 checkLocal defEnv outerEnv divertEnv localEnv renameEnv identifiers ellipsisLevel ellipsisIndex pattern@(List _) input@(List _) flags esym =
   loadLocal defEnv outerEnv divertEnv localEnv renameEnv identifiers pattern input ellipsisLevel ellipsisIndex flags esym
 
 checkLocal _ _ _ _ _ _ _ _ _ _ _ _ = return $ Bool False
 
+-- |Helper for filter, remove all lispvals that are not the ellipsis marker
+filterEsym :: String -> LispVal -> Bool
+filterEsym esym (Atom a) = esym == a
+filterEsym _ _ = False
+
 -- |Determine if an identifier in a pattern matches an identifier of the same
 --  name in the input.
 --
@@ -649,25 +653,26 @@
    _ -> do
     -- Determine if we should recursively rename an atom
     -- This code is a bit of a hack/mess at the moment
-    if  a == aa -- Prevent an infinite loop
-        -- Preserve keywords encountered in the macro 
-        -- as each of these is really a special form, and renaming them
-        -- would not work because there is nothing to divert back...
-        || a == "if"
-        || a == "let-syntax" 
-        || a == "letrec-syntax" 
-        || a == "define-syntax" 
-        || a == "define"  
-        || a == "set!"
-        || a == "lambda"
-        || a == "quote"
-        || a == "expand"
-        || a == "string-set!"
-        || a == "set-car!"
-        || a == "set-cdr!"
-        || a == "vector-set!"
-        || a == "hash-table-set!"
-        || a == "hash-table-delete!"
+    if  (a `elem` 
+           [ aa -- Prevent an infinite loop
+           -- Preserve keywords encountered in the macro 
+           -- as each of these is really a special form, and renaming them
+           -- would not work because there is nothing to divert back...
+           , "if"
+           , "let-syntax" 
+           , "letrec-syntax" 
+           , "define-syntax" 
+           , "define"  
+           , "set!"
+           , "lambda"
+           , "quote"
+           , "expand"
+           , "string-set!"
+           , "set-car!"
+           , "set-cdr!"
+           , "vector-set!"
+           , "hash-table-set!"
+           , "hash-table-delete!"])
        then walkExpandedAtom defEnv useEnv divertEnv renameEnv cleanupEnv 
                              dim startOfList inputIsQuoted (List result) a ts isQuoted maybeMacro apply
        else walkExpanded defEnv useEnv divertEnv renameEnv cleanupEnv 
@@ -839,7 +844,7 @@
 --    env <- liftIO $ extendEnv (trace ("found procedure abstraction, vars = " ++ show vars ++ "body = " ++ show fbody) renameEnv) []
     env <- liftIO $ extendEnv renameEnv []
     renamedVars <- markBoundIdentifiers env cleanupEnv vars []
-    walkExpanded defEnv useEnv divertEnv env cleanupEnv dim True False (List [Atom "lambda", (renamedVars)]) (List fbody) apply
+    walkExpanded defEnv useEnv divertEnv env cleanupEnv dim True False (List [Atom "lambda", renamedVars]) (List fbody) apply
 
 walkExpandedAtom defEnv useEnv divertEnv renameEnv cleanupEnv dim True _ (List result) a@"lambda" ts False _ apply = do
     -- lambda is malformed, just transform as normal atom...
@@ -932,19 +937,18 @@
   isDefined <- getVar' renameEnv a
   case isDefined of
     Just expanded -> do
-       case isRec of
-         True  -> _expandAtom isRec renameEnv expanded
-         False -> return expanded
+       if isRec then _expandAtom isRec renameEnv expanded
+                else return expanded
     Nothing -> return $ Atom a 
 _expandAtom _ _ a = return a
 
 -- |Recursively expand an atom that may have been renamed multiple times
 recExpandAtom :: Env -> LispVal -> IOThrowsError LispVal
-recExpandAtom renameEnv a = _expandAtom True renameEnv a
+recExpandAtom = _expandAtom True
 
 -- |Expand an atom
 expandAtom :: Env -> LispVal -> IOThrowsError LispVal
-expandAtom renameEnv a = _expandAtom False renameEnv a
+expandAtom = _expandAtom False
 
 -- |Clean up any remaining renamed variables in the expanded code
 --  Only needed in special circumstances to deal with quoting.
@@ -1173,17 +1177,17 @@
 
                       Nil "" -> -- No matches, keep going
                                 continueTransform defEnv outerEnv divertEnv localEnv renameEnv cleanupEnv dim identifiers esym ellipsisLevel ellipsisIndex result $ tail ts
-                      v@(_) -> transformRule defEnv outerEnv divertEnv localEnv renameEnv cleanupEnv dim identifiers esym ellipsisLevel ellipsisIndex (List $ result ++ [v]) (List $ tail ts)
+                      v -> transformRule defEnv outerEnv divertEnv localEnv renameEnv cleanupEnv dim identifiers esym ellipsisLevel ellipsisIndex (List $ result ++ [v]) (List $ tail ts)
              else -- Matched 0 times, skip it
                   transformRule defEnv outerEnv divertEnv localEnv renameEnv cleanupEnv dim identifiers esym ellipsisLevel ellipsisIndex (List result) (List $ tail ts)
 
     noEllipsis isDefined = do
       isImproperPattern <- loadNamespacedBool 'p' -- "improper pattern"
       isImproperInput <- loadNamespacedBool 'i' -- "improper input"
-      t <- if (isDefined)
+      t <- if isDefined
               then do
                    var <- getVar localEnv a
-                   case (var) of
+                   case var of
                      Nil "" -> do 
                         -- Fix for issue #42: A 0 match case for var (input ran out in pattern), flag to calling code
                         --
@@ -1197,8 +1201,7 @@
                             Bool True -> return $ Nil "var (pair) not defined in pattern"
                             _ -> return $ Nil "var not defined in pattern"
 -- TODO: I think the outerEnv should be accessed by the walker, and not within rewrite as is done below...
-                     Nil input -> do v <- getVar outerEnv input
-                                     return v
+                     Nil input -> getVar outerEnv input
                      List _ -> do
                           if ellipsisLevel > 0
                                   then -- Take all elements, instead of one-at-a-time
@@ -1206,9 +1209,7 @@
                                                            isImproperPattern 
                                                            isImproperInput 
                                   else return var -- no ellipsis, just return elements directly, so all can be appended
-                     _ -> if ellipsisLevel > 0
-                             then return var -- Let this pass, in case var is not involved in o-to-n match
-                             else return var
+                     _ -> return var
               else do
                   -- Rename each encountered symbol, but the trick is that we want to give
                   -- the same symbol the same new name if it is found more than once, so...
@@ -1224,7 +1225,7 @@
                        _ <- defineNamespacedVar renameEnv 'r' {-"renamed"-} a $ Atom renamed
                        -- Keep track of vars that are renamed; maintain reverse mapping
                        _ <- defineVar cleanupEnv renamed $ Atom a -- Global record for final cleanup of macro
-                       _ <- defineVar (renameEnv) renamed $ Atom a -- Keep for Clinger
+                       _ <- defineVar renameEnv renamed $ Atom a -- Keep for Clinger
 --                       return $ Atom (trace ("macro call renamed " ++ a ++ " to " ++ renamed) renamed)
                        return $ Atom renamed
       case t of
@@ -1393,7 +1394,7 @@
                           ellipsisIndex 
                          (List result) 
                          (List $ remaining)
-       else if length result > 0 
+       else if not (null result)
                then return $ List result
                else if ellipsisLevel > 0 
                        then return $ Nil ""  -- Nothing remains, no match
diff --git a/hs-src/Language/Scheme/Macro/Matches.hs b/hs-src/Language/Scheme/Macro/Matches.hs
--- a/hs-src/Language/Scheme/Macro/Matches.hs
+++ b/hs-src/Language/Scheme/Macro/Matches.hs
@@ -46,7 +46,7 @@
      then Nil "" -- Error: there are not enough elements in the list
      else do
        let lst = drop i lData
-       if length lst > 0
+       if not (null lst)
           then getData (head lst) is
           else Nil "" -- Error: not enough elements in list
 getData val [] = val -- Base case: we have found the requested element
@@ -62,9 +62,10 @@
 setData (List lData) (i:is) val = do
   -- Fill "holes" as long as they are not at the leaves.
   --
-  -- This is because, when a match occurs it happens 0 or more times.
-  -- Therefore it is not possible (at the leaves) for a match to occur where that match is not
-  -- placed at the end of the list. For example, if the pattern is:
+  -- This is because,  when a match occurs it happens 0 or more  times.
+  -- Therefore it is not  possible (at the leaves) for a match to occur 
+  -- where that match is not placed at the end of the list. For example
+  -- if the pattern is:
   --
   -- a ...
   --
@@ -72,9 +73,10 @@
   --
   -- 1 2 3
   --
-  -- Then we always store the first match in position 0, second in 1, etc. There are no holes
-  -- in this case because there is never a reason to skip any of these positions.
-  if length is > 0 && length lData < i + 1 
+  -- Then we always store the first match in position 0, second in 1, etc. 
+  -- There  are no  holes  in this  case  because there is never a  reason 
+  -- to skip any of these positions.
+  if not (null is) && length lData < i + 1 
      then set $ fill lData $ i + 1
      else set lData
 
@@ -89,16 +91,16 @@
                    then List $ (fst content) ++ [val] ++ [c] -- Base case - Requested pos must be one less than c
                    else List $ (fst content) ++ [setData c is val]
       (c:cs) -> if length is < 1
-                   then List $ (fst content) ++ [val] ++ [c] ++ (cs) -- Base case - Requested pos must be one less than c
-                   else List $ (fst content) ++ [setData c is val] ++ (cs) 
+                   then List $ (fst content) ++ [val] ++ [c] ++ cs -- Base case - Requested pos must be one less than c
+                   else List $ (fst content) ++ [setData c is val] ++ cs 
 
 setData _ _ val = val -- Should never be reached; just return val
 
 -- |Compare actual input with expected
 _cmp :: LispVal -> LispVal -> IO ()
 _cmp input expected = do
-  putStrLn $ show input
-  putStrLn $ show $ assert (eqVal expected input) input
+  print input
+  print (assert (eqVal expected input) input)
 
 -- |Run this function to test the above code
 _test :: IO ()
diff --git a/hs-src/Language/Scheme/Numerical.hs b/hs-src/Language/Scheme/Numerical.hs
--- a/hs-src/Language/Scheme/Numerical.hs
+++ b/hs-src/Language/Scheme/Numerical.hs
@@ -146,21 +146,20 @@
 numDiv [Complex n] = return $ Complex $ 1 / n
 numDiv aparams = do
   foldl1M (\ a b -> doDiv =<< (numCast [a, b])) aparams
-  where doDiv (List [(Number a), (Number b)]) = if b == 0
-                                                   then throwError $ DivideByZero
-                                                   else if (mod a b) == 0
-                                                           then return $ Number $ div a b
-                                                           -- Convert to a rational if the result is not an integer
-                                                           else return $ Rational $ (fromInteger a) / (fromInteger b)
-        doDiv (List [(Float a), (Float b)]) = if b == 0.0
-                                                   then throwError $ DivideByZero
-                                                   else return $ Float $ a / b
-        doDiv (List [(Rational a), (Rational b)]) = if b == 0
-                                                       then throwError $ DivideByZero
-                                                       else return $ Rational $ a / b
-        doDiv (List [(Complex a), (Complex b)]) = if b == 0
-                                                       then throwError $ DivideByZero
-                                                       else return $ Complex $ a / b
+  where doDiv (List [(Number a), (Number b)])
+            | b == 0 = throwError $ DivideByZero
+            | (mod a b) == 0 = return $ Number $ div a b
+            | otherwise = -- Not an integer
+                return $ Rational $ (fromInteger a) / (fromInteger b)
+        doDiv (List [(Float a), (Float b)]) 
+            | b == 0.0 = throwError $ DivideByZero
+            | otherwise = return $ Float $ a / b
+        doDiv (List [(Rational a), (Rational b)])
+            | b == 0 = throwError $ DivideByZero
+            | otherwise = return $ Rational $ a / b
+        doDiv (List [(Complex a), (Complex b)])
+            | b == 0 = throwError $ DivideByZero
+            | otherwise = return $ Complex $ a / b
         doDiv _ = throwError $ Default "Unexpected error in /"
 
 -- |Take the modulus of the given numbers
@@ -531,15 +530,14 @@
 num2String [x] = throwError $ TypeMismatch "number" x
 num2String badArgList = throwError $ NumArgs (Just 1) badArgList
 
-
 -- | Determine if the given value is not a number
 isNumNaN :: [LispVal] -> ThrowsError LispVal
-isNumNaN ([Float n]) = return    $ Bool $ isNaN n
+isNumNaN ([Float n]) = return $ Bool $ isNaN n
 isNumNaN _ = return $ Bool False
 
 -- | Determine if number is infinite
 isNumInfinite :: [LispVal] -> ThrowsError LispVal
-isNumInfinite ([Float n]) = return    $ Bool $ isInfinite n
+isNumInfinite ([Float n]) = return $ Bool $ isInfinite n
 isNumInfinite _ = return $ Bool False
 
 -- | Determine if number is not infinite
diff --git a/hs-src/Language/Scheme/Parser.hs b/hs-src/Language/Scheme/Parser.hs
--- a/hs-src/Language/Scheme/Parser.hs
+++ b/hs-src/Language/Scheme/Parser.hs
@@ -172,8 +172,8 @@
   sign <- many (oneOf "-")
   num <- many1 (oneOf "01234567")
   case (length sign) of
-     0 -> return $ Number $ fst $ Numeric.readOct num !! 0
-     1 -> return $ Number $ fromInteger $ (*) (-1) $ fst $ Numeric.readOct num !! 0
+     0 -> return $ Number $ fst $ head (Numeric.readOct num)
+     1 -> return $ Number $ fromInteger $ (*) (-1) $ fst $ head (Numeric.readOct num)
      _ -> pzero
 
 -- |Parse an integer in binary notation, base 2
@@ -183,8 +183,8 @@
   sign <- many (oneOf "-")
   num <- many1 (oneOf "01")
   case (length sign) of
-     0 -> return $ Number $ fst $ Numeric.readInt 2 (`elem` "01") DC.digitToInt num !! 0
-     1 -> return $ Number $ fromInteger $ (*) (-1) $ fst $ Numeric.readInt 2 (`elem` "01") DC.digitToInt num !! 0
+     0 -> return $ Number $ fst $ head (Numeric.readInt 2 (`elem` "01") DC.digitToInt num)
+     1 -> return $ Number $ fromInteger $ (*) (-1) $ fst $ head (Numeric.readInt 2 (`elem` "01") DC.digitToInt num)
      _ -> pzero
 
 -- |Parse an integer in hexadecimal notation, base 16
@@ -194,8 +194,8 @@
   sign <- many (oneOf "-")
   num <- many1 (digit <|> oneOf "abcdefABCDEF")
   case (length sign) of
-     0 -> return $ Number $ fst $ Numeric.readHex num !! 0
-     1 -> return $ Number $ fromInteger $ (*) (-1) $ fst $ Numeric.readHex num !! 0
+     0 -> return $ Number $ fst $ head (Numeric.readHex num)
+     1 -> return $ Number $ fromInteger $ (*) (-1) $ fst $ head (Numeric.readHex num)
      _ -> pzero
 
 -- |Parser for Integer, base 10
@@ -203,7 +203,7 @@
 parseDecimalNumber = do
   _ <- try (many (string "#d"))
   sign <- many (oneOf "-")
-  num <- many1 (digit)
+  num <- many1 digit
   if (length sign) > 1
      then pzero
      else return $ (Number . read) $ sign ++ num
@@ -216,8 +216,7 @@
 parseDecimalNumberMaybeExponent :: Parser LispVal
 parseDecimalNumberMaybeExponent = do
   num <- parseDecimalNumber
-  result <- parseNumberExponent num
-  return result
+  parseNumberExponent num
 
 -- |Parse an integer in any base
 parseNumber :: Parser LispVal
@@ -231,21 +230,20 @@
 parseRealNumber :: Parser LispVal
 parseRealNumber = do
   sign <- many (oneOf "-+")
-  num <- many (digit)
+  num <- many digit
   _ <- char '.'
-  frac <- many1 (digit)
-  let dec = if length num > 0
+  frac <- many1 digit
+  let dec = if not (null num)
                then num ++ "." ++ frac
                else "0." ++ frac
   f <- case (length sign) of
-     0 -> return $ Float $ fst $ Numeric.readFloat dec !! 0
+     0 -> return $ Float $ fst $ head (Numeric.readFloat dec)
           -- Bit of a hack, but need to support the + sign as well as the minus.
      1 -> if sign == "-" 
-             then return $ Float $ (*) (-1.0) $ fst $ Numeric.readFloat dec !! 0
-             else return $ Float $ fst $ Numeric.readFloat dec !! 0
+             then return $ Float $ (*) (-1.0) $ fst $ head (Numeric.readFloat dec)
+             else return $ Float $ fst $ head (Numeric.readFloat dec)
      _ -> pzero
-  result <- parseNumberExponent f
-  return result
+  parseNumberExponent f
 
 -- | Parse the exponent section of a floating point number
 --   in scientific notation. Eg "e10" from "1.0e10"
@@ -255,7 +253,7 @@
   case (length expnt) of
     0 -> return n
     1 -> do
-      num <- try (parseDecimalNumber)
+      num <- try parseDecimalNumber
       case num of
         Number nexp -> buildResult n nexp
         _ -> pzero
@@ -273,7 +271,7 @@
     Number n -> do
       _ <- char '/'
       sign <- many (oneOf "-")
-      num <- many1 (digit)
+      num <- many1 digit
       if (length sign) > 1
          then pzero
          else do
@@ -286,14 +284,14 @@
 -- |Parse a complex number
 parseComplexNumber :: Parser LispVal
 parseComplexNumber = do
-  lispreal <- (try (parseRealNumber) <|> try (parseRationalNumber) <|> parseDecimalNumber)
+  lispreal <- (try parseRealNumber <|> try parseRationalNumber <|> parseDecimalNumber)
   let real = case lispreal of
                   Number n -> fromInteger n
                   Rational r -> fromRational r
                   Float f -> f
                   _ -> 0
   _ <- char '+'
-  lispimag <- (try (parseRealNumber) <|> try (parseRationalNumber) <|> parseDecimalNumber)
+  lispimag <- (try parseRealNumber <|> try parseRationalNumber <|> parseDecimalNumber)
   let imag = case lispimag of
                   Number n -> fromInteger n
                   Rational r -> fromRational r
@@ -326,13 +324,13 @@
     let ns = Numeric.readHex num
     case ns of
         [] -> fail $ "Unable to parse hex value " ++ show num
-        _ -> return $ DC.chr $ fst $ ns !! 0
+        _ -> return $ DC.chr $ fst $ head ns
 
 -- |Parse a string
 parseString :: Parser LispVal
 parseString = do
   _ <- char '"'
-  x <- many (parseEscapedChar <|> noneOf ("\""))
+  x <- many (parseEscapedChar <|> noneOf "\"")
   _ <- char '"'
   return $ String x
 
@@ -465,7 +463,7 @@
 --         x <- parseHashTable
 --         _ <- lexeme $ char ')'
 --         return x
-  <|> try (parseAtom)
+  <|> try parseAtom
   <|> lexeme parseString
   <|> lexeme parseBool
   <|> parseQuoted
@@ -481,9 +479,7 @@
 mainParser :: Parser LispVal
 mainParser = do
     _ <- whiteSpace
-    x <- parseExpr
--- FUTURE? (seemed to break test cases, but is supposed to be best practice?)    eof
-    return x
+    parseExpr
 
 -- |Use a parser to parse the given text, throwing an error
 --  if there is a problem parsing the text.
diff --git a/hs-src/Language/Scheme/Primitives.hs b/hs-src/Language/Scheme/Primitives.hs
--- a/hs-src/Language/Scheme/Primitives.hs
+++ b/hs-src/Language/Scheme/Primitives.hs
@@ -93,6 +93,7 @@
  , isProcedure 
  , isList 
  , isVector 
+ , isRecord
  , isByteVector
  , isNull 
  , isEOFObject 
@@ -144,14 +145,15 @@
  , readAll
  , fileExists
  , deleteFile
+ , eofObject 
  -- ** Symbol generation
  , gensym
  , _gensym
  -- ** Time
  , currentTimestamp
  -- ** System
- , eofObject 
  , system
+ , getEnvVars
 -- , systemRead
 
  ) where
@@ -173,11 +175,12 @@
 import Data.Word
 import qualified System.Cmd
 import System.Directory (doesFileExist, removeFile)
+import qualified System.Environment as SE
 import System.Exit (ExitCode(..))
 import System.IO
 import System.IO.Error
 --import System.Process (readProcess)
--- import Debug.Trace
+--import Debug.Trace
 
 #if __GLASGOW_HASKELL__ < 702
 try' = try
@@ -472,7 +475,7 @@
 --
 --   Returns: ByteVector
 readByteVector :: [LispVal] -> IOThrowsError LispVal
-readByteVector args = readBuffer args (\ inBytes -> ByteVector inBytes)
+readByteVector args = readBuffer args ByteVector
 
 -- | Read a string from the given port
 --
@@ -483,7 +486,7 @@
 --
 --   Returns: String
 readString :: [LispVal] -> IOThrowsError LispVal
-readString args = readBuffer args (\ inBytes -> String $ BSU.toString inBytes)
+readString args = readBuffer args (String . BSU.toString)
 
 -- |Helper function to read n bytes from a port into a buffer
 readBuffer :: [LispVal] -> (BSU.ByteString -> LispVal) -> IOThrowsError LispVal
@@ -1162,7 +1165,7 @@
 --   Returns: Bool - True if found, False otherwise
 --
 hashTblExists :: [LispVal] -> ThrowsError LispVal
-hashTblExists [(HashTable ht), key@(_)] = do
+hashTblExists [(HashTable ht), key] = do
   case Data.Map.lookup key ht of
     Just _ -> return $ Bool True
     Nothing -> return $ Bool False
@@ -1181,11 +1184,11 @@
 --   Returns: Object containing the key's value
 --
 hashTblRef :: [LispVal] -> ThrowsError LispVal
-hashTblRef [(HashTable ht), key@(_)] = do
+hashTblRef [(HashTable ht), key] = do
   case Data.Map.lookup key ht of
     Just val -> return val
     Nothing -> throwError $ BadSpecialForm "Hash table does not contain key" key
-hashTblRef [(HashTable ht), key@(_), Func _ _ _ _] = do
+hashTblRef [(HashTable ht), key, Func {}] = do
   case Data.Map.lookup key ht of
     Just val -> return $ val
     Nothing -> throwError $ NotImplemented "thunk"
@@ -1231,7 +1234,7 @@
 --
 hashTblKeys :: [LispVal] -> ThrowsError LispVal
 hashTblKeys [(HashTable ht)] = do
-  return $ List $ map (\ (k, _) -> k) $ Data.Map.toList ht
+  return $ List $ map fst $ Data.Map.toList ht
 hashTblKeys [badType] = throwError $ TypeMismatch "hash-table" badType
 hashTblKeys badArgList = throwError $ NumArgs (Just 1) badArgList
 
@@ -1245,7 +1248,7 @@
 --
 hashTblValues :: [LispVal] -> ThrowsError LispVal
 hashTblValues [(HashTable ht)] = do
-  return $ List $ map (\ (_, v) -> v) $ Data.Map.toList ht
+  return $ List $ map snd $ Data.Map.toList ht
 hashTblValues [badType] = throwError $ TypeMismatch "hash-table" badType
 hashTblValues badArgList = throwError $ NumArgs (Just 1) badArgList
 
@@ -1278,7 +1281,7 @@
 buildString (Char c : rest) = do
   cs <- buildString rest
   case cs of
-    String s -> return $ String $ [c] ++ s
+    String s -> return $ String $ c:s
     badType -> throwError $ TypeMismatch "character" badType
 buildString [badType] = throwError $ TypeMismatch "character" badType
 buildString badArgList = throwError $ NumArgs (Just 1) badArgList
@@ -1382,14 +1385,12 @@
     [badType] -> throwError $ TypeMismatch "string string" badType
     badArgList -> throwError $ NumArgs (Just 2) badArgList
  where ciCmp s1 s2 idx = 
-         if idx == (length s1)
-            then True
-            else if (toLower $ s1 !! idx) == (toLower $ s2 !! idx)
-                    then ciCmp s1 s2 (idx + 1)
-                    else False
+         (idx == (length s1)) ||
+         (((toLower $ s1 !! idx) == (toLower $ s2 !! idx)) && 
+          ciCmp s1 s2 (idx + 1))
 
 -- |Helper function
-stringCIBoolBinop :: ([Char] -> [Char] -> Bool) -> [LispVal] -> IOThrowsError LispVal
+stringCIBoolBinop :: (String -> String -> Bool) -> [LispVal] -> IOThrowsError LispVal
 stringCIBoolBinop op args = do 
   List dargs <- recDerefPtrs $ List args -- Deref any pointers
   case dargs of
@@ -1397,7 +1398,7 @@
       liftThrows $ boolBinop unpackStr op [(String $ strToLower s1), (String $ strToLower s2)]
     [badType] -> throwError $ TypeMismatch "string string" badType
     badArgList -> throwError $ NumArgs (Just 2) badArgList
-  where strToLower str = map (toLower) str
+  where strToLower = map toLower
 
 -- |Helper function
 charCIBoolBinop :: (Char -> Char -> Bool) -> [LispVal] -> ThrowsError LispVal
@@ -1468,7 +1469,7 @@
 --
 stringToList :: [LispVal] -> IOThrowsError LispVal
 stringToList [p@(Pointer _ _)] = derefPtr p >>= box >>= stringToList
-stringToList [(String s)] = return $ List $ map (Char) s
+stringToList [(String s)] = return $ List $ map Char s
 stringToList [badType] = throwError $ TypeMismatch "string" badType
 stringToList badArgList = throwError $ NumArgs (Just 1) badArgList
 
@@ -1568,28 +1569,49 @@
 --   Returns: Bool - True if procedure, False otherwise
 --
 isProcedure :: [LispVal] -> ThrowsError LispVal
-isProcedure ([Continuation _ _ _ _ _]) = return $ Bool True
+isProcedure ([Continuation {}]) = return $ Bool True
 isProcedure ([PrimitiveFunc _]) = return $ Bool True
-isProcedure ([Func _ _ _ _]) = return $ Bool True
-isProcedure ([HFunc _ _ _ _]) = return $ Bool True
+isProcedure ([Func {}]) = return $ Bool True
+isProcedure ([HFunc {}]) = return $ Bool True
 isProcedure ([IOFunc _]) = return $ Bool True
 isProcedure ([EvalFunc _]) = return $ Bool True
 isProcedure ([CustFunc _]) = return $ Bool True
 isProcedure _ = return $ Bool False
 
--- | Determine if given object is a bytevector
+-- | Determine if given object is a vector
 --
 --   Arguments:
 --
 --   * Value to check
 --
---   Returns: Bool - True if bytevector, False otherwise
+--   Returns: Bool - True if vector, False otherwise
 --
 isVector :: LispVal -> IOThrowsError LispVal
 isVector p@(Pointer _ _) = derefPtr p >>= isVector
-isVector (Vector _) = return $ Bool True
+isVector (Vector vs) = do
+    case elems vs of
+        -- Special exception for record types
+        ((Atom "  record-marker  ") : _) -> return $ Bool False
+        _ -> return $ Bool True
 isVector _ = return $ Bool False
 
+-- | Determine if given object is a record
+--
+--   Arguments:
+--
+--   * Value to check
+--
+--   Returns: Bool - True if record, False otherwise
+--
+isRecord :: LispVal -> IOThrowsError LispVal
+isRecord p@(Pointer _ _) = derefPtr p >>= isRecord
+isRecord (Vector vs) = do
+    case (elems vs) of
+        -- Special exception for record types
+        ((Atom "  record-marker  ") : _) -> return $ Bool True
+        _ -> return $ Bool False
+isRecord _ = return $ Bool False
+
 -- | Determine if given object is a bytevector
 --
 --   Arguments:
@@ -1939,6 +1961,17 @@
         ExitSuccess -> return $ Number 0
         ExitFailure code -> return $ Number $ toInteger code
 system err = throwError $ TypeMismatch "string" $ List err
+
+-- | Retrieve all environment variables
+--
+--   Arguments: (none)
+--
+--   Returns: List - list of key/value alists
+--
+getEnvVars :: [LispVal] -> IOThrowsError LispVal
+getEnvVars _ = do
+    vars <- liftIO $ SE.getEnvironment
+    return $ List $ map (\ (k, v) -> DottedList [String k] (String v)) vars
 
 -- FUTURE (?):
 -- systemRead :: [LispVal] -> IOThrowsError LispVal
diff --git a/hs-src/Language/Scheme/Types.hs b/hs-src/Language/Scheme/Types.hs
--- a/hs-src/Language/Scheme/Types.hs
+++ b/hs-src/Language/Scheme/Types.hs
@@ -330,7 +330,7 @@
         -- ^ Arguments to the function
         -> LispVal
         -- ^ The Haskell function packaged as a LispVal
-makeCPSWArgs env cont@(Continuation _ _ _ _ dynWind) cps args = 
+makeCPSWArgs env cont@(Continuation {dynamicWind=dynWind}) cps args = 
     Continuation 
         env 
         (Just (HaskellBody cps (Just args))) 
@@ -372,11 +372,11 @@
 eqv [(Char arg1), (Char arg2)] = return $ Bool $ arg1 == arg2
 eqv [(Atom arg1), (Atom arg2)] = return $ Bool $ arg1 == arg2
 eqv [(DottedList xs x), (DottedList ys y)] = eqv [List $ xs ++ [x], List $ ys ++ [y]]
-eqv [(Vector arg1), (Vector arg2)] = eqv [List $ (elems arg1), List $ (elems arg2)]
+eqv [(Vector arg1), (Vector arg2)] = eqv [List (elems arg1), List (elems arg2)]
 eqv [(ByteVector a), (ByteVector b)] = return $ Bool $ a == b
 eqv [(HashTable arg1), (HashTable arg2)] =
-  eqv [List $ (map (\ (x, y) -> List [x, y]) $ Data.Map.toAscList arg1),
-       List $ (map (\ (x, y) -> List [x, y]) $ Data.Map.toAscList arg2)]
+  eqv [List (map (\ (x, y) -> List [x, y]) $ Data.Map.toAscList arg1),
+       List (map (\ (x, y) -> List [x, y]) $ Data.Map.toAscList arg2)]
 --
 -- This comparison function may be too simplistic. Basically we check to see if
 -- functions have the same calling interface. If they do, then we compare the 
@@ -391,7 +391,7 @@
   if (show x) /= (show y)
      then return $ Bool False
      else eqvList eqv [List xBody, List yBody] 
-eqv [x@(HFunc _ _ _ _), y@(HFunc _ _ _ _)] = do
+eqv [x@(HFunc{}), y@(HFunc{})] = do
   if (show x) /= (show y)
      then return $ Bool False
      else return $ Bool True
@@ -407,8 +407,9 @@
 
 -- |Compare two lists of haskell values, using the given comparison function
 eqvList :: ([LispVal] -> ThrowsError LispVal) -> [LispVal] -> ThrowsError LispVal
-eqvList eqvFunc [(List arg1), (List arg2)] = return $ Bool $ (length arg1 == length arg2) &&
-                                                    (all eqvPair $ zip arg1 arg2)
+eqvList eqvFunc [(List arg1), (List arg2)] = 
+    return $ Bool $ (length arg1 == length arg2) &&
+                    all eqvPair (zip arg1 arg2)
     where eqvPair (x1, x2) = case eqvFunc [x1, x2] of
                                Left _ -> False
                                Right (Bool val) -> val
@@ -436,19 +437,19 @@
 showVal (Char chr) = [chr]
 showVal (Atom name) = name
 showVal (Number contents) = show contents
-showVal (Complex contents) = (show $ realPart contents) ++ "+" ++ (show $ imagPart contents) ++ "i"
+showVal (Complex contents) = show (realPart contents) ++ "+" ++ (show $ imagPart contents) ++ "i"
 showVal (Rational contents) = (show (numerator contents)) ++ "/" ++ (show (denominator contents))
 showVal (Float contents) = show contents
 showVal (Bool True) = "#t"
 showVal (Bool False) = "#f"
-showVal (Vector contents) = "#(" ++ (unwordsList $ Data.Array.elems contents) ++ ")"
+showVal (Vector contents) = "#(" ++ unwordsList (Data.Array.elems contents) ++ ")"
 showVal (ByteVector contents) = "#u8(" ++ unwords (map show (BS.unpack contents)) ++ ")"
 showVal (HashTable _) = "<hash-table>"
 showVal (List contents) = "(" ++ unwordsList contents ++ ")"
 showVal (DottedList h t) = "(" ++ unwordsList h ++ " . " ++ showVal t ++ ")"
 showVal (PrimitiveFunc _) = "<primitive>"
-showVal (Continuation _ _ _ _ _) = "<continuation>"
-showVal (Syntax _ _ _ _ _ _) = "<syntax>"
+showVal (Continuation {}) = "<continuation>"
+showVal (Syntax {}) = "<syntax>"
 showVal (SyntaxExplicitRenaming _) = "<er-macro-transformer syntax>"
 showVal (Func {params = args, vararg = varargs, body = _, closure = _}) =
   "(lambda (" ++ unwords args ++
@@ -540,7 +541,7 @@
   let syms = filter filterArgs ps
   if (length syms) /= (length ps)
      then throwError $ Default $ 
-             "Invalid lambda parameter(s): " ++ (show $ List ps)
+             "Invalid lambda parameter(s): " ++ show (List ps)
      else do
          let strs = DL.sort $ map (\ (Atom a) -> a) ps
          case dupe strs of
diff --git a/hs-src/Language/Scheme/Util.hs b/hs-src/Language/Scheme/Util.hs
--- a/hs-src/Language/Scheme/Util.hs
+++ b/hs-src/Language/Scheme/Util.hs
@@ -19,7 +19,7 @@
 
 -- |A utility function to escape backslashes in the given string
 escapeBackslashes :: String -> String
-escapeBackslashes s = foldr step [] s
+escapeBackslashes = foldr step []
   where step x xs  | x == '\\'  = '\\' : '\\' : xs
                    | otherwise =  x : xs 
 
diff --git a/hs-src/Language/Scheme/Variables.hs b/hs-src/Language/Scheme/Variables.hs
--- a/hs-src/Language/Scheme/Variables.hs
+++ b/hs-src/Language/Scheme/Variables.hs
@@ -50,6 +50,7 @@
     , derefPtr
 --    , derefPtrs
     , recDerefPtrs
+    , safeRecDerefPtrs
     , recDerefToFnc
     ) where
 import Language.Scheme.Types
@@ -228,14 +229,14 @@
 isBound :: Env      -- ^ Environment
         -> String   -- ^ Variable
         -> IO Bool  -- ^ True if the variable is bound
-isBound envRef var = isNamespacedBound envRef varNamespace var
+isBound envRef = isNamespacedBound envRef varNamespace
 
 -- |Determine if a variable is bound in the default namespace, 
 --  in this environment or one of its parents.
 isRecBound :: Env      -- ^ Environment
            -> String   -- ^ Variable
            -> IO Bool  -- ^ True if the variable is bound
-isRecBound envRef var = isNamespacedRecBound envRef varNamespace var
+isRecBound envRef = isNamespacedRecBound envRef varNamespace
 
 -- |Determine if a variable is bound in a given namespace
 isNamespacedBound 
@@ -244,7 +245,7 @@
     -> String   -- ^ Variable
     -> IO Bool  -- ^ True if the variable is bound
 isNamespacedBound envRef namespace var = 
-    (readIORef $ bindings envRef) >>= return . Data.Map.member (getVarName namespace var)
+    readIORef (bindings envRef) >>= return . Data.Map.member (getVarName namespace var)
 
 -- |Determine if a variable is bound in a given namespace
 --  or a parent of the given environment.
@@ -263,14 +264,14 @@
 getVar :: Env       -- ^ Environment
        -> String    -- ^ Variable
        -> IOThrowsError LispVal -- ^ Contents of the variable
-getVar envRef var = getNamespacedVar envRef varNamespace var
+getVar envRef = getNamespacedVar envRef varNamespace
 
 -- |Retrieve the value of a variable defined in the default namespace,
 --  or Nothing if it is not defined
 getVar' :: Env       -- ^ Environment
         -> String    -- ^ Variable
         -> IOThrowsError (Maybe LispVal) -- ^ Contents of the variable
-getVar' envRef var = getNamespacedVar' envRef varNamespace var
+getVar' envRef = getNamespacedVar' envRef varNamespace
 
 -- |Retrieve an ioRef defined in a given namespace
 getNamespacedRef :: Env     -- ^ Environment
@@ -280,8 +281,7 @@
 getNamespacedRef envRef
                  namespace
                  var = do
-  let fnc io = return io
-  v <- getNamespacedObj' envRef namespace var fnc
+  v <- getNamespacedObj' envRef namespace var return
   case v of
     Just a -> return a
     Nothing -> (throwError $ UnboundVar "Getting an unbound variable" var)
@@ -308,8 +308,7 @@
 getNamespacedVar' envRef
                  namespace
                  var = do 
-    getNamespacedObj' envRef namespace var fnc
-  where fnc io = readIORef io
+    getNamespacedObj' envRef namespace var readIORef
 
 getNamespacedObj' :: Env     -- ^ Environment
                  -> Char    -- ^ Namespace
@@ -335,7 +334,7 @@
     -> String   -- ^ Variable
     -> LispVal  -- ^ Value
     -> IOThrowsError LispVal -- ^ Value
-setVar envRef var value = setNamespacedVar envRef varNamespace var value
+setVar envRef = setNamespacedVar envRef varNamespace
 
 -- |Set a variable in a given namespace
 setNamespacedVar 
@@ -468,8 +467,8 @@
 
 -- |A wrapper for updateNamespaceObject that uses the variable namespace.
 updateObject :: Env -> String -> LispVal -> IOThrowsError LispVal
-updateObject env var value = 
-  updateNamespacedObject env varNamespace var value
+updateObject env = 
+  updateNamespacedObject env varNamespace
 
 -- |This function updates the object that "var" refers to. If "var" is
 --  a pointer, that means this function will update that pointer (or the last
@@ -496,7 +495,7 @@
     -> String   -- ^ Variable
     -> LispVal  -- ^ Value
     -> IOThrowsError LispVal -- ^ Value
-defineVar envRef var value = defineNamespacedVar envRef varNamespace var value
+defineVar envRef = defineNamespacedVar envRef varNamespace 
 
 -- |Bind a variable in the given namespace
 defineNamespacedVar
@@ -602,27 +601,40 @@
 --  This could potentially be expensive on large data structures 
 --  since it must walk the entire object.
 recDerefPtrs :: LispVal -> IOThrowsError LispVal
+recDerefPtrs = safeRecDerefPtrs []
+
+-- |Attempt to dereference pointers safely, without being caught in a cycle
+safeRecDerefPtrs :: [LispVal] -> LispVal -> IOThrowsError LispVal
 #ifdef UsePointers
-recDerefPtrs (List l) = do
-    result <- mapM recDerefPtrs l
+safeRecDerefPtrs ps (List l) = do
+    result <- mapM (safeRecDerefPtrs ps) l
     return $ List result
-recDerefPtrs (DottedList ls l) = do
-    ds <- mapM recDerefPtrs ls
-    d <- recDerefPtrs l
+safeRecDerefPtrs ps (DottedList ls l) = do
+    ds <- mapM (safeRecDerefPtrs ps) ls
+    d <- safeRecDerefPtrs ps l
     return $ DottedList ds d
-recDerefPtrs (Vector v) = do
-    let vs = elems v
-    ds <- mapM recDerefPtrs vs
-    return $ Vector $ listArray (0, length vs - 1) ds
-recDerefPtrs (HashTable ht) = do
-    ks <- mapM recDerefPtrs $ map (\ (k, _) -> k) $ Data.Map.toList ht
-    vs <- mapM recDerefPtrs $ map (\ (_, v) -> v) $ Data.Map.toList ht
+safeRecDerefPtrs ps (Vector v) = do
+   let vs = elems v
+   ds <- mapM (safeRecDerefPtrs ps) vs
+   return $ Vector $ listArray (0, length vs - 1) ds
+safeRecDerefPtrs ps (HashTable ht) = do
+    ks <- mapM (safeRecDerefPtrs ps)$ map (\ (k, _) -> k) $ Data.Map.toList ht
+    vs <- mapM (safeRecDerefPtrs ps)$ map (\ (_, v) -> v) $ Data.Map.toList ht
     return $ HashTable $ Data.Map.fromList $ zip ks vs
 #endif
-recDerefPtrs (Pointer p env) = do
-    result <- getVar env p
-    recDerefPtrs result 
-recDerefPtrs v = return v
+safeRecDerefPtrs ps ptr@(Pointer p env) = do
+    if containsPtr ps ptr
+       then return ptr -- Avoid cycle
+       else do
+            result <- getVar env p
+            safeRecDerefPtrs (ptr : ps) result 
+safeRecDerefPtrs _ v = return v
+
+containsPtr :: [LispVal] -> LispVal -> Bool
+containsPtr ((Pointer pa ea):ps) p@(Pointer pb eb) = do
+    let found = (pa == pb) && ((bindings ea) == (bindings eb))
+    found || containsPtr ps p
+containsPtr _ _ = False
 
 -- |A helper to recursively dereference all pointers and
 --  pass results to a function
diff --git a/husk-scheme.cabal b/husk-scheme.cabal
--- a/husk-scheme.cabal
+++ b/husk-scheme.cabal
@@ -1,5 +1,5 @@
 Name:                husk-scheme
-Version:             3.16.1
+Version:             3.17
 Synopsis:            R5RS Scheme interpreter, compiler, and library.
 Description:         
   <<https://github.com/justinethier/husk-scheme/raw/master/docs/husk-scheme.png>>
@@ -56,6 +56,10 @@
     Type:            git
     Location:        git://github.com/justinethier/husk-scheme.git
 
+flag usedebug
+    description: Include debug trace statements in compiled code.
+    default: False
+
 flag useffi
     description: Haskell Foreign Function Interface (FFI). Allows husk to import and call into Haskell code directly from Scheme code. Turn off FFI to decrease build times and minimize executable sizes
     default: False
@@ -65,7 +69,7 @@
     default: True
 
 flag useptrs
-    description: Turn off pointers to increase performance at the expense of severely restricting the functionality of mutable variables. Setting this flag to false will revert back to the behavior from previous versions of husk.
+    description: Turn off pointers to increase performance at the expense of severely restricting the functionality of mutable variables. Setting this flag to false will revert back to the behavior from older versions of husk.
     default: True
 
 Library
@@ -90,6 +94,9 @@
                    Language.Scheme.Util
   Other-Modules:   Paths_husk_scheme
 
+  if flag(usedebug)
+    cpp-options: -DUseDebug
+
   if flag(useffi)
     Build-Depends: ghc, ghc-paths
     Exposed-Modules:  Language.Scheme.FFI
@@ -112,6 +119,8 @@
 
 Executable huskc
   Build-Depends: husk-scheme, base >= 2.0 && < 5, array, containers, haskeline, transformers, mtl, parsec, directory, ghc-paths, process, filepath
+  if flag(usedebug)
+    cpp-options: -DUseDebug
   if flag(useffi)
     Build-Depends: ghc, ghc-paths
     cpp-options: -DUseFfi
diff --git a/lib/core.scm b/lib/core.scm
--- a/lib/core.scm
+++ b/lib/core.scm
@@ -785,3 +785,48 @@
              ((check (caar ls)) `(,(rename 'begin) ,@(cdar ls)))
              (else (expand (cdr ls))))))))
 ;; END
+
+;; SRFI 39:
+(define (make-parameter init . o)
+  (let* ((converter
+           (if (pair? o) (car o) (lambda (x) x))))
+    (lambda args
+      (cond
+        ((null? args)
+         (converter init))
+        ((eq? (car args) '<param-set!>)
+         (set! init (cadr args)))
+        ((eq? (car args) '<param-convert>)
+         converter)
+       (else
+         (error "bad parameter syntax"))))))
+
+(define-syntax parameterize
+  (syntax-rules ()
+    ((parameterize ("step")
+                   ((param value p old new) ...)
+                   ()
+                   body ...)
+     (let ((p param) ...)
+       (let ((old (p)) ...
+             (new ((p '<param-convert>) value)) ...)
+        (dynamic-wind
+          (lambda () (p '<param-set!> new) ...)
+          ;(lambda () . body) ; bug in husk, should surround with ()
+          (lambda () body ...) ; bug in husk, should surround with ()
+          (lambda () (p '<param-set!> old) ...)))))
+    ((parameterize ("step")
+                   args
+                   ((param value) . rest)
+                   body ...)
+     (parameterize ("step")
+                   ((param value p old new) . args)
+                   rest
+                   body ...))
+    ((parameterize ((param value) ...) body ...)
+     (parameterize ("step")
+                   ()
+                   ((param value) ...)
+                   body ...))))
+;; END SRFI 39
+
diff --git a/lib/scheme/base.sld b/lib/scheme/base.sld
--- a/lib/scheme/base.sld
+++ b/lib/scheme/base.sld
@@ -170,7 +170,8 @@
     cond-expand
     ;current-error-port
     ;define
-    ;define-record-type
+    define-record-type
+    record?
     ;define-syntax
     ;define-values
     ;else
@@ -202,13 +203,13 @@
     list-copy
     ;list-set!
     make-list
-    ;make-parameter
+    make-parameter
     ;open-input-bytevector
     ;open-input-string
     ;open-output-bytevector
     ;open-output-string
     output-port-open?
-    ;parameterize
+    parameterize
     ;peek-u8
     ;port?
     ;quote
@@ -256,4 +257,5 @@
     ;write-u8
     %husk-switch-to-parent-environment
     )
+    (include "../srfi/srfi-9.scm")
     (import (scheme)))
diff --git a/lib/scheme/process-context.sld b/lib/scheme/process-context.sld
--- a/lib/scheme/process-context.sld
+++ b/lib/scheme/process-context.sld
@@ -9,14 +9,21 @@
 
 (define-library (scheme process-context)
     (export 
-         system
-         exit-success
+         emergency-exit
+         get-environment-variable
+         get-environment-variables
          exit-fail
-; TODO:
-;        command-line
-;        emergency-exit
-;        exit
-;        get-environment-variable
-;        get-environment-variables
-        )
-    (import (scheme)))
+         exit-success
+         system)
+    (import (scheme))
+    (begin
+        (define (get-environment-variable var)
+          (let ((var+val (assoc var (get-environment-variables))))
+            (if var+val
+                (cdr var+val)
+                #f)))
+        (define (emergency-exit . obj)
+            (if (or (null? obj)
+                    (car obj))
+                (exit-success)
+                (exit-fail)))))
diff --git a/lib/srfi/srfi-9.scm b/lib/srfi/srfi-9.scm
new file mode 100644
--- /dev/null
+++ b/lib/srfi/srfi-9.scm
@@ -0,0 +1,209 @@
+;;;; This file contains the implementation of SRFI-9 from:
+;;;; http://srfi.schemers.org/srfi-9/srfi-9.html
+
+;;;;
+;;;; Section 1 - Syntax definitions
+;;;;
+
+; Definition of DEFINE-RECORD-TYPE
+
+(define-syntax define-record-type
+  (syntax-rules ()
+    ((define-record-type type
+       (constructor constructor-tag ...)
+       predicate
+       (field-tag accessor . more) ...)
+     (begin
+       (define type
+         (make-record-type 'type '(field-tag ...)))
+       (define constructor
+         (record-constructor type '(constructor-tag ...)))
+       (define predicate
+         (record-predicate type))
+       (define-record-field type field-tag accessor . more)
+       ...))))
+
+; An auxilliary macro for define field accessors and modifiers.
+; This is needed only because modifiers are optional.
+
+(define-syntax define-record-field
+  (syntax-rules ()
+    ((define-record-field type field-tag accessor)
+     (define accessor (record-accessor type 'field-tag)))
+    ((define-record-field type field-tag accessor modifier)
+     (begin
+       (define accessor (record-accessor type 'field-tag))
+       (define modifier (record-modifier type 'field-tag))))))
+
+;;;;
+;;;; Section 3 - Records
+;;;;
+
+; This implements a record abstraction that is identical to vectors,
+; except that they are not vectors (VECTOR? returns false when given a
+; record and RECORD? returns false when given a vector).  The following
+; procedures are provided:
+;   (record? <value>)                -> <boolean>
+;   (make-record <size>)             -> <record>
+;   (record-ref <record> <index>)    -> <value>
+;   (record-set! <record> <index> <value>) -> <unspecific>
+;
+; These can implemented in R5RS Scheme as vectors with a distinguishing
+; value at index zero, providing VECTOR? is redefined to be a procedure
+; that returns false if its argument contains the distinguishing record
+; value.  EVAL is also redefined to use the new value of VECTOR?.
+
+; Define the marker and redefine VECTOR? and EVAL.
+
+;;(define record-marker (list 'record-marker))
+;;
+;;(define real-vector? vector?)
+;;
+;;(define (vector? x)
+;;  (and (real-vector? x)
+;;       (or (= 0 (vector-length x))
+;;       (not (eq? (vector-ref x 0)
+;;        record-marker)))))
+;;
+;;; This won't work if ENV is the interaction environment and someone has
+;;; redefined LAMBDA there.
+;;
+;;(define eval
+;;  (let ((real-eval eval))
+;;    (lambda (exp env)
+;;      ((real-eval `(lambda (vector?) ,exp))
+;;       vector?))))
+;;
+;;; Definitions of the record procedures.
+;;
+;;(define (record? x)
+;;  (and (real-vector? x)
+;;       (< 0 (vector-length x))
+;;       (eq? (vector-ref x 0)
+;;            record-marker)))
+
+(define (make-record size)
+  (let ((new (make-vector (+ size 1))))
+    (vector-set! new 0 (string->symbol "  record-marker  "))
+    new))
+
+(define (record-ref record index)
+  (vector-ref record (+ index 1)))
+
+(define (record-set! record index value)
+  (vector-set! record (+ index 1) value))
+
+;;;;
+;;;; Record types section
+;;;;
+
+; We define the following procedures:
+; 
+; (make-record-type <type-name <field-names>)    -> <record-type>
+; (record-constructor <record-type<field-names>) -> <constructor>
+; (record-predicate <record-type>)               -> <predicate>
+; (record-accessor <record-type <field-name>)    -> <accessor>
+; (record-modifier <record-type <field-name>)    -> <modifier>
+;   where
+; (<constructor> <initial-value> ...)         -> <record>
+; (<predicate> <value>)                       -> <boolean>
+; (<accessor> <record>)                       -> <value>
+; (<modifier> <record> <value>)         -> <unspecific>
+
+; Record types are implemented using vector-like records.  The first
+; slot of each record contains the record's type, which is itself a
+; record.
+
+(define (record-type record)
+  (record-ref record 0))
+
+;----------------
+; Record types are themselves records, so we first define the type for
+; them.  Except for problems with circularities, this could be defined as:
+;  (define-record-type :record-type
+;    (make-record-type name field-tags)
+;    record-type?
+;    (name record-type-name)
+;    (field-tags record-type-field-tags))
+; As it is, we need to define everything by hand.
+
+(define :record-type (make-record 3))
+(record-set! :record-type 0 :record-type)   ; Its type is itself.
+(record-set! :record-type 1 ':record-type)
+(record-set! :record-type 2 '(name field-tags))
+
+; Now that :record-type exists we can define a procedure for making more
+; record types.
+
+(define (make-record-type name field-tags)
+  (let ((new (make-record 3)))
+    (record-set! new 0 :record-type)
+    (record-set! new 1 name)
+    (record-set! new 2 field-tags)
+    new))
+
+; Accessors for record types.
+
+(define (record-type-name record-type)
+  (record-ref record-type 1))
+
+(define (record-type-field-tags record-type)
+  (record-ref record-type 2))
+
+;----------------
+; A utility for getting the offset of a field within a record.
+
+(define (field-index type tag)
+  (let loop ((i 1) (tags (record-type-field-tags type)))
+    (cond ((null? tags)
+           (error "record type has no such field" type tag))
+          ((eq? tag (car tags))
+           i)
+          (else
+           (loop (+ i 1) (cdr tags))))))
+
+;----------------
+; Now we are ready to define RECORD-CONSTRUCTOR and the rest of the
+; procedures used by the macro expansion of DEFINE-RECORD-TYPE.
+
+(define (record-constructor type tags)
+  (let ((size (length (record-type-field-tags type)))
+        (arg-count (length tags))
+        (indexes (map (lambda (tag)
+                        (field-index type tag))
+                      tags)))
+    (lambda args
+      (if (= (length args)
+             arg-count)
+          (let ((new (make-record (+ size 1))))
+            (record-set! new 0 type)
+            (for-each (lambda (arg i)
+            (record-set! new i arg))
+                      args
+                      indexes)
+            new)
+          (error "wrong number of arguments to constructor" type args)))))
+
+(define (record-predicate type)
+  (lambda (thing)
+    (and (record? thing)
+         (eq? (record-type thing)
+              type))))
+
+(define (record-accessor type tag)
+  (let ((index (field-index type tag)))
+    (lambda (thing)
+      (if (and (record? thing)
+               (eq? (record-type thing)
+                    type))
+          (record-ref thing index)
+          (error "accessor applied to bad value" type tag thing)))))
+
+(define (record-modifier type tag)
+  (let ((index (field-index type tag)))
+    (lambda (thing value)
+      (if (and (record? thing)
+               (eq? (record-type thing)
+                    type))
+          (record-set! thing index value)
+          (error "modifier applied to bad value" type tag thing)))))
diff --git a/lib/stdlib.scm b/lib/stdlib.scm
--- a/lib/stdlib.scm
+++ b/lib/stdlib.scm
@@ -10,3 +10,4 @@
 (load "cxr.scm")
 (load "core.scm")
 (load "lazy.scm")
+(load "srfi/srfi-9.scm")
