diff --git a/fay.cabal b/fay.cabal
--- a/fay.cabal
+++ b/fay.cabal
@@ -1,5 +1,5 @@
 name:                fay
-version:             0.15.0.0
+version:             0.16.0.0
 synopsis:            A compiler for Fay, a Haskell subset that compiles to JavaScript.
 description:         Fay is a proper subset of Haskell which is type-checked
                      with GHC, and compiled to JavaScript. It is lazy, pure, has a Fay monad,
@@ -29,53 +29,308 @@
 build-type:          Custom
 cabal-version:       >=1.8
 data-files:          js/runtime.js
-                     hs/stdlib.hs
-                     src/Language/Fay/FFI.hs
-extra-source-files:  examples/ref.hs examples/alert.hs examples/console.hs examples/dom.hs
-                     examples/tailrecursive.hs examples/data.hs examples/canvaswater.hs
-                     examples/canvaswater.html examples/haskell.png
-                     -- Test cases
-                     tests/ints.hs tests/ints tests/asPatternMatch
-                     tests/caseList.hs tests/Double2.hs
-                     tests/fromInteger tests/List.hs tests/RecCon
-                     tests/recordPatternMatch tests/String.hs
-                     tests/asPatternMatch.hs tests/fromInteger.hs
-                     tests/RecCon.hs tests/recordPatternMatch2
-                     tests/caseWildcard tests/Double3 tests/Monad
-                     tests/recordPatternMatch2.hs tests/tailRecursion
-                     tests/basicFunctions tests/caseWildcard.hs
-                     tests/Double3.hs tests/Monad2 tests/RecDecl
-                     tests/tailRecursion.hs tests/basicFunctions.hs
-                     tests/HierarchicalImport tests/Monad2.hs
-                     tests/RecDecl.hs tests/recordPatternMatch.hs
-                     tests/do tests/Double4 tests/then tests/Bool
-                     tests/doAssingPatternMatch tests/Double4.hs
-                     tests/HierarchicalImport.hs tests/Monad.hs
-                     tests/records tests/then.hs tests/Bool.hs
-                     tests/doAssingPatternMatch.hs
-                     tests/recordFunctionPatternMatch tests/records.hs
-                     tests/Double.hs tests/mutableReference
-                     tests/recordFunctionPatternMatch.hs tests/utf8
-                     tests/case tests/doBindAssign
-                     tests/infixDataConst tests/mutableReference.hs
-                     tests/recordUseBeforeDefine tests/utf8.hs
-                     tests/case2 tests/doBindAssign.hs tests/emptyMain
-                     tests/infixDataConst.hs tests/RecordImport_Export
-                     tests/recordUseBeforeDefine.hs tests/case2.hs
-                     tests/emptyMain.hs tests/patternGuards
-                     tests/RecordImport_Export.hs tests/where
-                     tests/do.hs tests/List tests/patternGuards.hs
-                     tests/reservedWords tests/where.hs tests/case.hs
-                     tests/fix tests/List2 tests/RecordImport_Import
-                     tests/reservedWords.hs tests/Double tests/fix.hs
-                     tests/List2.hs tests/patternMatchFail.hs
-                     tests/RecordImport_Import.hs tests/caseList
-                     tests/Double2 tests/String
-                     tests/Hierarchical/Export.hs
-                     tests/Hierarchical/RecordDefined.hs
-                     tests/Api/Records.hs tests/Api/ImportRecords.hs
-                     tests/Api/CPPTypecheck.hs
-                     tests/serialization.hs tests/serialization
+                     src/Fay/FFI.hs
+extra-source-files:
+  -- Examples
+  examples/alert.hs
+  examples/canvaswater.hs
+  examples/canvaswater.html
+  examples/console.hs
+  examples/data.hs
+  examples/dom.hs
+  examples/haskell.png
+  examples/ref.hs
+  examples/tailrecursive.hs
+  -- Test cases
+  tests/Api/CPPTypecheck.hs
+  tests/Api/ImportRecords.hs
+  tests/Api/Records.hs
+  tests/asPatternMatch.hs
+  tests/asPatternMatch.res
+  tests/AutomaticList.hs
+  tests/AutomaticList.res
+  tests/baseFixities.hs
+  tests/baseFixities.res
+  tests/basicFunctions.hs
+  tests/basicFunctions.res
+  tests/Bool.hs
+  tests/Bool.res
+  tests/case.hs
+  tests/case.res
+  tests/case2.hs
+  tests/case2.res
+  tests/caseList.hs
+  tests/caseList.res
+  tests/caseWildcard.hs
+  tests/caseWildcard.res
+  tests/Char.hs
+  tests/Char.res
+  tests/circular.hs
+  tests/CPP.hs
+  tests/CPP.res
+  tests/curry.hs
+  tests/curry.res
+  tests/cycle.hs
+  tests/cycle.res
+  tests/Defined.hs
+  tests/Defined.res
+  tests/do.hs
+  tests/do.res
+  tests/doAssingPatternMatch.hs
+  tests/doAssingPatternMatch.res
+  tests/doBindAssign.hs
+  tests/doBindAssign.res
+  tests/doLet.hs
+  tests/doLet.res
+  tests/DoLet2.hs
+  tests/DoLet2_partial.res
+  tests/DoLet3.hs
+  tests/DoLet3_partial.res
+  tests/Double.hs
+  tests/Double.res
+  tests/Double2.hs
+  tests/Double2.res
+  tests/Double3.hs
+  tests/Double3.res
+  tests/Double4.hs
+  tests/Double4.res
+  tests/Either.hs
+  tests/Either.res
+  tests/emptyMain.hs
+  tests/emptyMain.res
+  tests/enumFrom.hs
+  tests/enumFrom.res
+  tests/Eq.hs
+  tests/Eq.res
+  tests/error.hs
+  tests/ExportEThingAll.hs
+  tests/ExportEThingAll.res
+  tests/ExportEThingAll_Export.hs
+  tests/ExportEThingAll_Export.res
+  tests/ExportEThingWith.hs
+  tests/ExportEThingWith.res
+  tests/ExportList.hs
+  tests/ExportList.res
+  tests/ExportList_A.hs
+  tests/ExportList_A.res
+  tests/ExportList_B.hs
+  tests/ExportList_B.res
+  tests/ExportList_C.hs
+  tests/ExportList_C.res
+  tests/ExportList_D.hs
+  tests/ExportList_D.res
+  tests/ExportQualified_Export.hs
+  tests/ExportQualified_Export.res
+  tests/ExportQualified_Import.hs
+  tests/ExportQualified_Import.res
+  tests/ExportType.hs
+  tests/ExportType.res
+  tests/ffiExpr.hs
+  tests/ffiExpr.res
+  tests/ffimunging.hs
+  tests/ffimunging.res
+  tests/fix.hs
+  tests/fix.res
+  tests/Floating.hs
+  tests/Floating.res
+  tests/fromInteger.hs
+  tests/fromInteger.res
+  tests/GADTs_without_records.hs
+  tests/GADTs_without_records.res
+  tests/guards.hs
+  tests/guards.res
+  tests/GuardWhere.hs
+  tests/GuardWhere.res
+  tests/HidePreludeImport.hs
+  tests/HidePreludeImport.res
+  tests/HidePreludeImport_Import.hs
+  tests/HidePreludeImport_Import.res
+  tests/Hierarchical/Export.hs
+  tests/Hierarchical/Export.res
+  tests/Hierarchical/RecordDefined.hs
+  tests/Hierarchical/RecordDefined.res
+  tests/HierarchicalImport.hs
+  tests/HierarchicalImport.res
+  tests/ImportHiding.hs
+  tests/ImportHiding.res
+  tests/ImportIThingAll.hs
+  tests/ImportIThingAll.res
+  tests/ImportList.hs
+  tests/ImportList.res
+  tests/ImportList1/A.hs
+  tests/ImportList1/A.res
+  tests/ImportList1/B.hs
+  tests/ImportList1/B.res
+  tests/ImportList1/C.hs
+  tests/ImportList1/C.res
+  tests/ImportListType.hs
+  tests/ImportListType.res
+  tests/ImportType.hs
+  tests/ImportType.res
+  tests/ImportType2.hs
+  tests/ImportType2.res
+  tests/ImportType2I/A.hs
+  tests/ImportType2I/A.res
+  tests/ImportType2I/B.hs
+  tests/ImportType2I/B.res
+  tests/infixDataConst.hs
+  tests/infixDataConst.res
+  tests/Integral.hs
+  tests/Integral.res
+  tests/ints.hs
+  tests/ints.res
+  tests/Issue215/B.hs
+  tests/Issue215/B.res
+  tests/Issue215A.hs
+  tests/Issue215A.res
+  tests/Js2FayFunc.hs
+  tests/Js2FayFunc.res
+  tests/LazyOperators.hs
+  tests/LazyOperators.res
+  tests/linesAndWords.hs
+  tests/linesAndWords.res
+  tests/List.hs
+  tests/List.res
+  tests/List2.hs
+  tests/List2.res
+  tests/listComprehensions.hs
+  tests/listComprehensions.res
+  tests/listlen.hs
+  tests/listlen.res
+  tests/ModuleRecordClash/R.hs
+  tests/ModuleRecordClash/R.res
+  tests/ModuleRecordClash.hs
+  tests/ModuleRecordClash.res
+  tests/Monad.hs
+  tests/Monad.res
+  tests/Monad2.hs
+  tests/Monad2.res
+  tests/mutableReference.hs
+  tests/mutableReference.res
+  tests/namedFieldPuns.hs
+  tests/namedFieldPuns.res
+  tests/nameGen.hs
+  tests/nameGen.res
+  tests/negation.hs
+  tests/negation.res
+  tests/NestedImporting/A.hs
+  tests/NestedImporting/A.res
+  tests/NestedImporting.hs
+  tests/NestedImporting.res
+  tests/NestedImporting2/A.hs
+  tests/NestedImporting2/A.res
+  tests/NestedImporting2.hs
+  tests/NestedImporting2.res
+  tests/newtype.hs
+  tests/newtype.res
+  tests/NewtypeImport_Export.hs
+  tests/NewtypeImport_Export.res
+  tests/NewtypeImport_Import.hs
+  tests/NewtypeImport_Import.res
+  tests/Nullable.hs
+  tests/Nullable.res
+  tests/Num.hs
+  tests/Num.res
+  tests/nums.hs
+  tests/nums.res
+  tests/numTheory.hs
+  tests/numTheory.res
+  tests/Ord.hs
+  tests/Ord.res
+  tests/pats.hs
+  tests/pats.res
+  tests/patternGuards.hs
+  tests/patternGuards.res
+  tests/patternMatchFail.hs
+  tests/patternMatchingTuples.hs
+  tests/patternMatchingTuples.res
+  tests/Ratio.hs
+  tests/Ratio.res
+  tests/RealFrac.hs
+  tests/RealFrac.res
+  tests/RecCon.hs
+  tests/RecCon.res
+  tests/RecDecl.hs
+  tests/RecDecl.res
+  tests/recordFunctionPatternMatch.hs
+  tests/recordFunctionPatternMatch.res
+  tests/RecordImport2_Export1.hs
+  tests/RecordImport2_Export1.res
+  tests/RecordImport2_Export2.hs
+  tests/RecordImport2_Export2.res
+  tests/RecordImport2_Import.hs
+  tests/RecordImport2_Import.res
+  tests/RecordImport_Export.hs
+  tests/RecordImport_Export.res
+  tests/RecordImport_Import.hs
+  tests/RecordImport_Import.res
+  tests/recordPatternMatch.hs
+  tests/recordPatternMatch.res
+  tests/recordPatternMatch2.hs
+  tests/recordPatternMatch2.res
+  tests/records.hs
+  tests/records.res
+  tests/recordUseBeforeDefine.hs
+  tests/recordUseBeforeDefine.res
+  tests/recordWildCards.hs
+  tests/recordWildCards_partial.res
+  tests/recursive.hs
+  tests/recursive.res
+  tests/ReExport1.hs
+  tests/ReExport1.res
+  tests/ReExport2.hs
+  tests/ReExport2.res
+  tests/ReExport3.hs
+  tests/ReExport3.res
+  tests/reservedWords.hs
+  tests/reservedWords.res
+  tests/sections.hs
+  tests/sections.res
+  tests/seq-fake.hs
+  tests/seq-fake.res
+  tests/seq.hs
+  tests/serialization.hs
+  tests/serialization.res
+  tests/Sink.hs
+  tests/Sink.res
+  tests/SkipLetTypes.hs
+  tests/SkipLetTypes.res
+  tests/SkipWhereTypes.hs
+  tests/SkipWhereTypes.res
+  tests/String.hs
+  tests/String.res
+  tests/StringForcing.hs
+  tests/StringForcing.res
+  tests/succPred.hs
+  tests/succPred.res
+  tests/T190.hs
+  tests/T190.res
+  tests/T190_A.hs
+  tests/T190_A.res
+  tests/T190_B.hs
+  tests/T190_B.res
+  tests/T190_C.hs
+  tests/T190_C.res
+  tests/tailRecursion.hs
+  tests/tailRecursion.res
+  tests/then.hs
+  tests/then.res
+  tests/TupleCalls.hs
+  tests/TupleCalls.res
+  tests/TyVarSerialization.hs
+  tests/TyVarSerialization.res
+  tests/unit.hs
+  tests/unit.res
+  tests/utf8.hs
+  tests/utf8.res
+  tests/where.hs
+  tests/where.res
+  tests/whereBind.hs
+  tests/whereBind.res
+  tests/whereBind2.hs
+  tests/whereBind2.res
+  tests/whereBind3.hs
+  tests/whereBind3.res
 
 source-repository head
   type: git
@@ -87,8 +342,33 @@
 
 library
   hs-source-dirs:    src
-  exposed-modules:   Fay, Fay.Types, Language.Fay.FFI, Fay.Convert, Fay.Compiler, Fay.Compiler.Debug, Fay.Compiler.Config
-  other-modules:     Fay.Compiler.Print, Control.Monad.IO, System.Process.Extra, Data.List.Extra, Paths_fay, Fay.Compiler.Misc, Fay.Compiler.FFI, Fay.Compiler.Optimizer, Fay.Compiler.Packages, Fay.Compiler.ModuleScope, Control.Monad.Extra, Fay.Compiler.InitialPass, Fay.Compiler.Decl, Fay.Compiler.Defaults, Fay.Compiler.Exp, Fay.Compiler.Pattern, Fay.Compiler.Typecheck, Fay.Compiler.GADT
+  exposed-modules:     Fay
+                     , Fay.Compiler
+                     , Fay.Compiler.Config
+                     , Fay.Compiler.Debug
+                     , Fay.Convert
+                     , Fay.Types
+                     , Fay.FFI
+  other-modules:       Control.Monad.Extra
+                     , Control.Monad.IO
+                     , Data.List.Extra
+                     , Fay.Compiler.Decl
+                     , Fay.Compiler.Defaults
+                     , Fay.Compiler.Exp
+                     , Fay.Compiler.FFI
+                     , Fay.Compiler.GADT
+                     , Fay.Compiler.InitialPass
+                     , Fay.Compiler.Misc
+                     , Fay.Compiler.ModuleScope
+                     , Fay.Compiler.Optimizer
+                     , Fay.Compiler.Packages
+                     , Fay.Compiler.Pattern
+                     , Fay.Compiler.Print
+                     , Fay.Compiler.QName
+                     , Fay.Compiler.Typecheck
+                     , Paths_fay
+                     , System.Directory.Extra
+                     , System.Process.Extra
   ghc-options:       -O2 -Wall -fno-warn-name-shadowing
   build-depends:     base >= 4 && < 5,
                      aeson,
@@ -100,7 +380,7 @@
                      ghc-paths,
                      Cabal,
                      haskell-src-exts,
-                     language-ecmascript >= 0.10,
+                     language-ecmascript >= 0.15,
                      mtl,
                      pretty-show,
                      process,
@@ -174,6 +454,7 @@
                      process,
                      safe,
                      syb,
+                     split,
                      text,
                      unordered-containers,
                      utf8-string,
diff --git a/hs/stdlib.hs b/hs/stdlib.hs
deleted file mode 100644
--- a/hs/stdlib.hs
+++ /dev/null
@@ -1,3 +0,0 @@
-data Maybe a
-  = Just a
-  | Nothing
diff --git a/js/runtime.js b/js/runtime.js
--- a/js/runtime.js
+++ b/js/runtime.js
@@ -1,3 +1,7 @@
+/*******************************************************************************
+ * Misc.
+ */
+
 // Workaround for missing functionality in IE 8 and earlier.
 if( Object.create === undefined ) {
   Object.create = function( o ) {
@@ -7,6 +11,14 @@
   };
 }
 
+// Insert properties of b in place into a.
+function Fay$$objConcat(a,b){
+  for (var p in b) if (b.hasOwnProperty(p)){
+    a[p] = b[p];
+  }
+  return a;
+}
+
 /*******************************************************************************
  * Thunks.
  */
@@ -186,7 +198,6 @@
       fayObj = Fay$$_(fayObj.cdr);
     }
     jsObj = arr;
-
   }
   else if(base == "tuple") {
     // Serialize Fay tuple to JavaScript array.
@@ -202,7 +213,7 @@
   }
   else if(base == "defined") {
     fayObj = Fay$$_(fayObj);
-    if (fayObj instanceof $_Language$Fay$FFI$Undefined) {
+    if (fayObj instanceof Fay.FFI._Undefined) {
       jsObj = undefined;
     } else {
       jsObj = Fay$$fayToJs(args[0],fayObj.slot1);
@@ -211,7 +222,7 @@
   }
   else if(base == "nullable") {
     fayObj = Fay$$_(fayObj);
-    if (fayObj instanceof $_Language$Fay$FFI$Null) {
+    if (fayObj instanceof Fay.FFI._Null) {
       jsObj = null;
     } else {
       jsObj = Fay$$fayToJs(args[0],fayObj.slot1);
@@ -228,21 +239,37 @@
   else if(base == "automatic" || base == "user") {
     if(fayObj instanceof Fay$$$)
       fayObj = Fay$$_(fayObj);
-    jsObj = Fay$$fayToJsUserDefined(type,fayObj);
 
+    if(fayObj instanceof Fay$$Cons){
+      // Serialize Fay list to JavaScript array.
+      var arr = [];
+      fayObj = Fay$$_(fayObj);
+      while(fayObj instanceof Fay$$Cons) {
+        arr.push(Fay$$fayToJs(["automatic"],fayObj.car));
+        fayObj = Fay$$_(fayObj.cdr);
+      }
+      jsObj = arr;
+    } else {
+      var fayToJsFun = Fay$$fayToJsHash[fayObj.constructor.name];
+      jsObj = fayToJsFun ? fayToJsFun(type,type[2],fayObj) : fayObj;
+    }
   }
   else
     throw new Error("Unhandled Fay->JS translation type: " + base);
   return jsObj;
 }
 
+// Stores the mappings from fay types to js objects.
+// This will be populated by compiled modules.
+var Fay$$fayToJsHash = {};
+
 // Specialized serializer for string.
 function Fay$$fayToJs_string(fayObj){
   // Serialize Fay string to JavaScript string.
   var str = "";
   fayObj = Fay$$_(fayObj);
   while(fayObj instanceof Fay$$Cons) {
-    str += fayObj.car;
+    str += Fay$$_(fayObj.car);
     fayObj = Fay$$_(fayObj.cdr);
   }
   return str;
@@ -331,17 +358,17 @@
   }
   else if(base == "defined") {
     if (jsObj === undefined) {
-      fayObj = new $_Language$Fay$FFI$Undefined();
+      fayObj = new Fay.FFI._Undefined();
     } else {
-      fayObj = new $_Language$Fay$FFI$Defined(Fay$$jsToFay(args[0],jsObj));
+      fayObj = new Fay.FFI._Defined(Fay$$jsToFay(args[0],jsObj));
     }
 
   }
   else if(base == "nullable") {
     if (jsObj === null) {
-      fayObj = new $_Language$Fay$FFI$Null();
+      fayObj = new Fay.FFI._Null();
     } else {
-      fayObj = new $_Language$Fay$FFI$Nullable(Fay$$jsToFay(args[0],jsObj));
+      fayObj = new Fay.FFI.Nullable(Fay$$jsToFay(args[0],jsObj));
     }
 
   }
@@ -361,8 +388,16 @@
   }
   else if(base == "automatic" || base == "user") {
     if (jsObj && jsObj['instance']) {
-      fayObj = Fay$$jsToFayUserDefined(type,jsObj);
+      var jsToFayFun = Fay$$jsToFayHash[jsObj["instance"]];
+      fayObj = jsToFayFun ? jsToFayFun(type,type[2],jsObj) : jsObj;
     }
+    else if (jsObj instanceof Array) {
+      var list = null;
+      for (var i = jsObj.length - 1; i >= 0; i--) {
+        list = new Fay$$Cons(Fay$$jsToFay([base], jsObj[i]), list);
+      }
+      fayObj = list;
+    }
     else
       fayObj = jsObj;
 
@@ -370,6 +405,10 @@
   else { throw new Error("Unhandled JS->Fay translation type: " + base); }
   return fayObj;
 }
+
+// Stores the mappings from js objects to fay types.
+// This will be populated by compiled modules.
+var Fay$$jsToFayHash = {};
 
 /*******************************************************************************
  * Lists.
diff --git a/src/Fay.hs b/src/Fay.hs
--- a/src/Fay.hs
+++ b/src/Fay.hs
@@ -21,13 +21,11 @@
 import           Fay.Compiler
 import           Fay.Compiler.Misc   (printSrcLoc)
 import           Fay.Compiler.Packages
-import           Fay.Compiler.Print
 import           Fay.Types
 
 import           Control.Applicative
 import           Control.Monad
 import           Data.List
-import qualified Data.Set                     as S
 import           Language.Haskell.Exts        (prettyPrint)
 import           Language.Haskell.Exts.Syntax
 import           Paths_fay
@@ -41,8 +39,8 @@
                   (compileFromToAndGenerateHtml config filein)
                   fileout
   case result of
-    Right out -> maybe (putStrLn out) (flip writeFile out) fileout
-    Left err -> error $ showCompileError $ err
+    Right out -> maybe (putStrLn out) (`writeFile` out) fileout
+    Left err -> error $ showCompileError err
 
 -- | Compile the given file and write to the output, also generate any HTML.
 compileFromToAndGenerateHtml :: CompileConfig -> FilePath -> FilePath -> IO (Either CompileError String)
@@ -56,7 +54,7 @@
           , "<html>"
           , "  <head>"
           ,"    <meta http-equiv='Content-Type' content='text/html; charset=utf-8'>"
-          , unlines . map ("    "++) . map makeScriptTagSrc $ configHtmlJSLibs config
+          , unlines . map (("    "++) . makeScriptTagSrc) $ configHtmlJSLibs config
           , "    " ++ makeScriptTagSrc relativeJsPath
           , "    </script>"
           , "  </head>"
@@ -66,14 +64,12 @@
       return (Right out)
             where relativeJsPath = makeRelative (dropFileName fileout) fileout
                   makeScriptTagSrc :: FilePath -> String
-                  makeScriptTagSrc = \s ->
-                    "<script type=\"text/javascript\" src=\"" ++ s ++ "\"></script>"
+                  makeScriptTagSrc s = "<script type=\"text/javascript\" src=\"" ++ s ++ "\"></script>"
     Left err -> return (Left err)
 
 -- | Compile the given file.
 compileFile :: CompileConfig -> FilePath -> IO (Either CompileError String)
-compileFile config filein = do
-  either Left (Right . fst) <$> compileFileWithState config filein
+compileFile config filein = either Left (Right . fst) <$> compileFileWithState config filein
 
 -- | Compile a file returning the state.
 compileFileWithState :: CompileConfig -> FilePath -> IO (Either CompileError (String,CompileState))
@@ -82,7 +78,7 @@
   hscode <- readFile filein
   raw <- readFile runtime
   config' <- resolvePackages config
-  compileToModule filein config' raw compileToplevelModule hscode
+  compileToModule filein config' raw (compileToplevelModule filein) hscode
 
 -- | Compile the given module to a runnable module.
 compileToModule :: (Show from,Show to,CompilesTo from to)
@@ -91,52 +87,24 @@
                 -> IO (Either CompileError (String,CompileState))
 compileToModule filepath config raw with hscode = do
   result <- compileViaStr filepath config with hscode
-  case result of
-    Left err -> return (Left err)
+  return $ case result of
+    Left err -> Left err
     Right (PrintState{..},state,_) ->
-      return $ Right $ (generate (concat (reverse psOutput))
-                                        (S.toList $ getCurrentExportsWithoutNewtypes state)
-                                        (stateModuleName state), state)
-
-  where generate | configNaked config = generateNaked
-                 | otherwise          = generateWrapped
-        generateNaked jscode _exports _module = unlines $
-          [if configExportRuntime config then raw else ""
-          ,jscode]
-        generateWrapped jscode exports (ModuleName (clean -> modulename)) = unlines $ filter (not . null) $
-          ["/** @constructor"
-          ,"*/"
-          ,"var " ++ modulename ++ " = function(){"
-          ,if configExportRuntime config then raw else ""
-          ,jscode
-          ,"// Exports"
-          ,unlines (map printExport exports)
-          ,"// Built-ins"
-          ,"this._ = Fay$$_;"
-          ,if configExportBuiltins config
-              then unlines ["this.$           = Fay$$$;"
-                           ,"this.$fayToJs    = Fay$$fayToJs;"
-                           ,"this.$jsToFay    = Fay$$jsToFay;"
-                           ]
-              else ""
-          ,"};"
-          ,if not (configLibrary config)
-              then unlines [";"
-                           ,"var main = new " ++ modulename ++ "();"
-                           ,"main._(main." ++ modulename ++ "$main);"
-                           ]
-              else ""
-          ]
-        clean ('.':cs) = '$' : clean cs
-        clean (c:cs)   = c : clean cs
-        clean [] = []
-
--- | Print an this.x = x; export out.
-printExport :: QName -> String
-printExport name =
-  printJSString (JsSetProp JsThis
-                           (JsNameVar name)
-                           (JsName (JsNameVar name)))
+      Right ( generateWrapped (concat $ reverse psOutput)
+                              (stateModuleName state)
+            , state
+            )
+  where
+    generateWrapped jscode (ModuleName modulename) =
+      unlines $ filter (not . null)
+      [if configExportRuntime config then raw else ""
+      ,jscode
+      ,if not (configLibrary config)
+          then unlines [";"
+                       ,"Fay$$_(" ++ modulename ++ ".main);"
+                       ]
+          else ""
+      ]
 
 -- | Convert a Haskell filename to a JS filename.
 toJsName :: String -> String
@@ -147,25 +115,24 @@
 -- | Print a compile error for human consumption.
 showCompileError :: CompileError -> String
 showCompileError e = case e of
-  ParseError _ err -> err
+  ParseError pos err -> err ++ " at line: " ++ show (srcLine pos) ++ " column: " ++ show (srcColumn pos)
   UnsupportedDeclaration d -> "unsupported declaration: " ++ prettyPrint d
   UnsupportedExportSpec es -> "unsupported export specification: " ++ prettyPrint es
-  UnsupportedMatchSyntax m -> "unsupported match/binding syntax: " ++ prettyPrint m
-  UnsupportedWhereInMatch m -> "unsupported `where' syntax: " ++ prettyPrint m
-  UnsupportedWhereInAlt alt -> "`where' not supported here: " ++ prettyPrint alt
   UnsupportedExpression expr -> "unsupported expression syntax: " ++ prettyPrint expr
-  UnsupportedQualStmt stmt -> "unsupported list qualifier: " ++ prettyPrint stmt
-  UnsupportedLiteral lit -> "unsupported literal syntax: " ++ prettyPrint lit
+  UnsupportedFieldPattern p -> "unsupported field pattern: " ++ prettyPrint p
+  UnsupportedImport i -> "unsupported import syntax, we're too lazy: " ++ prettyPrint i
+  UnsupportedLet -> "let not supported here"
   UnsupportedLetBinding d -> "unsupported let binding: " ++ prettyPrint d
-  UnsupportedOperator qop -> "unsupported operator syntax: " ++ prettyPrint qop
+  UnsupportedLiteral lit -> "unsupported literal syntax: " ++ prettyPrint lit
+  UnsupportedModuleSyntax m -> "unsupported module syntax" ++ prettyPrint m
   UnsupportedPattern pat -> "unsupported pattern syntax: " ++ prettyPrint pat
+  UnsupportedQualStmt stmt -> "unsupported list qualifier: " ++ prettyPrint stmt
+  UnsupportedRecursiveDo -> "recursive `do' isn't supported"
   UnsupportedRhs rhs -> "unsupported right-hand side syntax: " ++ prettyPrint rhs
-  UnsupportedGuardedAlts ga -> "unsupported guarded alts: " ++ prettyPrint ga
+  UnsupportedWhereInAlt alt -> "`where' not supported here: " ++ prettyPrint alt
+  UnsupportedWhereInMatch m -> "unsupported `where' syntax: " ++ prettyPrint m
   EmptyDoBlock -> "empty `do' block"
-  UnsupportedModuleSyntax{} -> "unsupported module syntax (may be supported later)"
-  LetUnsupported -> "let not supported here"
   InvalidDoBlock -> "invalid `do' block"
-  RecursiveDoUnsupported -> "recursive `do' isn't supported"
   FfiNeedsTypeSig d -> "your FFI declaration needs a type signature: " ++ prettyPrint d
   FfiFormatBadChars      srcloc cs -> printSrcLoc srcloc ++ ": invalid characters for FFI format string: " ++ show cs
   FfiFormatNoSuchArg     srcloc i  -> printSrcLoc srcloc ++ ": no such argument in FFI format string: " ++ show i
@@ -174,13 +141,11 @@
     printSrcLoc srcloc ++ ":" ++
     "\ninvalid JavaScript code in FFI format string:\n"
                                          ++ err ++ "\nin " ++ code
-  UnsupportedFieldPattern p -> "unsupported field pattern: " ++ prettyPrint p
-  UnsupportedImport i -> "unsupported import syntax, we're too lazy: " ++ prettyPrint i
   Couldn'tFindImport i places ->
     "could not find an import in the path: " ++ prettyPrint i ++ ", \n" ++
     "searched in these places: " ++ intercalate ", " places
-  UnableResolveUnqualified name -> "unable to resolve unqualified name " ++ prettyPrint name
   UnableResolveQualified qname -> "unable to resolve qualified names " ++ prettyPrint qname
+  GHCError s -> "ghc: " ++ s
 
 -- | Get the JS runtime source.
 getRuntime :: IO String
diff --git a/src/Fay/Compiler.hs b/src/Fay/Compiler.hs
--- a/src/Fay/Compiler.hs
+++ b/src/Fay/Compiler.hs
@@ -1,8 +1,9 @@
-{-# LANGUAGE MultiParamTypeClasses #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE FlexibleInstances #-}
-{-# LANGUAGE RecordWildCards #-}
 {-# OPTIONS -Wall -fno-warn-name-shadowing -fno-warn-orphans #-}
+{-# LANGUAGE FlexibleInstances     #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings     #-}
+{-# LANGUAGE RecordWildCards       #-}
+{-# LANGUAGE ViewPatterns          #-}
 
 -- | The Haskell→Javascript compiler.
 
@@ -10,10 +11,14 @@
   (runCompile
   ,compileViaStr
   ,compileToAst
-  ,compileModule
   ,compileExp
   ,compileDecl
   ,compileToplevelModule
+  ,compileModuleFromFile
+  ,compileModuleFromContents
+  ,compileModuleFromName
+  ,compileModule
+  ,compileModuleFromAST
   ,parseFay)
   where
 
@@ -24,8 +29,10 @@
 import           Fay.Compiler.FFI
 import           Fay.Compiler.InitialPass (initialPass)
 import           Fay.Compiler.Misc
+import           Fay.Compiler.ModuleScope (findPrimOp)
 import           Fay.Compiler.Optimizer
 import           Fay.Compiler.Typecheck
+import           Fay.Compiler.QName
 import           Fay.Types
 
 import           Control.Applicative
@@ -76,31 +83,77 @@
                           (parseFay filepath from))
 
 -- | Compile the top-level Fay module.
-compileToplevelModule :: Module -> Compile [JsStmt]
-compileToplevelModule mod@(Module _ (ModuleName modulename) _ _ _ _ _)  = do
+compileToplevelModule :: FilePath -> Module -> Compile [JsStmt]
+compileToplevelModule filein mod@(Module _ (ModuleName modulename) _ _ _ _ _)  = do
   cfg <- config id
-
   when (configTypecheck cfg) $
     typecheck (configPackageConf cfg) (configWall cfg) $
       fromMaybe modulename $ configFilePath cfg
   initialPass mod
   cs <- io defaultCompileState
   modify $ \s -> s { stateImported = stateImported cs }
-  (stmts,CompileWriter{..}) <- listen $ compileModule True mod
-  let fay2js = if null writerFayToJs then [] else fayToJsDispatcher writerFayToJs
-      js2fay = if null writerJsToFay then [] else jsToFayDispatcher writerJsToFay
-      maybeOptimize = if configOptimize cfg then runOptimizer optimizeToplevel else id
-  if configDispatcherOnly cfg
-     then return (maybeOptimize (writerCons ++ fay2js ++ js2fay))
-     else return (maybeOptimize (stmts ++
-                    if configDispatchers cfg then writerCons ++ fay2js ++ js2fay else []))
+  fmap fst . listen $ compileModuleFromFile filein
 
 --------------------------------------------------------------------------------
 -- Compilers
 
--- | Compile Haskell module.
-compileModule :: Bool -> Module -> Compile [JsStmt]
-compileModule toplevel (Module _ modulename _pragmas Nothing _exports imports decls) =
+-- | Read a file and compile.
+compileModuleFromFile :: FilePath -> Compile [JsStmt]
+compileModuleFromFile fp = io (readFile fp) >>= compileModule fp
+
+-- | Compile a source string.
+compileModuleFromContents :: String -> Compile [JsStmt]
+compileModuleFromContents = compileModule "<interactive>"
+
+-- | Lookup a module from include directories and compile.
+compileModuleFromName :: ModuleName -> Compile [JsStmt]
+compileModuleFromName name =
+  unlessImported name compileModule
+    where
+      unlessImported :: ModuleName
+                     -> (FilePath -> String -> Compile [JsStmt])
+                     -> Compile [JsStmt]
+      unlessImported "Fay.Types" _ = return []
+      unlessImported name importIt = do
+        imported <- gets stateImported
+        case lookup name imported of
+          Just _  -> return []
+          Nothing -> do
+            dirs <- configDirectoryIncludePaths <$> config id
+            (filepath,contents) <- findImport dirs name
+            modify $ \s -> s { stateImported = (name,filepath) : imported }
+            importIt filepath contents
+
+-- | Compile given the location and source string.
+compileModule :: FilePath -> String -> Compile [JsStmt]
+compileModule filepath contents = do
+  state <- get
+  reader <- ask
+  result <- io $ compileToAst filepath reader state compileModuleFromAST contents
+  case result of
+    Right (stmts,state,writer) -> do
+      modify $ \s -> s { stateImported      = stateImported state
+                       , stateLocalScope    = S.empty
+                       , stateJsModulePaths = stateJsModulePaths state
+                       }
+      maybeOptimize $ stmts ++ writerCons writer ++ makeTranscoding writer
+    Left err -> throwError err
+  where
+    makeTranscoding :: CompileWriter -> [JsStmt]
+    makeTranscoding CompileWriter{..} =
+      let fay2js = if null writerFayToJs then [] else fayToJsHash writerFayToJs
+          js2fay = if null writerJsToFay then [] else jsToFayHash writerJsToFay
+      in fay2js ++ js2fay
+    maybeOptimize :: [JsStmt] -> Compile [JsStmt]
+    maybeOptimize stmts = do
+      cfg <- config id
+      return $ if configOptimize cfg
+        then runOptimizer optimizeToplevel stmts
+        else stmts
+
+-- | Compile a parse HSE module.
+compileModuleFromAST :: Module -> Compile [JsStmt]
+compileModuleFromAST (Module _ modulename _pragmas Nothing _exports imports decls) =
   withModuleScope $ do
     imported <- fmap concat (mapM compileImport imports)
     modify $ \s -> s { stateModuleName = modulename
@@ -110,54 +163,61 @@
 
     exportStdlib     <- config configExportStdlib
     exportStdlibOnly <- config configExportStdlibOnly
-    if exportStdlibOnly
-       then if anStdlibModule modulename || toplevel
-               then if toplevel
-                       then return imported
-                       else return (current ++ imported)
-               else return []
-       else if not exportStdlib && anStdlibModule modulename
-               then return []
-               else return (imported ++ current)
-compileModule _ mod = throwError (UnsupportedModuleSyntax mod)
+    modulePaths      <- createModulePath modulename
+    extExports       <- generateExports
+    let stmts = imported ++ modulePaths ++ current ++ extExports
+    return $ if exportStdlibOnly
+      then if anStdlibModule modulename
+              then stmts
+              else []
+      else if not exportStdlib && anStdlibModule modulename
+              then []
+              else stmts
+compileModuleFromAST mod = throwError (UnsupportedModuleSyntax mod)
 
-instance CompilesTo Module [JsStmt] where compileTo = compileModule False
+instance CompilesTo Module [JsStmt] where compileTo = compileModuleFromAST
 
+
+-- | For a module A.B, generate
+-- | var A = {};
+-- | A.B = {};
+createModulePath :: ModuleName -> Compile [JsStmt]
+createModulePath =
+  liftM concat . mapM modPath . mkModulePaths
+  where
+    modPath :: ModulePath -> Compile [JsStmt]
+    modPath mp = whenImportNotGenerated mp $ \(unModulePath -> l) -> case l of
+     [n] -> [JsVar (JsNameVar . UnQual $ Ident n) (JsObj [])]
+     _   -> [JsSetModule mp (JsObj [])]
+
+    whenImportNotGenerated :: ModulePath -> (ModulePath -> [JsStmt]) -> Compile [JsStmt]
+    whenImportNotGenerated mp makePath = do
+      added <- gets $ addedModulePath mp
+      if added
+        then return []
+        else do
+          modify $ addModulePath mp
+          return $ makePath mp
+
+-- | Generate exports for non local names, local exports have already been added to the module.
+generateExports :: Compile [JsStmt]
+generateExports = do
+  m <- gets stateModuleName
+  map (exportExp m) . S.toList . getNonLocalExports <$> gets id
+  where
+    exportExp :: ModuleName -> QName -> JsStmt
+    exportExp m v = JsSetQName (changeModule m v) $ case findPrimOp v of
+      Just p  -> JsName $ JsNameVar p
+      Nothing -> JsName $ JsNameVar v
+
 -- | Is the module a standard module, i.e., one that we'd rather not
 -- output code for if we're compiling separate files.
 anStdlibModule :: ModuleName -> Bool
-anStdlibModule (ModuleName name) = elem name ["Prelude","FFI","Language.Fay.FFI","Data.Data"]
+anStdlibModule (ModuleName name) = name `elem` ["Prelude","FFI","Fay.FFI","Data.Data"]
 
 -- | Compile the given import.
 compileImport :: ImportDecl -> Compile [JsStmt]
---  warn $ "import with package syntax ignored: " ++ prettyPrint i
+-- Package imports are ignored since they are used for some trickery in fay-base.
 compileImport (ImportDecl _ _    _     _ Just{}  _       _) = return []
-compileImport (ImportDecl _ name False _ Nothing Nothing _) =
-  unlessImported name $ \filepath contents -> do
-    state <- get
-    reader <- ask
-    result <- liftIO $ compileToAst filepath reader state (compileModule False) contents
-    case result of
-      Right (stmts,state,writer) -> do
-        tell writer
-        modify $ \s -> s { stateImported   = stateImported state
-                         , stateLocalScope = S.empty
-                         }
-        return stmts
-      Left err -> throwError err
+compileImport (ImportDecl _ name False _ Nothing Nothing _) = compileModuleFromName name
 compileImport i = throwError $ UnsupportedImport i
-
-unlessImported :: ModuleName
-               -> (FilePath -> String -> Compile [JsStmt])
-               -> Compile [JsStmt]
-unlessImported "Fay.Types" _ = return []
-unlessImported name importIt = do
-  imported <- gets stateImported
-  case lookup name imported of
-    Just _  -> return []
-    Nothing -> do
-      dirs <- configDirectoryIncludePaths <$> config id
-      (filepath,contents) <- findImport dirs name
-      modify $ \s -> s { stateImported = (name,filepath) : imported }
-      res <- importIt filepath contents
-      return res
diff --git a/src/Fay/Compiler/Config.hs b/src/Fay/Compiler/Config.hs
--- a/src/Fay/Compiler/Config.hs
+++ b/src/Fay/Compiler/Config.hs
@@ -38,29 +38,25 @@
 
 -- | Default configuration.
 instance Default CompileConfig where
-  def =
-    addConfigPackage "fay-base" $
-      CompileConfig
-      { configOptimize           = False
-      , configFlattenApps        = False
-      , configExportBuiltins     = True
-      , configExportRuntime      = True
-      , configExportStdlib       = True
-      , configExportStdlibOnly   = False
-      , configDispatchers        = True
-      , configDispatcherOnly     = False
-      , configNaked              = False
-      , configDirectoryIncludes  = []
-      , configPrettyPrint        = False
-      , configHtmlWrapper        = False
-      , configHtmlJSLibs         = []
-      , configLibrary            = False
-      , configWarn               = True
-      , configFilePath           = Nothing
-      , configTypecheck          = True
-      , configWall               = False
-      , configGClosure           = False
-      , configPackageConf        = Nothing
-      , configPackages           = []
-      , configBasePath           = Nothing
-      }
+  def = addConfigPackage "fay-base"
+    CompileConfig
+    { configOptimize           = False
+    , configFlattenApps        = False
+    , configExportBuiltins     = True
+    , configExportRuntime      = True
+    , configExportStdlib       = True
+    , configExportStdlibOnly   = False
+    , configDirectoryIncludes  = []
+    , configPrettyPrint        = False
+    , configHtmlWrapper        = False
+    , configHtmlJSLibs         = []
+    , configLibrary            = False
+    , configWarn               = True
+    , configFilePath           = Nothing
+    , configTypecheck          = True
+    , configWall               = False
+    , configGClosure           = False
+    , configPackageConf        = Nothing
+    , configPackages           = []
+    , configBasePath           = Nothing
+    }
diff --git a/src/Fay/Compiler/Debug.hs b/src/Fay/Compiler/Debug.hs
--- a/src/Fay/Compiler/Debug.hs
+++ b/src/Fay/Compiler/Debug.hs
@@ -14,7 +14,7 @@
 
 -- | Compile a String of Fay and print it as beautified JavaScript.
 printTestCompile :: String -> IO ()
-printTestCompile = printCompile def { configWarn = False } (compileModule False)
+printTestCompile = printCompile def { configWarn = False } compileModuleFromAST
 
 -- | Compile a Haskell source string to a JavaScript source string.
 compileTestAst :: (Show from,Show to,CompilesTo from to)
@@ -57,5 +57,4 @@
   result <- compileViaStr "<interactive>" config { configPrettyPrint = True } with from
   case result of
     Left err -> print err
-    Right (PrintState{..},_,_) -> do
-      putStrLn (concat (reverse (psOutput)))
+    Right (PrintState{..},_,_) -> putStrLn . concat . reverse $ psOutput
diff --git a/src/Fay/Compiler/Decl.hs b/src/Fay/Compiler/Decl.hs
--- a/src/Fay/Compiler/Decl.hs
+++ b/src/Fay/Compiler/Decl.hs
@@ -67,7 +67,7 @@
           Just sig -> compileFFI srcloc ident formatstr sig
           Nothing  -> throwError (FfiNeedsTypeSig pat)
         _ -> compileUnguardedRhs srcloc toplevel ident rhs
-    PatBind srcloc (PVar ident) Nothing (UnGuardedRhs rhs) bdecls -> do
+    PatBind srcloc (PVar ident) Nothing (UnGuardedRhs rhs) bdecls ->
       compileUnguardedRhs srcloc toplevel ident (Let bdecls rhs)
     PatBind srcloc pat Nothing (UnGuardedRhs rhs) _bdecls -> do
       exp <- compileExp rhs
@@ -79,11 +79,11 @@
 
 -- | Compile a normal simple pattern binding.
 compileUnguardedRhs :: SrcLoc -> Bool -> Name -> Exp -> Compile [JsStmt]
-compileUnguardedRhs srcloc toplevel ident rhs = do
+compileUnguardedRhs _srcloc toplevel ident rhs = do
   unless toplevel $ bindVar ident
   withScope $ do
     body <- compileExp rhs
-    bind <- bindToplevel srcloc toplevel ident (thunk body)
+    bind <- bindToplevel toplevel ident (thunk body)
     return [bind]
 
 -- | Compile a data declaration (or a GADT, latter is converted to former).
@@ -94,7 +94,7 @@
       case condecl of
         ConDecl name types  -> do
           let fields =  map (Ident . ("slot"++) . show . fst) . zip [1 :: Integer ..] $ types
-              fields' = (zip (map return fields) types)
+              fields' = zip (map return fields) types
           cons <- makeConstructor name fields
           func <- makeFunc name fields
           emitFayToJs name tyvars fields'
@@ -123,12 +123,12 @@
   where
     emitCons cons = tell (mempty { writerCons = [cons] })
 
-    -- Creates a constructor R_RecConstr for a Record
+    -- Creates a constructor _RecConstr for a Record
     makeConstructor :: Name -> [Name] -> Compile JsStmt
     makeConstructor name (map (JsNameVar . UnQual) -> fields) = do
       qname <- qualify name
       return $
-        JsExpStmt $
+        JsSetConstructor qname $
           JsFun (Just $ JsConstructor qname)
                 fields
                 (for fields $ \field -> JsSetProp JsThis field (JsName field))
@@ -139,17 +139,23 @@
     makeFunc name (map (JsNameVar . UnQual) -> fields) = do
       let fieldExps = map JsName fields
       qname <- qualify name
-      return $ JsVar (JsNameVar qname) $
-        foldr (\slot inner -> JsFun Nothing [slot] [] (Just inner))
-          (thunk $ JsNew (JsConstructor qname) fieldExps)
-          fields
+      let mp = mkModulePathFromQName qname
+      let func = foldr (\slot inner -> JsFun Nothing [slot] [] (Just inner))
+                       (thunk $ JsNew (JsConstructor qname) fieldExps)
+                       fields
+      added <- gets (addedModulePath mp)
+      if added
+        then return . JsSetQName qname $ JsApp (JsName $ JsBuiltIn "objConcat")
+                                               [func, JsName $ JsNameVar qname]
+        else do
+          modify $ addModulePath mp
+          return $ JsSetQName qname func
 
     -- Creates getters for a RecDecl's values
     makeAccessors :: SrcLoc -> [Name] -> Compile [JsStmt]
-    makeAccessors srcloc fields =
+    makeAccessors _srcloc fields =
       forM fields $ \name ->
-           bindToplevel srcloc
-                        toplevel
+           bindToplevel toplevel
                         name
                         (JsFun Nothing
                                [JsNameVar "x"]
@@ -161,11 +167,10 @@
 -- | Compile a function which pattern matches (causing a case analysis).
 compileFunCase :: Bool -> [Match] -> Compile [JsStmt]
 compileFunCase _toplevel [] = return []
-compileFunCase toplevel matches@(Match srcloc name argslen _ _ _:_) = do
+compileFunCase toplevel matches@(Match _ name argslen _ _ _:_) = do
   pats <- fmap optimizePatConditions (mapM compileCase matches)
   bindVar name
-  bind <- bindToplevel srcloc
-                       toplevel
+  bind <- bindToplevel toplevel
                        name
                        (foldr (\arg inner -> JsFun Nothing [arg] [] (Just inner))
                               (stmtsThunk (concat pats ++ basecase))
@@ -176,7 +181,7 @@
         isWildCardMatch (Match _ _ pats _ _ _) = all isWildCardPat pats
 
         compileCase :: Match -> Compile [JsStmt]
-        compileCase match@(Match _ _ pats _ rhs _) = do
+        compileCase match@(Match _ _ pats _ rhs _) =
           withScope $ do
             whereDecls' <- whereDecls match
             generateScope $ zipWithM (\arg pat -> compilePat (JsName arg) pat []) args pats
diff --git a/src/Fay/Compiler/Defaults.hs b/src/Fay/Compiler/Defaults.hs
--- a/src/Fay/Compiler/Defaults.hs
+++ b/src/Fay/Compiler/Defaults.hs
@@ -29,15 +29,16 @@
 defaultCompileState :: IO CompileState
 defaultCompileState = do
   types <- getDataFileName "src/Language/Fay/Types.hs"
-  return $ CompileState {
-    _stateExports = M.empty
-  , stateModuleName = ModuleName "Main"
-  , stateRecordTypes = []
-  , stateRecords = []
-  , stateNewtypes = []
-  , stateImported = [("Fay.Types",types)]
-  , stateNameDepth = 1
-  , stateLocalScope = S.empty
-  , stateModuleScope = def
-  , stateModuleScopes = M.empty
-  }
+  return CompileState
+    {  _stateExports = M.empty
+    , stateModuleName = ModuleName "Main"
+    , stateRecordTypes = []
+    , stateRecords = []
+    , stateNewtypes = []
+    , stateImported = [("Fay.Types",types)]
+    , stateNameDepth = 1
+    , stateLocalScope = S.empty
+    , stateModuleScope = def
+    , stateModuleScopes = M.empty
+    , stateJsModulePaths = S.empty
+    }
diff --git a/src/Fay/Compiler/Exp.hs b/src/Fay/Compiler/Exp.hs
--- a/src/Fay/Compiler/Exp.hs
+++ b/src/Fay/Compiler/Exp.hs
@@ -2,14 +2,14 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
 
--- | Compile expressions
+-- | Compile expressions.
 
 module Fay.Compiler.Exp where
 
 import Fay.Compiler.Misc
 import Fay.Compiler.Pattern
 import Fay.Compiler.Print
-import Fay.Compiler.FFI             (ffiFun)
+import Fay.Compiler.FFI             (compileFFIExp)
 import Fay.Types
 
 import Control.Applicative
@@ -46,12 +46,12 @@
     EnumFromThen a b              -> compileEnumFromThen a b
     EnumFromThenTo a b z          -> compileEnumFromThenTo a b z
     RecConstr name fieldUpdates   -> compileRecConstr name fieldUpdates
-    RecUpdate rec  fieldUpdates   -> updateRec rec fieldUpdates
+    RecUpdate rec  fieldUpdates   -> compileRecUpdate rec fieldUpdates
     ListComp exp stmts            -> compileExp =<< desugarListComp exp stmts
     ExpTypeSig srcloc exp sig     ->
       case ffiExp exp of
         Nothing -> compileExp exp
-        Just formatstr -> ffiFun srcloc Nothing formatstr sig
+        Just formatstr -> compileFFIExp srcloc Nothing formatstr sig
 
     exp -> throwError (UnsupportedExpression exp)
 
@@ -79,13 +79,14 @@
 
 -- | Compile simple application.
 compileApp :: Exp -> Exp -> Compile JsExp
-compileApp exp1@(Con q) exp2 = do
+compileApp exp1@(Con q) exp2 =
   maybe (compileApp' exp1 exp2) (const $ compileExp exp2) =<< lookupNewtypeConst q
-compileApp exp1@(Var q) exp2 = do
+compileApp exp1@(Var q) exp2 =
   maybe (compileApp' exp1 exp2) (const $ compileExp exp2) =<< lookupNewtypeDest q
 compileApp exp1 exp2 =
   compileApp' exp1 exp2
 
+-- | Helper for compileApp.
 compileApp' :: Exp -> Exp -> Compile JsExp
 compileApp' exp1 exp2 = do
   flattenApps <- config configFlattenApps
@@ -132,7 +133,7 @@
 
 -- | Compile a let expression.
 compileLet :: [Decl] -> Exp -> Compile JsExp
-compileLet decls exp = do
+compileLet decls exp =
   withScope $ do
     generateScope $ mapM compileLetDecl decls
     binds <- mapM compileLetDecl decls
@@ -143,12 +144,11 @@
 compileLetDecl :: Decl -> Compile [JsStmt]
 compileLetDecl decl = do
   compileDecls <- asks readerCompileDecls
-  v <- case decl of
+  case decl of
     decl@PatBind{} -> compileDecls False [decl]
     decl@FunBind{} -> compileDecls False [decl]
     TypeSig{}      -> return []
     _              -> throwError (UnsupportedLetBinding decl)
-  return v
 
 -- | Compile a list expression.
 compileList :: [Exp] -> Compile JsExp
@@ -200,11 +200,11 @@
 -- | Compile guards
 compileGuards :: [GuardedRhs] -> Compile JsStmt
 compileGuards ((GuardedRhs _ (Qualifier (Var (UnQual (Ident "otherwise"))):_) exp):_) =
-  (\e -> JsIf (JsLit (JsBool True)) [JsEarlyReturn e] []) <$> compileExp exp
+  (\e -> JsIf (JsLit $ JsBool True) [JsEarlyReturn e] []) <$> compileExp exp
 compileGuards (GuardedRhs _ (Qualifier guard:_) exp : rest) =
   makeIf <$> fmap force (compileExp guard)
          <*> compileExp exp
-         <*> if null rest then (return []) else do
+         <*> if null rest then return [] else do
            gs' <- compileGuards rest
            return [gs']
     where makeIf gs e gss = JsIf gs [JsEarlyReturn e] gss
@@ -219,10 +219,10 @@
 
 -- | Compile a lambda.
 compileLambda :: [Pat] -> Exp -> Compile JsExp
-compileLambda pats exp = do
+compileLambda pats exp =
   withScope $ do
     generateScope $ generateStatements JsNull
-    exp <- compileExp exp
+    exp   <- compileExp exp
     stmts <- generateStatements exp
     case stmts of
       [JsEarlyReturn fun@JsFun{}] -> return fun
@@ -309,8 +309,9 @@
         -- I couldn't find a code that generates (FieldUpdate (FieldPun ..))
         updateStmt _ u = error ("updateStmt: " ++ show u)
 
-updateRec :: Exp -> [FieldUpdate] -> Compile JsExp
-updateRec rec fieldUpdates = do
+-- | Compile a record update.
+compileRecUpdate :: Exp -> [FieldUpdate] -> Compile JsExp
+compileRecUpdate rec fieldUpdates = do
     record <- force <$> compileExp rec
     let copyName = UnQual (Ident "$_record_to_update")
         copy = JsVar (JsNameVar copyName)
@@ -351,7 +352,7 @@
 
 -- | Make a Fay list.
 makeList :: [JsExp] -> JsExp
-makeList exps = (JsApp (JsName (JsBuiltIn "list")) [JsList exps])
+makeList exps = JsApp (JsName $ JsBuiltIn "list") [JsList exps]
 
 -- | Compile a statement of a do block.
 compileStmt :: Maybe Exp -> Stmt -> Compile (Maybe Exp)
@@ -363,7 +364,7 @@
   where initStmt =
           case stmt of
             Qualifier exp -> return (Just exp)
-            LetStmt{}     -> throwError LetUnsupported
+            LetStmt{}     -> throwError UnsupportedLet
             _             -> throwError InvalidDoBlock
 
         subsequentStmt inner =
@@ -373,8 +374,8 @@
                                                     (QVarOp (UnQual (Symbol ">>")))
                                                     inner))
             LetStmt (BDecls binds) -> return (Just (Let (BDecls binds) inner))
-            LetStmt _ -> throwError LetUnsupported
-            RecStmt{} -> throwError RecursiveDoUnsupported
+            LetStmt _ -> throwError UnsupportedLet
+            RecStmt{} -> throwError UnsupportedRecursiveDo
 
         compileGenerator srcloc pat inner exp = do
           let body = Lambda srcloc [pat] inner
diff --git a/src/Fay/Compiler/FFI.hs b/src/Fay/Compiler/FFI.hs
--- a/src/Fay/Compiler/FFI.hs
+++ b/src/Fay/Compiler/FFI.hs
@@ -1,22 +1,22 @@
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
 {-# LANGUAGE TupleSections     #-}
 {-# LANGUAGE ViewPatterns      #-}
 {-# OPTIONS -Wall #-}
 
--- | Compiling the FFI support.
+-- | Compile FFI definitions.
 
 module Fay.Compiler.FFI
   (emitFayToJs
   ,emitJsToFay
   ,compileFFI
-  ,ffiFun
-  ,jsToFayDispatcher
-  ,fayToJsDispatcher)
-  where
+  ,compileFFIExp
+  ,jsToFayHash
+  ,fayToJsHash
+  ) where
 
 import Fay.Compiler.Misc
 import Fay.Compiler.Print           (printJSString)
+import Fay.Compiler.QName
 import Fay.Types
 
 import Control.Monad.Error
@@ -31,7 +31,7 @@
 import Language.ECMAScript3.Syntax
 import Language.Haskell.Exts        (prettyPrint)
 import Language.Haskell.Exts.Syntax
-import Prelude                      hiding (exp)
+import Prelude                      hiding (exp, mod)
 import Safe
 
 -- | Compile an FFI call.
@@ -43,7 +43,7 @@
 compileFFI srcloc name formatstr sig =
   -- substitute newtypes with their child types before calling
   -- real compileFFI
-  compileFFI' srcloc name formatstr =<< rmNewtys sig
+  compileFFI' =<< rmNewtys sig
 
   where rmNewtys :: Type -> Compile Type
         rmNewtys (TyForall b c t) = TyForall b c <$> rmNewtys t
@@ -61,19 +61,18 @@
         rmNewtys (TyInfix t1 q t2)= flip TyInfix q <$> rmNewtys t1 <*> rmNewtys t2
         rmNewtys (TyKind t k)     = flip TyKind k <$> rmNewtys t
 
-compileFFI' :: SrcLoc -> Name -> String -> Type -> Compile [JsStmt]
-compileFFI' srcloc name formatstr sig = do
-  fun <- ffiFun srcloc (Just name) formatstr sig
-  stmt <- bindToplevel srcloc True name fun
-  return [stmt]
+        compileFFI' :: Type -> Compile [JsStmt]
+        compileFFI' sig' = do
+          fun <- compileFFIExp srcloc (Just name) formatstr sig'
+          stmt <- bindToplevel True name fun
+          return [stmt]
 
-ffiFun :: SrcLoc -> Maybe Name -> String -> Type -> Compile JsExp
-ffiFun srcloc nameopt formatstr sig = do
-  let name = case nameopt of
-               Nothing -> "<exp>"
-               Just n -> n
+-- | Compile an FFI expression (also used when compiling top level definitions).
+compileFFIExp :: SrcLoc -> Maybe Name -> String -> Type -> Compile JsExp
+compileFFIExp srcloc nameopt formatstr sig = do
+  let name = fromMaybe "<exp>" nameopt
   inner <- formatFFI srcloc formatstr (zip params funcFundamentalTypes)
-  case JS.parse JS.parseExpression (prettyPrint name) (printJSString (wrapReturn inner)) of
+  case JS.parse JS.expression (prettyPrint name) (printJSString (wrapReturn inner)) of
     Left err -> throwError (FfiFormatInvalidJavaScript srcloc inner (show err))
     Right exp  -> do
       config' <- config id
@@ -93,7 +92,7 @@
         returnType = last funcFundamentalTypes
 
 -- | Warn about uses of naked x.y which will not play nicely with Google Closure.
-warnDotUses :: SrcLoc -> String -> ParsedExpression -> Compile ()
+warnDotUses :: SrcLoc -> String -> Expression SourcePos -> Compile ()
 warnDotUses srcloc string expr =
   when anyrefs $
     warn $ printSrcLoc srcloc ++ ":\nDot ref syntax used in FFI JS code: " ++ string
@@ -101,20 +100,20 @@
   where anyrefs = not (null (listify dotref expr)) ||
                   not (null (listify ldot expr))
 
-        dotref :: ParsedExpression -> Bool
+        dotref :: Expression SourcePos -> Bool
         dotref x = case x of
           DotRef _ (VarRef _ (Id _ name)) _
-             | elem name globalNames -> False
-          DotRef{}                   -> True
-          _                          -> False
+             | name `elem` globalNames -> False
+          DotRef{}                     -> True
+          _                            -> False
 
         ldot :: LValue SourcePos -> Bool
         ldot x =
           case x of
             LDot _ (VarRef _ (Id _ name)) _
-             | elem name globalNames -> False
-            LDot{}                   -> True
-            _                        -> False
+             | name `elem` globalNames -> False
+            LDot{}                     -> True
+            _                          -> False
 
         globalNames = ["Math","console","JSON"]
 
@@ -122,10 +121,14 @@
 emitFayToJs :: Name -> [TyVarBind] -> [([Name],BangType)] -> Compile ()
 emitFayToJs name tyvars (explodeFields -> fieldTypes) = do
   qname <- qualify name
-  let ctrName = printJSString $ JsConstructor qname
+  let ctrName = printJSString $ unqualName qname
   tell $ mempty { writerFayToJs = [(ctrName, translator)] }
 
   where
+    unqualName :: QName -> Name
+    unqualName (UnQual n) = n
+    unqualName (Qual _ n) = n
+    unqualName Special{}  = error "unqualName: Special{}"
     translator =
       JsFun Nothing
             [JsNameVar "type", argTypes, transcodingObjForced]
@@ -139,10 +142,10 @@
     fieldStmts :: [(Int,(Name,BangType))] -> [JsStmt]
     fieldStmts [] = []
     fieldStmts ((i,fieldType):fts) =
-      (JsVar obj_v field) :
-        (JsIf (JsNeq JsUndefined (JsName obj_v))
+      JsVar obj_v field :
+        JsIf (JsNeq JsUndefined (JsName obj_v))
           [JsSetPropExtern obj_ decl (JsName obj_v)]
-          []) :
+          [] :
         fieldStmts fts
       where
         obj_v = JsNameVar (UnQual (Ident $ "obj_" ++ d))
@@ -327,63 +330,20 @@
   inject n =
     case listToMaybe (drop (n-1) args) of
       Nothing -> throwError (FfiFormatNoSuchArg srcloc n)
-      Just (arg,typ) -> do
+      Just (arg,typ) ->
         return (printJSString (fayToJs SerializeAnywhere typ (JsName arg)))
 
 -- | Generate n name-typ pairs from the given list.
 explodeFields :: [([a], t)] -> [(a, t)]
 explodeFields = concatMap $ \(names,typ) -> map (,typ) names
 
--- | The dispatcher for Fay->JS conversion.
-fayToJsDispatcher :: [(String,JsExp)] -> [JsStmt]
-fayToJsDispatcher cases =
-  [JsVar fayToJsHash $ JsObj cases
-  ,JsExpStmt $
-     JsFun (Just $ JsBuiltIn "fayToJsUserDefined")
-           [JsNameVar "type",transcodingObj]
-           [JsVar transcodingObjForced $ force (JsName transcodingObj)
-           ,JsVar fayToJsFun  $ JsLookup
-                  (JsName fayToJsHash)
-                  (JsGetProp (JsGetProp (JsName transcodingObjForced)
-                                        (JsNameVar "constructor"))
-                             (JsNameVar "name"))
-           ]
-           (Just $ JsTernaryIf
-                 (JsName fayToJsFun)
-                 (JsApp (JsName fayToJsFun)
-                        [JsName $ JsNameVar "type"
-                        ,JsLookup (JsName JsParametrizedType) (JsLit (JsInt 2))
-                        ,JsName transcodingObjForced
-                        ])
-                 (JsName transcodingObj))
-  ]
-  where fayToJsHash = JsBuiltIn "fayToJsHash"
-        fayToJsFun  = JsNameVar "fayToJsFun"
-
-
--- | The dispatcher for JS->Fay conversion.
-jsToFayDispatcher :: [(String,JsExp)] -> [JsStmt]
-jsToFayDispatcher cases =
-  [JsVar jsToFayHash $ JsObj cases
-  ,JsExpStmt $
-     JsFun (Just $ JsBuiltIn "jsToFayUserDefined")
-           [JsNameVar "type",transcodingObj]
-           [JsVar jsToFayFun  $ JsLookup
-                  (JsName jsToFayHash)
-                  (JsGetPropExtern (JsName transcodingObj) "instance")
-           ]
-           (Just $ JsTernaryIf
-                 (JsName jsToFayFun)
-                 (JsApp (JsName jsToFayFun)
-                        [JsName $ JsNameVar "type"
-                        ,JsLookup (JsName JsParametrizedType) (JsLit (JsInt 2))
-                        ,JsName transcodingObj
-                        ])
-                 (JsName transcodingObj))
-  ]
-  where jsToFayHash = JsBuiltIn "jsToFayHash"
-        jsToFayFun  = JsNameVar "jsToFayFun"
+-- | Generate Fay→JS encoding.
+fayToJsHash :: [(String, JsExp)] -> [JsStmt]
+fayToJsHash cases = [JsExpStmt $ JsApp (JsName $ JsBuiltIn "objConcat") [JsName $ JsBuiltIn "fayToJsHash", JsObj cases]]
 
+-- | Generate JS→Fay decoding.
+jsToFayHash :: [(String, JsExp)] -> [JsStmt]
+jsToFayHash cases = [JsExpStmt $ JsApp (JsName $ JsBuiltIn "objConcat") [JsName $ JsBuiltIn "jsToFayHash", JsObj cases]]
 
 -- | Make a JS→Fay decoder.
 emitJsToFay ::  Name -> [TyVarBind] -> [([Name], BangType)] -> Compile ()
@@ -395,7 +355,7 @@
     translator qname =
       JsFun Nothing [JsNameVar "type", argTypes, transcodingObj] []
             (Just $ JsNew (JsConstructor qname)
-                          (map decodeField (map (getIndex name tyvars) fieldTypes)))
+                          (map (decodeField . getIndex name tyvars) fieldTypes))
     -- Decode JS→Fay field
     decodeField :: (Int,(Name,BangType)) -> JsExp
     decodeField (i,(fname,typ)) =
@@ -412,7 +372,7 @@
 getIndex :: Name -> [TyVarBind] -> (Name,BangType) -> (Int,(Name,BangType))
 getIndex name tyvars (sname,ty) =
   case bangType ty of
-    TyVar tyname -> case lookup tyname (zip (map tyvar tyvars) [0..]) of
+    TyVar tyname -> case elemIndex tyname (map tyvar tyvars) of
       Nothing -> error $ "unknown type variable " ++ prettyPrint tyname ++
                          " for " ++ prettyPrint name ++ "." ++ prettyPrint sname ++ "," ++
                          " vars were: " ++ unwords (map prettyPrint tyvars)
diff --git a/src/Fay/Compiler/GADT.hs b/src/Fay/Compiler/GADT.hs
--- a/src/Fay/Compiler/GADT.hs
+++ b/src/Fay/Compiler/GADT.hs
@@ -1,4 +1,8 @@
-module Fay.Compiler.GADT(convertGADT) where
+-- | Convert GADTs into normal data types.
+
+module Fay.Compiler.GADT
+  (convertGADT
+  ) where
 
 import           Language.Haskell.Exts hiding (name, binds)
 
diff --git a/src/Fay/Compiler/InitialPass.hs b/src/Fay/Compiler/InitialPass.hs
--- a/src/Fay/Compiler/InitialPass.hs
+++ b/src/Fay/Compiler/InitialPass.hs
@@ -1,5 +1,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 
+-- | Preprocessing collecting names, data types, newtypes, imports, and exports
+-- for all modules recursively.
 module Fay.Compiler.InitialPass
   (initialPass
   ) where
@@ -14,14 +16,17 @@
 import           Control.Monad.Error
 import           Control.Monad.Extra
 import           Control.Monad.RWS
+import           Control.Monad.IO
+import           Data.List.Extra
 import qualified Data.Set as S
 import qualified Data.Map as M
 import           Language.Haskell.Exts.Parser
 import           Language.Haskell.Exts.Syntax
 import           Prelude hiding (mod, read)
 
+-- | Preprocess and collect all information needed during code generation.
 initialPass :: Module -> Compile ()
-initialPass (Module _ mod _ Nothing exports imports decls) = do
+initialPass (Module _ mod _ Nothing exports imports decls) =
   withModuleScope $ do
     modify $ \s -> s { stateModuleName = mod
                      , stateModuleScope = findTopLevelNames mod decls
@@ -55,12 +60,12 @@
             -> (from -> Compile ())
             -> String
             -> Compile (Either CompileError ((),CompileState,CompileWriter))
-compileWith filepath r st with from = do
-  liftIO $ runCompile r
-                      st
-                      (parseResult (throwError . uncurry ParseError)
-                                   with
-                                   (parseFay filepath from))
+compileWith filepath r st with from =
+  io $ runCompile r
+                  st
+                  (parseResult (throwError . uncurry ParseError)
+                  with
+                  (parseFay filepath from))
 
 -- | Don't re-import the same modules.
 unlessImported :: ModuleName
@@ -88,7 +93,7 @@
 
 -- | Add new types to the state
 compileNewtypeDecl :: [QualConDecl] -> Compile ()
-compileNewtypeDecl [QualConDecl _ _ _ condecl] = do
+compileNewtypeDecl [QualConDecl _ _ _ condecl] =
   case condecl of
       -- newtype declaration without destructor
     ConDecl name  [ty]            -> addNewtype name Nothing ty
@@ -104,7 +109,7 @@
       qcname <- qualify cname
       qdname <- case dname of
                   Nothing -> return Nothing
-                  Just n  -> qualify n >>= return . Just
+                  Just n  -> Just <$> qualify n
       modify (\cs@CompileState{stateNewtypes=nts} ->
                cs{stateNewtypes=(qcname,qdname,getBangTy ty):nts})
 compileNewtypeDecl q = error $ "compileNewtypeDecl: Should be impossible (this is a bug). Got: " ++ show q
@@ -114,7 +119,7 @@
 scanRecordDecls decl = do
   case decl of
     DataDecl _loc DataType _ctx name _tyvarb qualcondecls _deriv -> do
-      let ns = flip map qualcondecls (\(QualConDecl _loc' _tyvarbinds _ctx' condecl) -> conDeclName condecl)
+      let ns = for qualcondecls (\(QualConDecl _loc' _tyvarbinds _ctx' condecl) -> conDeclName condecl)
       addRecordTypeState name ns
     _ -> return ()
 
diff --git a/src/Fay/Compiler/Misc.hs b/src/Fay/Compiler/Misc.hs
--- a/src/Fay/Compiler/Misc.hs
+++ b/src/Fay/Compiler/Misc.hs
@@ -32,11 +32,6 @@
 import           System.Process                  (readProcess)
 import           Text.ParserCombinators.ReadP    (readP_to_S)
 
--- | Extra the string from an ident.
-unname :: Name -> String
-unname (Ident str) = str
-unname _ = error "Expected ident from uname." -- FIXME:
-
 -- | Make an identifier from the built-in HJ module.
 fayBuiltin :: String -> QName
 fayBuiltin = Qual (ModuleName "Fay$") . Ident
@@ -66,7 +61,7 @@
 -- | Resolve a given maybe-qualified name to a fully qualifed name.
 tryResolveName :: QName -> Compile (Maybe QName)
 tryResolveName special@Special{} = return (Just special)
-tryResolveName q@Qual{} = do
+tryResolveName q@Qual{} =
   ModuleScope.resolveName q <$> gets stateModuleScope
 tryResolveName u@(UnQual name) = do
   names <- gets stateLocalScope
@@ -75,9 +70,12 @@
     then return $ Just (UnQual name)
     else maybe (Just <$> qualify name) (return . Just) $ ModuleScope.resolveName u env
 
+-- | Resolve a given maybe-qualified name to a fully qualifed name.
+-- Use this when a resolution failure is a bug.
 unsafeResolveName :: QName -> Compile QName
 unsafeResolveName q = maybe (throwError $ UnableResolveQualified q) return =<< tryResolveName q
 
+-- | Resolve a newtype constructor.
 lookupNewtypeConst :: QName -> Compile (Maybe (Maybe QName,Type))
 lookupNewtypeConst n = do
   mName <- tryResolveName n
@@ -89,6 +87,7 @@
         Nothing -> return Nothing
         Just (_,dname,ty) -> return $ Just (dname,ty)
 
+-- | Resolve a newtype destructor.
 lookupNewtypeDest :: QName -> Compile (Maybe (QName,Type))
 lookupNewtypeDest n = do
   mName <- tryResolveName n
@@ -109,11 +108,15 @@
 qualifyQName n             = return n
 
 -- | Make a top-level binding.
-bindToplevel :: SrcLoc -> Bool -> Name -> JsExp -> Compile JsStmt
-bindToplevel srcloc toplevel name expr = do
-  qname <- (if toplevel then qualify else return . UnQual) name
-  return (JsMappedVar srcloc (JsNameVar qname) expr)
+bindToplevel :: Bool -> Name -> JsExp -> Compile JsStmt
+bindToplevel toplevel name expr =
+  if toplevel
+    then do
+      mod <- gets stateModuleName
+      return $ JsSetQName (Qual mod name) expr
+    else return $ JsVar (JsNameVar $ UnQual name) expr
 
+
 -- | Create a temporary environment and discard it after the given computation.
 withModuleScope :: Compile a -> Compile a
 withModuleScope m = do
@@ -140,7 +143,7 @@
 
 -- | Bind a variable in the current scope.
 bindVar :: Name -> Compile ()
-bindVar name = do
+bindVar name =
   modify $ \s -> s { stateLocalScope = S.insert name (stateLocalScope s) }
 
 -- | Emit exported names.
@@ -166,8 +169,7 @@
   -- qualified imports are not supported yet an error will be thrown
   -- on the import so hopefully this won't be confusing.
   EThingAll (Qual _ _) -> return ()
-  e -> do
-    throwError $ UnsupportedExportSpec e
+  e -> throwError $ UnsupportedExportSpec e
  where
    emitVar = return . UnQual >=> unsafeResolveName >=> emitExport . EVar
    emitCName (VarName n) = emitVar n
@@ -255,7 +257,7 @@
 warn "" = return ()
 warn w = do
   shouldWarn <- config configWarn
-  when shouldWarn . liftIO . hPutStrLn stderr $ "Warning: " ++ w
+  when shouldWarn . io . hPutStrLn stderr $ "Warning: " ++ w
 
 -- | Pretty print a source location.
 printSrcLoc :: SrcLoc -> String
@@ -291,7 +293,7 @@
   go (dir:dirs) name = do
     exists <- io (doesFileExist path)
     if exists
-      then fmap (path,) (fmap stdlibHack (io (readFile path)))
+      then (path,) . stdlibHack <$> io (readFile path)
       else go dirs name
     where
       path = dir </> replace '.' '/' (prettyPrint name) ++ ".hs"
@@ -300,8 +302,7 @@
     throwError $ Couldn'tFindImport name alldirs
 
   stdlibHack
-    | mname == ModuleName "Language.Fay.Stdlib" = \s -> s ++ "\n\ndata Maybe a = Just a | Nothing"
-    | mname == ModuleName "Language.Fay.FFI"    = const "module Language.Fay.FFI where\n\ndata Nullable a = Nullable a | Null\n\ndata Defined a = Defined a | Undefined"
+    | mname == ModuleName "Fay.FFI" = const "module Fay.FFI where\n\ndata Nullable a = Nullable a | Null\n\ndata Defined a = Defined a | Undefined"
     | otherwise = id
 
 -- | Run the compiler.
diff --git a/src/Fay/Compiler/ModuleScope.hs b/src/Fay/Compiler/ModuleScope.hs
--- a/src/Fay/Compiler/ModuleScope.hs
+++ b/src/Fay/Compiler/ModuleScope.hs
@@ -8,10 +8,11 @@
   ,bindAsLocals
   ,findTopLevelNames
   ,resolveName
-  ,moduleLocals)
-  where
+  ,moduleLocals
+  ,findPrimOp
+  ) where
 
-import Fay.Compiler.GADT
+import           Fay.Compiler.GADT
 
 import           Control.Arrow
 import           Control.Monad.Reader
@@ -63,7 +64,7 @@
 bindAsLocals qs (ModuleScope binds) =
   -- This needs to be changed to not use unqual to support qualified imports.
   ModuleScope $ binds `M.union` M.fromList (map (unqual &&& id) qs)
-    where unqual (Qual _ n) = (UnQual n)
+    where unqual (Qual _ n) = UnQual n
           unqual u@UnQual{} = u
           unqual Special{}  = error "fay: ModuleScope.bindAsLocals: Special"
 
@@ -90,25 +91,30 @@
 -- So e.g. will compile to (*) Fay$$mult, which is in runtime.js.
 envPrimOpsMap :: Map Name QName
 envPrimOpsMap = M.fromList
-  [ (Symbol ">>",    (Qual (ModuleName "Fay$") (Ident "then")))
-  , (Symbol ">>=",   (Qual (ModuleName "Fay$") (Ident "bind")))
-  , (Ident "return", (Qual (ModuleName "Fay$") (Ident "return")))
-  , (Ident "force",  (Qual (ModuleName "Fay$") (Ident "force")))
-  , (Ident "seq",    (Qual (ModuleName "Fay$") (Ident "seq")))
-  , (Symbol "*",     (Qual (ModuleName "Fay$") (Ident "mult")))
-  , (Symbol "+",     (Qual (ModuleName "Fay$") (Ident "add")))
-  , (Symbol "-",     (Qual (ModuleName "Fay$") (Ident "sub")))
-  , (Symbol "/",     (Qual (ModuleName "Fay$") (Ident "divi")))
-  , (Symbol "==",    (Qual (ModuleName "Fay$") (Ident "eq")))
-  , (Symbol "/=",    (Qual (ModuleName "Fay$") (Ident "neq")))
-  , (Symbol ">",     (Qual (ModuleName "Fay$") (Ident "gt")))
-  , (Symbol "<",     (Qual (ModuleName "Fay$") (Ident "lt")))
-  , (Symbol ">=",    (Qual (ModuleName "Fay$") (Ident "gte")))
-  , (Symbol "<=",    (Qual (ModuleName "Fay$") (Ident "lte")))
-  , (Symbol "&&",    (Qual (ModuleName "Fay$") (Ident "and")))
-  , (Symbol "||",    (Qual (ModuleName "Fay$") (Ident "or")))
+  [ (Symbol ">>",    Qual (ModuleName "Fay$") (Ident "then"))
+  , (Symbol ">>=",   Qual (ModuleName "Fay$") (Ident "bind"))
+  , (Ident "return", Qual (ModuleName "Fay$") (Ident "return"))
+  , (Ident "force",  Qual (ModuleName "Fay$") (Ident "force"))
+  , (Ident "seq",    Qual (ModuleName "Fay$") (Ident "seq"))
+  , (Symbol "*",     Qual (ModuleName "Fay$") (Ident "mult"))
+  , (Symbol "+",     Qual (ModuleName "Fay$") (Ident "add"))
+  , (Symbol "-",     Qual (ModuleName "Fay$") (Ident "sub"))
+  , (Symbol "/",     Qual (ModuleName "Fay$") (Ident "divi"))
+  , (Symbol "==",    Qual (ModuleName "Fay$") (Ident "eq"))
+  , (Symbol "/=",    Qual (ModuleName "Fay$") (Ident "neq"))
+  , (Symbol ">",     Qual (ModuleName "Fay$") (Ident "gt"))
+  , (Symbol "<",     Qual (ModuleName "Fay$") (Ident "lt"))
+  , (Symbol ">=",    Qual (ModuleName "Fay$") (Ident "gte"))
+  , (Symbol "<=",    Qual (ModuleName "Fay$") (Ident "lte"))
+  , (Symbol "&&",    Qual (ModuleName "Fay$") (Ident "and"))
+  , (Symbol "||",    Qual (ModuleName "Fay$") (Ident "or"))
   ]
 
+-- | Lookup a primop that was resolved to a Prelude definition.
+findPrimOp :: QName -> Maybe QName
+findPrimOp (Qual (ModuleName "Prelude") s) = M.lookup s envPrimOpsMap
+findPrimOp _ = Nothing
+
 --------------------------------------------------------------------------------
 -- AST
 
@@ -123,13 +129,13 @@
 
 d_decl :: Decl -> ModuleScopeSt
 d_decl d = case d of
-  DataDecl _ _ _ _ _ dd _         -> mapM_ d_qualCon dd
-  GDataDecl _ DataType _l _i _v _n decls _ -> mapM_ d_qualCon (map convertGADT decls)
-  PatBind _ (PVar n) _ _ _        -> bindName n
-  FunBind (Match _ n _ _ _ _ : _) -> bindName n
-  ClassDecl _ _ _ _ _ cds         -> mapM_ d_classDecl cds
-  TypeSig _ ns _                  -> mapM_ bindName ns
-  _                               -> return ()
+  DataDecl _ _ _ _ _ dd _           -> mapM_ d_qualCon dd
+  GDataDecl _ DataType _ _ _ _ ds _ -> mapM_ (d_qualCon . convertGADT) ds
+  PatBind _ (PVar n) _ _ _          -> bindName n
+  FunBind (Match _ n _ _ _ _ : _)   -> bindName n
+  ClassDecl _ _ _ _ _ cds           -> mapM_ d_classDecl cds
+  TypeSig _ ns _                    -> mapM_ bindName ns
+  _                                 -> return ()
 
 d_classDecl :: ClassDecl -> ModuleScopeSt
 d_classDecl cd = case cd of
diff --git a/src/Fay/Compiler/Optimizer.hs b/src/Fay/Compiler/Optimizer.hs
--- a/src/Fay/Compiler/Optimizer.hs
+++ b/src/Fay/Compiler/Optimizer.hs
@@ -40,7 +40,7 @@
 runOptimizer :: ([JsStmt] -> Optimize [JsStmt]) -> [JsStmt] -> [JsStmt]
 runOptimizer optimizer stmts =
   let (newstmts,OptState _ uncurried) = flip runState st $ optimizer stmts
-  in (newstmts ++ (tco (catMaybes (map (uncurryBinding newstmts) (nub uncurried)))))
+  in newstmts ++ (tco . mapMaybe (uncurryBinding newstmts) $ nub uncurried)
   where st = OptState stmts []
 
 -- | Inline x >> y to x;y in the JS output.
@@ -56,6 +56,9 @@
       JsWhile exp stmts       -> JsWhile (inline exp) (map go stmts)
       JsUpdate name exp       -> JsUpdate name (inline exp)
       JsSetProp a b exp       -> JsSetProp a b (inline exp)
+      JsSetQName a exp        -> JsSetQName a (inline exp)
+      JsSetModule a exp       -> JsSetModule a (inline exp)
+      JsSetConstructor a exp  -> JsSetConstructor a (inline exp)
       JsSetPropExtern a b exp -> JsSetPropExtern a b (inline exp)
       JsContinue              -> JsContinue
       JsBlock stmts           -> JsBlock (map go stmts)
@@ -64,9 +67,7 @@
   inline expr =
     case expr of
       -- Optimizations
-      JsApp op args -> case flatten expr of
-        Nothing -> JsApp (inline op) (map inline args)
-        Just x  -> x
+      JsApp op args -> fromMaybe (JsApp (inline op) $ map inline args) (flatten expr)
 
       -- Plumbing
       JsFun nm names stmts mexp        -> JsFun nm names (map go stmts) (fmap inline mexp)
@@ -101,10 +102,9 @@
 collect :: JsExp -> Maybe [JsExp]
 collect exp =
   case exp of
-    JsApp op args | isThen op -> do
+    JsApp op args | isThen op ->
       case args of
-        [rest,x] -> do xs <- collect rest
-                       return (x : xs)
+        [rest,x] -> (x :) <$> collect rest
         [x]  -> return [x]
         _ -> Nothing
     _ -> return [exp]
@@ -224,7 +224,7 @@
 
 -- | Collect functions and their arity from the whole codeset.
 collectFuncs :: [JsStmt] -> [FuncArity]
-collectFuncs = (++ prim) . concat . map collectFunc where
+collectFuncs = (++ prim) . concatMap collectFunc where
   collectFunc (JsMappedVar _ name exp) = collectFunc (JsVar name exp)
   collectFunc (JsVar (JsNameVar name) exp) | arity > 0 = [(name,arity)]
     where arity = expArity exp
diff --git a/src/Fay/Compiler/Packages.hs b/src/Fay/Compiler/Packages.hs
--- a/src/Fay/Compiler/Packages.hs
+++ b/src/Fay/Compiler/Packages.hs
@@ -22,7 +22,7 @@
 -- | Given a configuration, resolve any packages specified to their
 -- data file directories for importing the *.hs sources.
 resolvePackages :: CompileConfig -> IO CompileConfig
-resolvePackages config = do
+resolvePackages config =
   foldM resolvePackage config (configPackages config)
 
 -- | Resolve package.
@@ -38,7 +38,7 @@
                     else fmap ($ nameVer) getShareGen
       let includes = [shareDir,shareDir </> "src"]
       exists <- mapM doesSourceDirExist includes
-      if any id exists
+      if or exists
          then return (addConfigDirectoryIncludes (map (Just nameVer,) includes) config)
          else error $ "unable to find (existing) package's share dir: " ++ name ++ "\n" ++
                       "tried: " ++ unlines includes ++ "\n" ++
@@ -62,8 +62,7 @@
     Left  (err,_out) -> error $ "ghc-pkg describe error:\n" ++ err
     Right (_err,out) -> return out
 
-  where args = concat [["describe",name]
-                      ,["-f" ++ db' | Just db' <- [db]]]
+  where args = ["describe",name] ++ ["-f" ++ db' | Just db' <- [db]]
 
 -- | Get the package version from the package description.
 packageVersion :: String -> Maybe String
diff --git a/src/Fay/Compiler/Pattern.hs b/src/Fay/Compiler/Pattern.hs
--- a/src/Fay/Compiler/Pattern.hs
+++ b/src/Fay/Compiler/Pattern.hs
@@ -6,6 +6,7 @@
 module Fay.Compiler.Pattern where
 
 import Fay.Compiler.Misc
+import Fay.Compiler.QName
 import Fay.Types
 
 import Control.Monad.Error
@@ -75,10 +76,6 @@
 
         compilePats' _ (pat:_) = throwError (UnsupportedFieldPattern pat)
 
-        unQual (Qual _ n) = n
-        unQual (UnQual n) = n
-        unQual Special{} = error "Trying to unqualify a Special..."
-
 -- | Compile a literal value from a pattern match.
 compilePLit :: JsExp -> Literal -> [JsStmt] -> Compile [JsStmt]
 compilePLit exp literal body = do
@@ -101,9 +98,10 @@
 compilePAsPat :: JsExp -> Name -> Pat -> [JsStmt] -> Compile [JsStmt]
 compilePAsPat exp name pat body = do
   bindVar name
-  x <- compilePat exp pat body
-  return ([JsVar (JsNameVar (UnQual name)) exp] ++ x)
+  p <- compilePat exp pat body
+  return $ JsVar (JsNameVar $ UnQual name) exp : p
 
+-- | Compile a pattern match on a newtype.
 compileNewtypePat :: [Pat] -> JsExp -> [JsStmt] -> Compile [JsStmt]
 compileNewtypePat [pat] exp body = compilePat exp pat body
 compileNewtypePat ps _ _ = error $ "compileNewtypePat: Should be impossible (this is a bug). Got: " ++ show ps
@@ -156,7 +154,7 @@
 compileInfixPat :: JsExp -> Pat -> [JsStmt] -> Compile [JsStmt]
 compileInfixPat exp pat@(PInfixApp left (Special cons) right) body =
   case cons of
-    Cons -> do
+    Cons ->
       withScopedTmpJsName $ \tmpName -> do
         let forcedExp = JsName tmpName
             x = JsGetProp forcedExp (JsNameVar "car")
diff --git a/src/Fay/Compiler/Print.hs b/src/Fay/Compiler/Print.hs
--- a/src/Fay/Compiler/Print.hs
+++ b/src/Fay/Compiler/Print.hs
@@ -1,8 +1,9 @@
-{-# OPTIONS -fno-warn-orphans #-}
+{-# OPTIONS -fno-warn-orphans        #-}
 {-# OPTIONS -fno-warn-unused-do-bind #-}
-{-# LANGUAGE FlexibleInstances    #-}
-{-# LANGUAGE RecordWildCards      #-}
-{-# LANGUAGE TypeSynonymInstances #-}
+{-# LANGUAGE FlexibleInstances       #-}
+{-# LANGUAGE RecordWildCards         #-}
+{-# LANGUAGE TypeSynonymInstances    #-}
+{-# LANGUAGE ViewPatterns            #-}
 
 -- | Simple code (non-pretty) printing.
 --
@@ -54,7 +55,8 @@
 instance Printable QName where
   printJS qname =
     case qname of
-      Qual moduleName name -> moduleName +> "$" +> name
+      Qual (ModuleName "Fay$") name -> "Fay$$" +> name
+      Qual moduleName name -> moduleName +> "." +> name
       UnQual name -> printJS name
       Special con -> printJS con
 
@@ -64,7 +66,7 @@
     write "Fay$"
   printJS (ModuleName moduleName) = write $ go moduleName
 
-    where go ('.':xs) = '$' : go xs
+    where go ('.':xs) = '.' : go xs
           go (x:xs) = normalizeName [x] ++ go xs
           go [] = []
 
@@ -81,7 +83,7 @@
 instance Printable Name where
   printJS name = write $
     case name of
-      Ident ident -> encodeName ident
+      Ident  idn -> encodeName idn
       Symbol sym -> encodeName sym
 
 -- | Print a list of statements.
@@ -100,6 +102,12 @@
     name +> " = " +> expr +> ";" +> newline
   printJS (JsSetProp name prop expr) =
     name +> "." +> prop +> " = " +> expr +> ";" +> newline
+  printJS (JsSetQName name expr) =
+    name +> " = " +> expr +> ";" +> newline
+  printJS (JsSetConstructor name expr) =
+    printCons name +> " = " +> expr +> ";" +> newline
+  printJS (JsSetModule mp expr) =
+    mp +> " = " +> expr +> ";" +> newline
   printJS (JsSetPropExtern name prop expr) =
     name +> "['" +> prop +> "'] = " +> expr +> ";" +> newline
   printJS (JsIf exp thens elses) =
@@ -122,6 +130,10 @@
   printJS (JsMappedVar _ name expr) =
     "var " +> name +> " = " +> expr +> ";" +> newline
 
+-- | Print a module path.
+instance Printable ModulePath where
+  printJS (unModulePath -> l) = write $ intercalate "." l
+
 -- | Print an expression.
 instance Printable JsExp where
   printJS (JsSeq es) = "(" +> intercalateM "," (map printJS es) +> ")"
@@ -165,9 +177,14 @@
   printJS (JsObj assoc) =
     "{" +> (intercalateM "," (map cons assoc)) +> "}"
       where cons (key,value) = "\"" +> key +> "\": " +> value
+  printJS (JsLitObj assoc) =
+    "{" +> (intercalateM "," (map cons assoc)) +> "}"
+      where
+        cons :: (Name, JsExp) -> Printer ()
+        cons (key,value) = "\"" +> key +> "\": " +> value
   printJS (JsFun nm params stmts ret) =
-    "function"
-    +> maybe (return ()) ((" " +>) . printJS) nm
+       "function"
+    +> maybe (return ()) ((" " +>) . printJS . ident) nm
     +> "("
     +> (intercalateM "," (map printJS params))
     +> "){" +> newline
@@ -184,7 +201,17 @@
      where isFunc JsFun{..} = True; isFunc _ = False
   printJS (JsNegApp args) =
       "(-(" +> printJS args +> "))"
+  printJS (JsAnd a b) =
+      printJS a +> "&&" +> printJS b
+  printJS (JsOr a b) =
+      printJS a +> "||" +> printJS b
 
+-- | Unqualify a JsName.
+ident :: JsName -> JsName
+ident n = case n of
+  JsConstructor (Qual _ s) -> JsNameVar $ UnQual s
+  a -> a
+
 -- | Print one of the kinds of names.
 instance Printable JsName where
   printJS name =
@@ -196,10 +223,21 @@
       JsApply             -> write "Fay$$__"
       JsParam i           -> write ("$p" ++ show i)
       JsTmp i             -> write ("$tmp" ++ show i)
-      JsConstructor qname -> "$_" +> printJS qname
+      JsConstructor qname -> printCons qname
       JsBuiltIn qname     -> "Fay$$" +> printJS qname
       JsParametrizedType  -> write "type"
+      JsModuleName (ModuleName m) -> write m
 
+-- | Print a constructor name given a QName.
+printCons :: QName -> Printer ()
+printCons (UnQual n) = printConsName n
+printCons (Qual (ModuleName m) n) = printJS m +> "." +> printConsName n
+printCons (Special _) = error "qname2String Special"
+
+-- | Print a constructor name given a Name. Helper for printCons.
+printConsName :: Name -> Printer ()
+printConsName n = write "_" >> printJS n
+
 -- | Just write out strings.
 instance Printable String where
   printJS = write
@@ -224,7 +262,11 @@
   ,"static","super","switch","synchronized","this","throw","throws"
   ,"transient","true","try","typeof","undefined","var","void","while"
   ,"window","with","yield"]
+  -- These are not reserved, but they exist on thunks (inherited from Object) meaning they shouldn't be overridden.
+  -- The problem only occurs if there is a module A.B and a constructor B in module A.
+   ++ ["__defineGetter__", "__defineSetter__", "__lookupGetter__", "__lookupSetter__", "constructor", "force", "forced", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "value", "valueOf"]
 
+
 -- | Encode a Haskell name to JavaScript.
 encodeName :: String -> String
 -- | This is a hack for names generated in the Haskell AST. Should be
@@ -235,7 +277,7 @@
   | otherwise                 = normalizeName name
 
 -- | Normalize the given name to JavaScript-valid names.
-normalizeName :: [Char] -> [Char]
+normalizeName :: String -> String
 normalizeName name =
   concatMap encodeChar name
 
diff --git a/src/Fay/Compiler/QName.hs b/src/Fay/Compiler/QName.hs
new file mode 100644
--- /dev/null
+++ b/src/Fay/Compiler/QName.hs
@@ -0,0 +1,27 @@
+-- | Extras for haskell-src-exts names.
+
+module Fay.Compiler.QName where
+
+import Language.Haskell.Exts.Syntax
+
+-- | Extract the module name from a qualified name.
+qModName :: QName -> Maybe ModuleName
+qModName (Qual m _) = Just m
+qModName _          = Nothing
+
+-- | Extract the name from a QName.
+unQual :: QName -> Name
+unQual (Qual _ n) = n
+unQual (UnQual n) = n
+unQual Special{} = error "unQual Special{}"
+
+-- | Change or add the ModuleName of a QName.
+changeModule :: ModuleName -> QName -> QName
+changeModule m (Qual _ n) = Qual m n
+changeModule m (UnQual n) = Qual m n
+changeModule _ Special{}  = error "changeModule Special{}"
+
+-- | Extract the string from a Name.
+unname :: Name -> String
+unname (Ident s) = s
+unname (Symbol s) = s
diff --git a/src/Fay/Compiler/Typecheck.hs b/src/Fay/Compiler/Typecheck.hs
--- a/src/Fay/Compiler/Typecheck.hs
+++ b/src/Fay/Compiler/Typecheck.hs
@@ -3,6 +3,7 @@
 module Fay.Compiler.Typecheck where
 
 import           Control.Monad.IO
+import           Control.Monad.Error
 import           Data.List
 import           Data.Maybe
 import           Fay.Compiler.Misc
@@ -29,14 +30,15 @@
         return [flag ++ '=' : pk]
   let flags =
           [ "-fno-code"
+          , "-XNoImplicitPrelude"
           , "-hide-package base"
           , "-cpp", "-DFAY=1"
           , "-main-is"
           , "Language.Fay.DummyMain"
-          , "-i" ++ concat (intersperse ":" includeDirs)
+          , "-i" ++ intercalate ":" includeDirs
           , fp ] ++ ghcPackageDbArgs ++ wallF ++ map ("-package " ++) packages
   res <- io $ readAllFromProcess GHCPaths.ghc flags ""
-  either (error . fst) (warn . fst) res
+  either (throwError . GHCError . fst) (warn . fst) res
    where
     wallF | wall = ["-Wall"]
           | otherwise = []
diff --git a/src/Fay/Convert.hs b/src/Fay/Convert.hs
--- a/src/Fay/Convert.hs
+++ b/src/Fay/Convert.hs
@@ -97,7 +97,7 @@
 
 -- | Convert a value representing a Fay value to a Haskell value.
 readFromFay :: Data a => Value -> Maybe a
-readFromFay value = do
+readFromFay value =
   parseDataOrTuple value
   `ext1R` parseArray value
   `extR` parseDouble value
diff --git a/src/Fay/FFI.hs b/src/Fay/FFI.hs
new file mode 100644
--- /dev/null
+++ b/src/Fay/FFI.hs
@@ -0,0 +1,49 @@
+{-# LANGUAGE NoImplicitPrelude    #-}
+{-# LANGUAGE TypeSynonymInstances #-}
+
+-- | The internal FFI module.
+
+module Fay.FFI
+  (Fay
+  ,Nullable (..)
+  ,Defined (..)
+  ,Ptr
+  ,Automatic
+  ,ffi)
+  where
+
+import           Fay.Types
+import           Prelude      (Bool, Char, Double, Int, Maybe, String, error)
+
+-- | Values that may be null
+--  Nullable x decodes to x, Null decodes to null.
+data Nullable a = Nullable a | Null
+
+-- | Values that may be undefined
+-- Defined x encodes to x, Undefined decodes to undefined.
+-- An undefined property in a record will be removed when encoding.
+data Defined a = Defined a | Undefined
+
+-- | Do not serialize the specified type. This is useful for, e.g.
+--
+-- > foo :: String -> String
+-- > foo = ffi "%1"
+--
+-- This would normally serialize and unserialize the string, for no
+-- reason, in this case. Instead:
+--
+-- > foo :: Ptr String -> Ptr String
+--
+-- Will just give an identity function.
+type Ptr a = a
+
+-- | The opposite of "Ptr". Serialize the specified polymorphic type.
+--
+-- > foo :: Automatic a -> String
+--
+type Automatic a = a
+
+-- | Declare a foreign action.
+ffi :: String        -- ^ The foreign value.
+    -> a             -- ^ Bottom.
+ffi = error "Fay.FFI.ffi: Used foreign function outside a JS engine context."
diff --git a/src/Fay/Types.hs b/src/Fay/Types.hs
--- a/src/Fay/Types.hs
+++ b/src/Fay/Types.hs
@@ -4,6 +4,7 @@
 {-# LANGUAGE GeneralizedNewtypeDeriving #-}
 {-# LANGUAGE MultiParamTypeClasses      #-}
 {-# LANGUAGE OverloadedStrings          #-}
+{-# LANGUAGE RecordWildCards            #-}
 
 -- | All Fay types and instances.
 
@@ -23,6 +24,7 @@
   ,CompileState(..)
   ,addCurrentExport
   ,getCurrentExports
+  ,getNonLocalExports
   ,getCurrentExportsWithoutNewtypes
   ,getExportsFor
   ,faySourceDir
@@ -30,8 +32,14 @@
   ,PrintState(..)
   ,Printer(..)
   ,Mapping(..)
-  ,SerializeContext(..))
-  where
+  ,SerializeContext(..)
+  ,ModulePath (unModulePath)
+  ,mkModulePath
+  ,mkModulePaths
+  ,mkModulePathFromQName
+  ,addModulePath
+  ,addedModulePath
+  ) where
 
 import           Control.Applicative
 import           Control.Monad.Error    (Error, ErrorT, MonadError)
@@ -39,6 +47,8 @@
 import           Control.Monad.State
 import           Control.Monad.RWS
 import           Data.Default
+import           Data.List
+import           Data.List.Split
 import           Data.Maybe
 import           Data.Map              (Map)
 import qualified Data.Map              as M
@@ -46,9 +56,9 @@
 import qualified Data.Set              as S
 import           Data.String
 import           Language.Haskell.Exts
-import           System.FilePath
 
 import           Fay.Compiler.ModuleScope (ModuleScope)
+import           Fay.Compiler.QName
 import           Paths_fay
 
 --------------------------------------------------------------------------------
@@ -62,9 +72,6 @@
   , configExportRuntime      :: Bool                       -- ^ Export the runtime?
   , configExportStdlib       :: Bool                       -- ^ Export the stdlib?
   , configExportStdlibOnly   :: Bool                       -- ^ Export /only/ the stdlib?
-  , configDispatchers        :: Bool                       -- ^ Export dispatchers?
-  , configDispatcherOnly     :: Bool                       -- ^ Export /only/ the dispatcher?
-  , configNaked              :: Bool                       -- ^ Export without a module wrapper?
   , configDirectoryIncludes :: [(Maybe String, FilePath)]  -- ^ Possibly a fay package name, and a include directory.
   , configPrettyPrint        :: Bool                       -- ^ Pretty print the JS output?
   , configHtmlWrapper        :: Bool                       -- ^ Output a HTML file including the produced JS.
@@ -80,6 +87,25 @@
   , configBasePath           :: Maybe FilePath             -- ^ Custom source location for fay-base
   } deriving (Show)
 
+-- | The name of a module split into a list for code generation.
+newtype ModulePath = ModulePath { unModulePath :: [String] }
+  deriving (Eq, Ord, Show)
+
+-- | Construct the complete ModulePath from a ModuleName.
+mkModulePath :: ModuleName -> ModulePath
+mkModulePath (ModuleName m) = ModulePath . splitOn "." $ m
+
+-- | Construct intermediate module paths from a ModuleName.
+-- mkModulePaths "A.B" => [["A"], ["A","B"]]
+mkModulePaths :: ModuleName -> [ModulePath]
+mkModulePaths (ModuleName m) = map ModulePath . tail . inits . splitOn "." $ m
+
+-- | Converting a QName to a ModulePath is only relevant for constructors since
+-- they can conflict with module names.
+mkModulePathFromQName :: QName -> ModulePath
+mkModulePathFromQName (Qual (ModuleName m) n) = mkModulePath $ ModuleName $ m ++ "." ++ unname n
+mkModulePathFromQName _ = error "mkModulePathFromQName: Not a qualified name"
+
 -- | State of the compiler.
 data CompileState = CompileState
   { _stateExports     :: Map ModuleName (Set QName) -- ^ Collects exports from modules
@@ -92,6 +118,7 @@
   , stateModuleScope  :: ModuleScope                -- ^ Names in the module scope.
   , stateModuleScopes :: Map ModuleName ModuleScope
   , stateModuleName   :: ModuleName                 -- ^ Name of the module currently being compiled.
+  , stateJsModulePaths :: Set ModulePath
   } deriving (Show)
 
 -- | Things written out by the compiler.
@@ -117,8 +144,16 @@
 
 -- | The data-files source directory.
 faySourceDir :: IO FilePath
-faySourceDir = fmap (takeDirectory . takeDirectory . takeDirectory) (getDataFileName "src/Language/Fay/Stdlib.hs")
+faySourceDir = getDataFileName "src/"
 
+-- | Add a ModulePath to CompileState, meaning it has been printed.
+addModulePath :: ModulePath -> CompileState -> CompileState
+addModulePath mp cs = cs { stateJsModulePaths = mp `S.insert` stateJsModulePaths cs }
+
+-- | Has this ModulePath been added/printed?
+addedModulePath :: ModulePath -> CompileState -> Bool
+addedModulePath mp CompileState{..} = mp `S.member` stateJsModulePaths
+
 -- | Adds a new export to '_stateExports' for the module specified by
 -- 'stateModuleName'.
 addCurrentExport :: QName -> CompileState -> CompileState
@@ -128,10 +163,15 @@
     qnames = maybe (S.singleton q) (S.insert q)
            $ M.lookup (stateModuleName cs) (_stateExports cs)
 
--- | Get all of the exported identifiers for the current module.
+-- | Get all exports for the current module.
 getCurrentExports :: CompileState -> Set QName
 getCurrentExports cs = getExportsFor (stateModuleName cs) cs
 
+-- | Get exports from the current module originating from other modules.
+getNonLocalExports :: CompileState -> Set QName
+getNonLocalExports st = S.filter ((/= Just (stateModuleName st)) . qModName) . getCurrentExportsWithoutNewtypes $ st
+
+-- | Get all exports from the current module except newtypes.
 getCurrentExportsWithoutNewtypes :: CompileState -> Set QName
 getCurrentExportsWithoutNewtypes cs = excludeNewtypes cs $ getCurrentExports cs
   where
@@ -199,32 +239,29 @@
   = ParseError SrcLoc String
   | UnsupportedDeclaration Decl
   | UnsupportedExportSpec ExportSpec
-  | UnsupportedMatchSyntax Match
-  | UnsupportedWhereInMatch Match
   | UnsupportedExpression Exp
-  | UnsupportedLiteral Literal
+  | UnsupportedFieldPattern PatField
+  | UnsupportedImport ImportDecl
+  | UnsupportedLet
   | UnsupportedLetBinding Decl
-  | UnsupportedOperator QOp
+  | UnsupportedLiteral Literal
+  | UnsupportedModuleSyntax Module
   | UnsupportedPattern Pat
-  | UnsupportedFieldPattern PatField
+  | UnsupportedQualStmt QualStmt
+  | UnsupportedRecursiveDo
   | UnsupportedRhs Rhs
-  | UnsupportedGuardedAlts GuardedAlts
   | UnsupportedWhereInAlt Alt
-  | UnsupportedImport ImportDecl
-  | UnsupportedQualStmt QualStmt
+  | UnsupportedWhereInMatch Match
   | EmptyDoBlock
-  | UnsupportedModuleSyntax Module
-  | LetUnsupported
   | InvalidDoBlock
-  | RecursiveDoUnsupported
   | Couldn'tFindImport ModuleName [FilePath]
   | FfiNeedsTypeSig Decl
   | FfiFormatBadChars SrcLoc String
   | FfiFormatNoSuchArg SrcLoc Int
   | FfiFormatIncompleteArg SrcLoc
   | FfiFormatInvalidJavaScript SrcLoc String String
-  | UnableResolveUnqualified Name
   | UnableResolveQualified QName
+  | GHCError String
   deriving (Show)
 instance Error CompileError
 
@@ -245,6 +282,9 @@
   | JsWhile JsExp [JsStmt]
   | JsUpdate JsName JsExp
   | JsSetProp JsName JsName JsExp
+  | JsSetQName QName JsExp
+  | JsSetModule ModulePath JsExp
+  | JsSetConstructor QName JsExp
   | JsSetPropExtern JsName JsName JsExp
   | JsContinue
   | JsBlock [JsStmt]
@@ -277,7 +317,10 @@
   | JsNeq JsExp JsExp
   | JsInfix String JsExp JsExp -- Used to optimize *, /, +, etc
   | JsObj [(String,JsExp)]
+  | JsLitObj [(Name,JsExp)]
   | JsUndefined
+  | JsAnd JsExp JsExp
+  | JsOr  JsExp JsExp
   deriving (Show,Eq)
 
 -- | A name of some kind.
@@ -292,6 +335,7 @@
   | JsTmp Integer
   | JsConstructor QName
   | JsBuiltIn Name
+  | JsModuleName ModuleName
   deriving (Eq,Show)
 
 -- | Literal value type.
diff --git a/src/Language/Fay/FFI.hs b/src/Language/Fay/FFI.hs
deleted file mode 100644
--- a/src/Language/Fay/FFI.hs
+++ /dev/null
@@ -1,51 +0,0 @@
-{-# LANGUAGE EmptyDataDecls       #-}
-{-# LANGUAGE NoImplicitPrelude    #-}
-{-# LANGUAGE TypeSynonymInstances #-}
-
--- | The internal FFI module. Needs to be renamed to Fay.FFI at some point.
-
-module Language.Fay.FFI
-  (Fay
-  ,Nullable (..)
-  ,Defined (..)
-  ,Ptr
-  ,Automatic
-  ,ffi)
-  where
-
-import           Fay.Types
-import           Prelude            (Bool, Char, Double, Int, Maybe, String,
-                                     error)
-
--- | Values that may be null
---  Nullable x decodes to x, Null decodes to null.
-data Nullable a = Nullable a | Null
-
--- | Values that may be undefined
--- Defined x encodes to x, Undefined decodes to undefined.
--- An undefined property in a record will be removed when encoding.
-data Defined a = Defined a | Undefined
-
--- | Do not serialize the specified type. This is useful for, e.g.
---
--- > foo :: String -> String
--- > foo = ffi "%1"
---
--- This would normally serialize and unserialize the string, for no
--- reason, in this case. Instead:
---
--- > foo :: Ptr String -> Ptr String
---
--- Will just give an identity function.
-type Ptr a = a
-
--- | The opposite of "Ptr". Serialize the specified polymorphic type.
---
--- > foo :: Automatic a -> String
---
-type Automatic a = a
-
--- | Declare a foreign action.
-ffi :: String        -- ^ The foreign value.
-    -> a             -- ^ Bottom.
-ffi = error "Language.Fay.FFI.foreignFay: Used foreign function not in a JS engine context."
diff --git a/src/Main.hs b/src/Main.hs
--- a/src/Main.hs
+++ b/src/Main.hs
@@ -12,7 +12,7 @@
 
 import qualified Control.Exception        as E
 import           Control.Monad
-import           Control.Monad.Error
+import           Control.Monad.IO
 import           Data.Default
 import           Data.List.Split          (wordsBy)
 import           Data.Maybe
@@ -21,7 +21,6 @@
 import           Paths_fay                (version)
 import           System.Console.Haskeline
 import           System.Environment
-import           System.IO
 
 -- | Options and help.
 data FayCompilerOptions = FayCompilerOptions
@@ -44,9 +43,6 @@
   , optNoRTS        :: Bool
   , optNoStdlib     :: Bool
   , optPrintRuntime :: Bool
-  , optNaked        :: Bool
-  , optNoDispatcher :: Bool
-  , optDispatcher   :: Bool
   , optStdlibOnly   :: Bool
   , optNoBuiltins   :: Bool
   , optBasePath     :: Maybe FilePath
@@ -59,39 +55,33 @@
   opts <- execParser parser
   if optVersion opts
     then runCommandVersion
-    else do
-      if optPrintRuntime opts
-         then getRuntime >>= readFile >>= putStr
-         else do
-           let config = addConfigDirectoryIncludePaths ("." : optInclude opts) $
-                 addConfigPackages (optPackages opts) $ def
-                   { configOptimize         = optOptimize opts
-                   , configFlattenApps      = optFlattenApps opts
-                   , configExportBuiltins   = not (optNoBuiltins opts)
-                   , configPrettyPrint      = optPretty opts
-                   , configLibrary          = optLibrary opts
-                   , configHtmlWrapper      = optHTMLWrapper opts
-                   , configHtmlJSLibs       = optHTMLJSLibs opts
-                   , configTypecheck        = not $ optNoGHC opts
-                   , configWall             = optWall opts
-                   , configGClosure         = optGClosure opts
-                   , configPackageConf      = optPackageConf opts <|> packageConf
-                   , configExportRuntime    = not (optNoRTS opts)
-                   , configNaked            = optNaked opts
-                   , configExportStdlib     = not (optNoStdlib opts)
-                   , configDispatchers      = not (optNoDispatcher opts)
-                   , configDispatcherOnly   = optDispatcher opts
-                   , configExportStdlibOnly = optStdlibOnly opts
-                   , configBasePath         = optBasePath opts
-                   }
-           void $ incompatible htmlAndStdout opts "Html wrapping and stdout are incompatible"
-           case optFiles opts of
-                ["-"] -> hGetContents stdin >>= printCompile config (compileModule True)
-                []    -> runInteractive
-                files -> forM_ files $ \file -> do
-                  if optStdout opts
-                    then compileFromTo config file Nothing
-                    else compileFromTo config file (Just (outPutFile opts file))
+    else if optPrintRuntime opts
+      then getRuntime >>= readFile >>= putStr
+      else do
+        let config = addConfigDirectoryIncludePaths ("." : optInclude opts) $
+              addConfigPackages (optPackages opts) $ def
+                { configOptimize         = optOptimize opts
+                , configFlattenApps      = optFlattenApps opts
+                , configExportBuiltins   = not (optNoBuiltins opts)
+                , configPrettyPrint      = optPretty opts
+                , configLibrary          = optLibrary opts
+                , configHtmlWrapper      = optHTMLWrapper opts
+                , configHtmlJSLibs       = optHTMLJSLibs opts
+                , configTypecheck        = not $ optNoGHC opts
+                , configWall             = optWall opts
+                , configGClosure         = optGClosure opts
+                , configPackageConf      = optPackageConf opts <|> packageConf
+                , configExportRuntime    = not (optNoRTS opts)
+                , configExportStdlib     = not (optNoStdlib opts)
+                , configExportStdlibOnly = optStdlibOnly opts
+                , configBasePath         = optBasePath opts
+                }
+        void $ incompatible htmlAndStdout opts "Html wrapping and stdout are incompatible"
+        case optFiles opts of
+             ["-"] -> getContents >>= printCompile config compileModuleFromAST
+             []    -> runInteractive
+             files -> forM_ files $ \file ->
+               compileFromTo config file (if optStdout opts then Nothing else Just (outPutFile opts file))
 
   where
     parser = info (helper <*> options) (fullDesc <> header helpTxt)
@@ -124,9 +114,6 @@
   <*> switch (long "no-rts" <> short 'r' <> help "Don't export the RTS")
   <*> switch (long "no-stdlib" <> help "Don't generate code for the Prelude/FFI")
   <*> switch (long "print-runtime" <> help "Print the runtime JS source to stdout")
-  <*> switch (long "naked" <> help "Print all declarations naked at the top-level (unwrapped)")
-  <*> switch (long "no-dispatcher" <> help "Don't output a type serialization dispatcher")
-  <*> switch (long "dispatcher" <> help "Only output the type serialization dispatchers")
   <*> switch (long "stdlib" <> help "Only output the stdlib")
   <*> switch (long "no-builtins" <> help "Don't export no-builtins")
   <*> optional (strOption (long "base-path" <> help "If fay can't find the sources of fay-base you can use this to provide the path. Use --base-path ~/example instead of --base-path=~/example to make sure ~ is expanded properly"))
@@ -139,9 +126,9 @@
 incompatible :: Monad m
   => (FayCompilerOptions -> Bool)
   -> FayCompilerOptions -> String -> m Bool
-incompatible test opts message = case test opts of
-  True -> E.throw $ userError message
-  False -> return True
+incompatible test opts message = if test opts
+  then E.throw $ userError message
+  else return True
 
 -- | The basic help text.
 helpTxt :: String
@@ -170,17 +157,17 @@
       Nothing -> return ()
       Just "" -> loop
       Just input -> do
-        result <- liftIO $ compileViaStr "<interactive>" config compileExp input
+        result <- io $ compileViaStr "<interactive>" config compileExp input
         case result of
           Left err -> do
             -- an error occured, maybe input was not an expression,
             -- but a declaration, try compiling the input as a declaration
-            outputStrLn ("can't parse input as expression: " ++ show err)
-            result' <- liftIO $ compileViaStr "<interactive>" config (compileDecl True) input
+            outputStrLn $ "can't parse input as expression: " ++ show err
+            result' <- io $ compileViaStr "<interactive>" config (compileDecl True) input
             case result' of
               Right (PrintState{..},_,_) -> outputStr (concat (reverse psOutput))
               Left err' ->
-                outputStrLn ("can't parse input as declaration: " ++ show err')
+                outputStrLn $ "can't parse input as declaration: " ++ show err'
           Right (PrintState{..},_,_) -> outputStr (concat (reverse psOutput))
         loop
   config = def { configPrettyPrint = True }
diff --git a/src/System/Directory/Extra.hs b/src/System/Directory/Extra.hs
new file mode 100644
--- /dev/null
+++ b/src/System/Directory/Extra.hs
@@ -0,0 +1,21 @@
+-- | Extra directory functions.
+module System.Directory.Extra where
+
+import Control.Monad (forM)
+import System.Directory (doesDirectoryExist, getDirectoryContents)
+import System.FilePath ((</>))
+
+-- | Get all files in a folder and its subdirectories.
+-- Taken from Real World Haskell
+-- http://book.realworldhaskell.org/read/io-case-study-a-library-for-searching-the-filesystem.html
+getRecursiveContents :: FilePath -> IO [FilePath]
+getRecursiveContents topdir = do
+  names <- getDirectoryContents topdir
+  let properNames = filter (`notElem` [".", ".."]) names
+  paths <- forM properNames $ \name -> do
+    let path = topdir </> name
+    isDirectory <- doesDirectoryExist path
+    if isDirectory
+      then getRecursiveContents path
+      else return [path]
+  return (concat paths)
diff --git a/src/System/Process/Extra.hs b/src/System/Process/Extra.hs
--- a/src/System/Process/Extra.hs
+++ b/src/System/Process/Extra.hs
@@ -5,6 +5,7 @@
 import System.Exit
 import System.Process
 
+-- | Read from a process returning both std err and out.
 readAllFromProcess :: FilePath -> [String] -> String -> IO (Either (String,String) (String,String))
 readAllFromProcess program flags input = do
   (code,out,err) <- readProcessWithExitCode program flags input
diff --git a/src/Test/Api.hs b/src/Test/Api.hs
--- a/src/Test/Api.hs
+++ b/src/Test/Api.hs
@@ -40,7 +40,7 @@
   res <- compileFileWithState defConf { configPackageConf = whatAGreatFramework } "tests/Api/Records.hs"
   case res of
     Left err -> error (show err)
-    Right (_,r) -> do
+    Right (_,r) ->
       -- TODO order should not matter
       assertEqual "stateRecordTypes mismatch"
         [ (UnQual (Ident "T"),[UnQual (Symbol ":+")])
@@ -54,7 +54,7 @@
   res <- compileFileWithState defConf { configPackageConf = whatAGreatFramework } "tests/Api/ImportRecords.hs"
   case res of
     Left err -> error (show err)
-    Right (_,r) -> do
+    Right (_,r) ->
       -- TODO order should not matter
       assertEqual "stateRecordTypes mismatch"
         [ (UnQual (Ident "T"),[UnQual (Symbol ":+")])
diff --git a/src/Test/CommandLine.hs b/src/Test/CommandLine.hs
--- a/src/Test/CommandLine.hs
+++ b/src/Test/CommandLine.hs
@@ -19,7 +19,7 @@
 
 compileFile :: [String] -> IO (Either String String)
 compileFile flags = do
-  whatAGreatFramework <- fmap (fmap (\x -> x</>"bin"</>"fay") . (lookup "HASKELL_SANDBOX"))
+  whatAGreatFramework <- fmap (fmap (\x -> x</>"bin"</>"fay") . lookup "HASKELL_SANDBOX")
                               getEnvironment
   fay <- fayPath
   let path = fromMaybe "couldn't find fay" (whatAGreatFramework <|> fay)
diff --git a/src/Tests.hs b/src/Tests.hs
--- a/src/Tests.hs
+++ b/src/Tests.hs
@@ -15,6 +15,7 @@
 import           Data.List
 import           Data.Maybe
 import           System.Directory
+import           System.Directory.Extra
 import           System.Environment
 import           System.FilePath
 import           System.Process.Extra
@@ -42,7 +43,7 @@
 -- | Make the case-by-case unit tests.
 makeCompilerTests :: Maybe FilePath -> Maybe FilePath -> IO Test
 makeCompilerTests packageConf basePath = do
-  files <- fmap (map ("tests" </>) . sort . filter (isSuffixOf ".hs")) $ getDirectoryContents "tests"
+  files <- sort . filter (not . isInfixOf "/Api/") . filter (isSuffixOf ".hs") <$> getRecursiveContents "tests"
   return $ testGroup "Tests" $ flip map files $ \file -> testCase file $ do
     testFile packageConf basePath False file
     testFile packageConf basePath True file
@@ -51,6 +52,7 @@
 testFile packageConf basePath opt file = do
   let root = (reverse . drop 1 . dropWhile (/='.') . reverse) file
       out = toJsName file
+      resf = root <.> "res"
       config =
         addConfigDirectoryIncludePaths ["tests/"] $
           def { configOptimize = opt
@@ -58,13 +60,13 @@
               , configPackageConf = packageConf
               , configBasePath = basePath
               }
-  outExists <- doesFileExist root
+  resExists <- doesFileExist resf
   let partialName = root ++ "_partial"
   partialExists <- doesFileExist partialName
   compileFromTo config file (Just out)
   result <- runJavaScriptFile out
-  if outExists
-     then do output <- readFile root
+  if resExists
+     then do output <- readFile resf
              assertEqual file output (either show snd result)
      else
        if partialExists
@@ -73,7 +75,7 @@
              output <- readFile partialName
              assertEqual file output res
            Right (err,res) -> assertFailure $ "Did not fail:\n stdout: " ++ res ++ "\n\nstderr: " ++ err
-         else assertEqual file True (either (const True) (const False) result)
+         else assertEqual (file ++ ": Expected program to fail") True (either (const True) (const False) result)
 
 -- | Run a JS file.
 runJavaScriptFile :: String -> IO (Either (String,String) (String,String))
diff --git a/tests/AutomaticList.hs b/tests/AutomaticList.hs
new file mode 100644
--- /dev/null
+++ b/tests/AutomaticList.hs
@@ -0,0 +1,36 @@
+module AutomaticList where
+
+import Prelude
+import FFI
+
+main :: Fay ()
+main = do
+  printA [1,2,3]
+  printA [[1],[2],[3]]
+  printA (1,2)
+  printA ([1],[2])
+  printArr [1,2,3]
+  printArr [[1],[2],[3]]
+  printT (1,2)
+  printT ([1],[2])
+  printA . tail $ readA "[1,2,3]"
+  printA . tail $ readArr "[1,2,3]"
+  printA . snd $ readT "[1,2]"
+
+printA :: Automatic a -> Fay ()
+printA = ffi "console.log(%1)"
+
+printArr :: Automatic [a] -> Fay ()
+printArr = ffi "console.log(%1)"
+
+printT :: (Automatic a, Automatic b) -> Fay ()
+printT = ffi "console.log(%1)"
+
+readA :: String -> Automatic a
+readA = ffi "JSON.parse(%1)"
+
+readArr :: String -> Automatic [a]
+readArr = ffi "JSON.parse(%1)"
+
+readT :: String -> Automatic (a,b)
+readT = ffi "JSON.parse(%1)"
diff --git a/tests/AutomaticList.res b/tests/AutomaticList.res
new file mode 100644
--- /dev/null
+++ b/tests/AutomaticList.res
@@ -0,0 +1,11 @@
+[ 1, 2, 3 ]
+[ [ 1 ], [ 2 ], [ 3 ] ]
+[ 1, 2 ]
+[ [ 1 ], [ 2 ] ]
+[ 1, 2, 3 ]
+[ [ 1 ], [ 2 ], [ 3 ] ]
+[ 1, 2 ]
+[ [ 1 ], [ 2 ] ]
+[ 2, 3 ]
+[ 2, 3 ]
+2
diff --git a/tests/Bool b/tests/Bool
deleted file mode 100644
--- a/tests/Bool
+++ /dev/null
@@ -1,1 +0,0 @@
-true
diff --git a/tests/Bool.res b/tests/Bool.res
new file mode 100644
--- /dev/null
+++ b/tests/Bool.res
@@ -0,0 +1,1 @@
+true
diff --git a/tests/CPP.hs b/tests/CPP.hs
new file mode 100644
--- /dev/null
+++ b/tests/CPP.hs
@@ -0,0 +1,23 @@
+{-# LANGUAGE CPP #-}
+#ifdef FAY
+import           Prelude
+#else
+this is invalid code
+#endif
+
+#ifdef FAY
+main :: Fay ()
+#endif
+
+#ifndef FAY
+more invalid code
+#if FAY
+this should not be used
+#endif
+#else
+#if FAY
+main = print True
+#else
+invalid and nested
+#endif
+#endif
diff --git a/tests/CPP.res b/tests/CPP.res
new file mode 100644
--- /dev/null
+++ b/tests/CPP.res
@@ -0,0 +1,1 @@
+true
diff --git a/tests/Char.hs b/tests/Char.hs
new file mode 100644
--- /dev/null
+++ b/tests/Char.hs
@@ -0,0 +1,10 @@
+module Char where
+
+import Prelude
+import FFI
+
+main :: Fay ()
+main = do
+  print 'a'
+  putStrLn ('a' : "bc")
+  print (head "abc")
diff --git a/tests/Char.res b/tests/Char.res
new file mode 100644
--- /dev/null
+++ b/tests/Char.res
@@ -0,0 +1,3 @@
+a
+abc
+a
diff --git a/tests/Defined.hs b/tests/Defined.hs
new file mode 100644
--- /dev/null
+++ b/tests/Defined.hs
@@ -0,0 +1,31 @@
+import           FFI
+import           Prelude
+
+data R = R (Defined Double)
+
+main :: Fay ()
+main = do
+  printD $ Defined (1 :: Double)
+  printS $ Defined "Hello, World!"
+  printSS $ Defined ["Hello,","World!"]
+  printD $ (Undefined :: Defined Double)
+  print $ R (Defined 1)
+  print $ R Undefined
+  print $ r1
+  print $ r2
+  return ()
+
+printD :: Defined Double -> Fay ()
+printD = ffi "console.log(%1)"
+
+printS :: Defined String -> Fay ()
+printS = ffi "console.log(%1)"
+
+printSS :: Defined [String] -> Fay ()
+printSS = ffi "console.log(%1)"
+
+r1 :: R
+r1 = ffi "{ instance: 'R', slot1 : 1 }"
+
+r2 :: R
+r2 = ffi "{ instance : 'R' }"
diff --git a/tests/Defined.res b/tests/Defined.res
new file mode 100644
--- /dev/null
+++ b/tests/Defined.res
@@ -0,0 +1,8 @@
+1
+Hello, World!
+[ 'Hello,', 'World!' ]
+undefined
+{ instance: 'R', slot1: 1 }
+{ instance: 'R' }
+{ instance: 'R', slot1: 1 }
+{ instance: 'R' }
diff --git a/tests/DoLet2.hs b/tests/DoLet2.hs
new file mode 100644
--- /dev/null
+++ b/tests/DoLet2.hs
@@ -0,0 +1,9 @@
+module DoLet2 where
+
+import Prelude
+import FFI
+
+main = do
+  print 1
+  let [a,b] = [3]
+  print a
diff --git a/tests/DoLet2_partial.res b/tests/DoLet2_partial.res
new file mode 100644
--- /dev/null
+++ b/tests/DoLet2_partial.res
@@ -0,0 +1,1 @@
+1
diff --git a/tests/DoLet3.hs b/tests/DoLet3.hs
new file mode 100644
--- /dev/null
+++ b/tests/DoLet3.hs
@@ -0,0 +1,18 @@
+module DoLet3 where
+
+import Prelude
+import FFI
+
+data R = R Int
+
+main = do
+  print 1
+  let [a] = [2]
+  print a
+  let (b,c) = (3,4)
+  print b
+  print c
+  let R d = R 5
+  print d
+  let [e] = []
+  print e
diff --git a/tests/DoLet3_partial.res b/tests/DoLet3_partial.res
new file mode 100644
--- /dev/null
+++ b/tests/DoLet3_partial.res
@@ -0,0 +1,5 @@
+1
+2
+3
+4
+5
diff --git a/tests/Double b/tests/Double
deleted file mode 100644
--- a/tests/Double
+++ /dev/null
@@ -1,1 +0,0 @@
-4
diff --git a/tests/Double.hs b/tests/Double.hs
--- a/tests/Double.hs
+++ b/tests/Double.hs
@@ -1,4 +1,3 @@
 import           Prelude
 
-main = print (2 * 4 / 2)
-
+main = print ((2 * 4 / 2) :: Double)
diff --git a/tests/Double.res b/tests/Double.res
new file mode 100644
--- /dev/null
+++ b/tests/Double.res
@@ -0,0 +1,1 @@
+4
diff --git a/tests/Double2 b/tests/Double2
deleted file mode 100644
--- a/tests/Double2
+++ /dev/null
@@ -1,1 +0,0 @@
-14
diff --git a/tests/Double2.hs b/tests/Double2.hs
--- a/tests/Double2.hs
+++ b/tests/Double2.hs
@@ -1,4 +1,3 @@
 import           Prelude
 
-main = print (10 + (2 * (4 / 2)))
-
+main = print ((10 + (2 * (4 / 2))) :: Double)
diff --git a/tests/Double2.res b/tests/Double2.res
new file mode 100644
--- /dev/null
+++ b/tests/Double2.res
@@ -0,0 +1,1 @@
+14
diff --git a/tests/Double3 b/tests/Double3
deleted file mode 100644
--- a/tests/Double3
+++ /dev/null
@@ -1,1 +0,0 @@
-7.5
diff --git a/tests/Double3.hs b/tests/Double3.hs
--- a/tests/Double3.hs
+++ b/tests/Double3.hs
@@ -1,4 +1,3 @@
 import           Prelude
 
-main = print (5 * 3 / 2)
-
+main = print ((5 * 3 / 2) :: Double)
diff --git a/tests/Double3.res b/tests/Double3.res
new file mode 100644
--- /dev/null
+++ b/tests/Double3.res
@@ -0,0 +1,1 @@
+7.5
diff --git a/tests/Double4 b/tests/Double4
deleted file mode 100644
--- a/tests/Double4
+++ /dev/null
@@ -1,1 +0,0 @@
-1
diff --git a/tests/Double4.res b/tests/Double4.res
new file mode 100644
--- /dev/null
+++ b/tests/Double4.res
@@ -0,0 +1,1 @@
+1
diff --git a/tests/Either.hs b/tests/Either.hs
new file mode 100644
--- /dev/null
+++ b/tests/Either.hs
@@ -0,0 +1,14 @@
+import Prelude
+
+raw :: Either Int Int -> Int
+raw x = case x of Left a -> a + 1
+                  Right b -> b + 2
+
+func :: Either Int Int -> Int
+func x = either (\x -> x + 1) (\x -> x + 2) x
+
+main = do
+  print $ raw $ Left 5
+  print $ raw $ Right 5
+  print $ func $ Left 5
+  print $ func $ Right 5
diff --git a/tests/Either.res b/tests/Either.res
new file mode 100644
--- /dev/null
+++ b/tests/Either.res
@@ -0,0 +1,4 @@
+6
+7
+6
+7
diff --git a/tests/Eq.hs b/tests/Eq.hs
new file mode 100644
--- /dev/null
+++ b/tests/Eq.hs
@@ -0,0 +1,7 @@
+import Prelude
+
+main = do
+  when (1 == 1) $ putStrLn "Expected =="
+  when (1 == 2) $ putStrLn "Unexpected =="
+  when (1 /= 1) $ putStrLn "Unexpected /="
+  when (1 /= 2) $ putStrLn "Expected /="
diff --git a/tests/Eq.res b/tests/Eq.res
new file mode 100644
--- /dev/null
+++ b/tests/Eq.res
@@ -0,0 +1,2 @@
+Expected ==
+Expected /=
diff --git a/tests/ExportEThingAll.hs b/tests/ExportEThingAll.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportEThingAll.hs
@@ -0,0 +1,6 @@
+module ExportEThingAll where
+
+import Prelude
+import ExportEThingAll_Export
+
+main = print Barbles
diff --git a/tests/ExportEThingAll.res b/tests/ExportEThingAll.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportEThingAll.res
@@ -0,0 +1,1 @@
+{ instance: 'Barbles' }
diff --git a/tests/ExportEThingAll_Export.hs b/tests/ExportEThingAll_Export.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportEThingAll_Export.hs
@@ -0,0 +1,3 @@
+module ExportEThingAll_Export (Bar(..)) where
+
+data Bar = Barbles
diff --git a/tests/ExportEThingAll_Export.res b/tests/ExportEThingAll_Export.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportEThingAll_Export.res
diff --git a/tests/ExportEThingWith.hs b/tests/ExportEThingWith.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportEThingWith.hs
@@ -0,0 +1,3 @@
+module ExportEThingWith (Bar(Barbles)) where
+
+data Bar = Barbles
diff --git a/tests/ExportEThingWith.res b/tests/ExportEThingWith.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportEThingWith.res
diff --git a/tests/ExportList.hs b/tests/ExportList.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportList.hs
@@ -0,0 +1,18 @@
+module Main (main) where
+
+import Prelude
+import ExportList_A
+import FFI
+
+a = A { a1 = 3 }
+b = B { b1 = 4 }
+
+main :: Fay ()
+main = do
+  print x
+  print y
+  print $ a1 a
+  print $ b1 b
+  print c
+  print d
+
diff --git a/tests/ExportList.res b/tests/ExportList.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportList.res
@@ -0,0 +1,6 @@
+1
+2
+3
+4
+42
+64
diff --git a/tests/ExportList_A.hs b/tests/ExportList_A.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportList_A.hs
@@ -0,0 +1,11 @@
+module ExportList_A (x, A (..), B (B, b1), module ExportList_B) where
+
+import ExportList_B
+import Prelude
+
+x :: Double
+x = 1
+
+data A = A { a1 :: Double }
+
+data B = B { b1 :: Double }
diff --git a/tests/ExportList_A.res b/tests/ExportList_A.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportList_A.res
diff --git a/tests/ExportList_B.hs b/tests/ExportList_B.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportList_B.hs
@@ -0,0 +1,8 @@
+module ExportList_B (y, module ExportList_C, module ExportList_D) where
+
+import ExportList_C
+import ExportList_D
+import Prelude
+
+y :: Double
+y = 2
diff --git a/tests/ExportList_B.res b/tests/ExportList_B.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportList_B.res
diff --git a/tests/ExportList_C.hs b/tests/ExportList_C.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportList_C.hs
@@ -0,0 +1,3 @@
+module ExportList_C where
+
+c = 42
diff --git a/tests/ExportList_C.res b/tests/ExportList_C.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportList_C.res
diff --git a/tests/ExportList_D.hs b/tests/ExportList_D.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportList_D.hs
@@ -0,0 +1,3 @@
+module ExportList_D(module ExportList_D) where
+
+d = 64
diff --git a/tests/ExportList_D.res b/tests/ExportList_D.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportList_D.res
diff --git a/tests/ExportQualified_Export.hs b/tests/ExportQualified_Export.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportQualified_Export.hs
@@ -0,0 +1,9 @@
+{-# LANGUAGE PackageImports #-}
+module ExportQualified_Export (main, X.X) where
+
+import Prelude
+
+import "foo" X
+
+main :: Fay ()
+main = return ()
diff --git a/tests/ExportQualified_Export.res b/tests/ExportQualified_Export.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportQualified_Export.res
diff --git a/tests/ExportQualified_Import.hs b/tests/ExportQualified_Import.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportQualified_Import.hs
@@ -0,0 +1,6 @@
+module ExportQualified_Import where
+
+import ExportQualified_Export
+
+x :: X
+x = undefined
diff --git a/tests/ExportQualified_Import.res b/tests/ExportQualified_Import.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportQualified_Import.res
diff --git a/tests/ExportType.hs b/tests/ExportType.hs
new file mode 100644
--- /dev/null
+++ b/tests/ExportType.hs
@@ -0,0 +1,24 @@
+module ExportType (
+    X (..) -- Export constructor implicitly (EThingAll)
+  , Y (Y)  -- Export constructor explicitly (EThingWith)
+  , Z (..) -- Export fields implicitly (EThingAll)
+  , W      -- Export only type (EAbs)
+  , w      -- Export fields separately (EVar)
+  , V (V, v1) -- Export fields partially (EThingWith)
+  ) where
+
+import           FFI
+import           Prelude
+
+data X = X
+
+data Y = Y
+
+data Z = Z { z :: Double }
+
+data W = W
+
+w :: W
+w = W
+
+data V = V { v1 :: Double, v2 :: Double }
diff --git a/tests/ExportType.res b/tests/ExportType.res
new file mode 100644
--- /dev/null
+++ b/tests/ExportType.res
diff --git a/tests/Floating.hs b/tests/Floating.hs
new file mode 100644
--- /dev/null
+++ b/tests/Floating.hs
@@ -0,0 +1,10 @@
+import Prelude
+
+main = do
+  print $ exp 0
+  print $ sqrt 4
+  print $ log (exp 3)
+  print $ 2 ** 2
+  print $ logBase 10 100
+  print $ sin (pi/2)
+  print $ cos pi
diff --git a/tests/Floating.res b/tests/Floating.res
new file mode 100644
--- /dev/null
+++ b/tests/Floating.res
@@ -0,0 +1,7 @@
+1
+2
+3
+4
+2
+1
+-1
diff --git a/tests/GADTs_without_records.hs b/tests/GADTs_without_records.hs
new file mode 100644
--- /dev/null
+++ b/tests/GADTs_without_records.hs
@@ -0,0 +1,40 @@
+{-# LANGUAGE GADTs #-}
+
+module GADTs_without_records where
+
+import Prelude
+
+data Expr a where
+  I :: Int -> Expr Int
+  Plus :: Expr Int -> Expr Int -> Expr Int
+  B :: Bool -> Expr Bool
+  IfThenElse :: Expr Bool -> Expr a -> Expr a -> Expr a
+  
+false :: Expr Bool
+false = B False
+
+true :: Expr Bool
+true = B True
+
+eval :: Expr a -> a
+eval (I x) = x
+eval (Plus a1 a2) = eval a1 + eval a2
+eval (B x) = x
+eval (IfThenElse p e1 e2) = case eval p of
+  True -> eval e1
+  False -> eval e2
+  
+n5 = I 5
+n2 = I 2
+
+expr1 = Plus n5 n2
+
+expr2 = IfThenElse true expr1 n5
+expr3 = IfThenElse false expr1 n5
+
+main = do
+  when (eval n5 == 5) $ putStrLn "Expected 5: Ok"
+  when (eval n2 == 2) $ putStrLn "Expected 2: Ok"
+  when (eval expr1 == 7) $ putStrLn "Expected 7: Ok"
+  when (eval expr2 == 7) $ putStrLn "Expected 7: Ok"
+  when (eval expr3 == 5) $ putStrLn "Expected 5: Ok"
diff --git a/tests/GADTs_without_records.res b/tests/GADTs_without_records.res
new file mode 100644
--- /dev/null
+++ b/tests/GADTs_without_records.res
@@ -0,0 +1,5 @@
+Expected 5: Ok
+Expected 2: Ok
+Expected 7: Ok
+Expected 7: Ok
+Expected 5: Ok
diff --git a/tests/GuardWhere.hs b/tests/GuardWhere.hs
new file mode 100644
--- /dev/null
+++ b/tests/GuardWhere.hs
@@ -0,0 +1,9 @@
+import Prelude
+
+poseL :: Bool -> String
+poseL y | y == True = "Not OK"
+  where x = 5
+poseL _ = "OK"
+
+main :: Fay ()
+main = putStrLn $ poseL False
diff --git a/tests/GuardWhere.res b/tests/GuardWhere.res
new file mode 100644
--- /dev/null
+++ b/tests/GuardWhere.res
@@ -0,0 +1,1 @@
+OK
diff --git a/tests/HidePreludeImport.hs b/tests/HidePreludeImport.hs
new file mode 100644
--- /dev/null
+++ b/tests/HidePreludeImport.hs
@@ -0,0 +1,7 @@
+module HidePreludeImport where
+
+import HidePreludeImport_Import
+import Prelude hiding (last)
+
+main :: Fay ()
+main = print last
diff --git a/tests/HidePreludeImport.res b/tests/HidePreludeImport.res
new file mode 100644
--- /dev/null
+++ b/tests/HidePreludeImport.res
@@ -0,0 +1,1 @@
+1
diff --git a/tests/HidePreludeImport_Import.hs b/tests/HidePreludeImport_Import.hs
new file mode 100644
--- /dev/null
+++ b/tests/HidePreludeImport_Import.hs
@@ -0,0 +1,6 @@
+module HidePreludeImport_Import where
+
+import           Prelude
+
+last :: Double
+last = 1
diff --git a/tests/HidePreludeImport_Import.res b/tests/HidePreludeImport_Import.res
new file mode 100644
--- /dev/null
+++ b/tests/HidePreludeImport_Import.res
diff --git a/tests/Hierarchical/Export.hs b/tests/Hierarchical/Export.hs
--- a/tests/Hierarchical/Export.hs
+++ b/tests/Hierarchical/Export.hs
@@ -1,8 +1,6 @@
-
-
 module Hierarchical.Export where
 
-import           Language.Fay.FFI
+import           FFI
 import           Prelude
 
 exported :: String
diff --git a/tests/Hierarchical/Export.res b/tests/Hierarchical/Export.res
new file mode 100644
--- /dev/null
+++ b/tests/Hierarchical/Export.res
diff --git a/tests/Hierarchical/RecordDefined.hs b/tests/Hierarchical/RecordDefined.hs
--- a/tests/Hierarchical/RecordDefined.hs
+++ b/tests/Hierarchical/RecordDefined.hs
@@ -1,8 +1,6 @@
-
-
 module Hierarchical.RecordDefined where
 
-import           Language.Fay.FFI
+import           FFI
 import           Prelude
 
 data Callback a = Callback Double
diff --git a/tests/Hierarchical/RecordDefined.res b/tests/Hierarchical/RecordDefined.res
new file mode 100644
--- /dev/null
+++ b/tests/Hierarchical/RecordDefined.res
diff --git a/tests/HierarchicalImport b/tests/HierarchicalImport
deleted file mode 100644
--- a/tests/HierarchicalImport
+++ /dev/null
@@ -1,1 +0,0 @@
-exported
diff --git a/tests/HierarchicalImport.res b/tests/HierarchicalImport.res
new file mode 100644
--- /dev/null
+++ b/tests/HierarchicalImport.res
@@ -0,0 +1,1 @@
+exported
diff --git a/tests/ImportHiding.hs b/tests/ImportHiding.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportHiding.hs
@@ -0,0 +1,9 @@
+import Prelude
+
+import ImportList1.A hiding (y)
+import ImportList1.B hiding (x)
+
+main :: Fay ()
+main = do
+  print x
+  print y
diff --git a/tests/ImportHiding.res b/tests/ImportHiding.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportHiding.res
@@ -0,0 +1,2 @@
+1
+2
diff --git a/tests/ImportIThingAll.hs b/tests/ImportIThingAll.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportIThingAll.hs
@@ -0,0 +1,10 @@
+import           Prelude
+import           FFI
+
+import           ImportList1.C        (A (..))
+
+main :: Fay ()
+main = do
+  print $ B1 1
+  print $ b1 (B1 1)
+  print $ B2 2
diff --git a/tests/ImportIThingAll.res b/tests/ImportIThingAll.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportIThingAll.res
@@ -0,0 +1,3 @@
+{ instance: 'B1', b1: 1 }
+1
+{ instance: 'B2', slot1: 2 }
diff --git a/tests/ImportList.hs b/tests/ImportList.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportList.hs
@@ -0,0 +1,16 @@
+module ImportList where
+
+import           Prelude
+import           FFI
+
+import           ImportList1.A        (x)
+import           ImportList1.B        (y, R (s1), r, s2, X (Y), (<<>>))
+
+main :: Fay ()
+main = do
+  print x
+  print y
+  print $ s1 r
+  print $ s2 r
+  print $ Y 1
+  print $ 2 <<>> 3
diff --git a/tests/ImportList.res b/tests/ImportList.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportList.res
@@ -0,0 +1,6 @@
+1
+2
+3
+4
+{ instance: 'Y', slot1: 1 }
+5
diff --git a/tests/ImportList1/A.hs b/tests/ImportList1/A.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportList1/A.hs
@@ -0,0 +1,12 @@
+module ImportList1.A where
+
+import           Prelude
+import           FFI
+
+x :: Double
+x = 1
+
+y :: Double
+y = 1
+
+data R = S
diff --git a/tests/ImportList1/A.res b/tests/ImportList1/A.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportList1/A.res
diff --git a/tests/ImportList1/B.hs b/tests/ImportList1/B.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportList1/B.hs
@@ -0,0 +1,20 @@
+module ImportList1.B where
+
+import           Prelude
+import           FFI
+
+x :: Double
+x = 2
+
+y :: Double
+y = 2
+
+data R = S { s1 :: Double, s2 :: Double }
+
+r :: R
+r = S 3 4
+
+data X = Y Int
+
+(<<>>) :: Double -> Double -> Double
+(<<>>) = (+)
diff --git a/tests/ImportList1/B.res b/tests/ImportList1/B.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportList1/B.res
diff --git a/tests/ImportList1/C.hs b/tests/ImportList1/C.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportList1/C.hs
@@ -0,0 +1,10 @@
+module ImportList1.C where
+
+import           Prelude
+
+data A = B1 { b1 :: Double } | B2 Double
+
+data UnimportedX = UnimportedY
+
+unimportedF :: Double
+unimportedF = 1
diff --git a/tests/ImportList1/C.res b/tests/ImportList1/C.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportList1/C.res
diff --git a/tests/ImportListType.hs b/tests/ImportListType.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportListType.hs
@@ -0,0 +1,4 @@
+import Prelude (Fay, putStrLn)
+
+main :: Fay ()
+main = putStrLn "ok"
diff --git a/tests/ImportListType.res b/tests/ImportListType.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportListType.res
@@ -0,0 +1,1 @@
+ok
diff --git a/tests/ImportType.hs b/tests/ImportType.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportType.hs
@@ -0,0 +1,17 @@
+import           Prelude
+
+import           ExportType
+
+w' :: W
+w' = w
+
+main :: Fay ()
+main = do
+  print X
+  print Y
+  print (Z 1)
+  print (z (Z 1))
+  print w'
+  print (V 1 2)
+  print (v1 (V 1 2))
+
diff --git a/tests/ImportType.res b/tests/ImportType.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportType.res
@@ -0,0 +1,7 @@
+{ instance: 'X' }
+{ instance: 'Y' }
+{ instance: 'Z', z: 1 }
+1
+{ instance: 'W' }
+{ instance: 'V', v1: 1, v2: 2 }
+1
diff --git a/tests/ImportType2.hs b/tests/ImportType2.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportType2.hs
@@ -0,0 +1,6 @@
+module ImportType2 where
+
+import ImportType2I.A (foo)
+import ImportType2I.B (Foo)
+
+main = foo
diff --git a/tests/ImportType2.res b/tests/ImportType2.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportType2.res
@@ -0,0 +1,1 @@
+A
diff --git a/tests/ImportType2I/A.hs b/tests/ImportType2I/A.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportType2I/A.hs
@@ -0,0 +1,5 @@
+module ImportType2I.A where
+
+import Prelude
+
+foo = putStrLn "A"
diff --git a/tests/ImportType2I/A.res b/tests/ImportType2I/A.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportType2I/A.res
diff --git a/tests/ImportType2I/B.hs b/tests/ImportType2I/B.hs
new file mode 100644
--- /dev/null
+++ b/tests/ImportType2I/B.hs
@@ -0,0 +1,7 @@
+module ImportType2I.B where
+
+import Prelude
+
+data Foo
+
+foo = putStrLn "B!"
diff --git a/tests/ImportType2I/B.res b/tests/ImportType2I/B.res
new file mode 100644
--- /dev/null
+++ b/tests/ImportType2I/B.res
diff --git a/tests/Integral.hs b/tests/Integral.hs
new file mode 100644
--- /dev/null
+++ b/tests/Integral.hs
@@ -0,0 +1,30 @@
+import Prelude
+
+printPair :: (Int,Int) -> Fay ()
+printPair (x,y) = print x >> print y
+
+main = do
+  print (( 3) `quot` ( 2))
+  print (( 3) `quot` (-2))
+  print ((-3) `quot` ( 2))
+  print ((-3) `quot` (-2))
+  print (( 3) `rem` ( 2))
+  print (( 3) `rem` (-2))
+  print ((-3) `rem` ( 2))
+  print ((-3) `rem` (-2))
+  print (( 3) `div` ( 2))
+  print (( 3) `div` (-2))
+  print ((-3) `div` ( 2))
+  print ((-3) `div` (-2))
+  print (( 3) `mod` ( 2))
+  print (( 3) `mod` (-2))
+  print ((-3) `mod` ( 2))
+  print ((-3) `mod` (-2))
+  printPair (( 3) `divMod` ( 2))
+  printPair (( 3) `divMod` (-2))
+  printPair ((-3) `divMod` ( 2))
+  printPair ((-3) `divMod` (-2))
+  printPair (( 3) `quotRem` ( 2))
+  printPair (( 3) `quotRem` (-2))
+  printPair ((-3) `quotRem` ( 2))
+  printPair ((-3) `quotRem` (-2))
diff --git a/tests/Integral.res b/tests/Integral.res
new file mode 100644
--- /dev/null
+++ b/tests/Integral.res
@@ -0,0 +1,32 @@
+1
+-1
+-1
+1
+1
+1
+-1
+-1
+1
+-2
+-2
+1
+1
+-1
+1
+-1
+1
+1
+-2
+-1
+-2
+1
+1
+-1
+1
+1
+-1
+1
+-1
+-1
+1
+-1
diff --git a/tests/Issue215/B.hs b/tests/Issue215/B.hs
new file mode 100644
--- /dev/null
+++ b/tests/Issue215/B.hs
@@ -0,0 +1,6 @@
+module Issue215.B where
+
+import Prelude
+
+f :: Int -> Maybe Int
+f x = Just x
diff --git a/tests/Issue215/B.res b/tests/Issue215/B.res
new file mode 100644
--- /dev/null
+++ b/tests/Issue215/B.res
diff --git a/tests/Issue215A.hs b/tests/Issue215A.hs
new file mode 100644
--- /dev/null
+++ b/tests/Issue215A.hs
@@ -0,0 +1,7 @@
+module Issue215A where
+
+import Prelude
+import Issue215.B
+
+main = do
+        print $ f 2
diff --git a/tests/Issue215A.res b/tests/Issue215A.res
new file mode 100644
--- /dev/null
+++ b/tests/Issue215A.res
@@ -0,0 +1,1 @@
+{ instance: 'Just', slot1: 2 }
diff --git a/tests/Js2FayFunc.hs b/tests/Js2FayFunc.hs
new file mode 100644
--- /dev/null
+++ b/tests/Js2FayFunc.hs
@@ -0,0 +1,23 @@
+import FFI
+import Prelude
+
+main = do
+  f <- getF
+  g <- getG
+  h <- getH 0
+  ret1 <- f "hey" "world" 123
+  ret2 <- f "ahoy" "la" 666
+  ret3 <- g "ack"
+  putStrLn ret1
+  putStrLn ret2
+  putStrLn ret3
+  putStrLn (h "apples" "pears")
+
+getF :: Fay (String -> String -> Int -> Fay String)
+getF = ffi "(function(x,y,z){ return 'getF: ' + x + ', ' + y + ', ' + z; })"
+
+getG :: Fay (String -> Fay String)
+getG = ffi "(function(x){ return 'getG: ' + x; })"
+
+getH :: Int -> Fay (String -> String -> String)
+getH = ffi "(function(x,y){ return 'getH: ' + x + ', ' + y; })"
diff --git a/tests/Js2FayFunc.res b/tests/Js2FayFunc.res
new file mode 100644
--- /dev/null
+++ b/tests/Js2FayFunc.res
@@ -0,0 +1,4 @@
+getF: hey, world, 123
+getF: ahoy, la, 666
+getG: ack
+getH: apples, pears
diff --git a/tests/LazyOperators.hs b/tests/LazyOperators.hs
new file mode 100644
--- /dev/null
+++ b/tests/LazyOperators.hs
@@ -0,0 +1,6 @@
+import           Prelude
+
+main :: Fay ()
+main = print testFn
+
+testFn = let f a b = snd (a/b,10::Double) in f 1 0 -- undefined undefined
diff --git a/tests/LazyOperators.res b/tests/LazyOperators.res
new file mode 100644
--- /dev/null
+++ b/tests/LazyOperators.res
@@ -0,0 +1,1 @@
+10
diff --git a/tests/List b/tests/List
deleted file mode 100644
--- a/tests/List
+++ /dev/null
@@ -1,1 +0,0 @@
-[1,2,3,4,5]
diff --git a/tests/List.hs b/tests/List.hs
--- a/tests/List.hs
+++ b/tests/List.hs
@@ -1,5 +1,5 @@
 import           FFI
-import           Prelude
+import           Prelude hiding (take)
 
 main = putStrLn (showList (take 5 (let ns = 1 : map' (\x -> x + 1) ns in ns)))
 
diff --git a/tests/List.res b/tests/List.res
new file mode 100644
--- /dev/null
+++ b/tests/List.res
@@ -0,0 +1,1 @@
+[1,2,3,4,5]
diff --git a/tests/List2 b/tests/List2
deleted file mode 100644
--- a/tests/List2
+++ /dev/null
@@ -1,1 +0,0 @@
-[1,61.5,3782.25,232608.375,14305415.0625]
diff --git a/tests/List2.hs b/tests/List2.hs
--- a/tests/List2.hs
+++ b/tests/List2.hs
@@ -1,5 +1,5 @@
 import           FFI
-import           Prelude
+import           Prelude hiding (take)
 
 main = putStrLn (showList (take 5 (let ns = 1 : map' (foo 123) ns in ns)))
 
diff --git a/tests/List2.res b/tests/List2.res
new file mode 100644
--- /dev/null
+++ b/tests/List2.res
@@ -0,0 +1,1 @@
+[1,61.5,3782.25,232608.375,14305415.0625]
diff --git a/tests/ModuleRecordClash.hs b/tests/ModuleRecordClash.hs
new file mode 100644
--- /dev/null
+++ b/tests/ModuleRecordClash.hs
@@ -0,0 +1,11 @@
+module ModuleRecordClash (main) where
+
+import Prelude
+import ModuleRecordClash.R
+
+data R = R
+
+main :: Fay ()
+main = do
+  print R
+  print i
diff --git a/tests/ModuleRecordClash.res b/tests/ModuleRecordClash.res
new file mode 100644
--- /dev/null
+++ b/tests/ModuleRecordClash.res
@@ -0,0 +1,2 @@
+{ instance: 'R' }
+1
diff --git a/tests/ModuleRecordClash/R.hs b/tests/ModuleRecordClash/R.hs
new file mode 100644
--- /dev/null
+++ b/tests/ModuleRecordClash/R.hs
@@ -0,0 +1,6 @@
+module ModuleRecordClash.R where
+
+import Prelude
+
+i :: Double
+i = 1
diff --git a/tests/ModuleRecordClash/R.res b/tests/ModuleRecordClash/R.res
new file mode 100644
--- /dev/null
+++ b/tests/ModuleRecordClash/R.res
diff --git a/tests/Monad b/tests/Monad
deleted file mode 100644
--- a/tests/Monad
+++ /dev/null
@@ -1,3 +0,0 @@
-456
-789
-101112
diff --git a/tests/Monad.res b/tests/Monad.res
new file mode 100644
--- /dev/null
+++ b/tests/Monad.res
@@ -0,0 +1,3 @@
+456
+789
+101112
diff --git a/tests/Monad2 b/tests/Monad2
deleted file mode 100644
--- a/tests/Monad2
+++ /dev/null
@@ -1,1 +0,0 @@
-abc: 123
diff --git a/tests/Monad2.res b/tests/Monad2.res
new file mode 100644
--- /dev/null
+++ b/tests/Monad2.res
@@ -0,0 +1,1 @@
+abc: 123
diff --git a/tests/NestedImporting.hs b/tests/NestedImporting.hs
new file mode 100644
--- /dev/null
+++ b/tests/NestedImporting.hs
@@ -0,0 +1,6 @@
+module NestedImporting where
+
+import Prelude
+
+r :: Double
+r = 1
diff --git a/tests/NestedImporting.res b/tests/NestedImporting.res
new file mode 100644
--- /dev/null
+++ b/tests/NestedImporting.res
diff --git a/tests/NestedImporting/A.hs b/tests/NestedImporting/A.hs
new file mode 100644
--- /dev/null
+++ b/tests/NestedImporting/A.hs
@@ -0,0 +1,7 @@
+module NestedImporting.A where
+
+import Prelude
+import NestedImporting
+
+main :: Fay ()
+main = print r
diff --git a/tests/NestedImporting/A.res b/tests/NestedImporting/A.res
new file mode 100644
--- /dev/null
+++ b/tests/NestedImporting/A.res
@@ -0,0 +1,1 @@
+1
diff --git a/tests/NestedImporting2.hs b/tests/NestedImporting2.hs
new file mode 100644
--- /dev/null
+++ b/tests/NestedImporting2.hs
@@ -0,0 +1,7 @@
+module NestedImporting2 where
+
+import Prelude
+import NestedImporting2.A
+
+main :: Fay ()
+main = print r
diff --git a/tests/NestedImporting2.res b/tests/NestedImporting2.res
new file mode 100644
--- /dev/null
+++ b/tests/NestedImporting2.res
@@ -0,0 +1,1 @@
+1
diff --git a/tests/NestedImporting2/A.hs b/tests/NestedImporting2/A.hs
new file mode 100644
--- /dev/null
+++ b/tests/NestedImporting2/A.hs
@@ -0,0 +1,6 @@
+module NestedImporting2.A where
+
+import Prelude
+
+r :: Double
+r = 1
diff --git a/tests/NestedImporting2/A.res b/tests/NestedImporting2/A.res
new file mode 100644
--- /dev/null
+++ b/tests/NestedImporting2/A.res
diff --git a/tests/NewtypeImport_Export.hs b/tests/NewtypeImport_Export.hs
new file mode 100644
--- /dev/null
+++ b/tests/NewtypeImport_Export.hs
@@ -0,0 +1,12 @@
+module NewtypeImport_Export where
+
+import FFI
+import Prelude
+
+newtype MyInteger = MyInteger Int
+
+data Foo = Bar { bar :: Double }
+newtype Baz = Baz { unwrapBaz :: Foo }
+
+getBaz :: Fay Baz
+getBaz = ffi "{ instance: 'Bar', bar: 1 }"
diff --git a/tests/NewtypeImport_Export.res b/tests/NewtypeImport_Export.res
new file mode 100644
--- /dev/null
+++ b/tests/NewtypeImport_Export.res
diff --git a/tests/NewtypeImport_Import.hs b/tests/NewtypeImport_Import.hs
new file mode 100644
--- /dev/null
+++ b/tests/NewtypeImport_Import.hs
@@ -0,0 +1,25 @@
+import           Prelude
+import           NewtypeImport_Export
+
+x = case MyInteger undefined of
+      MyInteger _ -> 1
+
+y = case undefined of
+      MyInteger _ -> 1
+
+int :: Int
+int = undefined
+
+yInt = case int of
+         _ -> 1
+
+main = do
+    print x
+    print y
+    print yInt
+    print (Baz (Bar 1))
+    baz <- getBaz
+    print baz
+    case baz of
+      Baz (Bar i) -> print i
+    print (bar $ unwrapBaz baz)
diff --git a/tests/NewtypeImport_Import.res b/tests/NewtypeImport_Import.res
new file mode 100644
--- /dev/null
+++ b/tests/NewtypeImport_Import.res
@@ -0,0 +1,7 @@
+1
+1
+1
+{ instance: 'Bar', bar: 1 }
+{ instance: 'Bar', bar: 1 }
+1
+1
diff --git a/tests/Nullable.hs b/tests/Nullable.hs
new file mode 100644
--- /dev/null
+++ b/tests/Nullable.hs
@@ -0,0 +1,42 @@
+import           FFI
+import           Prelude
+
+data R = R (Nullable Double)
+
+main :: Fay ()
+main = do
+  printD $ Nullable (1 :: Double)
+  printNS $ Nullable "Hello, World!"
+  printSS $ Nullable ["Hello,","World!"]
+  printD $ (Null :: Nullable Double)
+  print' $ R (Nullable 1)
+  print' $ R Null
+  print' $ r1
+  print' $ r2
+  print' $ parseInt "3"
+  print' $ parseInt "x"
+  return ()
+
+printD :: Nullable Double -> Fay ()
+printD = ffi "console.log(%1)"
+
+printNS :: Nullable String -> Fay ()
+printNS = ffi "console.log(%1)"
+
+printS :: Defined String -> Fay ()
+printS = ffi "console.log(%1)"
+
+printSS :: Defined [String] -> Fay ()
+printSS = ffi "console.log(%1)"
+
+print' :: Automatic f -> Fay ()
+print' = ffi "console.log(%1)"
+
+r1 :: R
+r1 = ffi "{ instance: 'R', slot1 : 1 }"
+
+r2 :: R
+r2 = ffi "{ instance : 'R', slot1 : null }"
+
+parseInt :: String -> Nullable Int
+parseInt = ffi "(function () { var n = global.parseInt(%1, 10); if (isNaN(n)) return null; return n; })()"
diff --git a/tests/Nullable.res b/tests/Nullable.res
new file mode 100644
--- /dev/null
+++ b/tests/Nullable.res
@@ -0,0 +1,10 @@
+1
+Hello, World!
+[ 'Hello,', 'World!' ]
+null
+{ instance: 'R', slot1: 1 }
+{ instance: 'R', slot1: null }
+{ instance: 'R', slot1: 1 }
+{ instance: 'R', slot1: null }
+{ instance: 'Nullable', slot1: 3 }
+{ instance: 'Null' }
diff --git a/tests/Num.hs b/tests/Num.hs
new file mode 100644
--- /dev/null
+++ b/tests/Num.hs
@@ -0,0 +1,9 @@
+import Prelude
+
+main = do
+  print (1 + 2)
+  print (4 - 1)
+  print (3 * 1)
+  print (negate (1 - 4))
+  print (abs (1 - 4))
+  print ((-3) * signum (-10))
diff --git a/tests/Num.res b/tests/Num.res
new file mode 100644
--- /dev/null
+++ b/tests/Num.res
@@ -0,0 +1,6 @@
+3
+3
+3
+3
+3
+3
diff --git a/tests/Ord.hs b/tests/Ord.hs
new file mode 100644
--- /dev/null
+++ b/tests/Ord.hs
@@ -0,0 +1,21 @@
+import Prelude
+
+main = do
+  when (1 < 2) $ putStrLn "Expected <"
+  when (1 < 1) $ putStrLn "Unexpected < (1)"
+  when (2 < 1) $ putStrLn "Unexpected < (2)"
+  when (1 >= 2) $ putStrLn "Unexpected >="
+  when (1 >= 1) $ putStrLn "Expected >= (1)"
+  when (2 >= 1) $ putStrLn "Expected >= (2)"
+  when (1 > 2) $ putStrLn "Unexpected > (1)"
+  when (1 > 1) $ putStrLn "Unexpected > (2)"
+  when (2 > 1) $ putStrLn "Expected >"
+  when (1 <= 2) $ putStrLn "Expected <= (1)"
+  when (1 <= 1) $ putStrLn "Expected <= (2)"
+  when (2 <= 1) $ putStrLn "Unexpected <="
+  print $ max 1 2
+  print $ min 1 2
+  case compare 1 2 of
+    EQ -> putStrLn "FAIL (EQ)"
+    LT -> putStrLn "WIN (LT)"
+    GT -> putStrLn "FAIL (GT)"
diff --git a/tests/Ord.res b/tests/Ord.res
new file mode 100644
--- /dev/null
+++ b/tests/Ord.res
@@ -0,0 +1,9 @@
+Expected <
+Expected >= (1)
+Expected >= (2)
+Expected >
+Expected <= (1)
+Expected <= (2)
+2
+1
+WIN (LT)
diff --git a/tests/Ratio.hs b/tests/Ratio.hs
new file mode 100644
--- /dev/null
+++ b/tests/Ratio.hs
@@ -0,0 +1,10 @@
+module Ratio where
+
+import Prelude
+import Data.Ratio
+
+main :: Fay ()
+main = do
+  print $ 3 % 5
+  print $ numerator (3 % 5)
+  print $ denominator (3 % 5)
diff --git a/tests/Ratio.res b/tests/Ratio.res
new file mode 100644
--- /dev/null
+++ b/tests/Ratio.res
@@ -0,0 +1,3 @@
+{ instance: 'Ratio', slot1: 3, slot2: 5 }
+3
+5
diff --git a/tests/ReExport1.hs b/tests/ReExport1.hs
new file mode 100644
--- /dev/null
+++ b/tests/ReExport1.hs
@@ -0,0 +1,4 @@
+module ReExport1 where
+
+x = 42
+
diff --git a/tests/ReExport1.res b/tests/ReExport1.res
new file mode 100644
--- /dev/null
+++ b/tests/ReExport1.res
diff --git a/tests/ReExport2.hs b/tests/ReExport2.hs
new file mode 100644
--- /dev/null
+++ b/tests/ReExport2.hs
@@ -0,0 +1,3 @@
+module ReExport2 (x) where
+
+import ReExport1
diff --git a/tests/ReExport2.res b/tests/ReExport2.res
new file mode 100644
--- /dev/null
+++ b/tests/ReExport2.res
diff --git a/tests/ReExport3.hs b/tests/ReExport3.hs
new file mode 100644
--- /dev/null
+++ b/tests/ReExport3.hs
@@ -0,0 +1,5 @@
+import Prelude
+import ReExport2
+
+main :: Fay ()
+main = print x
diff --git a/tests/ReExport3.res b/tests/ReExport3.res
new file mode 100644
--- /dev/null
+++ b/tests/ReExport3.res
@@ -0,0 +1,1 @@
+42
diff --git a/tests/RealFrac.hs b/tests/RealFrac.hs
new file mode 100644
--- /dev/null
+++ b/tests/RealFrac.hs
@@ -0,0 +1,10 @@
+import Prelude
+
+main = do
+  print $ fst $ properFraction 1.5
+  print $ snd $ properFraction 1.5
+  print $ truncate (-1.5)
+  print $ round (-1.5)
+  print $ ceiling (-1.5)
+  print $ floor (-1.5)
+  return ()
diff --git a/tests/RealFrac.res b/tests/RealFrac.res
new file mode 100644
--- /dev/null
+++ b/tests/RealFrac.res
@@ -0,0 +1,6 @@
+1
+0.5
+-1
+-1
+-1
+-2
diff --git a/tests/RecCon b/tests/RecCon
deleted file mode 100644
--- a/tests/RecCon
+++ /dev/null
@@ -1,1 +0,0 @@
-123
diff --git a/tests/RecCon.hs b/tests/RecCon.hs
--- a/tests/RecCon.hs
+++ b/tests/RecCon.hs
@@ -4,6 +4,4 @@
 
 main = print (head (fix (\xs -> 123 : xs)))
 
-head (x:xs) = x
-
 fix f = let x = f x in x
diff --git a/tests/RecCon.res b/tests/RecCon.res
new file mode 100644
--- /dev/null
+++ b/tests/RecCon.res
@@ -0,0 +1,1 @@
+123
diff --git a/tests/RecDecl b/tests/RecDecl
deleted file mode 100644
--- a/tests/RecDecl
+++ /dev/null
@@ -1,12 +0,0 @@
-{ instance: 'R', i: 10, c: 'a' }
-{ instance: 'R', i: 20, c: 'a' }
-{ instance: 'R', i: 123, c: 'b' }
-{ instance: 'R', i: 1, c: 'a' }
-1
-"a"
-{ instance: 'R', i: 2, c: 'b' }
-{ instance: 'R', c: 'b' }
-{ instance: 'R', i: 3, c: 'c' }
-{ instance: 'S', slot1: 1, slot2: 'a' }
-{ instance: 'X', _x1: 1, _x2: 2 }
-{ instance: 'X', _x1: 1, _x2: 2 }
diff --git a/tests/RecDecl.hs b/tests/RecDecl.hs
--- a/tests/RecDecl.hs
+++ b/tests/RecDecl.hs
@@ -2,9 +2,7 @@
 import           Prelude
 
 data R = R { i :: Double, c :: Char }
-instance Foreign R
 data S = S Double Char
-instance Foreign S
 
 -- RecDecl
 r1 :: R
@@ -28,7 +26,6 @@
 
 -- Multiple fields with the same type
 data X = X { _x1, _x2 :: Int }
-instance Foreign X
 
 x1 = X 1 2
 x2 = X { _x1 = 1, _x2 = 2 }
@@ -53,4 +50,3 @@
   print s1
   print x1
   print x2
-
diff --git a/tests/RecDecl.res b/tests/RecDecl.res
new file mode 100644
--- /dev/null
+++ b/tests/RecDecl.res
@@ -0,0 +1,12 @@
+{ instance: 'R', i: 10, c: 'a' }
+{ instance: 'R', i: 20, c: 'a' }
+{ instance: 'R', i: 123, c: 'b' }
+{ instance: 'R', i: 1, c: 'a' }
+1
+"a"
+{ instance: 'R', i: 2, c: 'b' }
+{ instance: 'R', c: 'b' }
+{ instance: 'R', i: 3, c: 'c' }
+{ instance: 'S', slot1: 1, slot2: 'a' }
+{ instance: 'X', _x1: 1, _x2: 2 }
+{ instance: 'X', _x1: 1, _x2: 2 }
diff --git a/tests/RecordImport2_Export1.hs b/tests/RecordImport2_Export1.hs
new file mode 100644
--- /dev/null
+++ b/tests/RecordImport2_Export1.hs
@@ -0,0 +1,6 @@
+module RecordImport2_Export1 (main) where
+import Prelude
+data R = R { wrong :: Double }
+
+main :: Fay ()
+main = return ()
diff --git a/tests/RecordImport2_Export1.res b/tests/RecordImport2_Export1.res
new file mode 100644
--- /dev/null
+++ b/tests/RecordImport2_Export1.res
diff --git a/tests/RecordImport2_Export2.hs b/tests/RecordImport2_Export2.hs
new file mode 100644
--- /dev/null
+++ b/tests/RecordImport2_Export2.hs
@@ -0,0 +1,3 @@
+module RecordImport2_Export2 where
+import Prelude
+data R = R { correct :: Double }
diff --git a/tests/RecordImport2_Export2.res b/tests/RecordImport2_Export2.res
new file mode 100644
--- /dev/null
+++ b/tests/RecordImport2_Export2.res
diff --git a/tests/RecordImport2_Import.hs b/tests/RecordImport2_Import.hs
new file mode 100644
--- /dev/null
+++ b/tests/RecordImport2_Import.hs
@@ -0,0 +1,9 @@
+module RecordExport where
+
+import Prelude
+import FFI
+import RecordImport2_Export1
+import RecordImport2_Export2
+
+main :: Fay ()
+main = print $ R 1
diff --git a/tests/RecordImport2_Import.res b/tests/RecordImport2_Import.res
new file mode 100644
--- /dev/null
+++ b/tests/RecordImport2_Import.res
@@ -0,0 +1,1 @@
+{ instance: 'R', correct: 1 }
diff --git a/tests/RecordImport_Export b/tests/RecordImport_Export
deleted file mode 100644
--- a/tests/RecordImport_Export
+++ /dev/null
diff --git a/tests/RecordImport_Export.res b/tests/RecordImport_Export.res
new file mode 100644
--- /dev/null
+++ b/tests/RecordImport_Export.res
diff --git a/tests/RecordImport_Import b/tests/RecordImport_Import
deleted file mode 100644
--- a/tests/RecordImport_Import
+++ /dev/null
@@ -1,2 +0,0 @@
-R 1
-Fields 2 3
diff --git a/tests/RecordImport_Import.res b/tests/RecordImport_Import.res
new file mode 100644
--- /dev/null
+++ b/tests/RecordImport_Import.res
@@ -0,0 +1,2 @@
+R 1
+Fields 2 3
diff --git a/tests/Sink.hs b/tests/Sink.hs
new file mode 100644
--- /dev/null
+++ b/tests/Sink.hs
@@ -0,0 +1,14 @@
+-- https://github.com/faylang/fay/issues/285
+module Main where
+
+import Prelude
+import FFI
+
+run :: Fay ()
+run = do
+    runSink (Sink putStrLn) "hello"
+
+newtype Sink a = Sink { runSink :: a -> Fay () }
+
+main :: Fay ()
+main = run
diff --git a/tests/Sink.res b/tests/Sink.res
new file mode 100644
--- /dev/null
+++ b/tests/Sink.res
@@ -0,0 +1,1 @@
+hello
diff --git a/tests/SkipLetTypes.hs b/tests/SkipLetTypes.hs
new file mode 100644
--- /dev/null
+++ b/tests/SkipLetTypes.hs
@@ -0,0 +1,6 @@
+import Prelude
+
+main = let t :: Bool
+           t = True
+       in print t
+
diff --git a/tests/SkipLetTypes.res b/tests/SkipLetTypes.res
new file mode 100644
--- /dev/null
+++ b/tests/SkipLetTypes.res
@@ -0,0 +1,1 @@
+true
diff --git a/tests/SkipWhereTypes.hs b/tests/SkipWhereTypes.hs
new file mode 100644
--- /dev/null
+++ b/tests/SkipWhereTypes.hs
@@ -0,0 +1,7 @@
+import Prelude
+
+main = print t
+  where
+    t :: Bool
+    t = True
+
diff --git a/tests/SkipWhereTypes.res b/tests/SkipWhereTypes.res
new file mode 100644
--- /dev/null
+++ b/tests/SkipWhereTypes.res
@@ -0,0 +1,1 @@
+true
diff --git a/tests/String b/tests/String
deleted file mode 100644
--- a/tests/String
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello, World!
diff --git a/tests/String.res b/tests/String.res
new file mode 100644
--- /dev/null
+++ b/tests/String.res
@@ -0,0 +1,1 @@
+Hello, World!
diff --git a/tests/StringForcing.hs b/tests/StringForcing.hs
new file mode 100644
--- /dev/null
+++ b/tests/StringForcing.hs
@@ -0,0 +1,10 @@
+module StringForcing where
+
+import Prelude
+import FFI
+
+main = do
+  let s1 = "alma"
+  let s2 = s1 ++ map id s1
+  putStrLn s1
+  putStrLn s2
diff --git a/tests/StringForcing.res b/tests/StringForcing.res
new file mode 100644
--- /dev/null
+++ b/tests/StringForcing.res
@@ -0,0 +1,2 @@
+alma
+almaalma
diff --git a/tests/T190.hs b/tests/T190.hs
new file mode 100644
--- /dev/null
+++ b/tests/T190.hs
@@ -0,0 +1,9 @@
+module T190 where
+
+import Prelude
+
+import T190_B
+import T190_C
+
+main :: Fay ()
+main = foo "Hello"
diff --git a/tests/T190.res b/tests/T190.res
new file mode 100644
--- /dev/null
+++ b/tests/T190.res
@@ -0,0 +1,1 @@
+Hello
diff --git a/tests/T190_A.hs b/tests/T190_A.hs
new file mode 100644
--- /dev/null
+++ b/tests/T190_A.hs
@@ -0,0 +1,6 @@
+module T190_A where
+
+import Prelude
+
+foo :: Int -> Fay ()
+foo _ = putStrLn "WRONG!"
diff --git a/tests/T190_A.res b/tests/T190_A.res
new file mode 100644
--- /dev/null
+++ b/tests/T190_A.res
diff --git a/tests/T190_B.hs b/tests/T190_B.hs
new file mode 100644
--- /dev/null
+++ b/tests/T190_B.hs
@@ -0,0 +1,6 @@
+module T190_B where
+
+import T190_A
+
+main :: Fay ()
+main = return ()
diff --git a/tests/T190_B.res b/tests/T190_B.res
new file mode 100644
--- /dev/null
+++ b/tests/T190_B.res
diff --git a/tests/T190_C.hs b/tests/T190_C.hs
new file mode 100644
--- /dev/null
+++ b/tests/T190_C.hs
@@ -0,0 +1,6 @@
+module T190_C where
+
+import Prelude
+
+foo :: String -> Fay ()
+foo x = putStrLn x
diff --git a/tests/T190_C.res b/tests/T190_C.res
new file mode 100644
--- /dev/null
+++ b/tests/T190_C.res
diff --git a/tests/TupleCalls.hs b/tests/TupleCalls.hs
new file mode 100644
--- /dev/null
+++ b/tests/TupleCalls.hs
@@ -0,0 +1,19 @@
+import FFI
+import Prelude
+
+f :: (Int,Double) -> Double
+f = ffi "%1[0]+%1[1]"
+
+g :: Double -> (Int,Double)
+g = ffi "[Math.floor(%1),Math.round(100*(%1-Math.floor(%1)))/100]"
+
+h :: (String,Int) -> (Int,String)
+h = ffi "[%1[0]['length'],'#'+%1[1]['toString']()+'#']"
+
+main = do
+  print $ f (1,2.3)
+  print $ fst (g 8.76)
+  print $ snd (g 8.76)
+  print $ fst (h ("abc",12))
+  putStrLn $ snd (h ("abc",12))
+
diff --git a/tests/TupleCalls.res b/tests/TupleCalls.res
new file mode 100644
--- /dev/null
+++ b/tests/TupleCalls.res
@@ -0,0 +1,5 @@
+3.3
+8
+0.76
+3
+#12#
diff --git a/tests/TyVarSerialization.hs b/tests/TyVarSerialization.hs
new file mode 100644
--- /dev/null
+++ b/tests/TyVarSerialization.hs
@@ -0,0 +1,16 @@
+module TyVarSerialization where
+
+import Prelude
+import FFI
+
+main :: Fay ()
+main = do
+  printEither (Left [1,2,3])
+  printEither (Right "Yow!")
+  printTuple ("Hey",["ey","baby"],1,"wanna",["know"],"if you'll be my girl")
+
+printEither :: Either [Int] String -> Fay ()
+printEither = ffi "console.log(%1)"
+
+printTuple :: (String,[String],Int,String,[String],String) -> Fay ()
+printTuple = ffi "console.log(%1)"
diff --git a/tests/TyVarSerialization.res b/tests/TyVarSerialization.res
new file mode 100644
--- /dev/null
+++ b/tests/TyVarSerialization.res
@@ -0,0 +1,8 @@
+{ instance: 'Left', slot1: [ 1, 2, 3 ] }
+{ instance: 'Right', slot1: 'Yow!' }
+[ 'Hey',
+  [ 'ey', 'baby' ],
+  1,
+  'wanna',
+  [ 'know' ],
+  'if you\'ll be my girl' ]
diff --git a/tests/asPatternMatch b/tests/asPatternMatch
deleted file mode 100644
--- a/tests/asPatternMatch
+++ /dev/null
@@ -1,7 +0,0 @@
-{ car: { car: 1, cdr: { car: 2, cdr: [Object] } },
-  cdr: { car: { car: 1, cdr: [Object] }, cdr: null } }
-{ car: { car: 1, cdr: { car: 2, cdr: [Object] } },
-  cdr: { car: 1, cdr: { car: [Object], cdr: null } } }
-{ car: { car: 1, cdr: { car: 2, cdr: [Object] } },
-  cdr: { car: 1, cdr: { car: [Object], cdr: null } } }
-{ car: 'o', cdr: { car: 'k', cdr: null } }
diff --git a/tests/asPatternMatch.res b/tests/asPatternMatch.res
new file mode 100644
--- /dev/null
+++ b/tests/asPatternMatch.res
@@ -0,0 +1,4 @@
+[ [ 1, 2, 3 ], [ 1, 2, 3 ] ]
+[ [ 1, 2, 3 ], 1, [ 2, 3 ] ]
+[ [ 1, 2, 3 ], 1, [ 2, 3 ] ]
+[ 'o', 'k' ]
diff --git a/tests/baseFixities.hs b/tests/baseFixities.hs
new file mode 100644
--- /dev/null
+++ b/tests/baseFixities.hs
@@ -0,0 +1,15 @@
+import Prelude
+
+fmap :: (a -> b) -> Fay a -> Fay b
+fmap f m = m >>= (return . f)
+
+-- Note that this fixity declaration doesn't do anything except fix
+-- typechecking since Fay ignores fixities other than the baseFixities
+-- supplied to HSE. But since <$> is a base operator it's parsed as it
+-- should be.
+infixl 4 <$>
+(<$>) :: (a -> b) -> Fay a -> Fay b
+(<$>) = fmap
+
+main :: Fay ()
+main = print =<< ((+3) . (+2) <$> (return (1 :: Double)))
diff --git a/tests/baseFixities.res b/tests/baseFixities.res
new file mode 100644
--- /dev/null
+++ b/tests/baseFixities.res
@@ -0,0 +1,1 @@
+6
diff --git a/tests/basicFunctions b/tests/basicFunctions
deleted file mode 100644
--- a/tests/basicFunctions
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello, World!
diff --git a/tests/basicFunctions.res b/tests/basicFunctions.res
new file mode 100644
--- /dev/null
+++ b/tests/basicFunctions.res
@@ -0,0 +1,1 @@
+Hello, World!
diff --git a/tests/case b/tests/case
deleted file mode 100644
--- a/tests/case
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello!
diff --git a/tests/case.res b/tests/case.res
new file mode 100644
--- /dev/null
+++ b/tests/case.res
@@ -0,0 +1,1 @@
+Hello!
diff --git a/tests/case2 b/tests/case2
deleted file mode 100644
--- a/tests/case2
+++ /dev/null
@@ -1,1 +0,0 @@
-Ney!
diff --git a/tests/case2.res b/tests/case2.res
new file mode 100644
--- /dev/null
+++ b/tests/case2.res
@@ -0,0 +1,1 @@
+Ney!
diff --git a/tests/caseList b/tests/caseList
deleted file mode 100644
--- a/tests/caseList
+++ /dev/null
@@ -1,1 +0,0 @@
-OK.
diff --git a/tests/caseList.res b/tests/caseList.res
new file mode 100644
--- /dev/null
+++ b/tests/caseList.res
@@ -0,0 +1,1 @@
+OK.
diff --git a/tests/caseWildcard b/tests/caseWildcard
deleted file mode 100644
--- a/tests/caseWildcard
+++ /dev/null
@@ -1,1 +0,0 @@
-Ney!
diff --git a/tests/caseWildcard.res b/tests/caseWildcard.res
new file mode 100644
--- /dev/null
+++ b/tests/caseWildcard.res
@@ -0,0 +1,1 @@
+Ney!
diff --git a/tests/circular.hs b/tests/circular.hs
new file mode 100644
--- /dev/null
+++ b/tests/circular.hs
@@ -0,0 +1,7 @@
+import Prelude
+
+main :: Fay ()
+main = let y = x + 1
+           x = y + 1
+       in print y
+
diff --git a/tests/curry.hs b/tests/curry.hs
new file mode 100644
--- /dev/null
+++ b/tests/curry.hs
@@ -0,0 +1,11 @@
+import Prelude
+
+f :: Int -> Int -> Int
+f x y = x + y
+
+g :: (Int, Int) -> Int
+g (x,y) = x + y
+
+main = do
+  print $ curry g 3 4
+  print $ uncurry f (3,4)
diff --git a/tests/curry.res b/tests/curry.res
new file mode 100644
--- /dev/null
+++ b/tests/curry.res
@@ -0,0 +1,2 @@
+7
+7
diff --git a/tests/cycle.hs b/tests/cycle.hs
new file mode 100644
--- /dev/null
+++ b/tests/cycle.hs
@@ -0,0 +1,3 @@
+import Prelude
+
+main = mapM_ putStrLn (take 5 (cycle ["a", "b", "c"]))
diff --git a/tests/cycle.res b/tests/cycle.res
new file mode 100644
--- /dev/null
+++ b/tests/cycle.res
@@ -0,0 +1,5 @@
+a
+b
+c
+a
+b
diff --git a/tests/do b/tests/do
deleted file mode 100644
--- a/tests/do
+++ /dev/null
@@ -1,2 +0,0 @@
-Hello,
-World!
diff --git a/tests/do.res b/tests/do.res
new file mode 100644
--- /dev/null
+++ b/tests/do.res
@@ -0,0 +1,2 @@
+Hello,
+World!
diff --git a/tests/doAssingPatternMatch b/tests/doAssingPatternMatch
deleted file mode 100644
--- a/tests/doAssingPatternMatch
+++ /dev/null
@@ -1,1 +0,0 @@
-OK.
diff --git a/tests/doAssingPatternMatch.res b/tests/doAssingPatternMatch.res
new file mode 100644
--- /dev/null
+++ b/tests/doAssingPatternMatch.res
@@ -0,0 +1,1 @@
+OK.
diff --git a/tests/doBindAssign b/tests/doBindAssign
deleted file mode 100644
--- a/tests/doBindAssign
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello, World!
diff --git a/tests/doBindAssign.res b/tests/doBindAssign.res
new file mode 100644
--- /dev/null
+++ b/tests/doBindAssign.res
@@ -0,0 +1,1 @@
+Hello, World!
diff --git a/tests/doLet.hs b/tests/doLet.hs
new file mode 100644
--- /dev/null
+++ b/tests/doLet.hs
@@ -0,0 +1,46 @@
+import           Prelude
+
+main = do
+  first
+  second
+  third
+  fourth
+  fifth
+  sixth
+
+first = do
+  let x = 123
+  print x
+
+second = do
+  let x = 123
+  x <- return 10
+  print x
+
+third = do
+  x <- return 123
+  let x = 777
+  print x
+
+fourth = do
+  x <- return 123
+  let y = 777
+  print x
+  print y
+
+fifth = do
+  print 123
+  x <- return 123
+  print 10
+  let y = 777
+  print y
+  print x
+
+sixth = do
+  print 123
+  Just x <- return (Just 123)
+  print 10
+  let y = 777
+  print y
+  print x
+
diff --git a/tests/doLet.res b/tests/doLet.res
new file mode 100644
--- /dev/null
+++ b/tests/doLet.res
@@ -0,0 +1,13 @@
+123
+10
+777
+123
+777
+123
+10
+777
+123
+123
+10
+777
+123
diff --git a/tests/emptyMain b/tests/emptyMain
deleted file mode 100644
--- a/tests/emptyMain
+++ /dev/null
diff --git a/tests/emptyMain.res b/tests/emptyMain.res
new file mode 100644
--- /dev/null
+++ b/tests/emptyMain.res
diff --git a/tests/enumFrom.hs b/tests/enumFrom.hs
new file mode 100644
--- /dev/null
+++ b/tests/enumFrom.hs
@@ -0,0 +1,8 @@
+import Prelude
+
+main :: Fay ()
+main = do
+    forM_ [1..5] $ \i -> print i
+    forM_ (take 5 [1..]) $ \i -> print i
+    forM_ [1,3..9] $ \i -> print i
+    forM_ (take 3 [1,3..]) $ \i -> print i
diff --git a/tests/enumFrom.res b/tests/enumFrom.res
new file mode 100644
--- /dev/null
+++ b/tests/enumFrom.res
@@ -0,0 +1,18 @@
+1
+2
+3
+4
+5
+1
+2
+3
+4
+5
+1
+3
+5
+7
+9
+1
+3
+5
diff --git a/tests/error.hs b/tests/error.hs
new file mode 100644
--- /dev/null
+++ b/tests/error.hs
@@ -0,0 +1,3 @@
+import Prelude
+
+main = error "This is an error"
diff --git a/tests/ffiExpr.hs b/tests/ffiExpr.hs
new file mode 100644
--- /dev/null
+++ b/tests/ffiExpr.hs
@@ -0,0 +1,11 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+module Main where
+
+import Prelude
+import FFI
+
+main :: Fay ()
+main = do
+    ffi "console.log('hello world')" :: Fay ()
+    ret <- ffi "(function () { return 1; })()" :: Fay Int
+    print ret
diff --git a/tests/ffiExpr.res b/tests/ffiExpr.res
new file mode 100644
--- /dev/null
+++ b/tests/ffiExpr.res
@@ -0,0 +1,2 @@
+hello world
+1
diff --git a/tests/ffimunging.hs b/tests/ffimunging.hs
new file mode 100644
--- /dev/null
+++ b/tests/ffimunging.hs
@@ -0,0 +1,30 @@
+{-# LANGUAGE NoImplicitPrelude #-}
+
+module Maybe where
+
+import FFI
+import Prelude
+
+data Munge a b = Fudge a b
+
+data Foo = Foo (Munge [String] [Int])
+
+munge :: Foo -> Foo
+munge = ffi "%1"
+
+sponge :: Munge [String] [Int] -> Munge [String] [Int]
+sponge = ffi "%1"
+
+main = do
+  case munge (Foo (Fudge ["a","b"] [1,2])) of
+    Foo (Fudge xs is) -> do printS xs
+                            printI is
+  case sponge Fudge ["a","b"] [1,2] of
+    Fudge xs is -> do printS xs
+                      printI is
+
+printS :: [String] -> Fay ()
+printS = ffi "console.log(%1)"
+
+printI :: [Int] -> Fay ()
+printI = ffi "console.log(%1)"
diff --git a/tests/ffimunging.res b/tests/ffimunging.res
new file mode 100644
--- /dev/null
+++ b/tests/ffimunging.res
@@ -0,0 +1,4 @@
+[ 'a', 'b' ]
+[ 1, 2 ]
+[ 'a', 'b' ]
+[ 1, 2 ]
diff --git a/tests/fix b/tests/fix
deleted file mode 100644
--- a/tests/fix
+++ /dev/null
@@ -1,1 +0,0 @@
-123
diff --git a/tests/fix.hs b/tests/fix.hs
--- a/tests/fix.hs
+++ b/tests/fix.hs
@@ -2,8 +2,4 @@
 
 main = print (head (tail (fix (\xs -> 123 : xs))))
 
-head (x:xs) = x
-
 fix f = let x = f x in x
-
-tail (_:xs) = xs
diff --git a/tests/fix.res b/tests/fix.res
new file mode 100644
--- /dev/null
+++ b/tests/fix.res
@@ -0,0 +1,1 @@
+123
diff --git a/tests/fromInteger b/tests/fromInteger
deleted file mode 100644
--- a/tests/fromInteger
+++ /dev/null
@@ -1,1 +0,0 @@
-5
diff --git a/tests/fromInteger.res b/tests/fromInteger.res
new file mode 100644
--- /dev/null
+++ b/tests/fromInteger.res
@@ -0,0 +1,1 @@
+5
diff --git a/tests/guards.hs b/tests/guards.hs
new file mode 100644
--- /dev/null
+++ b/tests/guards.hs
@@ -0,0 +1,20 @@
+import Prelude
+
+f n | n <= 0 = 0
+    | n >= 10 = 11
+f n          = n + 1
+
+g n = case n of
+  n | n <= 0 -> 0
+    | n >= 10 -> 11
+  n -> n + 1
+
+main = do
+  print $ f (-1)
+  print $ f 12
+  print $ f 1
+
+  print $ g (-1)
+  print $ g 12
+  print $ g 1
+
diff --git a/tests/guards.res b/tests/guards.res
new file mode 100644
--- /dev/null
+++ b/tests/guards.res
@@ -0,0 +1,6 @@
+0
+11
+2
+0
+11
+2
diff --git a/tests/infixDataConst b/tests/infixDataConst
deleted file mode 100644
--- a/tests/infixDataConst
+++ /dev/null
@@ -1,3 +0,0 @@
-{ instance: '$58$$61$$62$',
-  slot1: { instance: 'InfixConst1', slot1: 123, slot2: 123 },
-  slot2: { instance: 'InfixConst2', slot1: false, slot2: true } }
diff --git a/tests/infixDataConst.hs b/tests/infixDataConst.hs
--- a/tests/infixDataConst.hs
+++ b/tests/infixDataConst.hs
@@ -1,15 +1,11 @@
 import           Prelude
 
 data Ty1 = Integer `InfixConst1` Integer
-instance Foreign Ty1
 
 data Ty2 = Bool `InfixConst2` Bool
-instance Foreign Ty2
 
 data Ty3 = Ty1 :=> Ty2
-instance Foreign Ty3
 
 t = (123 `InfixConst1` 123) :=> (False `InfixConst2` True)
 
 main = print t
-
diff --git a/tests/infixDataConst.res b/tests/infixDataConst.res
new file mode 100644
--- /dev/null
+++ b/tests/infixDataConst.res
@@ -0,0 +1,3 @@
+{ instance: '$58$$61$$62$',
+  slot1: { instance: 'InfixConst1', slot1: 123, slot2: 123 },
+  slot2: { instance: 'InfixConst2', slot1: false, slot2: true } }
diff --git a/tests/ints b/tests/ints
deleted file mode 100644
--- a/tests/ints
+++ /dev/null
@@ -1,1 +0,0 @@
-123
diff --git a/tests/ints.res b/tests/ints.res
new file mode 100644
--- /dev/null
+++ b/tests/ints.res
@@ -0,0 +1,1 @@
+123
diff --git a/tests/linesAndWords.hs b/tests/linesAndWords.hs
new file mode 100644
--- /dev/null
+++ b/tests/linesAndWords.hs
@@ -0,0 +1,9 @@
+import Prelude
+
+quote s = "\"" ++ s ++ "\""
+
+main = do
+  mapM_ (putStrLn . quote) $ words "  this  is\ta\n\r\ftest  "
+  putStrLn $ quote $ unwords ["this", "is", "too"]
+  mapM_ (putStrLn . quote) $ lines " \n  testing\n\n"
+  putStrLn $ quote $ unlines ["testing this", "as well"]
diff --git a/tests/linesAndWords.res b/tests/linesAndWords.res
new file mode 100644
--- /dev/null
+++ b/tests/linesAndWords.res
@@ -0,0 +1,11 @@
+"this"
+"is"
+"a"
+"test"
+"this is too"
+" "
+"  testing"
+""
+"testing this
+as well
+"
diff --git a/tests/listComprehensions.hs b/tests/listComprehensions.hs
new file mode 100644
--- /dev/null
+++ b/tests/listComprehensions.hs
@@ -0,0 +1,4 @@
+import Prelude
+
+main :: Fay ()
+main = putStrLn $ show $ sum [ x*x | x <- [1, 2, 3, 4, 5], let y = x + 4, y < 8]
diff --git a/tests/listComprehensions.res b/tests/listComprehensions.res
new file mode 100644
--- /dev/null
+++ b/tests/listComprehensions.res
@@ -0,0 +1,1 @@
+14
diff --git a/tests/listlen.hs b/tests/listlen.hs
new file mode 100644
--- /dev/null
+++ b/tests/listlen.hs
@@ -0,0 +1,49 @@
+module Listlen (main) where
+
+import FFI
+import Prelude
+
+-- Test provided by ticket
+go :: [Double] -> [Double]
+go  [] = []
+go  (c:cs) = let placed = go cs in (place c placed : placed)
+
+place :: Double -> [Double] -> Double
+place c [] = c
+place c [_] = c
+
+-- | Main entry point.
+main :: Fay ()
+main = do
+  forM_ (go [1,2]) $ \c -> c `seq` return ()
+  printS "OK"
+
+  case (1 : (2 : (3 : (4 : (5 : []))))) of
+    (_1:_2:_3:_4:_5:[]) -> printS "OK"
+
+  case (1 : (2 : (3 : (4 : (5 : []))))) of
+    (_1:_2:_3:_4:_5:_6:[]) -> printS "FAIL"
+    _ -> printS "OK"
+
+  case (1 : (2 : (3 : (4 : (5 : []))))) of
+    (1:2:3:4:5:[]) -> printS "OK"
+
+  case (1 : (2 : (3 : (4 : (5 : []))))) of
+    (1:2:3:_) -> printS "OK"
+
+  case (1 : (2 : (3 : (4 : (5 : []))))) of
+    (1:2:3:7:8:[]) -> printS "FAIL"
+    (1:2:3:4:5:[]) -> printS "OK"
+
+  case [] of
+    (1:[]) -> printS "FAIL"
+    [1,2] -> printS "FAIL"
+    [] -> printS "OK"
+
+  case ([] : []) of
+    ([1]:[]) -> printS "FAIL"
+    [[1,2]] -> printS "FAIL"
+    [[]] -> printS "OK"
+
+printS :: String -> Fay ()
+printS = ffi "console.log(%1)"
diff --git a/tests/listlen.res b/tests/listlen.res
new file mode 100644
--- /dev/null
+++ b/tests/listlen.res
@@ -0,0 +1,8 @@
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
diff --git a/tests/mutableReference b/tests/mutableReference
deleted file mode 100644
--- a/tests/mutableReference
+++ /dev/null
@@ -1,1 +0,0 @@
-Hai!
diff --git a/tests/mutableReference.hs b/tests/mutableReference.hs
--- a/tests/mutableReference.hs
+++ b/tests/mutableReference.hs
@@ -14,14 +14,12 @@
 
 data Ref a
 instance Show (Ref a)
-instance Foreign a => Foreign (Ref a)
 
-newRef :: Foreign a => a -> Fay (Ref a)
+newRef :: a -> Fay (Ref a)
 newRef = ffi "new Fay$$Ref(%1)"
 
-writeRef :: Foreign a => Ref a -> a -> Fay ()
+writeRef :: Ref a -> a -> Fay ()
 writeRef = ffi "Fay$$writeRef(%1,%2)"
 
-readRef :: Foreign a => Ref a -> Fay a
+readRef :: Ref a -> Fay a
 readRef = ffi "Fay$$readRef(%1)"
-
diff --git a/tests/mutableReference.res b/tests/mutableReference.res
new file mode 100644
--- /dev/null
+++ b/tests/mutableReference.res
@@ -0,0 +1,1 @@
+Hai!
diff --git a/tests/nameGen.hs b/tests/nameGen.hs
new file mode 100644
--- /dev/null
+++ b/tests/nameGen.hs
@@ -0,0 +1,15 @@
+import           Prelude
+
+data SomeRec = SomeRec { a :: Integer, b :: Integer } | Y | X
+
+main = do
+    -- https://github.com/faylang/fay/issues/121
+    putStrLn $ case Y of
+                    SomeRec _ _ -> "Bad"
+                    Y -> "OK."
+
+    let t = Y
+    putStrLn $ case t of
+                    SomeRec _ _ -> "Bad"
+                    Y -> "OK."
+
diff --git a/tests/nameGen.res b/tests/nameGen.res
new file mode 100644
--- /dev/null
+++ b/tests/nameGen.res
@@ -0,0 +1,2 @@
+OK.
+OK.
diff --git a/tests/namedFieldPuns.hs b/tests/namedFieldPuns.hs
new file mode 100644
--- /dev/null
+++ b/tests/namedFieldPuns.hs
@@ -0,0 +1,24 @@
+{-# LANGUAGE NamedFieldPuns #-}
+
+import           FFI
+import           Prelude
+
+data SomeRec = SomeRec { a :: Integer, b :: Integer } | Y | X
+
+fun :: SomeRec -> SomeRec
+fun SomeRec{a} = SomeRec{a=a+1, b=10}
+
+fun2 :: SomeRec -> SomeRec
+fun2 r = let a = 5 in r{a}
+
+main = do
+    let r = SomeRec{a=1, b=2}
+    print r
+    print (fun r)
+    print (fun2 r)
+
+    -- https://github.com/faylang/fay/issues/121
+    let t = Y
+    putStrLn $ case t of
+                    SomeRec{a} -> "Bad"
+                    Y -> "OK."
diff --git a/tests/namedFieldPuns.res b/tests/namedFieldPuns.res
new file mode 100644
--- /dev/null
+++ b/tests/namedFieldPuns.res
@@ -0,0 +1,4 @@
+{ instance: 'SomeRec', a: 1, b: 2 }
+{ instance: 'SomeRec', a: 2, b: 10 }
+{ instance: 'SomeRec', a: 5, b: 2 }
+OK.
diff --git a/tests/negation.hs b/tests/negation.hs
new file mode 100644
--- /dev/null
+++ b/tests/negation.hs
@@ -0,0 +1,9 @@
+import Prelude
+
+main = do print $ (-7/2)
+          print $ (-7)/2
+          print $ -f x/y
+     where f n = n * n
+           x = 5
+           y = 2
+
diff --git a/tests/negation.res b/tests/negation.res
new file mode 100644
--- /dev/null
+++ b/tests/negation.res
@@ -0,0 +1,3 @@
+-3.5
+-3.5
+-12.5
diff --git a/tests/newtype.hs b/tests/newtype.hs
new file mode 100644
--- /dev/null
+++ b/tests/newtype.hs
@@ -0,0 +1,33 @@
+import FFI
+import Prelude
+
+newtype MyInteger = MyInteger Int
+
+x = case MyInteger undefined of
+      MyInteger _ -> 1
+
+y = case undefined of
+      MyInteger _ -> 1
+
+int :: Int
+int = undefined
+
+yInt = case int of
+         _ -> 1
+
+data Foo = Bar { bar :: Double }
+newtype Baz = Baz { unwrapBaz :: Foo }
+
+getBaz :: Fay Baz
+getBaz = ffi "{ instance: 'Bar', bar: 1 }"
+
+main = do
+    print x
+    print y
+    print yInt
+    print (Baz (Bar 1))
+    baz <- getBaz
+    print baz
+    case baz of
+      Baz (Bar i) -> print i
+    print (bar $ unwrapBaz baz)
diff --git a/tests/newtype.res b/tests/newtype.res
new file mode 100644
--- /dev/null
+++ b/tests/newtype.res
@@ -0,0 +1,7 @@
+1
+1
+1
+{ instance: 'Bar', bar: 1 }
+{ instance: 'Bar', bar: 1 }
+1
+1
diff --git a/tests/numTheory.hs b/tests/numTheory.hs
new file mode 100644
--- /dev/null
+++ b/tests/numTheory.hs
@@ -0,0 +1,12 @@
+import Prelude
+
+main = do
+  print $ (subtract 3 5 :: Int)
+  print $ even 4
+  print $ even 3
+  print $ odd 4
+  print $ odd 3
+  print $ gcd (-3) (-2)
+  print $ lcm 6 10
+  print $ (4^5 :: Int)
+  print $ 4^^(-2)
diff --git a/tests/numTheory.res b/tests/numTheory.res
new file mode 100644
--- /dev/null
+++ b/tests/numTheory.res
@@ -0,0 +1,9 @@
+2
+true
+false
+false
+true
+1
+30
+1024
+0.0625
diff --git a/tests/nums.hs b/tests/nums.hs
new file mode 100644
--- /dev/null
+++ b/tests/nums.hs
@@ -0,0 +1,5 @@
+import           Prelude
+
+main :: Fay ()
+main = print (-10 :: Double)
+
diff --git a/tests/nums.res b/tests/nums.res
new file mode 100644
--- /dev/null
+++ b/tests/nums.res
@@ -0,0 +1,1 @@
+-10
diff --git a/tests/pats.hs b/tests/pats.hs
new file mode 100644
--- /dev/null
+++ b/tests/pats.hs
@@ -0,0 +1,9 @@
+import Prelude
+
+main :: Fay ()
+main =
+      case [1,2] of
+        []    -> putStrLn "got []"
+        [a]   -> putStrLn "got one value."
+        [a,b] -> putStrLn "got two values."
+
diff --git a/tests/pats.res b/tests/pats.res
new file mode 100644
--- /dev/null
+++ b/tests/pats.res
@@ -0,0 +1,1 @@
+got two values.
diff --git a/tests/patternGuards b/tests/patternGuards
deleted file mode 100644
--- a/tests/patternGuards
+++ /dev/null
@@ -1,3 +0,0 @@
-[true,false]
-[2,1,0]
-[true,false]
diff --git a/tests/patternGuards.hs b/tests/patternGuards.hs
--- a/tests/patternGuards.hs
+++ b/tests/patternGuards.hs
@@ -21,9 +21,12 @@
 
 main :: Fay ()
 main = do
-  putStrLn $ showList [isPositive 1, isPositive 0]
-  putStrLn $ showList [threeConds 3, threeConds 1, threeConds 0]
-  putStrLn $ showList [withOtherwise 2, withOtherwise 0]
+  putStrLn $ showListB [isPositive 1, isPositive 0]
+  putStrLn $ showListD [threeConds 3, threeConds 1, threeConds 0]
+  putStrLn $ showListB [withOtherwise 2, withOtherwise 0]
 
-showList :: [Double] -> String
-showList = ffi "JSON.stringify(%1)"
+showListB :: [Bool] -> String
+showListB = ffi "JSON.stringify(%1)"
+
+showListD :: [Double] -> String
+showListD = ffi "JSON.stringify(%1)"
diff --git a/tests/patternGuards.res b/tests/patternGuards.res
new file mode 100644
--- /dev/null
+++ b/tests/patternGuards.res
@@ -0,0 +1,3 @@
+[true,false]
+[2,1,0]
+[true,false]
diff --git a/tests/patternMatchingTuples.hs b/tests/patternMatchingTuples.hs
new file mode 100644
--- /dev/null
+++ b/tests/patternMatchingTuples.hs
@@ -0,0 +1,12 @@
+-- compile with fay --html-wrapper
+-- error thrown as soon as HTML page is loaded:
+-- Uncaught TypeError: Cannot read property 'car' of null
+
+import Prelude
+
+main :: Fay ()
+main = putStrLn doTest
+
+doTest :: String
+doTest = case ("x","") of
+    (x : xs, c) -> "OK."
diff --git a/tests/patternMatchingTuples.res b/tests/patternMatchingTuples.res
new file mode 100644
--- /dev/null
+++ b/tests/patternMatchingTuples.res
@@ -0,0 +1,1 @@
+OK.
diff --git a/tests/recordFunctionPatternMatch b/tests/recordFunctionPatternMatch
deleted file mode 100644
--- a/tests/recordFunctionPatternMatch
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello!
diff --git a/tests/recordFunctionPatternMatch.res b/tests/recordFunctionPatternMatch.res
new file mode 100644
--- /dev/null
+++ b/tests/recordFunctionPatternMatch.res
@@ -0,0 +1,1 @@
+Hello!
diff --git a/tests/recordPatternMatch b/tests/recordPatternMatch
deleted file mode 100644
--- a/tests/recordPatternMatch
+++ /dev/null
@@ -1,1 +0,0 @@
-World!
diff --git a/tests/recordPatternMatch.res b/tests/recordPatternMatch.res
new file mode 100644
--- /dev/null
+++ b/tests/recordPatternMatch.res
@@ -0,0 +1,1 @@
+World!
diff --git a/tests/recordPatternMatch2 b/tests/recordPatternMatch2
deleted file mode 100644
--- a/tests/recordPatternMatch2
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello!
diff --git a/tests/recordPatternMatch2.res b/tests/recordPatternMatch2.res
new file mode 100644
--- /dev/null
+++ b/tests/recordPatternMatch2.res
@@ -0,0 +1,1 @@
+Hello!
diff --git a/tests/recordUseBeforeDefine b/tests/recordUseBeforeDefine
deleted file mode 100644
--- a/tests/recordUseBeforeDefine
+++ /dev/null
@@ -1,2 +0,0 @@
-1
-1
diff --git a/tests/recordUseBeforeDefine.res b/tests/recordUseBeforeDefine.res
new file mode 100644
--- /dev/null
+++ b/tests/recordUseBeforeDefine.res
@@ -0,0 +1,2 @@
+1
+1
diff --git a/tests/recordWildCards.hs b/tests/recordWildCards.hs
new file mode 100644
--- /dev/null
+++ b/tests/recordWildCards.hs
@@ -0,0 +1,29 @@
+{-# LANGUAGE NamedFieldPuns  #-}
+{-# LANGUAGE RecordWildCards #-}
+
+import           FFI
+import           Prelude
+
+data C = C { a :: Int, b :: Int, c :: Int, d :: Int }
+
+data X = X { foo :: Int } | Y { foo :: Int }
+
+f :: C -> Int
+f (C {a, ..}) = a + d
+
+test_fun :: C
+test_fun = let {a=10; b=20; c=30; d=40} in C{..}
+
+test2 :: X -> Int
+test2 X{..} = foo
+
+main = do
+    let r = C{a=1, b=2, c=3, d=4}
+    print (f r)
+    print test_fun
+
+    let x = X{foo=9}
+    print (test2 x)
+
+    let y = Y{foo=6}
+    print (test2 y)
diff --git a/tests/recordWildCards_partial.res b/tests/recordWildCards_partial.res
new file mode 100644
--- /dev/null
+++ b/tests/recordWildCards_partial.res
@@ -0,0 +1,3 @@
+5
+{ instance: 'C', a: 10, b: 20, c: 30, d: 40 }
+9
diff --git a/tests/records b/tests/records
deleted file mode 100644
--- a/tests/records
+++ /dev/null
@@ -1,4 +0,0 @@
-Hello!
-Hello!
-Hello!
-Hello!
diff --git a/tests/records.res b/tests/records.res
new file mode 100644
--- /dev/null
+++ b/tests/records.res
@@ -0,0 +1,4 @@
+Hello!
+Hello!
+Hello!
+Hello!
diff --git a/tests/recursive.hs b/tests/recursive.hs
new file mode 100644
--- /dev/null
+++ b/tests/recursive.hs
@@ -0,0 +1,21 @@
+module Main where
+
+import Prelude
+
+ones :: [Int]
+ones = 1 : ones
+
+twos :: Int -> [Int]
+twos f = 2 : twos f
+
+threes = ones where
+  ones = 1 : ones
+
+threeConflict = head threeConflict where
+  threeConflict = 3 : threeConflict
+
+main = do
+  print (head (tail ones))
+  print (head (tail (twos 0)))
+  print (head (tail threes))
+  print threeConflict
diff --git a/tests/recursive.res b/tests/recursive.res
new file mode 100644
--- /dev/null
+++ b/tests/recursive.res
@@ -0,0 +1,4 @@
+1
+2
+1
+3
diff --git a/tests/reservedWords b/tests/reservedWords
deleted file mode 100644
--- a/tests/reservedWords
+++ /dev/null
@@ -1,37 +0,0 @@
-break
-catch
-const
-continue
-debugger
-delete
-enum
-export
-extends
-finally
-for
-function
-implements
-instanceof
-interface
-new
-null
-package
-private
-protected
-public
-return
-static
-super
-switch
-this
-throw
-try
-typeof
-undefined
-var
-void
-while
-with
-yield
-
-stdconst
diff --git a/tests/reservedWords.res b/tests/reservedWords.res
new file mode 100644
--- /dev/null
+++ b/tests/reservedWords.res
@@ -0,0 +1,37 @@
+break
+catch
+const
+continue
+debugger
+delete
+enum
+export
+extends
+finally
+for
+function
+implements
+instanceof
+interface
+new
+null
+package
+private
+protected
+public
+return
+static
+super
+switch
+this
+throw
+try
+typeof
+undefined
+var
+void
+while
+with
+yield
+
+stdconst
diff --git a/tests/sections.hs b/tests/sections.hs
new file mode 100644
--- /dev/null
+++ b/tests/sections.hs
@@ -0,0 +1,10 @@
+import Prelude
+
+withTwo :: (Int -> Int) -> Int
+withTwo f = f 2
+
+main :: Fay ()
+main = do
+  print $ (* 3) 2
+  print $ (7 `div`) 2
+  print $ withTwo (4*)
diff --git a/tests/sections.res b/tests/sections.res
new file mode 100644
--- /dev/null
+++ b/tests/sections.res
@@ -0,0 +1,3 @@
+6
+3
+8
diff --git a/tests/seq-fake.hs b/tests/seq-fake.hs
new file mode 100644
--- /dev/null
+++ b/tests/seq-fake.hs
@@ -0,0 +1,6 @@
+import Prelude
+
+fakeSeq :: a -> b -> b
+fakeSeq x y = y
+
+main = error "You shall not pass!" `fakeSeq` return ()
diff --git a/tests/seq-fake.res b/tests/seq-fake.res
new file mode 100644
--- /dev/null
+++ b/tests/seq-fake.res
diff --git a/tests/seq.hs b/tests/seq.hs
new file mode 100644
--- /dev/null
+++ b/tests/seq.hs
@@ -0,0 +1,3 @@
+import Prelude
+
+main = error "You shall not pass!" `seq` return ()
diff --git a/tests/serialization b/tests/serialization
deleted file mode 100644
--- a/tests/serialization
+++ /dev/null
@@ -1,17 +0,0 @@
-{ instance: 'Parametric',
-  slot1: { instance: 'ConcreteRecord', concreteField: 123 } }
-{ instance: 'Parametric',
-  slot1: { instance: 'ConcreteRecord', concreteField: 123 } }
-{ instance: 'Parametric',
-  slot1: { forced: false, value: [Function] } }
-{ instance: 'Just',
-  slot1: { instance: 'ConcreteRecord', concreteField: 42 } }
-{ instance: 'Just',
-  slot1: { instance: 'ConcreteRecord', concreteField: 42 } }
-{ instance: 'Just',
-  slot1: { forced: false, value: [Function] } }
-{ forced: false, value: [Function] }
-{ instance: 'Just',
-  slot1: { forced: false, value: [Function] } }
-{ instance: 'Just',
-  slot1: { instance: 'ConcreteRecord', concreteField: 42 } }
diff --git a/tests/serialization.res b/tests/serialization.res
new file mode 100644
--- /dev/null
+++ b/tests/serialization.res
@@ -0,0 +1,17 @@
+{ instance: 'Parametric',
+  slot1: { instance: 'ConcreteRecord', concreteField: 123 } }
+{ instance: 'Parametric',
+  slot1: { instance: 'ConcreteRecord', concreteField: 123 } }
+{ instance: 'Parametric',
+  slot1: { forced: false, value: [Function] } }
+{ instance: 'Just',
+  slot1: { instance: 'ConcreteRecord', concreteField: 42 } }
+{ instance: 'Just',
+  slot1: { instance: 'ConcreteRecord', concreteField: 42 } }
+{ instance: 'Just',
+  slot1: { forced: false, value: [Function] } }
+{ forced: false, value: [Function] }
+{ instance: 'Just',
+  slot1: { forced: false, value: [Function] } }
+{ instance: 'Just',
+  slot1: { instance: 'ConcreteRecord', concreteField: 42 } }
diff --git a/tests/succPred.hs b/tests/succPred.hs
new file mode 100644
--- /dev/null
+++ b/tests/succPred.hs
@@ -0,0 +1,5 @@
+import Prelude
+
+main = do
+  print (succ 1 :: Int)
+  print (pred 1 :: Int)
diff --git a/tests/succPred.res b/tests/succPred.res
new file mode 100644
--- /dev/null
+++ b/tests/succPred.res
@@ -0,0 +1,2 @@
+2
+0
diff --git a/tests/tailRecursion b/tests/tailRecursion
deleted file mode 100644
--- a/tests/tailRecursion
+++ /dev/null
@@ -1,1 +0,0 @@
-500500
diff --git a/tests/tailRecursion.res b/tests/tailRecursion.res
new file mode 100644
--- /dev/null
+++ b/tests/tailRecursion.res
@@ -0,0 +1,1 @@
+500500
diff --git a/tests/then b/tests/then
deleted file mode 100644
--- a/tests/then
+++ /dev/null
@@ -1,2 +0,0 @@
-Hello,
-World!
diff --git a/tests/then.res b/tests/then.res
new file mode 100644
--- /dev/null
+++ b/tests/then.res
@@ -0,0 +1,2 @@
+Hello,
+World!
diff --git a/tests/unit.hs b/tests/unit.hs
new file mode 100644
--- /dev/null
+++ b/tests/unit.hs
@@ -0,0 +1,5 @@
+import Prelude
+main = case (f ()) of
+  () -> print 123
+
+  where f () = ()
diff --git a/tests/unit.res b/tests/unit.res
new file mode 100644
--- /dev/null
+++ b/tests/unit.res
@@ -0,0 +1,1 @@
+123
diff --git a/tests/utf8 b/tests/utf8
deleted file mode 100644
--- a/tests/utf8
+++ /dev/null
@@ -1,62 +0,0 @@
-¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
-Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĩ ĩ Ī ī Ĭ ĭ Į į İ ı Ĳ ĳ Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ŉ Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ œ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş ş Š š Ţ ţ Ť ť Ŧ ŧ Ũ ũ Ū ū Ŭ ŭ Ů ů Ű ű Ų ų Ŵ ŵ Ŷ ŷ Ÿ Ź ź Ż ż Ž ž ſ
-ƀ Ɓ Ƃ ƃ Ƅ ƅ Ɔ Ƈ ƈ Ɖ Ɗ Ƌ ƌ ƍ Ǝ Ə Ɛ Ƒ ƒ Ɠ Ɣ ƕ Ɩ Ɨ Ƙ ƙ ƚ ƛ Ɯ Ɲ ƞ Ɵ Ơ ơ Ƣ ƣ Ƥ ƥ Ʀ Ƨ ƨ Ʃ ƪ ƫ Ƭ ƭ Ʈ Ư ư Ʊ Ʋ Ƴ ƴ Ƶ ƶ Ʒ Ƹ ƹ ƺ ƻ Ƽ ƽ ƾ ƿ ǀ ǁ ǂ ǃ Ǆ ǅ ǆ Ǉ ǈ ǉ Ǌ ǋ ǌ Ǎ ǎ Ǐ ǐ Ǒ ǒ Ǔ ǔ Ǖ ǖ Ǘ ǘ Ǚ ǚ Ǜ ǜ ǝ Ǟ ǟ Ǡ ǡ Ǣ ǣ Ǥ ǥ Ǧ ǧ Ǩ ǩ Ǫ ǫ Ǭ ǭ Ǯ ǯ ǰ Ǳ ǲ ǳ Ǵ ǵ Ǻ ǻ Ǽ ǽ Ǿ ǿ Ȁ ȁ Ȃ ȃ ...
-ɐ ɑ ɒ ɓ ɔ ɕ ɖ ɗ ɘ ə ɚ ɛ ɜ ɝ ɞ ɟ ɠ ɡ ɢ ɣ ɤ ɥ ɦ ɧ ɨ ɩ ɪ ɫ ɬ ɭ ɮ ɯ ɰ ɱ ɲ ɳ ɴ ɵ ɶ ɷ ɸ ɹ ɺ ɻ ɼ ɽ ɾ ɿ ʀ ʁ ʂ ʃ ʄ ʅ ʆ ʇ ʈ ʉ ʊ ʋ ʌ ʍ ʎ ʏ ʐ ʑ ʒ ʓ ʔ ʕ ʖ ʗ ʘ ʙ ʚ ʛ ʜ ʝ ʞ ʟ ʠ ʡ ʢ ʣ ʤ ʥ ʦ ʧ ʨ
-ʰ ʱ ʲ ʳ ʴ ʵ ʶ ʷ ʸ ʹ ʺ ʻ ʼ ʽ ʾ ʿ ˀ ˁ ˂ ˃ ˄ ˅ ˆ ˇ ˈ ˉ ˊ ˋ ˌ ˍ ˎ ˏ ː ˑ ˒ ˓ ˔ ˕ ˖ ˗ ˘ ˙ ˚ ˛ ˜ ˝ ˞ ˠ ˡ ˢ ˣ ˤ ˥ ˦ ˧ ˨ ˩
-̀ ́ ̂ ̃ ̄ ̅ ̆ ̇ ̈ ̉ ̊ ̋ ̌ ̍ ̎ ̏ ̐ ̑ ̒ ̓ ̔ ̕ ̖ ̗ ̘ ̙ ̚ ̛ ̜ ̝ ̞ ̟ ̠ ̡ ̢ ̣ ̤ ̥ ̦ ̧ ̨ ̩ ̪ ̫ ̬ ̭ ̮ ̯ ̰ ̱ ̲ ̳ ̴ ̵ ̶ ̷ ̸ ̹ ̺ ̻ ̼ ̽ ̾ ̿ ̀ ́ ͂ ̓ ̈́ ͅ ͠ ͡
-ʹ ͵ ͺ ; ΄ ΅ Ά · Έ Ή Ί Ό Ύ Ώ ΐ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω Ϊ Ϋ ά έ ή ί ΰ α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω ϊ ϋ ό ύ ώ ϐ ϑ ϒ ϓ ϔ ϕ ϖ Ϛ Ϝ Ϟ Ϡ Ϣ ϣ Ϥ ϥ Ϧ ϧ Ϩ ϩ Ϫ ϫ Ϭ ϭ Ϯ ϯ ϰ ϱ ϲ ϳ
-Ё Ђ Ѓ Є Ѕ І Ї Ј Љ Њ Ћ Ќ Ў Џ А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я ё ђ ѓ є ѕ і ї ј љ њ ћ ќ ў џ Ѡ ѡ Ѣ ѣ Ѥ ѥ Ѧ ѧ Ѩ ѩ Ѫ ѫ Ѭ ѭ Ѯ ѯ Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ Ѹ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ Ҁ ҁ ҂ ҃ ...
-Ա Բ Գ Դ Ե Զ Է Ը Թ Ժ Ի Լ Խ Ծ Կ Հ Ձ Ղ Ճ Մ Յ Ն Շ Ո Չ Պ Ջ Ռ Ս Վ Տ Ր Ց Ւ Փ Ք Օ Ֆ ՙ ՚ ՛ ՜ ՝ ՞ ՟ ա բ գ դ ե զ է ը թ ժ ի լ խ ծ կ հ ձ ղ ճ մ յ ն շ ո չ պ ջ ռ ս վ տ ր ց ւ փ ք օ ֆ և ։
-֑ ֒ ֓ ֔ ֕ ֖ ֗ ֘ ֙ ֚ ֛ ֜ ֝ ֞ ֟ ֠ ֡ ֣ ֤ ֥ ֦ ֧ ֨ ֩ ֪ ֫ ֬ ֭ ֮ ֯ ְ ֱ ֲ ֳ ִ ֵ ֶ ַ ָ ֹ ֻ ּ ֽ ־ ֿ ׀ ׁ ׂ ׃ ׄ א ב ג ד ה ו ז ח ט י ך כ ל ם מ ן נ ס ע ף פ ץ צ ק ר ש ת װ ױ ײ ׳ ״
-، ؛ ؟ ء آ أ ؤ إ ئ ا ب ة ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ـ ف ق ك ل م ن ه و ى ي ً ٌ ٍ َ ُ ِ ّ ْ ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ٪ ٫ ٬ ٭ ٰ ٱ ٲ ٳ ٴ ٵ ٶ ٷ ٸ ٹ ٺ ٻ ټ ٽ پ ٿ ڀ ځ ڂ ڃ ڄ څ چ ڇ ڈ ډ ڊ ڋ ڌ ڍ ڎ ڏ ڐ ڑ ڒ ړ ڔ ڕ ږ ڗ ژ ڙ ښ ڛ ڜ ڝ ڞ ڟ ڠ ڡ ڢ ڣ ڤ ڥ ڦ ڧ ڨ ک ڪ ګ ڬ ڭ ڮ گ ڰ ڱ ...
-ँ ं ः अ आ इ ई उ ऊ ऋ ऌ ऍ ऎ ए ऐ ऑ ऒ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न ऩ प फ ब भ म य र ऱ ल ळ ऴ व श ष स ह ़ ऽ ा ि ी ु ू ृ ॄ ॅ ॆ े ै ॉ ॊ ो ौ ् ॐ ॑ ॒ ॓ ॔ क़ ख़ ग़ ज़ ड़ ढ़ फ़ य़ ॠ ॡ ॢ ॣ । ॥ ० १ २ ३ ४ ५ ६ ७ ८ ९ ॰
-ঁ ং ঃ অ আ ই ঈ উ ঊ ঋ ঌ এ ঐ ও ঔ ক খ গ ঘ ঙ চ ছ জ ঝ ঞ ট ঠ ড ঢ ণ ত থ দ ধ ন প ফ ব ভ ম য র ল শ ষ স হ ় া ি ী ু ূ ৃ ৄ ে ৈ ো ৌ ্ ৗ ড় ঢ় য় ৠ ৡ ৢ ৣ ০ ১ ২ ৩ ৪ ৫ ৬ ৭ ৮ ৯ ৰ ৱ ৲ ৳ ৴ ৵ ৶ ৷ ৸ ৹ ৺
-ਂ ਅ ਆ ਇ ਈ ਉ ਊ ਏ ਐ ਓ ਔ ਕ ਖ ਗ ਘ ਙ ਚ ਛ ਜ ਝ ਞ ਟ ਠ ਡ ਢ ਣ ਤ ਥ ਦ ਧ ਨ ਪ ਫ ਬ ਭ ਮ ਯ ਰ ਲ ਲ਼ ਵ ਸ਼ ਸ ਹ ਼ ਾ ਿ ੀ ੁ ੂ ੇ ੈ ੋ ੌ ੍ ਖ਼ ਗ਼ ਜ਼ ੜ ਫ਼ ੦ ੧ ੨ ੩ ੪ ੫ ੬ ੭ ੮ ੯ ੰ ੱ ੲ ੳ ੴ
-ઁ ં ઃ અ આ ઇ ઈ ઉ ઊ ઋ ઍ એ ઐ ઑ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ ળ વ શ ષ સ હ ઼ ઽ ા િ ી ુ ૂ ૃ ૄ ૅ ે ૈ ૉ ો ૌ ્ ૐ ૠ ૦ ૧ ૨ ૩ ૪ ૫ ૬ ૭ ૮ ૯
-ଁ ଂ ଃ ଅ ଆ ଇ ଈ ଉ ଊ ଋ ଌ ଏ ଐ ଓ ଔ କ ଖ ଗ ଘ ଙ ଚ ଛ ଜ ଝ ଞ ଟ ଠ ଡ ଢ ଣ ତ ଥ ଦ ଧ ନ ପ ଫ ବ ଭ ମ ଯ ର ଲ ଳ ଶ ଷ ସ ହ ଼ ଽ ା ି ୀ ୁ ୂ ୃ େ ୈ ୋ ୌ ୍ ୖ ୗ ଡ଼ ଢ଼ ୟ ୠ ୡ ୦ ୧ ୨ ୩ ୪ ୫ ୬ ୭ ୮ ୯ ୰
-ஂ ஃ அ ஆ இ ஈ உ ஊ எ ஏ ஐ ஒ ஓ ஔ க ங ச ஜ ஞ ட ண த ந ன ப ம ய ர ற ல ள ழ வ ஷ ஸ ஹ ா ி ீ ு ூ ெ ே ை ொ ோ ௌ ் ௗ ௧ ௨ ௩ ௪ ௫ ௬ ௭ ௮ ௯ ௰ ௱ ௲
-ఁ ం ః అ ఆ ఇ ఈ ఉ ఊ ఋ ఌ ఎ ఏ ఐ ఒ ఓ ఔ క ఖ గ ఘ ఙ చ ఛ జ ఝ ఞ ట ఠ డ ఢ ణ త థ ద ధ న ప ఫ బ భ మ య ర ఱ ల ళ వ శ ష స హ ా ి ీ ు ూ ృ ౄ ె ే ై ొ ో ౌ ్ ౕ ౖ ౠ ౡ ౦ ౧ ౨ ౩ ౪ ౫ ౬ ౭ ౮ ౯
-ಂ ಃ ಅ ಆ ಇ ಈ ಉ ಊ ಋ ಌ ಎ ಏ ಐ ಒ ಓ ಔ ಕ ಖ ಗ ಘ ಙ ಚ ಛ ಜ ಝ ಞ ಟ ಠ ಡ ಢ ಣ ತ ಥ ದ ಧ ನ ಪ ಫ ಬ ಭ ಮ ಯ ರ ಱ ಲ ಳ ವ ಶ ಷ ಸ ಹ ಾ ಿ ೀ ು ೂ ೃ ೄ ೆ ೇ ೈ ೊ ೋ ೌ ್ ೕ ೖ ೞ ೠ ೡ ೦ ೧ ೨ ೩ ೪ ೫ ೬ ೭ ೮ ೯
-ം ഃ അ ആ ഇ ഈ ഉ ഊ ഋ ഌ എ ഏ ഐ ഒ ഓ ഔ ക ഖ ഗ ഘ ങ ച ഛ ജ ഝ ഞ ട ഠ ഡ ഢ ണ ത ഥ ദ ധ ന പ ഫ ബ ഭ മ യ ര റ ല ള ഴ വ ശ ഷ സ ഹ ാ ി ീ ു ൂ ൃ െ േ ൈ ൊ ോ ൌ ് ൗ ൠ ൡ ൦ ൧ ൨ ൩ ൪ ൫ ൬ ൭ ൮ ൯
-ก ข ฃ ค ฅ ฆ ง จ ฉ ช ซ ฌ ญ ฎ ฏ ฐ ฑ ฒ ณ ด ต ถ ท ธ น บ ป ผ ฝ พ ฟ ภ ม ย ร ฤ ล ฦ ว ศ ษ ส ห ฬ อ ฮ ฯ ะ ั า ำ ิ ี ึ ื ุ ู ฺ ฿ เ แ โ ใ ไ ๅ ๆ ็ ่ ้ ๊ ๋ ์ ํ ๎ ๏ ๐ ๑ ๒ ๓ ๔ ๕ ๖ ๗ ๘ ๙ ๚ ๛
-ກ ຂ ຄ ງ ຈ ຊ ຍ ດ ຕ ຖ ທ ນ ບ ປ ຜ ຝ ພ ຟ ມ ຢ ຣ ລ ວ ສ ຫ ອ ຮ ຯ ະ ັ າ ຳ ິ ີ ຶ ື ຸ ູ ົ ຼ ຽ ເ ແ ໂ ໃ ໄ ໆ ່ ້ ໊ ໋ ໌ ໍ ໐ ໑ ໒ ໓ ໔ ໕ ໖ ໗ ໘ ໙ ໜ ໝ
-ༀ ༁ ༂ ༃ ༄ ༅ ༆ ༇ ༈ ༉ ༊ ་ ༌ ། ༎ ༏ ༐ ༑ ༒ ༓ ༔ ༕ ༖ ༗ ༘ ༙ ༚ ༛ ༜ ༝ ༞ ༟ ༠ ༡ ༢ ༣ ༤ ༥ ༦ ༧ ༨ ༩ ༪ ༫ ༬ ༭ ༮ ༯ ༰ ༱ ༲ ༳ ༴ ༵ ༶ ༷ ༸ ༹ ༺ ༻ ༼ ༽ ༾ ༿ ཀ ཁ ག གྷ ང ཅ ཆ ཇ ཉ ཊ ཋ ཌ ཌྷ ཎ ཏ ཐ ད དྷ ན པ ཕ བ བྷ མ ཙ ཚ ཛ ཛྷ ཝ ཞ ཟ འ ཡ ར ལ ཤ ཥ ས ཧ ཨ ཀྵ ཱ ི ཱི ུ ཱུ ྲྀ ཷ ླྀ ཹ ེ ཻ ོ ཽ ཾ ཿ ྀ ཱྀ ྂ ྃ ྄ ྅ ྆ ྇ ...
-Ⴀ Ⴁ Ⴂ Ⴃ Ⴄ Ⴅ Ⴆ Ⴇ Ⴈ Ⴉ Ⴊ Ⴋ Ⴌ Ⴍ Ⴎ Ⴏ Ⴐ Ⴑ Ⴒ Ⴓ Ⴔ Ⴕ Ⴖ Ⴗ Ⴘ Ⴙ Ⴚ Ⴛ Ⴜ Ⴝ Ⴞ Ⴟ Ⴠ Ⴡ Ⴢ Ⴣ Ⴤ Ⴥ ა ბ გ დ ე ვ ზ თ ი კ ლ მ ნ ო პ ჟ რ ს ტ უ ფ ქ ღ ყ შ ჩ ც ძ წ ჭ ხ ჯ ჰ ჱ ჲ ჳ ჴ ჵ ჶ ჻
-ᄀ ᄁ ᄂ ᄃ ᄄ ᄅ ᄆ ᄇ ᄈ ᄉ ᄊ ᄋ ᄌ ᄍ ᄎ ᄏ ᄐ ᄑ ᄒ ᄓ ᄔ ᄕ ᄖ ᄗ ᄘ ᄙ ᄚ ᄛ ᄜ ᄝ ᄞ ᄟ ᄠ ᄡ ᄢ ᄣ ᄤ ᄥ ᄦ ᄧ ᄨ ᄩ ᄪ ᄫ ᄬ ᄭ ᄮ ᄯ ᄰ ᄱ ᄲ ᄳ ᄴ ᄵ ᄶ ᄷ ᄸ ᄹ ᄺ ᄻ ᄼ ᄽ ᄾ ᄿ ᅀ ᅁ ᅂ ᅃ ᅄ ᅅ ᅆ ᅇ ᅈ ᅉ ᅊ ᅋ ᅌ ᅍ ᅎ ᅏ ᅐ ᅑ ᅒ ᅓ ᅔ ᅕ ᅖ ᅗ ᅘ ᅙ ᅟ ᅠ ᅡ ᅢ ᅣ ᅤ ᅥ ᅦ ᅧ ᅨ ᅩ ᅪ ᅫ ᅬ ᅭ ᅮ ᅯ ᅰ ᅱ ᅲ ᅳ ᅴ ᅵ ᅶ ᅷ ᅸ ᅹ ᅺ ᅻ ᅼ ᅽ ᅾ ᅿ ᆀ ᆁ ᆂ ᆃ ᆄ ...
-Ḁ ḁ Ḃ ḃ Ḅ ḅ Ḇ ḇ Ḉ ḉ Ḋ ḋ Ḍ ḍ Ḏ ḏ Ḑ ḑ Ḓ ḓ Ḕ ḕ Ḗ ḗ Ḙ ḙ Ḛ ḛ Ḝ ḝ Ḟ ḟ Ḡ ḡ Ḣ ḣ Ḥ ḥ Ḧ ḧ Ḩ ḩ Ḫ ḫ Ḭ ḭ Ḯ ḯ Ḱ ḱ Ḳ ḳ Ḵ ḵ Ḷ ḷ Ḹ ḹ Ḻ ḻ Ḽ ḽ Ḿ ḿ Ṁ ṁ Ṃ ṃ Ṅ ṅ Ṇ ṇ Ṉ ṉ Ṋ ṋ Ṍ ṍ Ṏ ṏ Ṑ ṑ Ṓ ṓ Ṕ ṕ Ṗ ṗ Ṙ ṙ Ṛ ṛ Ṝ ṝ Ṟ ṟ Ṡ ṡ Ṣ ṣ Ṥ ṥ Ṧ ṧ Ṩ ṩ Ṫ ṫ Ṭ ṭ Ṯ ṯ Ṱ ṱ Ṳ ṳ Ṵ ṵ Ṷ ṷ Ṹ ṹ Ṻ ṻ Ṽ ṽ Ṿ ṿ ...
-ἀ ἁ ἂ ἃ ἄ ἅ ἆ ἇ Ἀ Ἁ Ἂ Ἃ Ἄ Ἅ Ἆ Ἇ ἐ ἑ ἒ ἓ ἔ ἕ Ἐ Ἑ Ἒ Ἓ Ἔ Ἕ ἠ ἡ ἢ ἣ ἤ ἥ ἦ ἧ Ἠ Ἡ Ἢ Ἣ Ἤ Ἥ Ἦ Ἧ ἰ ἱ ἲ ἳ ἴ ἵ ἶ ἷ Ἰ Ἱ Ἲ Ἳ Ἴ Ἵ Ἶ Ἷ ὀ ὁ ὂ ὃ ὄ ὅ Ὀ Ὁ Ὂ Ὃ Ὄ Ὅ ὐ ὑ ὒ ὓ ὔ ὕ ὖ ὗ Ὑ Ὓ Ὕ Ὗ ὠ ὡ ὢ ὣ ὤ ὥ ὦ ὧ Ὠ Ὡ Ὢ Ὣ Ὤ Ὥ Ὦ Ὧ ὰ ά ὲ έ ὴ ή ὶ ί ὸ ό ὺ ύ ὼ ώ ᾀ ᾁ ᾂ ᾃ ᾄ ᾅ ᾆ ᾇ ᾈ ᾉ ᾊ ᾋ ᾌ ᾍ ...
-‐ ‑ ‒ – — ― ‖ ‗ ‘ ’ ‚ ‛ “ ” „ ‟
-⁰ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ⁺ ⁻ ⁼ ⁽ ⁾ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₊ ₋ ₌ ₍ ₎
-₠ ₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫
-⃐ ⃑ ⃒ ⃓ ⃔ ⃕ ⃖ ⃗ ⃘ ⃙ ⃚ ⃛ ⃜ ⃝ ⃞ ⃟ ⃠ ⃡
-℀ ℁ ℂ ℃ ℄ ℅ ℆ ℇ ℈ ℉ ℊ ℋ ℌ ℍ ℎ ℏ ℐ ℑ ℒ ℓ ℔ ℕ № ℗ ℘ ℙ ℚ ℛ ℜ ℝ ℞ ℟ ℠ ℡ ™ ℣ ℤ ℥ Ω ℧ ℨ ℩ K Å ℬ ℭ ℮ ℯ ℰ ℱ Ⅎ ℳ ℴ ℵ ℶ ℷ ℸ
-⅓ ⅔ ⅕ ⅖ ⅗ ⅘ ⅙ ⅚ ⅛ ⅜ ⅝ ⅞ ⅟ Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ Ⅺ Ⅻ Ⅼ Ⅽ Ⅾ Ⅿ ⅰ ⅱ ⅲ ⅳ ⅴ ⅵ ⅶ ⅷ ⅸ ⅹ ⅺ ⅻ ⅼ ⅽ ⅾ ⅿ ↀ ↁ ↂ
-← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↚ ↛ ↜ ↝ ↞ ↟ ↠ ↡ ↢ ↣ ↤ ↥ ↦ ↧ ↨ ↩ ↪ ↫ ↬ ↭ ↮ ↯ ↰ ↱ ↲ ↳ ↴ ↵ ↶ ↷ ↸ ↹ ↺ ↻ ↼ ↽ ↾ ↿ ⇀ ⇁ ⇂ ⇃ ⇄ ⇅ ⇆ ⇇ ⇈ ⇉ ⇊ ⇋ ⇌ ⇍ ⇎ ⇏ ⇐ ⇑ ⇒ ⇓ ⇔ ⇕ ⇖ ⇗ ⇘ ⇙ ⇚ ⇛ ⇜ ⇝ ⇞ ⇟ ⇠ ⇡ ⇢ ⇣ ⇤ ⇥ ⇦ ⇧ ⇨ ⇩ ⇪
-∀ ∁ ∂ ∃ ∄ ∅ ∆ ∇ ∈ ∉ ∊ ∋ ∌ ∍ ∎ ∏ ∐ ∑ − ∓ ∔ ∕ ∖ ∗ ∘ ∙ √ ∛ ∜ ∝ ∞ ∟ ∠ ∡ ∢ ∣ ∤ ∥ ∦ ∧ ∨ ∩ ∪ ∫ ∬ ∭ ∮ ∯ ∰ ∱ ∲ ∳ ∴ ∵ ∶ ∷ ∸ ∹ ∺ ∻ ∼ ∽ ∾ ∿ ≀ ≁ ≂ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≏ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≠ ≡ ≢ ≣ ≤ ≥ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ...
-⌀ ⌂ ⌃ ⌄ ⌅ ⌆ ⌇ ⌈ ⌉ ⌊ ⌋ ⌌ ⌍ ⌎ ⌏ ⌐ ⌑ ⌒ ⌓ ⌔ ⌕ ⌖ ⌗ ⌘ ⌙ ⌚ ⌛ ⌜ ⌝ ⌞ ⌟ ⌠ ⌡ ⌢ ⌣ ⌤ ⌥ ⌦ ⌧ ⌨ 〈 〉 ⌫ ⌬ ⌭ ⌮ ⌯ ⌰ ⌱ ⌲ ⌳ ⌴ ⌵ ⌶ ⌷ ⌸ ⌹ ⌺ ⌻ ⌼ ⌽ ⌾ ⌿ ⍀ ⍁ ⍂ ⍃ ⍄ ⍅ ⍆ ⍇ ⍈ ⍉ ⍊ ⍋ ⍌ ⍍ ⍎ ⍏ ⍐ ⍑ ⍒ ⍓ ⍔ ⍕ ⍖ ⍗ ⍘ ⍙ ⍚ ⍛ ⍜ ⍝ ⍞ ⍟ ⍠ ⍡ ⍢ ⍣ ⍤ ⍥ ⍦ ⍧ ⍨ ⍩ ⍪ ⍫ ⍬ ⍭ ⍮ ⍯ ⍰ ⍱ ⍲ ⍳ ⍴ ⍵ ⍶ ⍷ ⍸ ⍹ ⍺
-␀ ␁ ␂ ␃ ␄ ␅ ␆ ␇ ␈ ␉ ␊ ␋ ␌ ␍ ␎ ␏ ␐ ␑ ␒ ␓ ␔ ␕ ␖ ␗ ␘ ␙ ␚ ␛ ␜ ␝ ␞ ␟ ␠ ␡ ␢ ␣ ␤
-⑀ ⑁ ⑂ ⑃ ⑄ ⑅ ⑆ ⑇ ⑈ ⑉ ⑊
-① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ...
-─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏ ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟ ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯ ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿ ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏ ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯ ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿
-▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏ ▐ ░ ▒ ▓ ▔ ▕
-■ □ ▢ ▣ ▤ ▥ ▦ ▧ ▨ ▩ ▪ ▫ ▬ ▭ ▮ ▯ ▰ ▱ ▲ △ ▴ ▵ ▶ ▷ ▸ ▹ ► ▻ ▼ ▽ ▾ ▿ ◀ ◁ ◂ ◃ ◄ ◅ ◆ ◇ ◈ ◉ ◊ ○ ◌ ◍ ◎ ● ◐ ◑ ◒ ◓ ◔ ◕ ◖ ◗ ◘ ◙ ◚ ◛ ◜ ◝ ◞ ◟ ◠ ◡ ◢ ◣ ◤ ◥ ◦ ◧ ◨ ◩ ◪ ◫ ◬ ◭ ◮ ◯
-☀ ☁ ☂ ☃ ☄ ★ ☆ ☇ ☈ ☉ ☊ ☋ ☌ ☍ ☎ ☏ ☐ ☑ ☒ ☓ ☚ ☛ ☜ ☝ ☞ ☟ ☠ ☡ ☢ ☣ ☤ ☥ ☦ ☧ ☨ ☩ ☪ ☫ ☬ ☭ ☮ ☯ ☰ ☱ ☲ ☳ ☴ ☵ ☶ ☷ ☸ ☹ ☺ ☻ ☼ ☽ ☾ ☿ ♀ ♁ ♂ ♃ ♄ ♅ ♆ ♇ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ ♔ ♕ ♖ ♗ ♘ ♙ ♚ ♛ ♜ ♝ ♞ ♟ ♠ ♡ ♢ ♣ ♤ ♥ ♦ ♧ ♨ ♩ ♪ ♫ ♬ ♭ ♮ ♯
-✁ ✂ ✃ ✄ ✆ ✇ ✈ ✉ ✌ ✍ ✎ ✏ ✐ ✑ ✒ ✓ ✔ ✕ ✖ ✗ ✘ ✙ ✚ ✛ ✜ ✝ ✞ ✟ ✠ ✡ ✢ ✣ ✤ ✥ ✦ ✧ ✩ ✪ ✫ ✬ ✭ ✮ ✯ ✰ ✱ ✲ ✳ ✴ ✵ ✶ ✷ ✸ ✹ ✺ ✻ ✼ ✽ ✾ ✿ ❀ ❁ ❂ ❃ ❄ ❅ ❆ ❇ ❈ ❉ ❊ ❋ ❍ ❏ ❐ ❑ ❒ ❖ ❘ ❙ ❚ ❛ ❜ ❝ ❞ ❡ ❢ ❣ ❤ ❥ ❦ ❧ ❶ ❷ ❸ ❹ ❺ ❻ ❼ ❽ ❾ ❿ ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ ➓ ➔ ➘ ➙ ➚ ➛ ➜ ➝ ...
-　 、 。 〃 〄 々 〆 〇 〈 〉 《 》 「 」 『 』 【 】 〒 〓 〔 〕 〖 〗 〘 〙 〚 〛 〜 〝 〞 〟 〠 〡 〢 〣 〤 〥 〦 〧 〨 〩 〪 〫 〬 〭 〮 〯 〰 〱 〲 〳 〴 〵 〶 〷 〿
-ぁ あ ぃ い ぅ う ぇ え ぉ お か が き ぎ く ぐ け げ こ ご さ ざ し じ す ず せ ぜ そ ぞ た だ ち ぢ っ つ づ て で と ど な に ぬ ね の は ば ぱ ひ び ぴ ふ ぶ ぷ へ べ ぺ ほ ぼ ぽ ま み む め も ゃ や ゅ ゆ ょ よ ら り る れ ろ ゎ わ ゐ ゑ を ん ゔ ゙ ゚ ゛ ゜ ゝ ゞ
-ァ ア ィ イ ゥ ウ ェ エ ォ オ カ ガ キ ギ ク グ ケ ゲ コ ゴ サ ザ シ ジ ス ズ セ ゼ ソ ゾ タ ダ チ ヂ ッ ツ ヅ テ デ ト ド ナ ニ ヌ ネ ノ ハ バ パ ヒ ビ ピ フ ブ プ ヘ ベ ペ ホ ボ ポ マ ミ ム メ モ ャ ヤ ュ ユ ョ ヨ ラ リ ル レ ロ ヮ ワ ヰ ヱ ヲ ン ヴ ヵ ヶ ヷ ヸ ヹ ヺ ・ ー ヽ ヾ
-ㄅ ㄆ ㄇ ㄈ ㄉ ㄊ ㄋ ㄌ ㄍ ㄎ ㄏ ㄐ ㄑ ㄒ ㄓ ㄔ ㄕ ㄖ ㄗ ㄘ ㄙ ㄚ ㄛ ㄜ ㄝ ㄞ ㄟ ㄠ ㄡ ㄢ ㄣ ㄤ ㄥ ㄦ ㄧ ㄨ ㄩ ㄪ ㄫ ㄬ
-ㄱ ㄲ ㄳ ㄴ ㄵ ㄶ ㄷ ㄸ ㄹ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅁ ㅂ ㅃ ㅄ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ ㅏ ㅐ ㅑ ㅒ ㅓ ㅔ ㅕ ㅖ ㅗ ㅘ ㅙ ㅚ ㅛ ㅜ ㅝ ㅞ ㅟ ㅠ ㅡ ㅢ ㅣ ㅤ ㅥ ㅦ ㅧ ㅨ ㅩ ㅪ ㅫ ㅬ ㅭ ㅮ ㅯ ㅰ ㅱ ㅲ ㅳ ㅴ ㅵ ㅶ ㅷ ㅸ ㅹ ㅺ ㅻ ㅼ ㅽ ㅾ ㅿ ㆀ ㆁ ㆂ ㆃ ㆄ ㆅ ㆆ ㆇ ㆈ ㆉ ㆊ ㆋ ㆌ ㆍ ㆎ
-㆐ ㆑ ㆒ ㆓ ㆔ ㆕ ㆖ ㆗ ㆘ ㆙ ㆚ ㆛ ㆜ ㆝ ㆞ ㆟
-㈀ ㈁ ㈂ ㈃ ㈄ ㈅ ㈆ ㈇ ㈈ ㈉ ㈊ ㈋ ㈌ ㈍ ㈎ ㈏ ㈐ ㈑ ㈒ ㈓ ㈔ ㈕ ㈖ ㈗ ㈘ ㈙ ㈚ ㈛ ㈜ ㈠ ㈡ ㈢ ㈣ ㈤ ㈥ ㈦ ㈧ ㈨ ㈩ ㈪ ㈫ ㈬ ㈭ ㈮ ㈯ ㈰ ㈱ ㈲ ㈳ ㈴ ㈵ ㈶ ㈷ ㈸ ㈹ ㈺ ㈻ ㈼ ㈽ ㈾ ㈿ ㉀ ㉁ ㉂ ㉃ ㉠ ㉡ ㉢ ㉣ ㉤ ㉥ ㉦ ㉧ ㉨ ㉩ ㉪ ㉫ ㉬ ㉭ ㉮ ㉯ ㉰ ㉱ ㉲ ㉳ ㉴ ㉵ ㉶ ㉷ ㉸ ㉹ ㉺ ㉻ ㉿ ㊀ ㊁ ㊂ ㊃ ㊄ ㊅ ㊆ ㊇ ㊈ ㊉ ㊊ ㊋ ㊌ ㊍ ㊎ ㊏ ㊐ ㊑ ㊒ ㊓ ㊔ ㊕ ㊖ ㊗ ㊘ ㊙ ㊚ ㊛ ㊜ ㊝ ㊞ ㊟ ㊠ ㊡ ...
-㌀ ㌁ ㌂ ㌃ ㌄ ㌅ ㌆ ㌇ ㌈ ㌉ ㌊ ㌋ ㌌ ㌍ ㌎ ㌏ ㌐ ㌑ ㌒ ㌓ ㌔ ㌕ ㌖ ㌗ ㌘ ㌙ ㌚ ㌛ ㌜ ㌝ ㌞ ㌟ ㌠ ㌡ ㌢ ㌣ ㌤ ㌥ ㌦ ㌧ ㌨ ㌩ ㌪ ㌫ ㌬ ㌭ ㌮ ㌯ ㌰ ㌱ ㌲ ㌳ ㌴ ㌵ ㌶ ㌷ ㌸ ㌹ ㌺ ㌻ ㌼ ㌽ ㌾ ㌿ ㍀ ㍁ ㍂ ㍃ ㍄ ㍅ ㍆ ㍇ ㍈ ㍉ ㍊ ㍋ ㍌ ㍍ ㍎ ㍏ ㍐ ㍑ ㍒ ㍓ ㍔ ㍕ ㍖ ㍗ ㍘ ㍙ ㍚ ㍛ ㍜ ㍝ ㍞ ㍟ ㍠ ㍡ ㍢ ㍣ ㍤ ㍥ ㍦ ㍧ ㍨ ㍩ ㍪ ㍫ ㍬ ㍭ ㍮ ㍯ ㍰ ㍱ ㍲ ㍳ ㍴ ㍵ ㍶ ㍻ ㍼ ㍽ ㍾ ㍿ ㎀ ㎁ ㎂ ㎃ ...
-一 丁 丂 七 丄 丅 丆 万 丈 三 上 下 丌 不 与 丏 丐 丑 丒 专 且 丕 世 丗 丘 丙 业 丛 东 丝 丞 丟 丠 両 丢 丣 两 严 並 丧 丨 丩 个 丫 丬 中 丮 丯 丰 丱 串 丳 临 丵 丶 丷 丸 丹 为 主 丼 丽 举 丿 乀 乁 乂 乃 乄 久 乆 乇 么 义 乊 之 乌 乍 乎 乏 乐 乑 乒 乓 乔 乕 乖 乗 乘 乙 乚 乛 乜 九 乞 也 习 乡 乢 乣 乤 乥 书 乧 乨 乩 乪 乫 乬 乭 乮 乯 买 乱 乲 乳 乴 乵 乶 乷 乸 乹 乺 乻 乼 乽 乾 乿 ...
-가 각 갂 갃 간 갅 갆 갇 갈 갉 갊 갋 갌 갍 갎 갏 감 갑 값 갓 갔 강 갖 갗 갘 같 갚 갛 개 객 갞 갟 갠 갡 갢 갣 갤 갥 갦 갧 갨 갩 갪 갫 갬 갭 갮 갯 갰 갱 갲 갳 갴 갵 갶 갷 갸 갹 갺 갻 갼 갽 갾 갿 걀 걁 걂 걃 걄 걅 걆 걇 걈 걉 걊 걋 걌 걍 걎 걏 걐 걑 걒 걓 걔 걕 걖 걗 걘 걙 걚 걛 걜 걝 걞 걟 걠 걡 걢 걣 걤 걥 걦 걧 걨 걩 걪 걫 걬 걭 걮 걯 거 걱 걲 걳 건 걵 걶 걷 걸 걹 걺 걻 걼 걽 걾 걿 ...
-豈 更 車 賈 滑 串 句 龜 龜 契 金 喇 奈 懶 癩 羅 蘿 螺 裸 邏 樂 洛 烙 珞 落 酪 駱 亂 卵 欄 爛 蘭 鸞 嵐 濫 藍 襤 拉 臘 蠟 廊 朗 浪 狼 郎 來 冷 勞 擄 櫓 爐 盧 老 蘆 虜 路 露 魯 鷺 碌 祿 綠 菉 錄 鹿 論 壟 弄 籠 聾 牢 磊 賂 雷 壘 屢 樓 淚 漏 累 縷 陋 勒 肋 凜 凌 稜 綾 菱 陵 讀 拏 樂 諾 丹 寧 怒 率 異 北 磻 便 復 不 泌 數 索 參 塞 省 葉 說 殺 辰 沈 拾 若 掠 略 亮 兩 凉 梁 糧 良 諒 量 勵 ...
-ﬀ ﬁ ﬂ ﬃ ﬄ ﬅ ﬆ ﬓ ﬔ ﬕ ﬖ ﬗ ﬞ ײַ ﬠ ﬡ ﬢ ﬣ ﬤ ﬥ ﬦ ﬧ ﬨ ﬩ שׁ שׂ שּׁ שּׂ אַ אָ אּ בּ גּ דּ הּ וּ זּ טּ יּ ךּ כּ לּ מּ נּ סּ ףּ פּ צּ קּ רּ שּ תּ וֹ בֿ כֿ פֿ ﭏ
-ﭐ ﭑ ﭒ ﭓ ﭔ ﭕ ﭖ ﭗ ﭘ ﭙ ﭚ ﭛ ﭜ ﭝ ﭞ ﭟ ﭠ ﭡ ﭢ ﭣ ﭤ ﭥ ﭦ ﭧ ﭨ ﭩ ﭪ ﭫ ﭬ ﭭ ﭮ ﭯ ﭰ ﭱ ﭲ ﭳ ﭴ ﭵ ﭶ ﭷ ﭸ ﭹ ﭺ ﭻ ﭼ ﭽ ﭾ ﭿ ﮀ ﮁ ﮂ ﮃ ﮄ ﮅ ﮆ ﮇ ﮈ ﮉ ﮊ ﮋ ﮌ ﮍ ﮎ ﮏ ﮐ ﮑ ﮒ ﮓ ﮔ ﮕ ﮖ ﮗ ﮘ ﮙ ﮚ ﮛ ﮜ ﮝ ﮞ ﮟ ﮠ ﮡ ﮢ ﮣ ﮤ ﮥ ﮦ ﮧ ﮨ ﮩ ﮪ ﮫ ﮬ ﮭ ﮮ ﮯ ﮰ ﮱ ﯓ ﯔ ﯕ ﯖ ﯗ ﯘ ﯙ ﯚ ﯛ ﯜ ﯝ ﯞ ﯟ ﯠ ﯡ ﯢ ﯣ ﯤ ﯥ ﯦ ﯧ ﯨ ﯩ ﯪ ﯫ ﯬ ﯭ ﯮ ﯯ ﯰ ...
-︠ ︡ ︢ ︣
-︰ ︱ ︲ ︳ ︴ ︵ ︶ ︷ ︸ ︹ ︺ ︻ ︼ ︽ ︾ ︿ ﹀ ﹁ ﹂ ﹃ ﹄ ﹉ ﹊ ﹋ ﹌ ﹍ ﹎ ﹏
-﹐ ﹑ ﹒ ﹔ ﹕ ﹖ ﹗ ﹘ ﹙ ﹚ ﹛ ﹜ ﹝ ﹞ ﹟ ﹠ ﹡ ﹢ ﹣ ﹤ ﹥ ﹦ ﹨ ﹩ ﹪ ﹫
-ﹰ ﹱ ﹲ ﹴ ﹶ ﹷ ﹸ ﹹ ﹺ ﹻ ﹼ ﹽ ﹾ ﹿ ﺀ ﺁ ﺂ ﺃ ﺄ ﺅ ﺆ ﺇ ﺈ ﺉ ﺊ ﺋ ﺌ ﺍ ﺎ ﺏ ﺐ ﺑ ﺒ ﺓ ﺔ ﺕ ﺖ ﺗ ﺘ ﺙ ﺚ ﺛ ﺜ ﺝ ﺞ ﺟ ﺠ ﺡ ﺢ ﺣ ﺤ ﺥ ﺦ ﺧ ﺨ ﺩ ﺪ ﺫ ﺬ ﺭ ﺮ ﺯ ﺰ ﺱ ﺲ ﺳ ﺴ ﺵ ﺶ ﺷ ﺸ ﺹ ﺺ ﺻ ﺼ ﺽ ﺾ ﺿ ﻀ ﻁ ﻂ ﻃ ﻄ ﻅ ﻆ ﻇ ﻈ ﻉ ﻊ ﻋ ﻌ ﻍ ﻎ ﻏ ﻐ ﻑ ﻒ ﻓ ﻔ ﻕ ﻖ ﻗ ﻘ ﻙ ﻚ ﻛ ﻜ ﻝ ﻞ ﻟ ﻠ ﻡ ﻢ ﻣ ﻤ ﻥ ﻦ ﻧ ﻨ ﻩ ﻪ ﻫ ﻬ ﻭ ﻮ ﻯ ﻰ ﻱ ...
-！ ＂ ＃ ＄ ％ ＆ ＇ （ ） ＊ ＋ ， － ． ／ ０ １ ２ ３ ４ ５ ６ ７ ８ ９ ： ； ＜ ＝ ＞ ？ ＠ Ａ Ｂ Ｃ Ｄ Ｅ Ｆ Ｇ Ｈ Ｉ Ｊ Ｋ Ｌ Ｍ Ｎ Ｏ Ｐ Ｑ Ｒ Ｓ Ｔ Ｕ Ｖ Ｗ Ｘ Ｙ Ｚ ［ ＼ ］ ＾ ＿ ｀ ａ ｂ ｃ ｄ ｅ ｆ ｇ ｈ ｉ ｊ ｋ ｌ ｍ ｎ ｏ ｐ ｑ ｒ ｓ ｔ ｕ ｖ ｗ ｘ ｙ ｚ ｛ ｜ ｝ ～ ｡ ｢ ｣ ､ ･ ｦ ｧ ｨ ｩ ｪ ｫ ｬ ｭ ｮ ｯ ｰ ｱ ｲ ｳ ｴ ｵ ｶ ｷ ｸ ｹ ｺ ｻ ｼ ｽ ｾ ｿ ﾀ ﾁ ﾂ ...
diff --git a/tests/utf8.res b/tests/utf8.res
new file mode 100644
--- /dev/null
+++ b/tests/utf8.res
@@ -0,0 +1,62 @@
+¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ
+Ā ā Ă ă Ą ą Ć ć Ĉ ĉ Ċ ċ Č č Ď ď Đ đ Ē ē Ĕ ĕ Ė ė Ę ę Ě ě Ĝ ĝ Ğ ğ Ġ ġ Ģ ģ Ĥ ĥ Ħ ħ Ĩ ĩ Ī ī Ĭ ĭ Į į İ ı Ĳ ĳ Ĵ ĵ Ķ ķ ĸ Ĺ ĺ Ļ ļ Ľ ľ Ŀ ŀ Ł ł Ń ń Ņ ņ Ň ň ŉ Ŋ ŋ Ō ō Ŏ ŏ Ő ő Œ œ Ŕ ŕ Ŗ ŗ Ř ř Ś ś Ŝ ŝ Ş ş Š š Ţ ţ Ť ť Ŧ ŧ Ũ ũ Ū ū Ŭ ŭ Ů ů Ű ű Ų ų Ŵ ŵ Ŷ ŷ Ÿ Ź ź Ż ż Ž ž ſ
+ƀ Ɓ Ƃ ƃ Ƅ ƅ Ɔ Ƈ ƈ Ɖ Ɗ Ƌ ƌ ƍ Ǝ Ə Ɛ Ƒ ƒ Ɠ Ɣ ƕ Ɩ Ɨ Ƙ ƙ ƚ ƛ Ɯ Ɲ ƞ Ɵ Ơ ơ Ƣ ƣ Ƥ ƥ Ʀ Ƨ ƨ Ʃ ƪ ƫ Ƭ ƭ Ʈ Ư ư Ʊ Ʋ Ƴ ƴ Ƶ ƶ Ʒ Ƹ ƹ ƺ ƻ Ƽ ƽ ƾ ƿ ǀ ǁ ǂ ǃ Ǆ ǅ ǆ Ǉ ǈ ǉ Ǌ ǋ ǌ Ǎ ǎ Ǐ ǐ Ǒ ǒ Ǔ ǔ Ǖ ǖ Ǘ ǘ Ǚ ǚ Ǜ ǜ ǝ Ǟ ǟ Ǡ ǡ Ǣ ǣ Ǥ ǥ Ǧ ǧ Ǩ ǩ Ǫ ǫ Ǭ ǭ Ǯ ǯ ǰ Ǳ ǲ ǳ Ǵ ǵ Ǻ ǻ Ǽ ǽ Ǿ ǿ Ȁ ȁ Ȃ ȃ ...
+ɐ ɑ ɒ ɓ ɔ ɕ ɖ ɗ ɘ ə ɚ ɛ ɜ ɝ ɞ ɟ ɠ ɡ ɢ ɣ ɤ ɥ ɦ ɧ ɨ ɩ ɪ ɫ ɬ ɭ ɮ ɯ ɰ ɱ ɲ ɳ ɴ ɵ ɶ ɷ ɸ ɹ ɺ ɻ ɼ ɽ ɾ ɿ ʀ ʁ ʂ ʃ ʄ ʅ ʆ ʇ ʈ ʉ ʊ ʋ ʌ ʍ ʎ ʏ ʐ ʑ ʒ ʓ ʔ ʕ ʖ ʗ ʘ ʙ ʚ ʛ ʜ ʝ ʞ ʟ ʠ ʡ ʢ ʣ ʤ ʥ ʦ ʧ ʨ
+ʰ ʱ ʲ ʳ ʴ ʵ ʶ ʷ ʸ ʹ ʺ ʻ ʼ ʽ ʾ ʿ ˀ ˁ ˂ ˃ ˄ ˅ ˆ ˇ ˈ ˉ ˊ ˋ ˌ ˍ ˎ ˏ ː ˑ ˒ ˓ ˔ ˕ ˖ ˗ ˘ ˙ ˚ ˛ ˜ ˝ ˞ ˠ ˡ ˢ ˣ ˤ ˥ ˦ ˧ ˨ ˩
+̀ ́ ̂ ̃ ̄ ̅ ̆ ̇ ̈ ̉ ̊ ̋ ̌ ̍ ̎ ̏ ̐ ̑ ̒ ̓ ̔ ̕ ̖ ̗ ̘ ̙ ̚ ̛ ̜ ̝ ̞ ̟ ̠ ̡ ̢ ̣ ̤ ̥ ̦ ̧ ̨ ̩ ̪ ̫ ̬ ̭ ̮ ̯ ̰ ̱ ̲ ̳ ̴ ̵ ̶ ̷ ̸ ̹ ̺ ̻ ̼ ̽ ̾ ̿ ̀ ́ ͂ ̓ ̈́ ͅ ͠ ͡
+ʹ ͵ ͺ ; ΄ ΅ Ά · Έ Ή Ί Ό Ύ Ώ ΐ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω Ϊ Ϋ ά έ ή ί ΰ α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω ϊ ϋ ό ύ ώ ϐ ϑ ϒ ϓ ϔ ϕ ϖ Ϛ Ϝ Ϟ Ϡ Ϣ ϣ Ϥ ϥ Ϧ ϧ Ϩ ϩ Ϫ ϫ Ϭ ϭ Ϯ ϯ ϰ ϱ ϲ ϳ
+Ё Ђ Ѓ Є Ѕ І Ї Ј Љ Њ Ћ Ќ Ў Џ А Б В Г Д Е Ж З И Й К Л М Н О П Р С Т У Ф Х Ц Ч Ш Щ Ъ Ы Ь Э Ю Я а б в г д е ж з и й к л м н о п р с т у ф х ц ч ш щ ъ ы ь э ю я ё ђ ѓ є ѕ і ї ј љ њ ћ ќ ў џ Ѡ ѡ Ѣ ѣ Ѥ ѥ Ѧ ѧ Ѩ ѩ Ѫ ѫ Ѭ ѭ Ѯ ѯ Ѱ ѱ Ѳ ѳ Ѵ ѵ Ѷ ѷ Ѹ ѹ Ѻ ѻ Ѽ ѽ Ѿ ѿ Ҁ ҁ ҂ ҃ ...
+Ա Բ Գ Դ Ե Զ Է Ը Թ Ժ Ի Լ Խ Ծ Կ Հ Ձ Ղ Ճ Մ Յ Ն Շ Ո Չ Պ Ջ Ռ Ս Վ Տ Ր Ց Ւ Փ Ք Օ Ֆ ՙ ՚ ՛ ՜ ՝ ՞ ՟ ա բ գ դ ե զ է ը թ ժ ի լ խ ծ կ հ ձ ղ ճ մ յ ն շ ո չ պ ջ ռ ս վ տ ր ց ւ փ ք օ ֆ և ։
+֑ ֒ ֓ ֔ ֕ ֖ ֗ ֘ ֙ ֚ ֛ ֜ ֝ ֞ ֟ ֠ ֡ ֣ ֤ ֥ ֦ ֧ ֨ ֩ ֪ ֫ ֬ ֭ ֮ ֯ ְ ֱ ֲ ֳ ִ ֵ ֶ ַ ָ ֹ ֻ ּ ֽ ־ ֿ ׀ ׁ ׂ ׃ ׄ א ב ג ד ה ו ז ח ט י ך כ ל ם מ ן נ ס ע ף פ ץ צ ק ר ש ת װ ױ ײ ׳ ״
+، ؛ ؟ ء آ أ ؤ إ ئ ا ب ة ت ث ج ح خ د ذ ر ز س ش ص ض ط ظ ع غ ـ ف ق ك ل م ن ه و ى ي ً ٌ ٍ َ ُ ِ ّ ْ ٠ ١ ٢ ٣ ٤ ٥ ٦ ٧ ٨ ٩ ٪ ٫ ٬ ٭ ٰ ٱ ٲ ٳ ٴ ٵ ٶ ٷ ٸ ٹ ٺ ٻ ټ ٽ پ ٿ ڀ ځ ڂ ڃ ڄ څ چ ڇ ڈ ډ ڊ ڋ ڌ ڍ ڎ ڏ ڐ ڑ ڒ ړ ڔ ڕ ږ ڗ ژ ڙ ښ ڛ ڜ ڝ ڞ ڟ ڠ ڡ ڢ ڣ ڤ ڥ ڦ ڧ ڨ ک ڪ ګ ڬ ڭ ڮ گ ڰ ڱ ...
+ँ ं ः अ आ इ ई उ ऊ ऋ ऌ ऍ ऎ ए ऐ ऑ ऒ ओ औ क ख ग घ ङ च छ ज झ ञ ट ठ ड ढ ण त थ द ध न ऩ प फ ब भ म य र ऱ ल ळ ऴ व श ष स ह ़ ऽ ा ि ी ु ू ृ ॄ ॅ ॆ े ै ॉ ॊ ो ौ ् ॐ ॑ ॒ ॓ ॔ क़ ख़ ग़ ज़ ड़ ढ़ फ़ य़ ॠ ॡ ॢ ॣ । ॥ ० १ २ ३ ४ ५ ६ ७ ८ ९ ॰
+ঁ ং ঃ অ আ ই ঈ উ ঊ ঋ ঌ এ ঐ ও ঔ ক খ গ ঘ ঙ চ ছ জ ঝ ঞ ট ঠ ড ঢ ণ ত থ দ ধ ন প ফ ব ভ ম য র ল শ ষ স হ ় া ি ী ু ূ ৃ ৄ ে ৈ ো ৌ ্ ৗ ড় ঢ় য় ৠ ৡ ৢ ৣ ০ ১ ২ ৩ ৪ ৫ ৬ ৭ ৮ ৯ ৰ ৱ ৲ ৳ ৴ ৵ ৶ ৷ ৸ ৹ ৺
+ਂ ਅ ਆ ਇ ਈ ਉ ਊ ਏ ਐ ਓ ਔ ਕ ਖ ਗ ਘ ਙ ਚ ਛ ਜ ਝ ਞ ਟ ਠ ਡ ਢ ਣ ਤ ਥ ਦ ਧ ਨ ਪ ਫ ਬ ਭ ਮ ਯ ਰ ਲ ਲ਼ ਵ ਸ਼ ਸ ਹ ਼ ਾ ਿ ੀ ੁ ੂ ੇ ੈ ੋ ੌ ੍ ਖ਼ ਗ਼ ਜ਼ ੜ ਫ਼ ੦ ੧ ੨ ੩ ੪ ੫ ੬ ੭ ੮ ੯ ੰ ੱ ੲ ੳ ੴ
+ઁ ં ઃ અ આ ઇ ઈ ઉ ઊ ઋ ઍ એ ઐ ઑ ઓ ઔ ક ખ ગ ઘ ઙ ચ છ જ ઝ ઞ ટ ઠ ડ ઢ ણ ત થ દ ધ ન પ ફ બ ભ મ ય ર લ ળ વ શ ષ સ હ ઼ ઽ ા િ ી ુ ૂ ૃ ૄ ૅ ે ૈ ૉ ો ૌ ્ ૐ ૠ ૦ ૧ ૨ ૩ ૪ ૫ ૬ ૭ ૮ ૯
+ଁ ଂ ଃ ଅ ଆ ଇ ଈ ଉ ଊ ଋ ଌ ଏ ଐ ଓ ଔ କ ଖ ଗ ଘ ଙ ଚ ଛ ଜ ଝ ଞ ଟ ଠ ଡ ଢ ଣ ତ ଥ ଦ ଧ ନ ପ ଫ ବ ଭ ମ ଯ ର ଲ ଳ ଶ ଷ ସ ହ ଼ ଽ ା ି ୀ ୁ ୂ ୃ େ ୈ ୋ ୌ ୍ ୖ ୗ ଡ଼ ଢ଼ ୟ ୠ ୡ ୦ ୧ ୨ ୩ ୪ ୫ ୬ ୭ ୮ ୯ ୰
+ஂ ஃ அ ஆ இ ஈ உ ஊ எ ஏ ஐ ஒ ஓ ஔ க ங ச ஜ ஞ ட ண த ந ன ப ம ய ர ற ல ள ழ வ ஷ ஸ ஹ ா ி ீ ு ூ ெ ே ை ொ ோ ௌ ் ௗ ௧ ௨ ௩ ௪ ௫ ௬ ௭ ௮ ௯ ௰ ௱ ௲
+ఁ ం ః అ ఆ ఇ ఈ ఉ ఊ ఋ ఌ ఎ ఏ ఐ ఒ ఓ ఔ క ఖ గ ఘ ఙ చ ఛ జ ఝ ఞ ట ఠ డ ఢ ణ త థ ద ధ న ప ఫ బ భ మ య ర ఱ ల ళ వ శ ష స హ ా ి ీ ు ూ ృ ౄ ె ే ై ొ ో ౌ ్ ౕ ౖ ౠ ౡ ౦ ౧ ౨ ౩ ౪ ౫ ౬ ౭ ౮ ౯
+ಂ ಃ ಅ ಆ ಇ ಈ ಉ ಊ ಋ ಌ ಎ ಏ ಐ ಒ ಓ ಔ ಕ ಖ ಗ ಘ ಙ ಚ ಛ ಜ ಝ ಞ ಟ ಠ ಡ ಢ ಣ ತ ಥ ದ ಧ ನ ಪ ಫ ಬ ಭ ಮ ಯ ರ ಱ ಲ ಳ ವ ಶ ಷ ಸ ಹ ಾ ಿ ೀ ು ೂ ೃ ೄ ೆ ೇ ೈ ೊ ೋ ೌ ್ ೕ ೖ ೞ ೠ ೡ ೦ ೧ ೨ ೩ ೪ ೫ ೬ ೭ ೮ ೯
+ം ഃ അ ആ ഇ ഈ ഉ ഊ ഋ ഌ എ ഏ ഐ ഒ ഓ ഔ ക ഖ ഗ ഘ ങ ച ഛ ജ ഝ ഞ ട ഠ ഡ ഢ ണ ത ഥ ദ ധ ന പ ഫ ബ ഭ മ യ ര റ ല ള ഴ വ ശ ഷ സ ഹ ാ ി ീ ു ൂ ൃ െ േ ൈ ൊ ോ ൌ ് ൗ ൠ ൡ ൦ ൧ ൨ ൩ ൪ ൫ ൬ ൭ ൮ ൯
+ก ข ฃ ค ฅ ฆ ง จ ฉ ช ซ ฌ ญ ฎ ฏ ฐ ฑ ฒ ณ ด ต ถ ท ธ น บ ป ผ ฝ พ ฟ ภ ม ย ร ฤ ล ฦ ว ศ ษ ส ห ฬ อ ฮ ฯ ะ ั า ำ ิ ี ึ ื ุ ู ฺ ฿ เ แ โ ใ ไ ๅ ๆ ็ ่ ้ ๊ ๋ ์ ํ ๎ ๏ ๐ ๑ ๒ ๓ ๔ ๕ ๖ ๗ ๘ ๙ ๚ ๛
+ກ ຂ ຄ ງ ຈ ຊ ຍ ດ ຕ ຖ ທ ນ ບ ປ ຜ ຝ ພ ຟ ມ ຢ ຣ ລ ວ ສ ຫ ອ ຮ ຯ ະ ັ າ ຳ ິ ີ ຶ ື ຸ ູ ົ ຼ ຽ ເ ແ ໂ ໃ ໄ ໆ ່ ້ ໊ ໋ ໌ ໍ ໐ ໑ ໒ ໓ ໔ ໕ ໖ ໗ ໘ ໙ ໜ ໝ
+ༀ ༁ ༂ ༃ ༄ ༅ ༆ ༇ ༈ ༉ ༊ ་ ༌ ། ༎ ༏ ༐ ༑ ༒ ༓ ༔ ༕ ༖ ༗ ༘ ༙ ༚ ༛ ༜ ༝ ༞ ༟ ༠ ༡ ༢ ༣ ༤ ༥ ༦ ༧ ༨ ༩ ༪ ༫ ༬ ༭ ༮ ༯ ༰ ༱ ༲ ༳ ༴ ༵ ༶ ༷ ༸ ༹ ༺ ༻ ༼ ༽ ༾ ༿ ཀ ཁ ག གྷ ང ཅ ཆ ཇ ཉ ཊ ཋ ཌ ཌྷ ཎ ཏ ཐ ད དྷ ན པ ཕ བ བྷ མ ཙ ཚ ཛ ཛྷ ཝ ཞ ཟ འ ཡ ར ལ ཤ ཥ ས ཧ ཨ ཀྵ ཱ ི ཱི ུ ཱུ ྲྀ ཷ ླྀ ཹ ེ ཻ ོ ཽ ཾ ཿ ྀ ཱྀ ྂ ྃ ྄ ྅ ྆ ྇ ...
+Ⴀ Ⴁ Ⴂ Ⴃ Ⴄ Ⴅ Ⴆ Ⴇ Ⴈ Ⴉ Ⴊ Ⴋ Ⴌ Ⴍ Ⴎ Ⴏ Ⴐ Ⴑ Ⴒ Ⴓ Ⴔ Ⴕ Ⴖ Ⴗ Ⴘ Ⴙ Ⴚ Ⴛ Ⴜ Ⴝ Ⴞ Ⴟ Ⴠ Ⴡ Ⴢ Ⴣ Ⴤ Ⴥ ა ბ გ დ ე ვ ზ თ ი კ ლ მ ნ ო პ ჟ რ ს ტ უ ფ ქ ღ ყ შ ჩ ც ძ წ ჭ ხ ჯ ჰ ჱ ჲ ჳ ჴ ჵ ჶ ჻
+ᄀ ᄁ ᄂ ᄃ ᄄ ᄅ ᄆ ᄇ ᄈ ᄉ ᄊ ᄋ ᄌ ᄍ ᄎ ᄏ ᄐ ᄑ ᄒ ᄓ ᄔ ᄕ ᄖ ᄗ ᄘ ᄙ ᄚ ᄛ ᄜ ᄝ ᄞ ᄟ ᄠ ᄡ ᄢ ᄣ ᄤ ᄥ ᄦ ᄧ ᄨ ᄩ ᄪ ᄫ ᄬ ᄭ ᄮ ᄯ ᄰ ᄱ ᄲ ᄳ ᄴ ᄵ ᄶ ᄷ ᄸ ᄹ ᄺ ᄻ ᄼ ᄽ ᄾ ᄿ ᅀ ᅁ ᅂ ᅃ ᅄ ᅅ ᅆ ᅇ ᅈ ᅉ ᅊ ᅋ ᅌ ᅍ ᅎ ᅏ ᅐ ᅑ ᅒ ᅓ ᅔ ᅕ ᅖ ᅗ ᅘ ᅙ ᅟ ᅠ ᅡ ᅢ ᅣ ᅤ ᅥ ᅦ ᅧ ᅨ ᅩ ᅪ ᅫ ᅬ ᅭ ᅮ ᅯ ᅰ ᅱ ᅲ ᅳ ᅴ ᅵ ᅶ ᅷ ᅸ ᅹ ᅺ ᅻ ᅼ ᅽ ᅾ ᅿ ᆀ ᆁ ᆂ ᆃ ᆄ ...
+Ḁ ḁ Ḃ ḃ Ḅ ḅ Ḇ ḇ Ḉ ḉ Ḋ ḋ Ḍ ḍ Ḏ ḏ Ḑ ḑ Ḓ ḓ Ḕ ḕ Ḗ ḗ Ḙ ḙ Ḛ ḛ Ḝ ḝ Ḟ ḟ Ḡ ḡ Ḣ ḣ Ḥ ḥ Ḧ ḧ Ḩ ḩ Ḫ ḫ Ḭ ḭ Ḯ ḯ Ḱ ḱ Ḳ ḳ Ḵ ḵ Ḷ ḷ Ḹ ḹ Ḻ ḻ Ḽ ḽ Ḿ ḿ Ṁ ṁ Ṃ ṃ Ṅ ṅ Ṇ ṇ Ṉ ṉ Ṋ ṋ Ṍ ṍ Ṏ ṏ Ṑ ṑ Ṓ ṓ Ṕ ṕ Ṗ ṗ Ṙ ṙ Ṛ ṛ Ṝ ṝ Ṟ ṟ Ṡ ṡ Ṣ ṣ Ṥ ṥ Ṧ ṧ Ṩ ṩ Ṫ ṫ Ṭ ṭ Ṯ ṯ Ṱ ṱ Ṳ ṳ Ṵ ṵ Ṷ ṷ Ṹ ṹ Ṻ ṻ Ṽ ṽ Ṿ ṿ ...
+ἀ ἁ ἂ ἃ ἄ ἅ ἆ ἇ Ἀ Ἁ Ἂ Ἃ Ἄ Ἅ Ἆ Ἇ ἐ ἑ ἒ ἓ ἔ ἕ Ἐ Ἑ Ἒ Ἓ Ἔ Ἕ ἠ ἡ ἢ ἣ ἤ ἥ ἦ ἧ Ἠ Ἡ Ἢ Ἣ Ἤ Ἥ Ἦ Ἧ ἰ ἱ ἲ ἳ ἴ ἵ ἶ ἷ Ἰ Ἱ Ἲ Ἳ Ἴ Ἵ Ἶ Ἷ ὀ ὁ ὂ ὃ ὄ ὅ Ὀ Ὁ Ὂ Ὃ Ὄ Ὅ ὐ ὑ ὒ ὓ ὔ ὕ ὖ ὗ Ὑ Ὓ Ὕ Ὗ ὠ ὡ ὢ ὣ ὤ ὥ ὦ ὧ Ὠ Ὡ Ὢ Ὣ Ὤ Ὥ Ὦ Ὧ ὰ ά ὲ έ ὴ ή ὶ ί ὸ ό ὺ ύ ὼ ώ ᾀ ᾁ ᾂ ᾃ ᾄ ᾅ ᾆ ᾇ ᾈ ᾉ ᾊ ᾋ ᾌ ᾍ ...
+‐ ‑ ‒ – — ― ‖ ‗ ‘ ’ ‚ ‛ “ ” „ ‟
+⁰ ⁴ ⁵ ⁶ ⁷ ⁸ ⁹ ⁺ ⁻ ⁼ ⁽ ⁾ ⁿ ₀ ₁ ₂ ₃ ₄ ₅ ₆ ₇ ₈ ₉ ₊ ₋ ₌ ₍ ₎
+₠ ₡ ₢ ₣ ₤ ₥ ₦ ₧ ₨ ₩ ₪ ₫
+⃐ ⃑ ⃒ ⃓ ⃔ ⃕ ⃖ ⃗ ⃘ ⃙ ⃚ ⃛ ⃜ ⃝ ⃞ ⃟ ⃠ ⃡
+℀ ℁ ℂ ℃ ℄ ℅ ℆ ℇ ℈ ℉ ℊ ℋ ℌ ℍ ℎ ℏ ℐ ℑ ℒ ℓ ℔ ℕ № ℗ ℘ ℙ ℚ ℛ ℜ ℝ ℞ ℟ ℠ ℡ ™ ℣ ℤ ℥ Ω ℧ ℨ ℩ K Å ℬ ℭ ℮ ℯ ℰ ℱ Ⅎ ℳ ℴ ℵ ℶ ℷ ℸ
+⅓ ⅔ ⅕ ⅖ ⅗ ⅘ ⅙ ⅚ ⅛ ⅜ ⅝ ⅞ ⅟ Ⅰ Ⅱ Ⅲ Ⅳ Ⅴ Ⅵ Ⅶ Ⅷ Ⅸ Ⅹ Ⅺ Ⅻ Ⅼ Ⅽ Ⅾ Ⅿ ⅰ ⅱ ⅲ ⅳ ⅴ ⅵ ⅶ ⅷ ⅸ ⅹ ⅺ ⅻ ⅼ ⅽ ⅾ ⅿ ↀ ↁ ↂ
+← ↑ → ↓ ↔ ↕ ↖ ↗ ↘ ↙ ↚ ↛ ↜ ↝ ↞ ↟ ↠ ↡ ↢ ↣ ↤ ↥ ↦ ↧ ↨ ↩ ↪ ↫ ↬ ↭ ↮ ↯ ↰ ↱ ↲ ↳ ↴ ↵ ↶ ↷ ↸ ↹ ↺ ↻ ↼ ↽ ↾ ↿ ⇀ ⇁ ⇂ ⇃ ⇄ ⇅ ⇆ ⇇ ⇈ ⇉ ⇊ ⇋ ⇌ ⇍ ⇎ ⇏ ⇐ ⇑ ⇒ ⇓ ⇔ ⇕ ⇖ ⇗ ⇘ ⇙ ⇚ ⇛ ⇜ ⇝ ⇞ ⇟ ⇠ ⇡ ⇢ ⇣ ⇤ ⇥ ⇦ ⇧ ⇨ ⇩ ⇪
+∀ ∁ ∂ ∃ ∄ ∅ ∆ ∇ ∈ ∉ ∊ ∋ ∌ ∍ ∎ ∏ ∐ ∑ − ∓ ∔ ∕ ∖ ∗ ∘ ∙ √ ∛ ∜ ∝ ∞ ∟ ∠ ∡ ∢ ∣ ∤ ∥ ∦ ∧ ∨ ∩ ∪ ∫ ∬ ∭ ∮ ∯ ∰ ∱ ∲ ∳ ∴ ∵ ∶ ∷ ∸ ∹ ∺ ∻ ∼ ∽ ∾ ∿ ≀ ≁ ≂ ≃ ≄ ≅ ≆ ≇ ≈ ≉ ≊ ≋ ≌ ≍ ≎ ≏ ≐ ≑ ≒ ≓ ≔ ≕ ≖ ≗ ≘ ≙ ≚ ≛ ≜ ≝ ≞ ≟ ≠ ≡ ≢ ≣ ≤ ≥ ≦ ≧ ≨ ≩ ≪ ≫ ≬ ≭ ≮ ≯ ≰ ≱ ≲ ≳ ≴ ≵ ≶ ≷ ≸ ≹ ≺ ≻ ≼ ≽ ≾ ≿ ...
+⌀ ⌂ ⌃ ⌄ ⌅ ⌆ ⌇ ⌈ ⌉ ⌊ ⌋ ⌌ ⌍ ⌎ ⌏ ⌐ ⌑ ⌒ ⌓ ⌔ ⌕ ⌖ ⌗ ⌘ ⌙ ⌚ ⌛ ⌜ ⌝ ⌞ ⌟ ⌠ ⌡ ⌢ ⌣ ⌤ ⌥ ⌦ ⌧ ⌨ 〈 〉 ⌫ ⌬ ⌭ ⌮ ⌯ ⌰ ⌱ ⌲ ⌳ ⌴ ⌵ ⌶ ⌷ ⌸ ⌹ ⌺ ⌻ ⌼ ⌽ ⌾ ⌿ ⍀ ⍁ ⍂ ⍃ ⍄ ⍅ ⍆ ⍇ ⍈ ⍉ ⍊ ⍋ ⍌ ⍍ ⍎ ⍏ ⍐ ⍑ ⍒ ⍓ ⍔ ⍕ ⍖ ⍗ ⍘ ⍙ ⍚ ⍛ ⍜ ⍝ ⍞ ⍟ ⍠ ⍡ ⍢ ⍣ ⍤ ⍥ ⍦ ⍧ ⍨ ⍩ ⍪ ⍫ ⍬ ⍭ ⍮ ⍯ ⍰ ⍱ ⍲ ⍳ ⍴ ⍵ ⍶ ⍷ ⍸ ⍹ ⍺
+␀ ␁ ␂ ␃ ␄ ␅ ␆ ␇ ␈ ␉ ␊ ␋ ␌ ␍ ␎ ␏ ␐ ␑ ␒ ␓ ␔ ␕ ␖ ␗ ␘ ␙ ␚ ␛ ␜ ␝ ␞ ␟ ␠ ␡ ␢ ␣ ␤
+⑀ ⑁ ⑂ ⑃ ⑄ ⑅ ⑆ ⑇ ⑈ ⑉ ⑊
+① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ⑴ ⑵ ⑶ ⑷ ⑸ ⑹ ⑺ ⑻ ⑼ ⑽ ⑾ ⑿ ⒀ ⒁ ⒂ ⒃ ⒄ ⒅ ⒆ ⒇ ⒈ ⒉ ⒊ ⒋ ⒌ ⒍ ⒎ ⒏ ⒐ ⒑ ⒒ ⒓ ⒔ ⒕ ⒖ ⒗ ⒘ ⒙ ⒚ ⒛ ⒜ ⒝ ⒞ ⒟ ⒠ ⒡ ⒢ ⒣ ⒤ ⒥ ⒦ ⒧ ⒨ ⒩ ⒪ ⒫ ⒬ ⒭ ⒮ ⒯ ⒰ ⒱ ⒲ ⒳ ⒴ ⒵ Ⓐ Ⓑ Ⓒ Ⓓ Ⓔ Ⓕ Ⓖ Ⓗ Ⓘ Ⓙ Ⓚ Ⓛ Ⓜ Ⓝ Ⓞ Ⓟ Ⓠ Ⓡ Ⓢ Ⓣ Ⓤ Ⓥ Ⓦ Ⓧ Ⓨ Ⓩ ⓐ ⓑ ⓒ ⓓ ⓔ ⓕ ⓖ ⓗ ⓘ ⓙ ⓚ ⓛ ⓜ ⓝ ⓞ ⓟ ...
+─ ━ │ ┃ ┄ ┅ ┆ ┇ ┈ ┉ ┊ ┋ ┌ ┍ ┎ ┏ ┐ ┑ ┒ ┓ └ ┕ ┖ ┗ ┘ ┙ ┚ ┛ ├ ┝ ┞ ┟ ┠ ┡ ┢ ┣ ┤ ┥ ┦ ┧ ┨ ┩ ┪ ┫ ┬ ┭ ┮ ┯ ┰ ┱ ┲ ┳ ┴ ┵ ┶ ┷ ┸ ┹ ┺ ┻ ┼ ┽ ┾ ┿ ╀ ╁ ╂ ╃ ╄ ╅ ╆ ╇ ╈ ╉ ╊ ╋ ╌ ╍ ╎ ╏ ═ ║ ╒ ╓ ╔ ╕ ╖ ╗ ╘ ╙ ╚ ╛ ╜ ╝ ╞ ╟ ╠ ╡ ╢ ╣ ╤ ╥ ╦ ╧ ╨ ╩ ╪ ╫ ╬ ╭ ╮ ╯ ╰ ╱ ╲ ╳ ╴ ╵ ╶ ╷ ╸ ╹ ╺ ╻ ╼ ╽ ╾ ╿
+▀ ▁ ▂ ▃ ▄ ▅ ▆ ▇ █ ▉ ▊ ▋ ▌ ▍ ▎ ▏ ▐ ░ ▒ ▓ ▔ ▕
+■ □ ▢ ▣ ▤ ▥ ▦ ▧ ▨ ▩ ▪ ▫ ▬ ▭ ▮ ▯ ▰ ▱ ▲ △ ▴ ▵ ▶ ▷ ▸ ▹ ► ▻ ▼ ▽ ▾ ▿ ◀ ◁ ◂ ◃ ◄ ◅ ◆ ◇ ◈ ◉ ◊ ○ ◌ ◍ ◎ ● ◐ ◑ ◒ ◓ ◔ ◕ ◖ ◗ ◘ ◙ ◚ ◛ ◜ ◝ ◞ ◟ ◠ ◡ ◢ ◣ ◤ ◥ ◦ ◧ ◨ ◩ ◪ ◫ ◬ ◭ ◮ ◯
+☀ ☁ ☂ ☃ ☄ ★ ☆ ☇ ☈ ☉ ☊ ☋ ☌ ☍ ☎ ☏ ☐ ☑ ☒ ☓ ☚ ☛ ☜ ☝ ☞ ☟ ☠ ☡ ☢ ☣ ☤ ☥ ☦ ☧ ☨ ☩ ☪ ☫ ☬ ☭ ☮ ☯ ☰ ☱ ☲ ☳ ☴ ☵ ☶ ☷ ☸ ☹ ☺ ☻ ☼ ☽ ☾ ☿ ♀ ♁ ♂ ♃ ♄ ♅ ♆ ♇ ♈ ♉ ♊ ♋ ♌ ♍ ♎ ♏ ♐ ♑ ♒ ♓ ♔ ♕ ♖ ♗ ♘ ♙ ♚ ♛ ♜ ♝ ♞ ♟ ♠ ♡ ♢ ♣ ♤ ♥ ♦ ♧ ♨ ♩ ♪ ♫ ♬ ♭ ♮ ♯
+✁ ✂ ✃ ✄ ✆ ✇ ✈ ✉ ✌ ✍ ✎ ✏ ✐ ✑ ✒ ✓ ✔ ✕ ✖ ✗ ✘ ✙ ✚ ✛ ✜ ✝ ✞ ✟ ✠ ✡ ✢ ✣ ✤ ✥ ✦ ✧ ✩ ✪ ✫ ✬ ✭ ✮ ✯ ✰ ✱ ✲ ✳ ✴ ✵ ✶ ✷ ✸ ✹ ✺ ✻ ✼ ✽ ✾ ✿ ❀ ❁ ❂ ❃ ❄ ❅ ❆ ❇ ❈ ❉ ❊ ❋ ❍ ❏ ❐ ❑ ❒ ❖ ❘ ❙ ❚ ❛ ❜ ❝ ❞ ❡ ❢ ❣ ❤ ❥ ❦ ❧ ❶ ❷ ❸ ❹ ❺ ❻ ❼ ❽ ❾ ❿ ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉ ➊ ➋ ➌ ➍ ➎ ➏ ➐ ➑ ➒ ➓ ➔ ➘ ➙ ➚ ➛ ➜ ➝ ...
+　 、 。 〃 〄 々 〆 〇 〈 〉 《 》 「 」 『 』 【 】 〒 〓 〔 〕 〖 〗 〘 〙 〚 〛 〜 〝 〞 〟 〠 〡 〢 〣 〤 〥 〦 〧 〨 〩 〪 〫 〬 〭 〮 〯 〰 〱 〲 〳 〴 〵 〶 〷 〿
+ぁ あ ぃ い ぅ う ぇ え ぉ お か が き ぎ く ぐ け げ こ ご さ ざ し じ す ず せ ぜ そ ぞ た だ ち ぢ っ つ づ て で と ど な に ぬ ね の は ば ぱ ひ び ぴ ふ ぶ ぷ へ べ ぺ ほ ぼ ぽ ま み む め も ゃ や ゅ ゆ ょ よ ら り る れ ろ ゎ わ ゐ ゑ を ん ゔ ゙ ゚ ゛ ゜ ゝ ゞ
+ァ ア ィ イ ゥ ウ ェ エ ォ オ カ ガ キ ギ ク グ ケ ゲ コ ゴ サ ザ シ ジ ス ズ セ ゼ ソ ゾ タ ダ チ ヂ ッ ツ ヅ テ デ ト ド ナ ニ ヌ ネ ノ ハ バ パ ヒ ビ ピ フ ブ プ ヘ ベ ペ ホ ボ ポ マ ミ ム メ モ ャ ヤ ュ ユ ョ ヨ ラ リ ル レ ロ ヮ ワ ヰ ヱ ヲ ン ヴ ヵ ヶ ヷ ヸ ヹ ヺ ・ ー ヽ ヾ
+ㄅ ㄆ ㄇ ㄈ ㄉ ㄊ ㄋ ㄌ ㄍ ㄎ ㄏ ㄐ ㄑ ㄒ ㄓ ㄔ ㄕ ㄖ ㄗ ㄘ ㄙ ㄚ ㄛ ㄜ ㄝ ㄞ ㄟ ㄠ ㄡ ㄢ ㄣ ㄤ ㄥ ㄦ ㄧ ㄨ ㄩ ㄪ ㄫ ㄬ
+ㄱ ㄲ ㄳ ㄴ ㄵ ㄶ ㄷ ㄸ ㄹ ㄺ ㄻ ㄼ ㄽ ㄾ ㄿ ㅀ ㅁ ㅂ ㅃ ㅄ ㅅ ㅆ ㅇ ㅈ ㅉ ㅊ ㅋ ㅌ ㅍ ㅎ ㅏ ㅐ ㅑ ㅒ ㅓ ㅔ ㅕ ㅖ ㅗ ㅘ ㅙ ㅚ ㅛ ㅜ ㅝ ㅞ ㅟ ㅠ ㅡ ㅢ ㅣ ㅤ ㅥ ㅦ ㅧ ㅨ ㅩ ㅪ ㅫ ㅬ ㅭ ㅮ ㅯ ㅰ ㅱ ㅲ ㅳ ㅴ ㅵ ㅶ ㅷ ㅸ ㅹ ㅺ ㅻ ㅼ ㅽ ㅾ ㅿ ㆀ ㆁ ㆂ ㆃ ㆄ ㆅ ㆆ ㆇ ㆈ ㆉ ㆊ ㆋ ㆌ ㆍ ㆎ
+㆐ ㆑ ㆒ ㆓ ㆔ ㆕ ㆖ ㆗ ㆘ ㆙ ㆚ ㆛ ㆜ ㆝ ㆞ ㆟
+㈀ ㈁ ㈂ ㈃ ㈄ ㈅ ㈆ ㈇ ㈈ ㈉ ㈊ ㈋ ㈌ ㈍ ㈎ ㈏ ㈐ ㈑ ㈒ ㈓ ㈔ ㈕ ㈖ ㈗ ㈘ ㈙ ㈚ ㈛ ㈜ ㈠ ㈡ ㈢ ㈣ ㈤ ㈥ ㈦ ㈧ ㈨ ㈩ ㈪ ㈫ ㈬ ㈭ ㈮ ㈯ ㈰ ㈱ ㈲ ㈳ ㈴ ㈵ ㈶ ㈷ ㈸ ㈹ ㈺ ㈻ ㈼ ㈽ ㈾ ㈿ ㉀ ㉁ ㉂ ㉃ ㉠ ㉡ ㉢ ㉣ ㉤ ㉥ ㉦ ㉧ ㉨ ㉩ ㉪ ㉫ ㉬ ㉭ ㉮ ㉯ ㉰ ㉱ ㉲ ㉳ ㉴ ㉵ ㉶ ㉷ ㉸ ㉹ ㉺ ㉻ ㉿ ㊀ ㊁ ㊂ ㊃ ㊄ ㊅ ㊆ ㊇ ㊈ ㊉ ㊊ ㊋ ㊌ ㊍ ㊎ ㊏ ㊐ ㊑ ㊒ ㊓ ㊔ ㊕ ㊖ ㊗ ㊘ ㊙ ㊚ ㊛ ㊜ ㊝ ㊞ ㊟ ㊠ ㊡ ...
+㌀ ㌁ ㌂ ㌃ ㌄ ㌅ ㌆ ㌇ ㌈ ㌉ ㌊ ㌋ ㌌ ㌍ ㌎ ㌏ ㌐ ㌑ ㌒ ㌓ ㌔ ㌕ ㌖ ㌗ ㌘ ㌙ ㌚ ㌛ ㌜ ㌝ ㌞ ㌟ ㌠ ㌡ ㌢ ㌣ ㌤ ㌥ ㌦ ㌧ ㌨ ㌩ ㌪ ㌫ ㌬ ㌭ ㌮ ㌯ ㌰ ㌱ ㌲ ㌳ ㌴ ㌵ ㌶ ㌷ ㌸ ㌹ ㌺ ㌻ ㌼ ㌽ ㌾ ㌿ ㍀ ㍁ ㍂ ㍃ ㍄ ㍅ ㍆ ㍇ ㍈ ㍉ ㍊ ㍋ ㍌ ㍍ ㍎ ㍏ ㍐ ㍑ ㍒ ㍓ ㍔ ㍕ ㍖ ㍗ ㍘ ㍙ ㍚ ㍛ ㍜ ㍝ ㍞ ㍟ ㍠ ㍡ ㍢ ㍣ ㍤ ㍥ ㍦ ㍧ ㍨ ㍩ ㍪ ㍫ ㍬ ㍭ ㍮ ㍯ ㍰ ㍱ ㍲ ㍳ ㍴ ㍵ ㍶ ㍻ ㍼ ㍽ ㍾ ㍿ ㎀ ㎁ ㎂ ㎃ ...
+一 丁 丂 七 丄 丅 丆 万 丈 三 上 下 丌 不 与 丏 丐 丑 丒 专 且 丕 世 丗 丘 丙 业 丛 东 丝 丞 丟 丠 両 丢 丣 两 严 並 丧 丨 丩 个 丫 丬 中 丮 丯 丰 丱 串 丳 临 丵 丶 丷 丸 丹 为 主 丼 丽 举 丿 乀 乁 乂 乃 乄 久 乆 乇 么 义 乊 之 乌 乍 乎 乏 乐 乑 乒 乓 乔 乕 乖 乗 乘 乙 乚 乛 乜 九 乞 也 习 乡 乢 乣 乤 乥 书 乧 乨 乩 乪 乫 乬 乭 乮 乯 买 乱 乲 乳 乴 乵 乶 乷 乸 乹 乺 乻 乼 乽 乾 乿 ...
+가 각 갂 갃 간 갅 갆 갇 갈 갉 갊 갋 갌 갍 갎 갏 감 갑 값 갓 갔 강 갖 갗 갘 같 갚 갛 개 객 갞 갟 갠 갡 갢 갣 갤 갥 갦 갧 갨 갩 갪 갫 갬 갭 갮 갯 갰 갱 갲 갳 갴 갵 갶 갷 갸 갹 갺 갻 갼 갽 갾 갿 걀 걁 걂 걃 걄 걅 걆 걇 걈 걉 걊 걋 걌 걍 걎 걏 걐 걑 걒 걓 걔 걕 걖 걗 걘 걙 걚 걛 걜 걝 걞 걟 걠 걡 걢 걣 걤 걥 걦 걧 걨 걩 걪 걫 걬 걭 걮 걯 거 걱 걲 걳 건 걵 걶 걷 걸 걹 걺 걻 걼 걽 걾 걿 ...
+豈 更 車 賈 滑 串 句 龜 龜 契 金 喇 奈 懶 癩 羅 蘿 螺 裸 邏 樂 洛 烙 珞 落 酪 駱 亂 卵 欄 爛 蘭 鸞 嵐 濫 藍 襤 拉 臘 蠟 廊 朗 浪 狼 郎 來 冷 勞 擄 櫓 爐 盧 老 蘆 虜 路 露 魯 鷺 碌 祿 綠 菉 錄 鹿 論 壟 弄 籠 聾 牢 磊 賂 雷 壘 屢 樓 淚 漏 累 縷 陋 勒 肋 凜 凌 稜 綾 菱 陵 讀 拏 樂 諾 丹 寧 怒 率 異 北 磻 便 復 不 泌 數 索 參 塞 省 葉 說 殺 辰 沈 拾 若 掠 略 亮 兩 凉 梁 糧 良 諒 量 勵 ...
+ﬀ ﬁ ﬂ ﬃ ﬄ ﬅ ﬆ ﬓ ﬔ ﬕ ﬖ ﬗ ﬞ ײַ ﬠ ﬡ ﬢ ﬣ ﬤ ﬥ ﬦ ﬧ ﬨ ﬩ שׁ שׂ שּׁ שּׂ אַ אָ אּ בּ גּ דּ הּ וּ זּ טּ יּ ךּ כּ לּ מּ נּ סּ ףּ פּ צּ קּ רּ שּ תּ וֹ בֿ כֿ פֿ ﭏ
+ﭐ ﭑ ﭒ ﭓ ﭔ ﭕ ﭖ ﭗ ﭘ ﭙ ﭚ ﭛ ﭜ ﭝ ﭞ ﭟ ﭠ ﭡ ﭢ ﭣ ﭤ ﭥ ﭦ ﭧ ﭨ ﭩ ﭪ ﭫ ﭬ ﭭ ﭮ ﭯ ﭰ ﭱ ﭲ ﭳ ﭴ ﭵ ﭶ ﭷ ﭸ ﭹ ﭺ ﭻ ﭼ ﭽ ﭾ ﭿ ﮀ ﮁ ﮂ ﮃ ﮄ ﮅ ﮆ ﮇ ﮈ ﮉ ﮊ ﮋ ﮌ ﮍ ﮎ ﮏ ﮐ ﮑ ﮒ ﮓ ﮔ ﮕ ﮖ ﮗ ﮘ ﮙ ﮚ ﮛ ﮜ ﮝ ﮞ ﮟ ﮠ ﮡ ﮢ ﮣ ﮤ ﮥ ﮦ ﮧ ﮨ ﮩ ﮪ ﮫ ﮬ ﮭ ﮮ ﮯ ﮰ ﮱ ﯓ ﯔ ﯕ ﯖ ﯗ ﯘ ﯙ ﯚ ﯛ ﯜ ﯝ ﯞ ﯟ ﯠ ﯡ ﯢ ﯣ ﯤ ﯥ ﯦ ﯧ ﯨ ﯩ ﯪ ﯫ ﯬ ﯭ ﯮ ﯯ ﯰ ...
+︠ ︡ ︢ ︣
+︰ ︱ ︲ ︳ ︴ ︵ ︶ ︷ ︸ ︹ ︺ ︻ ︼ ︽ ︾ ︿ ﹀ ﹁ ﹂ ﹃ ﹄ ﹉ ﹊ ﹋ ﹌ ﹍ ﹎ ﹏
+﹐ ﹑ ﹒ ﹔ ﹕ ﹖ ﹗ ﹘ ﹙ ﹚ ﹛ ﹜ ﹝ ﹞ ﹟ ﹠ ﹡ ﹢ ﹣ ﹤ ﹥ ﹦ ﹨ ﹩ ﹪ ﹫
+ﹰ ﹱ ﹲ ﹴ ﹶ ﹷ ﹸ ﹹ ﹺ ﹻ ﹼ ﹽ ﹾ ﹿ ﺀ ﺁ ﺂ ﺃ ﺄ ﺅ ﺆ ﺇ ﺈ ﺉ ﺊ ﺋ ﺌ ﺍ ﺎ ﺏ ﺐ ﺑ ﺒ ﺓ ﺔ ﺕ ﺖ ﺗ ﺘ ﺙ ﺚ ﺛ ﺜ ﺝ ﺞ ﺟ ﺠ ﺡ ﺢ ﺣ ﺤ ﺥ ﺦ ﺧ ﺨ ﺩ ﺪ ﺫ ﺬ ﺭ ﺮ ﺯ ﺰ ﺱ ﺲ ﺳ ﺴ ﺵ ﺶ ﺷ ﺸ ﺹ ﺺ ﺻ ﺼ ﺽ ﺾ ﺿ ﻀ ﻁ ﻂ ﻃ ﻄ ﻅ ﻆ ﻇ ﻈ ﻉ ﻊ ﻋ ﻌ ﻍ ﻎ ﻏ ﻐ ﻑ ﻒ ﻓ ﻔ ﻕ ﻖ ﻗ ﻘ ﻙ ﻚ ﻛ ﻜ ﻝ ﻞ ﻟ ﻠ ﻡ ﻢ ﻣ ﻤ ﻥ ﻦ ﻧ ﻨ ﻩ ﻪ ﻫ ﻬ ﻭ ﻮ ﻯ ﻰ ﻱ ...
+！ ＂ ＃ ＄ ％ ＆ ＇ （ ） ＊ ＋ ， － ． ／ ０ １ ２ ３ ４ ５ ６ ７ ８ ９ ： ； ＜ ＝ ＞ ？ ＠ Ａ Ｂ Ｃ Ｄ Ｅ Ｆ Ｇ Ｈ Ｉ Ｊ Ｋ Ｌ Ｍ Ｎ Ｏ Ｐ Ｑ Ｒ Ｓ Ｔ Ｕ Ｖ Ｗ Ｘ Ｙ Ｚ ［ ＼ ］ ＾ ＿ ｀ ａ ｂ ｃ ｄ ｅ ｆ ｇ ｈ ｉ ｊ ｋ ｌ ｍ ｎ ｏ ｐ ｑ ｒ ｓ ｔ ｕ ｖ ｗ ｘ ｙ ｚ ｛ ｜ ｝ ～ ｡ ｢ ｣ ､ ･ ｦ ｧ ｨ ｩ ｪ ｫ ｬ ｭ ｮ ｯ ｰ ｱ ｲ ｳ ｴ ｵ ｶ ｷ ｸ ｹ ｺ ｻ ｼ ｽ ｾ ｿ ﾀ ﾁ ﾂ ...
diff --git a/tests/where b/tests/where
deleted file mode 100644
--- a/tests/where
+++ /dev/null
@@ -1,1 +0,0 @@
-Hello my friends and family
diff --git a/tests/where.res b/tests/where.res
new file mode 100644
--- /dev/null
+++ b/tests/where.res
@@ -0,0 +1,1 @@
+Hello my friends and family
diff --git a/tests/whereBind.hs b/tests/whereBind.hs
new file mode 100644
--- /dev/null
+++ b/tests/whereBind.hs
@@ -0,0 +1,8 @@
+import           Prelude
+
+main :: Fay ()
+main =
+    let x = 10
+    in putStrLn $ show (x + y)
+  where y = 20
+
diff --git a/tests/whereBind.res b/tests/whereBind.res
new file mode 100644
--- /dev/null
+++ b/tests/whereBind.res
@@ -0,0 +1,1 @@
+30
diff --git a/tests/whereBind2.hs b/tests/whereBind2.hs
new file mode 100644
--- /dev/null
+++ b/tests/whereBind2.hs
@@ -0,0 +1,11 @@
+import           Prelude
+
+someFun x = fun x
+  where fun x | x < 50 = "ok"
+              | otherwise = "nop"
+
+main :: Fay ()
+main = do
+    putStrLn (someFun 30)
+    putStrLn (someFun 100)
+
diff --git a/tests/whereBind2.res b/tests/whereBind2.res
new file mode 100644
--- /dev/null
+++ b/tests/whereBind2.res
@@ -0,0 +1,2 @@
+ok
+nop
diff --git a/tests/whereBind3.hs b/tests/whereBind3.hs
new file mode 100644
--- /dev/null
+++ b/tests/whereBind3.hs
@@ -0,0 +1,9 @@
+import           Prelude
+
+f :: String -> String
+f x = friends ++ family
+  where friends = x
+        family = " and family"
+
+main = putStrLn (f "my friends")
+
diff --git a/tests/whereBind3.res b/tests/whereBind3.res
new file mode 100644
--- /dev/null
+++ b/tests/whereBind3.res
@@ -0,0 +1,1 @@
+my friends and family
