packages feed

purescript 0.5.5 → 0.5.6

raw patch · 27 files changed

+483/−283 lines, 27 filesdep ~basePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: base

API changes (from Hackage documentation)

- Language.PureScript.CodeGen.JS: CommonJS :: ModuleType
- Language.PureScript.CodeGen.JS: Globals :: ModuleType
- Language.PureScript.CodeGen.JS: data ModuleType
- Language.PureScript.Errors: newtype ErrorStack
- Language.PureScript.Names: instance Typeable1 Qualified
- Language.PureScript.Options: defaultOptions :: Options
- Language.PureScript.Options: instance Show Options
- Language.PureScript.Options: optionsBrowserNamespace :: Options -> Maybe String
- Language.PureScript.Options: optionsCodeGenModules :: Options -> [String]
- Language.PureScript.Options: optionsModules :: Options -> [String]
+ Language.PureScript.Errors: MultipleErrors :: [ErrorStack] -> ErrorStack
+ Language.PureScript.Errors: data ErrorStack
+ Language.PureScript.Names: instance Typeable Qualified
+ Language.PureScript.Options: Compile :: Mode
+ Language.PureScript.Options: CompileOptions :: String -> [String] -> [String] -> ModeOptions Compile
+ Language.PureScript.Options: Make :: Mode
+ Language.PureScript.Options: MakeOptions :: ModeOptions Make
+ Language.PureScript.Options: browserNamespace :: ModeOptions Compile -> String
+ Language.PureScript.Options: codeGenModules :: ModeOptions Compile -> [String]
+ Language.PureScript.Options: data Mode
+ Language.PureScript.Options: data ModeOptions mode
+ Language.PureScript.Options: defaultCompileOptions :: Options Compile
+ Language.PureScript.Options: defaultMakeOptions :: Options Make
+ Language.PureScript.Options: entryPointModules :: ModeOptions Compile -> [String]
+ Language.PureScript.Options: instance Show (ModeOptions mode)
+ Language.PureScript.Options: instance Show (Options mode)
+ Language.PureScript.Options: optionsAdditional :: Options mode -> ModeOptions mode
+ Language.PureScript.TypeChecker.Monad: parU :: [a] -> (a -> UnifyT t Check b) -> UnifyT t Check [b]
+ Language.PureScript.TypeClassDictionaries: tcdExported :: TypeClassDictionaryInScope -> Bool
- Language.PureScript: compile :: Options -> [Module] -> [String] -> Either String (String, String, Environment)
+ Language.PureScript: compile :: Options Compile -> [Module] -> [String] -> Either String (String, String, Environment)
- Language.PureScript: compile' :: Environment -> Options -> [Module] -> [String] -> Either String (String, String, Environment)
+ Language.PureScript: compile' :: Environment -> Options Compile -> [Module] -> [String] -> Either String (String, String, Environment)
- Language.PureScript: make :: (Functor m, Applicative m, Monad m, MonadMake m) => FilePath -> Options -> [(FilePath, Module)] -> [String] -> m Environment
+ Language.PureScript: make :: (Functor m, Applicative m, Monad m, MonadMake m) => FilePath -> Options Make -> [(FilePath, Module)] -> [String] -> m Environment
- Language.PureScript.CodeGen.JS: declToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Declaration -> Environment -> SupplyT m (Maybe [JS])
+ Language.PureScript.CodeGen.JS: declToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Declaration -> Environment -> SupplyT m (Maybe [JS])
- Language.PureScript.CodeGen.JS: moduleToJs :: (Functor m, Applicative m, Monad m) => ModuleType -> Options -> Module -> Environment -> SupplyT m [JS]
+ Language.PureScript.CodeGen.JS: moduleToJs :: (Functor m, Applicative m, Monad m) => Options mode -> Module -> Environment -> SupplyT m [JS]
- Language.PureScript.Optimizer: optimize :: Options -> JS -> JS
+ Language.PureScript.Optimizer: optimize :: Options mode -> JS -> JS
- Language.PureScript.Optimizer.MagicDo: magicDo :: Options -> JS -> JS
+ Language.PureScript.Optimizer.MagicDo: magicDo :: Options mode -> JS -> JS
- Language.PureScript.Optimizer.TCO: tco :: Options -> JS -> JS
+ Language.PureScript.Optimizer.TCO: tco :: Options mode -> JS -> JS
- Language.PureScript.Options: Options :: Bool -> Bool -> Bool -> Bool -> Maybe String -> Bool -> Maybe String -> [String] -> [String] -> Bool -> Options
+ Language.PureScript.Options: Options :: Bool -> Bool -> Bool -> Bool -> Maybe String -> Bool -> Bool -> ModeOptions mode -> Options mode
- Language.PureScript.Options: data Options
+ Language.PureScript.Options: data Options mode
- Language.PureScript.Options: optionsMain :: Options -> Maybe String
+ Language.PureScript.Options: optionsMain :: Options mode -> Maybe String
- Language.PureScript.Options: optionsNoMagicDo :: Options -> Bool
+ Language.PureScript.Options: optionsNoMagicDo :: Options mode -> Bool
- Language.PureScript.Options: optionsNoOptimizations :: Options -> Bool
+ Language.PureScript.Options: optionsNoOptimizations :: Options mode -> Bool
- Language.PureScript.Options: optionsNoPrelude :: Options -> Bool
+ Language.PureScript.Options: optionsNoPrelude :: Options mode -> Bool
- Language.PureScript.Options: optionsNoTco :: Options -> Bool
+ Language.PureScript.Options: optionsNoTco :: Options mode -> Bool
- Language.PureScript.Options: optionsPerformRuntimeTypeChecks :: Options -> Bool
+ Language.PureScript.Options: optionsPerformRuntimeTypeChecks :: Options mode -> Bool
- Language.PureScript.Options: optionsVerboseErrors :: Options -> Bool
+ Language.PureScript.Options: optionsVerboseErrors :: Options mode -> Bool
- Language.PureScript.TypeChecker: typeCheckAll :: Maybe ModuleName -> ModuleName -> [Declaration] -> Check [Declaration]
+ Language.PureScript.TypeChecker: typeCheckAll :: Maybe ModuleName -> ModuleName -> Maybe [DeclarationRef] -> [Declaration] -> Check [Declaration]
- Language.PureScript.TypeChecker.Monad: runCheck :: Options -> Check a -> Either String (a, Environment)
+ Language.PureScript.TypeChecker.Monad: runCheck :: Options mode -> Check a -> Either String (a, Environment)
- Language.PureScript.TypeChecker.Monad: runCheck' :: Options -> Environment -> Check a -> Either String (a, Environment)
+ Language.PureScript.TypeChecker.Monad: runCheck' :: Options mode -> Environment -> Check a -> Either String (a, Environment)
- Language.PureScript.TypeClassDictionaries: TypeClassDictionaryInScope :: Qualified Ident -> Qualified ProperName -> [Type] -> Maybe [(Qualified ProperName, [Type])] -> TypeClassDictionaryType -> TypeClassDictionaryInScope
+ Language.PureScript.TypeClassDictionaries: TypeClassDictionaryInScope :: Qualified Ident -> Qualified ProperName -> [Type] -> Maybe [(Qualified ProperName, [Type])] -> TypeClassDictionaryType -> Bool -> TypeClassDictionaryInScope

Files

docgen/Main.hs view
@@ -144,7 +144,8 @@   let exported = filter (isDctorExported name exps . fst) ctors   atIndent n $ show dtype ++ " " ++ typeName ++ (if null exported then "" else " where")   forM_ exported $ \(ctor, tys) ->-    atIndent (n + 2) $ P.runProperName ctor ++ " :: " ++ concatMap (\ty -> prettyPrintType' ty ++ " -> ") tys ++ typeName+    let ctorTy = foldr P.function (P.TypeConstructor (P.Qualified Nothing name)) tys+    in atIndent (n + 2) $ P.runProperName ctor ++ " :: " ++ prettyPrintType' ctorTy renderDeclaration n _ (P.ExternDataDeclaration name kind) =   atIndent n $ "data " ++ P.runProperName name ++ " :: " ++ P.prettyPrintKind kind renderDeclaration n _ (P.TypeSynonymDeclaration name args ty) = do
+ examples/failing/InstanceExport.purs view
@@ -0,0 +1,15 @@+module InstanceExport (S(..), f) where++newtype S = S String++class F a where+  f :: a -> String++instance fs :: F S where+  f (S s) = s++module Test where++import InstanceExport++test = f $ S "Test"
+ examples/failing/MultipleErrors.purs view
@@ -0,0 +1,9 @@+module MultipleErrors where++foo :: Number -> Number+foo 0 = "Test"+foo n = bar (n - 1)++bar :: Number -> Number+bar 0 = "Test"+bar n = foo (n - 1)
+ examples/failing/OverlappingArguments.purs view
@@ -0,0 +1,3 @@+module OverlappingArguments where++f x x = x
+ examples/failing/OverlappingBinders.purs view
@@ -0,0 +1,4 @@+module OverlappingBinders where++f x = case x of+  (y:y@(z:zs)) -> y
+ examples/passing/BlockString.purs view
@@ -0,0 +1,12 @@+module Main where++foreign import foo """+  function foo(s) {+    return s;+  }+""" :: String -> String++bar :: String -> String+bar _ = foo "test"++main = Debug.Trace.trace "Done"
+ examples/passing/IfThenElseMaybe.purs view
@@ -0,0 +1,9 @@+module Main where++data Maybe a = Nothing | Just a++test1 = if true then Just 10 else Nothing++test2 = if true then Nothing else Just 10++main = Debug.Trace.trace "Done"
prelude/prelude.purs view
@@ -66,7 +66,7 @@    foreign import cons     "function cons(e) {\-    \  return function (l) {\+    \  return function(l) {\     \    return [e].concat(l);\     \  };\     \}" :: forall a. a -> [a] -> [a]@@ -97,8 +97,8 @@     show = showNumberImpl    foreign import showArrayImpl-    "function showArrayImpl (f) {\-    \  return function (xs) {\+    "function showArrayImpl(f) {\+    \  return function(xs) {\     \    var ss = [];\     \    for (var i = 0, l = xs.length; i < l; i++) {\     \      ss[i] = f(xs[i]);\@@ -327,10 +327,10 @@    foreign import unsafeCompareImpl     "function unsafeCompareImpl(lt) {\-    \  return function (eq) {\-    \    return function (gt) {\-    \      return function (x) {\-    \        return function (y) {\+    \  return function(eq) {\+    \    return function(gt) {\+    \      return function(x) {\+    \        return function(y) {\     \          return x < y ? lt : x > y ? gt : eq;\     \        };\     \      };\@@ -803,7 +803,7 @@    foreign import untilE "function untilE(f) {\                         \  return function() {\-                        \    while (!f()) { }\+                        \    while (!f());\                         \    return {};\                         \  };\                         \}" :: forall e. Eff e Boolean -> Eff e Unit@@ -878,7 +878,7 @@   foreign import data STArray :: * -> * -> *    foreign import newSTRef "function newSTRef(val) {\-                          \  return function () {\+                          \  return function() {\                           \    return { value: val };\                           \  };\                           \}" :: forall a h r. a -> Eff (st :: ST h | r) (STRef h a)
psc-make/Main.hs view
@@ -12,7 +12,7 @@ -- ----------------------------------------------------------------------------- -{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving #-}  module Main where @@ -66,7 +66,7 @@   liftError = either throwError return   progress = makeIO . U.putStrLn -compile :: FilePath -> [FilePath] -> FilePath -> P.Options -> Bool -> IO ()+compile :: FilePath -> [FilePath] -> FilePath -> P.Options P.Make -> Bool -> IO () compile prelude input outputDir opts usePrefix = do   modules <- readInput allInputFiles   case modules of@@ -81,7 +81,7 @@           exitFailure         Right _ -> do           exitSuccess-  where +  where     prefix = if usePrefix                then ["Generated by psc-make version " ++ showVersion Paths.version]                else []@@ -124,8 +124,8 @@ verboseErrors = value $ flag $ (optInfo [ "v", "verbose-errors" ])      { optDoc = "Display verbose error messages" } -options :: Term P.Options-options = P.Options <$> noPrelude <*> noTco <*> performRuntimeTypeChecks <*> noMagicDo <*> pure Nothing <*> noOpts <*> pure Nothing <*> pure [] <*> pure [] <*> verboseErrors+options :: Term (P.Options P.Make)+options = P.Options <$> noPrelude <*> noTco <*> performRuntimeTypeChecks <*> noMagicDo <*> pure Nothing <*> noOpts <*> verboseErrors <*> pure P.MakeOptions  noPrefix :: Term Bool noPrefix = value $ flag $ (optInfo ["p", "no-prefix" ])@@ -145,3 +145,4 @@ main = do   prelude <- P.preludeFilename   run (term prelude, termInfo)+
psc/Main.hs view
@@ -12,7 +12,7 @@ -- ----------------------------------------------------------------------------- -{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DataKinds, GeneralizedNewtypeDeriving #-}  module Main where @@ -44,7 +44,7 @@   collect :: [(FilePath, Either ParseError [P.Module])] -> Either ParseError [(FilePath, P.Module)]   collect = fmap concat . sequence . map (\(fp, e) -> fmap (map ((,) fp)) e) -compile :: FilePath -> P.Options -> Bool -> [FilePath] -> Maybe FilePath -> Maybe FilePath -> Bool -> IO ()+compile :: FilePath -> P.Options P.Compile -> Bool -> [FilePath] -> Maybe FilePath -> Maybe FilePath -> Bool -> IO () compile prelude opts stdin input output externs usePrefix = do   modules <- readInput stdInOrInputFiles   case modules of@@ -70,7 +70,7 @@                     | P.optionsNoPrelude opts = Just input                     | otherwise = Just $ prelude : input   prefix = if usePrefix-              then ["Generated by psc version " ++ showVersion Paths.version]                    +              then ["Generated by psc version " ++ showVersion Paths.version]               else []  mkdirp :: FilePath -> IO ()@@ -136,8 +136,10 @@ noPrefix = value $ flag $ (optInfo ["no-prefix" ])      { optDoc = "Do not include comment header"} -options :: Term P.Options-options = P.Options <$> noPrelude <*> noTco <*> performRuntimeTypeChecks <*> noMagicDo <*> runMain <*> noOpts <*> (Just <$> browserNamespace) <*> dceModules <*> codeGenModules <*> verboseErrors+options :: Term (P.Options P.Compile)+options = P.Options <$> noPrelude <*> noTco <*> performRuntimeTypeChecks <*> noMagicDo <*> runMain <*> noOpts <*> verboseErrors <*> additionalOptions+  where+  additionalOptions = P.CompileOptions <$> browserNamespace <*> dceModules <*> codeGenModules  term :: FilePath -> Term (IO ()) term prelude = compile prelude <$> options <*> useStdIn <*> inputFiles <*> outputFile <*> externsFile <*> (not <$> noPrefix)@@ -153,4 +155,5 @@ main = do   prelude <- P.preludeFilename   run (term prelude, termInfo)+ 
psci/Main.hs view
@@ -13,7 +13,7 @@ -- ----------------------------------------------------------------------------- -{-# LANGUAGE DoAndIfThenElse, FlexibleContexts, GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DataKinds, DoAndIfThenElse, FlexibleContexts, GeneralizedNewtypeDeriving #-}  module Main where @@ -198,8 +198,8 @@  -- | Compilation options. ---options :: P.Options-options = P.Options False True False True Nothing True Nothing [] [] False+options :: P.Options P.Make+options = P.Options False False False False Nothing False False P.MakeOptions  -- | -- PSCI monad@@ -276,7 +276,7 @@ handleDeclaration value = do   st <- PSCI $ lift get   let m = createTemporaryModule True st value-  e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [("$PSCI.purs", m)]) [] +  e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [("$PSCI.purs", m)]) []   case e of     Left err -> PSCI $ outputStrLn err     Right _ -> do@@ -295,7 +295,7 @@ handleTypeOf value = do   st <- PSCI $ lift get   let m = createTemporaryModule False st value-  e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [("$PSCI.purs", m)]) [] +  e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [("$PSCI.purs", m)]) []   case e of     Left err -> PSCI $ outputStrLn err     Right env' ->@@ -311,7 +311,7 @@   st <- PSCI $ lift get   let m = createTemporaryModuleForKind st typ       mName = P.ModuleName [P.ProperName "$PSCI"]-  e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [("$PSCI.purs", m)]) [] +  e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [("$PSCI.purs", m)]) []   case e of     Left err -> PSCI $ outputStrLn err     Right env' ->@@ -329,13 +329,13 @@ -- | -- Parses the input and returns either a Metacommand or an expression. ---getCommand :: InputT (StateT PSCiState IO) (Either ParseError (Maybe Command))-getCommand = do+getCommand :: Bool -> InputT (StateT PSCiState IO) (Either ParseError (Maybe Command))+getCommand singleLineMode = do   firstLine <- getInputLine "> "   case firstLine of     Nothing -> return (Right Nothing)     Just "" -> return (Right Nothing)-    Just s@ (':' : _) -> return . either Left (Right . Just) $ parseCommand s -- The start of a command+    Just s | singleLineMode || head s == ':' -> return . either Left (Right . Just) $ parseCommand s     Just s -> either Left (Right . Just) . parseCommand <$> go [s]   where     go :: [String] -> InputT (StateT PSCiState IO) String@@ -371,9 +371,16 @@ handleCommand (KindOf typ) = handleKindOf typ handleCommand _ = PSCI $ outputStrLn "Unknown command" +singleLineFlag :: Cmd.Term Bool+singleLineFlag = Cmd.value $ Cmd.flag $ (Cmd.optInfo ["single-line-mode"])+                                                { Cmd.optName = "Single-line mode"+                                                , Cmd.optDoc = "Run in single-line mode"+                                                }+ inputFiles :: Cmd.Term [FilePath] inputFiles = Cmd.value $ Cmd.posAny [] $ Cmd.posInfo { Cmd.posName = "file(s)"-                                                     , Cmd.posDoc = "Optional .purs files to load on start" }+                                                     , Cmd.posDoc = "Optional .purs files to load on start"+                                                     }  loadUserConfig :: IO (Maybe [Command]) loadUserConfig = do@@ -391,8 +398,8 @@ -- | -- The PSCI main loop. ---loop :: [FilePath] -> IO ()-loop files = do+loop :: Bool -> [FilePath] -> IO ()+loop singleLineMode files = do   config <- loadUserConfig   preludeFilename <- P.preludeFilename   filesAndModules <- mapM (\file -> fmap (fmap (map ((,) file))) . loadModule $ file) (preludeFilename : files)@@ -409,7 +416,7 @@       where         go :: InputT (StateT PSCiState IO) ()         go = do-          c <- getCommand+          c <- getCommand singleLineMode           case c of             Left err -> outputStrLn (show err) >> go             Right Nothing -> go@@ -417,7 +424,7 @@             Right (Just c') -> runPSCI (handleCommand c') >> go  term :: Cmd.Term (IO ())-term = loop <$> inputFiles+term = loop <$> singleLineFlag <*> inputFiles  termInfo :: Cmd.TermInfo termInfo = Cmd.defTI@@ -428,3 +435,4 @@  main :: IO () main = Cmd.run (term, termInfo)+
purescript.cabal view
@@ -1,5 +1,5 @@ name: purescript-version: 0.5.5+version: 0.5.6 cabal-version: >=1.8 build-type: Custom license: MIT
src/Language/PureScript.hs view
@@ -13,6 +13,8 @@ -- ----------------------------------------------------------------------------- +{-# LANGUAGE DataKinds #-}+ module Language.PureScript (module P, compile, compile', MonadMake(..), make, preludeFilename) where  import Language.PureScript.Types as P@@ -39,15 +41,18 @@ import Data.List (find, sortBy, groupBy, intercalate) import Data.Time.Clock import Data.Function (on)-import Data.Maybe (fromJust, fromMaybe)+import Data.Maybe (listToMaybe, fromMaybe) import Control.Monad.Error import Control.Monad.State.Lazy import Control.Arrow ((&&&)) import Control.Applicative import qualified Data.Map as M import qualified Data.Set as S-import System.FilePath (pathSeparator) +import System.FilePath ((</>), pathSeparator)+import System.Directory (getHomeDirectory, doesFileExist)+import System.Environment.XDG.BaseDir (getUserConfigDir)+ -- | -- Compile a collection of modules --@@ -67,21 +72,21 @@ -- --  * Pretty-print the generated Javascript ---compile :: Options -> [Module] -> [String] -> Either String (String, String, Environment)+compile :: Options Compile -> [Module] -> [String] -> Either String (String, String, Environment) compile = compile' initEnvironment -compile' :: Environment -> Options -> [Module] -> [String] -> Either String (String, String, Environment)+compile' :: Environment -> Options Compile -> [Module] -> [String] -> Either String (String, String, Environment) compile' env opts ms prefix = do   (sorted, _) <- sortModules $ map importPrim $ if optionsNoPrelude opts then ms else (map importPrelude ms)   (desugared, nextVar) <- stringifyErrorStack True $ runSupplyT 0 $ desugar sorted   (elaborated, env') <- runCheck' opts env $ forM desugared $ typeCheckModule mainModuleIdent   regrouped <- stringifyErrorStack True $ createBindingGroupsModule . collapseBindingGroupsModule $ elaborated-  let entryPoints = moduleNameFromString `map` optionsModules opts+  let entryPoints = moduleNameFromString `map` entryPointModules (optionsAdditional opts)   let elim = if null entryPoints then regrouped else eliminateDeadCode entryPoints regrouped   let renamed = renameInModules elim-  let codeGenModules = moduleNameFromString `map` optionsCodeGenModules opts-  let modulesToCodeGen = if null codeGenModules then renamed else filter (\(Module mn _ _) -> mn `elem` codeGenModules) renamed-  let js = evalSupply nextVar $ concat <$> mapM (\m -> moduleToJs Globals opts m env') modulesToCodeGen+  let codeGenModuleNames = moduleNameFromString `map` codeGenModules (optionsAdditional opts)+  let modulesToCodeGen = if null codeGenModuleNames then renamed else filter (\(Module mn _ _) -> mn `elem` codeGenModuleNames) renamed+  let js = evalSupply nextVar $ concat <$> mapM (\m -> moduleToJs opts m env') modulesToCodeGen   let exts = intercalate "\n" . map (`moduleToPs` env') $ modulesToCodeGen   js' <- generateMain env' opts js   let pjs = unlines $ map ("// " ++) prefix ++ [prettyPrintJS js']@@ -92,7 +97,7 @@ typeCheckModule :: Maybe ModuleName -> Module -> Check Module typeCheckModule mainModuleName (Module mn decls exps) = do   modify (\s -> s { checkCurrentModule = Just mn })-  decls' <- typeCheckAll mainModuleName mn decls+  decls' <- typeCheckAll mainModuleName mn exps decls   mapM_ checkTypesAreExported exps'   return $ Module mn decls' exps   where@@ -126,13 +131,13 @@     go _ = True  -generateMain :: Environment -> Options -> [JS] -> Either String [JS]+generateMain :: Environment -> Options Compile -> [JS] -> Either String [JS] generateMain env opts js =   case moduleNameFromString <$> optionsMain opts of     Just mmi -> do       when ((mmi, Ident C.main) `M.notMember` names env) $         Left $ show mmi ++ "." ++ C.main ++ " is undefined"-      return $ js ++ [JSApp (JSAccessor C.main (JSAccessor (moduleNameToJs mmi) (JSVar (fromJust (optionsBrowserNamespace opts))))) []]+      return $ js ++ [JSApp (JSAccessor C.main (JSAccessor (moduleNameToJs mmi) (JSVar (browserNamespace (optionsAdditional opts))))) []]     _ -> return js  -- |@@ -170,7 +175,7 @@ -- If timestamps have not changed, the externs file can be used to provide the module's types without -- having to typecheck the module again. ---make :: (Functor m, Applicative m, Monad m, MonadMake m) => FilePath -> Options -> [(FilePath, Module)] -> [String] -> m Environment+make :: (Functor m, Applicative m, Monad m, MonadMake m) => FilePath -> Options Make -> [(FilePath, Module)] -> [String] -> m Environment make outputDir opts ms prefix = do   let filePathMap = M.fromList (map (\(fp, Module mn _ _) -> (mn, fp)) ms) @@ -216,9 +221,9 @@     regrouped <- lift . liftError . stringifyErrorStack True . createBindingGroups moduleName' . collapseBindingGroups $ elaborated      let mod' = Module moduleName' regrouped exps-    let [renamed] = renameInModules [mod'] +    let [renamed] = renameInModules [mod'] -    pjs <- prettyPrintJS <$> moduleToJs CommonJS opts renamed env'+    pjs <- prettyPrintJS <$> moduleToJs opts renamed env'     let js = unlines $ map ("// " ++) prefix ++ [pjs]     let exts = unlines $ map ("-- " ++ ) prefix ++ [moduleToPs renamed env'] @@ -266,4 +271,22 @@ importPrelude = addDefaultImport (ModuleName [ProperName C.prelude])  preludeFilename :: IO FilePath-preludeFilename = Paths.getDataFileName "prelude/prelude.purs"+preludeFilename = fromMaybe missingPrelude . listToMaybe <$> do+  fs <- sequence [xdsPrelude, homePrelude, cabalPrelude]+  filterM doesFileExist fs+  where+  missingPrelude :: FilePath+  missingPrelude = error "No Prelude found in user home, XDS user config directory or cabal path."++  xdsPrelude :: IO FilePath+  xdsPrelude = do+    configDir <- getUserConfigDir "purescript"+    return $ configDir </> "prelude" </> "prelude.purs"++  homePrelude :: IO FilePath+  homePrelude = do+    homeDir <- getHomeDirectory+    return $ homeDir </> ".purescript" </> "prelude" </> "prelude.purs"++  cabalPrelude :: IO FilePath+  cabalPrelude = Paths.getDataFileName "prelude/prelude.purs"
src/Language/PureScript/CodeGen/JS.hs view
@@ -13,17 +13,16 @@ -- ----------------------------------------------------------------------------- -{-# LANGUAGE DoAndIfThenElse #-}+{-# LANGUAGE GADTs, DoAndIfThenElse #-}  module Language.PureScript.CodeGen.JS (     module AST,-    ModuleType(..),     declToJs,     moduleToJs,     identNeedsEscaping ) where -import Data.Maybe (catMaybes, fromJust)+import Data.Maybe (catMaybes) import Data.Function (on) import Data.List (nub, (\\), delete, sortBy) @@ -43,39 +42,35 @@ import qualified Language.PureScript.Constants as C  -- |--- Different types of modules which are supported----data ModuleType = CommonJS | Globals---- | -- Generate code in the simplified Javascript intermediate representation for all declarations in a -- module. ---moduleToJs :: (Functor m, Applicative m, Monad m) => ModuleType -> Options -> Module -> Environment -> SupplyT m [JS]-moduleToJs mt opts (Module name decls (Just exps)) env = do-  let jsImports = map (importToJs mt opts) . delete (ModuleName [ProperName C.prim]) . (\\ [name]) . nub $ concatMap imports decls+moduleToJs :: (Functor m, Applicative m, Monad m) => Options mode -> Module -> Environment -> SupplyT m [JS]+moduleToJs opts (Module name decls (Just exps)) env = do+  let jsImports = map (importToJs opts) . delete (ModuleName [ProperName C.prim]) . (\\ [name]) . nub $ concatMap imports decls   jsDecls <- mapM (\decl -> declToJs opts name decl env) decls   let optimized = concat $ map (map $ optimize opts) $ catMaybes jsDecls   let isModuleEmpty = null exps   let moduleBody = JSStringLiteral "use strict" : jsImports ++ optimized   let moduleExports = JSObjectLiteral $ concatMap exportToJs exps-  return $ case mt of-    CommonJS -> moduleBody ++ [JSAssignment (JSAccessor "exports" (JSVar "module")) moduleExports]-    Globals | not isModuleEmpty ->-      [ JSVariableIntroduction (fromJust (optionsBrowserNamespace opts))-                               (Just (JSBinary Or (JSVar (fromJust (optionsBrowserNamespace opts))) (JSObjectLiteral [])) )-      , JSAssignment (JSAccessor (moduleNameToJs name) (JSVar (fromJust (optionsBrowserNamespace opts))))+  return $ case optionsAdditional opts of+    MakeOptions -> moduleBody ++ [JSAssignment (JSAccessor "exports" (JSVar "module")) moduleExports]+    CompileOptions ns _ _ | not isModuleEmpty ->+      [ JSVariableIntroduction ns+                               (Just (JSBinary Or (JSVar ns) (JSObjectLiteral [])) )+      , JSAssignment (JSAccessor (moduleNameToJs name) (JSVar ns))                      (JSApp (JSFunction Nothing [] (JSBlock (moduleBody ++ [JSReturn moduleExports]))) [])       ]     _ -> []-moduleToJs _ _ _ _ = error "Exports should have been elaborated in name desugaring"+moduleToJs _ _ _ = error "Exports should have been elaborated in name desugaring" -importToJs :: ModuleType -> Options -> ModuleName -> JS-importToJs mt opts mn = JSVariableIntroduction (moduleNameToJs mn) (Just moduleBody)+importToJs :: Options mode -> ModuleName -> JS+importToJs opts mn =+  JSVariableIntroduction (moduleNameToJs mn) (Just moduleBody)   where-  moduleBody = case mt of-    CommonJS -> JSApp (JSVar "require") [JSStringLiteral (runModuleName mn)]-    Globals -> JSAccessor (moduleNameToJs mn) (JSVar (fromJust (optionsBrowserNamespace opts)))+  moduleBody = case optionsAdditional opts of+    MakeOptions -> JSApp (JSVar "require") [JSStringLiteral (runModuleName mn)]+    CompileOptions ns _ _ -> JSAccessor (moduleNameToJs mn) (JSVar ns)  imports :: Declaration -> [ModuleName] imports (ImportDeclaration mn _ _) = [mn]@@ -95,7 +90,7 @@ -- | -- Generate code in the simplified Javascript intermediate representation for a declaration ---declToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Declaration -> Environment -> SupplyT m (Maybe [JS])+declToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Declaration -> Environment -> SupplyT m (Maybe [JS]) declToJs opts mp (ValueDeclaration ident _ _ _ val) e = do   js <- valueToJs opts mp e val   return $ Just [JSVariableIntroduction (identToJs ident) (Just js)]@@ -190,7 +185,7 @@ -- | -- Generate code in the simplified Javascript intermediate representation for a value or expression. ---valueToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Environment -> Expr -> SupplyT m JS+valueToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Environment -> Expr -> SupplyT m JS valueToJs _ _ _ (NumericLiteral n) = return $ JSNumericLiteral n valueToJs _ _ _ (StringLiteral s) = return $ JSStringLiteral s valueToJs _ _ _ (BooleanLiteral b) = return $ JSBooleanLiteral b@@ -315,7 +310,7 @@ -- Generate code in the simplified Javascript intermediate representation for pattern match binders -- and guards. ---bindersToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Environment -> [CaseAlternative] -> [JS] -> SupplyT m JS+bindersToJs :: (Functor m, Applicative m, Monad m) => Options mode -> ModuleName -> Environment -> [CaseAlternative] -> [JS] -> SupplyT m JS bindersToJs opts m e binders vals = do   valNames <- replicateM (length vals) freshName   let assignments = zipWith JSVariableIntroduction valNames (map Just vals)@@ -405,7 +400,7 @@     ( JSVariableIntroduction tailVar (Just (JSApp (JSAccessor "slice" (JSVar varName)) [JSNumericLiteral (Left numberOfHeadBinders)])) :       js2     )) Nothing]-  where +  where   uncons :: [Binder] -> Binder -> ([Binder], Binder)   uncons acc (ConsBinder h t) = uncons (h : acc) t   uncons acc (PositionedBinder _ b) = uncons acc b@@ -415,4 +410,5 @@   return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : js) binderToJs m e varName done (PositionedBinder _ binder) =   binderToJs m e varName done binder+ 
src/Language/PureScript/Errors.hs view
@@ -16,7 +16,7 @@  module Language.PureScript.Errors where -import Data.List (intercalate)+import Data.List (intersperse, intercalate) import Data.Monoid  import Control.Monad.Error@@ -41,26 +41,36 @@ -- | -- Compilation errors ---data CompileError = CompileError {-    -- |-    -- Error message-    ---    compileErrorMessage :: String-    -- |-    -- The value where the error occurred-    ---  , compileErrorValue :: Maybe ErrorSource-    -- |-    -- Optional source position information-    ---  , compileErrorPosition :: Maybe SourcePos-  } deriving (Show)+data CompileError+  = CompileError+      { -- |+        -- Error message+        --+        compileErrorMessage :: String+        -- |+        -- The value where the error occurred+        --+      , compileErrorValue :: Maybe ErrorSource+        -- |+        -- Optional source position information+        --+      , compileErrorPosition :: Maybe SourcePos+      }+  deriving (Show)  -- | -- A stack trace for an error ---newtype ErrorStack = ErrorStack { runErrorStack :: [CompileError] } deriving (Show, Monoid)+data ErrorStack+  = ErrorStack { runErrorStack :: [CompileError] }+  | MultipleErrors [ErrorStack] deriving (Show) +instance Monoid ErrorStack where+  mempty = ErrorStack []+  mappend (ErrorStack xs) (ErrorStack ys) = ErrorStack (xs ++ ys)+  mappend (MultipleErrors es) x = MultipleErrors [ e <> x | e <- es ]+  mappend x (MultipleErrors es) = MultipleErrors [ x <> e | e <- es ]+ instance Error ErrorStack where   strMsg s = ErrorStack [CompileError s Nothing Nothing]   noMsg = ErrorStack []@@ -80,6 +90,8 @@       in case length es' of         1 -> showError (head es')         _ -> showError (head es') ++ "\n" ++ showError (last es')+prettyPrintErrorStack printFullStack (MultipleErrors es) =+  unlines $ intersperse "" $ "Multiple errors:" : map (prettyPrintErrorStack printFullStack) es  stringifyErrorStack :: Bool -> Either ErrorStack a -> Either String a stringifyErrorStack printFullStack = either (Left . prettyPrintErrorStack printFullStack) Right
src/Language/PureScript/Optimizer.hs view
@@ -49,7 +49,7 @@ -- | -- Apply a series of optimizer passes to simplified Javascript code ---optimize :: Options -> JS -> JS+optimize :: Options mode -> JS -> JS optimize opts | optionsNoOptimizations opts = id               | otherwise = untilFixedPoint (applyAll   [ collapseNestedBlocks
src/Language/PureScript/Optimizer/MagicDo.hs view
@@ -28,7 +28,7 @@  import qualified Language.PureScript.Constants as C -magicDo :: Options -> JS -> JS+magicDo :: Options mode -> JS -> JS magicDo opts | optionsNoMagicDo opts = id              | otherwise = inlineST . magicDo' 
src/Language/PureScript/Optimizer/TCO.hs view
@@ -21,7 +21,7 @@ -- | -- Eliminate tail calls ---tco :: Options -> JS -> JS+tco :: Options mode -> JS -> JS tco opts | optionsNoTco opts = id          | otherwise = tco' 
src/Language/PureScript/Options.hs view
@@ -13,12 +13,37 @@ -- ----------------------------------------------------------------------------- +{-# LANGUAGE GADTs, DataKinds, StandaloneDeriving #-}+ module Language.PureScript.Options where  -- |+-- Indicates the mode of the compiler. Lifted using DataKinds to refine the Options type.+--+data Mode = Compile | Make++-- |+-- Per-mode options+--+data ModeOptions mode where+  CompileOptions :: String -> [String] -> [String] -> ModeOptions Compile+  MakeOptions :: ModeOptions Make++browserNamespace :: ModeOptions Compile -> String+browserNamespace (CompileOptions ns _ _) = ns++entryPointModules :: ModeOptions Compile -> [String]+entryPointModules (CompileOptions _ ms _) = ms++codeGenModules :: ModeOptions Compile -> [String]+codeGenModules (CompileOptions _ _ ms) = ms++deriving instance Show (ModeOptions mode)++-- | -- The data type of compiler options ---data Options = Options {+data Options mode = Options {     -- |     -- Disable inclusion of the built in Prelude     --@@ -45,27 +70,24 @@     --   , optionsNoOptimizations :: Bool     -- |-    -- Specify the namespace that PureScript modules will be exported to when running in the-    -- browser.-    ---  , optionsBrowserNamespace :: Maybe String-    -- |-    -- The modules to keep while enabling dead code elimination-    ---  , optionsModules :: [String]-    -- |-    -- The modules to code gen-    ---  , optionsCodeGenModules :: [String]-    -- |     -- Verbose error message     --   , optionsVerboseErrors :: Bool-+    -- |+    -- Specify the namespace that PureScript modules will be exported to when running in the+    -- browser.+    --+  , optionsAdditional :: ModeOptions mode   } deriving Show  -- | -- Default compiler options ---defaultOptions :: Options-defaultOptions = Options False False False False Nothing False Nothing [] [] False+defaultCompileOptions :: Options Compile+defaultCompileOptions = Options False False False False Nothing False False (CompileOptions "PS" [] [])++-- |+-- Default make options+--+defaultMakeOptions :: Options Make+defaultMakeOptions = Options False False False False Nothing False False MakeOptions
src/Language/PureScript/Parser/Common.hs view
@@ -155,7 +155,9 @@ -- Parse a string literal -- stringLiteral :: P.Parsec String u String-stringLiteral = PT.stringLiteral tokenParser+stringLiteral = lexeme blockString <|> PT.stringLiteral tokenParser+  where delimeter   = P.try (P.string "\"\"\"")+        blockString = delimeter >> P.manyTill P.anyChar delimeter  -- | -- Parse whitespace
src/Language/PureScript/Sugar/CaseDeclarations.hs view
@@ -20,7 +20,7 @@ ) where  import Data.Monoid ((<>))-import Data.List (groupBy)+import Data.List (nub, groupBy)  import Control.Applicative import Control.Monad ((<=<), forM, join, unless, replicateM)@@ -31,6 +31,7 @@ import Language.PureScript.Environment import Language.PureScript.Errors import Language.PureScript.Supply+import Language.PureScript.TypeChecker.Monad (guardWith)  -- | -- Replace all top-level binders in a module with case expressions.@@ -82,6 +83,7 @@ toDecls [ValueDeclaration ident nameKind bs Nothing val] | all isVarBinder bs = do   let args = map (\(VarBinder arg) -> arg) bs       body = foldr (Abs . Left) val args+  guardWith (strMsg "Overlapping function argument names") $ length (nub args) == length args   return [ValueDeclaration ident nameKind [] Nothing body] toDecls ds@(ValueDeclaration ident _ bs _ _ : _) = do   let tuples = map toTuple ds
src/Language/PureScript/Sugar/TypeClasses.hs view
@@ -151,36 +151,46 @@ --   }; -} desugarDecl :: ModuleName -> [DeclarationRef] -> Declaration -> Desugar (Maybe DeclarationRef, [Declaration])-desugarDecl mn _ d@(TypeClassDeclaration name args implies members) = do-  modify (M.insert (mn, name) d)-  return $ (Nothing, d : typeClassDictionaryDeclaration name args implies members : map (typeClassMemberToDictionaryAccessor mn name args) members)-desugarDecl mn exps d@(TypeInstanceDeclaration name deps className tys members) = do-  desugared <- lift $ desugarCases members-  dictDecl <- typeInstanceDictionaryDeclaration name mn deps className tys desugared-  let expRef = if isExportedClass className && all isExportedType (getConstructors `concatMap` tys)-               then Just $ TypeInstanceRef name-               else Nothing-  return $ (expRef, [d, dictDecl])+desugarDecl mn exps = go   where+  go d@(TypeClassDeclaration name args implies members) = do+    modify (M.insert (mn, name) d)+    return $ (Nothing, d : typeClassDictionaryDeclaration name args implies members : map (typeClassMemberToDictionaryAccessor mn name args) members)+  go d@(ExternInstanceDeclaration name _ className tys) = return (expRef name className tys, [d])+  go d@(TypeInstanceDeclaration name deps className tys members) = do+    desugared <- lift $ desugarCases members+    dictDecl <- typeInstanceDictionaryDeclaration name mn deps className tys desugared+    return $ (expRef name className tys, [d, dictDecl])+  go (PositionedDeclaration pos d) = do+    (dr, ds) <- rethrowWithPosition pos $ desugarDecl mn exps d+    return (dr, map (PositionedDeclaration pos) ds)+  go other = return (Nothing, [other])++  expRef :: Ident -> Qualified ProperName -> [Type] -> Maybe DeclarationRef+  expRef name className tys+    | isExportedClass className && all isExportedType (getConstructors `concatMap` tys) = Just $ TypeInstanceRef name+    | otherwise = Nothing+   isExportedClass :: Qualified ProperName -> Bool   isExportedClass = isExported (elem . TypeClassRef)+   isExportedType :: Qualified ProperName -> Bool   isExportedType = isExported $ \pn -> isJust . find (matchesTypeRef pn)+   isExported :: (ProperName -> [DeclarationRef] -> Bool) -> Qualified ProperName -> Bool   isExported test (Qualified (Just mn') pn) = mn /= mn' || test pn exps   isExported _ _ = error "Names should have been qualified in name desugaring"+   matchesTypeRef :: ProperName -> DeclarationRef -> Bool   matchesTypeRef pn (TypeRef pn' _) = pn == pn'   matchesTypeRef _ _ = False+   getConstructors :: Type -> [Qualified ProperName]   getConstructors = everythingOnTypes (++) getConstructor+   getConstructor :: Type -> [Qualified ProperName]   getConstructor (TypeConstructor tcname) = [tcname]   getConstructor _ = []-desugarDecl mn exps (PositionedDeclaration pos d) = do-  (dr, ds) <- rethrowWithPosition pos $ desugarDecl mn exps d-  return (dr, map (PositionedDeclaration pos) ds)-desugarDecl _ _ other = return (Nothing, [other])  memberToNameAndType :: Declaration -> (Ident, Type) memberToNameAndType (TypeDeclaration ident ty) = (ident, ty)@@ -275,3 +285,5 @@   typeInstanceDictionaryEntryValue (ValueDeclaration _ _ [] _ val) = val   typeInstanceDictionaryEntryValue (PositionedDeclaration pos d) = PositionedValue pos (typeInstanceDictionaryEntryValue d)   typeInstanceDictionaryEntryValue _ = error "Invalid declaration in type instance definition"++
src/Language/PureScript/TypeChecker.hs view
@@ -119,112 +119,128 @@ -- --  * Process module imports ---typeCheckAll :: Maybe ModuleName -> ModuleName -> [Declaration] -> Check [Declaration]-typeCheckAll _ _ [] = return []-typeCheckAll mainModuleName moduleName (d@(DataDeclaration dtype name args dctors) : rest) = do-  rethrow (strMsg ("Error in type constructor " ++ show name) <>) $ do-    when (dtype == Newtype) $ checkNewtype dctors-    checkDuplicateTypeArguments args-    ctorKind <- kindsOf True moduleName name args (concatMap snd dctors)-    addDataType moduleName dtype name args dctors ctorKind-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds+typeCheckAll :: Maybe ModuleName -> ModuleName -> Maybe [DeclarationRef] -> [Declaration] -> Check [Declaration]+typeCheckAll mainModuleName moduleName exps = go   where-  checkNewtype :: [(ProperName, [Type])] -> Check ()-  checkNewtype [(_, [_])] = return ()-  checkNewtype [(_, _)] = throwError . strMsg $ "newtypes constructors must have a single argument"-  checkNewtype _ = throwError . strMsg $ "newtypes must have a single constructor"-typeCheckAll mainModuleName moduleName (d@(DataBindingGroupDeclaration tys) : rest) = do-  rethrow (strMsg "Error in data binding group" <>) $ do-    let syns = mapMaybe toTypeSynonym tys-    let dataDecls = mapMaybe toDataDecl tys-    (syn_ks, data_ks) <- kindsOfAll moduleName syns (map (\(_, name, args, dctors) -> (name, args, concatMap snd dctors)) dataDecls)-    forM_ (zip dataDecls data_ks) $ \((dtype, name, args, dctors), ctorKind) -> do+  go :: [Declaration] -> Check [Declaration]+  go [] = return []+  go (d@(DataDeclaration dtype name args dctors) : rest) = do+    rethrow (strMsg ("Error in type constructor " ++ show name) <>) $ do+      when (dtype == Newtype) $ checkNewtype dctors       checkDuplicateTypeArguments args+      ctorKind <- kindsOf True moduleName name args (concatMap snd dctors)       addDataType moduleName dtype name args dctors ctorKind-    forM_ (zip syns syn_ks) $ \((name, args, ty), kind) -> do+    ds <- go rest+    return $ d : ds+    where+    checkNewtype :: [(ProperName, [Type])] -> Check ()+    checkNewtype [(_, [_])] = return ()+    checkNewtype [(_, _)] = throwError . strMsg $ "newtypes constructors must have a single argument"+    checkNewtype _ = throwError . strMsg $ "newtypes must have a single constructor"+  go (d@(DataBindingGroupDeclaration tys) : rest) = do+    rethrow (strMsg "Error in data binding group" <>) $ do+      let syns = mapMaybe toTypeSynonym tys+      let dataDecls = mapMaybe toDataDecl tys+      (syn_ks, data_ks) <- kindsOfAll moduleName syns (map (\(_, name, args, dctors) -> (name, args, concatMap snd dctors)) dataDecls)+      forM_ (zip dataDecls data_ks) $ \((dtype, name, args, dctors), ctorKind) -> do+        checkDuplicateTypeArguments args+        addDataType moduleName dtype name args dctors ctorKind+      forM_ (zip syns syn_ks) $ \((name, args, ty), kind) -> do+        checkDuplicateTypeArguments args+        addTypeSynonym moduleName name args ty kind+    ds <- go rest+    return $ d : ds+    where+    toTypeSynonym (TypeSynonymDeclaration nm args ty) = Just (nm, args, ty)+    toTypeSynonym (PositionedDeclaration _ d') = toTypeSynonym d'+    toTypeSynonym _ = Nothing+    toDataDecl (DataDeclaration dtype nm args dctors) = Just (dtype, nm, args, dctors)+    toDataDecl (PositionedDeclaration _ d') = toDataDecl d'+    toDataDecl _ = Nothing+  go (d@(TypeSynonymDeclaration name args ty) : rest) = do+    rethrow (strMsg ("Error in type synonym " ++ show name) <>) $ do       checkDuplicateTypeArguments args+      kind <- kindsOf False moduleName name args [ty]       addTypeSynonym moduleName name args ty kind-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds-  where-  toTypeSynonym (TypeSynonymDeclaration nm args ty) = Just (nm, args, ty)-  toTypeSynonym (PositionedDeclaration _ d') = toTypeSynonym d'-  toTypeSynonym _ = Nothing-  toDataDecl (DataDeclaration dtype nm args dctors) = Just (dtype, nm, args, dctors)-  toDataDecl (PositionedDeclaration _ d') = toDataDecl d'-  toDataDecl _ = Nothing-typeCheckAll mainModuleName moduleName (d@(TypeSynonymDeclaration name args ty) : rest) = do-  rethrow (strMsg ("Error in type synonym " ++ show name) <>) $ do-    checkDuplicateTypeArguments args-    kind <- kindsOf False moduleName name args [ty]-    addTypeSynonym moduleName name args ty kind-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds-typeCheckAll _ _ (TypeDeclaration _ _ : _) = error "Type declarations should have been removed"-typeCheckAll mainModuleName moduleName (ValueDeclaration name nameKind [] Nothing val : rest) = do-  d <- rethrow (strMsg ("Error in declaration " ++ show name) <>) $ do-    valueIsNotDefined moduleName name-    [(_, (val', ty))] <- typesOf mainModuleName moduleName [(name, val)]-    addValue moduleName name ty nameKind-    return $ ValueDeclaration name nameKind [] Nothing val'-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds-typeCheckAll _ _ (ValueDeclaration{} : _) = error "Binders were not desugared"-typeCheckAll mainModuleName moduleName (BindingGroupDeclaration vals : rest) = do-  d <- rethrow (strMsg ("Error in binding group " ++ show (map (\(ident, _, _) -> ident) vals)) <>) $ do-    forM_ (map (\(ident, _, _) -> ident) vals) $ \name ->+    ds <- go rest+    return $ d : ds+  go (TypeDeclaration _ _ : _) = error "Type declarations should have been removed"+  go (ValueDeclaration name nameKind [] Nothing val : rest) = do+    d <- rethrow (strMsg ("Error in declaration " ++ show name) <>) $ do       valueIsNotDefined moduleName name-    tys <- typesOf mainModuleName moduleName $ map (\(ident, _, ty) -> (ident, ty)) vals-    vals' <- forM (zipWith (\(name, nameKind, _) (_, (val, ty)) -> (name, val, nameKind, ty)) vals tys) $ \(name, val, nameKind, ty) -> do+      [(_, (val', ty))] <- typesOf mainModuleName moduleName [(name, val)]       addValue moduleName name ty nameKind-      return (name, nameKind, val)-    return $ BindingGroupDeclaration vals'-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds-typeCheckAll mainModuleName moduleName (d@(ExternDataDeclaration name kind) : rest) = do-  env <- getEnv-  putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (kind, ExternData) (types env) }-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds-typeCheckAll mainModuleName moduleName (d@(ExternDeclaration importTy name _ ty) : rest) = do-  rethrow (strMsg ("Error in foreign import declaration " ++ show name) <>) $ do+      return $ ValueDeclaration name nameKind [] Nothing val'+    ds <- go rest+    return $ d : ds+  go (ValueDeclaration{} : _) = error "Binders were not desugared"+  go (BindingGroupDeclaration vals : rest) = do+    d <- rethrow (strMsg ("Error in binding group " ++ show (map (\(ident, _, _) -> ident) vals)) <>) $ do+      forM_ (map (\(ident, _, _) -> ident) vals) $ \name ->+        valueIsNotDefined moduleName name+      tys <- typesOf mainModuleName moduleName $ map (\(ident, _, ty) -> (ident, ty)) vals+      vals' <- forM (zipWith (\(name, nameKind, _) (_, (val, ty)) -> (name, val, nameKind, ty)) vals tys) $ \(name, val, nameKind, ty) -> do+        addValue moduleName name ty nameKind+        return (name, nameKind, val)+      return $ BindingGroupDeclaration vals'+    ds <- go rest+    return $ d : ds+  go (d@(ExternDataDeclaration name kind) : rest) = do     env <- getEnv-    kind <- kindOf moduleName ty-    guardWith (strMsg "Expected kind *") $ kind == Star-    case M.lookup (moduleName, name) (names env) of-      Just _ -> throwError . strMsg $ show name ++ " is already defined"-      Nothing -> putEnv (env { names = M.insert (moduleName, name) (ty, Extern importTy, Defined) (names env) })-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds-typeCheckAll mainModuleName moduleName (d@(FixityDeclaration _ name) : rest) = do-  ds <- typeCheckAll mainModuleName moduleName rest-  env <- getEnv-  guardWith (strMsg ("Fixity declaration with no binding: " ++ name)) $ M.member (moduleName, Op name) $ names env-  return $ d : ds-typeCheckAll mainModuleName currentModule (d@(ImportDeclaration moduleName _ _) : rest) = do-  tcds <- getTypeClassDictionaries-  let instances = filter (\tcd -> let Qualified (Just mn) _ = tcdName tcd in moduleName == mn) tcds-  addTypeClassDictionaries [ tcd { tcdName = Qualified (Just currentModule) ident, tcdType = TCDAlias (canonicalizeDictionary tcd) }-                           | tcd <- instances-                           , let (Qualified _ ident) = tcdName tcd-                           ]-  ds <- typeCheckAll mainModuleName currentModule rest-  return $ d : ds-typeCheckAll mainModuleName moduleName (d@(TypeClassDeclaration pn args implies tys) : rest) = do-  addTypeClass moduleName pn args implies tys-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds-typeCheckAll mainModuleName moduleName (TypeInstanceDeclaration dictName deps className tys _ : rest) = do-  typeCheckAll mainModuleName moduleName (ExternInstanceDeclaration dictName deps className tys : rest)-typeCheckAll mainModuleName moduleName (d@(ExternInstanceDeclaration dictName deps className tys) : rest) = do-  mapM_ (checkTypeClassInstance moduleName) tys-  forM_ deps $ mapM_ (checkTypeClassInstance moduleName) . snd-  addTypeClassDictionaries [TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) className tys (Just deps) TCDRegular]-  ds <- typeCheckAll mainModuleName moduleName rest-  return $ d : ds-typeCheckAll mainModuleName moduleName (PositionedDeclaration pos d : rest) =-  rethrowWithPosition pos $ do-    (d' : rest') <- typeCheckAll mainModuleName moduleName (d : rest)-    return (PositionedDeclaration pos d' : rest')+    putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (kind, ExternData) (types env) }+    ds <- go rest+    return $ d : ds+  go (d@(ExternDeclaration importTy name _ ty) : rest) = do+    rethrow (strMsg ("Error in foreign import declaration " ++ show name) <>) $ do+      env <- getEnv+      kind <- kindOf moduleName ty+      guardWith (strMsg "Expected kind *") $ kind == Star+      case M.lookup (moduleName, name) (names env) of+        Just _ -> throwError . strMsg $ show name ++ " is already defined"+        Nothing -> putEnv (env { names = M.insert (moduleName, name) (ty, Extern importTy, Defined) (names env) })+    ds <- go rest+    return $ d : ds+  go (d@(FixityDeclaration _ name) : rest) = do+    ds <- go rest+    env <- getEnv+    guardWith (strMsg ("Fixity declaration with no binding: " ++ name)) $ M.member (moduleName, Op name) $ names env+    return $ d : ds+  go (d@(ImportDeclaration importedModule _ _) : rest) = do+    tcds <- getTypeClassDictionaries+    let instances = filter (\tcd -> let Qualified (Just mn) _ = tcdName tcd in importedModule == mn) tcds+    addTypeClassDictionaries [ tcd { tcdName = Qualified (Just moduleName) ident, tcdType = TCDAlias (canonicalizeDictionary tcd) }+                             | tcd <- instances+                             , tcdExported tcd+                             , let (Qualified _ ident) = tcdName tcd+                             ]+    ds <- go rest+    return $ d : ds+  go (d@(TypeClassDeclaration pn args implies tys) : rest) = do+    addTypeClass moduleName pn args implies tys+    ds <- go rest+    return $ d : ds+  go (TypeInstanceDeclaration dictName deps className tys _ : rest) = do+    go (ExternInstanceDeclaration dictName deps className tys : rest)+  go (d@(ExternInstanceDeclaration dictName deps className tys) : rest) = do+    mapM_ (checkTypeClassInstance moduleName) tys+    forM_ deps $ mapM_ (checkTypeClassInstance moduleName) . snd+    addTypeClassDictionaries [TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) className tys (Just deps) TCDRegular isInstanceExported]+    ds <- go rest+    return $ d : ds+    where+    isInstanceExported :: Bool+    isInstanceExported = maybe True (any exportsInstance) exps +    +    exportsInstance :: DeclarationRef -> Bool+    exportsInstance (TypeInstanceRef name) | name == dictName = True+    exportsInstance (PositionedDeclarationRef _ r) = exportsInstance r+    exportsInstance _ = False+    +  go (PositionedDeclaration pos d : rest) =+    rethrowWithPosition pos $ do+      (d' : rest') <- go (d : rest)+      return (PositionedDeclaration pos d' : rest')+++ 
src/Language/PureScript/TypeChecker/Monad.hs view
@@ -28,6 +28,7 @@ import Language.PureScript.Errors  import Data.Maybe+import Data.Either (lefts, rights)  import Control.Applicative import Control.Monad.State@@ -190,13 +191,13 @@ -- | -- Run a computation in the Check monad, starting with an empty @Environment@ ---runCheck :: Options -> Check a -> Either String (a, Environment)+runCheck :: Options mode -> Check a -> Either String (a, Environment) runCheck opts = runCheck' opts initEnvironment  -- | -- Run a computation in the Check monad, failing with an error, or succeeding with a return value and the final @Environment@. ---runCheck' :: Options -> Environment -> Check a -> Either String (a, Environment)+runCheck' :: Options mode -> Environment -> Check a -> Either String (a, Environment) runCheck' opts env c = stringifyErrorStack (optionsVerboseErrors opts) $ do   (a, s) <- flip runStateT (CheckState env 0 0 Nothing) $ unCheck c   return (a, checkEnv s)@@ -232,4 +233,19 @@   (a, ust) <- runUnify (defaultUnifyState { unifyNextVar = checkNextVar st }) unify   modify $ \st' -> st' { checkNextVar = unifyNextVar ust }   return (a, unifyCurrentSubstitution ust)++-- |+-- Typecheck in parallel+--+parU :: [a] -> (a -> UnifyT t Check b) -> UnifyT t Check [b]+parU xs f = forM xs (withError . f) >>= collectErrors+  where+  withError :: UnifyT t Check a -> UnifyT t Check (Either ErrorStack a)+  withError u = catchError (Right <$> u) (return . Left)++  collectErrors :: [Either ErrorStack a] -> UnifyT t Check [a]+  collectErrors es = case lefts es of+    [err] -> throwError err+    [] -> return $ rights es+    errs -> throwError $ MultipleErrors errs 
src/Language/PureScript/TypeChecker/Types.hs view
@@ -42,10 +42,11 @@ -}  import Data.List-import Data.Maybe (maybeToList, isNothing, isJust, fromMaybe)+import Data.Maybe (maybeToList, fromMaybe) import Data.Function (on) import Data.Ord (comparing) import Data.Monoid+import Data.Either (lefts, rights)  import Language.PureScript.Declarations import Language.PureScript.Types@@ -171,14 +172,16 @@ typesOf :: Maybe ModuleName -> ModuleName -> [(Ident, Expr)] -> Check [(Ident, (Expr, Type))] typesOf mainModuleName moduleName vals = do   tys <- fmap tidyUp . liftUnify $ do-    (es, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName vals-    forM es $ \e -> do-      triple@(_, (_, ty)) <- typeForBindingGroupElement moduleName e dict untypedDict-      -- If --main is enabled, need to check that `main` has type Eff eff a for some eff, a-      when (Just moduleName == mainModuleName && fst e == Ident C.main) $ do-        [eff, a] <- replicateM 2 fresh-        ty =?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Control", ProperName "Monad", ProperName "Eff"])) (ProperName "Eff"))) eff) a+    (untyped, typed, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName vals+    ds1 <- parU typed $ \e -> do+      triple@(_, (_, ty)) <- checkTypedBindingGroupElement moduleName e dict+      checkMain (fst e) ty       return triple+    ds2 <- forM untyped $ \e -> do+      triple@(_, (_, ty)) <- typeForBindingGroupElement e dict untypedDict+      checkMain (fst e) ty+      return triple+    return $ ds1 ++ ds2    forM tys $ \(ident, (val, ty)) -> do     -- Replace type class dictionary placeholders with actual dictionaries@@ -193,17 +196,25 @@   where   -- Apply the substitution that was returned from runUnify to both types and (type-annotated) values   tidyUp (ts, sub) = map (\(i, (val, ty)) -> (i, (overTypes (sub $?) val, sub $? ty))) ts+  -- If --main is enabled, need to check that `main` has type Eff eff a for some eff, a+  checkMain nm ty = when (Just moduleName == mainModuleName && nm == Ident C.main) $ do+    [eff, a] <- replicateM 2 fresh+    ty =?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Control", ProperName "Monad", ProperName "Eff"])) (ProperName "Eff"))) eff) a -typeDictionaryForBindingGroup :: ModuleName -> [(Ident, Expr)] -> UnifyT Type Check ([(Ident, (Expr, Maybe (Type, Bool)))], M.Map (ModuleName, Ident) (Type, NameKind, NameVisibility), [(Ident, Type)])+type TypeData = M.Map (ModuleName, Ident) (Type, NameKind, NameVisibility)++type UntypedData = [(Ident, Type)]++typeDictionaryForBindingGroup :: ModuleName -> [(Ident, Expr)] -> UnifyT Type Check ([(Ident, Expr)], [(Ident, (Expr, Type, Bool))], TypeData, UntypedData) typeDictionaryForBindingGroup moduleName vals = do   let     -- Map each declaration to a name/value pair, with an optional type, if the declaration is typed     es = map isTyped vals     -- Filter the typed and untyped declarations-    typed = filter (isJust . snd . snd) es-    untyped = filter (isNothing . snd . snd) es+    untyped = lefts es+    typed = rights es     -- Make a map of names to typed declarations-    typedDict = map (\(ident, (_, Just (ty, _))) -> (ident, ty)) typed+    typedDict = map (\(ident, (_, ty, _)) -> (ident, ty)) typed    -- Create fresh unification variables for the types of untyped declarations   untypedNames <- replicateM (length untyped) fresh@@ -213,37 +224,33 @@     untypedDict = zip (map fst untyped) untypedNames     -- Create the dictionary of all name/type pairs, which will be added to the environment during type checking     dict = M.fromList (map (\(ident, ty) -> ((moduleName, ident), (ty, LocalVariable, Undefined))) $ typedDict ++ untypedDict)-  return (es, dict, untypedDict)+  return (untyped, typed, dict, untypedDict) -typeForBindingGroupElement :: ModuleName -> (Ident, (Expr, Maybe (Type, Bool))) -> M.Map (ModuleName, Ident) (Type, NameKind, NameVisibility) -> [(Ident, Type)] -> UnifyT Type Check (Ident, (Expr, Type))-typeForBindingGroupElement moduleName el dict untypedDict =-  -- If the declaration is a function, it has access to other values in the binding group.-  -- If not, the generated code might fail at runtime since those values might be undefined.-  case el of-    -- Typed declarations-    (ident, (val', Just (ty, checkType))) -> do-      -- Kind check-      kind <- liftCheck $ kindOf moduleName ty-      guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star-      -- Check the type with the new names in scope-      ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty-      val'' <- if checkType-               then bindNames dict $ TypedValue True <$> check val' ty' <*> pure ty'-               else return (TypedValue False val' ty')-      return (ident, (val'', ty'))-    -- Untyped declarations-    (ident, (val', Nothing)) -> do-      -- Infer the type with the new names in scope-      TypedValue _ val'' ty <- bindNames dict $ infer val'-      ty =?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)-      return (ident, (TypedValue True val'' ty, ty))+checkTypedBindingGroupElement :: ModuleName -> (Ident, (Expr, Type, Bool)) -> TypeData ->  UnifyT Type Check (Ident, (Expr, Type))+checkTypedBindingGroupElement moduleName (ident, (val', ty, checkType)) dict = do+  -- Kind check+  kind <- liftCheck $ kindOf moduleName ty+  guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star+  -- Check the type with the new names in scope+  ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty+  val'' <- if checkType+           then bindNames dict $ TypedValue True <$> check val' ty' <*> pure ty'+           else return (TypedValue False val' ty')+  return (ident, (val'', ty')) +typeForBindingGroupElement :: (Ident, Expr) -> TypeData -> UntypedData -> UnifyT Type Check (Ident, (Expr, Type))+typeForBindingGroupElement (ident, val) dict untypedDict = do+  -- Infer the type with the new names in scope+  TypedValue _ val' ty <- bindNames dict $ infer val+  ty =?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)+  return (ident, (TypedValue True val' ty, ty))+ -- | -- Check if a value contains a type annotation ---isTyped :: (Ident, Expr) -> (Ident, (Expr, Maybe (Type, Bool)))-isTyped (name, TypedValue checkType value ty) = (name, (value, Just (ty, checkType)))-isTyped (name, value) = (name, (value, Nothing))+isTyped :: (Ident, Expr) -> (Either (Ident, Expr) (Ident, (Expr, Type, Bool)))+isTyped (name, TypedValue checkType value ty) = Right (name, (value, ty, checkType))+isTyped (name, value) = Left (name, value)  -- | -- Map a function over type annotations appearing inside a value@@ -655,8 +662,8 @@   cond' <- check cond tyBoolean   v2@(TypedValue _ _ t2) <- infer th   v3@(TypedValue _ _ t3) <- infer el-  t2 =?= t3-  return $ TypedValue True (IfThenElse cond' v2 v3) t2+  (v2', v3', t) <- meet v2 v3 t2 t3+  return $ TypedValue True (IfThenElse cond' v2' v3') t infer' (Let ds val) = do   (ds', val'@(TypedValue _ _ valTy)) <- inferLetBinding [] ds val infer   return $ TypedValue True (Let ds' val') valTy@@ -692,10 +699,10 @@   bindNames (M.singleton (moduleName, ident) (valTy', nameKind, Defined)) $ inferLetBinding (seen ++ [ValueDeclaration ident nameKind [] Nothing val']) rest ret j inferLetBinding seen (BindingGroupDeclaration ds : rest) ret j = do   Just moduleName <- checkCurrentModule <$> get-  (es, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName (map (\(i, _, v) -> (i, v)) ds)-  ds' <- forM es $ \e -> do-    (ident, (val', _)) <- typeForBindingGroupElement moduleName e dict untypedDict-    return $ (ident, LocalVariable, val')+  (untyped, typed, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName (map (\(i, _, v) -> (i, v)) ds)+  ds1' <- parU typed $ \e -> checkTypedBindingGroupElement moduleName e dict+  ds2' <- forM untyped $ \e -> typeForBindingGroupElement e dict untypedDict+  let ds' = [(ident, LocalVariable, val') | (ident, (val', _)) <- ds1' ++ ds2']   makeBindingGroupVisible $ bindNames dict $ inferLetBinding (seen ++ [BindingGroupDeclaration ds']) rest ret j inferLetBinding seen (PositionedDeclaration pos d : ds) ret j = rethrowWithPosition pos $ do   ((d' : ds'), val') <- inferLetBinding seen (d : ds) ret j@@ -778,6 +785,8 @@ checkBinders :: [Type] -> Type -> [CaseAlternative] -> UnifyT Type Check [CaseAlternative] checkBinders _ _ [] = return [] checkBinders nvals ret (CaseAlternative binders grd val : bs) = do+  guardWith (strMsg "Overlapping binders in case statement") $+    let ns = concatMap binderNames binders in length (nub ns) == length ns   Just moduleName <- checkCurrentModule <$> get   m1 <- M.unions <$> zipWithM inferBinder nvals binders   r <- bindLocalVariables moduleName [ (name, ty, Defined) | (name, ty) <- M.toList m1 ] $ do@@ -856,7 +865,7 @@     n <- liftCheck freshDictionaryName     return $ Ident $ "__dict_" ++ className ++ "_" ++ show n   val' <- makeBindingGroupVisible $ withTypeClassDictionaries (zipWith (\name (className, instanceTy) ->-    TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular) (map (Qualified Nothing) dictNames)+    TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular False) (map (Qualified Nothing) dictNames)       constraints) $ check val ty   return $ TypedValue True (foldr (Abs . Left) val' dictNames) t check' val (SaturatedTypeSynonym name args) = do@@ -1118,6 +1127,23 @@ subsumes' val ty1 ty2 = do   ty1 =?= ty2   return val++-- |+-- Compute the meet of two types, i.e. the most general type which both types subsume.+-- TODO: handle constrained types+--+meet :: Expr -> Expr -> Type -> Type -> UnifyT Type Check (Expr, Expr, Type)+meet e1 e2 (ForAll ident t1 _) t2 = do+  t1' <- replaceVarWithUnknown ident t1+  meet e1 e2 t1' t2+meet e1 e2 t1 (ForAll ident t2 _) = do+  t2' <- replaceVarWithUnknown ident t2+  meet e1 e2 t1 t2'+meet e1 e2 t1 t2 = do+  t1 =?= t2+  return (e1, e2, t1)++   
src/Language/PureScript/TypeClassDictionaries.hs view
@@ -46,6 +46,10 @@     -- The type of this dictionary     --     , tcdType :: TypeClassDictionaryType+    -- |+    -- Is this instance exported by its module?+    --+    , tcdExported :: Bool     } deriving (Show, Data, Typeable)  -- |
tests/Main.hs view
@@ -12,7 +12,7 @@ -- ----------------------------------------------------------------------------- -{-# LANGUAGE DoAndIfThenElse #-}+{-# LANGUAGE DataKinds, DoAndIfThenElse #-}  module Main (main) where @@ -34,15 +34,15 @@   text <- U.readFile inputFile   return $ P.runIndentParser inputFile P.parseModules text -compile :: P.Options -> [FilePath] -> IO (Either String (String, String, P.Environment))+compile :: P.Options P.Compile -> [FilePath] -> IO (Either String (String, String, P.Environment)) compile opts inputFiles = do   modules <- readInput inputFiles   case modules of     Left parseError ->       return (Left $ show parseError)-    Right ms -> return $ P.compile opts ms [] +    Right ms -> return $ P.compile opts ms [] -assert :: FilePath -> P.Options -> FilePath -> (Either String (String, String, P.Environment) -> IO (Maybe String)) -> IO ()+assert :: FilePath -> P.Options P.Compile -> FilePath -> (Either String (String, String, P.Environment) -> IO (Maybe String)) -> IO () assert preludeExterns opts inputFile f = do   e <- compile opts [preludeExterns, inputFile]   maybeErr <- f e@@ -53,7 +53,10 @@ assertCompiles :: String -> FilePath -> FilePath -> IO () assertCompiles preludeJs preludeExterns inputFile = do   putStrLn $ "Assert " ++ inputFile ++ " compiles successfully"-  let options = P.defaultOptions { P.optionsMain = Just "Main", P.optionsModules = ["Main"], P.optionsCodeGenModules = ["Main"], P.optionsBrowserNamespace = Just "Tests" }+  let options = P.defaultCompileOptions+                              { P.optionsMain = Just "Main"+                              , P.optionsAdditional = P.CompileOptions "Tests" ["Main"] ["Main"]+                              }   assert preludeExterns options inputFile $ either (return . Just) $ \(js, _, _) -> do     process <- findNodeProcess     result <- traverse (\node -> readProcessWithExitCode node [] (preludeJs ++ js)) process@@ -65,7 +68,7 @@ assertDoesNotCompile :: FilePath -> FilePath -> IO () assertDoesNotCompile preludeExterns inputFile = do   putStrLn $ "Assert " ++ inputFile ++ " does not compile"-  assert preludeExterns (P.defaultOptions { P.optionsBrowserNamespace = Just "Tests" }) inputFile $ \e ->+  assert preludeExterns (P.defaultCompileOptions { P.optionsAdditional = P.CompileOptions "Tests" [] [] }) inputFile $ \e ->     case e of       Left _ -> return Nothing       Right _ -> return $ Just "Should not have compiled"@@ -78,7 +81,7 @@ main = do   prelude <- P.preludeFilename   putStrLn "Compiling Prelude"-  preludeResult <- compile (P.defaultOptions { P.optionsBrowserNamespace = Just "Tests" }) [prelude]+  preludeResult <- compile (P.defaultCompileOptions { P.optionsAdditional = P.CompileOptions "Tests" [] [] }) [prelude]   case preludeResult of     Left err -> putStrLn err >> exitFailure     Right (preludeJs, exts, _) -> do@@ -97,3 +100,4 @@       forM_ failingTestCases $ \inputFile -> when (".purs" `isSuffixOf` inputFile) $         assertDoesNotCompile preludeExterns (failing ++ pathSeparator : inputFile)       exitSuccess+