git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge pull request #1873 from hdgarrood/fix-publish-tests
7bb21b5Phil Freeman
.gitignore−1
@@ -14,7 +14,6 @@ bower_components/
14node_modules
14node_modules
15tmp/
15tmp/
16.stack-work/
16.stack-work/
17−tests/support/flattened/
18output
17output
19examples/docs/docs/
18examples/docs/docs/
20core-tests/full-core-docs.md
19core-tests/full-core-docs.md
.travis.yml+1−4
@@ -2,13 +2,10 @@ language: c
2sudo: false
2sudo: false
3matrix:
3matrix:
4 include:
4 include:
5− - env: GHCVER=7.8.4 COVERAGE_SUITE=tests
5+ - env: GHCVER=7.8.4 COVERAGE=true
6 compiler: ": #GHC 7.8.4 - tests"
6 compiler: ": #GHC 7.8.4 - tests"
7 # ^ HACK before https://github.com/travis-ci/travis-ci/issues/4393 is resolved
7 # ^ HACK before https://github.com/travis-ci/travis-ci/issues/4393 is resolved
8 addons: {apt: {packages: [cabal-install-1.22,ghc-7.8.4,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
8 addons: {apt: {packages: [cabal-install-1.22,ghc-7.8.4,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
9− - env: GHCVER=7.8.4 COVERAGE_SUITE=psci-tests
10− compiler: ": #GHC 7.8.4 - psci-tests"
11− addons: {apt: {packages: [cabal-install-1.22,ghc-7.8.4,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
12 - env: GHCVER=7.8.4 STACKAGE=lts-2.22
9 - env: GHCVER=7.8.4 STACKAGE=lts-2.22
13 compiler: ": #GHC 7.8.4 - lts-2.22-1"
10 compiler: ": #GHC 7.8.4 - lts-2.22-1"
14 addons: {apt: {packages: [cabal-install-1.22,ghc-7.8.4,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
11 addons: {apt: {packages: [cabal-install-1.22,ghc-7.8.4,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
psci/PSCi.hs+5−5
@@ -44,11 +44,11 @@ import qualified Language.PureScript as P
44import qualified Language.PureScript.Names as N
44import qualified Language.PureScript.Names as N
45import qualified Paths_purescript as Paths
45import qualified Paths_purescript as Paths
46
46
47−import qualified Directive as D
47+import qualified PSCi.Directive as D
48−import Completion (completion)
48+import PSCi.Completion (completion)
49−import IO (mkdirp)
49+import PSCi.IO (mkdirp)
50−import Parser (parseCommand)
50+import PSCi.Parser (parseCommand)
51−import Types
51+import PSCi.Types
52
52
53-- | The name of the PSCI support module
53-- | The name of the PSCI support module
54supportModuleName :: P.ModuleName
54supportModuleName :: P.ModuleName
psci/Completion.hs → psci/PSCi/Completion.hsrenamed+3−3
@@ -1,6 +1,6 @@
1{-# LANGUAGE DataKinds #-}
1{-# LANGUAGE DataKinds #-}
2
2
3−module Completion where
3+module PSCi.Completion where
4
4
5import Prelude ()
5import Prelude ()
6import Prelude.Compat
6import Prelude.Compat
@@ -19,8 +19,8 @@ import System.Console.Haskeline
19import qualified Language.PureScript as P
19import qualified Language.PureScript as P
20import qualified Language.PureScript.Names as N
20import qualified Language.PureScript.Names as N
21
21
22−import qualified Directive as D
22+import qualified PSCi.Directive as D
23−import Types
23+import PSCi.Types
24
24
25-- Completions may read the state, but not modify it.
25-- Completions may read the state, but not modify it.
26type CompletionM = ReaderT PSCiState IO
26type CompletionM = ReaderT PSCiState IO
psci/Directive.hs → psci/PSCi/Directive.hsrenamed+2−2
@@ -13,13 +13,13 @@
13--
13--
14-----------------------------------------------------------------------------
14-----------------------------------------------------------------------------
15
15
16−module Directive where
16+module PSCi.Directive where
17
17
18import Data.Maybe (fromJust, listToMaybe)
18import Data.Maybe (fromJust, listToMaybe)
19import Data.List (isPrefixOf)
19import Data.List (isPrefixOf)
20import Data.Tuple (swap)
20import Data.Tuple (swap)
21
21
22−import Types
22+import PSCi.Types
23
23
24-- |
24-- |
25-- List of all avaliable directives.
25-- List of all avaliable directives.
psci/IO.hs → psci/PSCi/IO.hsrenamed+1−1
@@ -12,7 +12,7 @@
12--
12--
13-----------------------------------------------------------------------------
13-----------------------------------------------------------------------------
14
14
15−module IO where
15+module PSCi.IO where
16
16
17import System.Directory (createDirectoryIfMissing)
17import System.Directory (createDirectoryIfMissing)
18import System.FilePath (takeDirectory)
18import System.FilePath (takeDirectory)
psci/Parser.hs → psci/PSCi/Parser.hsrenamed+3−3
@@ -13,7 +13,7 @@
13--
13--
14-----------------------------------------------------------------------------
14-----------------------------------------------------------------------------
15
15
16−module Parser
16+module PSCi.Parser
17 ( parseCommand
17 ( parseCommand
18 ) where
18 ) where
19
19
@@ -28,8 +28,8 @@ import Text.Parsec hiding ((<|>))
28import qualified Language.PureScript as P
28import qualified Language.PureScript as P
29import Language.PureScript.Parser.Common (mark, same)
29import Language.PureScript.Parser.Common (mark, same)
30
30
31−import qualified Directive as D
31+import qualified PSCi.Directive as D
32−import Types
32+import PSCi.Types
33
33
34-- |
34-- |
35-- Parses PSCI metacommands or expressions input from the user.
35-- Parses PSCI metacommands or expressions input from the user.
psci/Types.hs → psci/PSCi/Types.hsrenamed+1−1
@@ -13,7 +13,7 @@
13--
13--
14-----------------------------------------------------------------------------
14-----------------------------------------------------------------------------
15
15
16−module Types where
16+module PSCi.Types where
17
17
18import Control.Arrow (second)
18import Control.Arrow (second)
19import Data.Map (Map)
19import Data.Map (Map)
purescript.cabal+21−24
@@ -27,7 +27,13 @@ extra-source-files: examples/passing/*.purs
27 , tests/support/package.json
27 , tests/support/package.json
28 , tests/support/bower.json
28 , tests/support/bower.json
29 , tests/support/setup-win.cmd
29 , tests/support/setup-win.cmd
30− , psci/tests/data/Sample.purs
30+ , tests/support/flattened/*.purs
31+ , tests/support/flattened/*.js
32+ , tests/support/psci/*.purs
33+ , tests/support/prelude/bower.json
34+ , tests/support/prelude/src/*.purs
35+ , tests/support/prelude/src/*.js
36+ , tests/support/prelude/LICENSE
31 , stack.yaml
37 , stack.yaml
32 , stack-lts-2.yaml
38 , stack-lts-2.yaml
33 , stack-lts-3.yaml
39 , stack-lts-3.yaml
@@ -213,12 +219,12 @@ executable psci
213 main-is: Main.hs
219 main-is: Main.hs
214 buildable: True
220 buildable: True
215 hs-source-dirs: psci psci/main
221 hs-source-dirs: psci psci/main
216− other-modules: Types
222+ other-modules: PSCi
223+ PSCi.Types
217− Parser
224+ PSCi.Parser
218− Directive
225+ PSCi.Directive
219− Completion
226+ PSCi.Completion
220− PSCi
227+ PSCi.IO
221− IO
222 ghc-options: -Wall -O2
228 ghc-options: -Wall -O2
223
229
224executable psc-docs
230executable psc-docs
@@ -273,24 +279,15 @@ test-suite tests
273 filepath -any, mtl -any, parsec -any, purescript -any,
279 filepath -any, mtl -any, parsec -any, purescript -any,
274 transformers -any, process -any, transformers-compat -any, time -any,
280 transformers -any, process -any, transformers-compat -any, time -any,
275 Glob -any, aeson-better-errors -any, bytestring -any, aeson -any,
281 Glob -any, aeson-better-errors -any, bytestring -any, aeson -any,
276− base-compat -any
282+ base-compat -any, haskeline >= 0.7.0.0, optparse-applicative -any,
283+ boxes -any, HUnit -any
284+ ghc-options: -Wall
277 type: exitcode-stdio-1.0
285 type: exitcode-stdio-1.0
278 main-is: Main.hs
286 main-is: Main.hs
279− other-modules: TestsSetup
287+ other-modules: TestUtils
280− TestPscPublish
288+ TestCompiler
281 TestDocs
289 TestDocs
290+ TestPscPublish
291+ TestPsci
282 buildable: True
292 buildable: True
283− hs-source-dirs: tests tests/common
293+ hs-source-dirs: tests psci
284−
285−test-suite psci-tests
286− build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
287− mtl -any, optparse-applicative >= 0.10.0, parsec -any,
288− haskeline >= 0.7.0.0, purescript -any, transformers -any,
289− transformers-compat -any, process -any, HUnit -any, time -any,
290− Glob -any, base-compat >=0.6.0, boxes >= 0.1.4 && < 0.2.0
291− type: exitcode-stdio-1.0
292− main-is: Main.hs
293− other-modules: TestsSetup
294− buildable: True
295− hs-source-dirs: psci psci/tests tests/common
296− ghc-options: -Wall
tests/Main.hs+8−204
@@ -16,171 +16,26 @@
16{-# LANGUAGE TupleSections #-}
16{-# LANGUAGE TupleSections #-}
17{-# LANGUAGE FlexibleInstances #-}
17{-# LANGUAGE FlexibleInstances #-}
18
18
19−-- Failing tests can specify the kind of error that should be thrown with a
20−-- @shouldFailWith declaration. For example:
21−--
22−-- "-- @shouldFailWith TypesDoNotUnify"
23−--
24−-- will cause the test to fail unless that module fails to compile with exactly
25−-- one TypesDoNotUnify error.
26−--
27−-- If a module is expected to produce multiple type errors, then use multiple
28−-- @shouldFailWith lines; for example:
29−--
30−-- -- @shouldFailWith TypesDoNotUnify
31−-- -- @shouldFailWith TypesDoNotUnify
32−-- -- @shouldFailWith TransitiveExportError
33−--
34−
35module Main (main) where
19module Main (main) where
36
20
37import Prelude ()
21import Prelude ()
38import Prelude.Compat
22import Prelude.Compat
39
23
40−import qualified Language.PureScript as P
24+import qualified TestCompiler
41−import qualified Language.PureScript.CodeGen.JS as J
42−import qualified Language.PureScript.CoreFn as CF
43−import qualified Language.PureScript.Docs as Docs
44−
45−import Data.Char (isSpace)
46−import Data.Maybe (mapMaybe, fromMaybe)
47−import Data.List (isSuffixOf, sort, stripPrefix)
48−import Data.Time.Clock (UTCTime())
49−
50−import qualified Data.Map as M
51−
52−import Control.Monad
53−import Control.Monad.IO.Class (liftIO)
54−import Control.Arrow ((>>>))
55−
56−import Control.Monad.Reader
57−import Control.Monad.Writer.Strict
58−import Control.Monad.Trans.Maybe
59−import Control.Monad.Trans.Except
60−import Control.Monad.Error.Class
61−
62−import System.Exit
63−import System.Process
64−import System.FilePath
65−import System.Directory
66−import System.IO.UTF8
67−import qualified System.Info
68−import qualified System.FilePath.Glob as Glob
69−
70−import Text.Parsec (ParseError)
71−
72−import TestsSetup
73−import TestPscPublish
25+import qualified TestPscPublish
74import qualified TestDocs
26import qualified TestDocs
75−
27+import qualified TestPsci
76−modulesDir :: FilePath
77−modulesDir = ".test_modules" </> "node_modules"
78−
79−makeActions :: M.Map P.ModuleName FilePath -> P.MakeActions P.Make
80−makeActions foreigns = (P.buildMakeActions modulesDir (P.internalError "makeActions: input file map was read.") foreigns False)
81− { P.getInputTimestamp = getInputTimestamp
82− , P.getOutputTimestamp = getOutputTimestamp
83− }
84− where
85− getInputTimestamp :: P.ModuleName -> P.Make (Either P.RebuildPolicy (Maybe UTCTime))
86− getInputTimestamp mn
87− | isSupportModule (P.runModuleName mn) = return (Left P.RebuildNever)
88− | otherwise = return (Left P.RebuildAlways)
89− where
90− isSupportModule = flip elem supportModules
91−
92− getOutputTimestamp :: P.ModuleName -> P.Make (Maybe UTCTime)
93− getOutputTimestamp mn = do
94− let filePath = modulesDir </> P.runModuleName mn
95− exists <- liftIO $ doesDirectoryExist filePath
96− return (if exists then Just (P.internalError "getOutputTimestamp: read timestamp") else Nothing)
97−
98−readInput :: [FilePath] -> IO [(FilePath, String)]
99−readInput inputFiles = forM inputFiles $ \inputFile -> do
100− text <- readUTF8File inputFile
101− return (inputFile, text)
102−
103−type TestM = WriterT [(FilePath, String)] IO
104−
105−runTest :: P.Make a -> IO (Either P.MultipleErrors a)
106−runTest = fmap fst . P.runMake P.defaultOptions
107−
108−compile :: [FilePath] -> M.Map P.ModuleName FilePath -> IO (Either P.MultipleErrors P.Environment)
109−compile inputFiles foreigns = runTest $ do
110− fs <- liftIO $ readInput inputFiles
111− ms <- P.parseModulesFromFiles id fs
112− P.make (makeActions foreigns) (map snd ms)
113−
114−assert :: [FilePath] ->
115− M.Map P.ModuleName FilePath ->
116− (Either P.MultipleErrors P.Environment -> IO (Maybe String)) ->
117− TestM ()
118−assert inputFiles foreigns f = do
119− e <- liftIO $ compile inputFiles foreigns
120− maybeErr <- liftIO $ f e
121− case maybeErr of
122− Just err -> tell [(last inputFiles, err)]
123− Nothing -> return ()
124−
125−assertCompiles :: [FilePath] -> M.Map P.ModuleName FilePath -> TestM ()
126−assertCompiles inputFiles foreigns = do
127− liftIO . putStrLn $ "Assert " ++ last inputFiles ++ " compiles successfully"
128− assert inputFiles foreigns $ \e ->
129− case e of
130− Left errs -> return . Just . P.prettyPrintMultipleErrors False $ errs
131− Right _ -> do
132− process <- findNodeProcess
133− let entryPoint = modulesDir </> "index.js"
134− writeFile entryPoint "require('Main').main()"
135− result <- traverse (\node -> readProcessWithExitCode node [entryPoint] "") process
136− case result of
137− Just (ExitSuccess, out, _) -> putStrLn out >> return Nothing
138− Just (ExitFailure _, _, err) -> return $ Just err
139− Nothing -> return $ Just "Couldn't find node.js executable"
140−
141−assertDoesNotCompile :: [FilePath] -> M.Map P.ModuleName FilePath -> TestM ()
142−assertDoesNotCompile inputFiles foreigns = do
143− let testFile = last inputFiles
144− liftIO . putStrLn $ "Assert " ++ testFile ++ " does not compile"
145− shouldFailWith <- getShouldFailWith testFile
146− assert inputFiles foreigns $ \e ->
147− case e of
148− Left errs -> do
149− putStrLn (P.prettyPrintMultipleErrors False errs)
150− return $ if null shouldFailWith
151− then Just $ "shouldFailWith declaration is missing (errors were: "
152− ++ show (map P.errorCode (P.runMultipleErrors errs))
153− ++ ")"
154− else checkShouldFailWith shouldFailWith errs
155− Right _ ->
156− return $ Just "Should not have compiled"
157−
158− where
159− getShouldFailWith =
160− readUTF8File
161− >>> liftIO
162− >>> fmap ( lines
163− >>> mapMaybe (stripPrefix "-- @shouldFailWith ")
164− >>> map trim
165− )
166−
167− checkShouldFailWith expected errs =
168− let actual = map P.errorCode $ P.runMultipleErrors errs
169− in if sort expected == sort actual
170− then Nothing
171− else Just $ "Expected these errors: " ++ show expected ++ ", but got these: " ++ show actual
172−
173− trim =
174− dropWhile isSpace >>> reverse >>> dropWhile isSpace >>> reverse
175
28
176main :: IO ()
29main :: IO ()
177main = do
30main = do
178 heading "Main compiler test suite"
31 heading "Main compiler test suite"
179− testCompiler
32+ TestCompiler.main
180 heading "Documentation test suite"
33 heading "Documentation test suite"
181 TestDocs.main
34 TestDocs.main
182− -- heading "psc-publish test suite"
35+ heading "psc-publish test suite"
183− -- testPscPublish
36+ TestPscPublish.main
37+ heading "psci test suite"
38+ TestPsci.main
184
39
185 where
40 where
186 heading msg = do
41 heading msg = do
@@ -189,54 +44,3 @@ main = do
189 putStrLn $ "# " ++ msg
44 putStrLn $ "# " ++ msg
190 putStrLn $ replicate 79 '#'
45 putStrLn $ replicate 79 '#'
191 putStrLn ""
46 putStrLn ""
192−
193−testCompiler :: IO ()
194−testCompiler = do
195− fetchSupportCode
196− cwd <- getCurrentDirectory
197−
198− let supportDir = cwd </> "tests" </> "support" </> "flattened"
199− let supportFiles ext = Glob.globDir1 (Glob.compile ("*." ++ ext)) supportDir
200−
201− supportPurs <- supportFiles "purs"
202− supportJS <- supportFiles "js"
203−
204− foreignFiles <- forM supportJS (\f -> (f,) <$> readUTF8File f)
205− Right (foreigns, _) <- runExceptT $ runWriterT $ P.parseForeignModulesFromFiles foreignFiles
206−
207− let passing = cwd </> "examples" </> "passing"
208− passingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents passing
209− let failing = cwd </> "examples" </> "failing"
210− failingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents failing
211−
212− failures <- execWriterT $ do
213− forM_ passingTestCases $ \inputFile ->
214− assertCompiles (supportPurs ++ [passing </> inputFile]) foreigns
215− forM_ failingTestCases $ \inputFile ->
216− assertDoesNotCompile (supportPurs ++ [failing </> inputFile]) foreigns
217−
218− if null failures
219− then pure ()
220− else do
221− putStrLn "Failures:"
222− forM_ failures $ \(fp, err) ->
223− let fp' = fromMaybe fp $ stripPrefix (failing ++ [pathSeparator]) fp
224− in putStrLn $ fp' ++ ": " ++ err
225− exitFailure
226−
227−testPscPublish :: IO ()
228−testPscPublish = do
229− testPackage "tests/support/prelude"
230−
231−
232−supportModules :: [String]
233−supportModules =
234− [ "Control.Monad.Eff.Class"
235− , "Control.Monad.Eff.Console"
236− , "Control.Monad.Eff"
237− , "Control.Monad.Eff.Unsafe"
238− , "Control.Monad.ST"
239− , "Data.Function"
240− , "Prelude"
241− , "Test.Assert"
242− ]
tests/TestCompiler.hsnew file+194
@@ -0,0 +1,194 @@
1+{-# LANGUAGE DataKinds #-}
2+{-# LANGUAGE DoAndIfThenElse #-}
3+{-# LANGUAGE TupleSections #-}
4+{-# LANGUAGE FlexibleInstances #-}
5+
6+module TestCompiler where
7+
8+-- Failing tests can specify the kind of error that should be thrown with a
9+-- @shouldFailWith declaration. For example:
10+--
11+-- "-- @shouldFailWith TypesDoNotUnify"
12+--
13+-- will cause the test to fail unless that module fails to compile with exactly
14+-- one TypesDoNotUnify error.
15+--
16+-- If a module is expected to produce multiple type errors, then use multiple
17+-- @shouldFailWith lines; for example:
18+--
19+-- -- @shouldFailWith TypesDoNotUnify
20+-- -- @shouldFailWith TypesDoNotUnify
21+-- -- @shouldFailWith TransitiveExportError
22+
23+import Prelude ()
24+import Prelude.Compat
25+
26+import qualified Language.PureScript as P
27+
28+import Data.Char (isSpace)
29+import Data.Maybe (mapMaybe, fromMaybe)
30+import Data.List (isSuffixOf, sort, stripPrefix)
31+import Data.Time.Clock (UTCTime())
32+
33+import qualified Data.Map as M
34+
35+import Control.Monad
36+import Control.Arrow ((>>>))
37+
38+import Control.Monad.Reader
39+import Control.Monad.Writer.Strict
40+import Control.Monad.Trans.Except
41+
42+import System.Exit
43+import System.Process hiding (cwd)
44+import System.FilePath
45+import System.Directory
46+import System.IO.UTF8
47+import qualified System.FilePath.Glob as Glob
48+
49+import TestUtils
50+
51+main :: IO ()
52+main = do
53+ cwd <- getCurrentDirectory
54+
55+ let supportDir = cwd </> "tests" </> "support" </> "flattened"
56+ let supportFiles ext = Glob.globDir1 (Glob.compile ("*." ++ ext)) supportDir
57+
58+ supportPurs <- supportFiles "purs"
59+ supportJS <- supportFiles "js"
60+
61+ foreignFiles <- forM supportJS (\f -> (f,) <$> readUTF8File f)
62+ Right (foreigns, _) <- runExceptT $ runWriterT $ P.parseForeignModulesFromFiles foreignFiles
63+
64+ let passing = cwd </> "examples" </> "passing"
65+ passingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents passing
66+ let failing = cwd </> "examples" </> "failing"
67+ failingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents failing
68+
69+ failures <- execWriterT $ do
70+ forM_ passingTestCases $ \inputFile ->
71+ assertCompiles (supportPurs ++ [passing </> inputFile]) foreigns
72+ forM_ failingTestCases $ \inputFile ->
73+ assertDoesNotCompile (supportPurs ++ [failing </> inputFile]) foreigns
74+
75+ if null failures
76+ then pure ()
77+ else do
78+ putStrLn "Failures:"
79+ forM_ failures $ \(fp, err) ->
80+ let fp' = fromMaybe fp $ stripPrefix (failing ++ [pathSeparator]) fp
81+ in putStrLn $ fp' ++ ": " ++ err
82+ exitFailure
83+
84+modulesDir :: FilePath
85+modulesDir = ".test_modules" </> "node_modules"
86+
87+makeActions :: M.Map P.ModuleName FilePath -> P.MakeActions P.Make
88+makeActions foreigns = (P.buildMakeActions modulesDir (P.internalError "makeActions: input file map was read.") foreigns False)
89+ { P.getInputTimestamp = getInputTimestamp
90+ , P.getOutputTimestamp = getOutputTimestamp
91+ }
92+ where
93+ getInputTimestamp :: P.ModuleName -> P.Make (Either P.RebuildPolicy (Maybe UTCTime))
94+ getInputTimestamp mn
95+ | isSupportModule (P.runModuleName mn) = return (Left P.RebuildNever)
96+ | otherwise = return (Left P.RebuildAlways)
97+ where
98+ isSupportModule = flip elem supportModules
99+
100+ getOutputTimestamp :: P.ModuleName -> P.Make (Maybe UTCTime)
101+ getOutputTimestamp mn = do
102+ let filePath = modulesDir </> P.runModuleName mn
103+ exists <- liftIO $ doesDirectoryExist filePath
104+ return (if exists then Just (P.internalError "getOutputTimestamp: read timestamp") else Nothing)
105+
106+readInput :: [FilePath] -> IO [(FilePath, String)]
107+readInput inputFiles = forM inputFiles $ \inputFile -> do
108+ text <- readUTF8File inputFile
109+ return (inputFile, text)
110+
111+type TestM = WriterT [(FilePath, String)] IO
112+
113+runTest :: P.Make a -> IO (Either P.MultipleErrors a)
114+runTest = fmap fst . P.runMake P.defaultOptions
115+
116+compile :: [FilePath] -> M.Map P.ModuleName FilePath -> IO (Either P.MultipleErrors P.Environment)
117+compile inputFiles foreigns = runTest $ do
118+ fs <- liftIO $ readInput inputFiles
119+ ms <- P.parseModulesFromFiles id fs
120+ P.make (makeActions foreigns) (map snd ms)
121+
122+assert :: [FilePath] ->
123+ M.Map P.ModuleName FilePath ->
124+ (Either P.MultipleErrors P.Environment -> IO (Maybe String)) ->
125+ TestM ()
126+assert inputFiles foreigns f = do
127+ e <- liftIO $ compile inputFiles foreigns
128+ maybeErr <- liftIO $ f e
129+ case maybeErr of
130+ Just err -> tell [(last inputFiles, err)]
131+ Nothing -> return ()
132+
133+assertCompiles :: [FilePath] -> M.Map P.ModuleName FilePath -> TestM ()
134+assertCompiles inputFiles foreigns = do
135+ liftIO . putStrLn $ "Assert " ++ last inputFiles ++ " compiles successfully"
136+ assert inputFiles foreigns $ \e ->
137+ case e of
138+ Left errs -> return . Just . P.prettyPrintMultipleErrors False $ errs
139+ Right _ -> do
140+ process <- findNodeProcess
141+ let entryPoint = modulesDir </> "index.js"
142+ writeFile entryPoint "require('Main').main()"
143+ result <- traverse (\node -> readProcessWithExitCode node [entryPoint] "") process
144+ case result of
145+ Just (ExitSuccess, out, _) -> putStrLn out >> return Nothing
146+ Just (ExitFailure _, _, err) -> return $ Just err
147+ Nothing -> return $ Just "Couldn't find node.js executable"
148+
149+assertDoesNotCompile :: [FilePath] -> M.Map P.ModuleName FilePath -> TestM ()
150+assertDoesNotCompile inputFiles foreigns = do
151+ let testFile = last inputFiles
152+ liftIO . putStrLn $ "Assert " ++ testFile ++ " does not compile"
153+ shouldFailWith <- getShouldFailWith testFile
154+ assert inputFiles foreigns $ \e ->
155+ case e of
156+ Left errs -> do
157+ putStrLn (P.prettyPrintMultipleErrors False errs)
158+ return $ if null shouldFailWith
159+ then Just $ "shouldFailWith declaration is missing (errors were: "
160+ ++ show (map P.errorCode (P.runMultipleErrors errs))
161+ ++ ")"
162+ else checkShouldFailWith shouldFailWith errs
163+ Right _ ->
164+ return $ Just "Should not have compiled"
165+
166+ where
167+ getShouldFailWith =
168+ readUTF8File
169+ >>> liftIO
170+ >>> fmap ( lines
171+ >>> mapMaybe (stripPrefix "-- @shouldFailWith ")
172+ >>> map trim
173+ )
174+
175+ checkShouldFailWith expected errs =
176+ let actual = map P.errorCode $ P.runMultipleErrors errs
177+ in if sort expected == sort actual
178+ then Nothing
179+ else Just $ "Expected these errors: " ++ show expected ++ ", but got these: " ++ show actual
180+
181+ trim =
182+ dropWhile isSpace >>> reverse >>> dropWhile isSpace >>> reverse
183+
184+supportModules :: [String]
185+supportModules =
186+ [ "Control.Monad.Eff.Class"
187+ , "Control.Monad.Eff.Console"
188+ , "Control.Monad.Eff"
189+ , "Control.Monad.Eff.Unsafe"
190+ , "Control.Monad.ST"
191+ , "Data.Function"
192+ , "Prelude"
193+ , "Test.Assert"
194+ ]
tests/TestDocs.hs+6−9
@@ -9,21 +9,17 @@ import Prelude.Compat
9
9
10import Data.Version (Version(..))
10import Data.Version (Version(..))
11
11
12−import Control.Monad hiding (forM_)
12+import Data.Monoid ((<>))
13−import Control.Applicative
14−import Control.Arrow
15import Data.Maybe (fromMaybe)
13import Data.Maybe (fromMaybe)
16import Data.List ((\\))
14import Data.List ((\\))
17import Data.Foldable
15import Data.Foldable
18−import Data.Traversable
19import System.Exit
16import System.Exit
20−import qualified Text.Parsec as Parsec
21
17
22import qualified Language.PureScript as P
18import qualified Language.PureScript as P
23import qualified Language.PureScript.Docs as Docs
19import qualified Language.PureScript.Docs as Docs
24import qualified Language.PureScript.Publish as Publish
20import qualified Language.PureScript.Publish as Publish
25
21
26−import qualified TestPscPublish
22+import TestUtils
27
23
28publishOpts :: Publish.PublishOptions
24publishOpts :: Publish.PublishOptions
29publishOpts = Publish.defaultPublishOptions
25publishOpts = Publish.defaultPublishOptions
@@ -34,7 +30,7 @@ publishOpts = Publish.defaultPublishOptions
34
30
35main :: IO ()
31main :: IO ()
36main = do
32main = do
37− TestPscPublish.pushd "examples/docs" $ do
33+ pushd "examples/docs" $ do
38 Docs.Package{..} <- Publish.preparePackage publishOpts
34 Docs.Package{..} <- Publish.preparePackage publishOpts
39 forM_ testCases $ \(mn, pragmas) ->
35 forM_ testCases $ \(mn, pragmas) ->
40 let mdl = takeJust ("module not found in docs: " ++ mn)
36 let mdl = takeJust ("module not found in docs: " ++ mn)
@@ -132,6 +128,7 @@ runAssertion assertion Docs.Module{..} =
132
128
133 childrenTitles = map Docs.cdeclTitle . Docs.declChildren
129 childrenTitles = map Docs.cdeclTitle . Docs.declChildren
134
130
131+checkConstrained :: P.Type -> String -> Bool
135checkConstrained ty tyClass =
132checkConstrained ty tyClass =
136 -- Note that we don't recurse on ConstrainedType if none of the constraints
133 -- Note that we don't recurse on ConstrainedType if none of the constraints
137 -- match; this is by design, as constraints should be moved to the front
134 -- match; this is by design, as constraints should be moved to the front
@@ -152,8 +149,8 @@ runAssertionIO assertion mdl = do
152 putStrLn ("In " ++ Docs.modName mdl ++ ": " ++ show assertion)
149 putStrLn ("In " ++ Docs.modName mdl ++ ": " ++ show assertion)
153 case runAssertion assertion mdl of
150 case runAssertion assertion mdl of
154 Pass -> pure ()
151 Pass -> pure ()
155− fail -> do
152+ Fail reason -> do
156− putStrLn (show fail)
153+ putStrLn ("Failed: " <> show reason)
157 exitFailure
154 exitFailure
158
155
159testCases :: [(String, [Assertion])]
156testCases :: [(String, [Assertion])]
tests/TestPscPublish.hs+9−8
@@ -20,13 +20,11 @@ import Data.Version
20import Language.PureScript.Docs
20import Language.PureScript.Docs
21import Language.PureScript.Publish
21import Language.PureScript.Publish
22
22
23−pushd :: forall a. FilePath -> IO a -> IO a
23+import TestUtils
24−pushd dir act = do
24+
25− original <- getCurrentDirectory
25+main :: IO ()
26− setCurrentDirectory dir
26+main = do
27− result <- try act :: IO (Either IOException a)
27+ testPackage "tests/support/prelude"
28− setCurrentDirectory original
29− either throwIO return result
30
28
31data TestResult
29data TestResult
32 = ParseFailed String
30 = ParseFailed String
@@ -48,6 +46,7 @@ roundTrip pkg =
48testRunOptions :: PublishOptions
46testRunOptions :: PublishOptions
49testRunOptions = defaultPublishOptions
47testRunOptions = defaultPublishOptions
50 { publishGetVersion = return testVersion
48 { publishGetVersion = return testVersion
49+ , publishWorkingTreeDirty = return ()
51 }
50 }
52 where testVersion = ("v999.0.0", Version [999,0,0] [])
51 where testVersion = ("v999.0.0", Version [999,0,0] [])
53
52
@@ -58,7 +57,9 @@ testPackage dir = do
58 pushd dir $ do
57 pushd dir $ do
59 r <- roundTrip <$> preparePackage testRunOptions
58 r <- roundTrip <$> preparePackage testRunOptions
60 case r of
59 case r of
61− Pass _ -> pure ()
60+ Pass _ -> do
61+ putStrLn ("psc-publish test passed for: " ++ dir)
62+ pure ()
62 other -> do
63 other -> do
63 putStrLn ("psc-publish tests failed on " ++ dir ++ ":")
64 putStrLn ("psc-publish tests failed on " ++ dir ++ ":")
64 putStrLn (show other)
65 putStrLn (show other)
psci/tests/Main.hs → tests/TestPsci.hsrenamed+5−8
@@ -1,7 +1,7 @@
1{-# LANGUAGE RecordWildCards #-}
1{-# LANGUAGE RecordWildCards #-}
2{-# LANGUAGE TupleSections #-}
2{-# LANGUAGE TupleSections #-}
3
3
4−module Main where
4+module TestPsci where
5
5
6import Prelude ()
6import Prelude ()
7import Prelude.Compat
7import Prelude.Compat
@@ -24,14 +24,11 @@ import Test.HUnit
24import qualified Language.PureScript as P
24import qualified Language.PureScript as P
25
25
26import PSCi
26import PSCi
27−import Completion
27+import PSCi.Completion
28−import Types
28+import PSCi.Types
29−
30−import TestsSetup
31
29
32main :: IO ()
30main :: IO ()
33main = do
31main = do
34− fetchSupportCode
35 Counts{..} <- runTestTT allTests
32 Counts{..} <- runTestTT allTests
36 when (errors + failures > 0) exitFailure
33 when (errors + failures > 0) exitFailure
37
34
@@ -65,8 +62,8 @@ completionTestData =
65 , ("import qualified Control.Monad.Eff.", map ("import qualified Control.Monad.Eff" ++) [".Unsafe", ".Class", ".Console"])
62 , ("import qualified Control.Monad.Eff.", map ("import qualified Control.Monad.Eff" ++) [".Unsafe", ".Class", ".Console"])
66
63
67 -- :load, :module should complete file paths
64 -- :load, :module should complete file paths
68− , (":l psci/tests/data/", [":l psci/tests/data/Sample.purs"])
65+ , (":l tests/support/psci/", [":l tests/support/psci/Sample.purs"])
69− , (":module psci/tests/data/", [":module psci/tests/data/Sample.purs"])
66+ , (":module tests/support/psci/", [":module tests/support/psci/Sample.purs"])
70
67
71 -- :quit, :help, :reset should not complete
68 -- :quit, :help, :reset should not complete
72 , (":help ", [])
69 , (":help ", [])
tests/common/TestsSetup.hs → tests/TestUtils.hsrenamed+23−3
@@ -10,7 +10,9 @@
10-- |
10-- |
11--
11--
12-----------------------------------------------------------------------------
12-----------------------------------------------------------------------------
13+{-# LANGUAGE ScopedTypeVariables #-}
14+
13−module TestsSetup where
15+module TestUtils where
14
16
15import Prelude ()
17import Prelude ()
16import Prelude.Compat
18import Prelude.Compat
@@ -18,6 +20,7 @@ import Prelude.Compat
18import Data.Maybe (fromMaybe)
20import Data.Maybe (fromMaybe)
19import Control.Monad
21import Control.Monad
20import Control.Monad.Trans.Maybe
22import Control.Monad.Trans.Maybe
23+import Control.Exception
21
24
22import System.Process
25import System.Process
23import System.Directory
26import System.Directory
@@ -30,8 +33,16 @@ findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names
30 where
33 where
31 names = ["nodejs", "node"]
34 names = ["nodejs", "node"]
32
35
33−fetchSupportCode :: IO ()
36+-- |
34−fetchSupportCode = do
37+-- Fetches code necessary to run the tests with. The resulting support code
38+-- should then be checked in, so that npm/bower etc is not required to run the
39+-- tests.
40+--
41+-- Simply rerun this (via ghci is probably easiest) when the support code needs
42+-- updating.
43+--
44+updateSupportCode :: IO ()
45+updateSupportCode = do
35 node <- fromMaybe (internalError "cannot find node executable") <$> findNodeProcess
46 node <- fromMaybe (internalError "cannot find node executable") <$> findNodeProcess
36 setCurrentDirectory "tests/support"
47 setCurrentDirectory "tests/support"
37 if System.Info.os == "mingw32"
48 if System.Info.os == "mingw32"
@@ -43,3 +54,12 @@ fetchSupportCode = do
43 callProcess "node_modules/.bin/bower" ["--allow-root", "install", "--config.interactive=false"]
54 callProcess "node_modules/.bin/bower" ["--allow-root", "install", "--config.interactive=false"]
44 callProcess node ["setup.js"]
55 callProcess node ["setup.js"]
45 setCurrentDirectory "../.."
56 setCurrentDirectory "../.."
57+
58+pushd :: forall a. FilePath -> IO a -> IO a
59+pushd dir act = do
60+ original <- getCurrentDirectory
61+ setCurrentDirectory dir
62+ result <- try act :: IO (Either IOException a)
63+ setCurrentDirectory original
64+ either throwIO return result
65+
tests/support/flattened/Control-Monad-Eff-Class.pursnew file+24
@@ -0,0 +1,24 @@
1+module Control.Monad.Eff.Class
2+ ( MonadEff
3+ , liftEff
4+ ) where
5+
6+import Prelude
7+
8+import Control.Monad.Eff
9+
10+-- | The `MonadEff` class captures those monads which support native effects.
11+-- |
12+-- | Instances are provided for `Eff` itself, and the standard monad transformers.
13+-- |
14+-- | `liftEff` can be used in any appropriate monad transformer stack to lift an action
15+-- | of type `Eff eff a` into the monad.
16+-- |
17+-- | Note that `MonadEff` is parameterized by the row of effects, so type inference can be
18+-- | tricky. It is generally recommended to either work with a polymorphic row of effects,
19+-- | or a concrete, closed row of effects such as `(trace :: Trace)`.
20+class (Monad m) <= MonadEff eff m where
21+ liftEff :: forall a. Eff eff a -> m a
22+
23+instance monadEffEff :: MonadEff eff (Eff eff) where
24+ liftEff = id
tests/support/flattened/Control-Monad-Eff-Console.jsnew file+18
@@ -0,0 +1,18 @@
1+/* global exports, console */
2+"use strict";
3+
4+// module Control.Monad.Eff.Console
5+
6+exports.log = function (s) {
7+ return function () {
8+ console.log(s);
9+ return {};
10+ };
11+};
12+
13+exports.error = function (s) {
14+ return function () {
15+ console.error(s);
16+ return {};
17+ };
18+};
tests/support/flattened/Control-Monad-Eff-Console.pursnew file+18
@@ -0,0 +1,18 @@
1+module Control.Monad.Eff.Console where
2+
3+import Prelude
4+
5+import Control.Monad.Eff
6+
7+-- | The `CONSOLE` effect represents those computations which write to the console.
8+foreign import data CONSOLE :: !
9+
10+-- | Write a message to the console.
11+foreign import log :: forall eff. String -> Eff (console :: CONSOLE | eff) Unit
12+
13+-- | Write an error to the console.
14+foreign import error :: forall eff. String -> Eff (console :: CONSOLE | eff) Unit
15+
16+-- | Write a value to the console, using its `Show` instance to produce a `String`.
17+print :: forall a eff. (Show a) => a -> Eff (console :: CONSOLE | eff) Unit
18+print = log <<< show
tests/support/flattened/Control-Monad-Eff-Unsafe.jsnew file+8
@@ -0,0 +1,8 @@
1+/* global exports */
2+"use strict";
3+
4+// module Control.Monad.Eff.Unsafe
5+
6+exports.unsafeInterleaveEff = function (f) {
7+ return f;
8+};
tests/support/flattened/Control-Monad-Eff-Unsafe.pursnew file+10
@@ -0,0 +1,10 @@
1+module Control.Monad.Eff.Unsafe where
2+
3+import Prelude
4+
5+import Control.Monad.Eff
6+
7+-- | Change the type of an effectful computation, allowing it to be run in another context.
8+-- |
9+-- | Note: use of this function can result in arbitrary side-effects.
10+foreign import unsafeInterleaveEff :: forall eff1 eff2 a. Eff eff1 a -> Eff eff2 a
tests/support/flattened/Control-Monad-Eff.jsnew file+62
@@ -0,0 +1,62 @@
1+/* global exports */
2+"use strict";
3+
4+// module Control.Monad.Eff
5+
6+exports.returnE = function (a) {
7+ return function () {
8+ return a;
9+ };
10+};
11+
12+exports.bindE = function (a) {
13+ return function (f) {
14+ return function () {
15+ return f(a())();
16+ };
17+ };
18+};
19+
20+exports.runPure = function (f) {
21+ return f();
22+};
23+
24+exports.untilE = function (f) {
25+ return function () {
26+ while (!f());
27+ return {};
28+ };
29+};
30+
31+exports.whileE = function (f) {
32+ return function (a) {
33+ return function () {
34+ while (f()) {
35+ a();
36+ }
37+ return {};
38+ };
39+ };
40+};
41+
42+exports.forE = function (lo) {
43+ return function (hi) {
44+ return function (f) {
45+ return function () {
46+ for (var i = lo; i < hi; i++) {
47+ f(i)();
48+ }
49+ };
50+ };
51+ };
52+};
53+
54+exports.foreachE = function (as) {
55+ return function (f) {
56+ return function () {
57+ for (var i = 0, l = as.length; i < l; i++) {
58+ f(as[i])();
59+ }
60+ };
61+ };
62+};
tests/support/flattened/Control-Monad-Eff.pursnew file+67
@@ -0,0 +1,67 @@
1+module Control.Monad.Eff
2+ ( Eff()
3+ , Pure()
4+ , runPure
5+ , untilE, whileE, forE, foreachE
6+ ) where
7+
8+import Prelude
9+
10+-- | The `Eff` type constructor is used to represent _native_ effects.
11+-- |
12+-- | See [Handling Native Effects with the Eff Monad](https://github.com/purescript/purescript/wiki/Handling-Native-Effects-with-the-Eff-Monad) for more details.
13+-- |
14+-- | The first type parameter is a row of effects which represents the contexts in which a computation can be run, and the second type parameter is the return type.
15+foreign import data Eff :: # ! -> * -> *
16+
17+foreign import returnE :: forall e a. a -> Eff e a
18+
19+foreign import bindE :: forall e a b. Eff e a -> (a -> Eff e b) -> Eff e b
20+
21+-- | The `Pure` type synonym represents _pure_ computations, i.e. ones in which all effects have been handled.
22+-- |
23+-- | The `runPure` function can be used to run pure computations and obtain their result.
24+type Pure a = forall e. Eff e a
25+
26+-- | Run a pure computation and return its result.
27+-- |
28+-- | Note: since this function has a rank-2 type, it may cause problems to apply this function using the `$` operator. The recommended approach
29+-- | is to use parentheses instead.
30+foreign import runPure :: forall a. Pure a -> a
31+
32+instance functorEff :: Functor (Eff e) where
33+ map = liftA1
34+
35+instance applyEff :: Apply (Eff e) where
36+ apply = ap
37+
38+instance applicativeEff :: Applicative (Eff e) where
39+ pure = returnE
40+
41+instance bindEff :: Bind (Eff e) where
42+ bind = bindE
43+
44+instance monadEff :: Monad (Eff e)
45+
46+-- | Loop until a condition becomes `true`.
47+-- |
48+-- | `untilE b` is an effectful computation which repeatedly runs the effectful computation `b`,
49+-- | until its return value is `true`.
50+foreign import untilE :: forall e. Eff e Boolean -> Eff e Unit
51+
52+-- | Loop while a condition is `true`.
53+-- |
54+-- | `whileE b m` is effectful computation which runs the effectful computation `b`. If its result is
55+-- | `true`, it runs the effectful computation `m` and loops. If not, the computation ends.
56+foreign import whileE :: forall e a. Eff e Boolean -> Eff e a -> Eff e Unit
57+
58+-- | Loop over a consecutive collection of numbers.
59+-- |
60+-- | `forE lo hi f` runs the computation returned by the function `f` for each of the inputs
61+-- | between `lo` (inclusive) and `hi` (exclusive).
62+foreign import forE :: forall e. Number -> Number -> (Number -> Eff e Unit) -> Eff e Unit
63+
64+-- | Loop over an array of values.
65+-- |
66+-- | `foreach xs f` runs the computation returned by the function `f` for each of the inputs `xs`.
67+foreign import foreachE :: forall e a. Array a -> (a -> Eff e Unit) -> Eff e Unit
tests/support/flattened/Control-Monad-ST.jsnew file+38
@@ -0,0 +1,38 @@
1+/* global exports */
2+"use strict";
3+
4+// module Control.Monad.ST
5+
6+exports.newSTRef = function (val) {
7+ return function () {
8+ return { value: val };
9+ };
10+};
11+
12+exports.readSTRef = function (ref) {
13+ return function () {
14+ return ref.value;
15+ };
16+};
17+
18+exports.modifySTRef = function (ref) {
19+ return function (f) {
20+ return function () {
21+ /* jshint boss: true */
22+ return ref.value = f(ref.value);
23+ };
24+ };
25+};
26+
27+exports.writeSTRef = function (ref) {
28+ return function (a) {
29+ return function () {
30+ /* jshint boss: true */
31+ return ref.value = a;
32+ };
33+ };
34+};
35+
36+exports.runST = function (f) {
37+ return f;
38+};
tests/support/flattened/Control-Monad-ST.pursnew file+42
@@ -0,0 +1,42 @@
1+module Control.Monad.ST where
2+
3+import Prelude
4+
5+import Control.Monad.Eff (Eff(), runPure)
6+
7+-- | The `ST` effect represents _local mutation_, i.e. mutation which does not "escape" into the surrounding computation.
8+-- |
9+-- | An `ST` computation is parameterized by a phantom type which is used to restrict the set of reference cells it is allowed to access.
10+-- |
11+-- | The `runST` function can be used to handle the `ST` effect.
12+foreign import data ST :: * -> !
13+
14+-- | The type `STRef s a` represents a mutable reference holding a value of type `a`, which can be used with the `ST s` effect.
15+foreign import data STRef :: * -> * -> *
16+
17+-- | Create a new mutable reference.
18+foreign import newSTRef :: forall a h r. a -> Eff (st :: ST h | r) (STRef h a)
19+
20+-- | Read the current value of a mutable reference.
21+foreign import readSTRef :: forall a h r. STRef h a -> Eff (st :: ST h | r) a
22+
23+-- | Modify the value of a mutable reference by applying a function to the current value.
24+foreign import modifySTRef :: forall a h r. STRef h a -> (a -> a) -> Eff (st :: ST h | r) a
25+
26+-- | Set the value of a mutable reference.
27+foreign import writeSTRef :: forall a h r. STRef h a -> a -> Eff (st :: ST h | r) a
28+
29+-- | Run an `ST` computation.
30+-- |
31+-- | Note: the type of `runST` uses a rank-2 type to constrain the phantom type `s`, such that the computation must not leak any mutable references
32+-- | to the surrounding computation.
33+-- |
34+-- | It may cause problems to apply this function using the `$` operator. The recommended approach is to use parentheses instead.
35+foreign import runST :: forall a r. (forall h. Eff (st :: ST h | r) a) -> Eff r a
36+
37+-- | A convenience function which combines `runST` with `runPure`, which can be used when the only required effect is `ST`.
38+-- |
39+-- | Note: since this function has a rank-2 type, it may cause problems to apply this function using the `$` operator. The recommended approach
40+-- | is to use parentheses instead.
41+pureST :: forall a. (forall h r. Eff (st :: ST h | r) a) -> a
42+pureST st = runPure (runST st)
tests/support/flattened/Data-Function.jsnew file+233
@@ -0,0 +1,233 @@
1+/* global exports */
2+"use strict";
3+
4+// module Data.Function
5+
6+exports.mkFn0 = function (fn) {
7+ return function () {
8+ return fn({});
9+ };
10+};
11+
12+exports.mkFn1 = function (fn) {
13+ return function (a) {
14+ return fn(a);
15+ };
16+};
17+
18+exports.mkFn2 = function (fn) {
19+ /* jshint maxparams: 2 */
20+ return function (a, b) {
21+ return fn(a)(b);
22+ };
23+};
24+
25+exports.mkFn3 = function (fn) {
26+ /* jshint maxparams: 3 */
27+ return function (a, b, c) {
28+ return fn(a)(b)(c);
29+ };
30+};
31+
32+exports.mkFn4 = function (fn) {
33+ /* jshint maxparams: 4 */
34+ return function (a, b, c, d) {
35+ return fn(a)(b)(c)(d);
36+ };
37+};
38+
39+exports.mkFn5 = function (fn) {
40+ /* jshint maxparams: 5 */
41+ return function (a, b, c, d, e) {
42+ return fn(a)(b)(c)(d)(e);
43+ };
44+};
45+
46+exports.mkFn6 = function (fn) {
47+ /* jshint maxparams: 6 */
48+ return function (a, b, c, d, e, f) {
49+ return fn(a)(b)(c)(d)(e)(f);
50+ };
51+};
52+
53+exports.mkFn7 = function (fn) {
54+ /* jshint maxparams: 7 */
55+ return function (a, b, c, d, e, f, g) {
56+ return fn(a)(b)(c)(d)(e)(f)(g);
57+ };
58+};
59+
60+exports.mkFn8 = function (fn) {
61+ /* jshint maxparams: 8 */
62+ return function (a, b, c, d, e, f, g, h) {
63+ return fn(a)(b)(c)(d)(e)(f)(g)(h);
64+ };
65+};
66+
67+exports.mkFn9 = function (fn) {
68+ /* jshint maxparams: 9 */
69+ return function (a, b, c, d, e, f, g, h, i) {
70+ return fn(a)(b)(c)(d)(e)(f)(g)(h)(i);
71+ };
72+};
73+
74+exports.mkFn10 = function (fn) {
75+ /* jshint maxparams: 10 */
76+ return function (a, b, c, d, e, f, g, h, i, j) {
77+ return fn(a)(b)(c)(d)(e)(f)(g)(h)(i)(j);
78+ };
79+};
80+
81+exports.runFn0 = function (fn) {
82+ return fn();
83+};
84+
85+exports.runFn1 = function (fn) {
86+ return function (a) {
87+ return fn(a);
88+ };
89+};
90+
91+exports.runFn2 = function (fn) {
92+ return function (a) {
93+ return function (b) {
94+ return fn(a, b);
95+ };
96+ };
97+};
98+
99+exports.runFn3 = function (fn) {
100+ return function (a) {
101+ return function (b) {
102+ return function (c) {
103+ return fn(a, b, c);
104+ };
105+ };
106+ };
107+};
108+
109+exports.runFn4 = function (fn) {
110+ return function (a) {
111+ return function (b) {
112+ return function (c) {
113+ return function (d) {
114+ return fn(a, b, c, d);
115+ };
116+ };
117+ };
118+ };
119+};
120+
121+exports.runFn5 = function (fn) {
122+ return function (a) {
123+ return function (b) {
124+ return function (c) {
125+ return function (d) {
126+ return function (e) {
127+ return fn(a, b, c, d, e);
128+ };
129+ };
130+ };
131+ };
132+ };
133+};
134+
135+exports.runFn6 = function (fn) {
136+ return function (a) {
137+ return function (b) {
138+ return function (c) {
139+ return function (d) {
140+ return function (e) {
141+ return function (f) {
142+ return fn(a, b, c, d, e, f);
143+ };
144+ };
145+ };
146+ };
147+ };
148+ };
149+};
150+
151+exports.runFn7 = function (fn) {
152+ return function (a) {
153+ return function (b) {
154+ return function (c) {
155+ return function (d) {
156+ return function (e) {
157+ return function (f) {
158+ return function (g) {
159+ return fn(a, b, c, d, e, f, g);
160+ };
161+ };
162+ };
163+ };
164+ };
165+ };
166+ };
167+};
168+
169+exports.runFn8 = function (fn) {
170+ return function (a) {
171+ return function (b) {
172+ return function (c) {
173+ return function (d) {
174+ return function (e) {
175+ return function (f) {
176+ return function (g) {
177+ return function (h) {
178+ return fn(a, b, c, d, e, f, g, h);
179+ };
180+ };
181+ };
182+ };
183+ };
184+ };
185+ };
186+ };
187+};
188+
189+exports.runFn9 = function (fn) {
190+ return function (a) {
191+ return function (b) {
192+ return function (c) {
193+ return function (d) {
194+ return function (e) {
195+ return function (f) {
196+ return function (g) {
197+ return function (h) {
198+ return function (i) {
199+ return fn(a, b, c, d, e, f, g, h, i);
200+ };
201+ };
202+ };
203+ };
204+ };
205+ };
206+ };
207+ };
208+ };
209+};
210+
211+exports.runFn10 = function (fn) {
212+ return function (a) {
213+ return function (b) {
214+ return function (c) {
215+ return function (d) {
216+ return function (e) {
217+ return function (f) {
218+ return function (g) {
219+ return function (h) {
220+ return function (i) {
221+ return function (j) {
222+ return fn(a, b, c, d, e, f, g, h, i, j);
223+ };
224+ };
225+ };
226+ };
227+ };
228+ };
229+ };
230+ };
231+ };
232+ };
233+};
tests/support/flattened/Data-Function.pursnew file+113
@@ -0,0 +1,113 @@
1+module Data.Function where
2+
3+import Prelude
4+
5+-- | The `on` function is used to change the domain of a binary operator.
6+-- |
7+-- | For example, we can create a function which compares two records based on the values of their `x` properties:
8+-- |
9+-- | ```purescript
10+-- | compareX :: forall r. { x :: Number | r } -> { x :: Number | r } -> Ordering
11+-- | compareX = compare `on` _.x
12+-- | ```
13+on :: forall a b c. (b -> b -> c) -> (a -> b) -> a -> a -> c
14+on f g x y = g x `f` g y
15+
16+-- | A function of zero arguments
17+foreign import data Fn0 :: * -> *
18+
19+-- | A function of one argument
20+foreign import data Fn1 :: * -> * -> *
21+
22+-- | A function of two arguments
23+foreign import data Fn2 :: * -> * -> * -> *
24+
25+-- | A function of three arguments
26+foreign import data Fn3 :: * -> * -> * -> * -> *
27+
28+-- | A function of four arguments
29+foreign import data Fn4 :: * -> * -> * -> * -> * -> *
30+
31+-- | A function of five arguments
32+foreign import data Fn5 :: * -> * -> * -> * -> * -> * -> *
33+
34+-- | A function of six arguments
35+foreign import data Fn6 :: * -> * -> * -> * -> * -> * -> * -> *
36+
37+-- | A function of seven arguments
38+foreign import data Fn7 :: * -> * -> * -> * -> * -> * -> * -> * -> *
39+
40+-- | A function of eight arguments
41+foreign import data Fn8 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> *
42+
43+-- | A function of nine arguments
44+foreign import data Fn9 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
45+
46+-- | A function of ten arguments
47+foreign import data Fn10 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> *
48+
49+-- | Create a function of no arguments
50+foreign import mkFn0 :: forall a. (Unit -> a) -> Fn0 a
51+
52+-- | Create a function of one argument
53+foreign import mkFn1 :: forall a b. (a -> b) -> Fn1 a b
54+
55+-- | Create a function of two arguments from a curried function
56+foreign import mkFn2 :: forall a b c. (a -> b -> c) -> Fn2 a b c
57+
58+-- | Create a function of three arguments from a curried function
59+foreign import mkFn3 :: forall a b c d. (a -> b -> c -> d) -> Fn3 a b c d
60+
61+-- | Create a function of four arguments from a curried function
62+foreign import mkFn4 :: forall a b c d e. (a -> b -> c -> d -> e) -> Fn4 a b c d e
63+
64+-- | Create a function of five arguments from a curried function
65+foreign import mkFn5 :: forall a b c d e f. (a -> b -> c -> d -> e -> f) -> Fn5 a b c d e f
66+
67+-- | Create a function of six arguments from a curried function
68+foreign import mkFn6 :: forall a b c d e f g. (a -> b -> c -> d -> e -> f -> g) -> Fn6 a b c d e f g
69+
70+-- | Create a function of seven arguments from a curried function
71+foreign import mkFn7 :: forall a b c d e f g h. (a -> b -> c -> d -> e -> f -> g -> h) -> Fn7 a b c d e f g h
72+
73+-- | Create a function of eight arguments from a curried function
74+foreign import mkFn8 :: forall a b c d e f g h i. (a -> b -> c -> d -> e -> f -> g -> h -> i) -> Fn8 a b c d e f g h i
75+
76+-- | Create a function of nine arguments from a curried function
77+foreign import mkFn9 :: forall a b c d e f g h i j. (a -> b -> c -> d -> e -> f -> g -> h -> i -> j) -> Fn9 a b c d e f g h i j
78+
79+-- | Create a function of ten arguments from a curried function
80+foreign import mkFn10 :: forall a b c d e f g h i j k. (a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k) -> Fn10 a b c d e f g h i j k
81+
82+-- | Apply a function of no arguments
83+foreign import runFn0 :: forall a. Fn0 a -> a
84+
85+-- | Apply a function of one argument
86+foreign import runFn1 :: forall a b. Fn1 a b -> a -> b
87+
88+-- | Apply a function of two arguments
89+foreign import runFn2 :: forall a b c. Fn2 a b c -> a -> b -> c
90+
91+-- | Apply a function of three arguments
92+foreign import runFn3 :: forall a b c d. Fn3 a b c d -> a -> b -> c -> d
93+
94+-- | Apply a function of four arguments
95+foreign import runFn4 :: forall a b c d e. Fn4 a b c d e -> a -> b -> c -> d -> e
96+
97+-- | Apply a function of five arguments
98+foreign import runFn5 :: forall a b c d e f. Fn5 a b c d e f -> a -> b -> c -> d -> e -> f
99+
100+-- | Apply a function of six arguments
101+foreign import runFn6 :: forall a b c d e f g. Fn6 a b c d e f g -> a -> b -> c -> d -> e -> f -> g
102+
103+-- | Apply a function of seven arguments
104+foreign import runFn7 :: forall a b c d e f g h. Fn7 a b c d e f g h -> a -> b -> c -> d -> e -> f -> g -> h
105+
106+-- | Apply a function of eight arguments
107+foreign import runFn8 :: forall a b c d e f g h i. Fn8 a b c d e f g h i -> a -> b -> c -> d -> e -> f -> g -> h -> i
108+
109+-- | Apply a function of nine arguments
110+foreign import runFn9 :: forall a b c d e f g h i j. Fn9 a b c d e f g h i j -> a -> b -> c -> d -> e -> f -> g -> h -> i -> j
111+
112+-- | Apply a function of ten arguments
113+foreign import runFn10 :: forall a b c d e f g h i j k. Fn10 a b c d e f g h i j k -> a -> b -> c -> d -> e -> f -> g -> h -> i -> j -> k
tests/support/flattened/Prelude.jsnew file+228
@@ -0,0 +1,228 @@
1+/* global exports */
2+"use strict";
3+
4+// module Prelude
5+
6+//- Functor --------------------------------------------------------------------
7+
8+exports.arrayMap = function (f) {
9+ return function (arr) {
10+ var l = arr.length;
11+ var result = new Array(l);
12+ for (var i = 0; i < l; i++) {
13+ result[i] = f(arr[i]);
14+ }
15+ return result;
16+ };
17+};
18+
19+//- Bind -----------------------------------------------------------------------
20+
21+exports.arrayBind = function (arr) {
22+ return function (f) {
23+ var result = [];
24+ for (var i = 0, l = arr.length; i < l; i++) {
25+ Array.prototype.push.apply(result, f(arr[i]));
26+ }
27+ return result;
28+ };
29+};
30+
31+//- Monoid ---------------------------------------------------------------------
32+
33+exports.concatString = function (s1) {
34+ return function (s2) {
35+ return s1 + s2;
36+ };
37+};
38+
39+exports.concatArray = function (xs) {
40+ return function (ys) {
41+ return xs.concat(ys);
42+ };
43+};
44+
45+//- Semiring -------------------------------------------------------------------
46+
47+exports.intAdd = function (x) {
48+ return function (y) {
49+ /* jshint bitwise: false */
50+ return x + y | 0;
51+ };
52+};
53+
54+exports.intMul = function (x) {
55+ return function (y) {
56+ /* jshint bitwise: false */
57+ return x * y | 0;
58+ };
59+};
60+
61+exports.numAdd = function (n1) {
62+ return function (n2) {
63+ return n1 + n2;
64+ };
65+};
66+
67+exports.numMul = function (n1) {
68+ return function (n2) {
69+ return n1 * n2;
70+ };
71+};
72+
73+//- ModuloSemiring -------------------------------------------------------------
74+
75+exports.intDiv = function (x) {
76+ return function (y) {
77+ /* jshint bitwise: false */
78+ return x / y | 0;
79+ };
80+};
81+
82+exports.intMod = function (x) {
83+ return function (y) {
84+ return x % y;
85+ };
86+};
87+
88+exports.numDiv = function (n1) {
89+ return function (n2) {
90+ return n1 / n2;
91+ };
92+};
93+
94+//- Ring -----------------------------------------------------------------------
95+
96+exports.intSub = function (x) {
97+ return function (y) {
98+ /* jshint bitwise: false */
99+ return x - y | 0;
100+ };
101+};
102+
103+exports.numSub = function (n1) {
104+ return function (n2) {
105+ return n1 - n2;
106+ };
107+};
108+
109+//- Eq -------------------------------------------------------------------------
110+
111+exports.refEq = function (r1) {
112+ return function (r2) {
113+ return r1 === r2;
114+ };
115+};
116+
117+exports.refIneq = function (r1) {
118+ return function (r2) {
119+ return r1 !== r2;
120+ };
121+};
122+
123+exports.eqArrayImpl = function (f) {
124+ return function (xs) {
125+ return function (ys) {
126+ if (xs.length !== ys.length) return false;
127+ for (var i = 0; i < xs.length; i++) {
128+ if (!f(xs[i])(ys[i])) return false;
129+ }
130+ return true;
131+ };
132+ };
133+};
134+
135+exports.ordArrayImpl = function (f) {
136+ return function (xs) {
137+ return function (ys) {
138+ var i = 0;
139+ var xlen = xs.length;
140+ var ylen = ys.length;
141+ while (i < xlen && i < ylen) {
142+ var x = xs[i];
143+ var y = ys[i];
144+ var o = f(x)(y);
145+ if (o !== 0) {
146+ return o;
147+ }
148+ i++;
149+ }
150+ if (xlen === ylen) {
151+ return 0;
152+ } else if (xlen > ylen) {
153+ return -1;
154+ } else {
155+ return 1;
156+ }
157+ };
158+ };
159+};
160+
161+//- Ord ------------------------------------------------------------------------
162+
163+exports.unsafeCompareImpl = function (lt) {
164+ return function (eq) {
165+ return function (gt) {
166+ return function (x) {
167+ return function (y) {
168+ return x < y ? lt : x > y ? gt : eq;
169+ };
170+ };
171+ };
172+ };
173+};
174+
175+//- Bounded --------------------------------------------------------------------
176+
177+exports.topInt = 2147483647;
178+exports.bottomInt = -2147483648;
179+
180+exports.topChar = String.fromCharCode(65535);
181+exports.bottomChar = String.fromCharCode(0);
182+
183+//- BooleanAlgebra -------------------------------------------------------------
184+
185+exports.boolOr = function (b1) {
186+ return function (b2) {
187+ return b1 || b2;
188+ };
189+};
190+
191+exports.boolAnd = function (b1) {
192+ return function (b2) {
193+ return b1 && b2;
194+ };
195+};
196+
197+exports.boolNot = function (b) {
198+ return !b;
199+};
200+
201+//- Show -----------------------------------------------------------------------
202+
203+exports.showIntImpl = function (n) {
204+ return n.toString();
205+};
206+
207+exports.showNumberImpl = function (n) {
208+ /* jshint bitwise: false */
209+ return n === (n | 0) ? n + ".0" : n.toString();
210+};
211+
212+exports.showCharImpl = function (c) {
213+ return c === "'" ? "'\\''" : "'" + c + "'";
214+};
215+
216+exports.showStringImpl = function (s) {
217+ return JSON.stringify(s);
218+};
219+
220+exports.showArrayImpl = function (f) {
221+ return function (xs) {
222+ var ss = [];
223+ for (var i = 0, l = xs.length; i < l; i++) {
224+ ss[i] = f(xs[i]);
225+ }
226+ return "[" + ss.join(",") + "]";
227+ };
228+};
tests/support/flattened/Prelude.pursnew file+872
@@ -0,0 +1,872 @@
1+module Prelude
2+ ( Unit(), unit
3+ , ($), (#)
4+ , flip
5+ , const
6+ , asTypeOf
7+ , otherwise
8+ , Semigroupoid, compose, (<<<), (>>>)
9+ , Category, id
10+ , Functor, map, (<$>), (<#>), void
11+ , Apply, apply, (<*>)
12+ , Applicative, pure, liftA1
13+ , Bind, bind, (>>=)
14+ , Monad, return, liftM1, ap
15+ , Semigroup, append, (<>), (++)
16+ , Semiring, add, zero, mul, one, (+), (*)
17+ , ModuloSemiring, div, mod, (/)
18+ , Ring, sub, negate, (-)
19+ , Num
20+ , DivisionRing
21+ , Eq, eq, (==), (/=)
22+ , Ordering(..), Ord, compare, (<), (>), (<=), (>=)
23+ , unsafeCompare
24+ , Bounded, top, bottom
25+ , BoundedOrd
26+ , BooleanAlgebra, conj, disj, not, (&&), (||)
27+ , Show, show
28+ ) where
29+
30+-- | The `Unit` type has a single inhabitant, called `unit`. It represents
31+-- | values with no computational content.
32+-- |
33+-- | `Unit` is often used, wrapped in a monadic type constructor, as the
34+-- | return type of a computation where only
35+-- | the _effects_ are important.
36+newtype Unit = Unit {}
37+
38+-- | `unit` is the sole inhabitant of the `Unit` type.
39+unit :: Unit
40+unit = Unit {}
41+
42+infixr 0 $
43+infixl 1 #
44+
45+-- | Applies a function to its argument.
46+-- |
47+-- | ```purescript
48+-- | length $ groupBy productCategory $ filter isInStock $ products
49+-- | ```
50+-- |
51+-- | is equivalent to:
52+-- |
53+-- | ```purescript
54+-- | length (groupBy productCategory (filter isInStock products))
55+-- | ```
56+-- |
57+-- | `($)` is different from [`(#)`](#-2) because it is right-infix instead of
58+-- | left: `a $ b $ c $ d x = a $ (b $ (c $ (d $ x))) = a (b (c (d x)))`
59+($) :: forall a b. (a -> b) -> a -> b
60+($) f x = f x
61+
62+-- | Applies an argument to a function.
63+-- |
64+-- | ```purescript
65+-- | products # filter isInStock # groupBy productCategory # length
66+-- | ```
67+-- |
68+-- | is equivalent to:
69+-- |
70+-- | ```purescript
71+-- | length (groupBy productCategory (filter isInStock products))
72+-- | ```
73+-- |
74+-- | `(#)` is different from [`($)`](#-1) because it is left-infix instead of
75+-- | right: `x # a # b # c # d = (((x # a) # b) # c) # d = d (c (b (a x)))`
76+(#) :: forall a b. a -> (a -> b) -> b
77+(#) x f = f x
78+
79+-- | Flips the order of the arguments to a function of two arguments.
80+-- |
81+-- | ```purescript
82+-- | flip const 1 2 = const 2 1 = 2
83+-- | ```
84+flip :: forall a b c. (a -> b -> c) -> b -> a -> c
85+flip f b a = f a b
86+
87+-- | Returns its first argument and ignores its second.
88+-- |
89+-- | ```purescript
90+-- | const 1 "hello" = 1
91+-- | ```
92+const :: forall a b. a -> b -> a
93+const a _ = a
94+
95+-- | This function returns its first argument, and can be used to assert type
96+-- | equalities. This can be useful when types are otherwise ambiguous.
97+-- |
98+-- | ```purescript
99+-- | main = print $ [] `asTypeOf` [0]
100+-- | ```
101+-- |
102+-- | If instead, we had written `main = print []`, the type of the argument
103+-- | `[]` would have been ambiguous, resulting in a compile-time error.
104+asTypeOf :: forall a. a -> a -> a
105+asTypeOf x _ = x
106+
107+-- | An alias for `true`, which can be useful in guard clauses:
108+-- |
109+-- | ```purescript
110+-- | max x y | x >= y = x
111+-- | | otherwise = y
112+-- | ```
113+otherwise :: Boolean
114+otherwise = true
115+
116+-- | A `Semigroupoid` is similar to a [`Category`](#category) but does not
117+-- | require an identity element `id`, just composable morphisms.
118+-- |
119+-- | `Semigroupoid`s must satisfy the following law:
120+-- |
121+-- | - Associativity: `p <<< (q <<< r) = (p <<< q) <<< r`
122+-- |
123+-- | One example of a `Semigroupoid` is the function type constructor `(->)`,
124+-- | with `(<<<)` defined as function composition.
125+class Semigroupoid a where
126+ compose :: forall b c d. a c d -> a b c -> a b d
127+
128+instance semigroupoidFn :: Semigroupoid (->) where
129+ compose f g x = f (g x)
130+
131+infixr 9 >>>
132+infixr 9 <<<
133+
134+-- | `(<<<)` is an alias for `compose`.
135+(<<<) :: forall a b c d. (Semigroupoid a) => a c d -> a b c -> a b d
136+(<<<) = compose
137+
138+-- | Forwards composition, or `(<<<)` with its arguments reversed.
139+(>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d
140+(>>>) = flip compose
141+
142+-- | `Category`s consist of objects and composable morphisms between them, and
143+-- | as such are [`Semigroupoids`](#semigroupoid), but unlike `semigroupoids`
144+-- | must have an identity element.
145+-- |
146+-- | Instances must satisfy the following law in addition to the
147+-- | `Semigroupoid` law:
148+-- |
149+-- | - Identity: `id <<< p = p <<< id = p`
150+class (Semigroupoid a) <= Category a where
151+ id :: forall t. a t t
152+
153+instance categoryFn :: Category (->) where
154+ id x = x
155+
156+-- | A `Functor` is a type constructor which supports a mapping operation
157+-- | `(<$>)`.
158+-- |
159+-- | `(<$>)` can be used to turn functions `a -> b` into functions
160+-- | `f a -> f b` whose argument and return types use the type constructor `f`
161+-- | to represent some computational context.
162+-- |
163+-- | Instances must satisfy the following laws:
164+-- |
165+-- | - Identity: `(<$>) id = id`
166+-- | - Composition: `(<$>) (f <<< g) = (f <$>) <<< (g <$>)`
167+class Functor f where
168+ map :: forall a b. (a -> b) -> f a -> f b
169+
170+instance functorFn :: Functor ((->) r) where
171+ map = compose
172+
173+instance functorArray :: Functor Array where
174+ map = arrayMap
175+
176+foreign import arrayMap :: forall a b. (a -> b) -> Array a -> Array b
177+
178+infixl 4 <$>
179+infixl 1 <#>
180+
181+-- | `(<$>)` is an alias for `map`
182+(<$>) :: forall f a b. (Functor f) => (a -> b) -> f a -> f b
183+(<$>) = map
184+
185+-- | `(<#>)` is `(<$>)` with its arguments reversed. For example:
186+-- |
187+-- | ```purescript
188+-- | [1, 2, 3] <#> \n -> n * n
189+-- | ```
190+(<#>) :: forall f a b. (Functor f) => f a -> (a -> b) -> f b
191+(<#>) fa f = f <$> fa
192+
193+-- | The `void` function is used to ignore the type wrapped by a
194+-- | [`Functor`](#functor), replacing it with `Unit` and keeping only the type
195+-- | information provided by the type constructor itself.
196+-- |
197+-- | `void` is often useful when using `do` notation to change the return type
198+-- | of a monadic computation:
199+-- |
200+-- | ```purescript
201+-- | main = forE 1 10 \n -> void do
202+-- | print n
203+-- | print (n * n)
204+-- | ```
205+void :: forall f a. (Functor f) => f a -> f Unit
206+void fa = const unit <$> fa
207+
208+-- | The `Apply` class provides the `(<*>)` which is used to apply a function
209+-- | to an argument under a type constructor.
210+-- |
211+-- | `Apply` can be used to lift functions of two or more arguments to work on
212+-- | values wrapped with the type constructor `f`. It might also be understood
213+-- | in terms of the `lift2` function:
214+-- |
215+-- | ```purescript
216+-- | lift2 :: forall f a b c. (Apply f) => (a -> b -> c) -> f a -> f b -> f c
217+-- | lift2 f a b = f <$> a <*> b
218+-- | ```
219+-- |
220+-- | `(<*>)` is recovered from `lift2` as `lift2 ($)`. That is, `(<*>)` lifts
221+-- | the function application operator `($)` to arguments wrapped with the
222+-- | type constructor `f`.
223+-- |
224+-- | Instances must satisfy the following law in addition to the `Functor`
225+-- | laws:
226+-- |
227+-- | - Associative composition: `(<<<) <$> f <*> g <*> h = f <*> (g <*> h)`
228+-- |
229+-- | Formally, `Apply` represents a strong lax semi-monoidal endofunctor.
230+class (Functor f) <= Apply f where
231+ apply :: forall a b. f (a -> b) -> f a -> f b
232+
233+instance applyFn :: Apply ((->) r) where
234+ apply f g x = f x (g x)
235+
236+instance applyArray :: Apply Array where
237+ apply = ap
238+
239+infixl 4 <*>
240+
241+-- | `(<*>)` is an alias for `apply`.
242+(<*>) :: forall f a b. (Apply f) => f (a -> b) -> f a -> f b
243+(<*>) = apply
244+
245+-- | The `Applicative` type class extends the [`Apply`](#apply) type class
246+-- | with a `pure` function, which can be used to create values of type `f a`
247+-- | from values of type `a`.
248+-- |
249+-- | Where [`Apply`](#apply) provides the ability to lift functions of two or
250+-- | more arguments to functions whose arguments are wrapped using `f`, and
251+-- | [`Functor`](#functor) provides the ability to lift functions of one
252+-- | argument, `pure` can be seen as the function which lifts functions of
253+-- | _zero_ arguments. That is, `Applicative` functors support a lifting
254+-- | operation for any number of function arguments.
255+-- |
256+-- | Instances must satisfy the following laws in addition to the `Apply`
257+-- | laws:
258+-- |
259+-- | - Identity: `(pure id) <*> v = v`
260+-- | - Composition: `(pure <<<) <*> f <*> g <*> h = f <*> (g <*> h)`
261+-- | - Homomorphism: `(pure f) <*> (pure x) = pure (f x)`
262+-- | - Interchange: `u <*> (pure y) = (pure ($ y)) <*> u`
263+class (Apply f) <= Applicative f where
264+ pure :: forall a. a -> f a
265+
266+instance applicativeFn :: Applicative ((->) r) where
267+ pure = const
268+
269+instance applicativeArray :: Applicative Array where
270+ pure x = [x]
271+
272+-- | `return` is an alias for `pure`.
273+return :: forall m a. (Applicative m) => a -> m a
274+return = pure
275+
276+-- | `liftA1` provides a default implementation of `(<$>)` for any
277+-- | [`Applicative`](#applicative) functor, without using `(<$>)` as provided
278+-- | by the [`Functor`](#functor)-[`Applicative`](#applicative) superclass
279+-- | relationship.
280+-- |
281+-- | `liftA1` can therefore be used to write [`Functor`](#functor) instances
282+-- | as follows:
283+-- |
284+-- | ```purescript
285+-- | instance functorF :: Functor F where
286+-- | map = liftA1
287+-- | ```
288+liftA1 :: forall f a b. (Applicative f) => (a -> b) -> f a -> f b
289+liftA1 f a = pure f <*> a
290+
291+-- | The `Bind` type class extends the [`Apply`](#apply) type class with a
292+-- | "bind" operation `(>>=)` which composes computations in sequence, using
293+-- | the return value of one computation to determine the next computation.
294+-- |
295+-- | The `>>=` operator can also be expressed using `do` notation, as follows:
296+-- |
297+-- | ```purescript
298+-- | x >>= f = do y <- x
299+-- | f y
300+-- | ```
301+-- |
302+-- | where the function argument of `f` is given the name `y`.
303+-- |
304+-- | Instances must satisfy the following law in addition to the `Apply`
305+-- | laws:
306+-- |
307+-- | - Associativity: `(x >>= f) >>= g = x >>= (\k => f k >>= g)`
308+-- |
309+-- | Associativity tells us that we can regroup operations which use `do`
310+-- | notation so that we can unambiguously write, for example:
311+-- |
312+-- | ```purescript
313+-- | do x <- m1
314+-- | y <- m2 x
315+-- | m3 x y
316+-- | ```
317+class (Apply m) <= Bind m where
318+ bind :: forall a b. m a -> (a -> m b) -> m b
319+
320+instance bindFn :: Bind ((->) r) where
321+ bind m f x = f (m x) x
322+
323+instance bindArray :: Bind Array where
324+ bind = arrayBind
325+
326+foreign import arrayBind :: forall a b. Array a -> (a -> Array b) -> Array b
327+
328+infixl 1 >>=
329+
330+-- | `(>>=)` is an alias for `bind`.
331+(>>=) :: forall m a b. (Bind m) => m a -> (a -> m b) -> m b
332+(>>=) = bind
333+
334+-- | The `Monad` type class combines the operations of the `Bind` and
335+-- | `Applicative` type classes. Therefore, `Monad` instances represent type
336+-- | constructors which support sequential composition, and also lifting of
337+-- | functions of arbitrary arity.
338+-- |
339+-- | Instances must satisfy the following laws in addition to the
340+-- | `Applicative` and `Bind` laws:
341+-- |
342+-- | - Left Identity: `pure x >>= f = f x`
343+-- | - Right Identity: `x >>= pure = x`
344+class (Applicative m, Bind m) <= Monad m
345+
346+instance monadFn :: Monad ((->) r)
347+instance monadArray :: Monad Array
348+
349+-- | `liftM1` provides a default implementation of `(<$>)` for any
350+-- | [`Monad`](#monad), without using `(<$>)` as provided by the
351+-- | [`Functor`](#functor)-[`Monad`](#monad) superclass relationship.
352+-- |
353+-- | `liftM1` can therefore be used to write [`Functor`](#functor) instances
354+-- | as follows:
355+-- |
356+-- | ```purescript
357+-- | instance functorF :: Functor F where
358+-- | map = liftM1
359+-- | ```
360+liftM1 :: forall m a b. (Monad m) => (a -> b) -> m a -> m b
361+liftM1 f a = do
362+ a' <- a
363+ return (f a')
364+
365+-- | `ap` provides a default implementation of `(<*>)` for any
366+-- | [`Monad`](#monad), without using `(<*>)` as provided by the
367+-- | [`Apply`](#apply)-[`Monad`](#monad) superclass relationship.
368+-- |
369+-- | `ap` can therefore be used to write [`Apply`](#apply) instances as
370+-- | follows:
371+-- |
372+-- | ```purescript
373+-- | instance applyF :: Apply F where
374+-- | apply = ap
375+-- | ```
376+ap :: forall m a b. (Monad m) => m (a -> b) -> m a -> m b
377+ap f a = do
378+ f' <- f
379+ a' <- a
380+ return (f' a')
381+
382+-- | The `Semigroup` type class identifies an associative operation on a type.
383+-- |
384+-- | Instances are required to satisfy the following law:
385+-- |
386+-- | - Associativity: `(x <> y) <> z = x <> (y <> z)`
387+-- |
388+-- | One example of a `Semigroup` is `String`, with `(<>)` defined as string
389+-- | concatenation.
390+class Semigroup a where
391+ append :: a -> a -> a
392+
393+infixr 5 <>
394+infixr 5 ++
395+
396+-- | `(<>)` is an alias for `append`.
397+(<>) :: forall s. (Semigroup s) => s -> s -> s
398+(<>) = append
399+
400+-- | `(++)` is an alternative alias for `append`.
401+(++) :: forall s. (Semigroup s) => s -> s -> s
402+(++) = append
403+
404+instance semigroupString :: Semigroup String where
405+ append = concatString
406+
407+instance semigroupUnit :: Semigroup Unit where
408+ append _ _ = unit
409+
410+instance semigroupFn :: (Semigroup s') => Semigroup (s -> s') where
411+ append f g = \x -> f x <> g x
412+
413+instance semigroupOrdering :: Semigroup Ordering where
414+ append LT _ = LT
415+ append GT _ = GT
416+ append EQ y = y
417+
418+instance semigroupArray :: Semigroup (Array a) where
419+ append = concatArray
420+
421+foreign import concatString :: String -> String -> String
422+foreign import concatArray :: forall a. Array a -> Array a -> Array a
423+
424+-- | The `Semiring` class is for types that support an addition and
425+-- | multiplication operation.
426+-- |
427+-- | Instances must satisfy the following laws:
428+-- |
429+-- | - Commutative monoid under addition:
430+-- | - Associativity: `(a + b) + c = a + (b + c)`
431+-- | - Identity: `zero + a = a + zero = a`
432+-- | - Commutative: `a + b = b + a`
433+-- | - Monoid under multiplication:
434+-- | - Associativity: `(a * b) * c = a * (b * c)`
435+-- | - Identity: `one * a = a * one = a`
436+-- | - Multiplication distributes over addition:
437+-- | - Left distributivity: `a * (b + c) = (a * b) + (a * c)`
438+-- | - Right distributivity: `(a + b) * c = (a * c) + (b * c)`
439+-- | - Annihiliation: `zero * a = a * zero = zero`
440+class Semiring a where
441+ add :: a -> a -> a
442+ zero :: a
443+ mul :: a -> a -> a
444+ one :: a
445+
446+instance semiringInt :: Semiring Int where
447+ add = intAdd
448+ zero = 0
449+ mul = intMul
450+ one = 1
451+
452+instance semiringNumber :: Semiring Number where
453+ add = numAdd
454+ zero = 0.0
455+ mul = numMul
456+ one = 1.0
457+
458+instance semiringUnit :: Semiring Unit where
459+ add _ _ = unit
460+ zero = unit
461+ mul _ _ = unit
462+ one = unit
463+
464+infixl 6 +
465+infixl 7 *
466+
467+-- | `(+)` is an alias for `add`.
468+(+) :: forall a. (Semiring a) => a -> a -> a
469+(+) = add
470+
471+-- | `(*)` is an alias for `mul`.
472+(*) :: forall a. (Semiring a) => a -> a -> a
473+(*) = mul
474+
475+foreign import intAdd :: Int -> Int -> Int
476+foreign import intMul :: Int -> Int -> Int
477+foreign import numAdd :: Number -> Number -> Number
478+foreign import numMul :: Number -> Number -> Number
479+
480+-- | The `Ring` class is for types that support addition, multiplication,
481+-- | and subtraction operations.
482+-- |
483+-- | Instances must satisfy the following law in addition to the `Semiring`
484+-- | laws:
485+-- |
486+-- | - Additive inverse: `a - a = (zero - a) + a = zero`
487+class (Semiring a) <= Ring a where
488+ sub :: a -> a -> a
489+
490+instance ringInt :: Ring Int where
491+ sub = intSub
492+
493+instance ringNumber :: Ring Number where
494+ sub = numSub
495+
496+instance ringUnit :: Ring Unit where
497+ sub _ _ = unit
498+
499+infixl 6 -
500+
501+-- | `(-)` is an alias for `sub`.
502+(-) :: forall a. (Ring a) => a -> a -> a
503+(-) = sub
504+
505+-- | `negate x` can be used as a shorthand for `zero - x`.
506+negate :: forall a. (Ring a) => a -> a
507+negate a = zero - a
508+
509+foreign import intSub :: Int -> Int -> Int
510+foreign import numSub :: Number -> Number -> Number
511+
512+-- | The `ModuloSemiring` class is for types that support addition,
513+-- | multiplication, division, and modulo (division remainder) operations.
514+-- |
515+-- | Instances must satisfy the following law in addition to the `Semiring`
516+-- | laws:
517+-- |
518+-- | - Remainder: ``a / b * b + (a `mod` b) = a``
519+class (Semiring a) <= ModuloSemiring a where
520+ div :: a -> a -> a
521+ mod :: a -> a -> a
522+
523+instance moduloSemiringInt :: ModuloSemiring Int where
524+ div = intDiv
525+ mod = intMod
526+
527+instance moduloSemiringNumber :: ModuloSemiring Number where
528+ div = numDiv
529+ mod _ _ = 0.0
530+
531+instance moduloSemiringUnit :: ModuloSemiring Unit where
532+ div _ _ = unit
533+ mod _ _ = unit
534+
535+infixl 7 /
536+
537+-- | `(/)` is an alias for `div`.
538+(/) :: forall a. (ModuloSemiring a) => a -> a -> a
539+(/) = div
540+
541+foreign import intDiv :: Int -> Int -> Int
542+foreign import numDiv :: Number -> Number -> Number
543+foreign import intMod :: Int -> Int -> Int
544+
545+-- | A `Ring` where every nonzero element has a multiplicative inverse.
546+-- |
547+-- | Instances must satisfy the following law in addition to the `Ring` and
548+-- | `ModuloSemiring` laws:
549+-- |
550+-- | - Multiplicative inverse: `(one / x) * x = one`
551+-- |
552+-- | As a consequence of this ```a `mod` b = zero``` as no divide operation
553+-- | will have a remainder.
554+class (Ring a, ModuloSemiring a) <= DivisionRing a
555+
556+instance divisionRingNumber :: DivisionRing Number
557+instance divisionRingUnit :: DivisionRing Unit
558+
559+-- | The `Num` class is for types that are commutative fields.
560+-- |
561+-- | Instances must satisfy the following law in addition to the
562+-- | `DivisionRing` laws:
563+-- |
564+-- | - Commutative multiplication: `a * b = b * a`
565+class (DivisionRing a) <= Num a
566+
567+instance numNumber :: Num Number
568+instance numUnit :: Num Unit
569+
570+-- | The `Eq` type class represents types which support decidable equality.
571+-- |
572+-- | `Eq` instances should satisfy the following laws:
573+-- |
574+-- | - Reflexivity: `x == x = true`
575+-- | - Symmetry: `x == y = y == x`
576+-- | - Transitivity: if `x == y` and `y == z` then `x == z`
577+class Eq a where
578+ eq :: a -> a -> Boolean
579+
580+infix 4 ==
581+infix 4 /=
582+
583+-- | `(==)` is an alias for `eq`. Tests whether one value is equal to another.
584+(==) :: forall a. (Eq a) => a -> a -> Boolean
585+(==) = eq
586+
587+-- | `(/=)` tests whether one value is _not equal_ to another. Shorthand for
588+-- | `not (x == y)`.
589+(/=) :: forall a. (Eq a) => a -> a -> Boolean
590+(/=) x y = not (x == y)
591+
592+instance eqBoolean :: Eq Boolean where
593+ eq = refEq
594+
595+instance eqInt :: Eq Int where
596+ eq = refEq
597+
598+instance eqNumber :: Eq Number where
599+ eq = refEq
600+
601+instance eqChar :: Eq Char where
602+ eq = refEq
603+
604+instance eqString :: Eq String where
605+ eq = refEq
606+
607+instance eqUnit :: Eq Unit where
608+ eq _ _ = true
609+
610+instance eqArray :: (Eq a) => Eq (Array a) where
611+ eq = eqArrayImpl (==)
612+
613+instance eqOrdering :: Eq Ordering where
614+ eq LT LT = true
615+ eq GT GT = true
616+ eq EQ EQ = true
617+ eq _ _ = false
618+
619+foreign import refEq :: forall a. a -> a -> Boolean
620+foreign import refIneq :: forall a. a -> a -> Boolean
621+foreign import eqArrayImpl :: forall a. (a -> a -> Boolean) -> Array a -> Array a -> Boolean
622+
623+-- | The `Ordering` data type represents the three possible outcomes of
624+-- | comparing two values:
625+-- |
626+-- | `LT` - The first value is _less than_ the second.
627+-- | `GT` - The first value is _greater than_ the second.
628+-- | `EQ` - The first value is _equal to_ the second.
629+data Ordering = LT | GT | EQ
630+
631+-- | The `Ord` type class represents types which support comparisons with a
632+-- | _total order_.
633+-- |
634+-- | `Ord` instances should satisfy the laws of total orderings:
635+-- |
636+-- | - Reflexivity: `a <= a`
637+-- | - Antisymmetry: if `a <= b` and `b <= a` then `a = b`
638+-- | - Transitivity: if `a <= b` and `b <= c` then `a <= c`
639+class (Eq a) <= Ord a where
640+ compare :: a -> a -> Ordering
641+
642+instance ordBoolean :: Ord Boolean where
643+ compare = unsafeCompare
644+
645+instance ordInt :: Ord Int where
646+ compare = unsafeCompare
647+
648+instance ordNumber :: Ord Number where
649+ compare = unsafeCompare
650+
651+instance ordString :: Ord String where
652+ compare = unsafeCompare
653+
654+instance ordChar :: Ord Char where
655+ compare = unsafeCompare
656+
657+instance ordUnit :: Ord Unit where
658+ compare _ _ = EQ
659+
660+instance ordArray :: (Ord a) => Ord (Array a) where
661+ compare xs ys = compare 0 $ ordArrayImpl (\x y -> case compare x y of
662+ EQ -> 0
663+ LT -> 1
664+ GT -> -1) xs ys
665+
666+foreign import ordArrayImpl :: forall a. (a -> a -> Int) -> Array a -> Array a -> Int
667+
668+instance ordOrdering :: Ord Ordering where
669+ compare LT LT = EQ
670+ compare EQ EQ = EQ
671+ compare GT GT = EQ
672+ compare LT _ = LT
673+ compare EQ LT = GT
674+ compare EQ GT = LT
675+ compare GT _ = GT
676+
677+infixl 4 <
678+infixl 4 >
679+infixl 4 <=
680+infixl 4 >=
681+
682+-- | Test whether one value is _strictly less than_ another.
683+(<) :: forall a. (Ord a) => a -> a -> Boolean
684+(<) a1 a2 = case a1 `compare` a2 of
685+ LT -> true
686+ _ -> false
687+
688+-- | Test whether one value is _strictly greater than_ another.
689+(>) :: forall a. (Ord a) => a -> a -> Boolean
690+(>) a1 a2 = case a1 `compare` a2 of
691+ GT -> true
692+ _ -> false
693+
694+-- | Test whether one value is _non-strictly less than_ another.
695+(<=) :: forall a. (Ord a) => a -> a -> Boolean
696+(<=) a1 a2 = case a1 `compare` a2 of
697+ GT -> false
698+ _ -> true
699+
700+-- | Test whether one value is _non-strictly greater than_ another.
701+(>=) :: forall a. (Ord a) => a -> a -> Boolean
702+(>=) a1 a2 = case a1 `compare` a2 of
703+ LT -> false
704+ _ -> true
705+
706+unsafeCompare :: forall a. a -> a -> Ordering
707+unsafeCompare = unsafeCompareImpl LT EQ GT
708+
709+foreign import unsafeCompareImpl :: forall a. Ordering -> Ordering -> Ordering -> a -> a -> Ordering
710+
711+-- | The `Bounded` type class represents types that are finite.
712+-- |
713+-- | Although there are no "internal" laws for `Bounded`, every value of `a`
714+-- | should be considered less than or equal to `top` by some means, and greater
715+-- | than or equal to `bottom`.
716+-- |
717+-- | The lack of explicit `Ord` constraint allows flexibility in the use of
718+-- | `Bounded` so it can apply to total and partially ordered sets, boolean
719+-- | algebras, etc.
720+class Bounded a where
721+ top :: a
722+ bottom :: a
723+
724+instance boundedBoolean :: Bounded Boolean where
725+ top = true
726+ bottom = false
727+
728+instance boundedUnit :: Bounded Unit where
729+ top = unit
730+ bottom = unit
731+
732+instance boundedOrdering :: Bounded Ordering where
733+ top = GT
734+ bottom = LT
735+
736+instance boundedInt :: Bounded Int where
737+ top = topInt
738+ bottom = bottomInt
739+
740+-- | Characters fall within the Unicode range.
741+instance boundedChar :: Bounded Char where
742+ top = topChar
743+ bottom = bottomChar
744+
745+instance boundedFn :: (Bounded b) => Bounded (a -> b) where
746+ top _ = top
747+ bottom _ = bottom
748+
749+foreign import topInt :: Int
750+foreign import bottomInt :: Int
751+
752+foreign import topChar :: Char
753+foreign import bottomChar :: Char
754+
755+-- | The `BoundedOrd` type class represents totally ordered finite data types.
756+-- |
757+-- | Instances should satisfy the following law in addition to the `Ord` laws:
758+-- |
759+-- | - Ordering: `bottom <= a <= top`
760+class (Bounded a, Ord a) <= BoundedOrd a
761+
762+instance boundedOrdBoolean :: BoundedOrd Boolean where
763+instance boundedOrdUnit :: BoundedOrd Unit where
764+instance boundedOrdOrdering :: BoundedOrd Ordering where
765+instance boundedOrdInt :: BoundedOrd Int where
766+instance boundedOrdChar :: BoundedOrd Char where
767+
768+-- | The `BooleanAlgebra` type class represents types that behave like boolean
769+-- | values.
770+-- |
771+-- | Instances should satisfy the following laws in addition to the `Bounded`
772+-- | laws:
773+-- |
774+-- | - Associativity:
775+-- | - `a || (b || c) = (a || b) || c`
776+-- | - `a && (b && c) = (a && b) && c`
777+-- | - Commutativity:
778+-- | - `a || b = b || a`
779+-- | - `a && b = b && a`
780+-- | - Distributivity:
781+-- | - `a && (b || c) = (a && b) || (a && c)`
782+-- | - `a || (b && c) = (a || b) && (a || c)`
783+-- | - Identity:
784+-- | - `a || bottom = a`
785+-- | - `a && top = a`
786+-- | - Idempotent:
787+-- | - `a || a = a`
788+-- | - `a && a = a`
789+-- | - Absorption:
790+-- | - `a || (a && b) = a`
791+-- | - `a && (a || b) = a`
792+-- | - Annhiliation:
793+-- | - `a || top = top`
794+-- | - Complementation:
795+-- | - `a && not a = bottom`
796+-- | - `a || not a = top`
797+class (Bounded a) <= BooleanAlgebra a where
798+ conj :: a -> a -> a
799+ disj :: a -> a -> a
800+ not :: a -> a
801+
802+instance booleanAlgebraBoolean :: BooleanAlgebra Boolean where
803+ conj = boolAnd
804+ disj = boolOr
805+ not = boolNot
806+
807+instance booleanAlgebraUnit :: BooleanAlgebra Unit where
808+ conj _ _ = unit
809+ disj _ _ = unit
810+ not _ = unit
811+
812+instance booleanAlgebraFn :: (BooleanAlgebra b) => BooleanAlgebra (a -> b) where
813+ conj fx fy a = fx a `conj` fy a
814+ disj fx fy a = fx a `disj` fy a
815+ not fx a = not (fx a)
816+
817+infixr 3 &&
818+infixr 2 ||
819+
820+-- | `(&&)` is an alias for `conj`.
821+(&&) :: forall a. (BooleanAlgebra a) => a -> a -> a
822+(&&) = conj
823+
824+-- | `(||)` is an alias for `disj`.
825+(||) :: forall a. (BooleanAlgebra a) => a -> a -> a
826+(||) = disj
827+
828+foreign import boolOr :: Boolean -> Boolean -> Boolean
829+foreign import boolAnd :: Boolean -> Boolean -> Boolean
830+foreign import boolNot :: Boolean -> Boolean
831+
832+-- | The `Show` type class represents those types which can be converted into
833+-- | a human-readable `String` representation.
834+-- |
835+-- | While not required, it is recommended that for any expression `x`, the
836+-- | string `show x` be executable PureScript code which evaluates to the same
837+-- | value as the expression `x`.
838+class Show a where
839+ show :: a -> String
840+
841+instance showBoolean :: Show Boolean where
842+ show true = "true"
843+ show false = "false"
844+
845+instance showInt :: Show Int where
846+ show = showIntImpl
847+
848+instance showNumber :: Show Number where
849+ show = showNumberImpl
850+
851+instance showChar :: Show Char where
852+ show = showCharImpl
853+
854+instance showString :: Show String where
855+ show = showStringImpl
856+
857+instance showUnit :: Show Unit where
858+ show _ = "unit"
859+
860+instance showArray :: (Show a) => Show (Array a) where
861+ show = showArrayImpl show
862+
863+instance showOrdering :: Show Ordering where
864+ show LT = "LT"
865+ show GT = "GT"
866+ show EQ = "EQ"
867+
868+foreign import showIntImpl :: Int -> String
869+foreign import showNumberImpl :: Number -> String
870+foreign import showCharImpl :: Char -> String
871+foreign import showStringImpl :: String -> String
872+foreign import showArrayImpl :: forall a. (a -> String) -> Array a -> String
tests/support/flattened/Test-Assert.jsnew file+27
@@ -0,0 +1,27 @@
1+/* global exports */
2+"use strict";
3+
4+// module Test.Assert
5+
6+exports["assert'"] = function (message) {
7+ return function (success) {
8+ return function () {
9+ if (!success) throw new Error(message);
10+ return {};
11+ };
12+ };
13+};
14+
15+exports.checkThrows = function (fn) {
16+ return function () {
17+ try {
18+ fn();
19+ return false;
20+ } catch (e) {
21+ if (e instanceof Error) return true;
22+ var err = new Error("Threw something other than an Error");
23+ err.something = e;
24+ throw err;
25+ }
26+ };
27+};
tests/support/flattened/Test-Assert.pursnew file+46
@@ -0,0 +1,46 @@
1+module Test.Assert
2+ ( assert'
3+ , assert
4+ , assertThrows
5+ , assertThrows'
6+ , ASSERT()
7+ ) where
8+
9+import Control.Monad.Eff (Eff())
10+import Prelude
11+
12+-- | Assertion effect type.
13+foreign import data ASSERT :: !
14+
15+-- | Throws a runtime exception with message "Assertion failed" when the boolean
16+-- | value is false.
17+assert :: forall e. Boolean -> Eff (assert :: ASSERT | e) Unit
18+assert = assert' "Assertion failed"
19+
20+-- | Throws a runtime exception with the specified message when the boolean
21+-- | value is false.
22+foreign import assert' :: forall e. String -> Boolean -> Eff (assert :: ASSERT | e) Unit
23+
24+-- | Throws a runtime exception with message "Assertion failed: An error should
25+-- | have been thrown", unless the argument throws an exception when evaluated.
26+-- |
27+-- | This function is specifically for testing unsafe pure code; for example,
28+-- | to make sure that an exception is thrown if a precondition is not
29+-- | satisfied. Functions which use `Eff (err :: EXCEPTION | eff) a` can be
30+-- | tested with `catchException` instead.
31+assertThrows :: forall e a. (Unit -> a) -> Eff (assert :: ASSERT | e) Unit
32+assertThrows = assertThrows' "Assertion failed: An error should have been thrown"
33+
34+-- | Throws a runtime exception with the specified message, unless the argument
35+-- | throws an exception when evaluated.
36+-- |
37+-- | This function is specifically for testing unsafe pure code; for example,
38+-- | to make sure that an exception is thrown if a precondition is not
39+-- | satisfied. Functions which use `Eff (err :: EXCEPTION | eff) a` can be
40+-- | tested with `catchException` instead.
41+assertThrows' :: forall e a. String -> (Unit -> a) -> Eff (assert :: ASSERT | e) Unit
42+assertThrows' msg fn =
43+ checkThrows fn >>= assert' msg
44+
45+
46+foreign import checkThrows :: forall e a. (Unit -> a) -> Eff (assert :: ASSERT | e) Boolean
psci/tests/data/Sample.purs → tests/support/psci/Sample.pursrenamed

The content is the same.

travis/after.sh+5−17
@@ -4,22 +4,10 @@ pushd core-tests/
4./test-everything.sh
4./test-everything.sh
5popd
5popd
6
6
7−if ! git describe --tags --exact-match >/dev/null 2>/dev/null && [ -n "$COVERAGE_SUITE" ]
7+if ! git describe --tags --exact-match >/dev/null 2>/dev/null && [ "$COVERAGE" = "true" ]
8then
8then
9− case "$COVERAGE_SUITE" in
10− "tests")
11− ./.cabal-sandbox/bin/hpc-coveralls \
9+ ./.cabal-sandbox/bin/hpc-coveralls \
12− --exclude-dir=dist/build/autogen \
13− --exclude-dir=tests \
14− tests;;
15− "psci-tests")
16− ./.cabal-sandbox/bin/hpc-coveralls \
17− --exclude-dir=dist/build/autogen \
10+ --exclude-dir=dist/build/autogen \
18− --exclude-dir=src \
19− --exclude-dir=psci/tests \
11+ --exclude-dir=tests \
20− psci-tests;;
12+ tests
21− *)
22− echo "unrecognised test suite $COVERAGE_SUITE"
23− exit 1;;
24− esac
25fi
13fi
travis/configure.sh+1−1
@@ -8,7 +8,7 @@ then
8 configure_flags="--disable-optimization $configure_flags"
8 configure_flags="--disable-optimization $configure_flags"
9fi
9fi
10
10
11−if [ -n "$COVERAGE_SUITE" ]
11+if [ "$COVERAGE" = "true" ]
12then
12then
13 configure_flags="--enable-coverage $configure_flags"
13 configure_flags="--enable-coverage $configure_flags"
14fi
14fi