diff options
author | PhilFreeman <> | 2016-06-01 00:58:00 (GMT) |
---|---|---|
committer | hdiff <hdiff@hdiff.luite.com> | 2016-06-01 00:58:00 (GMT) |
commit | 0f4090890a1b18cff078fbd427318c6848097703 (patch) | |
tree | 493724aed4d46ac8ff3ffd4b9fa6cae7229686b6 /tests | |
parent | 164b1a98130296e0cb0d4eb3b04066ccbfdb2394 (diff) |
version 0.9.10.9.1
Diffstat (limited to 'tests')
38 files changed, 383 insertions, 3225 deletions
diff --git a/tests/Language/PureScript/Ide/FilterSpec.hs b/tests/Language/PureScript/Ide/FilterSpec.hs index 700e30e..6415ec0 100644 --- a/tests/Language/PureScript/Ide/FilterSpec.hs +++ b/tests/Language/PureScript/Ide/FilterSpec.hs @@ -8,7 +8,7 @@ import qualified Language.PureScript as P import Test.Hspec value :: Text -> ExternDecl -value s = ValueDeclaration s P.TypeWildcard +value s = ValueDeclaration s $ P.TypeWildcard $ P.SourceSpan "" (P.SourcePos 0 0) (P.SourcePos 0 0) modules :: [Module] modules = diff --git a/tests/Language/PureScript/Ide/Imports/IntegrationSpec.hs b/tests/Language/PureScript/Ide/Imports/IntegrationSpec.hs index 9992819..ef56ccb 100644 --- a/tests/Language/PureScript/Ide/Imports/IntegrationSpec.hs +++ b/tests/Language/PureScript/Ide/Imports/IntegrationSpec.hs @@ -1,7 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} module Language.PureScript.Ide.Imports.IntegrationSpec where -import Control.Monad +import Control.Monad (void) import Data.Text (Text) import qualified Data.Text as T import qualified Data.Text.IO as TIO @@ -13,16 +13,9 @@ import System.FilePath setup :: IO () setup = do - Integration.deleteOutputFolder - s <- Integration.compileTestProject - unless s $ fail "Failed to compile .purs sources" - Integration.quitServer -- kill a eventually running psc-ide-server instance - _ <- Integration.startServer + Integration.reset mapM_ Integration.loadModuleWithDeps ["ImportsSpec", "ImportsSpec1"] -teardown :: IO () -teardown = Integration.quitServer - withSupportFiles :: (FilePath -> FilePath -> IO a) -> IO () withSupportFiles test = do pdir <- Integration.projectDirectory @@ -38,15 +31,15 @@ outputFileShouldBe expectation = do shouldBe (T.lines outRes) expectation spec :: Spec -spec = beforeAll_ setup $ afterAll_ teardown $ describe "Adding imports" $ do +spec = beforeAll_ setup . describe "Adding imports" $ do let sourceFileSkeleton :: [Text] -> [Text] sourceFileSkeleton importSection = [ "module ImportsSpec where" , ""] ++ importSection ++ [ "" , "myId = id"] it "adds an implicit import" $ do - withSupportFiles (Integration.addImplicitImport "Prelude") + withSupportFiles (Integration.addImplicitImport "ImportsSpec1") outputFileShouldBe (sourceFileSkeleton - [ "import Prelude" + [ "import ImportsSpec1" , "import Main (id)" ]) it "adds an explicit unqualified import" $ do diff --git a/tests/Language/PureScript/Ide/ImportsSpec.hs b/tests/Language/PureScript/Ide/ImportsSpec.hs index 36cbe25..e78fcb9 100644 --- a/tests/Language/PureScript/Ide/ImportsSpec.hs +++ b/tests/Language/PureScript/Ide/ImportsSpec.hs @@ -36,6 +36,9 @@ listImport = testParseImport "import Data.List as List" consoleImport = testParseImport "import Control.Monad.Eff.Console (log) as Console" maybeImport = testParseImport "import Data.Maybe (Maybe(Just))" +wildcard :: P.Type +wildcard = P.TypeWildcard $ P.SourceSpan "" (P.SourcePos 0 0) (P.SourcePos 0 0) + spec :: Spec spec = do describe "determining the importsection" $ do @@ -65,9 +68,11 @@ spec = do describe "import commands" $ do let simpleFileImports = let (_, _, i, _) = splitSimpleFile in i addValueImport i mn is = - prettyPrintImportSection (addExplicitImport' (ValueDeclaration i P.TypeWildcard) mn is) + prettyPrintImportSection (addExplicitImport' (ValueDeclaration i wildcard) mn is) + addOpImport op mn is = + prettyPrintImportSection (addExplicitImport' (ValueOperator op "" 2 P.Infix) mn is) addDtorImport i t mn is = - prettyPrintImportSection (addExplicitImport' (DataConstructor i t P.TypeWildcard) mn is) + prettyPrintImportSection (addExplicitImport' (DataConstructor i t wildcard) mn is) it "adds an implicit unqualified import" $ shouldBe (addImplicitImport' simpleFileImports (P.moduleNameFromString "Data.Map")) @@ -93,7 +98,7 @@ spec = do ] it "adds an operator to an explicit import list" $ shouldBe - (addValueImport "<~>" (P.moduleNameFromString "Data.Array") explicitImports) + (addOpImport (P.OpName "<~>") (P.moduleNameFromString "Data.Array") explicitImports) [ "import Prelude" , "import Data.Array ((<~>), tail)" ] diff --git a/tests/Language/PureScript/Ide/Integration.hs b/tests/Language/PureScript/Ide/Integration.hs index cea69fd..876eb21 100644 --- a/tests/Language/PureScript/Ide/Integration.hs +++ b/tests/Language/PureScript/Ide/Integration.hs @@ -27,33 +27,37 @@ module Language.PureScript.Ide.Integration , projectDirectory , deleteFileIfExists -- sending commands + , addImport + , addImplicitImport , loadModule , loadModuleWithDeps + , getCwd , getFlexCompletions + , getFlexCompletionsInModule , getType - , addImport - , addImplicitImport , rebuildModule + , reset -- checking results , resultIsSuccess , parseCompletions , parseTextResult ) where -import Control.Concurrent (threadDelay) +import Control.Concurrent (threadDelay) import Control.Exception -import Control.Monad (join, when) +import Control.Monad (join, when) import Data.Aeson import Data.Aeson.Types -import qualified Data.ByteString.Lazy.UTF8 as BSL -import Data.Either (isRight) -import Data.Maybe (fromJust) -import qualified Data.Text as T -import qualified Data.Vector as V +import qualified Data.ByteString.Lazy.UTF8 as BSL +import Data.Either (isRight) +import Data.Maybe (fromJust, isNothing, fromMaybe) +import qualified Data.Text as T +import qualified Data.Vector as V import Language.PureScript.Ide.Util import System.Directory import System.Exit import System.FilePath +import System.IO.Error (mkIOError, userErrorType) import System.Process projectDirectory :: IO FilePath @@ -64,7 +68,9 @@ projectDirectory = do startServer :: IO ProcessHandle startServer = do pdir <- projectDirectory - (_, _, _, procHandle) <- createProcess $ (shell "psc-ide-server") {cwd=Just pdir} + -- Turn off filewatching since it creates race condition in a testing environment + (_, _, _, procHandle) <- createProcess $ + (shell "psc-ide-server --no-watch") {cwd = Just pdir} threadDelay 500000 -- give the server 500ms to start up return procHandle @@ -74,9 +80,15 @@ stopServer = terminateProcess withServer :: IO a -> IO a withServer s = do _ <- startServer + started <- tryNTimes 5 (shush <$> (try getCwd :: IO (Either SomeException String))) + when (isNothing started) $ + throwIO (mkIOError userErrorType "psc-ide-server didn't start in time" Nothing Nothing) r <- s quitServer - return r + pure r + +shush :: Either a b -> Maybe b +shush = either (const Nothing) Just -- project management utils @@ -84,11 +96,22 @@ compileTestProject :: IO Bool compileTestProject = do pdir <- projectDirectory (_, _, _, procHandle) <- createProcess $ - (shell $ "psc " ++ fileGlob) {cwd=Just pdir - ,std_out=CreatePipe - ,std_err=CreatePipe + (shell $ "psc " ++ fileGlob) { cwd = Just pdir + , std_out = CreatePipe + , std_err = CreatePipe } - isSuccess <$> waitForProcess procHandle + r <- tryNTimes 5 (getProcessExitCode procHandle) + pure (fromMaybe False (isSuccess <$> r)) + +tryNTimes :: Int -> IO (Maybe a) -> IO (Maybe a) +tryNTimes 0 _ = pure Nothing +tryNTimes n action = do + r <- action + case r of + Nothing -> do + threadDelay 500000 + tryNTimes (n - 1) action + Just a -> pure (Just a) deleteOutputFolder :: IO () deleteOutputFolder = do @@ -110,9 +133,6 @@ isSuccess (ExitFailure _) = False fileGlob :: String fileGlob = unwords [ "\"src/**/*.purs\"" - , "\"src/**/*.js\"" - , "\"bower_components/purescript-*/**/*.purs\"" - , "\"bower_components/purescript-*/**/*.js\"" ] -- Integration Testing API @@ -130,6 +150,17 @@ quitServer = do _ <- try $ sendCommand quitCommand :: IO (Either SomeException String) return () +reset :: IO () +reset = do + let resetCommand = object ["command" .= ("reset" :: String)] + _ <- try $ sendCommand resetCommand :: IO (Either SomeException String) + return () + +getCwd :: IO String +getCwd = do + let cwdCommand = object ["command" .= ("cwd" :: String)] + sendCommand cwdCommand + loadModuleWithDeps :: String -> IO String loadModuleWithDeps m = sendCommand $ load [] [m] @@ -137,7 +168,10 @@ loadModule :: String -> IO String loadModule m = sendCommand $ load [m] [] getFlexCompletions :: String -> IO [(String, String, String)] -getFlexCompletions q = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q))) +getFlexCompletions q = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)) Nothing) + +getFlexCompletionsInModule :: String -> String -> IO [(String, String, String)] +getFlexCompletionsInModule q m = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)) (Just m)) getType :: String -> IO [(String, String, String)] getType q = parseCompletions <$> sendCommand (typeC q []) @@ -188,14 +222,17 @@ addImportW importCommand fp outfp = ]) -completion :: [Value] -> Maybe Value -> Value -completion filters matcher = +completion :: [Value] -> Maybe Value -> Maybe String -> Value +completion filters matcher currentModule = let matcher' = case matcher of Nothing -> [] Just m -> ["matcher" .= m] + currentModule' = case currentModule of + Nothing -> [] + Just cm -> ["currentModule" .= cm] in - commandWrapper "complete" (object $ "filters" .= filters : matcher') + commandWrapper "complete" (object $ "filters" .= filters : matcher' ++ currentModule' ) flexMatcher :: String -> Value flexMatcher q = object [ "matcher" .= ("flex" :: String) diff --git a/tests/Language/PureScript/Ide/MatcherSpec.hs b/tests/Language/PureScript/Ide/MatcherSpec.hs index 13cef33..954ded1 100644 --- a/tests/Language/PureScript/Ide/MatcherSpec.hs +++ b/tests/Language/PureScript/Ide/MatcherSpec.hs @@ -2,21 +2,22 @@ module Language.PureScript.Ide.MatcherSpec where +import Control.Monad (void) import Data.Text (Text) +import qualified Language.PureScript as P import Language.PureScript.Ide.Integration import Language.PureScript.Ide.Matcher import Language.PureScript.Ide.Types -import qualified Language.PureScript as P import Test.Hspec value :: Text -> ExternDecl -value s = ValueDeclaration s P.TypeWildcard +value s = ValueDeclaration s $ P.TypeWildcard $ P.SourceSpan "" (P.SourcePos 0 0) (P.SourcePos 0 0) completions :: [Match] -completions = [ - Match "" $ value "firstResult", - Match "" $ value "secondResult", - Match "" $ value "fiult" +completions = + [ Match "" (value "firstResult") + , Match "" (value "secondResult") + , Match "" (value "fiult") ] mkResult :: [Int] -> [Match] @@ -26,15 +27,7 @@ runFlex :: Text -> [Match] runFlex s = runMatcher (flexMatcher s) completions setup :: IO () -setup = do - deleteOutputFolder - _ <- compileTestProject - _ <- startServer - _ <- loadModuleWithDeps "Main" - return () - -teardown :: IO () -teardown = quitServer +setup = reset *> void (loadModuleWithDeps "Main") spec :: Spec spec = do @@ -46,8 +39,7 @@ spec = do it "scores short matches higher and sorts accordingly" $ runFlex "filt" `shouldBe` mkResult [2, 0] - beforeAll_ setup $ afterAll_ teardown $ - describe "Integration Tests: Flex Matcher" $ do + beforeAll_ setup . describe "Integration Tests: Flex Matcher" $ do it "doesn't match on an empty string" $ do cs <- getFlexCompletions "" cs `shouldBe` [] diff --git a/tests/Language/PureScript/Ide/RebuildSpec.hs b/tests/Language/PureScript/Ide/RebuildSpec.hs index f7370af..f78cd1b 100644 --- a/tests/Language/PureScript/Ide/RebuildSpec.hs +++ b/tests/Language/PureScript/Ide/RebuildSpec.hs @@ -1,22 +1,8 @@ module Language.PureScript.Ide.RebuildSpec where -import Control.Monad import qualified Language.PureScript.Ide.Integration as Integration -import Test.Hspec - import System.FilePath - -compile :: IO () -compile = do - Integration.deleteOutputFolder - s <- Integration.compileTestProject - unless s $ fail "Failed to compile .purs sources" - -teardown :: IO () -teardown = Integration.quitServer - -restart :: IO () -restart = Integration.quitServer *> (void Integration.startServer) +import Test.Hspec shouldBeSuccess :: String -> IO () shouldBeSuccess = shouldBe True . Integration.resultIsSuccess @@ -25,8 +11,7 @@ shouldBeFailure :: String -> IO () shouldBeFailure = shouldBe False . Integration.resultIsSuccess spec :: Spec -spec = beforeAll_ compile $ afterAll_ teardown $ before_ restart $ do - describe "Rebuilding single modules" $ do +spec = before_ Integration.reset . describe "Rebuilding single modules" $ do it "rebuilds a correct module without dependencies successfully" $ do _ <- Integration.loadModuleWithDeps "RebuildSpecSingleModule" pdir <- Integration.projectDirectory @@ -60,3 +45,9 @@ spec = beforeAll_ compile $ afterAll_ teardown $ before_ restart $ do pdir <- Integration.projectDirectory let file = pdir </> "src" </> "RebuildSpecWithMissingForeign.fail" Integration.rebuildModule file >>= shouldBeFailure + it "completes a hidden identifier after rebuilding" $ do + pdir <- Integration.projectDirectory + let file = pdir </> "src" </> "RebuildSpecWithHiddenIdent.purs" + Integration.rebuildModule file >>= shouldBeSuccess + res <- Integration.getFlexCompletionsInModule "hid" "RebuildSpecWithHiddenIdent" + shouldBe False (null res) diff --git a/tests/Language/PureScript/Ide/ReexportsSpec.hs b/tests/Language/PureScript/Ide/ReexportsSpec.hs index 42d28f0..5633d60 100644 --- a/tests/Language/PureScript/Ide/ReexportsSpec.hs +++ b/tests/Language/PureScript/Ide/ReexportsSpec.hs @@ -9,12 +9,15 @@ import Language.PureScript.Ide.Types import qualified Language.PureScript as P import Test.Hspec +wildcard :: P.Type +wildcard = P.TypeWildcard $ P.SourceSpan "" (P.SourcePos 0 0) (P.SourcePos 0 0) + decl1 :: ExternDecl -decl1 = ValueDeclaration "filter" P.TypeWildcard +decl1 = ValueDeclaration "filter" wildcard decl2 :: ExternDecl -decl2 = ValueDeclaration "map" P.TypeWildcard +decl2 = ValueDeclaration "map" wildcard decl3 :: ExternDecl -decl3 = ValueDeclaration "catMaybe" P.TypeWildcard +decl3 = ValueDeclaration "catMaybe" wildcard dep1 :: ExternDecl dep1 = Dependency "Test.Foo" [] (Just "T") dep2 :: ExternDecl diff --git a/tests/Language/PureScript/IdeSpec.hs b/tests/Language/PureScript/IdeSpec.hs index 83533f1..8ceedb1 100644 --- a/tests/Language/PureScript/IdeSpec.hs +++ b/tests/Language/PureScript/IdeSpec.hs @@ -11,7 +11,7 @@ import Language.PureScript.Ide.Types import Test.Hspec testState :: PscIdeState -testState = PscIdeState (Map.fromList [("Data.Array", []), ("Control.Monad.Eff", [])]) Map.empty +testState = PscIdeState (Map.fromList [("Data.Array", []), ("Control.Monad.Eff", [])]) Map.empty Nothing defaultConfig :: Configuration defaultConfig = diff --git a/tests/Main.hs b/tests/Main.hs index 2a246ef..61d1824 100644 --- a/tests/Main.hs +++ b/tests/Main.hs @@ -9,10 +9,11 @@ import Prelude () import Prelude.Compat import qualified TestCompiler -import qualified TestPscPublish import qualified TestDocs import qualified TestPsci import qualified TestPscIde +import qualified TestPscPublish +import qualified TestUtils import System.IO (hSetEncoding, stdout, stderr, utf8) @@ -21,6 +22,8 @@ main = do hSetEncoding stdout utf8 hSetEncoding stderr utf8 + heading "Updating support code" + TestUtils.updateSupportCode heading "Main compiler test suite" TestCompiler.main heading "Documentation test suite" diff --git a/tests/TestCompiler.hs b/tests/TestCompiler.hs index 43b0728..019b428 100644 --- a/tests/TestCompiler.hs +++ b/tests/TestCompiler.hs @@ -26,14 +26,16 @@ import Prelude.Compat import qualified Language.PureScript as P import Data.Char (isSpace) -import Data.Maybe (mapMaybe, fromMaybe) -import Data.List (isSuffixOf, sort, stripPrefix) +import Data.Function (on) +import Data.List (sort, stripPrefix, intercalate, groupBy, sortBy, minimumBy) +import Data.Maybe (mapMaybe) import Data.Time.Clock (UTCTime()) +import Data.Tuple (swap) import qualified Data.Map as M import Control.Monad -import Control.Arrow ((>>>)) +import Control.Arrow ((***), (>>>)) import Control.Monad.Reader import Control.Monad.Writer.Strict @@ -44,42 +46,116 @@ import System.Process hiding (cwd) import System.FilePath import System.Directory import System.IO.UTF8 +import System.IO.Silently import qualified System.FilePath.Glob as Glob import TestUtils +import Test.Hspec main :: IO () -main = do - cwd <- getCurrentDirectory - - let supportDir = cwd </> "tests" </> "support" </> "flattened" - let supportFiles ext = Glob.globDir1 (Glob.compile ("*." ++ ext)) supportDir - - supportPurs <- supportFiles "purs" - supportJS <- supportFiles "js" - - foreignFiles <- forM supportJS (\f -> (f,) <$> readUTF8File f) - Right (foreigns, _) <- runExceptT $ runWriterT $ P.parseForeignModulesFromFiles foreignFiles - - let passing = cwd </> "examples" </> "passing" - passingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents passing - let failing = cwd </> "examples" </> "failing" - failingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents failing - - failures <- execWriterT $ do - forM_ passingTestCases $ \inputFile -> - assertCompiles (supportPurs ++ [passing </> inputFile]) foreigns - forM_ failingTestCases $ \inputFile -> - assertDoesNotCompile (supportPurs ++ [failing </> inputFile]) foreigns - - if null failures - then pure () - else do - putStrLn "Failures:" - forM_ failures $ \(fp, err) -> - let fp' = fromMaybe fp $ stripPrefix (failing ++ [pathSeparator]) fp - in putStrLn $ fp' ++ ": " ++ err - exitFailure +main = hspec spec + +spec :: Spec +spec = do + + (supportExterns, passingTestCases, warningTestCases, failingTestCases) <- runIO $ do + cwd <- getCurrentDirectory + let passing = cwd </> "examples" </> "passing" + let warning = cwd </> "examples" </> "warning" + let failing = cwd </> "examples" </> "failing" + let supportDir = cwd </> "tests" </> "support" </> "bower_components" + let supportFiles ext = Glob.globDir1 (Glob.compile ("purescript-*/**/*." ++ ext)) supportDir + passingFiles <- getTestFiles passing <$> testGlob passing + warningFiles <- getTestFiles warning <$> testGlob warning + failingFiles <- getTestFiles failing <$> testGlob failing + supportPurs <- supportFiles "purs" + supportPursFiles <- readInput supportPurs + supportExterns <- runExceptT $ do + modules <- ExceptT . return $ P.parseModulesFromFiles id supportPursFiles + foreigns <- inferForeignModules modules + externs <- ExceptT . fmap fst . runTest $ P.make (makeActions foreigns) (map snd modules) + return (zip (map snd modules) externs) + case supportExterns of + Left errs -> fail (P.prettyPrintMultipleErrors P.defaultPPEOptions errs) + Right externs -> return (externs, passingFiles, warningFiles, failingFiles) + + context "Passing examples" $ + forM_ passingTestCases $ \testPurs -> + it ("'" <> takeFileName (getTestMain testPurs) <> "' should compile and run without error") $ + assertCompiles supportExterns testPurs + + context "Warning examples" $ + forM_ warningTestCases $ \testPurs -> do + let mainPath = getTestMain testPurs + expectedWarnings <- runIO $ getShouldWarnWith mainPath + it ("'" <> takeFileName mainPath <> "' should compile with warning(s) '" <> intercalate "', '" expectedWarnings <> "'") $ + assertCompilesWithWarnings supportExterns testPurs expectedWarnings + + context "Failing examples" $ + forM_ failingTestCases $ \testPurs -> do + let mainPath = getTestMain testPurs + expectedFailures <- runIO $ getShouldFailWith mainPath + it ("'" <> takeFileName mainPath <> "' should fail with '" <> intercalate "', '" expectedFailures <> "'") $ + assertDoesNotCompile supportExterns testPurs expectedFailures + + where + + -- A glob for all purs and js files within a test directory + testGlob :: FilePath -> IO [FilePath] + testGlob = Glob.globDir1 (Glob.compile "**/*.purs") + + -- Groups the test files so that a top-level file can have dependencies in a + -- subdirectory of the same name. The inner tuple contains a list of the + -- .purs files and the .js files for the test case. + getTestFiles :: FilePath -> [FilePath] -> [[FilePath]] + getTestFiles baseDir + = map (filter ((== ".purs") . takeExtensions) . map (baseDir </>)) + . groupBy ((==) `on` extractPrefix) + . sortBy (compare `on` extractPrefix) + . map (makeRelative baseDir) + + -- Takes the test entry point from a group of purs files - this is determined + -- by the file with the shortest path name, as everything but the main file + -- will be under a subdirectory. + getTestMain :: [FilePath] -> FilePath + getTestMain = minimumBy (compare `on` length) + + -- Extracts the filename part of a .purs file, or if the file is in a + -- subdirectory, the first part of that directory path. + extractPrefix :: FilePath -> FilePath + extractPrefix fp = + let dir = takeDirectory fp + ext = reverse ".purs" + in if dir == "." + then maybe fp reverse $ stripPrefix ext $ reverse fp + else dir + + -- Scans a file for @shouldFailWith directives in the comments, used to + -- determine expected failures + getShouldFailWith :: FilePath -> IO [String] + getShouldFailWith = extractPragma "shouldFailWith" + + -- Scans a file for @shouldWarnWith directives in the comments, used to + -- determine expected warnings + getShouldWarnWith :: FilePath -> IO [String] + getShouldWarnWith = extractPragma "shouldWarnWith" + + extractPragma :: String -> FilePath -> IO [String] + extractPragma pragma = fmap go . readUTF8File + where + go = lines >>> mapMaybe (stripPrefix ("-- @" ++ pragma ++ " ")) >>> map trim + +inferForeignModules + :: MonadIO m + => [(FilePath, P.Module)] + -> m (M.Map P.ModuleName FilePath) +inferForeignModules = P.inferForeignModules . fromList + where + fromList :: [(FilePath, P.Module)] -> M.Map P.ModuleName (Either P.RebuildPolicy FilePath) + fromList = M.fromList . map ((P.getModuleName *** Right) . swap) + +trim :: String -> String +trim = dropWhile isSpace >>> reverse >>> dropWhile isSpace >>> reverse modulesDir :: FilePath modulesDir = ".test_modules" </> "node_modules" @@ -108,53 +184,96 @@ readInput inputFiles = forM inputFiles $ \inputFile -> do text <- readUTF8File inputFile return (inputFile, text) -type TestM = WriterT [(FilePath, String)] IO +runTest :: P.Make a -> IO (Either P.MultipleErrors a, P.MultipleErrors) +runTest = P.runMake P.defaultOptions -runTest :: P.Make a -> IO (Either P.MultipleErrors a) -runTest = fmap fst . P.runMake P.defaultOptions - -compile :: [FilePath] -> M.Map P.ModuleName FilePath -> IO (Either P.MultipleErrors P.Environment) -compile inputFiles foreigns = runTest $ do +compile + :: [(P.Module, P.ExternsFile)] + -> [FilePath] + -> ([P.Module] -> IO ()) + -> IO (Either P.MultipleErrors [P.ExternsFile], P.MultipleErrors) +compile supportExterns inputFiles check = silence $ runTest $ do fs <- liftIO $ readInput inputFiles ms <- P.parseModulesFromFiles id fs - P.make (makeActions foreigns) (map snd ms) - -assert :: [FilePath] -> - M.Map P.ModuleName FilePath -> - (Either P.MultipleErrors P.Environment -> IO (Maybe String)) -> - TestM () -assert inputFiles foreigns f = do - e <- liftIO $ compile inputFiles foreigns - maybeErr <- liftIO $ f e - case maybeErr of - Just err -> tell [(last inputFiles, err)] - Nothing -> return () - -assertCompiles :: [FilePath] -> M.Map P.ModuleName FilePath -> TestM () -assertCompiles inputFiles foreigns = do - liftIO . putStrLn $ "Assert " ++ last inputFiles ++ " compiles successfully" - assert inputFiles foreigns $ \e -> + foreigns <- inferForeignModules ms + liftIO (check (map snd ms)) + let actions = makeActions foreigns + case ms of + [singleModule] -> pure <$> P.rebuildModule actions (map snd supportExterns) (snd singleModule) + _ -> P.make actions (map fst supportExterns ++ map snd ms) + +assert + :: [(P.Module, P.ExternsFile)] + -> [FilePath] + -> ([P.Module] -> IO ()) + -> (Either P.MultipleErrors P.MultipleErrors -> IO (Maybe String)) + -> Expectation +assert supportExterns inputFiles check f = do + (e, w) <- compile supportExterns inputFiles check + maybeErr <- f (const w <$> e) + maybe (return ()) expectationFailure maybeErr + +checkMain :: [P.Module] -> IO () +checkMain ms = + unless (any ((== P.moduleNameFromString "Main") . P.getModuleName) ms) + (fail "Main module missing") + +checkShouldFailWith :: [String] -> P.MultipleErrors -> Maybe String +checkShouldFailWith expected errs = + let actual = map P.errorCode $ P.runMultipleErrors errs + in if sort expected == sort actual + then Nothing + else Just $ "Expected these errors: " ++ show expected ++ ", but got these: " ++ show actual + +assertCompiles + :: [(P.Module, P.ExternsFile)] + -> [FilePath] + -> Expectation +assertCompiles supportExterns inputFiles = + assert supportExterns inputFiles checkMain $ \e -> case e of - Left errs -> return . Just . P.prettyPrintMultipleErrors False $ errs + Left errs -> return . Just . P.prettyPrintMultipleErrors P.defaultPPEOptions $ errs Right _ -> do process <- findNodeProcess let entryPoint = modulesDir </> "index.js" writeFile entryPoint "require('Main').main()" result <- traverse (\node -> readProcessWithExitCode node [entryPoint] "") process case result of - Just (ExitSuccess, out, _) -> putStrLn out >> return Nothing + Just (ExitSuccess, out, err) + | not (null err) -> return $ Just $ "Test wrote to stderr:\n\n" <> err + | not (null out) && trim (last (lines out)) == "Done" -> return Nothing + | otherwise -> return $ Just $ "Test did not finish with 'Done':\n\n" <> out Just (ExitFailure _, _, err) -> return $ Just err Nothing -> return $ Just "Couldn't find node.js executable" -assertDoesNotCompile :: [FilePath] -> M.Map P.ModuleName FilePath -> TestM () -assertDoesNotCompile inputFiles foreigns = do - let testFile = last inputFiles - liftIO . putStrLn $ "Assert " ++ testFile ++ " does not compile" - shouldFailWith <- getShouldFailWith testFile - assert inputFiles foreigns $ \e -> +assertCompilesWithWarnings + :: [(P.Module, P.ExternsFile)] + -> [FilePath] + -> [String] + -> Expectation +assertCompilesWithWarnings supportExterns inputFiles shouldWarnWith = + assert supportExterns inputFiles checkMain $ \e -> + case e of + Left errs -> + return . Just . P.prettyPrintMultipleErrors P.defaultPPEOptions $ errs + Right warnings -> + return + . fmap (printAllWarnings warnings) + $ checkShouldFailWith shouldWarnWith warnings + + where + printAllWarnings warnings = + (<> "\n\n" <> P.prettyPrintMultipleErrors P.defaultPPEOptions warnings) + +assertDoesNotCompile + :: [(P.Module, P.ExternsFile)] + -> [FilePath] + -> [String] + -> Expectation +assertDoesNotCompile supportExterns inputFiles shouldFailWith = + assert supportExterns inputFiles noPreCheck $ \e -> case e of - Left errs -> do - putStrLn (P.prettyPrintMultipleErrors False errs) + Left errs -> return $ if null shouldFailWith then Just $ "shouldFailWith declaration is missing (errors were: " ++ show (map P.errorCode (P.runMultipleErrors errs)) @@ -164,31 +283,4 @@ assertDoesNotCompile inputFiles foreigns = do return $ Just "Should not have compiled" where - getShouldFailWith = - readUTF8File - >>> liftIO - >>> fmap ( lines - >>> mapMaybe (stripPrefix "-- @shouldFailWith ") - >>> map trim - ) - - checkShouldFailWith expected errs = - let actual = map P.errorCode $ P.runMultipleErrors errs - in if sort expected == sort actual - then Nothing - else Just $ "Expected these errors: " ++ show expected ++ ", but got these: " ++ show actual - - trim = - dropWhile isSpace >>> reverse >>> dropWhile isSpace >>> reverse - -supportModules :: [String] -supportModules = - [ "Control.Monad.Eff.Class" - , "Control.Monad.Eff.Console" - , "Control.Monad.Eff" - , "Control.Monad.Eff.Unsafe" - , "Control.Monad.ST" - , "Data.Function" - , "Prelude" - , "Test.Assert" - ] + noPreCheck = const (return ()) diff --git a/tests/TestDocs.hs b/tests/TestDocs.hs index dff2da4..6a645c1 100644 --- a/tests/TestDocs.hs +++ b/tests/TestDocs.hs @@ -197,7 +197,7 @@ checkConstrained ty tyClass = False where matches className = - (==) className . P.runProperName . P.disqualify . fst + (==) className . P.runProperName . P.disqualify . P.constraintClass runAssertionIO :: Assertion -> Docs.Module -> IO () runAssertionIO assertion mdl = do @@ -266,13 +266,8 @@ testCases = ]) , ("TypeClassWithoutMembers", - [ ShouldBeDocumented (n "Intermediate") "SomeClass" [] - , ChildShouldNotBeDocumented (n "Intermediate") "SomeClass" "member" - ]) - - -- Remove this after 0.9. - , ("OldOperators", - [ ShouldBeDocumented (n "OldOperators2") "(>>)" [] + [ ShouldBeDocumented (n "TypeClassWithoutMembersIntermediate") "SomeClass" [] + , ChildShouldNotBeDocumented (n "TypeClassWithoutMembersIntermediate") "SomeClass" "member" ]) , ("NewOperators", diff --git a/tests/TestPscIde.hs b/tests/TestPscIde.hs index 1a6e072..d90b9d2 100644 --- a/tests/TestPscIde.hs +++ b/tests/TestPscIde.hs @@ -1,7 +1,14 @@ module TestPscIde where +import Control.Monad (unless) +import Language.PureScript.Ide.Integration import qualified PscIdeSpec -import Test.Hspec +import Test.Hspec main :: IO () -main = hspec PscIdeSpec.spec +main = do + deleteOutputFolder + s <- compileTestProject + unless s $ fail "Failed to compile .purs sources" + + withServer (hspec PscIdeSpec.spec) diff --git a/tests/TestPscPublish.hs b/tests/TestPscPublish.hs index af84c96..1c55a8a 100644 --- a/tests/TestPscPublish.hs +++ b/tests/TestPscPublish.hs @@ -24,7 +24,7 @@ import Language.PureScript.Publish.ErrorsWarnings as Publish import TestUtils main :: IO () -main = testPackage "tests/support/prelude" +main = testPackage "tests/support/bower_components/purescript-prelude" data TestResult = ParseFailed String diff --git a/tests/TestPsci.hs b/tests/TestPsci.hs index ee0a2c1..1047607 100644 --- a/tests/TestPsci.hs +++ b/tests/TestPsci.hs @@ -6,10 +6,8 @@ module TestPsci where import Prelude () import Prelude.Compat -import Control.Monad.Trans.State.Strict (runStateT) -import Control.Monad (when, forM) -import Control.Monad.Writer.Strict (runWriterT) -import Control.Monad.Trans.Except (runExceptT) +import Control.Monad.Trans.State.Strict (evalStateT) +import Control.Monad (when) import Data.List (sort) @@ -17,16 +15,17 @@ import System.Exit (exitFailure) import System.Console.Haskeline import System.FilePath ((</>)) import System.Directory (getCurrentDirectory) -import System.IO.UTF8 (readUTF8File) import qualified System.FilePath.Glob as Glob import Test.HUnit import qualified Language.PureScript as P -import PSCi.Module (loadAllModules) -import PSCi.Completion -import PSCi.Types +import Language.PureScript.Interactive.Module (loadAllModules) +import Language.PureScript.Interactive.Completion +import Language.PureScript.Interactive.Types + +import TestUtils (supportModules) main :: IO () main = do @@ -47,11 +46,10 @@ completionTests = completionTestData :: [(String, [String])] completionTestData = -- basic directives - [ (":h", [":help"]) + [ (":h", [":help"]) , (":re", [":reset"]) - , (":q", [":quit"]) - , (":mo", [":module"]) - , (":b", [":browse"]) + , (":q", [":quit"]) + , (":b", [":browse"]) -- :browse should complete module names , (":b Control.Monad.E", map (":b Control.Monad.Eff" ++) ["", ".Unsafe", ".Class", ".Console"]) @@ -60,11 +58,6 @@ completionTestData = -- import should complete module names , ("import Control.Monad.E", map ("import Control.Monad.Eff" ++) ["", ".Unsafe", ".Class", ".Console"]) , ("import Control.Monad.Eff.", map ("import Control.Monad.Eff" ++) [".Unsafe", ".Class", ".Console"]) - , ("import qualified Control.Monad.Eff.", map ("import qualified Control.Monad.Eff" ++) [".Unsafe", ".Class", ".Console"]) - - -- :load, :module should complete file paths - , (":l tests/support/psci/", [":l tests/support/psci/Sample.purs"]) - , (":module tests/support/psci/", [":module tests/support/psci/Sample.purs"]) -- :quit, :help, :reset should not complete , (":help ", []) @@ -76,13 +69,13 @@ completionTestData = , (":show a", []) -- :type should complete values and data constructors in scope - , (":type Control.Monad.Eff.Console.lo", [":type Control.Monad.Eff.Console.log"]) - , (":type uni", [":type unit"]) - , (":type E", [":type EQ"]) + , (":type Control.Monad.Eff.Console.lo", [":type Control.Monad.Eff.Console.log", ":type Control.Monad.Eff.Console.logShow"]) + --, (":type uni", [":type unit"]) + --, (":type E", [":type EQ"]) -- :kind should complete types in scope - , (":kind C", [":kind Control.Monad.Eff.Pure"]) - , (":kind O", [":kind Ordering"]) + --, (":kind C", [":kind Control.Monad.Eff.Pure"]) + --, (":kind O", [":kind Ordering"]) -- Only one argument for directives should be completed , (":show import ", []) @@ -91,8 +84,7 @@ completionTestData = -- a few other import tests , ("impor", ["import"]) - , ("import q", ["import qualified"]) - , ("import ", map ("import " ++) supportModules ++ ["import qualified"]) + , ("import ", map ("import " ++) supportModules) , ("import Prelude ", []) -- String and number literals should not be completed @@ -100,10 +92,10 @@ completionTestData = , ("34", []) -- Identifiers and data constructors should be completed - , ("uni", ["unit"]) + --, ("uni", ["unit"]) , ("Control.Monad.Eff.Class.", ["Control.Monad.Eff.Class.liftEff"]) - , ("G", ["GT"]) - , ("Prelude.L", ["Prelude.LT"]) + --, ("G", ["GT"]) + , ("Data.Ordering.L", ["Data.Ordering.LT"]) -- if a module is imported qualified, values should complete under the -- qualified name, as well as the original name. @@ -122,39 +114,25 @@ assertCompletedOk (line, expecteds) = do runCM :: CompletionM a -> IO a runCM act = do psciState <- getPSCiState - fmap fst (runStateT (liftCompletionM act) psciState) + evalStateT (liftCompletionM act) psciState getPSCiState :: IO PSCiState getPSCiState = do cwd <- getCurrentDirectory - let supportDir = cwd </> "tests" </> "support" </> "flattened" - let supportFiles ext = Glob.globDir1 (Glob.compile ("*." ++ ext)) supportDir + let supportDir = cwd </> "tests" </> "support" </> "bower_components" + let supportFiles ext = Glob.globDir1 (Glob.compile ("purescript-*/**/*." ++ ext)) supportDir pursFiles <- supportFiles "purs" - jsFiles <- supportFiles "js" modulesOrFirstError <- loadAllModules pursFiles - foreignFiles <- forM jsFiles (\f -> (f,) <$> readUTF8File f) - Right (foreigns, _) <- runExceptT $ runWriterT $ P.parseForeignModulesFromFiles foreignFiles case modulesOrFirstError of Left err -> print err >> exitFailure Right modules -> let imports = [controlMonadSTasST, (P.ModuleName [P.ProperName "Prelude"], P.Implicit, Nothing)] - in return (mkPSCiState imports modules foreigns [] []) + dummyExterns = P.internalError "TestPsci: dummyExterns should not be used" + in return (PSCiState imports [] (zip (map snd modules) (repeat dummyExterns))) controlMonadSTasST :: ImportedModule controlMonadSTasST = (s "Control.Monad.ST", P.Implicit, Just (s "ST")) where s = P.moduleNameFromString - -supportModules :: [String] -supportModules = - [ "Control.Monad.Eff.Class" - , "Control.Monad.Eff.Console" - , "Control.Monad.Eff" - , "Control.Monad.Eff.Unsafe" - , "Control.Monad.ST" - , "Data.Function" - , "Prelude" - , "Test.Assert" - ] diff --git a/tests/TestUtils.hs b/tests/TestUtils.hs index 7195db2..1f01d03 100644 --- a/tests/TestUtils.hs +++ b/tests/TestUtils.hs @@ -1,15 +1,3 @@ ------------------------------------------------------------------------------ --- --- Module : Main --- License : MIT (http://opensource.org/licenses/MIT) --- --- Maintainer : Phil Freeman <paf31@cantab.net> --- Stability : experimental --- Portability : --- --- | --- ------------------------------------------------------------------------------ {-# LANGUAGE ScopedTypeVariables #-} module TestUtils where @@ -17,7 +5,6 @@ module TestUtils where import Prelude () import Prelude.Compat -import Data.Maybe (fromMaybe) import Control.Monad import Control.Monad.Trans.Maybe import Control.Exception @@ -26,8 +13,6 @@ import System.Process import System.Directory import System.Info -import Language.PureScript.Crash - findNodeProcess :: IO (Maybe String) findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names where @@ -43,7 +28,6 @@ findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names -- updateSupportCode :: IO () updateSupportCode = do - node <- fromMaybe (internalError "cannot find node executable") <$> findNodeProcess setCurrentDirectory "tests/support" if System.Info.os == "mingw32" then callProcess "setup-win.cmd" [] @@ -52,9 +36,51 @@ updateSupportCode = do -- Sometimes we run as a root (e.g. in simple docker containers) -- And we are non-interactive: https://github.com/bower/bower/issues/1162 callProcess "node_modules/.bin/bower" ["--allow-root", "install", "--config.interactive=false"] - callProcess node ["setup.js"] setCurrentDirectory "../.." +-- | +-- The support modules that should be cached between test cases, to avoid +-- excessive rebuilding. +-- +supportModules :: [String] +supportModules = + [ "Control.Applicative" + , "Control.Apply" + , "Control.Bind" + , "Control.Category" + , "Control.Monad.Eff.Class" + , "Control.Monad.Eff.Console" + , "Control.Monad.Eff.Unsafe" + , "Control.Monad.Eff" + , "Control.Monad.ST" + , "Control.Monad" + , "Control.Semigroupoid" + , "Data.Boolean" + , "Data.BooleanAlgebra" + , "Data.Bounded" + , "Data.CommutativeRing" + , "Data.Eq" + , "Data.EuclideanRing" + , "Data.Field" + , "Data.Function.Uncurried" + , "Data.Function" + , "Data.Functor" + , "Data.HeytingAlgebra" + , "Data.Ord.Unsafe" + , "Data.Ord" + , "Data.Ordering" + , "Data.Ring" + , "Data.Semigroup" + , "Data.Semiring" + , "Data.Show" + , "Data.Unit" + , "Data.Void" + , "Partial" + , "Partial.Unsafe" + , "Prelude" + , "Test.Assert" + ] + pushd :: forall a. FilePath -> IO a -> IO a pushd dir act = do original <- getCurrentDirectory @@ -62,4 +88,3 @@ pushd dir act = do result <- try act :: IO (Either IOException a) setCurrentDirectory original either throwIO return result - diff --git a/tests/support/bower.json b/tests/support/bower.json index c29e6e8..ca9d449 100644 --- a/tests/support/bower.json +++ b/tests/support/bower.json @@ -1,11 +1,12 @@ { "name": "purescript-test-suite-support", "dependencies": { - "purescript-eff": "0.1.0", - "purescript-prelude": "0.1.3", - "purescript-assert": "0.1.1", - "purescript-st": "0.1.0", - "purescript-console": "0.1.0", - "purescript-functions": "0.1.0" + "purescript-assert": "1.0.0-rc.1", + "purescript-console": "1.0.0-rc.1", + "purescript-eff": "1.0.0-rc.1", + "purescript-functions": "1.0.0-rc.1", + "purescript-prelude": "1.0.0-rc.3", + "purescript-st": "1.0.0-rc.1", + "purescript-partial": "1.1.2" } } diff --git a/tests/support/flattened/Control-Monad-Eff-Class.purs b/tests/support/flattened/Control-Monad-Eff-Class.purs deleted file mode 100644 index dbfd58e..0000000 --- a/tests/support/flattened/Control-Monad-Eff-Class.purs +++ /dev/null @@ -1,24 +0,0 @@ -module Control.Monad.Eff.Class - ( MonadEff - , liftEff - ) where - -import Prelude - -import Control.Monad.Eff - --- | The `MonadEff` class captures those monads which support native effects. --- | --- | Instances are provided for `Eff` itself, and the standard monad transformers. --- | --- | `liftEff` can be used in any appropriate monad transformer stack to lift an action --- | of type `Eff eff a` into the monad. --- | --- | Note that `MonadEff` is parameterized by the row of effects, so type inference can be --- | tricky. It is generally recommended to either work with a polymorphic row of effects, --- | or a concrete, closed row of effects such as `(trace :: Trace)`. -class (Monad m) <= MonadEff eff m where - liftEff :: forall a. Eff eff a -> m a - -instance monadEffEff :: MonadEff eff (Eff eff) where - liftEff = id diff --git a/tests/support/flattened/Control-Monad-Eff-Console.js b/tests/support/flattened/Control-Monad-Eff-Console.js deleted file mode 100644 index 9ccfc26..0000000 --- a/tests/support/flattened/Control-Monad-Eff-Console.js +++ /dev/null @@ -1,18 +0,0 @@ -/* global exports, console */ -"use strict"; - -// module Control.Monad.Eff.Console - -exports.log = function (s) { - return function () { - console.log(s); - return {}; - }; -}; - -exports.error = function (s) { - return function () { - console.error(s); - return {}; - }; -}; diff --git a/tests/support/flattened/Control-Monad-Eff-Console.purs b/tests/support/flattened/Control-Monad-Eff-Console.purs deleted file mode 100644 index 0a03ee4..0000000 --- a/tests/support/flattened/Control-Monad-Eff-Console.purs +++ /dev/null @@ -1,18 +0,0 @@ -module Control.Monad.Eff.Console where - -import Prelude - -import Control.Monad.Eff - --- | The `CONSOLE` effect represents those computations which write to the console. -foreign import data CONSOLE :: ! - --- | Write a message to the console. -foreign import log :: forall eff. String -> Eff (console :: CONSOLE | eff) Unit - --- | Write an error to the console. -foreign import error :: forall eff. String -> Eff (console :: CONSOLE | eff) Unit - --- | Write a value to the console, using its `Show` instance to produce a `String`. -print :: forall a eff. (Show a) => a -> Eff (console :: CONSOLE | eff) Unit -print = log <<< show diff --git a/tests/support/flattened/Control-Monad-Eff-Unsafe.js b/tests/support/flattened/Control-Monad-Eff-Unsafe.js deleted file mode 100644 index bada18a..0000000 --- a/tests/support/flattened/Control-Monad-Eff-Unsafe.js +++ /dev/null @@ -1,8 +0,0 @@ -/* global exports */ -"use strict"; - -// module Control.Monad.Eff.Unsafe - -exports.unsafeInterleaveEff = function (f) { - return f; -}; diff --git a/tests/support/flattened/Control-Monad-Eff-Unsafe.purs b/tests/support/flattened/Control-Monad-Eff-Unsafe.purs deleted file mode 100644 index 5d6f104..0000000 --- a/tests/support/flattened/Control-Monad-Eff-Unsafe.purs +++ /dev/null @@ -1,10 +0,0 @@ -module Control.Monad.Eff.Unsafe where - -import Prelude - -import Control.Monad.Eff - --- | Change the type of an effectful computation, allowing it to be run in another context. --- | --- | Note: use of this function can result in arbitrary side-effects. -foreign import unsafeInterleaveEff :: forall eff1 eff2 a. Eff eff1 a -> Eff eff2 a diff --git a/tests/support/flattened/Control-Monad-Eff.js b/tests/support/flattened/Control-Monad-Eff.js deleted file mode 100644 index 1498f21..0000000 --- a/tests/support/flattened/Control-Monad-Eff.js +++ /dev/null @@ -1,62 +0,0 @@ -/* global exports */ -"use strict"; - -// module Control.Monad.Eff - -exports.returnE = function (a) { - return function () { - return a; - }; -}; - -exports.bindE = function (a) { - return function (f) { - return function () { - return f(a())(); - }; - }; -}; - -exports.runPure = function (f) { - return f(); -}; - -exports.untilE = function (f) { - return function () { - while (!f()); - return {}; - }; -}; - -exports.whileE = function (f) { - return function (a) { - return function () { - while (f()) { - a(); - } - return {}; - }; - }; -}; - -exports.forE = function (lo) { - return function (hi) { - return function (f) { - return function () { - for (var i = lo; i < hi; i++) { - f(i)(); - } - }; - }; - }; -}; - -exports.foreachE = function (as) { - return function (f) { - return function () { - for (var i = 0, l = as.length; i < l; i++) { - f(as[i])(); - } - }; - }; -}; diff --git a/tests/support/flattened/Control-Monad-Eff.purs b/tests/support/flattened/Control-Monad-Eff.purs deleted file mode 100644 index 0417c19..0000000 --- a/tests/support/flattened/Control-Monad-Eff.purs +++ /dev/null @@ -1,67 +0,0 @@ -module Control.Monad.Eff - ( Eff() - , Pure() - , runPure - , untilE, whileE, forE, foreachE - ) where - -import Prelude - --- | The `Eff` type constructor is used to represent _native_ effects. --- | --- | See [Handling Native Effects with the Eff Monad](https://github.com/purescript/purescript/wiki/Handling-Native-Effects-with-the-Eff-Monad) for more details. --- | --- | 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. -foreign import data Eff :: # ! -> * -> * - -foreign import returnE :: forall e a. a -> Eff e a - -foreign import bindE :: forall e a b. Eff e a -> (a -> Eff e b) -> Eff e b - --- | The `Pure` type synonym represents _pure_ computations, i.e. ones in which all effects have been handled. --- | --- | The `runPure` function can be used to run pure computations and obtain their result. -type Pure a = forall e. Eff e a - --- | Run a pure computation and return its result. --- | --- | Note: since this function has a rank-2 type, it may cause problems to apply this function using the `$` operator. The recommended approach --- | is to use parentheses instead. -foreign import runPure :: forall a. Pure a -> a - -instance functorEff :: Functor (Eff e) where - map = liftA1 - -instance applyEff :: Apply (Eff e) where - apply = ap - -instance applicativeEff :: Applicative (Eff e) where - pure = returnE - -instance bindEff :: Bind (Eff e) where - bind = bindE - -instance monadEff :: Monad (Eff e) - --- | Loop until a condition becomes `true`. --- | --- | `untilE b` is an effectful computation which repeatedly runs the effectful computation `b`, --- | until its return value is `true`. -foreign import untilE :: forall e. Eff e Boolean -> Eff e Unit - --- | Loop while a condition is `true`. --- | --- | `whileE b m` is effectful computation which runs the effectful computation `b`. If its result is --- | `true`, it runs the effectful computation `m` and loops. If not, the computation ends. -foreign import whileE :: forall e a. Eff e Boolean -> Eff e a -> Eff e Unit - --- | Loop over a consecutive collection of numbers. --- | --- | `forE lo hi f` runs the computation returned by the function `f` for each of the inputs --- | between `lo` (inclusive) and `hi` (exclusive). -foreign import forE :: forall e. Number -> Number -> (Number -> Eff e Unit) -> Eff e Unit - --- | Loop over an array of values. --- | --- | `foreach xs f` runs the computation returned by the function `f` for each of the inputs `xs`. -foreign import foreachE :: forall e a. Array a -> (a -> Eff e Unit) -> Eff e Unit diff --git a/tests/support/flattened/Control-Monad-ST.js b/tests/support/flattened/Control-Monad-ST.js deleted file mode 100644 index 64597c1..0000000 --- a/tests/support/flattened/Control-Monad-ST.js +++ /dev/null @@ -1,38 +0,0 @@ -/* global exports */ -"use strict"; - -// module Control.Monad.ST - -exports.newSTRef = function (val) { - return function () { - return { value: val }; - }; -}; - -exports.readSTRef = function (ref) { - return function () { - return ref.value; - }; -}; - -exports.modifySTRef = function (ref) { - return function (f) { - return function () { - /* jshint boss: true */ - return ref.value = f(ref.value); - }; - }; -}; - -exports.writeSTRef = function (ref) { - return function (a) { - return function () { - /* jshint boss: true */ - return ref.value = a; - }; - }; -}; - -exports.runST = function (f) { - return f; -}; diff --git a/tests/support/flattened/Control-Monad-ST.purs b/tests/support/flattened/Control-Monad-ST.purs deleted file mode 100644 index ac113e5..0000000 --- a/tests/support/flattened/Control-Monad-ST.purs +++ /dev/null @@ -1,42 +0,0 @@ -module Control.Monad.ST where - -import Prelude - -import Control.Monad.Eff (Eff(), runPure) - --- | The `ST` effect represents _local mutation_, i.e. mutation which does not "escape" into the surrounding computation. --- | --- | An `ST` computation is parameterized by a phantom type which is used to restrict the set of reference cells it is allowed to access. --- | --- | The `runST` function can be used to handle the `ST` effect. -foreign import data ST :: * -> ! - --- | The type `STRef s a` represents a mutable reference holding a value of type `a`, which can be used with the `ST s` effect. -foreign import data STRef :: * -> * -> * - --- | Create a new mutable reference. -foreign import newSTRef :: forall a h r. a -> Eff (st :: ST h | r) (STRef h a) - --- | Read the current value of a mutable reference. -foreign import readSTRef :: forall a h r. STRef h a -> Eff (st :: ST h | r) a - --- | Modify the value of a mutable reference by applying a function to the current value. -foreign import modifySTRef :: forall a h r. STRef h a -> (a -> a) -> Eff (st :: ST h | r) a - --- | Set the value of a mutable reference. -foreign import writeSTRef :: forall a h r. STRef h a -> a -> Eff (st :: ST h | r) a - --- | Run an `ST` computation. --- | --- | 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 --- | to the surrounding computation. --- | --- | It may cause problems to apply this function using the `$` operator. The recommended approach is to use parentheses instead. -foreign import runST :: forall a r. (forall h. Eff (st :: ST h | r) a) -> Eff r a - --- | A convenience function which combines `runST` with `runPure`, which can be used when the only required effect is `ST`. --- | --- | Note: since this function has a rank-2 type, it may cause problems to apply this function using the `$` operator. The recommended approach --- | is to use parentheses instead. -pureST :: forall a. (forall h r. Eff (st :: ST h | r) a) -> a -pureST st = runPure (runST st) diff --git a/tests/support/flattened/Data-Function.js b/tests/support/flattened/Data-Function.js deleted file mode 100644 index 0d6d0f4..0000000 --- a/tests/support/flattened/Data-Function.js +++ /dev/null @@ -1,233 +0,0 @@ -/* global exports */ -"use strict"; - -// module Data.Function - -exports.mkFn0 = function (fn) { - return function () { - return fn({}); - }; -}; - -exports.mkFn1 = function (fn) { - return function (a) { - return fn(a); - }; -}; - -exports.mkFn2 = function (fn) { - /* jshint maxparams: 2 */ - return function (a, b) { - return fn(a)(b); - }; -}; - -exports.mkFn3 = function (fn) { - /* jshint maxparams: 3 */ - return function (a, b, c) { - return fn(a)(b)(c); - }; -}; - -exports.mkFn4 = function (fn) { - /* jshint maxparams: 4 */ - return function (a, b, c, d) { - return fn(a)(b)(c)(d); - }; -}; - -exports.mkFn5 = function (fn) { - /* jshint maxparams: 5 */ - return function (a, b, c, d, e) { - return fn(a)(b)(c)(d)(e); - }; -}; - -exports.mkFn6 = function (fn) { - /* jshint maxparams: 6 */ - return function (a, b, c, d, e, f) { - return fn(a)(b)(c)(d)(e)(f); - }; -}; - -exports.mkFn7 = function (fn) { - /* jshint maxparams: 7 */ - return function (a, b, c, d, e, f, g) { - return fn(a)(b)(c)(d)(e)(f)(g); - }; -}; - -exports.mkFn8 = function (fn) { - /* jshint maxparams: 8 */ - return function (a, b, c, d, e, f, g, h) { - return fn(a)(b)(c)(d)(e)(f)(g)(h); - }; -}; - -exports.mkFn9 = function (fn) { - /* jshint maxparams: 9 */ - return function (a, b, c, d, e, f, g, h, i) { - return fn(a)(b)(c)(d)(e)(f)(g)(h)(i); - }; -}; - -exports.mkFn10 = function (fn) { - /* jshint maxparams: 10 */ - return function (a, b, c, d, e, f, g, h, i, j) { - return fn(a)(b)(c)(d)(e)(f)(g)(h)(i)(j); - }; -}; - -exports.runFn0 = function (fn) { - return fn(); -}; - -exports.runFn1 = function (fn) { - return function (a) { - return fn(a); - }; -}; - -exports.runFn2 = function (fn) { - return function (a) { - return function (b) { - return fn(a, b); - }; - }; -}; - -exports.runFn3 = function (fn) { - return function (a) { - return function (b) { - return function (c) { - return fn(a, b, c); - }; - }; - }; -}; - -exports.runFn4 = function (fn) { - return function (a) { - return function (b) { - return function (c) { - return function (d) { - return fn(a, b, c, d); - }; - }; - }; - }; -}; - -exports.runFn5 = function (fn) { - return function (a) { - return function (b) { - return function (c) { - return function (d) { - return function (e) { - return fn(a, b, c, d, e); - }; - }; - }; - }; - }; -}; - -exports.runFn6 = function (fn) { - return function (a) { - return function (b) { - return function (c) { - return function (d) { - return function (e) { - return function (f) { - return fn(a, b, c, d, e, f); - }; - }; - }; - }; - }; - }; -}; - -exports.runFn7 = function (fn) { - return function (a) { - return function (b) { - return function (c) { - return function (d) { - return function (e) { - return function (f) { - return function (g) { - return fn(a, b, c, d, e, f, g); - }; - }; - }; - }; - }; - }; - }; -}; - -exports.runFn8 = function (fn) { - return function (a) { - return function (b) { - return function (c) { - return function (d) { - return function (e) { - return function (f) { - return function (g) { - return function (h) { - return fn(a, b, c, d, e, f, g, h); - }; - }; - }; - }; - }; - }; - }; - }; -}; - -exports.runFn9 = function (fn) { - return function (a) { - return function (b) { - return function (c) { - return function (d) { - return function (e) { - return function (f) { - return function (g) { - return function (h) { - return function (i) { - return fn(a, b, c, d, e, f, g, h, i); - }; - }; - }; - }; - }; - }; - }; - }; - }; -}; - -exports.runFn10 = function (fn) { - return function (a) { - return function (b) { - return function (c) { - return function (d) { - return function (e) { - return function (f) { - return function (g) { - return function (h) { - return function (i) { - return function (j) { - return fn(a, b, c, d, e, f, g, h, i, j); - }; - }; - }; - }; - }; - }; - }; - }; - }; - }; -}; diff --git a/tests/support/flattened/Data-Function.purs b/tests/support/flattened/Data-Function.purs deleted file mode 100644 index 37ceca1..0000000 --- a/tests/support/flattened/Data-Function.purs +++ /dev/null @@ -1,113 +0,0 @@ -module Data.Function where - -import Prelude - --- | The `on` function is used to change the domain of a binary operator. --- | --- | For example, we can create a function which compares two records based on the values of their `x` properties: --- | --- | ```purescript --- | compareX :: forall r. { x :: Number | r } -> { x :: Number | r } -> Ordering --- | compareX = compare `on` _.x --- | ``` -on :: forall a b c. (b -> b -> c) -> (a -> b) -> a -> a -> c -on f g x y = g x `f` g y - --- | A function of zero arguments -foreign import data Fn0 :: * -> * - --- | A function of one argument -foreign import data Fn1 :: * -> * -> * - --- | A function of two arguments -foreign import data Fn2 :: * -> * -> * -> * - --- | A function of three arguments -foreign import data Fn3 :: * -> * -> * -> * -> * - --- | A function of four arguments -foreign import data Fn4 :: * -> * -> * -> * -> * -> * - --- | A function of five arguments -foreign import data Fn5 :: * -> * -> * -> * -> * -> * -> * - --- | A function of six arguments -foreign import data Fn6 :: * -> * -> * -> * -> * -> * -> * -> * - --- | A function of seven arguments -foreign import data Fn7 :: * -> * -> * -> * -> * -> * -> * -> * -> * - --- | A function of eight arguments -foreign import data Fn8 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * - --- | A function of nine arguments -foreign import data Fn9 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * - --- | A function of ten arguments -foreign import data Fn10 :: * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * -> * - --- | Create a function of no arguments -foreign import mkFn0 :: forall a. (Unit -> a) -> Fn0 a - --- | Create a function of one argument -foreign import mkFn1 :: forall a b. (a -> b) -> Fn1 a b - --- | Create a function of two arguments from a curried function -foreign import mkFn2 :: forall a b c. (a -> b -> c) -> Fn2 a b c - --- | Create a function of three arguments from a curried function -foreign import mkFn3 :: forall a b c d. (a -> b -> c -> d) -> Fn3 a b c d - --- | Create a function of four arguments from a curried function -foreign import mkFn4 :: forall a b c d e. (a -> b -> c -> d -> e) -> Fn4 a b c d e - --- | Create a function of five arguments from a curried function -foreign import mkFn5 :: forall a b c d e f. (a -> b -> c -> d -> e -> f) -> Fn5 a b c d e f - --- | Create a function of six arguments from a curried function -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 - --- | Create a function of seven arguments from a curried function -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 - --- | Create a function of eight arguments from a curried function -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 - --- | Create a function of nine arguments from a curried function -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 - --- | Create a function of ten arguments from a curried function -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 - --- | Apply a function of no arguments -foreign import runFn0 :: forall a. Fn0 a -> a - --- | Apply a function of one argument -foreign import runFn1 :: forall a b. Fn1 a b -> a -> b - --- | Apply a function of two arguments -foreign import runFn2 :: forall a b c. Fn2 a b c -> a -> b -> c - --- | Apply a function of three arguments -foreign import runFn3 :: forall a b c d. Fn3 a b c d -> a -> b -> c -> d - --- | Apply a function of four arguments -foreign import runFn4 :: forall a b c d e. Fn4 a b c d e -> a -> b -> c -> d -> e - --- | Apply a function of five arguments -foreign import runFn5 :: forall a b c d e f. Fn5 a b c d e f -> a -> b -> c -> d -> e -> f - --- | Apply a function of six arguments -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 - --- | Apply a function of seven arguments -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 - --- | Apply a function of eight arguments -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 - --- | Apply a function of nine arguments -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 - --- | Apply a function of ten arguments -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 diff --git a/tests/support/flattened/Prelude.js b/tests/support/flattened/Prelude.js deleted file mode 100644 index 72a855a..0000000 --- a/tests/support/flattened/Prelude.js +++ /dev/null @@ -1,228 +0,0 @@ -/* global exports */ -"use strict"; - -// module Prelude - -//- Functor -------------------------------------------------------------------- - -exports.arrayMap = function (f) { - return function (arr) { - var l = arr.length; - var result = new Array(l); - for (var i = 0; i < l; i++) { - result[i] = f(arr[i]); - } - return result; - }; -}; - -//- Bind ----------------------------------------------------------------------- - -exports.arrayBind = function (arr) { - return function (f) { - var result = []; - for (var i = 0, l = arr.length; i < l; i++) { - Array.prototype.push.apply(result, f(arr[i])); - } - return result; - }; -}; - -//- Monoid --------------------------------------------------------------------- - -exports.concatString = function (s1) { - return function (s2) { - return s1 + s2; - }; -}; - -exports.concatArray = function (xs) { - return function (ys) { - return xs.concat(ys); - }; -}; - -//- Semiring ------------------------------------------------------------------- - -exports.intAdd = function (x) { - return function (y) { - /* jshint bitwise: false */ - return x + y | 0; - }; -}; - -exports.intMul = function (x) { - return function (y) { - /* jshint bitwise: false */ - return x * y | 0; - }; -}; - -exports.numAdd = function (n1) { - return function (n2) { - return n1 + n2; - }; -}; - -exports.numMul = function (n1) { - return function (n2) { - return n1 * n2; - }; -}; - -//- ModuloSemiring ------------------------------------------------------------- - -exports.intDiv = function (x) { - return function (y) { - /* jshint bitwise: false */ - return x / y | 0; - }; -}; - -exports.intMod = function (x) { - return function (y) { - return x % y; - }; -}; - -exports.numDiv = function (n1) { - return function (n2) { - return n1 / n2; - }; -}; - -//- Ring ----------------------------------------------------------------------- - -exports.intSub = function (x) { - return function (y) { - /* jshint bitwise: false */ - return x - y | 0; - }; -}; - -exports.numSub = function (n1) { - return function (n2) { - return n1 - n2; - }; -}; - -//- Eq ------------------------------------------------------------------------- - -exports.refEq = function (r1) { - return function (r2) { - return r1 === r2; - }; -}; - -exports.refIneq = function (r1) { - return function (r2) { - return r1 !== r2; - }; -}; - -exports.eqArrayImpl = function (f) { - return function (xs) { - return function (ys) { - if (xs.length !== ys.length) return false; - for (var i = 0; i < xs.length; i++) { - if (!f(xs[i])(ys[i])) return false; - } - return true; - }; - }; -}; - -exports.ordArrayImpl = function (f) { - return function (xs) { - return function (ys) { - var i = 0; - var xlen = xs.length; - var ylen = ys.length; - while (i < xlen && i < ylen) { - var x = xs[i]; - var y = ys[i]; - var o = f(x)(y); - if (o !== 0) { - return o; - } - i++; - } - if (xlen === ylen) { - return 0; - } else if (xlen > ylen) { - return -1; - } else { - return 1; - } - }; - }; -}; - -//- Ord ------------------------------------------------------------------------ - -exports.unsafeCompareImpl = function (lt) { - return function (eq) { - return function (gt) { - return function (x) { - return function (y) { - return x < y ? lt : x > y ? gt : eq; - }; - }; - }; - }; -}; - -//- Bounded -------------------------------------------------------------------- - -exports.topInt = 2147483647; -exports.bottomInt = -2147483648; - -exports.topChar = String.fromCharCode(65535); -exports.bottomChar = String.fromCharCode(0); - -//- BooleanAlgebra ------------------------------------------------------------- - -exports.boolOr = function (b1) { - return function (b2) { - return b1 || b2; - }; -}; - -exports.boolAnd = function (b1) { - return function (b2) { - return b1 && b2; - }; -}; - -exports.boolNot = function (b) { - return !b; -}; - -//- Show ----------------------------------------------------------------------- - -exports.showIntImpl = function (n) { - return n.toString(); -}; - -exports.showNumberImpl = function (n) { - /* jshint bitwise: false */ - return n === (n | 0) ? n + ".0" : n.toString(); -}; - -exports.showCharImpl = function (c) { - return c === "'" ? "'\\''" : "'" + c + "'"; -}; - -exports.showStringImpl = function (s) { - return JSON.stringify(s); -}; - -exports.showArrayImpl = function (f) { - return function (xs) { - var ss = []; - for (var i = 0, l = xs.length; i < l; i++) { - ss[i] = f(xs[i]); - } - return "[" + ss.join(",") + "]"; - }; -}; diff --git a/tests/support/flattened/Prelude.purs b/tests/support/flattened/Prelude.purs deleted file mode 100644 index 21ec909..0000000 --- a/tests/support/flattened/Prelude.purs +++ /dev/null @@ -1,872 +0,0 @@ -module Prelude - ( Unit(), unit - , ($), (#) - , flip - , const - , asTypeOf - , otherwise - , Semigroupoid, compose, (<<<), (>>>) - , Category, id - , Functor, map, (<$>), (<#>), void - , Apply, apply, (<*>) - , Applicative, pure, liftA1 - , Bind, bind, (>>=) - , Monad, return, liftM1, ap - , Semigroup, append, (<>), (++) - , Semiring, add, zero, mul, one, (+), (*) - , ModuloSemiring, div, mod, (/) - , Ring, sub, negate, (-) - , Num - , DivisionRing - , Eq, eq, (==), (/=) - , Ordering(..), Ord, compare, (<), (>), (<=), (>=) - , unsafeCompare - , Bounded, top, bottom - , BoundedOrd - , BooleanAlgebra, conj, disj, not, (&&), (||) - , Show, show - ) where - --- | The `Unit` type has a single inhabitant, called `unit`. It represents --- | values with no computational content. --- | --- | `Unit` is often used, wrapped in a monadic type constructor, as the --- | return type of a computation where only --- | the _effects_ are important. -newtype Unit = Unit {} - --- | `unit` is the sole inhabitant of the `Unit` type. -unit :: Unit -unit = Unit {} - -infixr 0 $ -infixl 1 # - --- | Applies a function to its argument. --- | --- | ```purescript --- | length $ groupBy productCategory $ filter isInStock $ products --- | ``` --- | --- | is equivalent to: --- | --- | ```purescript --- | length (groupBy productCategory (filter isInStock products)) --- | ``` --- | --- | `($)` is different from [`(#)`](#-2) because it is right-infix instead of --- | left: `a $ b $ c $ d x = a $ (b $ (c $ (d $ x))) = a (b (c (d x)))` -($) :: forall a b. (a -> b) -> a -> b -($) f x = f x - --- | Applies an argument to a function. --- | --- | ```purescript --- | products # filter isInStock # groupBy productCategory # length --- | ``` --- | --- | is equivalent to: --- | --- | ```purescript --- | length (groupBy productCategory (filter isInStock products)) --- | ``` --- | --- | `(#)` is different from [`($)`](#-1) because it is left-infix instead of --- | right: `x # a # b # c # d = (((x # a) # b) # c) # d = d (c (b (a x)))` -(#) :: forall a b. a -> (a -> b) -> b -(#) x f = f x - --- | Flips the order of the arguments to a function of two arguments. --- | --- | ```purescript --- | flip const 1 2 = const 2 1 = 2 --- | ``` -flip :: forall a b c. (a -> b -> c) -> b -> a -> c -flip f b a = f a b - --- | Returns its first argument and ignores its second. --- | --- | ```purescript --- | const 1 "hello" = 1 --- | ``` -const :: forall a b. a -> b -> a -const a _ = a - --- | This function returns its first argument, and can be used to assert type --- | equalities. This can be useful when types are otherwise ambiguous. --- | --- | ```purescript --- | main = print $ [] `asTypeOf` [0] --- | ``` --- | --- | If instead, we had written `main = print []`, the type of the argument --- | `[]` would have been ambiguous, resulting in a compile-time error. -asTypeOf :: forall a. a -> a -> a -asTypeOf x _ = x - --- | An alias for `true`, which can be useful in guard clauses: --- | --- | ```purescript --- | max x y | x >= y = x --- | | otherwise = y --- | ``` -otherwise :: Boolean -otherwise = true - --- | A `Semigroupoid` is similar to a [`Category`](#category) but does not --- | require an identity element `id`, just composable morphisms. --- | --- | `Semigroupoid`s must satisfy the following law: --- | --- | - Associativity: `p <<< (q <<< r) = (p <<< q) <<< r` --- | --- | One example of a `Semigroupoid` is the function type constructor `(->)`, --- | with `(<<<)` defined as function composition. -class Semigroupoid a where - compose :: forall b c d. a c d -> a b c -> a b d - -instance semigroupoidFn :: Semigroupoid (->) where - compose f g x = f (g x) - -infixr 9 >>> -infixr 9 <<< - --- | `(<<<)` is an alias for `compose`. -(<<<) :: forall a b c d. (Semigroupoid a) => a c d -> a b c -> a b d -(<<<) = compose - --- | Forwards composition, or `(<<<)` with its arguments reversed. -(>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d -(>>>) = flip compose - --- | `Category`s consist of objects and composable morphisms between them, and --- | as such are [`Semigroupoids`](#semigroupoid), but unlike `semigroupoids` --- | must have an identity element. --- | --- | Instances must satisfy the following law in addition to the --- | `Semigroupoid` law: --- | --- | - Identity: `id <<< p = p <<< id = p` -class (Semigroupoid a) <= Category a where - id :: forall t. a t t - -instance categoryFn :: Category (->) where - id x = x - --- | A `Functor` is a type constructor which supports a mapping operation --- | `(<$>)`. --- | --- | `(<$>)` can be used to turn functions `a -> b` into functions --- | `f a -> f b` whose argument and return types use the type constructor `f` --- | to represent some computational context. --- | --- | Instances must satisfy the following laws: --- | --- | - Identity: `(<$>) id = id` --- | - Composition: `(<$>) (f <<< g) = (f <$>) <<< (g <$>)` -class Functor f where - map :: forall a b. (a -> b) -> f a -> f b - -instance functorFn :: Functor ((->) r) where - map = compose - -instance functorArray :: Functor Array where - map = arrayMap - -foreign import arrayMap :: forall a b. (a -> b) -> Array a -> Array b - -infixl 4 <$> -infixl 1 <#> - --- | `(<$>)` is an alias for `map` -(<$>) :: forall f a b. (Functor f) => (a -> b) -> f a -> f b -(<$>) = map - --- | `(<#>)` is `(<$>)` with its arguments reversed. For example: --- | --- | ```purescript --- | [1, 2, 3] <#> \n -> n * n --- | ``` -(<#>) :: forall f a b. (Functor f) => f a -> (a -> b) -> f b -(<#>) fa f = f <$> fa - --- | The `void` function is used to ignore the type wrapped by a --- | [`Functor`](#functor), replacing it with `Unit` and keeping only the type --- | information provided by the type constructor itself. --- | --- | `void` is often useful when using `do` notation to change the return type --- | of a monadic computation: --- | --- | ```purescript --- | main = forE 1 10 \n -> void do --- | print n --- | print (n * n) --- | ``` -void :: forall f a. (Functor f) => f a -> f Unit -void fa = const unit <$> fa - --- | The `Apply` class provides the `(<*>)` which is used to apply a function --- | to an argument under a type constructor. --- | --- | `Apply` can be used to lift functions of two or more arguments to work on --- | values wrapped with the type constructor `f`. It might also be understood --- | in terms of the `lift2` function: --- | --- | ```purescript --- | lift2 :: forall f a b c. (Apply f) => (a -> b -> c) -> f a -> f b -> f c --- | lift2 f a b = f <$> a <*> b --- | ``` --- | --- | `(<*>)` is recovered from `lift2` as `lift2 ($)`. That is, `(<*>)` lifts --- | the function application operator `($)` to arguments wrapped with the --- | type constructor `f`. --- | --- | Instances must satisfy the following law in addition to the `Functor` --- | laws: --- | --- | - Associative composition: `(<<<) <$> f <*> g <*> h = f <*> (g <*> h)` --- | --- | Formally, `Apply` represents a strong lax semi-monoidal endofunctor. -class (Functor f) <= Apply f where - apply :: forall a b. f (a -> b) -> f a -> f b - -instance applyFn :: Apply ((->) r) where - apply f g x = f x (g x) - -instance applyArray :: Apply Array where - apply = ap - -infixl 4 <*> - --- | `(<*>)` is an alias for `apply`. -(<*>) :: forall f a b. (Apply f) => f (a -> b) -> f a -> f b -(<*>) = apply - --- | The `Applicative` type class extends the [`Apply`](#apply) type class --- | with a `pure` function, which can be used to create values of type `f a` --- | from values of type `a`. --- | --- | Where [`Apply`](#apply) provides the ability to lift functions of two or --- | more arguments to functions whose arguments are wrapped using `f`, and --- | [`Functor`](#functor) provides the ability to lift functions of one --- | argument, `pure` can be seen as the function which lifts functions of --- | _zero_ arguments. That is, `Applicative` functors support a lifting --- | operation for any number of function arguments. --- | --- | Instances must satisfy the following laws in addition to the `Apply` --- | laws: --- | --- | - Identity: `(pure id) <*> v = v` --- | - Composition: `(pure <<<) <*> f <*> g <*> h = f <*> (g <*> h)` --- | - Homomorphism: `(pure f) <*> (pure x) = pure (f x)` --- | - Interchange: `u <*> (pure y) = (pure ($ y)) <*> u` -class (Apply f) <= Applicative f where - pure :: forall a. a -> f a - -instance applicativeFn :: Applicative ((->) r) where - pure = const - -instance applicativeArray :: Applicative Array where - pure x = [x] - --- | `return` is an alias for `pure`. -return :: forall m a. (Applicative m) => a -> m a -return = pure - --- | `liftA1` provides a default implementation of `(<$>)` for any --- | [`Applicative`](#applicative) functor, without using `(<$>)` as provided --- | by the [`Functor`](#functor)-[`Applicative`](#applicative) superclass --- | relationship. --- | --- | `liftA1` can therefore be used to write [`Functor`](#functor) instances --- | as follows: --- | --- | ```purescript --- | instance functorF :: Functor F where --- | map = liftA1 --- | ``` -liftA1 :: forall f a b. (Applicative f) => (a -> b) -> f a -> f b -liftA1 f a = pure f <*> a - --- | The `Bind` type class extends the [`Apply`](#apply) type class with a --- | "bind" operation `(>>=)` which composes computations in sequence, using --- | the return value of one computation to determine the next computation. --- | --- | The `>>=` operator can also be expressed using `do` notation, as follows: --- | --- | ```purescript --- | x >>= f = do y <- x --- | f y --- | ``` --- | --- | where the function argument of `f` is given the name `y`. --- | --- | Instances must satisfy the following law in addition to the `Apply` --- | laws: --- | --- | - Associativity: `(x >>= f) >>= g = x >>= (\k => f k >>= g)` --- | --- | Associativity tells us that we can regroup operations which use `do` --- | notation so that we can unambiguously write, for example: --- | --- | ```purescript --- | do x <- m1 --- | y <- m2 x --- | m3 x y --- | ``` -class (Apply m) <= Bind m where - bind :: forall a b. m a -> (a -> m b) -> m b - -instance bindFn :: Bind ((->) r) where - bind m f x = f (m x) x - -instance bindArray :: Bind Array where - bind = arrayBind - -foreign import arrayBind :: forall a b. Array a -> (a -> Array b) -> Array b - -infixl 1 >>= - --- | `(>>=)` is an alias for `bind`. -(>>=) :: forall m a b. (Bind m) => m a -> (a -> m b) -> m b -(>>=) = bind - --- | The `Monad` type class combines the operations of the `Bind` and --- | `Applicative` type classes. Therefore, `Monad` instances represent type --- | constructors which support sequential composition, and also lifting of --- | functions of arbitrary arity. --- | --- | Instances must satisfy the following laws in addition to the --- | `Applicative` and `Bind` laws: --- | --- | - Left Identity: `pure x >>= f = f x` --- | - Right Identity: `x >>= pure = x` -class (Applicative m, Bind m) <= Monad m - -instance monadFn :: Monad ((->) r) -instance monadArray :: Monad Array - --- | `liftM1` provides a default implementation of `(<$>)` for any --- | [`Monad`](#monad), without using `(<$>)` as provided by the --- | [`Functor`](#functor)-[`Monad`](#monad) superclass relationship. --- | --- | `liftM1` can therefore be used to write [`Functor`](#functor) instances --- | as follows: --- | --- | ```purescript --- | instance functorF :: Functor F where --- | map = liftM1 --- | ``` -liftM1 :: forall m a b. (Monad m) => (a -> b) -> m a -> m b -liftM1 f a = do - a' <- a - return (f a') - --- | `ap` provides a default implementation of `(<*>)` for any --- | [`Monad`](#monad), without using `(<*>)` as provided by the --- | [`Apply`](#apply)-[`Monad`](#monad) superclass relationship. --- | --- | `ap` can therefore be used to write [`Apply`](#apply) instances as --- | follows: --- | --- | ```purescript --- | instance applyF :: Apply F where --- | apply = ap --- | ``` -ap :: forall m a b. (Monad m) => m (a -> b) -> m a -> m b -ap f a = do - f' <- f - a' <- a - return (f' a') - --- | The `Semigroup` type class identifies an associative operation on a type. --- | --- | Instances are required to satisfy the following law: --- | --- | - Associativity: `(x <> y) <> z = x <> (y <> z)` --- | --- | One example of a `Semigroup` is `String`, with `(<>)` defined as string --- | concatenation. -class Semigroup a where - append :: a -> a -> a - -infixr 5 <> -infixr 5 ++ - --- | `(<>)` is an alias for `append`. -(<>) :: forall s. (Semigroup s) => s -> s -> s -(<>) = append - --- | `(++)` is an alternative alias for `append`. -(++) :: forall s. (Semigroup s) => s -> s -> s -(++) = append - -instance semigroupString :: Semigroup String where - append = concatString - -instance semigroupUnit :: Semigroup Unit where - append _ _ = unit - -instance semigroupFn :: (Semigroup s') => Semigroup (s -> s') where - append f g = \x -> f x <> g x - -instance semigroupOrdering :: Semigroup Ordering where - append LT _ = LT - append GT _ = GT - append EQ y = y - -instance semigroupArray :: Semigroup (Array a) where - append = concatArray - -foreign import concatString :: String -> String -> String -foreign import concatArray :: forall a. Array a -> Array a -> Array a - --- | The `Semiring` class is for types that support an addition and --- | multiplication operation. --- | --- | Instances must satisfy the following laws: --- | --- | - Commutative monoid under addition: --- | - Associativity: `(a + b) + c = a + (b + c)` --- | - Identity: `zero + a = a + zero = a` --- | - Commutative: `a + b = b + a` --- | - Monoid under multiplication: --- | - Associativity: `(a * b) * c = a * (b * c)` --- | - Identity: `one * a = a * one = a` --- | - Multiplication distributes over addition: --- | - Left distributivity: `a * (b + c) = (a * b) + (a * c)` --- | - Right distributivity: `(a + b) * c = (a * c) + (b * c)` --- | - Annihiliation: `zero * a = a * zero = zero` -class Semiring a where - add :: a -> a -> a - zero :: a - mul :: a -> a -> a - one :: a - -instance semiringInt :: Semiring Int where - add = intAdd - zero = 0 - mul = intMul - one = 1 - -instance semiringNumber :: Semiring Number where - add = numAdd - zero = 0.0 - mul = numMul - one = 1.0 - -instance semiringUnit :: Semiring Unit where - add _ _ = unit - zero = unit - mul _ _ = unit - one = unit - -infixl 6 + -infixl 7 * - --- | `(+)` is an alias for `add`. -(+) :: forall a. (Semiring a) => a -> a -> a -(+) = add - --- | `(*)` is an alias for `mul`. -(*) :: forall a. (Semiring a) => a -> a -> a -(*) = mul - -foreign import intAdd :: Int -> Int -> Int -foreign import intMul :: Int -> Int -> Int -foreign import numAdd :: Number -> Number -> Number -foreign import numMul :: Number -> Number -> Number - --- | The `Ring` class is for types that support addition, multiplication, --- | and subtraction operations. --- | --- | Instances must satisfy the following law in addition to the `Semiring` --- | laws: --- | --- | - Additive inverse: `a - a = (zero - a) + a = zero` -class (Semiring a) <= Ring a where - sub :: a -> a -> a - -instance ringInt :: Ring Int where - sub = intSub - -instance ringNumber :: Ring Number where - sub = numSub - -instance ringUnit :: Ring Unit where - sub _ _ = unit - -infixl 6 - - --- | `(-)` is an alias for `sub`. -(-) :: forall a. (Ring a) => a -> a -> a -(-) = sub - --- | `negate x` can be used as a shorthand for `zero - x`. -negate :: forall a. (Ring a) => a -> a -negate a = zero - a - -foreign import intSub :: Int -> Int -> Int -foreign import numSub :: Number -> Number -> Number - --- | The `ModuloSemiring` class is for types that support addition, --- | multiplication, division, and modulo (division remainder) operations. --- | --- | Instances must satisfy the following law in addition to the `Semiring` --- | laws: --- | --- | - Remainder: ``a / b * b + (a `mod` b) = a`` -class (Semiring a) <= ModuloSemiring a where - div :: a -> a -> a - mod :: a -> a -> a - -instance moduloSemiringInt :: ModuloSemiring Int where - div = intDiv - mod = intMod - -instance moduloSemiringNumber :: ModuloSemiring Number where - div = numDiv - mod _ _ = 0.0 - -instance moduloSemiringUnit :: ModuloSemiring Unit where - div _ _ = unit - mod _ _ = unit - -infixl 7 / - --- | `(/)` is an alias for `div`. -(/) :: forall a. (ModuloSemiring a) => a -> a -> a -(/) = div - -foreign import intDiv :: Int -> Int -> Int -foreign import numDiv :: Number -> Number -> Number -foreign import intMod :: Int -> Int -> Int - --- | A `Ring` where every nonzero element has a multiplicative inverse. --- | --- | Instances must satisfy the following law in addition to the `Ring` and --- | `ModuloSemiring` laws: --- | --- | - Multiplicative inverse: `(one / x) * x = one` --- | --- | As a consequence of this ```a `mod` b = zero``` as no divide operation --- | will have a remainder. -class (Ring a, ModuloSemiring a) <= DivisionRing a - -instance divisionRingNumber :: DivisionRing Number -instance divisionRingUnit :: DivisionRing Unit - --- | The `Num` class is for types that are commutative fields. --- | --- | Instances must satisfy the following law in addition to the --- | `DivisionRing` laws: --- | --- | - Commutative multiplication: `a * b = b * a` -class (DivisionRing a) <= Num a - -instance numNumber :: Num Number -instance numUnit :: Num Unit - --- | The `Eq` type class represents types which support decidable equality. --- | --- | `Eq` instances should satisfy the following laws: --- | --- | - Reflexivity: `x == x = true` --- | - Symmetry: `x == y = y == x` --- | - Transitivity: if `x == y` and `y == z` then `x == z` -class Eq a where - eq :: a -> a -> Boolean - -infix 4 == -infix 4 /= - --- | `(==)` is an alias for `eq`. Tests whether one value is equal to another. -(==) :: forall a. (Eq a) => a -> a -> Boolean -(==) = eq - --- | `(/=)` tests whether one value is _not equal_ to another. Shorthand for --- | `not (x == y)`. -(/=) :: forall a. (Eq a) => a -> a -> Boolean -(/=) x y = not (x == y) - -instance eqBoolean :: Eq Boolean where - eq = refEq - -instance eqInt :: Eq Int where - eq = refEq - -instance eqNumber :: Eq Number where - eq = refEq - -instance eqChar :: Eq Char where - eq = refEq - -instance eqString :: Eq String where - eq = refEq - -instance eqUnit :: Eq Unit where - eq _ _ = true - -instance eqArray :: (Eq a) => Eq (Array a) where - eq = eqArrayImpl (==) - -instance eqOrdering :: Eq Ordering where - eq LT LT = true - eq GT GT = true - eq EQ EQ = true - eq _ _ = false - -foreign import refEq :: forall a. a -> a -> Boolean -foreign import refIneq :: forall a. a -> a -> Boolean -foreign import eqArrayImpl :: forall a. (a -> a -> Boolean) -> Array a -> Array a -> Boolean - --- | The `Ordering` data type represents the three possible outcomes of --- | comparing two values: --- | --- | `LT` - The first value is _less than_ the second. --- | `GT` - The first value is _greater than_ the second. --- | `EQ` - The first value is _equal to_ the second. -data Ordering = LT | GT | EQ - --- | The `Ord` type class represents types which support comparisons with a --- | _total order_. --- | --- | `Ord` instances should satisfy the laws of total orderings: --- | --- | - Reflexivity: `a <= a` --- | - Antisymmetry: if `a <= b` and `b <= a` then `a = b` --- | - Transitivity: if `a <= b` and `b <= c` then `a <= c` -class (Eq a) <= Ord a where - compare :: a -> a -> Ordering - -instance ordBoolean :: Ord Boolean where - compare = unsafeCompare - -instance ordInt :: Ord Int where - compare = unsafeCompare - -instance ordNumber :: Ord Number where - compare = unsafeCompare - -instance ordString :: Ord String where - compare = unsafeCompare - -instance ordChar :: Ord Char where - compare = unsafeCompare - -instance ordUnit :: Ord Unit where - compare _ _ = EQ - -instance ordArray :: (Ord a) => Ord (Array a) where - compare xs ys = compare 0 $ ordArrayImpl (\x y -> case compare x y of - EQ -> 0 - LT -> 1 - GT -> -1) xs ys - -foreign import ordArrayImpl :: forall a. (a -> a -> Int) -> Array a -> Array a -> Int - -instance ordOrdering :: Ord Ordering where - compare LT LT = EQ - compare EQ EQ = EQ - compare GT GT = EQ - compare LT _ = LT - compare EQ LT = GT - compare EQ GT = LT - compare GT _ = GT - -infixl 4 < -infixl 4 > -infixl 4 <= -infixl 4 >= - --- | Test whether one value is _strictly less than_ another. -(<) :: forall a. (Ord a) => a -> a -> Boolean -(<) a1 a2 = case a1 `compare` a2 of - LT -> true - _ -> false - --- | Test whether one value is _strictly greater than_ another. -(>) :: forall a. (Ord a) => a -> a -> Boolean -(>) a1 a2 = case a1 `compare` a2 of - GT -> true - _ -> false - --- | Test whether one value is _non-strictly less than_ another. -(<=) :: forall a. (Ord a) => a -> a -> Boolean -(<=) a1 a2 = case a1 `compare` a2 of - GT -> false - _ -> true - --- | Test whether one value is _non-strictly greater than_ another. -(>=) :: forall a. (Ord a) => a -> a -> Boolean -(>=) a1 a2 = case a1 `compare` a2 of - LT -> false - _ -> true - -unsafeCompare :: forall a. a -> a -> Ordering -unsafeCompare = unsafeCompareImpl LT EQ GT - -foreign import unsafeCompareImpl :: forall a. Ordering -> Ordering -> Ordering -> a -> a -> Ordering - --- | The `Bounded` type class represents types that are finite. --- | --- | Although there are no "internal" laws for `Bounded`, every value of `a` --- | should be considered less than or equal to `top` by some means, and greater --- | than or equal to `bottom`. --- | --- | The lack of explicit `Ord` constraint allows flexibility in the use of --- | `Bounded` so it can apply to total and partially ordered sets, boolean --- | algebras, etc. -class Bounded a where - top :: a - bottom :: a - -instance boundedBoolean :: Bounded Boolean where - top = true - bottom = false - -instance boundedUnit :: Bounded Unit where - top = unit - bottom = unit - -instance boundedOrdering :: Bounded Ordering where - top = GT - bottom = LT - -instance boundedInt :: Bounded Int where - top = topInt - bottom = bottomInt - --- | Characters fall within the Unicode range. -instance boundedChar :: Bounded Char where - top = topChar - bottom = bottomChar - -instance boundedFn :: (Bounded b) => Bounded (a -> b) where - top _ = top - bottom _ = bottom - -foreign import topInt :: Int -foreign import bottomInt :: Int - -foreign import topChar :: Char -foreign import bottomChar :: Char - --- | The `BoundedOrd` type class represents totally ordered finite data types. --- | --- | Instances should satisfy the following law in addition to the `Ord` laws: --- | --- | - Ordering: `bottom <= a <= top` -class (Bounded a, Ord a) <= BoundedOrd a - -instance boundedOrdBoolean :: BoundedOrd Boolean where -instance boundedOrdUnit :: BoundedOrd Unit where -instance boundedOrdOrdering :: BoundedOrd Ordering where -instance boundedOrdInt :: BoundedOrd Int where -instance boundedOrdChar :: BoundedOrd Char where - --- | The `BooleanAlgebra` type class represents types that behave like boolean --- | values. --- | --- | Instances should satisfy the following laws in addition to the `Bounded` --- | laws: --- | --- | - Associativity: --- | - `a || (b || c) = (a || b) || c` --- | - `a && (b && c) = (a && b) && c` --- | - Commutativity: --- | - `a || b = b || a` --- | - `a && b = b && a` --- | - Distributivity: --- | - `a && (b || c) = (a && b) || (a && c)` --- | - `a || (b && c) = (a || b) && (a || c)` --- | - Identity: --- | - `a || bottom = a` --- | - `a && top = a` --- | - Idempotent: --- | - `a || a = a` --- | - `a && a = a` --- | - Absorption: --- | - `a || (a && b) = a` --- | - `a && (a || b) = a` --- | - Annhiliation: --- | - `a || top = top` --- | - Complementation: --- | - `a && not a = bottom` --- | - `a || not a = top` -class (Bounded a) <= BooleanAlgebra a where - conj :: a -> a -> a - disj :: a -> a -> a - not :: a -> a - -instance booleanAlgebraBoolean :: BooleanAlgebra Boolean where - conj = boolAnd - disj = boolOr - not = boolNot - -instance booleanAlgebraUnit :: BooleanAlgebra Unit where - conj _ _ = unit - disj _ _ = unit - not _ = unit - -instance booleanAlgebraFn :: (BooleanAlgebra b) => BooleanAlgebra (a -> b) where - conj fx fy a = fx a `conj` fy a - disj fx fy a = fx a `disj` fy a - not fx a = not (fx a) - -infixr 3 && -infixr 2 || - --- | `(&&)` is an alias for `conj`. -(&&) :: forall a. (BooleanAlgebra a) => a -> a -> a -(&&) = conj - --- | `(||)` is an alias for `disj`. -(||) :: forall a. (BooleanAlgebra a) => a -> a -> a -(||) = disj - -foreign import boolOr :: Boolean -> Boolean -> Boolean -foreign import boolAnd :: Boolean -> Boolean -> Boolean -foreign import boolNot :: Boolean -> Boolean - --- | The `Show` type class represents those types which can be converted into --- | a human-readable `String` representation. --- | --- | While not required, it is recommended that for any expression `x`, the --- | string `show x` be executable PureScript code which evaluates to the same --- | value as the expression `x`. -class Show a where - show :: a -> String - -instance showBoolean :: Show Boolean where - show true = "true" - show false = "false" - -instance showInt :: Show Int where - show = showIntImpl - -instance showNumber :: Show Number where - show = showNumberImpl - -instance showChar :: Show Char where - show = showCharImpl - -instance showString :: Show String where - show = showStringImpl - -instance showUnit :: Show Unit where - show _ = "unit" - -instance showArray :: (Show a) => Show (Array a) where - show = showArrayImpl show - -instance showOrdering :: Show Ordering where - show LT = "LT" - show GT = "GT" - show EQ = "EQ" - -foreign import showIntImpl :: Int -> String -foreign import showNumberImpl :: Number -> String -foreign import showCharImpl :: Char -> String -foreign import showStringImpl :: String -> String -foreign import showArrayImpl :: forall a. (a -> String) -> Array a -> String diff --git a/tests/support/flattened/Test-Assert.js b/tests/support/flattened/Test-Assert.js deleted file mode 100644 index ad1a67c..0000000 --- a/tests/support/flattened/Test-Assert.js +++ /dev/null @@ -1,27 +0,0 @@ -/* global exports */ -"use strict"; - -// module Test.Assert - -exports["assert'"] = function (message) { - return function (success) { - return function () { - if (!success) throw new Error(message); - return {}; - }; - }; -}; - -exports.checkThrows = function (fn) { - return function () { - try { - fn(); - return false; - } catch (e) { - if (e instanceof Error) return true; - var err = new Error("Threw something other than an Error"); - err.something = e; - throw err; - } - }; -}; diff --git a/tests/support/flattened/Test-Assert.purs b/tests/support/flattened/Test-Assert.purs deleted file mode 100644 index 66b8622..0000000 --- a/tests/support/flattened/Test-Assert.purs +++ /dev/null @@ -1,46 +0,0 @@ -module Test.Assert - ( assert' - , assert - , assertThrows - , assertThrows' - , ASSERT() - ) where - -import Control.Monad.Eff (Eff()) -import Prelude - --- | Assertion effect type. -foreign import data ASSERT :: ! - --- | Throws a runtime exception with message "Assertion failed" when the boolean --- | value is false. -assert :: forall e. Boolean -> Eff (assert :: ASSERT | e) Unit -assert = assert' "Assertion failed" - --- | Throws a runtime exception with the specified message when the boolean --- | value is false. -foreign import assert' :: forall e. String -> Boolean -> Eff (assert :: ASSERT | e) Unit - --- | Throws a runtime exception with message "Assertion failed: An error should --- | have been thrown", unless the argument throws an exception when evaluated. --- | --- | This function is specifically for testing unsafe pure code; for example, --- | to make sure that an exception is thrown if a precondition is not --- | satisfied. Functions which use `Eff (err :: EXCEPTION | eff) a` can be --- | tested with `catchException` instead. -assertThrows :: forall e a. (Unit -> a) -> Eff (assert :: ASSERT | e) Unit -assertThrows = assertThrows' "Assertion failed: An error should have been thrown" - --- | Throws a runtime exception with the specified message, unless the argument --- | throws an exception when evaluated. --- | --- | This function is specifically for testing unsafe pure code; for example, --- | to make sure that an exception is thrown if a precondition is not --- | satisfied. Functions which use `Eff (err :: EXCEPTION | eff) a` can be --- | tested with `catchException` instead. -assertThrows' :: forall e a. String -> (Unit -> a) -> Eff (assert :: ASSERT | e) Unit -assertThrows' msg fn = - checkThrows fn >>= assert' msg - - -foreign import checkThrows :: forall e a. (Unit -> a) -> Eff (assert :: ASSERT | e) Boolean diff --git a/tests/support/package.json b/tests/support/package.json index fa08203..18aa9a7 100644 --- a/tests/support/package.json +++ b/tests/support/package.json @@ -2,6 +2,7 @@ "private": true, "dependencies": { "bower": "^1.4.1", - "glob": "^5.0.14" + "glob": "^5.0.14", + "rimraf": "^2.5.2" } } diff --git a/tests/support/prelude/LICENSE b/tests/support/prelude/LICENSE deleted file mode 100644 index d3249fe..0000000 --- a/tests/support/prelude/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 PureScript - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/tests/support/prelude/bower.json b/tests/support/prelude/bower.json deleted file mode 100644 index 4182b35..0000000 --- a/tests/support/prelude/bower.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "purescript-prelude", - "homepage": "https://github.com/purescript/purescript-prelude", - "description": "The PureScript Prelude", - "keywords": [ - "purescript" - ], - "license": "MIT", - "repository": { - "type": "git", - "url": "git://github.com/purescript/purescript-prelude.git" - }, - "ignore": [ - "**/.*", - "bower_components", - "node_modules", - "output", - "test", - "bower.json", - "gulpfile.js", - "package.json" - ] -} diff --git a/tests/support/prelude/src/Prelude.js b/tests/support/prelude/src/Prelude.js deleted file mode 100644 index 72a855a..0000000 --- a/tests/support/prelude/src/Prelude.js +++ /dev/null @@ -1,228 +0,0 @@ -/* global exports */ -"use strict"; - -// module Prelude - -//- Functor -------------------------------------------------------------------- - -exports.arrayMap = function (f) { - return function (arr) { - var l = arr.length; - var result = new Array(l); - for (var i = 0; i < l; i++) { - result[i] = f(arr[i]); - } - return result; - }; -}; - -//- Bind ----------------------------------------------------------------------- - -exports.arrayBind = function (arr) { - return function (f) { - var result = []; - for (var i = 0, l = arr.length; i < l; i++) { - Array.prototype.push.apply(result, f(arr[i])); - } - return result; - }; -}; - -//- Monoid --------------------------------------------------------------------- - -exports.concatString = function (s1) { - return function (s2) { - return s1 + s2; - }; -}; - -exports.concatArray = function (xs) { - return function (ys) { - return xs.concat(ys); - }; -}; - -//- Semiring ------------------------------------------------------------------- - -exports.intAdd = function (x) { - return function (y) { - /* jshint bitwise: false */ - return x + y | 0; - }; -}; - -exports.intMul = function (x) { - return function (y) { - /* jshint bitwise: false */ - return x * y | 0; - }; -}; - -exports.numAdd = function (n1) { - return function (n2) { - return n1 + n2; - }; -}; - -exports.numMul = function (n1) { - return function (n2) { - return n1 * n2; - }; -}; - -//- ModuloSemiring ------------------------------------------------------------- - -exports.intDiv = function (x) { - return function (y) { - /* jshint bitwise: false */ - return x / y | 0; - }; -}; - -exports.intMod = function (x) { - return function (y) { - return x % y; - }; -}; - -exports.numDiv = function (n1) { - return function (n2) { - return n1 / n2; - }; -}; - -//- Ring ----------------------------------------------------------------------- - -exports.intSub = function (x) { - return function (y) { - /* jshint bitwise: false */ - return x - y | 0; - }; -}; - -exports.numSub = function (n1) { - return function (n2) { - return n1 - n2; - }; -}; - -//- Eq ------------------------------------------------------------------------- - -exports.refEq = function (r1) { - return function (r2) { - return r1 === r2; - }; -}; - -exports.refIneq = function (r1) { - return function (r2) { - return r1 !== r2; - }; -}; - -exports.eqArrayImpl = function (f) { - return function (xs) { - return function (ys) { - if (xs.length !== ys.length) return false; - for (var i = 0; i < xs.length; i++) { - if (!f(xs[i])(ys[i])) return false; - } - return true; - }; - }; -}; - -exports.ordArrayImpl = function (f) { - return function (xs) { - return function (ys) { - var i = 0; - var xlen = xs.length; - var ylen = ys.length; - while (i < xlen && i < ylen) { - var x = xs[i]; - var y = ys[i]; - var o = f(x)(y); - if (o !== 0) { - return o; - } - i++; - } - if (xlen === ylen) { - return 0; - } else if (xlen > ylen) { - return -1; - } else { - return 1; - } - }; - }; -}; - -//- Ord ------------------------------------------------------------------------ - -exports.unsafeCompareImpl = function (lt) { - return function (eq) { - return function (gt) { - return function (x) { - return function (y) { - return x < y ? lt : x > y ? gt : eq; - }; - }; - }; - }; -}; - -//- Bounded -------------------------------------------------------------------- - -exports.topInt = 2147483647; -exports.bottomInt = -2147483648; - -exports.topChar = String.fromCharCode(65535); -exports.bottomChar = String.fromCharCode(0); - -//- BooleanAlgebra ------------------------------------------------------------- - -exports.boolOr = function (b1) { - return function (b2) { - return b1 || b2; - }; -}; - -exports.boolAnd = function (b1) { - return function (b2) { - return b1 && b2; - }; -}; - -exports.boolNot = function (b) { - return !b; -}; - -//- Show ----------------------------------------------------------------------- - -exports.showIntImpl = function (n) { - return n.toString(); -}; - -exports.showNumberImpl = function (n) { - /* jshint bitwise: false */ - return n === (n | 0) ? n + ".0" : n.toString(); -}; - -exports.showCharImpl = function (c) { - return c === "'" ? "'\\''" : "'" + c + "'"; -}; - -exports.showStringImpl = function (s) { - return JSON.stringify(s); -}; - -exports.showArrayImpl = function (f) { - return function (xs) { - var ss = []; - for (var i = 0, l = xs.length; i < l; i++) { - ss[i] = f(xs[i]); - } - return "[" + ss.join(",") + "]"; - }; -}; diff --git a/tests/support/prelude/src/Prelude.purs b/tests/support/prelude/src/Prelude.purs deleted file mode 100644 index 21ec909..0000000 --- a/tests/support/prelude/src/Prelude.purs +++ /dev/null @@ -1,872 +0,0 @@ -module Prelude - ( Unit(), unit - , ($), (#) - , flip - , const - , asTypeOf - , otherwise - , Semigroupoid, compose, (<<<), (>>>) - , Category, id - , Functor, map, (<$>), (<#>), void - , Apply, apply, (<*>) - , Applicative, pure, liftA1 - , Bind, bind, (>>=) - , Monad, return, liftM1, ap - , Semigroup, append, (<>), (++) - , Semiring, add, zero, mul, one, (+), (*) - , ModuloSemiring, div, mod, (/) - , Ring, sub, negate, (-) - , Num - , DivisionRing - , Eq, eq, (==), (/=) - , Ordering(..), Ord, compare, (<), (>), (<=), (>=) - , unsafeCompare - , Bounded, top, bottom - , BoundedOrd - , BooleanAlgebra, conj, disj, not, (&&), (||) - , Show, show - ) where - --- | The `Unit` type has a single inhabitant, called `unit`. It represents --- | values with no computational content. --- | --- | `Unit` is often used, wrapped in a monadic type constructor, as the --- | return type of a computation where only --- | the _effects_ are important. -newtype Unit = Unit {} - --- | `unit` is the sole inhabitant of the `Unit` type. -unit :: Unit -unit = Unit {} - -infixr 0 $ -infixl 1 # - --- | Applies a function to its argument. --- | --- | ```purescript --- | length $ groupBy productCategory $ filter isInStock $ products --- | ``` --- | --- | is equivalent to: --- | --- | ```purescript --- | length (groupBy productCategory (filter isInStock products)) --- | ``` --- | --- | `($)` is different from [`(#)`](#-2) because it is right-infix instead of --- | left: `a $ b $ c $ d x = a $ (b $ (c $ (d $ x))) = a (b (c (d x)))` -($) :: forall a b. (a -> b) -> a -> b -($) f x = f x - --- | Applies an argument to a function. --- | --- | ```purescript --- | products # filter isInStock # groupBy productCategory # length --- | ``` --- | --- | is equivalent to: --- | --- | ```purescript --- | length (groupBy productCategory (filter isInStock products)) --- | ``` --- | --- | `(#)` is different from [`($)`](#-1) because it is left-infix instead of --- | right: `x # a # b # c # d = (((x # a) # b) # c) # d = d (c (b (a x)))` -(#) :: forall a b. a -> (a -> b) -> b -(#) x f = f x - --- | Flips the order of the arguments to a function of two arguments. --- | --- | ```purescript --- | flip const 1 2 = const 2 1 = 2 --- | ``` -flip :: forall a b c. (a -> b -> c) -> b -> a -> c -flip f b a = f a b - --- | Returns its first argument and ignores its second. --- | --- | ```purescript --- | const 1 "hello" = 1 --- | ``` -const :: forall a b. a -> b -> a -const a _ = a - --- | This function returns its first argument, and can be used to assert type --- | equalities. This can be useful when types are otherwise ambiguous. --- | --- | ```purescript --- | main = print $ [] `asTypeOf` [0] --- | ``` --- | --- | If instead, we had written `main = print []`, the type of the argument --- | `[]` would have been ambiguous, resulting in a compile-time error. -asTypeOf :: forall a. a -> a -> a -asTypeOf x _ = x - --- | An alias for `true`, which can be useful in guard clauses: --- | --- | ```purescript --- | max x y | x >= y = x --- | | otherwise = y --- | ``` -otherwise :: Boolean -otherwise = true - --- | A `Semigroupoid` is similar to a [`Category`](#category) but does not --- | require an identity element `id`, just composable morphisms. --- | --- | `Semigroupoid`s must satisfy the following law: --- | --- | - Associativity: `p <<< (q <<< r) = (p <<< q) <<< r` --- | --- | One example of a `Semigroupoid` is the function type constructor `(->)`, --- | with `(<<<)` defined as function composition. -class Semigroupoid a where - compose :: forall b c d. a c d -> a b c -> a b d - -instance semigroupoidFn :: Semigroupoid (->) where - compose f g x = f (g x) - -infixr 9 >>> -infixr 9 <<< - --- | `(<<<)` is an alias for `compose`. -(<<<) :: forall a b c d. (Semigroupoid a) => a c d -> a b c -> a b d -(<<<) = compose - --- | Forwards composition, or `(<<<)` with its arguments reversed. -(>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d -(>>>) = flip compose - --- | `Category`s consist of objects and composable morphisms between them, and --- | as such are [`Semigroupoids`](#semigroupoid), but unlike `semigroupoids` --- | must have an identity element. --- | --- | Instances must satisfy the following law in addition to the --- | `Semigroupoid` law: --- | --- | - Identity: `id <<< p = p <<< id = p` -class (Semigroupoid a) <= Category a where - id :: forall t. a t t - -instance categoryFn :: Category (->) where - id x = x - --- | A `Functor` is a type constructor which supports a mapping operation --- | `(<$>)`. --- | --- | `(<$>)` can be used to turn functions `a -> b` into functions --- | `f a -> f b` whose argument and return types use the type constructor `f` --- | to represent some computational context. --- | --- | Instances must satisfy the following laws: --- | --- | - Identity: `(<$>) id = id` --- | - Composition: `(<$>) (f <<< g) = (f <$>) <<< (g <$>)` -class Functor f where - map :: forall a b. (a -> b) -> f a -> f b - -instance functorFn :: Functor ((->) r) where - map = compose - -instance functorArray :: Functor Array where - map = arrayMap - -foreign import arrayMap :: forall a b. (a -> b) -> Array a -> Array b - -infixl 4 <$> -infixl 1 <#> - --- | `(<$>)` is an alias for `map` -(<$>) :: forall f a b. (Functor f) => (a -> b) -> f a -> f b -(<$>) = map - --- | `(<#>)` is `(<$>)` with its arguments reversed. For example: --- | --- | ```purescript --- | [1, 2, 3] <#> \n -> n * n --- | ``` -(<#>) :: forall f a b. (Functor f) => f a -> (a -> b) -> f b -(<#>) fa f = f <$> fa - --- | The `void` function is used to ignore the type wrapped by a --- | [`Functor`](#functor), replacing it with `Unit` and keeping only the type --- | information provided by the type constructor itself. --- | --- | `void` is often useful when using `do` notation to change the return type --- | of a monadic computation: --- | --- | ```purescript --- | main = forE 1 10 \n -> void do --- | print n --- | print (n * n) --- | ``` -void :: forall f a. (Functor f) => f a -> f Unit -void fa = const unit <$> fa - --- | The `Apply` class provides the `(<*>)` which is used to apply a function --- | to an argument under a type constructor. --- | --- | `Apply` can be used to lift functions of two or more arguments to work on --- | values wrapped with the type constructor `f`. It might also be understood --- | in terms of the `lift2` function: --- | --- | ```purescript --- | lift2 :: forall f a b c. (Apply f) => (a -> b -> c) -> f a -> f b -> f c --- | lift2 f a b = f <$> a <*> b --- | ``` --- | --- | `(<*>)` is recovered from `lift2` as `lift2 ($)`. That is, `(<*>)` lifts --- | the function application operator `($)` to arguments wrapped with the --- | type constructor `f`. --- | --- | Instances must satisfy the following law in addition to the `Functor` --- | laws: --- | --- | - Associative composition: `(<<<) <$> f <*> g <*> h = f <*> (g <*> h)` --- | --- | Formally, `Apply` represents a strong lax semi-monoidal endofunctor. -class (Functor f) <= Apply f where - apply :: forall a b. f (a -> b) -> f a -> f b - -instance applyFn :: Apply ((->) r) where - apply f g x = f x (g x) - -instance applyArray :: Apply Array where - apply = ap - -infixl 4 <*> - --- | `(<*>)` is an alias for `apply`. -(<*>) :: forall f a b. (Apply f) => f (a -> b) -> f a -> f b -(<*>) = apply - --- | The `Applicative` type class extends the [`Apply`](#apply) type class --- | with a `pure` function, which can be used to create values of type `f a` --- | from values of type `a`. --- | --- | Where [`Apply`](#apply) provides the ability to lift functions of two or --- | more arguments to functions whose arguments are wrapped using `f`, and --- | [`Functor`](#functor) provides the ability to lift functions of one --- | argument, `pure` can be seen as the function which lifts functions of --- | _zero_ arguments. That is, `Applicative` functors support a lifting --- | operation for any number of function arguments. --- | --- | Instances must satisfy the following laws in addition to the `Apply` --- | laws: --- | --- | - Identity: `(pure id) <*> v = v` --- | - Composition: `(pure <<<) <*> f <*> g <*> h = f <*> (g <*> h)` --- | - Homomorphism: `(pure f) <*> (pure x) = pure (f x)` --- | - Interchange: `u <*> (pure y) = (pure ($ y)) <*> u` -class (Apply f) <= Applicative f where - pure :: forall a. a -> f a - -instance applicativeFn :: Applicative ((->) r) where - pure = const - -instance applicativeArray :: Applicative Array where - pure x = [x] - --- | `return` is an alias for `pure`. -return :: forall m a. (Applicative m) => a -> m a -return = pure - --- | `liftA1` provides a default implementation of `(<$>)` for any --- | [`Applicative`](#applicative) functor, without using `(<$>)` as provided --- | by the [`Functor`](#functor)-[`Applicative`](#applicative) superclass --- | relationship. --- | --- | `liftA1` can therefore be used to write [`Functor`](#functor) instances --- | as follows: --- | --- | ```purescript --- | instance functorF :: Functor F where --- | map = liftA1 --- | ``` -liftA1 :: forall f a b. (Applicative f) => (a -> b) -> f a -> f b -liftA1 f a = pure f <*> a - --- | The `Bind` type class extends the [`Apply`](#apply) type class with a --- | "bind" operation `(>>=)` which composes computations in sequence, using --- | the return value of one computation to determine the next computation. --- | --- | The `>>=` operator can also be expressed using `do` notation, as follows: --- | --- | ```purescript --- | x >>= f = do y <- x --- | f y --- | ``` --- | --- | where the function argument of `f` is given the name `y`. --- | --- | Instances must satisfy the following law in addition to the `Apply` --- | laws: --- | --- | - Associativity: `(x >>= f) >>= g = x >>= (\k => f k >>= g)` --- | --- | Associativity tells us that we can regroup operations which use `do` --- | notation so that we can unambiguously write, for example: --- | --- | ```purescript --- | do x <- m1 --- | y <- m2 x --- | m3 x y --- | ``` -class (Apply m) <= Bind m where - bind :: forall a b. m a -> (a -> m b) -> m b - -instance bindFn :: Bind ((->) r) where - bind m f x = f (m x) x - -instance bindArray :: Bind Array where - bind = arrayBind - -foreign import arrayBind :: forall a b. Array a -> (a -> Array b) -> Array b - -infixl 1 >>= - --- | `(>>=)` is an alias for `bind`. -(>>=) :: forall m a b. (Bind m) => m a -> (a -> m b) -> m b -(>>=) = bind - --- | The `Monad` type class combines the operations of the `Bind` and --- | `Applicative` type classes. Therefore, `Monad` instances represent type --- | constructors which support sequential composition, and also lifting of --- | functions of arbitrary arity. --- | --- | Instances must satisfy the following laws in addition to the --- | `Applicative` and `Bind` laws: --- | --- | - Left Identity: `pure x >>= f = f x` --- | - Right Identity: `x >>= pure = x` -class (Applicative m, Bind m) <= Monad m - -instance monadFn :: Monad ((->) r) -instance monadArray :: Monad Array - --- | `liftM1` provides a default implementation of `(<$>)` for any --- | [`Monad`](#monad), without using `(<$>)` as provided by the --- | [`Functor`](#functor)-[`Monad`](#monad) superclass relationship. --- | --- | `liftM1` can therefore be used to write [`Functor`](#functor) instances --- | as follows: --- | --- | ```purescript --- | instance functorF :: Functor F where --- | map = liftM1 --- | ``` -liftM1 :: forall m a b. (Monad m) => (a -> b) -> m a -> m b -liftM1 f a = do - a' <- a - return (f a') - --- | `ap` provides a default implementation of `(<*>)` for any --- | [`Monad`](#monad), without using `(<*>)` as provided by the --- | [`Apply`](#apply)-[`Monad`](#monad) superclass relationship. --- | --- | `ap` can therefore be used to write [`Apply`](#apply) instances as --- | follows: --- | --- | ```purescript --- | instance applyF :: Apply F where --- | apply = ap --- | ``` -ap :: forall m a b. (Monad m) => m (a -> b) -> m a -> m b -ap f a = do - f' <- f - a' <- a - return (f' a') - --- | The `Semigroup` type class identifies an associative operation on a type. --- | --- | Instances are required to satisfy the following law: --- | --- | - Associativity: `(x <> y) <> z = x <> (y <> z)` --- | --- | One example of a `Semigroup` is `String`, with `(<>)` defined as string --- | concatenation. -class Semigroup a where - append :: a -> a -> a - -infixr 5 <> -infixr 5 ++ - --- | `(<>)` is an alias for `append`. -(<>) :: forall s. (Semigroup s) => s -> s -> s -(<>) = append - --- | `(++)` is an alternative alias for `append`. -(++) :: forall s. (Semigroup s) => s -> s -> s -(++) = append - -instance semigroupString :: Semigroup String where - append = concatString - -instance semigroupUnit :: Semigroup Unit where - append _ _ = unit - -instance semigroupFn :: (Semigroup s') => Semigroup (s -> s') where - append f g = \x -> f x <> g x - -instance semigroupOrdering :: Semigroup Ordering where - append LT _ = LT - append GT _ = GT - append EQ y = y - -instance semigroupArray :: Semigroup (Array a) where - append = concatArray - -foreign import concatString :: String -> String -> String -foreign import concatArray :: forall a. Array a -> Array a -> Array a - --- | The `Semiring` class is for types that support an addition and --- | multiplication operation. --- | --- | Instances must satisfy the following laws: --- | --- | - Commutative monoid under addition: --- | - Associativity: `(a + b) + c = a + (b + c)` --- | - Identity: `zero + a = a + zero = a` --- | - Commutative: `a + b = b + a` --- | - Monoid under multiplication: --- | - Associativity: `(a * b) * c = a * (b * c)` --- | - Identity: `one * a = a * one = a` --- | - Multiplication distributes over addition: --- | - Left distributivity: `a * (b + c) = (a * b) + (a * c)` --- | - Right distributivity: `(a + b) * c = (a * c) + (b * c)` --- | - Annihiliation: `zero * a = a * zero = zero` -class Semiring a where - add :: a -> a -> a - zero :: a - mul :: a -> a -> a - one :: a - -instance semiringInt :: Semiring Int where - add = intAdd - zero = 0 - mul = intMul - one = 1 - -instance semiringNumber :: Semiring Number where - add = numAdd - zero = 0.0 - mul = numMul - one = 1.0 - -instance semiringUnit :: Semiring Unit where - add _ _ = unit - zero = unit - mul _ _ = unit - one = unit - -infixl 6 + -infixl 7 * - --- | `(+)` is an alias for `add`. -(+) :: forall a. (Semiring a) => a -> a -> a -(+) = add - --- | `(*)` is an alias for `mul`. -(*) :: forall a. (Semiring a) => a -> a -> a -(*) = mul - -foreign import intAdd :: Int -> Int -> Int -foreign import intMul :: Int -> Int -> Int -foreign import numAdd :: Number -> Number -> Number -foreign import numMul :: Number -> Number -> Number - --- | The `Ring` class is for types that support addition, multiplication, --- | and subtraction operations. --- | --- | Instances must satisfy the following law in addition to the `Semiring` --- | laws: --- | --- | - Additive inverse: `a - a = (zero - a) + a = zero` -class (Semiring a) <= Ring a where - sub :: a -> a -> a - -instance ringInt :: Ring Int where - sub = intSub - -instance ringNumber :: Ring Number where - sub = numSub - -instance ringUnit :: Ring Unit where - sub _ _ = unit - -infixl 6 - - --- | `(-)` is an alias for `sub`. -(-) :: forall a. (Ring a) => a -> a -> a -(-) = sub - --- | `negate x` can be used as a shorthand for `zero - x`. -negate :: forall a. (Ring a) => a -> a -negate a = zero - a - -foreign import intSub :: Int -> Int -> Int -foreign import numSub :: Number -> Number -> Number - --- | The `ModuloSemiring` class is for types that support addition, --- | multiplication, division, and modulo (division remainder) operations. --- | --- | Instances must satisfy the following law in addition to the `Semiring` --- | laws: --- | --- | - Remainder: ``a / b * b + (a `mod` b) = a`` -class (Semiring a) <= ModuloSemiring a where - div :: a -> a -> a - mod :: a -> a -> a - -instance moduloSemiringInt :: ModuloSemiring Int where - div = intDiv - mod = intMod - -instance moduloSemiringNumber :: ModuloSemiring Number where - div = numDiv - mod _ _ = 0.0 - -instance moduloSemiringUnit :: ModuloSemiring Unit where - div _ _ = unit - mod _ _ = unit - -infixl 7 / - --- | `(/)` is an alias for `div`. -(/) :: forall a. (ModuloSemiring a) => a -> a -> a -(/) = div - -foreign import intDiv :: Int -> Int -> Int -foreign import numDiv :: Number -> Number -> Number -foreign import intMod :: Int -> Int -> Int - --- | A `Ring` where every nonzero element has a multiplicative inverse. --- | --- | Instances must satisfy the following law in addition to the `Ring` and --- | `ModuloSemiring` laws: --- | --- | - Multiplicative inverse: `(one / x) * x = one` --- | --- | As a consequence of this ```a `mod` b = zero``` as no divide operation --- | will have a remainder. -class (Ring a, ModuloSemiring a) <= DivisionRing a - -instance divisionRingNumber :: DivisionRing Number -instance divisionRingUnit :: DivisionRing Unit - --- | The `Num` class is for types that are commutative fields. --- | --- | Instances must satisfy the following law in addition to the --- | `DivisionRing` laws: --- | --- | - Commutative multiplication: `a * b = b * a` -class (DivisionRing a) <= Num a - -instance numNumber :: Num Number -instance numUnit :: Num Unit - --- | The `Eq` type class represents types which support decidable equality. --- | --- | `Eq` instances should satisfy the following laws: --- | --- | - Reflexivity: `x == x = true` --- | - Symmetry: `x == y = y == x` --- | - Transitivity: if `x == y` and `y == z` then `x == z` -class Eq a where - eq :: a -> a -> Boolean - -infix 4 == -infix 4 /= - --- | `(==)` is an alias for `eq`. Tests whether one value is equal to another. -(==) :: forall a. (Eq a) => a -> a -> Boolean -(==) = eq - --- | `(/=)` tests whether one value is _not equal_ to another. Shorthand for --- | `not (x == y)`. -(/=) :: forall a. (Eq a) => a -> a -> Boolean -(/=) x y = not (x == y) - -instance eqBoolean :: Eq Boolean where - eq = refEq - -instance eqInt :: Eq Int where - eq = refEq - -instance eqNumber :: Eq Number where - eq = refEq - -instance eqChar :: Eq Char where - eq = refEq - -instance eqString :: Eq String where - eq = refEq - -instance eqUnit :: Eq Unit where - eq _ _ = true - -instance eqArray :: (Eq a) => Eq (Array a) where - eq = eqArrayImpl (==) - -instance eqOrdering :: Eq Ordering where - eq LT LT = true - eq GT GT = true - eq EQ EQ = true - eq _ _ = false - -foreign import refEq :: forall a. a -> a -> Boolean -foreign import refIneq :: forall a. a -> a -> Boolean -foreign import eqArrayImpl :: forall a. (a -> a -> Boolean) -> Array a -> Array a -> Boolean - --- | The `Ordering` data type represents the three possible outcomes of --- | comparing two values: --- | --- | `LT` - The first value is _less than_ the second. --- | `GT` - The first value is _greater than_ the second. --- | `EQ` - The first value is _equal to_ the second. -data Ordering = LT | GT | EQ - --- | The `Ord` type class represents types which support comparisons with a --- | _total order_. --- | --- | `Ord` instances should satisfy the laws of total orderings: --- | --- | - Reflexivity: `a <= a` --- | - Antisymmetry: if `a <= b` and `b <= a` then `a = b` --- | - Transitivity: if `a <= b` and `b <= c` then `a <= c` -class (Eq a) <= Ord a where - compare :: a -> a -> Ordering - -instance ordBoolean :: Ord Boolean where - compare = unsafeCompare - -instance ordInt :: Ord Int where - compare = unsafeCompare - -instance ordNumber :: Ord Number where - compare = unsafeCompare - -instance ordString :: Ord String where - compare = unsafeCompare - -instance ordChar :: Ord Char where - compare = unsafeCompare - -instance ordUnit :: Ord Unit where - compare _ _ = EQ - -instance ordArray :: (Ord a) => Ord (Array a) where - compare xs ys = compare 0 $ ordArrayImpl (\x y -> case compare x y of - EQ -> 0 - LT -> 1 - GT -> -1) xs ys - -foreign import ordArrayImpl :: forall a. (a -> a -> Int) -> Array a -> Array a -> Int - -instance ordOrdering :: Ord Ordering where - compare LT LT = EQ - compare EQ EQ = EQ - compare GT GT = EQ - compare LT _ = LT - compare EQ LT = GT - compare EQ GT = LT - compare GT _ = GT - -infixl 4 < -infixl 4 > -infixl 4 <= -infixl 4 >= - --- | Test whether one value is _strictly less than_ another. -(<) :: forall a. (Ord a) => a -> a -> Boolean -(<) a1 a2 = case a1 `compare` a2 of - LT -> true - _ -> false - --- | Test whether one value is _strictly greater than_ another. -(>) :: forall a. (Ord a) => a -> a -> Boolean -(>) a1 a2 = case a1 `compare` a2 of - GT -> true - _ -> false - --- | Test whether one value is _non-strictly less than_ another. -(<=) :: forall a. (Ord a) => a -> a -> Boolean -(<=) a1 a2 = case a1 `compare` a2 of - GT -> false - _ -> true - --- | Test whether one value is _non-strictly greater than_ another. -(>=) :: forall a. (Ord a) => a -> a -> Boolean -(>=) a1 a2 = case a1 `compare` a2 of - LT -> false - _ -> true - -unsafeCompare :: forall a. a -> a -> Ordering -unsafeCompare = unsafeCompareImpl LT EQ GT - -foreign import unsafeCompareImpl :: forall a. Ordering -> Ordering -> Ordering -> a -> a -> Ordering - --- | The `Bounded` type class represents types that are finite. --- | --- | Although there are no "internal" laws for `Bounded`, every value of `a` --- | should be considered less than or equal to `top` by some means, and greater --- | than or equal to `bottom`. --- | --- | The lack of explicit `Ord` constraint allows flexibility in the use of --- | `Bounded` so it can apply to total and partially ordered sets, boolean --- | algebras, etc. -class Bounded a where - top :: a - bottom :: a - -instance boundedBoolean :: Bounded Boolean where - top = true - bottom = false - -instance boundedUnit :: Bounded Unit where - top = unit - bottom = unit - -instance boundedOrdering :: Bounded Ordering where - top = GT - bottom = LT - -instance boundedInt :: Bounded Int where - top = topInt - bottom = bottomInt - --- | Characters fall within the Unicode range. -instance boundedChar :: Bounded Char where - top = topChar - bottom = bottomChar - -instance boundedFn :: (Bounded b) => Bounded (a -> b) where - top _ = top - bottom _ = bottom - -foreign import topInt :: Int -foreign import bottomInt :: Int - -foreign import topChar :: Char -foreign import bottomChar :: Char - --- | The `BoundedOrd` type class represents totally ordered finite data types. --- | --- | Instances should satisfy the following law in addition to the `Ord` laws: --- | --- | - Ordering: `bottom <= a <= top` -class (Bounded a, Ord a) <= BoundedOrd a - -instance boundedOrdBoolean :: BoundedOrd Boolean where -instance boundedOrdUnit :: BoundedOrd Unit where -instance boundedOrdOrdering :: BoundedOrd Ordering where -instance boundedOrdInt :: BoundedOrd Int where -instance boundedOrdChar :: BoundedOrd Char where - --- | The `BooleanAlgebra` type class represents types that behave like boolean --- | values. --- | --- | Instances should satisfy the following laws in addition to the `Bounded` --- | laws: --- | --- | - Associativity: --- | - `a || (b || c) = (a || b) || c` --- | - `a && (b && c) = (a && b) && c` --- | - Commutativity: --- | - `a || b = b || a` --- | - `a && b = b && a` --- | - Distributivity: --- | - `a && (b || c) = (a && b) || (a && c)` --- | - `a || (b && c) = (a || b) && (a || c)` --- | - Identity: --- | - `a || bottom = a` --- | - `a && top = a` --- | - Idempotent: --- | - `a || a = a` --- | - `a && a = a` --- | - Absorption: --- | - `a || (a && b) = a` --- | - `a && (a || b) = a` --- | - Annhiliation: --- | - `a || top = top` --- | - Complementation: --- | - `a && not a = bottom` --- | - `a || not a = top` -class (Bounded a) <= BooleanAlgebra a where - conj :: a -> a -> a - disj :: a -> a -> a - not :: a -> a - -instance booleanAlgebraBoolean :: BooleanAlgebra Boolean where - conj = boolAnd - disj = boolOr - not = boolNot - -instance booleanAlgebraUnit :: BooleanAlgebra Unit where - conj _ _ = unit - disj _ _ = unit - not _ = unit - -instance booleanAlgebraFn :: (BooleanAlgebra b) => BooleanAlgebra (a -> b) where - conj fx fy a = fx a `conj` fy a - disj fx fy a = fx a `disj` fy a - not fx a = not (fx a) - -infixr 3 && -infixr 2 || - --- | `(&&)` is an alias for `conj`. -(&&) :: forall a. (BooleanAlgebra a) => a -> a -> a -(&&) = conj - --- | `(||)` is an alias for `disj`. -(||) :: forall a. (BooleanAlgebra a) => a -> a -> a -(||) = disj - -foreign import boolOr :: Boolean -> Boolean -> Boolean -foreign import boolAnd :: Boolean -> Boolean -> Boolean -foreign import boolNot :: Boolean -> Boolean - --- | The `Show` type class represents those types which can be converted into --- | a human-readable `String` representation. --- | --- | While not required, it is recommended that for any expression `x`, the --- | string `show x` be executable PureScript code which evaluates to the same --- | value as the expression `x`. -class Show a where - show :: a -> String - -instance showBoolean :: Show Boolean where - show true = "true" - show false = "false" - -instance showInt :: Show Int where - show = showIntImpl - -instance showNumber :: Show Number where - show = showNumberImpl - -instance showChar :: Show Char where - show = showCharImpl - -instance showString :: Show String where - show = showStringImpl - -instance showUnit :: Show Unit where - show _ = "unit" - -instance showArray :: (Show a) => Show (Array a) where - show = showArrayImpl show - -instance showOrdering :: Show Ordering where - show LT = "LT" - show GT = "GT" - show EQ = "EQ" - -foreign import showIntImpl :: Int -> String -foreign import showNumberImpl :: Number -> String -foreign import showCharImpl :: Char -> String -foreign import showStringImpl :: String -> String -foreign import showArrayImpl :: forall a. (a -> String) -> Array a -> String diff --git a/tests/support/pscide/src/RebuildSpecWithHiddenIdent.purs b/tests/support/pscide/src/RebuildSpecWithHiddenIdent.purs new file mode 100644 index 0000000..005bd15 --- /dev/null +++ b/tests/support/pscide/src/RebuildSpecWithHiddenIdent.purs @@ -0,0 +1,6 @@ +module RebuildSpecWithHiddenIdent (exported) where + +hidden x _ = x + +exported :: forall a. a -> a +exported x = x diff --git a/tests/support/setup.js b/tests/support/setup.js deleted file mode 100644 index 46b87b5..0000000 --- a/tests/support/setup.js +++ /dev/null @@ -1,22 +0,0 @@ -var glob = require("glob"); -var fs = require("fs"); - -try { - fs.mkdirSync("./flattened"); -} catch(e) { - // ignore the error if it already exists - if (e.code !== "EEXIST") { - throw(e); - } -} - -glob("bower_components/*/src/**/*.{js,purs}", function(err, files) { - if (err) throw err; - files.forEach(function(file) { - // We join with "-" because Cabal is weird about file extensions. - var dest = "./flattened/" + file.split("/").slice(3).join("-"); - console.log("Copying " + file + " to " + dest); - var content = fs.readFileSync(file, "utf-8"); - fs.writeFileSync(dest, content, "utf-8"); - }); -}) |