git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge branch 'master' into typed-binders
commit0644920eaf6669adcd251d9c5e997ee626e5fec5 authorBenjamin Kovach <bkovach5@uga.edu> dateThu 15 Oct 2015, 16:23 (11 years ago) parent91130e44dd8c87
65 files changed+1234−1125
.gitignore+1 .travis.yml+6−6 CONTRIBUTORS.md+1 INSTALL.md+12−2 LICENSE+167−68 bundle/README examples/passing/LargeSumType.purs+33 examples/passing/OptionalQualified.purs+13 examples/passing/QualifiedQualifiedImports.purs+6 examples/passing/UTF8Sourcefile.purs+10 license-generator/generate+3 psc/Main.hs+4−2 psci/PSCi.hs+13−10 purescript.cabal+6−2 src/Language/PureScript/AST/Exported.hs+1−1 src/Language/PureScript/AST/Traversals.hs+3−3 src/Language/PureScript/Bundle.hs+1−1 src/Language/PureScript/CodeGen/JS.hs+2−1 src/Language/PureScript/CodeGen/JS/Optimizer/Inliner.hs+1−1 src/Language/PureScript/CodeGen/JS/Optimizer/TCO.hs+1−1 src/Language/PureScript/CodeGen/JS/Optimizer/Unused.hs+1−1 src/Language/PureScript/CoreFn/Expr.hs+1−1 src/Language/PureScript/Docs/Convert.hs+2−3 src/Language/PureScript/Docs/Render.hs+3−2 src/Language/PureScript/Docs/Types.hs+1−1 src/Language/PureScript/Errors.hs+345−342 src/Language/PureScript/Linter.hs+4−4 src/Language/PureScript/Linter/Exhaustive.hs+74−47 src/Language/PureScript/Make.hs+122−62 src/Language/PureScript/ModuleDependencies.hs+9−7 src/Language/PureScript/Names.hs+4 src/Language/PureScript/Parser/Declarations.hs+26−28 src/Language/PureScript/Parser/Kinds.hs+1−1 src/Language/PureScript/Parser/Lexer.hs+1−1 src/Language/PureScript/Pretty/Common.hs+11 src/Language/PureScript/Pretty/JS.hs+13−13 src/Language/PureScript/Pretty/Kinds.hs+19−15 src/Language/PureScript/Pretty/Types.hs+56−35 src/Language/PureScript/Pretty/Values.hs+92−152 src/Language/PureScript/Publish.hs+1−1 src/Language/PureScript/Publish/ErrorsWarnings.hs+14−15 src/Language/PureScript/Renamer.hs+3−3 src/Language/PureScript/Sugar/BindingGroups.hs+1−1 src/Language/PureScript/Sugar/CaseDeclarations.hs+1−1 src/Language/PureScript/Sugar/DoNotation.hs+2−2 src/Language/PureScript/Sugar/Names.hs+2−3 src/Language/PureScript/Sugar/Names/Exports.hs+4−5 src/Language/PureScript/Sugar/Names/Imports.hs+1−1 src/Language/PureScript/Sugar/Operators.hs+1−1 src/Language/PureScript/Sugar/TypeClasses.hs+1−1 src/Language/PureScript/Sugar/TypeDeclarations.hs+37−33 src/Language/PureScript/TypeChecker.hs+15−27 src/Language/PureScript/TypeChecker/Entailment.hs+15−25 src/Language/PureScript/TypeChecker/Kinds.hs+2−2 src/Language/PureScript/TypeChecker/Rows.hs−1 src/Language/PureScript/TypeChecker/Skolems.hs+1−1 src/Language/PureScript/TypeChecker/Subsumption.hs+1−9 src/Language/PureScript/TypeChecker/Synonyms.hs+20−66 src/Language/PureScript/TypeChecker/Types.hs+15−67 src/Language/PureScript/TypeChecker/Unify.hs+11−26 src/Language/PureScript/Types.hs+2−16 src/System/IO/UTF8.hs+9 stack-lts-3.yaml+1−1 stack-nightly.yaml+1−1 tests/Main.hs+4−3
.gitignore+1
@@ -15,3 +15,4 @@ node_modules
1515tmp/
1616.stack-work/
1717tests/support/flattened/
18+output
.travis.yml+6−6
@@ -9,8 +9,8 @@ matrix:
99 - env: GHCVER=7.8.4 COVERAGE_SUITE=psci-tests
1010 compiler: ": #GHC 7.8.4 - psci-tests"
1111 addons: {apt: {packages: [cabal-install-1.22,ghc-7.8.4,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
12− - env: GHCVER=7.8.4 STACKAGE=lts-22
13− compiler: ": #GHC 7.8.4 - lts-2.22"
12+ - env: GHCVER=7.8.4 STACKAGE=lts-2.22
13+ compiler: ": #GHC 7.8.4 - lts-2.22-1"
1414 addons: {apt: {packages: [cabal-install-1.22,ghc-7.8.4,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
1515 - env: GHCVER=7.6.3
1616 compiler: ": #GHC 7.6.3"
@@ -18,11 +18,11 @@ matrix:
1818 - env: GHCVER=7.10.1
1919 compiler: ": #GHC 7.10.1"
2020 addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.1,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
21− - env: GHCVER=7.10.2 STACKAGE=lts=3.4 RUNSDISTTESTS=YES
22− compiler: ": #GHC 7.10.2 lts-3.4"
21+ - env: GHCVER=7.10.2 STACKAGE=lts=3.6 RUNSDISTTESTS=YES
22+ compiler: ": #GHC 7.10.2 lts-3.6"
2323 addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
24− - env: GHCVER=7.10.2 STACKAGE=nightly-2015-08-24
25− compiler: ": #GHC 7.10.2 nightly-2015-09-09"
24+ - env: GHCVER=7.10.2 STACKAGE=nightly-2015-09-29
25+ compiler: ": #GHC 7.10.2 nightly-2015-09-29"
2626 addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.2,happy-1.19.5,alex-3.1.4], sources: [hvr-ghc]}}
2727before_install:
2828 - unset CC
CONTRIBUTORS.md+1
@@ -53,6 +53,7 @@ This file lists the contributors to the PureScript compiler project, and the ter
5353- [@utkarshkukreti](https://github.com/utkarshkukreti) (Utkarsh Kukreti) My existing contributions and all future contributions until further notice are Copyright Utkarsh Kukreti, and are licensed to the owners and users of the PureScript compiler project under the terms of the [MIT license](http://opensource.org/licenses/MIT).
5454- [@vkorablin](https://github.com/vkorablin) (Vladimir Korablin) - My existing contributions and all future contributions until further notice are Copyright Vladimir Korablin, and are licensed to the owners and users of the PureScript compiler project under the terms of the MIT license.
5555- [@zudov](https://github.com/zudov) (Konstantin Zudov) My existing contributions and all future contributions until further notice are Copyright Konstantin Zudov, and are licensed to the owners and users of the PureScript compiler project under the terms of the [MIT license](http://opensource.org/licenses/MIT).
56+- [@senju](https://github.com/senju) - My existing contributions and all future contributions until further notice are Copyright senju, and are licensed to the owners and users of the PureScript compiler project under the terms of the [MIT license](http://opensource.org/licenses/MIT).
5657<http://opensource.org/licenses/MIT>.
5758
5859### Companies
INSTALL.md+12−2
@@ -24,15 +24,25 @@ requirements.
2424## Compiling from source
2525
2626GHC 7.6.1 or newer is required to compile from source. The easiest way is to
27−use `cabal-install`:
27+use stack:
2828
2929```
30−$ cabal update && cabal install purescript
30+$ stack install purescript
3131```
3232
33+This will then copy the compiler and utilities into `~/.local/bin`.
34+
35+
36+If you don't have stack installed yet there are install instructions
37+[here](https://github.com/commercialhaskell/stack/blob/master/doc/install_and_upgrade.md).
38+
39+If you don't have ghc installed yet, stack will prompt you to run `stack setup`
40+which will install ghc for you.
41+
3342The PureScript compiler has been known to run on OS X 10.6 when built with GHC
34437.6.
3544
45+
3646## The "curses" library
3747
3848`psci` depends on the `curses` library (via the Haskell package `terminfo`). If
LICENSE+167−68
@@ -31,6 +31,7 @@ PureScript uses the following Haskell library packages. Their license files foll
3131 array
3232 attoparsec
3333 base
34+ binary
3435 blaze-builder
3536 bower-json
3637 boxes
@@ -45,9 +46,10 @@ PureScript uses the following Haskell library packages. Their license files foll
4546 haskeline
4647 integer-gmp
4748 language-javascript
49+ lifted-base
50+ monad-control
4851 mtl
4952 nats
50− old-locale
5153 optparse-applicative
5254 parsec
5355 pattern-arrows
@@ -59,12 +61,14 @@ PureScript uses the following Haskell library packages. Their license files foll
5961 scientific
6062 semigroups
6163 split
64+ stm
6265 syb
6366 template-haskell
6467 terminfo
6568 text
6669 time
6770 transformers
71+ transformers-base
6872 transformers-compat
6973 unix
7074 unordered-containers
@@ -449,6 +453,39 @@ base LICENSE file:
449453
450454 -----------------------------------------------------------------------------
451455
456+binary LICENSE file:
457+
458+ Copyright (c) Lennart Kolmodin
459+
460+ All rights reserved.
461+
462+ Redistribution and use in source and binary forms, with or without
463+ modification, are permitted provided that the following conditions
464+ are met:
465+
466+ 1. Redistributions of source code must retain the above copyright
467+ notice, this list of conditions and the following disclaimer.
468+
469+ 2. Redistributions in binary form must reproduce the above copyright
470+ notice, this list of conditions and the following disclaimer in the
471+ documentation and/or other materials provided with the distribution.
472+
473+ 3. Neither the name of the author nor the names of his contributors
474+ may be used to endorse or promote products derived from this software
475+ without specific prior written permission.
476+
477+ THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
478+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
479+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
480+ DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
481+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
482+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
483+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
484+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
485+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
486+ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
487+ POSSIBILITY OF SUCH DAMAGE.
488+
452489blaze-builder LICENSE file:
453490
454491 Copyright Jasper Van der Jeugt 2010, Simon Meier 2010 & 2011
@@ -967,6 +1004,70 @@ language-javascript LICENSE file:
9671004 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
9681005 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9691006
1007+lifted-base LICENSE file:
1008+
1009+ Copyright © 2010-2012, Bas van Dijk, Anders Kaseorg
1010+ All rights reserved.
1011+
1012+ Redistribution and use in source and binary forms, with or without
1013+ modification, are permitted provided that the following conditions are
1014+ met:
1015+
1016+ • Redistributions of source code must retain the above copyright
1017+ notice, this list of conditions and the following disclaimer.
1018+
1019+ • Redistributions in binary form must reproduce the above copyright
1020+ notice, this list of conditions and the following disclaimer in the
1021+ documentation and/or other materials provided with the distribution.
1022+
1023+ • Neither the name of the author nor the names of other contributors
1024+ may be used to endorse or promote products derived from this
1025+ software without specific prior written permission.
1026+
1027+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1028+ “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1029+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1030+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1031+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1032+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1033+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1034+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1035+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1036+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1037+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1038+
1039+monad-control LICENSE file:
1040+
1041+ Copyright © 2010, Bas van Dijk, Anders Kaseorg
1042+ All rights reserved.
1043+
1044+ Redistribution and use in source and binary forms, with or without
1045+ modification, are permitted provided that the following conditions are
1046+ met:
1047+
1048+ • Redistributions of source code must retain the above copyright
1049+ notice, this list of conditions and the following disclaimer.
1050+
1051+ • Redistributions in binary form must reproduce the above copyright
1052+ notice, this list of conditions and the following disclaimer in the
1053+ documentation and/or other materials provided with the distribution.
1054+
1055+ • Neither the name of the author nor the names of other contributors
1056+ may be used to endorse or promote products derived from this
1057+ software without specific prior written permission.
1058+
1059+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1060+ “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1061+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1062+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1063+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1064+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1065+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1066+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1067+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1068+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1069+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1070+
9701071mtl LICENSE file:
9711072
9721073 The Glasgow Haskell Compiler License
@@ -1034,72 +1135,6 @@ nats LICENSE file:
10341135 ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
10351136 POSSIBILITY OF SUCH DAMAGE.
10361137
1037−old-locale LICENSE file:
1038−
1039− This library (libraries/base) is derived from code from two
1040− sources:
1041−
1042− * Code from the GHC project which is largely (c) The University of
1043− Glasgow, and distributable under a BSD-style license (see below),
1044−
1045− * Code from the Haskell 98 Report which is (c) Simon Peyton Jones
1046− and freely redistributable (but see the full license for
1047− restrictions).
1048−
1049− The full text of these licenses is reproduced below. Both of the
1050− licenses are BSD-style or compatible.
1051−
1052− -----------------------------------------------------------------------------
1053−
1054− The Glasgow Haskell Compiler License
1055−
1056− Copyright 2004, The University Court of the University of Glasgow.
1057− All rights reserved.
1058−
1059− Redistribution and use in source and binary forms, with or without
1060− modification, are permitted provided that the following conditions are met:
1061−
1062− - Redistributions of source code must retain the above copyright notice,
1063− this list of conditions and the following disclaimer.
1064−
1065− - Redistributions in binary form must reproduce the above copyright notice,
1066− this list of conditions and the following disclaimer in the documentation
1067− and/or other materials provided with the distribution.
1068−
1069− - Neither name of the University nor the names of its contributors may be
1070− used to endorse or promote products derived from this software without
1071− specific prior written permission.
1072−
1073− THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF
1074− GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
1075− INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
1076− FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1077− UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE
1078− FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1079− DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1080− SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1081− CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1082− LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1083− OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1084− DAMAGE.
1085−
1086− -----------------------------------------------------------------------------
1087−
1088− Code derived from the document "Report on the Programming Language
1089− Haskell 98", is distributed under the following license:
1090−
1091− Copyright (c) 2002 Simon Peyton Jones
1092−
1093− The authors intend this Report to belong to the entire Haskell
1094− community, and so we grant permission to copy and distribute it for
1095− any purpose, provided that it is reproduced in its entirety,
1096− including this Notice. Modified versions of this Report may also be
1097− copied and distributed for any purpose, provided that the modified
1098− version is clearly presented as such, and that it does not claim to
1099− be a definition of the Haskell 98 Language.
1100−
1101− -----------------------------------------------------------------------------
1102−
11031138optparse-applicative LICENSE file:
11041139
11051140 Copyright (c) 2012, Paolo Capriotti
@@ -1450,6 +1485,40 @@ split LICENSE file:
14501485 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
14511486 SUCH DAMAGE.
14521487
1488+stm LICENSE file:
1489+
1490+ The Glasgow Haskell Compiler License
1491+
1492+ Copyright 2004, The University Court of the University of Glasgow.
1493+ All rights reserved.
1494+
1495+ Redistribution and use in source and binary forms, with or without
1496+ modification, are permitted provided that the following conditions are met:
1497+
1498+ - Redistributions of source code must retain the above copyright notice,
1499+ this list of conditions and the following disclaimer.
1500+
1501+ - Redistributions in binary form must reproduce the above copyright notice,
1502+ this list of conditions and the following disclaimer in the documentation
1503+ and/or other materials provided with the distribution.
1504+
1505+ - Neither name of the University nor the names of its contributors may be
1506+ used to endorse or promote products derived from this software without
1507+ specific prior written permission.
1508+
1509+ THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY COURT OF THE UNIVERSITY OF
1510+ GLASGOW AND THE CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
1511+ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
1512+ FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
1513+ UNIVERSITY COURT OF THE UNIVERSITY OF GLASGOW OR THE CONTRIBUTORS BE LIABLE
1514+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1515+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
1516+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
1517+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
1518+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
1519+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
1520+ DAMAGE.
1521+
14531522syb LICENSE file:
14541523
14551524 This library (libraries/syb) is derived from code from several
@@ -1674,6 +1743,36 @@ transformers LICENSE file:
16741743 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
16751744 DAMAGE.
16761745
1746+transformers-base LICENSE file:
1747+
1748+ Copyright (c) 2011, Mikhail Vorozhtsov, Bas van Dijk
1749+ All rights reserved.
1750+
1751+ Redistribution and use in source and binary forms, with or without
1752+ modification, are permitted provided that the following conditions are met:
1753+
1754+ - Redistributions of source code must retain the above copyright notice,
1755+ this list of conditions and the following disclaimer.
1756+ - Redistributions in binary form must reproduce the above copyright
1757+ notice, this list of conditions and the following disclaimer in the
1758+ documentation and/or other materials provided with the distribution.
1759+ - Neither the names of the copyright owners nor the names of the
1760+ contributors may be used to endorse or promote products derived
1761+ from this software without specific prior written permission.
1762+
1763+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1764+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1765+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1766+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1767+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1768+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1769+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1770+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1771+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1772+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1773+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1774+
1775+
16771776transformers-compat LICENSE file:
16781777
16791778 Copyright 2012 Edward Kmett
@@ -1836,7 +1935,7 @@ vector LICENSE file:
18361935
18371936void LICENSE file:
18381937
1839− Copyright 2013 Edward Kmett
1938+ Copyright 2015 Edward Kmett
18401939
18411940 All rights reserved.
18421941
bundle/READMEmode 100755 → 100644

Only the mode changed.

examples/passing/LargeSumType.pursnew file+33
@@ -0,0 +1,33 @@
1+module Main where
2+
3+data Large = A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z
4+
5+explode A A = "A"
6+explode B B = "B"
7+explode C C = "C"
8+explode D D = "D"
9+explode E E = "E"
10+explode F F = "F"
11+explode G G = "G"
12+explode H H = "H"
13+explode I I = "I"
14+explode J J = "J"
15+explode K K = "K"
16+explode L L = "L"
17+explode M M = "M"
18+explode N N = "N"
19+explode O O = "O"
20+explode P P = "P"
21+explode Q Q = "Q"
22+explode R R = "R"
23+explode S S = "S"
24+explode T T = "T"
25+explode U U = "U"
26+explode V V = "V"
27+explode W W = "W"
28+explode X X = "X"
29+explode Y Y = "Y"
30+explode Z Z = "Z"
31+explode _ _ = ""
32+
33+main = Control.Monad.Eff.Console.log "Done"
examples/passing/OptionalQualified.pursnew file+13
@@ -0,0 +1,13 @@
1+module Main where
2+
3+-- qualified import with the "qualified" keyword
4+import qualified Prelude as P
5+
6+-- qualified import without the "qualified" keyword
7+import Control.Monad.Eff.Console as Console
8+
9+bind = P.bind
10+
11+main = do
12+ message <- P.return "success!"
13+ Console.log message
examples/passing/QualifiedQualifiedImports.pursnew file+6
@@ -0,0 +1,6 @@
1+module Main where
2+
3+-- qualified import with qualified imported names
4+import qualified Control.Monad.Eff.Console (log) as Console
5+
6+main = Console.log "Success!"
examples/passing/UTF8Sourcefile.pursnew file+10
@@ -0,0 +1,10 @@
1+module Main where
2+
3+import Control.Monad.Eff.Console
4+
5+-- '→' is multibyte sequence \u2192.
6+utf8multibyte = "Hello λ→ world!!"
7+
8+main = do
9+ log "done"
10+
license-generator/generate+3
@@ -9,6 +9,9 @@ set -e # exit on error
99set -u # exit on undefined variable
1010set -o pipefail # propagate nonzero exit codes through pipelines
1111
12+export LC_CTYPE=C
13+export LANG=C
14+
1215if ! which cabal-dependency-licenses >/dev/null; then
1316 echo "$0: the program 'cabal-dependency-licenses' is required." >&2
1417 echo "$0: see Hackage: https://hackage.haskell.org/package/cabal-dependency-licenses" >&2
psc/Main.hs+4−2
@@ -32,6 +32,7 @@ import Options.Applicative as Opts
3232
3333import System.Exit (exitSuccess, exitFailure)
3434import System.IO (hPutStrLn, stderr)
35+import System.IO.UTF8
3536import System.FilePath.Glob (glob)
3637
3738import qualified Language.PureScript as P
@@ -60,7 +61,7 @@ compile (PSCMakeOptions inputGlob inputForeignGlob outputDir opts usePrefix) = d
6061 let (jsFiles, pursFiles) = partition (isSuffixOf ".js") input
6162 moduleFiles <- readInput (InputOptions pursFiles)
6263 inputForeign <- globWarningOnMisses warnFileTypeNotFound inputForeignGlob
63− foreignFiles <- forM (inputForeign ++ jsFiles) (\inFile -> (inFile,) <$> readFile inFile)
64+ foreignFiles <- forM (inputForeign ++ jsFiles) (\inFile -> (inFile,) <$> readUTF8File inFile)
6465 case runWriterT (parseInputs moduleFiles foreignFiles) of
6566 Left errs -> do
6667 hPutStrLn stderr (P.prettyPrintMultipleErrors (P.optionsVerboseErrors opts) errs)
@@ -93,7 +94,7 @@ globWarningOnMisses warn = concatMapM globWithWarning
9394 concatMapM f = liftM concat . mapM f
9495
9596readInput :: InputOptions -> IO [(Either P.RebuildPolicy FilePath, String)]
96−readInput InputOptions{..} = forM ioInputFiles $ \inFile -> (Right inFile, ) <$> readFile inFile
97+readInput InputOptions{..} = forM ioInputFiles $ \inFile -> (Right inFile, ) <$> readUTF8File inFile
9798
9899parseInputs :: (Functor m, Applicative m, MonadError P.MultipleErrors m, MonadWriter P.MultipleErrors m)
99100 => [(Either P.RebuildPolicy FilePath, String)]
@@ -178,6 +179,7 @@ pscMakeOptions = PSCMakeOptions <$> many inputFile
178179 <*> options
179180 <*> (not <$> noPrefix)
180181
182+
181183main :: IO ()
182184main = execParser opts >>= compile
183185 where
psci/PSCi.hs+13−10
@@ -263,10 +263,10 @@ makeIO f io = do
263263
264264make :: PSCiState -> [(Either P.RebuildPolicy FilePath, P.Module)] -> P.Make P.Environment
265265make PSCiState{..} ms = P.make actions' (map snd (psciLoadedModules ++ ms))
266− where
267− filePathMap = M.fromList $ (first P.getModuleName . swap) `map` (psciLoadedModules ++ ms)
268− actions = P.buildMakeActions modulesDir filePathMap psciForeignFiles False
269− actions' = actions { P.progress = const (return ()) }
266+ where
267+ filePathMap = M.fromList $ (first P.getModuleName . swap) `map` (psciLoadedModules ++ ms)
268+ actions = P.buildMakeActions modulesDir filePathMap psciForeignFiles False
269+ actions' = actions { P.progress = const (return ()) }
270270
271271-- |
272272-- Takes a value declaration and evaluates it with the current state.
@@ -437,10 +437,10 @@ handleKindOf typ = do
437437-- Parses the input and returns either a Metacommand, or an error as a string.
438438--
439439getCommand :: Bool -> InputT (StateT PSCiState IO) (Either String (Maybe Command))
440−getCommand singleLineMode = do
441− firstLine <- getInputLine "> "
440+getCommand singleLineMode = handleInterrupt (return (Right Nothing)) $ do
441+ firstLine <- withInterrupt $ getInputLine "> "
442442 case firstLine of
443− Nothing -> return (Right Nothing)
443+ Nothing -> return (Right (Just QuitPSCi)) -- Ctrl-D when input is empty
444444 Just "" -> return (Right Nothing)
445445 Just s | singleLineMode || head s == ':' -> return . either Left (Right . Just) $ parseCommand s
446446 Just s -> either Left (Right . Just) . parseCommand <$> go [s]
@@ -464,7 +464,7 @@ handleCommand (LoadFile filePath) = whenFileExists filePath $ \absPath -> do
464464 Right mods -> PSCI . lift $ modify (updateModules (map ((,) (Right absPath)) mods))
465465handleCommand (LoadForeign filePath) = whenFileExists filePath $ \absPath -> do
466466 foreignsOrError <- psciIO . runMake $ do
467− foreignFile <- makeIO (const (P.SimpleErrorWrapper $ P.CannotReadFile absPath)) (readFile absPath)
467+ foreignFile <- makeIO (const (P.ErrorMessage [] $ P.CannotReadFile absPath)) (readFile absPath)
468468 P.parseForeignModulesFromFiles [(absPath, foreignFile)]
469469 case foreignsOrError of
470470 Left err -> PSCI $ outputStrLn $ P.prettyPrintMultipleErrors False err
@@ -533,7 +533,7 @@ loop PSCiOptions{..} = do
533533 historyFilename <- getHistoryFilename
534534 let settings = defaultSettings { historyFile = Just historyFilename }
535535 foreignsOrError <- runMake $ do
536− foreignFilesContent <- forM foreignFiles (\inFile -> (inFile,) <$> makeIO (const (P.SimpleErrorWrapper $ P.CannotReadFile inFile)) (readFile inFile))
536+ foreignFilesContent <- forM foreignFiles (\inFile -> (inFile,) <$> makeIO (const (P.ErrorMessage [] $ P.CannotReadFile inFile)) (readFile inFile))
537537 P.parseForeignModulesFromFiles foreignFilesContent
538538 case foreignsOrError of
539539 Left errs -> putStrLn (P.prettyPrintMultipleErrors False errs) >> exitFailure
@@ -555,7 +555,10 @@ loop PSCiOptions{..} = do
555555 Left err -> outputStrLn err >> go
556556 Right Nothing -> go
557557 Right (Just QuitPSCi) -> outputStrLn quitMessage
558− Right (Just c') -> runPSCI (loadAllImportedModules >> handleCommand c') >> go
558+ Right (Just c') -> do
559+ handleInterrupt (outputStrLn "Interrupted.")
560+ (withInterrupt (runPSCI (loadAllImportedModules >> handleCommand c')))
561+ go
559562
560563multiLineMode :: Parser Bool
561564multiLineMode = switch $
purescript.cabal+6−2
@@ -32,6 +32,9 @@ source-repository head
3232
3333library
3434 build-depends: base >=4.6 && <5,
35+ lifted-base >= 0.2.3 && < 0.2.4,
36+ monad-control >= 1.0.0.0 && < 1.1,
37+ transformers-base >= 0.4.0 && < 0.5,
3538 containers -any,
3639 unordered-containers -any,
3740 dlist -any,
@@ -55,7 +58,7 @@ library
5558 language-javascript == 0.5.*,
5659 syb -any,
5760 Glob >= 0.7 && < 0.8,
58− process >= 1.2.0 && < 1.3,
61+ process >= 1.2.0 && < 1.4,
5962 safe >= 0.3.9 && < 0.4,
6063 semigroups >= 0.16.2 && < 0.18
6164
@@ -162,6 +165,7 @@ library
162165 Control.Monad.Supply
163166 Control.Monad.Supply.Class
164167
168+ System.IO.UTF8
165169 exposed: True
166170 buildable: True
167171 hs-source-dirs: src
@@ -175,7 +179,7 @@ executable psc
175179 main-is: Main.hs
176180 buildable: True
177181 hs-source-dirs: psc
178− ghc-options: -Wall -O2 -fno-warn-unused-do-bind
182+ ghc-options: -Wall -O2 -fno-warn-unused-do-bind -threaded -rtsopts "-with-rtsopts=-N"
179183
180184executable psci
181185 build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
src/Language/PureScript/AST/Exported.hs+1−1
@@ -66,7 +66,7 @@ filterInstances (Just exps) =
6666 -- * the name is defined in a different module (and must be exported from
6767 -- that module; the code would fail to compile otherwise).
6868 visibleOutside _ (Qualified (Just _) _) = True
69− visibleOutside refs (Qualified Nothing n) = any (== n) refs
69+ visibleOutside refs (Qualified Nothing n) = n `elem` refs
7070
7171 typeName (TypeRef n _) = Just n
7272 typeName (PositionedDeclarationRef _ _ r) = typeName r
src/Language/PureScript/AST/Traversals.hs+3−3
@@ -219,10 +219,10 @@ everythingOnValues (<>) f g h i j = (f', g', h', i', j')
219219 f' d = f d
220220
221221 g' v@(UnaryMinus v1) = g v <> g' v1
222− g' v@(BinaryNoParens op v1 v2) = g v <> g op <> g' v1 <> g' v2
222+ g' v@(BinaryNoParens op v1 v2) = g v <> g' op <> g' v1 <> g' v2
223223 g' v@(Parens v1) = g v <> g' v1
224− g' v@(OperatorSection op (Left v1)) = g v <> g op <> g' v1
225− g' v@(OperatorSection op (Right v1)) = g v <> g op <> g' v1
224+ g' v@(OperatorSection op (Left v1)) = g v <> g' op <> g' v1
225+ g' v@(OperatorSection op (Right v1)) = g v <> g' op <> g' v1
226226 g' v@(ArrayLiteral vs) = foldl (<>) (g v) (map g' vs)
227227 g' v@(ObjectLiteral vs) = foldl (<>) (g v) (map (g' . snd) vs)
228228 g' v@(ObjectConstructor vs) = foldl (<>) (g v) (map g' (mapMaybe snd vs))
src/Language/PureScript/Bundle.hs+1−1
@@ -385,7 +385,7 @@ isModuleEmpty (Module _ els) = all isElementEmpty els
385385 where
386386 isElementEmpty :: ModuleElement -> Bool
387387 isElementEmpty (ExportsList exps) = null exps
388− isElementEmpty (Require _ _ _) = True
388+ isElementEmpty Require{} = True
389389 isElementEmpty (Other _) = True
390390 isElementEmpty _ = False
391391
src/Language/PureScript/CodeGen/JS.hs+2−1
@@ -27,6 +27,7 @@ module Language.PureScript.CodeGen.JS
2727 ) where
2828
2929import Data.List ((\\), delete, intersect)
30+import Data.Maybe (isNothing)
3031import qualified Data.Traversable as T (traverse)
3132
3233#if __GLASGOW_HASKELL__ < 710
@@ -62,7 +63,7 @@ moduleToJs (Module coms mn imps exps foreigns decls) foreign_ = do
6263 comments <- not <$> asks optionsNoComments
6364 let strict = JSStringLiteral "use strict"
6465 let header = if comments && not (null coms) then JSComment coms strict else strict
65− let foreign' = [JSVariableIntroduction "$foreign" foreign_ | not $ null foreigns || foreign_ == Nothing]
66+ let foreign' = [JSVariableIntroduction "$foreign" foreign_ | not $ null foreigns || isNothing foreign_]
6667 let moduleBody = header : foreign' ++ jsImports ++ concat optimized
6768 let foreignExps = exps `intersect` (fst `map` foreigns)
6869 let standardExps = exps \\ foreignExps
src/Language/PureScript/CodeGen/JS/Optimizer/Inliner.hs+1−1
@@ -255,7 +255,7 @@ inlineFnComposition = everywhereOnJSTopDownM convert
255255 return $ JSFunction Nothing [arg] (JSBlock [JSReturn $ JSApp x [JSApp y [JSVar arg]]])
256256 convert other = return other
257257 isFnCompose :: JS -> JS -> Bool
258− isFnCompose dict' fn = isDict semigroupoidFn dict' && (isPreludeFn (C.<<<) fn || isPreludeFn (C.compose) fn)
258+ isFnCompose dict' fn = isDict semigroupoidFn dict' && (isPreludeFn (C.<<<) fn || isPreludeFn C.compose fn)
259259
260260isDict :: (String, String) -> JS -> Bool
261261isDict (moduleName, dictName) (JSAccessor x (JSVar y)) = x == dictName && y == moduleName
src/Language/PureScript/CodeGen/JS/Optimizer/TCO.hs+1−1
@@ -124,5 +124,5 @@ tco' = everywhereOnJS convert
124124 hasFunction :: JS -> Bool
125125 hasFunction = getAny . everythingOnJS mappend (Any . isFunction)
126126 where
127− isFunction (JSFunction _ _ _) = True
127+ isFunction JSFunction{} = True
128128 isFunction _ = False
src/Language/PureScript/CodeGen/JS/Optimizer/Unused.hs+1−1
@@ -29,7 +29,7 @@ removeCodeAfterReturnStatements = everywhereOnJS (removeFromBlock go)
2929 where
3030 go :: [JS] -> [JS]
3131 go jss | not (any isJSReturn jss) = jss
32− | otherwise = let (body, ret : _) = span (not . isJSReturn) jss in body ++ [ret]
32+ | otherwise = let (body, ret : _) = break isJSReturn jss in body ++ [ret]
3333 isJSReturn (JSReturn _) = True
3434 isJSReturn _ = False
3535
src/Language/PureScript/CoreFn/Expr.hs+1−1
@@ -101,7 +101,7 @@ data CaseAlternative a = CaseAlternative
101101instance Functor CaseAlternative where
102102
103103 fmap f (CaseAlternative cabs car) = CaseAlternative
104− (fmap (fmap f) $ cabs)
104+ (fmap (fmap f) cabs)
105105 (either (Left . fmap (fmap f *** fmap f)) (Right . fmap f) car)
106106
107107-- |
src/Language/PureScript/Docs/Convert.hs+2−3
@@ -147,7 +147,7 @@ convertDeclaration (P.ExternDataDeclaration _ kind') title =
147147 basicDeclaration title (ExternDataDeclaration kind')
148148convertDeclaration (P.TypeSynonymDeclaration _ args ty) title =
149149 basicDeclaration title (TypeSynonymDeclaration args ty)
150−convertDeclaration (P.TypeClassDeclaration _ args implies ds) title = do
150+convertDeclaration (P.TypeClassDeclaration _ args implies ds) title =
151151 Just (Right (mkDeclaration title info) { declChildren = children })
152152 where
153153 info = TypeClassDeclaration args implies
@@ -158,7 +158,7 @@ convertDeclaration (P.TypeClassDeclaration _ args implies ds) title = do
158158 ChildDeclaration (P.showIdent ident') Nothing Nothing (ChildTypeClassMember ty)
159159 convertClassMember _ =
160160 error "Invalid argument to convertClassMember."
161−convertDeclaration (P.TypeInstanceDeclaration _ constraints className tys _) title = do
161+convertDeclaration (P.TypeInstanceDeclaration _ constraints className tys _) title =
162162 Just (Left (classNameString : typeNameStrings, AugmentChild childDecl))
163163 where
164164 classNameString = unQual className
@@ -166,7 +166,6 @@ convertDeclaration (P.TypeInstanceDeclaration _ constraints className tys _) tit
166166 unQual x = let (P.Qualified _ y) = x in P.runProperName y
167167
168168 extractProperNames (P.TypeConstructor n) = [unQual n]
169− extractProperNames (P.SaturatedTypeSynonym n _) = [unQual n]
170169 extractProperNames _ = []
171170
172171 childDecl = ChildDeclaration title Nothing Nothing (ChildInstance constraints classApp)
src/Language/PureScript/Docs/Render.hs+3−2
@@ -10,6 +10,7 @@
1010
1111module Language.PureScript.Docs.Render where
1212
13+import Data.Maybe (maybeToList)
1314import Data.Monoid ((<>))
1415import qualified Language.PureScript as P
1516
@@ -46,7 +47,7 @@ renderDeclarationWithOptions opts Declaration{..} =
4647 ]
4748 TypeClassDeclaration args implies ->
4849 [ keywordClass ]
49− ++ maybe [] (:[]) superclasses
50+ ++ maybeToList superclasses
5051 ++ [renderType' (typeApp declTitle args)]
5152 ++ if any (isTypeClassMember . cdeclInfo) declChildren
5253 then [keywordWhere]
@@ -75,7 +76,7 @@ renderChildDeclarationWithOptions opts ChildDeclaration{..} =
7576 [ keywordInstance
7677 , ident cdeclTitle
7778 , syntax "::"
78− ] ++ maybe [] (:[]) (renderConstraints constraints)
79+ ] ++ maybeToList (renderConstraints constraints)
7980 ++ [ renderType' ty ]
8081 ChildDataConstructor args ->
8182 [ renderType' typeApp' ]
src/Language/PureScript/Docs/Types.hs+1−1
@@ -425,7 +425,7 @@ asSourceSpan = P.SourceSpan <$> key "name" asString
425425
426426instance A.ToJSON a => A.ToJSON (Package a) where
427427 toJSON Package{..} =
428− A.object $
428+ A.object
429429 [ "packageMeta" .= pkgMeta
430430 , "version" .= showVersion pkgVersion
431431 , "versionTag" .= pkgVersionTag
src/Language/PureScript/Errors.hs+345−342
@@ -20,10 +20,11 @@
2020module Language.PureScript.Errors where
2121
2222import Data.Either (lefts, rights)
23−import Data.List (intercalate, transpose)
23+import Data.List (intercalate, transpose, nub, nubBy, partition)
2424import Data.Function (on)
2525#if __GLASGOW_HASKELL__ < 710
2626import Data.Foldable (fold, foldMap)
27+import Data.Traversable (traverse)
2728#else
2829import Data.Foldable (fold)
2930#endif
@@ -52,11 +53,8 @@ import qualified Text.PrettyPrint.Boxes as Box
5253import qualified Text.Parsec as P
5354import qualified Text.Parsec.Error as PE
5455import Text.Parsec.Error (Message(..))
55−import Data.List (nub)
5656
57−-- |
58−-- A type of error messages
59−--
57+-- | A type of error messages
6058data SimpleErrorMessage
6159 = ErrorParsingExterns P.ParseError
6260 | ErrorParsingFFIModule FilePath
@@ -100,6 +98,7 @@ data SimpleErrorMessage
10098 | CtorConflictsWithClass ProperName
10199 | ClassConflictsWithType ProperName
102100 | ClassConflictsWithCtor ProperName
101+ | DuplicateModuleName ModuleName
103102 | DuplicateClassExport ProperName
104103 | DuplicateValueExport Ident
105104 | DuplicateTypeArgument String
@@ -143,44 +142,54 @@ data SimpleErrorMessage
143142 | ShadowedTypeVar String
144143 | UnusedTypeVar String
145144 | WildcardInferredType Type
145+ | MissingTypeDeclaration Ident
146146 | NotExhaustivePattern [[Binder]] Bool
147147 | OverlappingPattern [[Binder]] Bool
148+ | IncompleteExhaustivityCheck
148149 | ClassOperator ProperName Ident
149150 | MisleadingEmptyTypeImport ModuleName ProperName
150151 | ImportHidingModule ModuleName
151− deriving (Show)
152−
153−-- |
154−-- Wrapper of simpler errors
155−--
156−data ErrorMessage
157− = NotYetDefined [Ident] ErrorMessage
158− | ErrorUnifyingTypes Type Type ErrorMessage
159− | ErrorInExpression Expr ErrorMessage
160− | ErrorInModule ModuleName ErrorMessage
161− | ErrorInInstance (Qualified ProperName) [Type] ErrorMessage
162− | ErrorInSubsumption Type Type ErrorMessage
163− | ErrorCheckingType Expr Type ErrorMessage
164− | ErrorCheckingKind Type ErrorMessage
165− | ErrorInferringType Expr ErrorMessage
166− | ErrorInApplication Expr Type Expr ErrorMessage
167− | ErrorInDataConstructor ProperName ErrorMessage
168− | ErrorInTypeConstructor ProperName ErrorMessage
169− | ErrorInBindingGroup [Ident] ErrorMessage
170− | ErrorInDataBindingGroup ErrorMessage
171− | ErrorInTypeSynonym ProperName ErrorMessage
172− | ErrorInValueDeclaration Ident ErrorMessage
173− | ErrorInTypeDeclaration Ident ErrorMessage
174− | ErrorInForeignImport Ident ErrorMessage
175− | PositionedError SourceSpan ErrorMessage
176− | SimpleErrorWrapper SimpleErrorMessage
177− deriving (Show)
152+ deriving Show
153+
154+-- | Error message hints, providing more detailed information about failure.
155+data ErrorMessageHint
156+ = NotYetDefined [Ident]
157+ | ErrorUnifyingTypes Type Type
158+ | ErrorInExpression Expr
159+ | ErrorInModule ModuleName
160+ | ErrorInInstance (Qualified ProperName) [Type]
161+ | ErrorInSubsumption Type Type
162+ | ErrorCheckingType Expr Type
163+ | ErrorCheckingKind Type
164+ | ErrorInferringType Expr
165+ | ErrorInApplication Expr Type Expr
166+ | ErrorInDataConstructor ProperName
167+ | ErrorInTypeConstructor ProperName
168+ | ErrorInBindingGroup [Ident]
169+ | ErrorInDataBindingGroup
170+ | ErrorInTypeSynonym ProperName
171+ | ErrorInValueDeclaration Ident
172+ | ErrorInTypeDeclaration Ident
173+ | ErrorInForeignImport Ident
174+ | PositionedError SourceSpan
175+ deriving Show
176+
177+-- | Categories of hints
178+data HintCategory
179+ = ExprHint
180+ | KindHint
181+ | CheckHint
182+ | PositionHint
183+ | OtherHint
184+ deriving (Show, Eq)
185+
186+data ErrorMessage = ErrorMessage [ErrorMessageHint] SimpleErrorMessage deriving (Show)
178187
179188instance UnificationError Type ErrorMessage where
180− occursCheckFailed t = SimpleErrorWrapper $ InfiniteType t
189+ occursCheckFailed t = ErrorMessage [] $ InfiniteType t
181190
182191instance UnificationError Kind ErrorMessage where
183− occursCheckFailed k = SimpleErrorWrapper $ InfiniteKind k
192+ occursCheckFailed k = ErrorMessage [] $ InfiniteKind k
184193
185194-- |
186195-- Get the error code for a particular error type
@@ -229,6 +238,7 @@ errorCode em = case unwrapErrorMessage em of
229238 CtorConflictsWithClass{} -> "CtorConflictsWithClass"
230239 ClassConflictsWithType{} -> "ClassConflictsWithType"
231240 ClassConflictsWithCtor{} -> "ClassConflictsWithCtor"
241+ DuplicateModuleName{} -> "DuplicateModuleName"
232242 DuplicateClassExport{} -> "DuplicateClassExport"
233243 DuplicateValueExport{} -> "DuplicateValueExport"
234244 DuplicateTypeArgument{} -> "DuplicateTypeArgument"
@@ -272,8 +282,10 @@ errorCode em = case unwrapErrorMessage em of
272282 ShadowedTypeVar{} -> "ShadowedTypeVar"
273283 UnusedTypeVar{} -> "UnusedTypeVar"
274284 WildcardInferredType{} -> "WildcardInferredType"
285+ MissingTypeDeclaration{} -> "MissingTypeDeclaration"
275286 NotExhaustivePattern{} -> "NotExhaustivePattern"
276287 OverlappingPattern{} -> "OverlappingPattern"
288+ IncompleteExhaustivityCheck{} -> "IncompleteExhaustivityCheck"
277289 ClassOperator{} -> "ClassOperator"
278290 MisleadingEmptyTypeImport{} -> "MisleadingEmptyTypeImport"
279291 ImportHidingModule{} -> "ImportHidingModule"
@@ -298,7 +310,7 @@ nonEmpty = not . null . runMultipleErrors
298310-- Create an error set from a single simple error message
299311--
300312errorMessage :: SimpleErrorMessage -> MultipleErrors
301−errorMessage err = MultipleErrors [SimpleErrorWrapper err]
313+errorMessage err = MultipleErrors [ErrorMessage [] err]
302314
303315
304316-- |
@@ -307,12 +319,14 @@ errorMessage err = MultipleErrors [SimpleErrorWrapper err]
307319singleError :: ErrorMessage -> MultipleErrors
308320singleError = MultipleErrors . pure
309321
310−-- |
311−-- Lift a function on ErrorMessage to a function on MultipleErrors
312−--
322+-- | Lift a function on ErrorMessage to a function on MultipleErrors
313323onErrorMessages :: (ErrorMessage -> ErrorMessage) -> MultipleErrors -> MultipleErrors
314324onErrorMessages f = MultipleErrors . map f . runMultipleErrors
315325
326+-- | Add a hint to an error message
327+addHint :: ErrorMessageHint -> MultipleErrors -> MultipleErrors
328+addHint hint = onErrorMessages $ \(ErrorMessage hints se) -> ErrorMessage (hint : hints) se
329+
316330-- | The various types of things which might need to be relabelled in errors messages.
317331data LabelType = TypeLabel | SkolemLabel String deriving (Show, Read, Eq, Ord)
318332
@@ -326,27 +340,7 @@ data Level = Error | Warning deriving Show
326340-- Extract nested error messages from wrapper errors
327341--
328342unwrapErrorMessage :: ErrorMessage -> SimpleErrorMessage
329−unwrapErrorMessage em = case em of
330− (ErrorCheckingKind _ err) -> unwrapErrorMessage err
331− (ErrorCheckingType _ _ err) -> unwrapErrorMessage err
332− (ErrorInApplication _ _ _ err) -> unwrapErrorMessage err
333− (ErrorInBindingGroup _ err) -> unwrapErrorMessage err
334− (ErrorInDataBindingGroup err) -> unwrapErrorMessage err
335− (ErrorInDataConstructor _ err) -> unwrapErrorMessage err
336− (ErrorInExpression _ err) -> unwrapErrorMessage err
337− (ErrorInForeignImport _ err) -> unwrapErrorMessage err
338− (ErrorInInstance _ _ err) -> unwrapErrorMessage err
339− (ErrorInModule _ err) -> unwrapErrorMessage err
340− (ErrorInSubsumption _ _ err) -> unwrapErrorMessage err
341− (ErrorInTypeConstructor _ err) -> unwrapErrorMessage err
342− (ErrorInTypeSynonym _ err) -> unwrapErrorMessage err
343− (ErrorInValueDeclaration _ err) -> unwrapErrorMessage err
344− (ErrorInTypeDeclaration _ err) -> unwrapErrorMessage err
345− (ErrorInferringType _ err) -> unwrapErrorMessage err
346− (ErrorUnifyingTypes _ _ err) -> unwrapErrorMessage err
347− (NotYetDefined _ err) -> unwrapErrorMessage err
348− (PositionedError _ err) -> unwrapErrorMessage err
349− (SimpleErrorWrapper sem) -> sem
343+unwrapErrorMessage (ErrorMessage _ se) = se
350344
351345replaceUnknowns :: Type -> State UnknownMap Type
352346replaceUnknowns = everywhereOnTypesM replaceTypes
@@ -362,400 +356,406 @@ replaceUnknowns = everywhereOnTypesM replaceTypes
362356 replaceTypes other = return other
363357
364358onTypesInErrorMessageM :: (Applicative m) => (Type -> m Type) -> ErrorMessage -> m ErrorMessage
365−onTypesInErrorMessageM f = g
359+onTypesInErrorMessageM f (ErrorMessage hints simple) = ErrorMessage <$> traverse gHint hints <*> gSimple simple
366360 where
367− gSimple (InfiniteType t) = InfiniteType <$> (f t)
368− gSimple (TypesDoNotUnify t1 t2) = TypesDoNotUnify <$> (f t1) <*> (f t2)
369− gSimple (ConstrainedTypeUnified t1 t2) = ConstrainedTypeUnified <$> (f t1) <*> (f t2)
370− gSimple (ExprDoesNotHaveType e t) = ExprDoesNotHaveType e <$> (f t)
371− gSimple (PropertyIsMissing s t) = PropertyIsMissing s <$> (f t)
372− gSimple (CannotApplyFunction t e) = CannotApplyFunction <$> f t <*> (pure e)
361+ gSimple (InfiniteType t) = InfiniteType <$> f t
362+ gSimple (TypesDoNotUnify t1 t2) = TypesDoNotUnify <$> f t1 <*> f t2
363+ gSimple (ConstrainedTypeUnified t1 t2) = ConstrainedTypeUnified <$> f t1 <*> f t2
364+ gSimple (ExprDoesNotHaveType e t) = ExprDoesNotHaveType e <$> f t
365+ gSimple (PropertyIsMissing s t) = PropertyIsMissing s <$> f t
366+ gSimple (CannotApplyFunction t e) = CannotApplyFunction <$> f t <*> pure e
373367 gSimple (InvalidInstanceHead t) = InvalidInstanceHead <$> f t
374368 gSimple other = pure other
375− g (ErrorInSubsumption t1 t2 em) = ErrorInSubsumption <$> (f t1) <*> (f t2) <*> (g em)
376− g (ErrorUnifyingTypes t1 t2 e) = ErrorUnifyingTypes <$> (f t1) <*> (f t2) <*> (g e)
377− g (ErrorCheckingType e t em) = ErrorCheckingType e <$> (f t) <*> (g em)
378− g (ErrorCheckingKind t em) = ErrorCheckingKind <$> (f t) <*> g em
379− g (ErrorInApplication e1 t1 e2 em) = ErrorInApplication e1 <$> (f t1) <*> (pure e2) <*> (g em)
380− g (NotYetDefined x e) = NotYetDefined x <$> (g e)
381− g (ErrorInExpression x e) = ErrorInExpression x <$> (g e)
382− g (ErrorInModule x e) = ErrorInModule x <$> (g e)
383− g (ErrorInInstance x y e) = ErrorInInstance x y <$> (g e)
384− g (ErrorInferringType x e) = ErrorInferringType x <$> (g e)
385− g (ErrorInDataConstructor x e) = ErrorInDataConstructor x <$> (g e)
386− g (ErrorInTypeConstructor x e) = ErrorInTypeConstructor x <$> (g e)
387− g (ErrorInBindingGroup x e) = ErrorInBindingGroup x <$> (g e)
388− g (ErrorInDataBindingGroup e) = ErrorInDataBindingGroup <$> (g e)
389− g (ErrorInTypeSynonym x e) = ErrorInTypeSynonym x <$> (g e)
390− g (ErrorInValueDeclaration x e) = ErrorInValueDeclaration x <$> (g e)
391− g (ErrorInTypeDeclaration x e) = ErrorInTypeDeclaration x <$> (g e)
392− g (ErrorInForeignImport x e) = ErrorInForeignImport x <$> (g e)
393− g (PositionedError x e) = PositionedError x <$> (g e)
394− g (SimpleErrorWrapper sem) = SimpleErrorWrapper <$> gSimple sem
369+ gHint (ErrorInSubsumption t1 t2) = ErrorInSubsumption <$> f t1 <*> f t2
370+ gHint (ErrorUnifyingTypes t1 t2) = ErrorUnifyingTypes <$> f t1 <*> f t2
371+ gHint (ErrorCheckingType e t) = ErrorCheckingType e <$> f t
372+ gHint (ErrorCheckingKind t) = ErrorCheckingKind <$> f t
373+ gHint (ErrorInApplication e1 t1 e2) = ErrorInApplication e1 <$> f t1 <*> pure e2
374+ gHint other = pure other
395375
396376-- |
397377-- Pretty print a single error, simplifying if necessary
398378--
399379prettyPrintSingleError :: Bool -> Level -> ErrorMessage -> State UnknownMap Box.Box
400−prettyPrintSingleError full level e = prettyPrintErrorMessage <$> onTypesInErrorMessageM replaceUnknowns (if full then e else simplifyErrorMessage e)
380+prettyPrintSingleError full level e = prettyPrintErrorMessage . positionHintsFirst . reverseHints <$> onTypesInErrorMessageM replaceUnknowns (if full then e else simplifyErrorMessage e)
401381 where
402− -- |
382+
403383 -- Pretty print an ErrorMessage
404− --
405384 prettyPrintErrorMessage :: ErrorMessage -> Box.Box
406− prettyPrintErrorMessage em =
385+ prettyPrintErrorMessage (ErrorMessage hints simple) =
407386 paras $
408− go em:suggestions em ++
387+ map renderHint hints ++
388+ renderSimpleErrorMessage simple :
389+ suggestions simple ++
409390 [line $ "See " ++ wikiUri ++ " for more information, or to contribute content related to this " ++ levelText ++ "."]
410391 where
411392 wikiUri :: String
412393 wikiUri = "https://github.com/purescript/purescript/wiki/Error-Code-" ++ errorCode e
413394
414− go :: ErrorMessage -> Box.Box
415− goSimple (CannotGetFileInfo path) =
395+ renderSimpleErrorMessage :: SimpleErrorMessage -> Box.Box
396+ renderSimpleErrorMessage (CannotGetFileInfo path) =
416397 paras [ line "Unable to read file info: "
417398 , indent . line $ path
418399 ]
419− goSimple (CannotReadFile path) =
400+ renderSimpleErrorMessage (CannotReadFile path) =
420401 paras [ line "Unable to read file: "
421402 , indent . line $ path
422403 ]
423− goSimple (CannotWriteFile path) =
404+ renderSimpleErrorMessage (CannotWriteFile path) =
424405 paras [ line "Unable to write file: "
425406 , indent . line $ path
426407 ]
427− goSimple (ErrorParsingExterns err) =
408+ renderSimpleErrorMessage (ErrorParsingExterns err) =
428409 paras [ lineWithLevel "parsing externs files: "
429− , indent . prettyPrintParseError $ err
410+ , prettyPrintParseError err
430411 ]
431− goSimple (ErrorParsingFFIModule path) =
412+ renderSimpleErrorMessage (ErrorParsingFFIModule path) =
432413 paras [ line "Unable to parse module from FFI file: "
433414 , indent . line $ path
434415 ]
435− goSimple (ErrorParsingModule err) =
416+ renderSimpleErrorMessage (ErrorParsingModule err) =
436417 paras [ line "Unable to parse module: "
437− , indent . prettyPrintParseError $ err
418+ , prettyPrintParseError err
438419 ]
439− goSimple (MissingFFIModule mn) =
420+ renderSimpleErrorMessage (MissingFFIModule mn) =
440421 line $ "Missing FFI implementations for module " ++ runModuleName mn
441− goSimple (UnnecessaryFFIModule mn path) =
422+ renderSimpleErrorMessage (UnnecessaryFFIModule mn path) =
442423 paras [ line $ "Unnecessary FFI implementations have been provided for module " ++ runModuleName mn ++ ": "
443424 , indent . line $ path
444425 ]
445− goSimple (MultipleFFIModules mn paths) =
446− paras $ [ line $ "Multiple FFI implementations have been provided for module " ++ runModuleName mn ++ ": " ]
447− ++ map (indent . line) paths
448− goSimple (InvalidExternsFile path) =
426+ renderSimpleErrorMessage (MultipleFFIModules mn paths) =
427+ paras [ line $ "Multiple FFI implementations have been provided for module " ++ runModuleName mn ++ ": "
428+ , indent . paras $ map line paths
429+ ]
430+ renderSimpleErrorMessage (InvalidExternsFile path) =
449431 paras [ line "Externs file is invalid: "
450432 , indent . line $ path
451433 ]
452− goSimple InvalidDoBind =
434+ renderSimpleErrorMessage InvalidDoBind =
453435 line "Bind statement cannot be the last statement in a do block. The last statement must be an expression."
454− goSimple InvalidDoLet =
436+ renderSimpleErrorMessage InvalidDoLet =
455437 line "Let statement cannot be the last statement in a do block. The last statement must be an expression."
456− goSimple CannotReorderOperators =
438+ renderSimpleErrorMessage CannotReorderOperators =
457439 line "Unable to reorder operators"
458− goSimple UnspecifiedSkolemScope =
440+ renderSimpleErrorMessage UnspecifiedSkolemScope =
459441 line "Skolem variable scope is unspecified"
460− goSimple OverlappingNamesInLet =
442+ renderSimpleErrorMessage OverlappingNamesInLet =
461443 line "Overlapping names in let binding."
462− goSimple (InfiniteType ty) =
444+ renderSimpleErrorMessage (InfiniteType ty) =
463445 paras [ line "An infinite type was inferred for an expression: "
464− , indent $ line $ prettyPrintType ty
446+ , indent $ typeAsBox ty
465447 ]
466− goSimple (InfiniteKind ki) =
448+ renderSimpleErrorMessage (InfiniteKind ki) =
467449 paras [ line "An infinite kind was inferred for a type: "
468− , indent $ line $ prettyPrintKind ki
450+ , indent $ kindAsBox ki
469451 ]
470− goSimple (MultipleFixities name) =
452+ renderSimpleErrorMessage (MultipleFixities name) =
471453 line $ "Multiple fixity declarations for " ++ showIdent name
472− goSimple (OrphanTypeDeclaration nm) =
454+ renderSimpleErrorMessage (OrphanTypeDeclaration nm) =
473455 line $ "Orphan type declaration for " ++ showIdent nm
474− goSimple (OrphanFixityDeclaration op) =
456+ renderSimpleErrorMessage (OrphanFixityDeclaration op) =
475457 line $ "Orphan fixity declaration for " ++ show op
476− goSimple (RedefinedModule name filenames) =
477− paras $ line ("Module " ++ runModuleName name ++ " has been defined multiple times:")
478− : map (indent . line . displaySourceSpan) filenames
479− goSimple (RedefinedIdent name) =
458+ renderSimpleErrorMessage (RedefinedModule name filenames) =
459+ paras [ line ("Module " ++ runModuleName name ++ " has been defined multiple times:")
460+ , indent . paras $ map (line . displaySourceSpan) filenames
461+ ]
462+ renderSimpleErrorMessage (RedefinedIdent name) =
480463 line $ "Name " ++ showIdent name ++ " has been defined multiple times"
481− goSimple (UnknownModule mn) =
464+ renderSimpleErrorMessage (UnknownModule mn) =
482465 line $ "Unknown module " ++ runModuleName mn
483− goSimple (UnknownType name) =
466+ renderSimpleErrorMessage (UnknownType name) =
484467 line $ "Unknown type " ++ showQualified runProperName name
485− goSimple (UnknownTypeClass name) =
468+ renderSimpleErrorMessage (UnknownTypeClass name) =
486469 line $ "Unknown type class " ++ showQualified runProperName name
487− goSimple (UnknownValue name) =
470+ renderSimpleErrorMessage (UnknownValue name) =
488471 line $ "Unknown value " ++ showQualified showIdent name
489− goSimple (UnknownTypeConstructor name) =
472+ renderSimpleErrorMessage (UnknownTypeConstructor name) =
490473 line $ "Unknown type constructor " ++ showQualified runProperName name
491− goSimple (UnknownDataConstructor dc tc) =
474+ renderSimpleErrorMessage (UnknownDataConstructor dc tc) =
492475 line $ "Unknown data constructor " ++ showQualified runProperName dc ++ foldMap ((" for type constructor " ++) . showQualified runProperName) tc
493− goSimple (UnknownImportType mn name) =
476+ renderSimpleErrorMessage (UnknownImportType mn name) =
494477 line $ "Module " ++ runModuleName mn ++ " does not export type " ++ runProperName name
495− goSimple (UnknownExportType name) =
478+ renderSimpleErrorMessage (UnknownExportType name) =
496479 line $ "Cannot export unknown type " ++ runProperName name
497− goSimple (UnknownImportTypeClass mn name) =
480+ renderSimpleErrorMessage (UnknownImportTypeClass mn name) =
498481 line $ "Module " ++ runModuleName mn ++ " does not export type class " ++ runProperName name
499− goSimple (UnknownExportTypeClass name) =
482+ renderSimpleErrorMessage (UnknownExportTypeClass name) =
500483 line $ "Cannot export unknown type class " ++ runProperName name
501− goSimple (UnknownImportValue mn name) =
484+ renderSimpleErrorMessage (UnknownImportValue mn name) =
502485 line $ "Module " ++ runModuleName mn ++ " does not export value " ++ showIdent name
503− goSimple (UnknownExportValue name) =
486+ renderSimpleErrorMessage (UnknownExportValue name) =
504487 line $ "Cannot export unknown value " ++ showIdent name
505− goSimple (UnknownExportModule name) =
488+ renderSimpleErrorMessage (UnknownExportModule name) =
506489 line $ "Cannot export unknown module " ++ runModuleName name ++ ", it either does not exist or has not been imported by the current module"
507− goSimple (UnknownImportDataConstructor mn tcon dcon) =
490+ renderSimpleErrorMessage (UnknownImportDataConstructor mn tcon dcon) =
508491 line $ "Module " ++ runModuleName mn ++ " does not export data constructor " ++ runProperName dcon ++ " for type " ++ runProperName tcon
509− goSimple (UnknownExportDataConstructor tcon dcon) =
492+ renderSimpleErrorMessage (UnknownExportDataConstructor tcon dcon) =
510493 line $ "Cannot export data constructor " ++ runProperName dcon ++ " for type " ++ runProperName tcon ++ " as it has not been declared"
511− goSimple (ConflictingImport nm mn) =
494+ renderSimpleErrorMessage (ConflictingImport nm mn) =
512495 line $ "Cannot declare " ++ show nm ++ " since another declaration of that name was imported from " ++ runModuleName mn
513− goSimple (ConflictingImports nm m1 m2) =
496+ renderSimpleErrorMessage (ConflictingImports nm m1 m2) =
514497 line $ "Conflicting imports for " ++ nm ++ " from modules " ++ runModuleName m1 ++ " and " ++ runModuleName m2
515− goSimple (ConflictingTypeDecls nm) =
498+ renderSimpleErrorMessage (ConflictingTypeDecls nm) =
516499 line $ "Conflicting type declarations for " ++ runProperName nm
517− goSimple (ConflictingCtorDecls nm) =
500+ renderSimpleErrorMessage (ConflictingCtorDecls nm) =
518501 line $ "Conflicting data constructor declarations for " ++ runProperName nm
519− goSimple (TypeConflictsWithClass nm) =
502+ renderSimpleErrorMessage (TypeConflictsWithClass nm) =
520503 line $ "Type " ++ runProperName nm ++ " conflicts with type class declaration of the same name"
521− goSimple (CtorConflictsWithClass nm) =
504+ renderSimpleErrorMessage (CtorConflictsWithClass nm) =
522505 line $ "Data constructor " ++ runProperName nm ++ " conflicts with type class declaration of the same name"
523− goSimple (ClassConflictsWithType nm) =
506+ renderSimpleErrorMessage (ClassConflictsWithType nm) =
524507 line $ "Type class " ++ runProperName nm ++ " conflicts with type declaration of the same name"
525− goSimple (ClassConflictsWithCtor nm) =
508+ renderSimpleErrorMessage (ClassConflictsWithCtor nm) =
526509 line $ "Type class " ++ runProperName nm ++ " conflicts with data constructor declaration of the same name"
527− goSimple (DuplicateClassExport nm) =
510+ renderSimpleErrorMessage (DuplicateModuleName mn) =
511+ line $ "Module " ++ runModuleName mn ++ " has been defined multiple times."
512+ renderSimpleErrorMessage (DuplicateClassExport nm) =
528513 line $ "Duplicate export declaration for type class " ++ runProperName nm
529− goSimple (DuplicateValueExport nm) =
514+ renderSimpleErrorMessage (DuplicateValueExport nm) =
530515 line $ "Duplicate export declaration for value " ++ showIdent nm
531− goSimple (CycleInDeclaration nm) =
516+ renderSimpleErrorMessage (CycleInDeclaration nm) =
532517 line $ "Cycle in declaration of " ++ showIdent nm
533− goSimple (CycleInModules mns) =
518+ renderSimpleErrorMessage (CycleInModules mns) =
534519 line $ "Cycle in module dependencies: " ++ intercalate ", " (map runModuleName mns)
535− goSimple (CycleInTypeSynonym pn) =
520+ renderSimpleErrorMessage (CycleInTypeSynonym pn) =
536521 line $ "Cycle in type synonym" ++ foldMap ((" " ++) . runProperName) pn
537− goSimple (NameIsUndefined ident) =
522+ renderSimpleErrorMessage (NameIsUndefined ident) =
538523 line $ showIdent ident ++ " is undefined"
539− goSimple (NameNotInScope ident) =
524+ renderSimpleErrorMessage (NameNotInScope ident) =
540525 line $ showIdent ident ++ " may not be defined in the current scope"
541− goSimple (UndefinedTypeVariable name) =
526+ renderSimpleErrorMessage (UndefinedTypeVariable name) =
542527 line $ "Type variable " ++ runProperName name ++ " is undefined"
543− goSimple (PartiallyAppliedSynonym name) =
528+ renderSimpleErrorMessage (PartiallyAppliedSynonym name) =
544529 paras [ line $ "Partially applied type synonym " ++ showQualified runProperName name
545530 , line "Type synonyms must be applied to all of their type arguments."
546531 ]
547− goSimple (EscapedSkolem binding) =
532+ renderSimpleErrorMessage (EscapedSkolem binding) =
548533 paras $ [ line "A type variable has escaped its scope." ]
549534 <> foldMap (\expr -> [ line "Relevant expression: "
550− , indent $ line $ prettyPrintValue expr
535+ , indent $ prettyPrintValue expr
551536 ]) binding
552− goSimple (TypesDoNotUnify t1 t2)
537+ renderSimpleErrorMessage (TypesDoNotUnify t1 t2)
553538 = paras [ line "Cannot unify type"
554− , indent $ line $ prettyPrintType t1
539+ , indent $ typeAsBox t1
555540 , line "with type"
556− , indent $ line $ prettyPrintType t2
541+ , indent $ typeAsBox t2
557542 ]
558− goSimple (KindsDoNotUnify k1 k2) =
543+ renderSimpleErrorMessage (KindsDoNotUnify k1 k2) =
559544 paras [ line "Cannot unify kind"
560− , indent $ line $ prettyPrintKind k1
545+ , indent $ kindAsBox k1
561546 , line "with kind"
562− , indent $ line $ prettyPrintKind k2
547+ , indent $ kindAsBox k2
563548 ]
564− goSimple (ConstrainedTypeUnified t1 t2) =
549+ renderSimpleErrorMessage (ConstrainedTypeUnified t1 t2) =
565550 paras [ line "Cannot unify constrained type"
566− , indent $ line $ prettyPrintType t1
551+ , indent $ typeAsBox t1
567552 , line "with type"
568− , indent $ line $ prettyPrintType t2
569− ]
570− goSimple (OverlappingInstances nm ts (d : ds)) =
571− paras [ line $ "Overlapping instances found for " ++ showQualified runProperName nm ++ " " ++ unwords (map prettyPrintTypeAtom ts) ++ ":"
553+ , indent $ typeAsBox t2
554+ ]
555+ renderSimpleErrorMessage (OverlappingInstances nm ts (d : ds)) =
556+ paras [ line "Overlapping instances found for"
557+ , indent $ Box.hsep 1 Box.left [ line (showQualified runProperName nm)
558+ , Box.vcat Box.left (map typeAtomAsBox ts)
559+ ]
560+ , line "The following instances were found:"
572561 , indent $ paras (line (showQualified showIdent d ++ " (chosen)") : map (line . showQualified showIdent) ds)
573562 ]
574− goSimple OverlappingInstances{} = error "OverlappingInstances: empty instance list"
575− goSimple (NoInstanceFound nm ts) =
576− line $ "No instance found for " ++ showQualified runProperName nm ++ " " ++ unwords (map prettyPrintTypeAtom ts)
577− goSimple (PossiblyInfiniteInstance nm ts) =
578− line $ "Instance for " ++ showQualified runProperName nm ++ " " ++ unwords (map prettyPrintTypeAtom ts) ++ " is possibly infinite."
579− goSimple (CannotDerive nm ts) =
580− line $ "Cannot derive " ++ showQualified runProperName nm ++ " instance for " ++ unwords (map prettyPrintTypeAtom ts)
581− goSimple (CannotFindDerivingType nm) =
563+ renderSimpleErrorMessage OverlappingInstances{} = error "OverlappingInstances: empty instance list"
564+ renderSimpleErrorMessage (NoInstanceFound nm ts) =
565+ paras [ line "No instance found for"
566+ , indent $ Box.hsep 1 Box.left [ line (showQualified runProperName nm)
567+ , Box.vcat Box.left (map typeAtomAsBox ts)
568+ ]
569+ ]
570+ renderSimpleErrorMessage (PossiblyInfiniteInstance nm ts) =
571+ paras [ line "Instance for"
572+ , indent $ Box.hsep 1 Box.left [ line (showQualified runProperName nm)
573+ , Box.vcat Box.left (map typeAtomAsBox ts)
574+ ]
575+ , line "is possibly infinite."
576+ ]
577+ renderSimpleErrorMessage (CannotDerive nm ts) =
578+ paras [ line "Cannot derive an instance for"
579+ , indent $ Box.hsep 1 Box.left [ line (showQualified runProperName nm)
580+ , Box.vcat Box.left (map typeAtomAsBox ts)
581+ ]
582+ ]
583+ renderSimpleErrorMessage (CannotFindDerivingType nm) =
582584 line $ "Cannot derive instance, because the type declaration for " ++ runProperName nm ++ " could not be found."
583− goSimple (DuplicateLabel l expr) =
585+ renderSimpleErrorMessage (DuplicateLabel l expr) =
584586 paras $ [ line $ "Duplicate label " ++ show l ++ " in row." ]
585587 <> foldMap (\expr' -> [ line "Relevant expression: "
586− , indent $ line $ prettyPrintValue expr'
588+ , indent $ prettyPrintValue expr'
587589 ]) expr
588− goSimple (DuplicateTypeArgument name) =
590+ renderSimpleErrorMessage (DuplicateTypeArgument name) =
589591 line $ "Duplicate type argument " ++ show name
590− goSimple (DuplicateValueDeclaration nm) =
592+ renderSimpleErrorMessage (DuplicateValueDeclaration nm) =
591593 line $ "Duplicate value declaration for " ++ showIdent nm
592− goSimple (ArgListLengthsDiffer ident) =
594+ renderSimpleErrorMessage (ArgListLengthsDiffer ident) =
593595 line $ "Argument list lengths differ in declaration " ++ showIdent ident
594− goSimple (OverlappingArgNames ident) =
596+ renderSimpleErrorMessage (OverlappingArgNames ident) =
595597 line $ "Overlapping names in function/binder" ++ foldMap ((" in declaration" ++) . showIdent) ident
596− goSimple (MissingClassMember ident) =
598+ renderSimpleErrorMessage (MissingClassMember ident) =
597599 line $ "Member " ++ showIdent ident ++ " has not been implemented"
598− goSimple (ExtraneousClassMember ident) =
600+ renderSimpleErrorMessage (ExtraneousClassMember ident) =
599601 line $ "Member " ++ showIdent ident ++ " is not a member of the class being instantiated"
600− goSimple (ExpectedType ty kind) =
602+ renderSimpleErrorMessage (ExpectedType ty kind) =
601603 paras [ line "In a type-annotated expression x :: t, the type t must have kind *."
602− , line $ "The error arises from the type " ++ prettyPrintType ty ++ " having the kind " ++ prettyPrintKind kind ++ " instead."
604+ , line "The error arises from the type"
605+ , indent $ typeAsBox ty
606+ , line "having the kind"
607+ , indent $ kindAsBox kind
608+ , line "instead."
603609 ]
604− goSimple (IncorrectConstructorArity nm) =
610+ renderSimpleErrorMessage (IncorrectConstructorArity nm) =
605611 line $ "Wrong number of arguments to constructor " ++ showQualified runProperName nm
606− goSimple SubsumptionCheckFailed = line "Unable to check type subsumption"
607− goSimple (ExprDoesNotHaveType expr ty) =
612+ renderSimpleErrorMessage SubsumptionCheckFailed = line "Unable to check type subsumption"
613+ renderSimpleErrorMessage (ExprDoesNotHaveType expr ty) =
608614 paras [ line "Expression"
609− , indent $ line $ prettyPrintValue expr
615+ , indent $ prettyPrintValue expr
610616 , line "does not have type"
611− , indent $ line $ prettyPrintType ty
617+ , indent $ typeAsBox ty
612618 ]
613− goSimple (PropertyIsMissing prop row) =
614− line $ "Row " ++ prettyPrintRow row ++ " lacks required property " ++ show prop
615− goSimple (CannotApplyFunction fn arg) =
619+ renderSimpleErrorMessage (PropertyIsMissing prop row) =
620+ paras [ line "Row"
621+ , indent $ prettyPrintRowWith '(' ')' row
622+ , line $ "lacks required property " ++ show prop
623+ ]
624+ renderSimpleErrorMessage (CannotApplyFunction fn arg) =
616625 paras [ line "Cannot apply function of type"
617− , indent $ line $ prettyPrintType fn
626+ , indent $ typeAsBox fn
618627 , line "to argument"
619− , indent $ line $ prettyPrintValue arg
628+ , indent $ prettyPrintValue arg
620629 ]
621− goSimple TypeSynonymInstance =
630+ renderSimpleErrorMessage TypeSynonymInstance =
622631 line "Type synonym instances are disallowed"
623− goSimple (OrphanInstance nm cnm ts) =
624− paras [ line $ "Instance " ++ showIdent nm ++ " for " ++ showQualified runProperName cnm ++ " " ++ unwords (map prettyPrintTypeAtom ts) ++ " is an orphan instance."
632+ renderSimpleErrorMessage (OrphanInstance nm cnm ts) =
633+ paras [ line $ "Instance " ++ showIdent nm ++ " for "
634+ , indent $ Box.hsep 1 Box.left [ line (showQualified runProperName cnm)
635+ , Box.vcat Box.left (map typeAtomAsBox ts)
636+ ]
637+ , line "is an orphan instance."
625638 , line "An orphan instance is an instance which is defined in neither the class module nor the data type module."
626639 , line "Consider moving the instance, if possible, or using a newtype wrapper."
627640 ]
628− goSimple InvalidNewtype =
641+ renderSimpleErrorMessage InvalidNewtype =
629642 line "Newtypes must define a single constructor with a single argument"
630− goSimple (InvalidInstanceHead ty) =
643+ renderSimpleErrorMessage (InvalidInstanceHead ty) =
631644 paras [ line "Invalid type in class instance head:"
632− , indent $ line $ prettyPrintType ty
645+ , indent $ typeAsBox ty
633646 ]
634− goSimple (TransitiveExportError x ys) =
647+ renderSimpleErrorMessage (TransitiveExportError x ys) =
635648 paras $ line ("An export for " ++ prettyPrintExport x ++ " requires the following to also be exported: ")
636649 : map (line . prettyPrintExport) ys
637− goSimple (ShadowedName nm) =
650+ renderSimpleErrorMessage (ShadowedName nm) =
638651 line $ "Name '" ++ showIdent nm ++ "' was shadowed"
639− goSimple (ShadowedTypeVar tv) =
652+ renderSimpleErrorMessage (ShadowedTypeVar tv) =
640653 line $ "Type variable '" ++ tv ++ "' was shadowed"
641− goSimple (UnusedTypeVar tv) =
654+ renderSimpleErrorMessage (UnusedTypeVar tv) =
642655 line $ "Type variable '" ++ tv ++ "' was declared but not used"
643− goSimple (ClassOperator className opName) =
656+ renderSimpleErrorMessage (ClassOperator className opName) =
644657 paras [ line $ "Class '" ++ runProperName className ++ "' declares operator " ++ showIdent opName ++ "."
645− , indent $ line "This may be disallowed in the future - consider declaring a named member in the class and making the operator an alias:"
646− , indent $ line $ showIdent opName ++ " = someMember"
658+ , line "This may be disallowed in the future - consider declaring a named member in the class and making the operator an alias:"
659+ , indent . line $ showIdent opName ++ " = someMember"
647660 ]
648− goSimple (MisleadingEmptyTypeImport mn name) =
661+ renderSimpleErrorMessage (MisleadingEmptyTypeImport mn name) =
649662 line $ "Importing type " ++ runProperName name ++ "(..) from " ++ runModuleName mn ++ " is misleading as it has no exported data constructors"
650− goSimple (ImportHidingModule name) =
663+ renderSimpleErrorMessage (ImportHidingModule name) =
651664 line $ "Attempted to hide module " ++ runModuleName name ++ " in import expression, this is not permitted"
652− goSimple (WildcardInferredType ty) =
653− line $ "The wildcard type definition has the inferred type " ++ prettyPrintType ty
654− goSimple (NotExhaustivePattern bs b) =
665+ renderSimpleErrorMessage (WildcardInferredType ty) =
666+ paras [ line "The wildcard type definition has the inferred type "
667+ , indent $ typeAsBox ty
668+ ]
669+ renderSimpleErrorMessage (MissingTypeDeclaration ident) =
670+ paras [ line $ "No type declaration was provided for the top-level declaration of " ++ showIdent ident ++ "."
671+ , line "It is good practice to provide type declarations as a form of documentation."
672+ , line "Consider using a type wildcard to display the inferred type:"
673+ , indent $ line $ showIdent ident ++ " :: _"
674+ ]
675+ renderSimpleErrorMessage (NotExhaustivePattern bs b) =
655676 paras $ [ line "A case expression could not be determined to cover all inputs."
656677 , line "The following additional cases are required to cover all inputs:\n"
657678 , Box.hsep 1 Box.left (map (paras . map (line . prettyPrintBinderAtom)) (transpose bs))
658679 ] ++
659680 [ line "..." | not b ]
660− goSimple (OverlappingPattern bs b) =
681+ renderSimpleErrorMessage (OverlappingPattern bs b) =
661682 paras $ [ line "A case expression contains unreachable cases:\n"
662683 , Box.hsep 1 Box.left (map (paras . map (line . prettyPrintBinderAtom)) (transpose bs))
663684 ] ++
664685 [ line "..." | not b ]
665− go (NotYetDefined names err) =
666− paras [ line $ "The following are not yet defined here: " ++ intercalate ", " (map showIdent names) ++ ":"
667− , indent $ go err
686+ renderSimpleErrorMessage IncompleteExhaustivityCheck =
687+ paras [ line "An exhaustivity check was abandoned due to too many possible cases."
688+ , line "You may want to decomposing your data types into smaller types."
668689 ]
669− go (ErrorUnifyingTypes t1 t2 err) =
690+
691+ renderHint :: ErrorMessageHint -> Box.Box
692+ renderHint (NotYetDefined names) =
693+ line $ "The following are not yet defined here: " ++ intercalate ", " (map showIdent names) ++ ":"
694+ renderHint (ErrorUnifyingTypes t1 t2) =
670695 paras [ lineWithLevel "unifying type "
671− , indent $ line $ prettyPrintType t1
696+ , indent $ typeAsBox t1
672697 , line "with type"
673− , indent $ line $ prettyPrintType t2
674− , go err
698+ , indent $ typeAsBox t2
675699 ]
676− go (ErrorInExpression expr err) =
700+ renderHint (ErrorInExpression expr) =
677701 paras [ lineWithLevel "in expression:"
678− , indent $ line $ prettyPrintValue expr
679− , go err
702+ , indent $ prettyPrintValue expr
680703 ]
681− go (ErrorInModule mn err) =
704+ renderHint (ErrorInModule mn) =
682705 paras [ lineWithLevel $ "in module " ++ runModuleName mn ++ ":"
683− , go err
684706 ]
685− go (ErrorInSubsumption t1 t2 err) =
707+ renderHint (ErrorInSubsumption t1 t2) =
686708 paras [ lineWithLevel "checking that type "
687− , indent $ line $ prettyPrintType t1
709+ , indent $ typeAsBox t1
688710 , line "subsumes type"
689− , indent $ line $ prettyPrintType t2
690− , go err
711+ , indent $ typeAsBox t2
691712 ]
692− go (ErrorInInstance name ts err) =
693− paras [ lineWithLevel $ "in type class instance " ++ showQualified runProperName name ++ " " ++ unwords (map prettyPrintTypeAtom ts) ++ ":"
694− , go err
713+ renderHint (ErrorInInstance nm ts) =
714+ paras [ lineWithLevel "in type class instance"
715+ , indent $ Box.hsep 1 Box.left [ line (showQualified runProperName nm)
716+ , Box.vcat Box.left (map typeAtomAsBox ts)
717+ ]
695718 ]
696− go (ErrorCheckingKind ty err) =
719+ renderHint (ErrorCheckingKind ty) =
697720 paras [ lineWithLevel "checking kind of type "
698− , indent $ line $ prettyPrintType ty
699− , go err
721+ , indent $ typeAsBox ty
700722 ]
701− go (ErrorInferringType expr err) =
723+ renderHint (ErrorInferringType expr) =
702724 paras [ lineWithLevel "inferring type of value "
703− , indent $ line $ prettyPrintValue expr
704− , go err
725+ , indent $ prettyPrintValue expr
705726 ]
706− go (ErrorCheckingType expr ty err) =
727+ renderHint (ErrorCheckingType expr ty) =
707728 paras [ lineWithLevel "checking that value "
708− , indent $ line $ prettyPrintValue expr
729+ , indent $ prettyPrintValue expr
709730 , line "has type"
710− , indent $ line $ prettyPrintType ty
711− , go err
731+ , indent $ typeAsBox ty
712732 ]
713− go (ErrorInApplication f t a err) =
733+ renderHint (ErrorInApplication f t a) =
714734 paras [ lineWithLevel "applying function"
715− , indent $ line $ prettyPrintValue f
735+ , indent $ prettyPrintValue f
716736 , line "of type"
717− , indent $ line $ prettyPrintType t
737+ , indent $ typeAsBox t
718738 , line "to argument"
719− , indent $ line $ prettyPrintValue a
720− , go err
721− ]
722− go (ErrorInDataConstructor nm err) =
723− paras [ lineWithLevel $ "in data constructor " ++ runProperName nm ++ ":"
724− , go err
725− ]
726− go (ErrorInTypeConstructor nm err) =
727− paras [ lineWithLevel $ "in type constructor " ++ runProperName nm ++ ":"
728− , go err
729− ]
730− go (ErrorInBindingGroup nms err) =
731− paras [ lineWithLevel $ "in binding group " ++ intercalate ", " (map showIdent nms) ++ ":"
732− , go err
733− ]
734− go (ErrorInDataBindingGroup err) =
735− paras [ lineWithLevel $ "in data binding group:"
736− , go err
737− ]
738− go (ErrorInTypeSynonym name err) =
739− paras [ lineWithLevel $ "in type synonym " ++ runProperName name ++ ":"
740− , go err
741− ]
742− go (ErrorInValueDeclaration n err) =
743− paras [ lineWithLevel $ "in value declaration " ++ showIdent n ++ ":"
744− , go err
745− ]
746− go (ErrorInTypeDeclaration n err) =
747− paras [ lineWithLevel $ "in type declaration for " ++ showIdent n ++ ":"
748− , go err
749− ]
750− go (ErrorInForeignImport nm err) =
751− paras [ lineWithLevel $ "in foreign import " ++ showIdent nm ++ ":"
752− , go err
753− ]
754− go (PositionedError srcSpan err) =
755− paras [ lineWithLevel $ "at " ++ displaySourceSpan srcSpan ++ ":"
756− , indent $ go err
757− ]
758− go (SimpleErrorWrapper sem) = goSimple sem
739+ , indent $ prettyPrintValue a
740+ ]
741+ renderHint (ErrorInDataConstructor nm) =
742+ lineWithLevel $ "in data constructor " ++ runProperName nm ++ ":"
743+ renderHint (ErrorInTypeConstructor nm) =
744+ lineWithLevel $ "in type constructor " ++ runProperName nm ++ ":"
745+ renderHint (ErrorInBindingGroup nms) =
746+ lineWithLevel $ "in binding group " ++ intercalate ", " (map showIdent nms) ++ ":"
747+ renderHint ErrorInDataBindingGroup =
748+ lineWithLevel "in data binding group:"
749+ renderHint (ErrorInTypeSynonym name) =
750+ lineWithLevel $ "in type synonym " ++ runProperName name ++ ":"
751+ renderHint (ErrorInValueDeclaration n) =
752+ lineWithLevel $ "in value declaration " ++ showIdent n ++ ":"
753+ renderHint (ErrorInTypeDeclaration n) =
754+ lineWithLevel $ "in type declaration for " ++ showIdent n ++ ":"
755+ renderHint (ErrorInForeignImport nm) =
756+ lineWithLevel $ "in foreign import " ++ showIdent nm ++ ":"
757+ renderHint (PositionedError srcSpan) =
758+ lineWithLevel $ "at " ++ displaySourceSpan srcSpan ++ ":"
759759
760760 lineWithLevel :: String -> Box.Box
761761 lineWithLevel text = line $ show level ++ " " ++ text
@@ -765,23 +765,19 @@ prettyPrintSingleError full level e = prettyPrintErrorMessage <$> onTypesInError
765765 Error -> "error"
766766 Warning -> "warning"
767767
768− suggestions :: ErrorMessage -> [Box.Box]
769− suggestions = suggestions' . unwrapErrorMessage
770− where
771− suggestions' (ConflictingImport nm im) = [ line $ "Possible fix: hide " ++ show nm ++ " when importing " ++ runModuleName im ++ ":"
768+ suggestions :: SimpleErrorMessage -> [Box.Box]
769+ suggestions (ConflictingImport nm im) = [ line $ "Possible fix: hide " ++ show nm ++ " when importing " ++ runModuleName im ++ ":"
772770 , indent . line $ "import " ++ runModuleName im ++ " hiding (" ++ nm ++ ")"
773771 ]
774− suggestions' (TypesDoNotUnify t1 t2)
775− | isObject t1 && isFunction t2 = [line "Note that function composition in PureScript is defined using (<<<)"]
776− | otherwise = []
777− suggestions' _ = []
772+ suggestions (TypesDoNotUnify t1 t2)
773+ | isObject t1 && isFunction t2 = [line "Note that function composition in PureScript is defined using (<<<)"]
774+ | otherwise = []
775+ suggestions _ = []
778776
779777 paras :: [Box.Box] -> Box.Box
780778 paras = Box.vcat Box.left
781779
782− -- |
783780 -- Pretty print and export declaration
784− --
785781 prettyPrintExport :: DeclarationRef -> String
786782 prettyPrintExport (TypeRef pn _) = runProperName pn
787783 prettyPrintExport (ValueRef ident) = showIdent ident
@@ -790,38 +786,44 @@ prettyPrintSingleError full level e = prettyPrintErrorMessage <$> onTypesInError
790786 prettyPrintExport (ModuleRef name) = "module " ++ runModuleName name
791787 prettyPrintExport (PositionedDeclarationRef _ _ ref) = prettyPrintExport ref
792788
793− -- |
794− -- Simplify an error message
795− --
796− simplifyErrorMessage :: ErrorMessage -> ErrorMessage
797− simplifyErrorMessage = unwrap Nothing
789+ -- Hints get added at the front, so we need to reverse them before rendering
790+ reverseHints :: ErrorMessage -> ErrorMessage
791+ reverseHints (ErrorMessage hints simple) = ErrorMessage (reverse hints) simple
792+
793+ -- | Put positional hints at the front of the list
794+ positionHintsFirst :: ErrorMessage -> ErrorMessage
795+ positionHintsFirst (ErrorMessage hints simple) = ErrorMessage (uncurry (++) $ partition (isPositionHint . hintCategory) hints) simple
798796 where
799− unwrap :: Maybe SourceSpan -> ErrorMessage -> ErrorMessage
800− unwrap pos (ErrorInExpression _ err) = unwrap pos err
801− unwrap pos (ErrorInInstance name ts err) = ErrorInInstance name ts (unwrap pos err)
802− unwrap pos (ErrorInSubsumption t1 t2 err) = ErrorInSubsumption t1 t2 (unwrap pos err)
803− unwrap pos (ErrorUnifyingTypes _ _ err) = unwrap pos err
804− unwrap pos (ErrorInferringType _ err) = unwrap pos err
805− unwrap pos (ErrorCheckingType _ _ err) = unwrap pos err
806− unwrap pos (ErrorCheckingKind ty err) = ErrorCheckingKind ty (unwrap pos err)
807− unwrap pos (ErrorInModule mn err) = ErrorInModule mn (unwrap pos err)
808− unwrap pos (ErrorInApplication _ _ _ err) = unwrap pos err
809− unwrap pos (ErrorInDataConstructor nm err) = ErrorInDataConstructor nm (unwrap pos err)
810− unwrap pos (ErrorInTypeConstructor nm err) = ErrorInTypeConstructor nm (unwrap pos err)
811− unwrap pos (ErrorInBindingGroup nms err) = ErrorInBindingGroup nms (unwrap pos err)
812− unwrap pos (ErrorInDataBindingGroup err) = ErrorInDataBindingGroup (unwrap pos err)
813− unwrap pos (ErrorInTypeSynonym nm err) = ErrorInTypeSynonym nm (unwrap pos err)
814− unwrap pos (ErrorInValueDeclaration nm err) = ErrorInValueDeclaration nm (unwrap pos err)
815− unwrap pos (ErrorInTypeDeclaration nm err) = ErrorInTypeDeclaration nm (unwrap pos err)
816− unwrap pos (ErrorInForeignImport nm err) = ErrorInForeignImport nm (unwrap pos err)
817− unwrap pos (NotYetDefined ns err) = NotYetDefined ns (unwrap pos err)
818− unwrap _ (PositionedError pos err) = unwrap (Just pos) err
819− unwrap pos other = wrap pos other
820−
821− wrap :: Maybe SourceSpan -> ErrorMessage -> ErrorMessage
822− wrap Nothing = id
823− wrap (Just pos) = PositionedError pos
797+ isPositionHint :: HintCategory -> Bool
798+ isPositionHint PositionHint = True
799+ isPositionHint OtherHint = True
800+ isPositionHint _ = False
824801
802+ -- | Simplify an error message
803+ simplifyErrorMessage :: ErrorMessage -> ErrorMessage
804+ simplifyErrorMessage (ErrorMessage hints simple) = ErrorMessage (simplifyHints hints) simple
805+ where
806+ -- Take the last instance of each "hint category"
807+ simplifyHints :: [ErrorMessageHint] -> [ErrorMessageHint]
808+ simplifyHints = reverse . nubBy categoriesEqual . reverse
809+
810+ -- Don't remove hints in the "other" category
811+ categoriesEqual :: ErrorMessageHint -> ErrorMessageHint -> Bool
812+ categoriesEqual x y =
813+ case (hintCategory x, hintCategory y) of
814+ (OtherHint, _) -> False
815+ (_, OtherHint) -> False
816+ (c1, c2) -> c1 == c2
817+
818+ hintCategory :: ErrorMessageHint -> HintCategory
819+ hintCategory ErrorCheckingType{} = ExprHint
820+ hintCategory ErrorInferringType{} = ExprHint
821+ hintCategory ErrorInExpression{} = ExprHint
822+ hintCategory ErrorUnifyingTypes{} = CheckHint
823+ hintCategory ErrorInSubsumption{} = CheckHint
824+ hintCategory ErrorInApplication{} = CheckHint
825+ hintCategory PositionedError{} = PositionHint
826+ hintCategory _ = OtherHint
825827
826828-- |
827829-- Pretty print multiple errors
@@ -837,11 +839,11 @@ prettyPrintMultipleWarnings full = renderBox . prettyPrintMultipleWarningsBox fu
837839
838840-- | Pretty print warnings as a Box
839841prettyPrintMultipleWarningsBox :: Bool -> MultipleErrors -> Box.Box
840−prettyPrintMultipleWarningsBox full = flip evalState M.empty . prettyPrintMultipleErrorsWith Warning "Warning found:" "Multiple warnings found:" full
842+prettyPrintMultipleWarningsBox full = flip evalState M.empty . prettyPrintMultipleErrorsWith Warning "Warning found:" "Warning" full
841843
842844-- | Pretty print errors as a Box
843845prettyPrintMultipleErrorsBox :: Bool -> MultipleErrors -> Box.Box
844−prettyPrintMultipleErrorsBox full = flip evalState M.empty . prettyPrintMultipleErrorsWith Error "Error found:" "Multiple errors found:" full
846+prettyPrintMultipleErrorsBox full = flip evalState M.empty . prettyPrintMultipleErrorsWith Error "Error found:" "Error" full
845847
846848prettyPrintMultipleErrorsWith :: Level -> String -> String -> Bool -> MultipleErrors -> State UnknownMap Box.Box
847849prettyPrintMultipleErrorsWith level intro _ full (MultipleErrors [e]) = do
@@ -851,15 +853,16 @@ prettyPrintMultipleErrorsWith level intro _ full (MultipleErrors [e]) = do
851853 , result
852854 ]
853855prettyPrintMultipleErrorsWith level _ intro full (MultipleErrors es) = do
854− result <- forM es $ (liftM $ Box.moveRight 2) . prettyPrintSingleError full level
855− return $
856− Box.vcat Box.left [ Box.text intro
857− , Box.vsep 1 Box.left result
858− ]
856+ result <- forM es $ prettyPrintSingleError full level
857+ return $ Box.vsep 1 Box.left $ concat $ zipWith withIntro [1 :: Int ..] result
858+ where
859+ withIntro i err = [ Box.text (intro ++ " " ++ show i ++ " of " ++ show (length es) ++ ":")
860+ , Box.moveRight 2 err
861+ ]
859862
860863-- | Pretty print a Parsec ParseError as a Box
861864prettyPrintParseError :: P.ParseError -> Box.Box
862−prettyPrintParseError = (prettyPrintParseErrorMessages "or" "unknown parse error" "expecting" "unexpected" "end of input") . PE.errorMessages
865+prettyPrintParseError = prettyPrintParseErrorMessages "or" "unknown parse error" "expecting" "unexpected" "end of input" . PE.errorMessages
863866
864867-- |
865868-- Pretty print ParseError detail messages.
@@ -872,9 +875,9 @@ prettyPrintParseErrorMessages msgOr msgUnknown msgExpecting msgUnExpected msgEnd
872875 | otherwise = Box.vcat Box.left $ map Box.text $ clean [showSysUnExpect,showUnExpect,showExpect,showMessages]
873876
874877 where
875− (sysUnExpect,msgs1) = span ((SysUnExpect "") ==) msgs
876− (unExpect,msgs2) = span ((UnExpect "") ==) msgs1
877− (expect,messages) = span ((Expect "") ==) msgs2
878+ (sysUnExpect,msgs1) = span (SysUnExpect "" ==) msgs
879+ (unExpect,msgs2) = span (UnExpect "" ==) msgs1
880+ (expect,messages) = span (Expect "" ==) msgs2
878881
879882 showExpect = showMany msgExpecting expect
880883 showUnExpect = showMany msgUnExpected unExpect
@@ -905,8 +908,9 @@ prettyPrintParseErrorMessages msgOr msgUnknown msgExpecting msgUnExpected msgEnd
905908
906909 clean = nub . filter (not . null)
907910
911+-- | Indent to the right, and pad on top and bottom.
908912indent :: Box.Box -> Box.Box
909−indent = Box.moveRight 2
913+indent = Box.moveUp 1 . Box.moveDown 1 . Box.moveRight 2
910914
911915line :: String -> Box.Box
912916line = Box.text
@@ -922,7 +926,7 @@ renderBox = unlines . map trimEnd . lines . Box.render
922926interpretMultipleErrorsAndWarnings :: (MonadError MultipleErrors m, MonadWriter MultipleErrors m) => (Either MultipleErrors a, MultipleErrors) -> m a
923927interpretMultipleErrorsAndWarnings (err, ws) = do
924928 tell ws
925− either throwError return $ err
929+ either throwError return err
926930
927931-- |
928932-- Rethrow an error with a more detailed error message in the case of failure
@@ -946,8 +950,7 @@ warnAndRethrowWithPosition :: (MonadError MultipleErrors m, MonadWriter Multiple
946950warnAndRethrowWithPosition pos = rethrowWithPosition pos . warnWithPosition pos
947951
948952withPosition :: SourceSpan -> ErrorMessage -> ErrorMessage
949−withPosition _ (PositionedError pos err) = withPosition pos err
950−withPosition pos err = PositionedError pos err
953+withPosition pos (ErrorMessage hints se) = ErrorMessage (PositionedError pos : hints) se
951954
952955-- |
953956-- Collect errors in in parallel
src/Language/PureScript/Linter.hs+4−4
@@ -40,7 +40,7 @@ import Language.PureScript.Linter.Exhaustive as L
4040-- |
4141-- | Right now, this pass only performs a shadowing check.
4242lint :: forall m. (Applicative m, MonadWriter MultipleErrors m) => Module -> m ()
43−lint (Module _ _ mn ds _) = censor (onErrorMessages (ErrorInModule mn)) $ mapM_ lintDeclaration ds
43+lint (Module _ _ mn ds _) = censor (addHint (ErrorInModule mn)) $ mapM_ lintDeclaration ds
4444 where
4545 moduleNames :: S.Set Ident
4646 moduleNames = S.fromList (nub (mapMaybe getDeclIdent ds))
@@ -58,9 +58,9 @@ lint (Module _ _ mn ds _) = censor (onErrorMessages (ErrorInModule mn)) $ mapM_
5858 let (f, _, _, _, _) = everythingWithContextOnValues moduleNames mempty mappend stepD stepE stepB def def
5959
6060 f' :: Declaration -> MultipleErrors
61− f' (PositionedDeclaration pos _ dec) = onErrorMessages (PositionedError pos) (f' dec)
62− f' dec@(ValueDeclaration name _ _ _) = onErrorMessages (ErrorInValueDeclaration name) (f dec <> checkTypeVarsInDecl dec)
63− f' (TypeDeclaration name ty) = onErrorMessages (ErrorInTypeDeclaration name) (checkTypeVars ty)
61+ f' (PositionedDeclaration pos _ dec) = addHint (PositionedError pos) (f' dec)
62+ f' dec@(ValueDeclaration name _ _ _) = addHint (ErrorInValueDeclaration name) (f dec <> checkTypeVarsInDecl dec)
63+ f' (TypeDeclaration name ty) = addHint (ErrorInTypeDeclaration name) (checkTypeVars ty)
6464 f' dec = f dec <> checkTypeVarsInDecl dec
6565
6666 in tell (f' d)
src/Language/PureScript/Linter/Exhaustive.hs+74−47
@@ -29,6 +29,9 @@ import qualified Data.Map as M
2929import Data.Maybe (fromMaybe)
3030import Data.List (foldl', sortBy, nub)
3131import Data.Function (on)
32+#if __GLASGOW_HASKELL__ < 710
33+import Data.Traversable (sequenceA)
34+#endif
3235
3336import Control.Monad (unless)
3437import Control.Applicative
@@ -43,7 +46,13 @@ import Language.PureScript.Kinds
4346import Language.PureScript.Types as P
4447import Language.PureScript.Errors
4548
46−import Language.PureScript.AST.Traversals (everywhereOnValuesTopDownM)
49+-- | There are two modes of failure for the redudancy check:
50+--
51+-- 1. Exhaustivity was incomeplete due to too many cases, so we couldn't determine redundancy.
52+-- 2. We didn't attempt to determine redundancy for a binder, e.g. an integer binder.
53+--
54+-- We want to warn the user in the first case.
55+data RedudancyError = Incomplete | Unknown
4756
4857-- |
4958-- Qualifies a propername from a given qualified propername and a default module name
@@ -59,20 +68,20 @@ qualifyName n defmn qn = Qualified (Just mn) n
5968-- where: - ProperName is the name of the constructor (for example, "Nothing" in Maybe)
6069-- - [Type] is the list of arguments, if it has (for example, "Just" has [TypeVar "a"])
6170--
62−getConstructors :: Environment -> ModuleName -> (Qualified ProperName) -> [(ProperName, [Type])]
71+getConstructors :: Environment -> ModuleName -> Qualified ProperName -> [(ProperName, [Type])]
6372getConstructors env defmn n = extractConstructors lnte
6473 where
6574 qpn :: Qualified ProperName
6675 qpn = getConsDataName n
6776
68− getConsDataName :: (Qualified ProperName) -> (Qualified ProperName)
77+ getConsDataName :: Qualified ProperName -> Qualified ProperName
6978 getConsDataName con = qualifyName nm defmn con
7079 where
7180 nm = case getConsInfo con of
7281 Nothing -> error $ "Constructor " ++ showQualified runProperName con ++ " not in the scope of the current environment in getConsDataName."
7382 Just (_, pm, _, _) -> pm
7483
75− getConsInfo :: (Qualified ProperName) -> Maybe (DataDeclType, ProperName, Type, [Ident])
84+ getConsInfo :: Qualified ProperName -> Maybe (DataDeclType, ProperName, Type, [Ident])
7685 getConsInfo con = M.lookup con dce
7786 where
7887 dce :: M.Map (Qualified ProperName) (DataDeclType, ProperName, Type, [Ident])
@@ -103,27 +112,27 @@ genericMerge _ [] [] = []
103112genericMerge f bs [] = map (\(s, b) -> f s (Just b) Nothing) bs
104113genericMerge f [] bs = map (\(s, b) -> f s Nothing (Just b)) bs
105114genericMerge f bsl@((s, b):bs) bsr@((s', b'):bs')
106− | s < s' = (f s (Just b) Nothing) : genericMerge f bs bsr
107− | s > s' = (f s' Nothing (Just b')) : genericMerge f bsl bs'
108− | otherwise = (f s (Just b) (Just b')) : genericMerge f bs bs'
115+ | s < s' = f s (Just b) Nothing : genericMerge f bs bsr
116+ | s > s' = f s' Nothing (Just b') : genericMerge f bsl bs'
117+ | otherwise = f s (Just b) (Just b') : genericMerge f bs bs'
109118
110119-- |
111120-- Find the uncovered set between two binders:
112121-- the first binder is the case we are trying to cover, the second one is the matching binder
113122--
114−missingCasesSingle :: Environment -> ModuleName -> Binder -> Binder -> ([Binder], Maybe Bool)
115−missingCasesSingle _ _ _ NullBinder = ([], Just True)
116−missingCasesSingle _ _ _ (VarBinder _) = ([], Just True)
123+missingCasesSingle :: Environment -> ModuleName -> Binder -> Binder -> ([Binder], Either RedudancyError Bool)
124+missingCasesSingle _ _ _ NullBinder = ([], return True)
125+missingCasesSingle _ _ _ (VarBinder _) = ([], return True)
117126missingCasesSingle env mn (VarBinder _) b = missingCasesSingle env mn NullBinder b
118127missingCasesSingle env mn br (NamedBinder _ bl) = missingCasesSingle env mn br bl
119128missingCasesSingle env mn NullBinder cb@(ConstructorBinder con _) =
120− (concatMap (\cp -> fst $ missingCasesSingle env mn cp cb) allPatterns, Just True)
129+ (concatMap (\cp -> fst $ missingCasesSingle env mn cp cb) allPatterns, return True)
121130 where
122131 allPatterns = map (\(p, t) -> ConstructorBinder (qualifyName p mn con) (initialize $ length t))
123132 $ getConstructors env mn con
124133missingCasesSingle env mn cb@(ConstructorBinder con bs) (ConstructorBinder con' bs')
125134 | con == con' = let (bs'', pr) = missingCasesMultiple env mn bs bs' in (map (ConstructorBinder con) bs'', pr)
126− | otherwise = ([cb], Just False)
135+ | otherwise = ([cb], return False)
127136missingCasesSingle env mn NullBinder (ObjectBinder bs) =
128137 (map (ObjectBinder . zip (map fst bs)) allMisses, pr)
129138 where
@@ -146,12 +155,12 @@ missingCasesSingle env mn (ObjectBinder bs) (ObjectBinder bs') =
146155 compBS e s b b' = (s, compB e b b')
147156
148157 (sortedNames, binders) = unzip $ genericMerge (compBS NullBinder) sbs sbs'
149−missingCasesSingle _ _ NullBinder (BooleanBinder b) = ([BooleanBinder $ not b], Just True)
158+missingCasesSingle _ _ NullBinder (BooleanBinder b) = ([BooleanBinder $ not b], return True)
150159missingCasesSingle _ _ (BooleanBinder bl) (BooleanBinder br)
151− | bl == br = ([], Just True)
152− | otherwise = ([BooleanBinder bl], Just False)
160+ | bl == br = ([], return True)
161+ | otherwise = ([BooleanBinder bl], return False)
153162missingCasesSingle env mn b (PositionedBinder _ _ cb) = missingCasesSingle env mn b cb
154−missingCasesSingle _ _ b _ = ([b], Nothing)
163+missingCasesSingle _ _ b _ = ([b], Left Unknown)
155164
156165-- |
157166-- Returns the uncovered set of binders
@@ -179,7 +188,7 @@ missingCasesSingle _ _ b _ = ([b], Nothing)
179188-- redundant or not, but uncovered at least. If we use `y` instead, we'll need to have a redundancy checker
180189-- (which ought to be available soon), or increase the complexity of the algorithm.
181190--
182−missingCasesMultiple :: Environment -> ModuleName -> [Binder] -> [Binder] -> ([[Binder]], Maybe Bool)
191+missingCasesMultiple :: Environment -> ModuleName -> [Binder] -> [Binder] -> ([[Binder]], Either RedudancyError Bool)
183192missingCasesMultiple env mn = go
184193 where
185194 go [] [] = ([], pure True)
@@ -213,10 +222,10 @@ isExhaustiveGuard (Right _) = True
213222-- |
214223-- Returns the uncovered set of case alternatives
215224--
216−missingCases :: Environment -> ModuleName -> [Binder] -> CaseAlternative -> ([[Binder]], Maybe Bool)
225+missingCases :: Environment -> ModuleName -> [Binder] -> CaseAlternative -> ([[Binder]], Either RedudancyError Bool)
217226missingCases env mn uncovered ca = missingCasesMultiple env mn uncovered (caseAlternativeBinders ca)
218227
219−missingAlternative :: Environment -> ModuleName -> CaseAlternative -> [Binder] -> ([[Binder]], Maybe Bool)
228+missingAlternative :: Environment -> ModuleName -> CaseAlternative -> [Binder] -> ([[Binder]], Either RedudancyError Bool)
220229missingAlternative env mn ca uncovered
221230 | isExhaustiveGuard (caseAlternativeResult ca) = mcases
222231 | otherwise = ([uncovered], snd mcases)
@@ -232,51 +241,69 @@ missingAlternative env mn ca uncovered
232241checkExhaustive :: forall m. (MonadWriter MultipleErrors m) => Environment -> ModuleName -> Int -> [CaseAlternative] -> m ()
233242checkExhaustive env mn numArgs cas = makeResult . first nub $ foldl' step ([initialize numArgs], (pure True, [])) cas
234243 where
235− step :: ([[Binder]], (Maybe Bool, [[Binder]])) -> CaseAlternative -> ([[Binder]], (Maybe Bool, [[Binder]]))
244+ step :: ([[Binder]], (Either RedudancyError Bool, [[Binder]])) -> CaseAlternative -> ([[Binder]], (Either RedudancyError Bool, [[Binder]]))
236245 step (uncovered, (nec, redundant)) ca =
237246 let (missed, pr) = unzip (map (missingAlternative env mn ca) uncovered)
238− cond = or <$> sequenceA pr
239− in (concat missed, (liftA2 (&&) cond nec,
240− if fromMaybe True cond then redundant else caseAlternativeBinders ca : redundant))
241−#if __GLASGOW_HASKELL__ < 710
242− where
243− sequenceA = foldr (liftA2 (:)) (pure [])
244−#endif
247+ (missed', approx) = splitAt 10000 (concat missed)
248+ cond = liftA2 (&&) (or <$> sequenceA pr) nec
249+ in (missed', ( if null approx
250+ then cond
251+ else Left Incomplete
252+ , if either (const True) id cond
253+ then redundant
254+ else caseAlternativeBinders ca : redundant
255+ )
256+ )
245257
246− makeResult :: ([[Binder]], (Maybe Bool, [[Binder]])) -> m ()
247− makeResult (bss, (_, bss')) =
258+ makeResult :: ([[Binder]], (Either RedudancyError Bool, [[Binder]])) -> m ()
259+ makeResult (bss, (rr, bss')) =
248260 do unless (null bss) tellExhaustive
249261 unless (null bss') tellRedundant
262+ case rr of
263+ Left Incomplete -> tellIncomplete
264+ _ -> return ()
250265 where
251266 tellExhaustive = tell . errorMessage . uncurry NotExhaustivePattern . second null . splitAt 5 $ bss
252267 tellRedundant = tell . errorMessage . uncurry OverlappingPattern . second null . splitAt 5 $ bss'
268+ tellIncomplete = tell . errorMessage $ IncompleteExhaustivityCheck
253269
254270-- |
255271-- Exhaustivity checking over a list of declarations
256272--
257273checkExhaustiveDecls :: forall m. (Applicative m, MonadWriter MultipleErrors m) => Environment -> ModuleName -> [Declaration] -> m ()
258−checkExhaustiveDecls env mn ds =
259− let (f, _, _) = everywhereOnValuesTopDownM return checkExpr return
274+checkExhaustiveDecls env mn = mapM_ onDecl
275+ where
276+ onDecl :: Declaration -> m ()
277+ onDecl (BindingGroupDeclaration bs) = mapM_ (onDecl . convert) bs
278+ where
279+ convert :: (Ident, NameKind, Expr) -> Declaration
280+ convert (name, nk, e) = ValueDeclaration name nk [] (Right e)
281+ onDecl (ValueDeclaration name _ _ (Right e)) = censor (addHint (ErrorInValueDeclaration name)) (onExpr e)
282+ onDecl (PositionedDeclaration pos _ dec) = censor (addHint (PositionedError pos)) (onDecl dec)
283+ onDecl _ = return ()
260284
261− f' :: Declaration -> m Declaration
262− f' d@(BindingGroupDeclaration bs) = mapM_ (f' . convert) bs >> return d
263− where
264− convert :: (Ident, NameKind, Expr) -> Declaration
265− convert (name, nk, e) = ValueDeclaration name nk [] (Right e)
266− f' d@(ValueDeclaration name _ _ _) = censor (onErrorMessages (ErrorInValueDeclaration name)) $ f d
267− f' (PositionedDeclaration pos com dec) = PositionedDeclaration pos com <$> censor (onErrorMessages (PositionedError pos)) (f' dec)
268− -- Don't generate two warnings for desugared dictionaries.
269− f' d@TypeInstanceDeclaration{} = return d
270− f' d = f d
285+ onExpr :: Expr -> m ()
286+ onExpr (UnaryMinus e) = onExpr e
287+ onExpr (ArrayLiteral es) = mapM_ onExpr es
288+ onExpr (ObjectLiteral es) = mapM_ (onExpr . snd) es
289+ onExpr (TypeClassDictionaryConstructorApp _ e) = onExpr e
290+ onExpr (Accessor _ e) = onExpr e
291+ onExpr (ObjectUpdate o es) = onExpr o >> mapM_ (onExpr . snd) es
292+ onExpr (Abs _ e) = onExpr e
293+ onExpr (App e1 e2) = onExpr e1 >> onExpr e2
294+ onExpr (IfThenElse e1 e2 e3) = onExpr e1 >> onExpr e2 >> onExpr e3
295+ onExpr (Case es cas) = checkExhaustive env mn (length es) cas >> mapM_ onExpr es >> mapM_ onCaseAlternative cas
296+ onExpr (TypedValue _ e _) = onExpr e
297+ onExpr (Let ds e) = mapM_ onDecl ds >> onExpr e
298+ onExpr (PositionedValue pos _ e) = censor (addHint (PositionedError pos)) (onExpr e)
299+ onExpr _ = return ()
271300
272− in mapM_ f' ds
273− where
274− checkExpr :: Expr -> m Expr
275− checkExpr c@(Case expr cas) = checkExhaustive env mn (length expr) cas >> return c
276− checkExpr other = return other
301+ onCaseAlternative :: CaseAlternative -> m ()
302+ onCaseAlternative (CaseAlternative _ (Left es)) = mapM_ (\(e, g) -> onExpr e >> onExpr g) es
303+ onCaseAlternative (CaseAlternative _ (Right e)) = onExpr e
277304
278305-- |
279306-- Exhaustivity checking over a single module
280307--
281308checkExhaustiveModule :: forall m. (Applicative m, MonadWriter MultipleErrors m) => Environment -> Module -> m ()
282−checkExhaustiveModule env (Module _ _ mn ds _) = censor (onErrorMessages (ErrorInModule mn)) $ checkExhaustiveDecls env mn ds
309+checkExhaustiveModule env (Module _ _ mn ds _) = censor (addHint (ErrorInModule mn)) $ checkExhaustiveDecls env mn ds
src/Language/PureScript/Make.hs+122−62
@@ -19,6 +19,8 @@
1919{-# LANGUAGE RankNTypes #-}
2020{-# LANGUAGE RecordWildCards #-}
2121{-# LANGUAGE ScopedTypeVariables #-}
22+{-# LANGUAGE MultiParamTypeClasses #-}
23+{-# LANGUAGE TypeFamilies #-}
2224{-# LANGUAGE CPP #-}
2325
2426module Language.PureScript.Make
@@ -39,29 +41,31 @@ module Language.PureScript.Make
3941#if __GLASGOW_HASKELL__ < 710
4042import Control.Applicative
4143#endif
42−import Control.Arrow ((&&&))
4344import Control.Monad
4445import Control.Monad.Error.Class (MonadError(..))
4546import Control.Monad.Trans.Except
4647import Control.Monad.Reader
4748import Control.Monad.Writer.Strict
4849import Control.Monad.Supply
50+import Control.Monad.Base (MonadBase(..))
51+import Control.Monad.Trans.Control (MonadBaseControl(..))
4952
50−import Data.Function (on)
51−import Data.Either (partitionEithers)
52−import Data.List (sortBy, groupBy, foldl')
53−import Data.Maybe (fromMaybe)
53+import Control.Concurrent.Lifted as C
54+
55+import Data.List (foldl', sort)
56+import Data.Maybe (fromMaybe, catMaybes)
5457import Data.Time.Clock
5558import Data.String (fromString)
5659import Data.Foldable (for_)
5760#if __GLASGOW_HASKELL__ < 710
5861import Data.Traversable (traverse)
5962#endif
63+import Data.Traversable (for)
6064import Data.Version (showVersion)
6165import Data.Aeson (encode, decode)
6266import qualified Data.ByteString.Lazy as B
63−import qualified Data.Map as M
6467import qualified Data.Set as S
68+import qualified Data.Map as M
6569
6670import System.Directory
6771 (doesFileExist, getModificationTime, createDirectoryIfMissing)
@@ -150,65 +154,113 @@ data RebuildPolicy
150154-- If timestamps have not changed, the externs file can be used to provide the module's types without
151155-- having to typecheck the module again.
152156--
153−make :: forall m. (Functor m, Applicative m, Monad m, MonadReader Options m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
157+make :: forall m. (Functor m, Applicative m, Monad m, MonadBaseControl IO m, MonadReader Options m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
154158 => MakeActions m
155159 -> [Module]
156160 -> m Environment
157161make MakeActions{..} ms = do
158− (sorted, graph) <- sortModules $ map importPrim ms
159− toRebuild <- foldM (\s (Module _ _ moduleName' _ _) -> do
160− inputTimestamp <- getInputTimestamp moduleName'
161− outputTimestamp <- getOutputTimestamp moduleName'
162− return $ case (inputTimestamp, outputTimestamp) of
163− (Right (Just t1), Just t2) | t1 < t2 -> s
164− (Left RebuildNever, Just _) -> s
165− _ -> S.insert moduleName' s) S.empty sorted
166−
167− (externs, toBuild) <- partitionEithers <$> rebuildIfNecessary (reverseDependencies graph) toRebuild sorted
168− for_ toBuild lint
169− (desugared, nextVar) <- runSupplyT 0 $ desugar externs toBuild
170− let env = foldl' (flip applyExternsFileToEnvironment) initEnvironment externs
171− evalSupplyT nextVar $ go env desugared
172− where
162+ checkModuleNamesAreUnique
163+
164+ (sorted, graph) <- sortModules ms
165+
166+ barriers <- zip (map getModuleName sorted) <$> replicateM (length ms) ((,) <$> C.newEmptyMVar <*> C.newEmptyMVar)
167+
168+ for_ sorted $ \m -> fork $ do
169+ let deps = fromMaybe (error "make: module not found in dependency graph.") (lookup (getModuleName m) graph)
170+ buildModule barriers (importPrim m) (deps `inOrderOf` map getModuleName sorted)
171+
172+ -- Wait for all threads to complete, and collect errors.
173+ errors <- catMaybes <$> for barriers (takeMVar . snd . snd)
174+
175+ -- All threads have completed, rethrow any caught errors.
176+ unless (null errors) $ throwError (mconcat errors)
177+
178+ -- Bundle up all the externs and return them as an Environment
179+ externs <- sequence <$> for barriers (takeMVar . fst . snd)
180+ return $ foldl' (flip applyExternsFileToEnvironment) initEnvironment (fromMaybe (error "make: externs were missing but no errors reported.") externs)
173181
174− go :: Environment -> [Module] -> SupplyT m Environment
175− go env [] = return env
176− go env (m@(Module ss coms moduleName' _ exps) : ms') = do
177− lift . progress $ CompilingModule moduleName'
178− (checked@(Module _ _ _ elaborated _), env') <- lift . runCheck' env $ typeCheckModule Nothing m
179− checkExhaustiveModule env' checked
180− regrouped <- createBindingGroups moduleName' . collapseBindingGroups $ elaborated
181− let mod' = Module ss coms moduleName' regrouped exps
182− corefn = CF.moduleToCoreFn env' mod'
183− [renamed] = renameInModules [corefn]
184− exts = encode $ moduleToExternsFile mod' env'
185− codegen renamed env' exts
186− go env' ms'
187−
188− rebuildIfNecessary :: M.Map ModuleName [ModuleName] -> S.Set ModuleName -> [Module] -> m [Either ExternsFile Module]
189− rebuildIfNecessary graph = rebuildIfNecessary'
190− where
191− rebuildIfNecessary' :: S.Set ModuleName -> [Module] -> m [Either ExternsFile Module]
192− rebuildIfNecessary' _ [] = return []
193− rebuildIfNecessary' toRebuild (m@(Module _ _ moduleName' _ _) : ms')
194− | moduleName' `S.member` toRebuild = rebuild toRebuild m moduleName' ms'
195− rebuildIfNecessary' toRebuild (m@(Module _ _ moduleName' _ _) : ms') = do
196− (_, externsJson) <- readExterns moduleName'
197− case decode externsJson of
198− Just externs
199− | efVersion externs == showVersion Paths.version -> (Left externs :) <$> rebuildIfNecessary' toRebuild ms'
200− _ -> rebuild toRebuild m moduleName' ms'
201−
202− rebuild :: S.Set ModuleName -> Module -> ModuleName -> [Module] -> m [Either ExternsFile Module]
203− rebuild toRebuild m moduleName ms' = do
204− let deps = fromMaybe [] $ moduleName `M.lookup` graph
205− (Right m :) <$> rebuildIfNecessary' (toRebuild `S.union` S.fromList deps) ms'
206−
207−reverseDependencies :: ModuleGraph -> M.Map ModuleName [ModuleName]
208−reverseDependencies g = combine [ (dep, mn) | (mn, deps) <- g, dep <- deps ]
209182 where
210− combine :: (Ord a) => [(a, b)] -> M.Map a [b]
211− combine = M.fromList . map ((fst . head) &&& map snd) . groupBy ((==) `on` fst) . sortBy (compare `on` fst)
183+ checkModuleNamesAreUnique :: m ()
184+ checkModuleNamesAreUnique =
185+ case findDuplicate (map getModuleName ms) of
186+ Nothing -> return ()
187+ Just mn -> throwError . errorMessage $ DuplicateModuleName mn
188+
189+ -- Verify that a list of values has unique keys
190+ findDuplicate :: (Ord a) => [a] -> Maybe a
191+ findDuplicate = go . sort
192+ where
193+ go (x : y : xs)
194+ | x == y = Just x
195+ | otherwise = go (y : xs)
196+ go _ = Nothing
197+
198+ -- Sort a list so its elements appear in the same order as in another list.
199+ inOrderOf :: (Ord a) => [a] -> [a] -> [a]
200+ inOrderOf xs ys = let s = S.fromList xs in filter (`S.member` s) ys
201+
202+ buildModule :: [(ModuleName, (C.MVar (Maybe ExternsFile), C.MVar (Maybe MultipleErrors)))] -> Module -> [ModuleName] -> m ()
203+ buildModule barriers m@(Module _ _ moduleName _ _) deps = flip catchError (markComplete Nothing . Just) $ do
204+ -- We need to wait for dependencies to be built, before checking if the current
205+ -- module should be rebuilt, so the first thing to do is to wait on the
206+ -- MVars for the module's dependencies.
207+ mexterns <- sequence <$> mapM (readMVar . fst . fromMaybe (error "make: no barrier") . flip lookup barriers) deps
208+
209+ outputTimestamp <- getOutputTimestamp moduleName
210+ dependencyTimestamp <- maximumMaybe <$> mapM (fmap shouldExist . getOutputTimestamp) deps
211+ inputTimestamp <- getInputTimestamp moduleName
212+
213+ let shouldRebuild = case (inputTimestamp, dependencyTimestamp, outputTimestamp) of
214+ (Right (Just t1), Just t3, Just t2) -> t1 > t2 || t3 > t2
215+ (Right (Just t1), Nothing, Just t2) -> t1 > t2
216+ (Left RebuildNever, _, Just _) -> False
217+ _ -> True
218+
219+ let rebuild =
220+ case mexterns of
221+ Just externs -> do
222+ progress $ CompilingModule moduleName
223+ let env = foldl' (flip applyExternsFileToEnvironment) initEnvironment externs
224+ lint m
225+ ([desugared], nextVar) <- runSupplyT 0 $ desugar externs [m]
226+ (checked@(Module ss coms _ elaborated exps), env') <- runCheck' env $ typeCheckModule desugared
227+ checkExhaustiveModule env' checked
228+ regrouped <- createBindingGroups moduleName . collapseBindingGroups $ elaborated
229+ let mod' = Module ss coms moduleName regrouped exps
230+ corefn = CF.moduleToCoreFn env' mod'
231+ [renamed] = renameInModules [corefn]
232+ exts = moduleToExternsFile mod' env'
233+ evalSupplyT nextVar $ codegen renamed env' $ encode exts
234+ markComplete (Just exts) Nothing
235+ Nothing -> markComplete Nothing Nothing
236+
237+ if shouldRebuild
238+ then rebuild
239+ else do
240+ mexts <- decodeExterns . snd <$> readExterns moduleName
241+ case mexts of
242+ Just exts -> markComplete (Just exts) Nothing
243+ Nothing -> rebuild
244+ where
245+ markComplete :: Maybe ExternsFile -> Maybe MultipleErrors -> m ()
246+ markComplete externs errors = do
247+ putMVar (fst $ fromMaybe (error "make: no barrier") $ lookup moduleName barriers) externs
248+ putMVar (snd $ fromMaybe (error "make: no barrier") $ lookup moduleName barriers) errors
249+
250+ maximumMaybe :: (Ord a) => [a] -> Maybe a
251+ maximumMaybe [] = Nothing
252+ maximumMaybe xs = Just $ maximum xs
253+
254+ -- Make sure a dependency exists
255+ shouldExist :: Maybe UTCTime -> UTCTime
256+ shouldExist (Just t) = t
257+ shouldExist _ = error "make: dependency should already have been built."
258+
259+ decodeExterns :: B.ByteString -> Maybe ExternsFile
260+ decodeExterns bs = do
261+ externs <- decode bs
262+ guard $ efVersion externs == showVersion Paths.version
263+ return externs
212264
213265-- |
214266-- Add an import declaration for a module if it does not already explicitly import it.
@@ -231,6 +283,14 @@ importPrim = addDefaultImport (ModuleName [ProperName C.prim])
231283newtype Make a = Make { unMake :: ReaderT Options (WriterT MultipleErrors (ExceptT MultipleErrors IO)) a }
232284 deriving (Functor, Applicative, Monad, MonadIO, MonadError MultipleErrors, MonadWriter MultipleErrors, MonadReader Options)
233285
286+instance MonadBase IO Make where
287+ liftBase = liftIO
288+
289+instance MonadBaseControl IO Make where
290+ type StM Make a = Either MultipleErrors (a, MultipleErrors)
291+ liftBaseWith f = Make $ liftBaseWith $ \q -> f (q . unMake)
292+ restoreM = Make . restoreM
293+
234294-- |
235295-- Execute a 'Make' monad, returning either errors, or the result of the compile plus any warnings.
236296--
@@ -305,15 +365,15 @@ buildMakeActions outputDir filePathMap foreigns usePrefix =
305365 requiresForeign = not . null . CF.moduleForeign
306366
307367 getTimestamp :: FilePath -> Make (Maybe UTCTime)
308− getTimestamp path = makeIO (const (SimpleErrorWrapper $ CannotGetFileInfo path)) $ do
368+ getTimestamp path = makeIO (const (ErrorMessage [] $ CannotGetFileInfo path)) $ do
309369 exists <- doesFileExist path
310370 traverse (const $ getModificationTime path) $ guard exists
311371
312372 readTextFile :: FilePath -> Make B.ByteString
313− readTextFile path = makeIO (const (SimpleErrorWrapper $ CannotReadFile path)) $ B.readFile path
373+ readTextFile path = makeIO (const (ErrorMessage [] $ CannotReadFile path)) $ B.readFile path
314374
315375 writeTextFile :: FilePath -> B.ByteString -> Make ()
316− writeTextFile path text = makeIO (const (SimpleErrorWrapper $ CannotWriteFile path)) $ do
376+ writeTextFile path text = makeIO (const (ErrorMessage [] $ CannotWriteFile path)) $ do
317377 mkdirp path
318378 B.writeFile path text
319379 where
src/Language/PureScript/ModuleDependencies.hs+9−7
@@ -23,20 +23,17 @@ import Control.Monad.Error.Class (MonadError(..))
2323
2424import Data.Graph
2525import Data.List (nub)
26−import Data.Maybe (mapMaybe)
26+import Data.Maybe (fromMaybe, mapMaybe)
2727
2828import Language.PureScript.AST
2929import Language.PureScript.Names
3030import Language.PureScript.Types
3131import Language.PureScript.Errors
3232
33−-- |
34−-- A list of modules with their dependencies
35−--
33+-- | A list of modules with their transitive dependencies
3634type ModuleGraph = [(ModuleName, [ModuleName])]
3735
38−-- |
39−-- Sort a collection of modules based on module dependencies.
36+-- | Sort a collection of modules based on module dependencies.
4037--
4138-- Reports an error if the module graph contains a cycle.
4239--
@@ -44,7 +41,12 @@ sortModules :: (MonadError MultipleErrors m) => [Module] -> m ([Module], ModuleG
4441sortModules ms = do
4542 let verts = map (\m@(Module _ _ _ ds _) -> (m, getModuleName m, nub (concatMap usedModules ds))) ms
4643 ms' <- mapM toModule $ stronglyConnComp verts
47− let moduleGraph = map (\(_, mn, deps) -> (mn, deps)) verts
44+ let (graph, fromVertex, toVertex) = graphFromEdges verts
45+ moduleGraph = do (_, mn, _) <- verts
46+ let v = fromMaybe (error "sortModules: vertex not found") (toVertex mn)
47+ deps = reachable graph v
48+ toKey i = case fromVertex i of (_, key, _) -> key
49+ return (mn, filter (/= mn) (map toKey deps))
4850 return (ms', moduleGraph)
4951
5052-- |
src/Language/PureScript/Names.hs+4
@@ -104,6 +104,10 @@ qualify _ (Qualified (Just m) a) = (m, a)
104104mkQualified :: a -> ModuleName -> Qualified a
105105mkQualified name mn = Qualified (Just mn) name
106106
107+-- | Remove the module name from a qualified name
108+disqualify :: Qualified a -> a
109+disqualify (Qualified _ a) = a
110+
107111-- |
108112-- Checks whether a qualified value is actually qualified with a module reference
109113--
src/Language/PureScript/Parser/Declarations.hs+26−28
@@ -151,33 +151,34 @@ parseImportDeclaration' = do
151151 where
152152 stdImport = do
153153 moduleName' <- moduleName
154− stdImportHiding moduleName' <|> stdImportQualifying moduleName'
154+ suffixHiding moduleName' <|> suffixQualifyingList moduleName'
155155 where
156− stdImportHiding mn = do
156+ suffixHiding mn = do
157157 reserved "hiding"
158− declType <- importDeclarationType Hiding
159− return (mn, declType, Nothing)
160− stdImportQualifying mn = do
161− declType <- importDeclarationType Explicit
158+ declType <- qualifyingList Hiding
162159 return (mn, declType, Nothing)
160+ suffixQualifyingList mn = do
161+ declType <- qualifyingList Explicit
162+ qName <- P.optionMaybe qualifiedName
163+ return (mn, declType, qName)
164+ qualifiedName = reserved "as" *> moduleName
163165 qualImport = do
164166 reserved "qualified"
165167 indented
166168 moduleName' <- moduleName
167− declType <- importDeclarationType Explicit
168− reserved "as"
169− asQ <- moduleName
170− return (moduleName', declType, Just asQ)
171− importDeclarationType expectedType = do
169+ declType <- qualifyingList Explicit
170+ qName <- qualifiedName
171+ return (moduleName', declType, Just qName)
172+ qualifyingList expectedType = do
172173 idents <- P.optionMaybe $ indented *> parens (commaSep parseDeclarationRef)
173174 return $ fromMaybe Implicit (expectedType <$> idents)
174175
175176
176177parseDeclarationRef :: TokenParser DeclarationRef
177178parseDeclarationRef =
178− parseModuleRef <|> (
179− withSourceSpan PositionedDeclarationRef $
180− ValueRef <$> parseIdent
179+ parseModuleRef <|>
180+ withSourceSpan PositionedDeclarationRef
181+ (ValueRef <$> parseIdent
181182 <|> do name <- properName
182183 dctors <- P.optionMaybe $ parens (symbol' ".." *> pure Nothing <|> Just <$> commaSep properName)
183184 return $ maybe (TypeClassRef name) (TypeRef name) dctors
@@ -203,8 +204,8 @@ parseTypeClassDeclaration = do
203204 mark (P.many (same *> positioned parseTypeDeclaration))
204205 return $ TypeClassDeclaration className idents implies members
205206
206−parseTypeInstanceDeclaration :: TokenParser Declaration
207−parseTypeInstanceDeclaration = do
207+parseInstanceDeclaration :: TokenParser (TypeInstanceBody -> Declaration)
208+parseInstanceDeclaration = do
208209 reserved "instance"
209210 name <- parseIdent <* indented <* doubleColon
210211 deps <- P.optionMaybe $ do
@@ -214,24 +215,21 @@ parseTypeInstanceDeclaration = do
214215 return deps
215216 className <- indented *> parseQualified properName
216217 ty <- P.many (indented *> noWildcards parseTypeAtom)
218+ return $ TypeInstanceDeclaration name (fromMaybe [] deps) className ty
219+
220+parseTypeInstanceDeclaration :: TokenParser Declaration
221+parseTypeInstanceDeclaration = do
222+ instanceDecl <- parseInstanceDeclaration
217223 members <- P.option [] . P.try $ do
218224 indented *> reserved "where"
219225 mark (P.many (same *> positioned parseValueDeclaration))
220− return $ TypeInstanceDeclaration name (fromMaybe [] deps) className ty (ExplicitInstance members)
226+ return $ instanceDecl (ExplicitInstance members)
221227
222228parseDerivingInstanceDeclaration :: TokenParser Declaration
223229parseDerivingInstanceDeclaration = do
224230 reserved "derive"
225− reserved "instance"
226− name <- parseIdent <* indented <* doubleColon
227− deps <- P.optionMaybe $ do
228− deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many (noWildcards parseTypeAtom)))
229− indented
230− rfatArrow
231− return deps
232− className <- indented *> parseQualified properName
233− ty <- P.many (indented *> noWildcards parseTypeAtom)
234− return $ TypeInstanceDeclaration name (fromMaybe [] deps) className ty DerivedInstance
231+ instanceDecl <- parseInstanceDeclaration
232+ return $ instanceDecl DerivedInstance
235233
236234positioned :: TokenParser Declaration -> TokenParser Declaration
237235positioned = withSourceSpan PositionedDeclaration
@@ -295,7 +293,7 @@ parseModulesFromFiles toFilePath input = do
295293 collect vss = [ (k, v) | (k, vs) <- vss, v <- vs ]
296294
297295toPositionedError :: P.ParseError -> ErrorMessage
298−toPositionedError perr = PositionedError (SourceSpan name start end) (SimpleErrorWrapper (ErrorParsingModule perr))
296+toPositionedError perr = ErrorMessage [ PositionedError (SourceSpan name start end) ] (ErrorParsingModule perr)
299297 where
300298 name = (P.sourceName . P.errorPos) perr
301299 start = (toSourcePos . P.errorPos) perr
src/Language/PureScript/Parser/Kinds.hs+1−1
@@ -46,4 +46,4 @@ parseKind :: TokenParser Kind
4646parseKind = P.buildExpressionParser operators parseTypeAtom P.<?> "kind"
4747 where
4848 operators = [ [ P.Prefix (symbol' "#" >> return Row) ]
49− , [ P.Infix ((P.try rarrow) >> return FunKind) P.AssocRight ] ]
49+ , [ P.Infix (P.try rarrow >> return FunKind) P.AssocRight ] ]
src/Language/PureScript/Parser/Lexer.hs+1−1
@@ -479,7 +479,7 @@ identifier = token go P.<?> "identifier"
479479 go _ = Nothing
480480
481481validModuleName :: String -> Bool
482−validModuleName s = not ('_' `elem` s)
482+validModuleName s = '_' `notElem` s
483483
484484-- |
485485-- A list of purescript reserved identifiers
src/Language/PureScript/Pretty/Common.hs+11
@@ -17,8 +17,11 @@ module Language.PureScript.Pretty.Common where
1717
1818import Control.Monad.State
1919import Data.List (intercalate)
20+
2021import Language.PureScript.Parser.Lexer (reservedPsNames, opChars)
2122
23+import Text.PrettyPrint.Boxes
24+
2225-- |
2326-- Wrap a string in parentheses
2427--
@@ -67,3 +70,11 @@ prettyPrintObjectKey :: String -> String
6770prettyPrintObjectKey s | s `elem` reservedPsNames = show s
6871 | any (`elem` opChars) s = show s
6972 | otherwise = s
73+
74+-- | Place a box before another, vertically when the first box takes up multiple lines.
75+before :: Box -> Box -> Box
76+before b1 b2 | rows b1 > 1 = b1 // b2
77+ | otherwise = b1 <> b2
78+
79+beforeWithSpace :: Box -> Box -> Box
80+beforeWithSpace b1 = before (b1 <> text " ")
src/Language/PureScript/Pretty/JS.hs+13−13
@@ -45,13 +45,13 @@ literals = mkPattern' match
4545 match (JSStringLiteral s) = return $ string s
4646 match (JSBooleanLiteral True) = return "true"
4747 match (JSBooleanLiteral False) = return "false"
48− match (JSArrayLiteral xs) = fmap concat $ sequence
48+ match (JSArrayLiteral xs) = concat <$> sequence
4949 [ return "[ "
50− , fmap (intercalate ", ") $ forM xs prettyPrintJS'
50+ , intercalate ", " <$> forM xs prettyPrintJS'
5151 , return " ]"
5252 ]
5353 match (JSObjectLiteral []) = return "{}"
54− match (JSObjectLiteral ps) = fmap concat $ sequence
54+ match (JSObjectLiteral ps) = concat <$> sequence
5555 [ return "{\n"
5656 , withIndent $ do
5757 jss <- forM ps $ \(key, value) -> fmap ((objectPropertyToString key ++ ": ") ++) . prettyPrintJS' $ value
@@ -65,7 +65,7 @@ literals = mkPattern' match
6565 objectPropertyToString :: String -> String
6666 objectPropertyToString s | identNeedsEscaping s = show s
6767 | otherwise = s
68− match (JSBlock sts) = fmap concat $ sequence
68+ match (JSBlock sts) = concat <$> sequence
6969 [ return "{\n"
7070 , withIndent $ prettyStatements sts
7171 , return "\n"
@@ -73,23 +73,23 @@ literals = mkPattern' match
7373 , return "}"
7474 ]
7575 match (JSVar ident) = return ident
76− match (JSVariableIntroduction ident value) = fmap concat $ sequence
76+ match (JSVariableIntroduction ident value) = concat <$> sequence
7777 [ return "var "
7878 , return ident
7979 , maybe (return "") (fmap (" = " ++) . prettyPrintJS') value
8080 ]
81− match (JSAssignment target value) = fmap concat $ sequence
81+ match (JSAssignment target value) = concat <$> sequence
8282 [ prettyPrintJS' target
8383 , return " = "
8484 , prettyPrintJS' value
8585 ]
86− match (JSWhile cond sts) = fmap concat $ sequence
86+ match (JSWhile cond sts) = concat <$> sequence
8787 [ return "while ("
8888 , prettyPrintJS' cond
8989 , return ") "
9090 , prettyPrintJS' sts
9191 ]
92− match (JSFor ident start end sts) = fmap concat $ sequence
92+ match (JSFor ident start end sts) = concat <$> sequence
9393 [ return $ "for (var " ++ ident ++ " = "
9494 , prettyPrintJS' start
9595 , return $ "; " ++ ident ++ " < "
@@ -97,30 +97,30 @@ literals = mkPattern' match
9797 , return $ "; " ++ ident ++ "++) "
9898 , prettyPrintJS' sts
9999 ]
100− match (JSForIn ident obj sts) = fmap concat $ sequence
100+ match (JSForIn ident obj sts) = concat <$> sequence
101101 [ return $ "for (var " ++ ident ++ " in "
102102 , prettyPrintJS' obj
103103 , return ") "
104104 , prettyPrintJS' sts
105105 ]
106− match (JSIfElse cond thens elses) = fmap concat $ sequence
106+ match (JSIfElse cond thens elses) = concat <$> sequence
107107 [ return "if ("
108108 , prettyPrintJS' cond
109109 , return ") "
110110 , prettyPrintJS' thens
111111 , maybe (return "") (fmap (" else " ++) . prettyPrintJS') elses
112112 ]
113− match (JSReturn value) = fmap concat $ sequence
113+ match (JSReturn value) = concat <$> sequence
114114 [ return "return "
115115 , prettyPrintJS' value
116116 ]
117− match (JSThrow value) = fmap concat $ sequence
117+ match (JSThrow value) = concat <$> sequence
118118 [ return "throw "
119119 , prettyPrintJS' value
120120 ]
121121 match (JSBreak lbl) = return $ "break " ++ lbl
122122 match (JSContinue lbl) = return $ "continue " ++ lbl
123− match (JSLabel lbl js) = fmap concat $ sequence
123+ match (JSLabel lbl js) = concat <$> sequence
124124 [ return $ lbl ++ ": "
125125 , prettyPrintJS' js
126126 ]
src/Language/PureScript/Pretty/Kinds.hs+19−15
@@ -14,7 +14,8 @@
1414-----------------------------------------------------------------------------
1515
1616module Language.PureScript.Pretty.Kinds (
17− prettyPrintKind
17+ prettyPrintKind,
18+ kindAsBox
1819) where
1920
2021import Data.Maybe (fromMaybe)
@@ -23,14 +24,15 @@ import Control.Arrow (ArrowPlus(..))
2324import Control.PatternArrows
2425
2526import Language.PureScript.Kinds
26−import Language.PureScript.Pretty.Common
2727
28−typeLiterals :: Pattern () Kind String
28+import Text.PrettyPrint.Boxes (Box(), text, render, (<>))
29+
30+typeLiterals :: Pattern () Kind Box
2931typeLiterals = mkPattern match
3032 where
31− match Star = Just "*"
32− match Bang = Just "!"
33− match (KUnknown u) = Just $ 'u' : show u
33+ match Star = Just $ text "*"
34+ match Bang = Just $ text "!"
35+ match (KUnknown u) = Just $ text $ 'u' : show u
3436 match _ = Nothing
3537
3638matchRow :: Pattern () Kind ((), Kind)
@@ -45,15 +47,17 @@ funKind = mkPattern match
4547 match (FunKind arg ret) = Just (arg, ret)
4648 match _ = Nothing
4749
48−-- |
49−-- Generate a pretty-printed string representing a Kind
50−--
50+-- | Generate a pretty-printed string representing a Kind
5151prettyPrintKind :: Kind -> String
52−prettyPrintKind = fromMaybe (error "Incomplete pattern") . pattern matchKind ()
52+prettyPrintKind = render . kindAsBox
53+
54+kindAsBox :: Kind -> Box
55+kindAsBox = fromMaybe (error "Incomplete pattern") . pattern matchKind ()
5356 where
54− matchKind :: Pattern () Kind String
55− matchKind = buildPrettyPrinter operators (typeLiterals <+> fmap parens matchKind)
56− operators :: OperatorTable () Kind String
57+ matchKind :: Pattern () Kind Box
58+ matchKind = buildPrettyPrinter operators (typeLiterals <+> fmap ((text "(" <>) . (<> text ")")) matchKind)
59+
60+ operators :: OperatorTable () Kind Box
5761 operators =
58− OperatorTable [ [ Wrap matchRow $ \_ k -> "# " ++ k]
59− , [ AssocR funKind $ \arg ret -> arg ++ " -> " ++ ret ] ]
62+ OperatorTable [ [ Wrap matchRow $ \_ k -> text "# " <> k]
63+ , [ AssocR funKind $ \arg ret -> arg <> text " -> " <> ret ] ]
src/Language/PureScript/Pretty/Types.hs+56−35
@@ -14,13 +14,15 @@
1414-----------------------------------------------------------------------------
1515
1616module Language.PureScript.Pretty.Types (
17+ typeAsBox,
1718 prettyPrintType,
19+ typeAtomAsBox,
1820 prettyPrintTypeAtom,
21+ prettyPrintRowWith,
1922 prettyPrintRow
2023) where
2124
2225import Data.Maybe (fromMaybe)
23−import Data.List (intercalate)
2426
2527import Control.Arrow ((<+>))
2628import Control.PatternArrows
@@ -32,36 +34,54 @@ import Language.PureScript.Pretty.Common
3234import Language.PureScript.Pretty.Kinds
3335import Language.PureScript.Environment
3436
35−typeLiterals :: Pattern () Type String
37+import Text.PrettyPrint.Boxes hiding ((<+>))
38+
39+typeLiterals :: Pattern () Type Box
3640typeLiterals = mkPattern match
3741 where
38− match TypeWildcard = Just "_"
39− match (TypeVar var) = Just var
40− match (PrettyPrintObject row) = Just $ "{ " ++ prettyPrintRow row ++ " }"
41− match (TypeConstructor ctor) = Just $ showQualified runProperName ctor
42− match (TUnknown u) = Just $ '_' : show u
43− match (Skolem name s _) = Just $ name ++ show s
44− match (ConstrainedType deps ty) = Just $ "(" ++ intercalate ", " (map (\(pn, ty') -> showQualified runProperName pn ++ " " ++ unwords (map prettyPrintTypeAtom ty')) deps) ++ ") => " ++ prettyPrintType ty
45− match (SaturatedTypeSynonym name args) = Just $ showQualified runProperName name ++ "<" ++ intercalate "," (map prettyPrintTypeAtom args) ++ ">"
46− match REmpty = Just "()"
47− match row@RCons{} = Just $ '(' : prettyPrintRow row ++ ")"
42+ match TypeWildcard = Just $ text "_"
43+ match (TypeVar var) = Just $ text var
44+ match (PrettyPrintObject row) = Just $ prettyPrintRowWith '{' '}' row
45+ match (TypeConstructor ctor) = Just $ text $ runProperName $ disqualify ctor
46+ match (TUnknown u) = Just $ text $ '_' : show u
47+ match (Skolem name s _) = Just $ text $ name ++ show s
48+ match (ConstrainedType deps ty) = Just $ constraintsAsBox deps `before` (text ") => " <> typeAsBox ty)
49+ match REmpty = Just $ text "()"
50+ match row@RCons{} = Just $ prettyPrintRowWith '(' ')' row
4851 match _ = Nothing
4952
53+constraintsAsBox :: [(Qualified ProperName, [Type])] -> Box
54+constraintsAsBox = vcat left . zipWith (\i (pn, tys) -> text (if i == 0 then "( " else ", ") <> constraintAsBox pn tys) [0 :: Int ..]
55+ where
56+ constraintAsBox pn tys = hsep 1 left (text (runProperName (disqualify pn)) : map typeAtomAsBox tys)
57+
5058-- |
5159-- Generate a pretty-printed string representing a Row
5260--
53−prettyPrintRow :: Type -> String
54−prettyPrintRow = (\(tys, rest) -> intercalate ", " (map (uncurry nameAndTypeToPs) tys) ++ tailToPs rest) . toList []
61+prettyPrintRowWith :: Char -> Char -> Type -> Box
62+prettyPrintRowWith open close = uncurry listToBox . toList []
5563 where
56− nameAndTypeToPs :: String -> Type -> String
57− nameAndTypeToPs name ty = prettyPrintObjectKey name ++ " :: " ++ prettyPrintType ty
58− tailToPs :: Type -> String
59− tailToPs REmpty = ""
60− tailToPs other = " | " ++ prettyPrintType other
64+ nameAndTypeToPs :: Char -> String -> Type -> Box
65+ nameAndTypeToPs start name ty = text (start : ' ' : prettyPrintObjectKey name ++ " :: ") <> typeAsBox ty
66+
67+ tailToPs :: Type -> Box
68+ tailToPs REmpty = nullBox
69+ tailToPs other = text "| " <> typeAsBox other
70+
71+ listToBox :: [(String, Type)] -> Type -> Box
72+ listToBox [] REmpty = text [open, close]
73+ listToBox [] rest = text [ open, ' ' ] <> tailToPs rest <> text [ ' ', close ]
74+ listToBox ts rest = vcat left $
75+ zipWith (\(nm, ty) i -> nameAndTypeToPs (if i == 0 then open else ',') nm ty) ts [0 :: Int ..] ++
76+ [ tailToPs rest, text [close] ]
77+
6178 toList :: [(String, Type)] -> Type -> ([(String, Type)], Type)
6279 toList tys (RCons name ty row) = toList ((name, ty):tys) row
6380 toList tys r = (tys, r)
6481
82+prettyPrintRow :: Type -> String
83+prettyPrintRow = render . prettyPrintRowWith '(' ')'
84+
6585typeApp :: Pattern () Type (Type, Type)
6686typeApp = mkPattern match
6787 where
@@ -92,19 +112,19 @@ insertPlaceholders = everywhereOnTypesTopDown convertForAlls . everywhereOnTypes
92112 go idents other = PrettyPrintForAll idents other
93113 convertForAlls other = other
94114
95−matchTypeAtom :: Pattern () Type String
96−matchTypeAtom = typeLiterals <+> fmap parens matchType
115+matchTypeAtom :: Pattern () Type Box
116+matchTypeAtom = typeLiterals <+> fmap ((`before` text ")") . (text "(" <>)) matchType
97117
98−matchType :: Pattern () Type String
118+matchType :: Pattern () Type Box
99119matchType = buildPrettyPrinter operators matchTypeAtom
100120 where
101− operators :: OperatorTable () Type String
121+ operators :: OperatorTable () Type Box
102122 operators =
103− OperatorTable [ [ AssocL typeApp $ \f x -> f ++ " " ++ x ]
104− , [ AssocR appliedFunction $ \arg ret -> arg ++ " -> " ++ ret
123+ OperatorTable [ [ AssocL typeApp $ \f x -> f `beforeWithSpace` x ]
124+ , [ AssocR appliedFunction $ \arg ret -> (arg <> text " ") `before` (text "-> " <> ret)
105125 ]
106− , [ Wrap forall_ $ \idents ty -> "forall " ++ unwords idents ++ ". " ++ ty ]
107− , [ Wrap kinded $ \k ty -> ty ++ " :: " ++ prettyPrintKind k ]
126+ , [ Wrap forall_ $ \idents ty -> text ("forall " ++ unwords idents ++ ". ") <> ty ]
127+ , [ Wrap kinded $ \k ty -> ty `before` (text " :: " <> kindAsBox k) ]
108128 ]
109129
110130forall_ :: Pattern () Type ([String], Type)
@@ -113,15 +133,16 @@ forall_ = mkPattern match
113133 match (PrettyPrintForAll idents ty) = Just (idents, ty)
114134 match _ = Nothing
115135
116−-- |
117−-- Generate a pretty-printed string representing a Type, as it should appear inside parentheses
118−--
136+typeAtomAsBox :: Type -> Box
137+typeAtomAsBox = fromMaybe (error "Incomplete pattern") . pattern matchTypeAtom () . insertPlaceholders
138+
139+-- | Generate a pretty-printed string representing a Type, as it should appear inside parentheses
119140prettyPrintTypeAtom :: Type -> String
120−prettyPrintTypeAtom = fromMaybe (error "Incomplete pattern") . pattern matchTypeAtom () . insertPlaceholders
141+prettyPrintTypeAtom = render . typeAtomAsBox
121142
143+typeAsBox :: Type -> Box
144+typeAsBox = fromMaybe (error "Incomplete pattern") . pattern matchType () . insertPlaceholders
122145
123−-- |
124−-- Generate a pretty-printed string representing a Type
125−--
146+-- | Generate a pretty-printed string representing a Type
126147prettyPrintType :: Type -> String
127−prettyPrintType = fromMaybe (error "Incomplete pattern") . pattern matchType () . insertPlaceholders
148+prettyPrintType = render . typeAsBox
src/Language/PureScript/Pretty/Values.hs+92−152
@@ -21,173 +21,113 @@ module Language.PureScript.Pretty.Values (
2121 prettyPrintBinderAtom
2222) where
2323
24−import Data.Maybe (fromMaybe)
2524import Data.List (intercalate)
2625
27−import Control.Arrow ((<+>), runKleisli, second)
28−import Control.PatternArrows
29−import Control.Monad.State
30−#if __GLASGOW_HASKELL__ < 710
31−import Control.Applicative
32−#endif
26+import Control.Arrow (second)
3327
3428import Language.PureScript.AST
3529import Language.PureScript.Names
3630import Language.PureScript.Pretty.Common
37−import Language.PureScript.Pretty.Types (prettyPrintType, prettyPrintTypeAtom)
31+import Language.PureScript.Pretty.Types (typeAsBox, typeAtomAsBox)
3832
39−literals :: Pattern PrinterState Expr String
40−literals = mkPattern' match
33+import Text.PrettyPrint.Boxes
34+
35+-- | Render an aligned list of items separated with commas
36+list :: Char -> Char -> (a -> Box) -> [a] -> Box
37+list open close _ [] = text [open, close]
38+list open close f xs = vcat left (zipWith toLine [0 :: Int ..] xs ++ [ text [ close ] ])
4139 where
42− match :: Expr -> StateT PrinterState Maybe String
43− match (NumericLiteral n) = return $ either show show n
44− match (StringLiteral s) = return $ show s
45− match (CharLiteral c) = return $ show c
46− match (BooleanLiteral True) = return "true"
47− match (BooleanLiteral False) = return "false"
48− match (ArrayLiteral xs) = return $ "[" ++ intercalate ", " (map prettyPrintValue xs) ++ "]"
49− match (ObjectLiteral ps) = prettyPrintObject' $ second Just `map` ps
50− match (ObjectConstructor ps) = prettyPrintObject' ps
51− match (ObjectGetter prop) = return $ "(." ++ prop ++ ")"
52− match (TypeClassDictionaryConstructorApp className ps) = concat <$> sequence
53− [ return (showQualified runProperName className ++ "(\n")
54− , match ps
55− , return ")"
56− ]
57− match (Constructor name) = return $ showQualified runProperName name
58− match (Case values binders) = concat <$> sequence
59− [ return "case "
60− , unwords <$> forM values prettyPrintValue'
61− , return " of\n"
62− , withIndent $ prettyPrintMany prettyPrintCaseAlternative binders
63− , currentIndent
64− ]
65− match (Let ds val) = concat <$> sequence
66− [ return "let\n"
67− , withIndent $ prettyPrintMany prettyPrintDeclaration ds
68− , return "\n"
69− , currentIndent
70− , return "in "
71− , prettyPrintValue' val
72− ]
73− match (Var ident) = return $ showQualified showIdent ident
74− match (Do els) = concat <$> sequence
75− [ return "do\n"
76− , withIndent $ prettyPrintMany prettyPrintDoNotationElement els
77− , currentIndent
78− ]
79− match (OperatorSection op (Right val)) = return $ "(" ++ prettyPrintValue op ++ " " ++ prettyPrintValue val ++ ")"
80− match (OperatorSection op (Left val)) = return $ "(" ++ prettyPrintValue val ++ " " ++ prettyPrintValue op ++ ")"
81− match (TypeClassDictionary (name, tys) _) = return $ "<<dict " ++ showQualified runProperName name ++ " " ++ unwords (map prettyPrintTypeAtom tys) ++ ">>"
82− match (SuperClassDictionary name _) = return $ "<<superclass dict " ++ showQualified runProperName name ++ ">>"
83− match (TypedValue _ val _) = prettyPrintValue' val
84− match (PositionedValue _ _ val) = prettyPrintValue' val
85− match _ = mzero
86−
87−prettyPrintDeclaration :: Declaration -> StateT PrinterState Maybe String
88−prettyPrintDeclaration (TypeDeclaration ident ty) = return $ showIdent ident ++ " :: " ++ prettyPrintType ty
89−prettyPrintDeclaration (ValueDeclaration ident _ [] (Right val)) = concat <$> sequence
90− [ return $ showIdent ident ++ " = "
91− , prettyPrintValue' val
92− ]
40+ toLine i a = text [ if i == 0 then open else ',', ' ' ] <> f a
41+
42+prettyPrintObject :: [(String, Maybe Expr)] -> Box
43+prettyPrintObject = list '{' '}' prettyPrintObjectProperty
44+ where
45+ prettyPrintObjectProperty :: (String, Maybe Expr) -> Box
46+ prettyPrintObjectProperty (key, value) = text (prettyPrintObjectKey key ++ ": ") <> maybe (text "_") prettyPrintValue value
47+
48+-- | Pretty-print an expression
49+prettyPrintValue :: Expr -> Box
50+prettyPrintValue (IfThenElse cond th el) =
51+ (text "if " <> prettyPrintValueAtom cond)
52+ // moveRight 2 (vcat left [ text "then " <> prettyPrintValueAtom th
53+ , text "else " <> prettyPrintValueAtom el
54+ ])
55+prettyPrintValue (Accessor prop val) = prettyPrintValueAtom val <> text ("." ++ show prop)
56+prettyPrintValue (ObjectUpdate o ps) = prettyPrintValueAtom o <> text " " <> list '{' '}' (\(key, val) -> text (key ++ " = ") <> prettyPrintValue val) ps
57+prettyPrintValue (ObjectUpdater o ps) = maybe (text "_") prettyPrintValueAtom o <> text " " <> list '{' '}' (\(key, val) -> text (key ++ " = ") <> maybe (text "_") prettyPrintValue val) ps
58+prettyPrintValue (App val arg) = prettyPrintValueAtom val `beforeWithSpace` prettyPrintValueAtom arg
59+prettyPrintValue (Abs (Left arg) val) = text ('\\' : showIdent arg ++ " -> ") // moveRight 2 (prettyPrintValue val)
60+prettyPrintValue (TypeClassDictionaryConstructorApp className ps) =
61+ text (runProperName (disqualify className) ++ " ") <> prettyPrintValueAtom ps
62+prettyPrintValue (Case values binders) =
63+ (text "case " <> foldl1 beforeWithSpace (map prettyPrintValueAtom values) <> text " of") //
64+ moveRight 2 (vcat left (map prettyPrintCaseAlternative binders))
65+prettyPrintValue (Let ds val) =
66+ text "let" //
67+ moveRight 2 (vcat left (map prettyPrintDeclaration ds)) //
68+ (text "in " <> prettyPrintValue val)
69+prettyPrintValue (Do els) =
70+ text "do " <> vcat left (map prettyPrintDoNotationElement els)
71+prettyPrintValue (TypeClassDictionary (name, tys) _) = foldl1 beforeWithSpace $ text ("#dict " ++ runProperName (disqualify name)) : map typeAtomAsBox tys
72+prettyPrintValue (SuperClassDictionary name _) = text $ "#dict " ++ runProperName (disqualify name)
73+prettyPrintValue (TypedValue _ val _) = prettyPrintValue val
74+prettyPrintValue (PositionedValue _ _ val) = prettyPrintValue val
75+prettyPrintValue expr = prettyPrintValueAtom expr
76+
77+-- | Pretty-print an atomic expression, adding parentheses if necessary.
78+prettyPrintValueAtom :: Expr -> Box
79+prettyPrintValueAtom (NumericLiteral n) = text $ either show show n
80+prettyPrintValueAtom (StringLiteral s) = text $ show s
81+prettyPrintValueAtom (CharLiteral c) = text $ show c
82+prettyPrintValueAtom (BooleanLiteral True) = text "true"
83+prettyPrintValueAtom (BooleanLiteral False) = text "false"
84+prettyPrintValueAtom (ArrayLiteral xs) = list '[' ']' prettyPrintValue xs
85+prettyPrintValueAtom (ObjectLiteral ps) = prettyPrintObject $ second Just `map` ps
86+prettyPrintValueAtom (ObjectConstructor ps) = prettyPrintObject ps
87+prettyPrintValueAtom (ObjectGetter prop) = text $ "_." ++ show prop
88+prettyPrintValueAtom (Constructor name) = text $ runProperName (disqualify name)
89+prettyPrintValueAtom (Var ident) = text $ showIdent (disqualify ident)
90+prettyPrintValueAtom (OperatorSection op (Right val)) = ((text "(" <> prettyPrintValue op) `beforeWithSpace` prettyPrintValue val) `before` text ")"
91+prettyPrintValueAtom (OperatorSection op (Left val)) = ((text "(" <> prettyPrintValue val) `beforeWithSpace` prettyPrintValue op) `before` text ")"
92+prettyPrintValueAtom (TypedValue _ val _) = prettyPrintValueAtom val
93+prettyPrintValueAtom (PositionedValue _ _ val) = prettyPrintValueAtom val
94+prettyPrintValueAtom expr = (text "(" <> prettyPrintValue expr) `before` text ")"
95+
96+prettyPrintDeclaration :: Declaration -> Box
97+prettyPrintDeclaration (TypeDeclaration ident ty) =
98+ text (showIdent ident ++ " :: ") <> typeAsBox ty
99+prettyPrintDeclaration (ValueDeclaration ident _ [] (Right val)) =
100+ text (showIdent ident ++ " = ") <> prettyPrintValue val
93101prettyPrintDeclaration (PositionedDeclaration _ _ d) = prettyPrintDeclaration d
94102prettyPrintDeclaration _ = error "Invalid argument to prettyPrintDeclaration"
95103
96−prettyPrintCaseAlternative :: CaseAlternative -> StateT PrinterState Maybe String
104+prettyPrintCaseAlternative :: CaseAlternative -> Box
97105prettyPrintCaseAlternative (CaseAlternative binders result) =
98− concat <$> sequence
99− [ return (unwords (map prettyPrintBinderAtom binders))
100− , prettyPrintResult result
101− ]
106+ text (unwords (map prettyPrintBinderAtom binders)) <> prettyPrintResult result
102107 where
103− prettyPrintResult (Left gs) = concat <$> sequence
104− [ return "\n"
105− , withIndent $ prettyPrintMany prettyPrintGuardedValue gs
106− ]
107− prettyPrintResult (Right v) = (" -> " ++) <$> prettyPrintValue' v
108−
109− prettyPrintGuardedValue (grd, val) =
110− concat <$> sequence
111− [ return "| "
112− , prettyPrintValue' grd
113− , return " -> "
114− , prettyPrintValue' val
115− ]
116−
117−prettyPrintDoNotationElement :: DoNotationElement -> StateT PrinterState Maybe String
108+ prettyPrintResult :: Either [(Guard, Expr)] Expr -> Box
109+ prettyPrintResult (Left gs) =
110+ vcat left (map prettyPrintGuardedValue gs)
111+ prettyPrintResult (Right v) = text " -> " <> prettyPrintValue v
112+
113+ prettyPrintGuardedValue :: (Guard, Expr) -> Box
114+ prettyPrintGuardedValue (grd, val) = foldl1 before
115+ [ text " | "
116+ , prettyPrintValue grd
117+ , text " -> "
118+ , prettyPrintValue val
119+ ]
120+
121+prettyPrintDoNotationElement :: DoNotationElement -> Box
118122prettyPrintDoNotationElement (DoNotationValue val) =
119− prettyPrintValue' val
123+ prettyPrintValue val
120124prettyPrintDoNotationElement (DoNotationBind binder val) =
121− concat <$> sequence
122− [ return (prettyPrintBinder binder)
123− , return " <- "
124− , prettyPrintValue' val
125− ]
125+ text (prettyPrintBinder binder ++ " <- ") <> prettyPrintValue val
126126prettyPrintDoNotationElement (DoNotationLet ds) =
127− concat <$> sequence
128− [ return "let "
129− , withIndent $ prettyPrintMany prettyPrintDeclaration ds
130− ]
127+ text "let" //
128+ moveRight 2 (vcat left (map prettyPrintDeclaration ds))
131129prettyPrintDoNotationElement (PositionedDoNotationElement _ _ el) = prettyPrintDoNotationElement el
132130
133−prettyPrintObject' :: [(String, Maybe Expr)] -> StateT PrinterState Maybe String
134−prettyPrintObject' [] = return "{}"
135−prettyPrintObject' ps = return $ "{ " ++ intercalate ", " (map prettyPrintObjectProperty ps) ++ "}"
136− where
137− prettyPrintObjectProperty :: (String, Maybe Expr) -> String
138− prettyPrintObjectProperty (key, value) = prettyPrintObjectKey key ++ ": " ++ maybe "_" prettyPrintValue value
139−
140−ifThenElse :: Pattern PrinterState Expr ((Expr, Expr), Expr)
141−ifThenElse = mkPattern match
142− where
143− match (IfThenElse cond th el) = Just ((th, el), cond)
144− match _ = Nothing
145−
146−accessor :: Pattern PrinterState Expr (String, Expr)
147−accessor = mkPattern match
148− where
149− match (Accessor prop val) = Just (prop, val)
150− match _ = Nothing
151−
152−objectUpdate :: Pattern PrinterState Expr ([String], Expr)
153−objectUpdate = mkPattern match
154− where
155− match (ObjectUpdate o ps) = Just (flip map ps $ \(key, val) -> key ++ " = " ++ prettyPrintValue val, o)
156− match (ObjectUpdater o ps) = Just (flip map ps $ \(key, val) -> key ++ " = " ++ maybe "_" prettyPrintValue val, fromMaybe (Var (Qualified Nothing $ Ident "_")) o)
157− match _ = Nothing
158−
159−app :: Pattern PrinterState Expr (String, Expr)
160−app = mkPattern match
161− where
162− match (App val arg) = Just (prettyPrintValue arg, val)
163− match _ = Nothing
164−
165−lam :: Pattern PrinterState Expr (String, Expr)
166−lam = mkPattern match
167− where
168− match (Abs (Left arg) val) = Just (showIdent arg, val)
169− match _ = Nothing
170−
171−-- |
172−-- Generate a pretty-printed string representing an expression
173−--
174−prettyPrintValue :: Expr -> String
175−prettyPrintValue = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyPrintValue'
176−
177−prettyPrintValue' :: Expr -> StateT PrinterState Maybe String
178−prettyPrintValue' = runKleisli $ runPattern matchValue
179− where
180− matchValue :: Pattern PrinterState Expr String
181− matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
182− operators :: OperatorTable PrinterState Expr String
183− operators =
184− OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "." ++ prop ]
185− , [ Wrap objectUpdate $ \ps val -> val ++ "{ " ++ intercalate ", " ps ++ " }" ]
186− , [ Wrap app $ \arg val -> val ++ "(" ++ arg ++ ")" ]
187− , [ Split lam $ \arg val -> "\\" ++ arg ++ " -> " ++ prettyPrintValue val ]
188− , [ Wrap ifThenElse $ \(th, el) cond -> "if " ++ cond ++ " then " ++ prettyPrintValue th ++ " else " ++ prettyPrintValue el ]
189− ]
190−
191131prettyPrintBinderAtom :: Binder -> String
192132prettyPrintBinderAtom NullBinder = "_"
193133prettyPrintBinderAtom (StringBinder str) = show str
@@ -196,7 +136,7 @@ prettyPrintBinderAtom (NumberBinder num) = either show show num
196136prettyPrintBinderAtom (BooleanBinder True) = "true"
197137prettyPrintBinderAtom (BooleanBinder False) = "false"
198138prettyPrintBinderAtom (VarBinder ident) = showIdent ident
199−prettyPrintBinderAtom (ConstructorBinder ctor []) = showQualified runProperName ctor
139+prettyPrintBinderAtom (ConstructorBinder ctor []) = runProperName (disqualify ctor)
200140prettyPrintBinderAtom (ObjectBinder bs) =
201141 "{ "
202142 ++ intercalate ", " (map prettyPrintObjectPropertyBinder bs)
@@ -216,8 +156,8 @@ prettyPrintBinderAtom b = parens (prettyPrintBinder b)
216156-- Generate a pretty-printed string representing a Binder
217157--
218158prettyPrintBinder :: Binder -> String
219−prettyPrintBinder (ConstructorBinder ctor []) = showQualified runProperName ctor
220−prettyPrintBinder (ConstructorBinder ctor args) = showQualified runProperName ctor ++ " " ++ unwords (map prettyPrintBinderAtom args)
159+prettyPrintBinder (ConstructorBinder ctor []) = runProperName (disqualify ctor)
160+prettyPrintBinder (ConstructorBinder ctor args) = runProperName (disqualify ctor) ++ " " ++ unwords (map prettyPrintBinderAtom args)
221161prettyPrintBinder (PositionedBinder _ _ binder) = prettyPrintBinder binder
222162prettyPrintBinder (TypedBinder ty binder) = prettyPrintBinder binder ++ " :: " ++ prettyPrintType ty
223163prettyPrintBinder b = prettyPrintBinderAtom b
src/Language/PureScript/Publish.hs+1−1
@@ -153,7 +153,7 @@ getGitWorkingTreeStatus :: PrepareM TreeStatus
153153getGitWorkingTreeStatus = do
154154 out <- readProcess' "git" ["status", "--porcelain"] ""
155155 return $
156− if null . filter (not . null) . lines $ out
156+ if all null . lines $ out
157157 then Clean
158158 else Dirty
159159
src/Language/PureScript/Publish/ErrorsWarnings.hs+14−15
@@ -98,10 +98,10 @@ renderError err =
9898 case err of
9999 UserError e ->
100100 vcat
101− [ para (concat
102− [ "There is a problem with your package, which meant that "
103− , "it could not be published."
104− ])
101+ [ para (
102+ "There is a problem with your package, which meant that " ++
103+ "it could not be published."
104+ )
105105 , para "Details:"
106106 , indented (displayUserError e)
107107 ]
@@ -123,10 +123,10 @@ renderError err =
123123displayUserError :: UserError -> Box
124124displayUserError e = case e of
125125 BowerJSONNotFound ->
126− para (concat
127− [ "The bower.json file was not found. Please create one, or run "
128− , "`pulp init`."
129− ])
126+ para (
127+ "The bower.json file was not found. Please create one, or run " ++
128+ "`pulp init`."
129+ )
130130 BowerExecutableNotFound names ->
131131 para (concat
132132 [ "The Bower executable was not found (tried: ", format names, "). Please"
@@ -217,10 +217,10 @@ displayUserError e = case e of
217217 , indented (P.prettyPrintMultipleErrorsBox False err)
218218 ]
219219 DirtyWorkingTree ->
220− para (concat
221− [ "Your git working tree is dirty. Please commit, discard, or stash "
222− , "your changes first."
223− ])
220+ para (
221+ "Your git working tree is dirty. Please commit, discard, or stash " ++
222+ "your changes first."
223+ )
224224
225225displayRepositoryError :: RepositoryFieldError -> Box
226226displayRepositoryError err = case err of
@@ -356,12 +356,11 @@ warnUndeclaredDependencies pkgNames =
356356 are = pl "are" "is"
357357 dependencies = pl "dependencies" "a dependency"
358358 in vcat $
359− [ para (concat
359+ para (concat
360360 [ "The following Bower ", packages, " ", are, " installed, but not "
361361 , "declared as ", dependencies, " in your bower.json file:"
362362 ])
363− ] ++
364− bulletedList runPackageName (NonEmpty.toList pkgNames)
363+ : bulletedList runPackageName (NonEmpty.toList pkgNames)
365364
366365warnUnacceptableVersions :: NonEmpty (PackageName, String) -> Box
367366warnUnacceptableVersions pkgs =
src/Language/PureScript/Renamer.hs+3−3
@@ -80,12 +80,12 @@ updateScope :: Ident -> Rename Ident
8080updateScope i@(Ident name) | name == C.__unused = return i
8181updateScope name = do
8282 scope <- get
83− name' <- case name `S.member` rsUsedNames scope of
84− True -> do
83+ name' <- if name `S.member` rsUsedNames scope
84+ then do
8585 let newNames = [ Ident (runIdent name ++ "_" ++ show (i :: Int)) | i <- [1..] ]
8686 Just newName = find (`S.notMember` rsUsedNames scope) newNames
8787 return newName
88− False -> return name
88+ else return name
8989 modify $ \s -> s { rsBoundNames = M.insert name name' (rsBoundNames s)
9090 , rsUsedNames = S.insert name' (rsUsedNames s)
9191 }
src/Language/PureScript/Sugar/BindingGroups.hs+1−1
@@ -184,7 +184,7 @@ toBindingGroup moduleName (CyclicSCC ds') =
184184 cycleError :: (MonadError MultipleErrors m) => Declaration -> [Declaration] -> m a
185185 cycleError (PositionedDeclaration p _ d) ds = rethrowWithPosition p $ cycleError d ds
186186 cycleError (ValueDeclaration n _ _ (Right _)) [] = throwError . errorMessage $ CycleInDeclaration n
187− cycleError d ds@(_:_) = rethrow (onErrorMessages (NotYetDefined (map getIdent ds))) $ cycleError d []
187+ cycleError d ds@(_:_) = rethrow (addHint (NotYetDefined (map getIdent ds))) $ cycleError d []
188188 cycleError _ _ = error "Expected ValueDeclaration"
189189
190190toDataBindingGroup :: (MonadError MultipleErrors m) => SCC Declaration -> m Declaration
src/Language/PureScript/Sugar/CaseDeclarations.hs+1−1
@@ -50,7 +50,7 @@ isLeft (Right _) = False
5050--
5151desugarCasesModule :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Module] -> m [Module]
5252desugarCasesModule ms = forM ms $ \(Module ss coms name ds exps) ->
53− rethrow (onErrorMessages (ErrorInModule name)) $
53+ rethrow (addHint (ErrorInModule name)) $
5454 Module ss coms name <$> (desugarCases <=< desugarAbs $ ds) <*> pure exps
5555
5656desugarAbs :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
src/Language/PureScript/Sugar/DoNotation.hs+2−2
@@ -42,13 +42,13 @@ desugarDoModule :: forall m. (Applicative m, MonadSupply m, MonadError MultipleE
4242desugarDoModule (Module ss coms mn ds exts) = Module ss coms mn <$> parU ds desugarDo <*> pure exts
4343
4444desugarDo :: forall m. (Applicative m, MonadSupply m, MonadError MultipleErrors m) => Declaration -> m Declaration
45−desugarDo (PositionedDeclaration pos com d) = PositionedDeclaration pos com <$> (rethrowWithPosition pos $ desugarDo d)
45+desugarDo (PositionedDeclaration pos com d) = PositionedDeclaration pos com <$> rethrowWithPosition pos (desugarDo d)
4646desugarDo d =
4747 let (f, _, _) = everywhereOnValuesM return replace return
4848 in f d
4949 where
5050 bind :: Expr
51− bind = Var (Qualified Nothing (Ident (C.bind)))
51+ bind = Var (Qualified Nothing (Ident C.bind))
5252
5353 replace :: Expr -> m Expr
5454 replace (Do els) = go els
src/Language/PureScript/Sugar/Names.hs+2−3
@@ -98,7 +98,7 @@ desugarImports externs modules = do
9898
9999 renameInModule' :: Env -> Module -> m Module
100100 renameInModule' env m@(Module _ _ mn _ _) =
101− rethrow (onErrorMessages (ErrorInModule mn)) $ do
101+ rethrow (addHint (ErrorInModule mn)) $ do
102102 let (_, imps, exps) = fromMaybe (error "Module is missing in renameInModule'") $ M.lookup mn env
103103 elaborateImports imps <$> renameInModule env imps (elaborateExports exps m)
104104
@@ -132,7 +132,7 @@ elaborateImports imps (Module ss coms mn decls exps) = Module ss coms mn decls'
132132 let (f, _, _, _, _) = everythingOnValues (++) (const []) fqValues (const []) (const []) (const [])
133133 in mkImport `map` nub (f `concatMap` decls) ++ decls
134134 fqValues :: Expr -> [ModuleName]
135− fqValues (Var (Qualified (Just mn') _)) | notElem mn' (importedModules imps) = [mn']
135+ fqValues (Var (Qualified (Just mn') _)) | mn' `notElem` importedModules imps = [mn']
136136 fqValues _ = []
137137 mkImport :: ModuleName -> Declaration
138138 mkImport mn' = ImportDeclaration mn' (Explicit []) Nothing
@@ -211,7 +211,6 @@ renameInModule env imports (Module ss coms mn decls exps) =
211211 where
212212 updateType :: Type -> m Type
213213 updateType (TypeConstructor name) = TypeConstructor <$> updateTypeName name pos
214− updateType (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym <$> updateTypeName name pos <*> pure tys
215214 updateType (ConstrainedType cs t) = ConstrainedType <$> updateConstraints pos cs <*> pure t
216215 updateType t = return t
217216
src/Language/PureScript/Sugar/Names/Exports.hs+4−5
@@ -43,7 +43,7 @@ import Language.PureScript.Sugar.Names.Env
4343--
4444findExportable :: forall m. (Applicative m, MonadError MultipleErrors m) => Module -> m Exports
4545findExportable (Module _ _ mn ds _) =
46− rethrow (onErrorMessages (ErrorInModule mn)) $ foldM updateExports nullExports ds
46+ rethrow (addHint (ErrorInModule mn)) $ foldM updateExports nullExports ds
4747 where
4848 updateExports :: Exports -> Declaration -> m Exports
4949 updateExports exps (TypeClassDeclaration tcn _ _ ds') = do
@@ -67,7 +67,7 @@ findExportable (Module _ _ mn ds _) =
6767--
6868resolveExports :: forall m. (Applicative m, MonadError MultipleErrors m) => Env -> ModuleName -> Imports -> Exports -> [DeclarationRef] -> m Exports
6969resolveExports env mn imps exps refs =
70− rethrow (onErrorMessages (ErrorInModule mn)) $ do
70+ rethrow (addHint (ErrorInModule mn)) $ do
7171 filtered <- filterModule mn exps refs
7272 foldM elaborateModuleExports filtered refs
7373
@@ -205,9 +205,8 @@ filterModule mn exps refs = do
205205 -- the data constructor to check.
206206 checkDcon :: ProperName -> [ProperName] -> ProperName -> m ()
207207 checkDcon tcon exps' name =
208− if name `elem` exps'
209− then return ()
210− else throwError . errorMessage $ UnknownExportDataConstructor tcon name
208+ unless (name `elem` exps') $
209+ throwError . errorMessage $ UnknownExportDataConstructor tcon name
211210
212211 -- Takes a list of all the exportable classes, the accumulated list of
213212 -- filtered exports, and a `DeclarationRef` for an explicit export. When the
src/Language/PureScript/Sugar/Names/Imports.hs+1−1
@@ -64,7 +64,7 @@ findImports = foldM (go Nothing) M.empty
6464--
6565resolveImports :: (Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => Env -> Module -> m Imports
6666resolveImports env (Module _ _ currentModule decls _) =
67− censor (onErrorMessages (ErrorInModule currentModule)) $ do
67+ censor (addHint (ErrorInModule currentModule)) $ do
6868 scope <- M.insert currentModule [(Nothing, Implicit, Nothing)] <$> findImports decls
6969 foldM (resolveModuleImport currentModule env) nullImports (M.toList scope)
7070
src/Language/PureScript/Sugar/Operators.hs+1−1
@@ -102,7 +102,7 @@ ensureNoDuplicates m = go $ sortBy (compare `on` fst) m
102102 go [] = return ()
103103 go [_] = return ()
104104 go ((x@(Qualified (Just mn) name), _) : (y, pos) : _) | x == y =
105− rethrow (onErrorMessages (ErrorInModule mn)) $
105+ rethrow (addHint (ErrorInModule mn)) $
106106 rethrowWithPosition pos $
107107 throwError . errorMessage $ MultipleFixities name
108108 go (_ : rest) = go rest
src/Language/PureScript/Sugar/TypeClasses.hs+1−1
@@ -243,7 +243,7 @@ unit = TypeApp tyObject REmpty
243243
244244typeInstanceDictionaryDeclaration :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => Ident -> ModuleName -> [Constraint] -> Qualified ProperName -> [Type] -> [Declaration] -> Desugar m Declaration
245245typeInstanceDictionaryDeclaration name mn deps className tys decls =
246− rethrow (onErrorMessages (ErrorInInstance className tys)) $ do
246+ rethrow (addHint (ErrorInInstance className tys)) $ do
247247 m <- get
248248
249249 -- Lookup the type arguments and member types for the type class
src/Language/PureScript/Sugar/TypeDeclarations.hs+37−33
@@ -15,18 +15,19 @@
1515-----------------------------------------------------------------------------
1616
1717{-# LANGUAGE FlexibleContexts #-}
18+{-# LANGUAGE ScopedTypeVariables #-}
1819{-# LANGUAGE CPP #-}
1920
2021module Language.PureScript.Sugar.TypeDeclarations (
21− desugarTypeDeclarations,
2222 desugarTypeDeclarationsModule
2323) where
2424
2525#if __GLASGOW_HASKELL__ < 710
2626import Control.Applicative
2727#endif
28−import Control.Monad (forM)
28+import Control.Monad (forM, when)
2929import Control.Monad.Error.Class (MonadError(..))
30+import Control.Monad.Writer.Class (MonadWriter(tell))
3031
3132import Language.PureScript.AST
3233import Language.PureScript.Names
@@ -37,36 +38,39 @@ import Language.PureScript.Traversals
3738-- |
3839-- Replace all top level type declarations in a module with type annotations
3940--
40−desugarTypeDeclarationsModule :: (Functor m, Applicative m, MonadError MultipleErrors m) => [Module] -> m [Module]
41+desugarTypeDeclarationsModule :: forall m. (Functor m, Applicative m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) => [Module] -> m [Module]
4142desugarTypeDeclarationsModule ms = forM ms $ \(Module ss coms name ds exps) ->
42− rethrow (onErrorMessages (ErrorInModule name)) $
43− Module ss coms name <$> desugarTypeDeclarations ds <*> pure exps
44−
45−-- |
46−-- Replace all top level type declarations with type annotations
47−--
48−desugarTypeDeclarations :: (Functor m, Applicative m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
49−desugarTypeDeclarations (PositionedDeclaration pos com d : ds) = do
50− (d' : ds') <- rethrowWithPosition pos $ desugarTypeDeclarations (d : ds)
51− return (PositionedDeclaration pos com d' : ds')
52−desugarTypeDeclarations (TypeDeclaration name ty : d : rest) = do
53− (_, nameKind, val) <- fromValueDeclaration d
54− desugarTypeDeclarations (ValueDeclaration name nameKind [] (Right (TypedValue True val ty)) : rest)
43+ rethrow (addHint (ErrorInModule name)) $
44+ Module ss coms name <$> desugarTypeDeclarations True ds <*> pure exps
5545 where
56− fromValueDeclaration :: (Functor m, Applicative m, MonadError MultipleErrors m) => Declaration -> m (Ident, NameKind, Expr)
57− fromValueDeclaration (ValueDeclaration name' nameKind [] (Right val)) | name == name' = return (name', nameKind, val)
58− fromValueDeclaration (PositionedDeclaration pos com d') = do
59− (ident, nameKind, val) <- rethrowWithPosition pos $ fromValueDeclaration d'
60− return (ident, nameKind, PositionedValue pos com val)
61− fromValueDeclaration _ = throwError . errorMessage $ OrphanTypeDeclaration name
62−desugarTypeDeclarations (TypeDeclaration name _ : []) = throwError . errorMessage $ OrphanTypeDeclaration name
63−desugarTypeDeclarations (ValueDeclaration name nameKind bs val : rest) = do
64− let (_, f, _) = everywhereOnValuesTopDownM return go return
65− f' (Left gs) = Left <$> mapM (pairM return f) gs
66− f' (Right v) = Right <$> f v
67− (:) <$> (ValueDeclaration name nameKind bs <$> f' val) <*> desugarTypeDeclarations rest
68− where
69− go (Let ds val') = Let <$> desugarTypeDeclarations ds <*> pure val'
70− go other = return other
71−desugarTypeDeclarations (d:ds) = (:) d <$> desugarTypeDeclarations ds
72−desugarTypeDeclarations [] = return []
46+
47+ desugarTypeDeclarations :: Bool -> [Declaration] -> m [Declaration]
48+ desugarTypeDeclarations reqd (PositionedDeclaration pos com d : ds) = do
49+ (d' : ds') <- rethrowWithPosition pos $ desugarTypeDeclarations reqd (d : ds)
50+ return (PositionedDeclaration pos com d' : ds')
51+ desugarTypeDeclarations reqd (TypeDeclaration name ty : d : rest) = do
52+ (_, nameKind, val) <- fromValueDeclaration d
53+ desugarTypeDeclarations reqd (ValueDeclaration name nameKind [] (Right (TypedValue True val ty)) : rest)
54+ where
55+ fromValueDeclaration :: Declaration -> m (Ident, NameKind, Expr)
56+ fromValueDeclaration (ValueDeclaration name' nameKind [] (Right val)) | name == name' = return (name', nameKind, val)
57+ fromValueDeclaration (PositionedDeclaration pos com d') = do
58+ (ident, nameKind, val) <- rethrowWithPosition pos $ fromValueDeclaration d'
59+ return (ident, nameKind, PositionedValue pos com val)
60+ fromValueDeclaration _ = throwError . errorMessage $ OrphanTypeDeclaration name
61+ desugarTypeDeclarations _ [TypeDeclaration name _] = throwError . errorMessage $ OrphanTypeDeclaration name
62+ desugarTypeDeclarations reqd (ValueDeclaration name nameKind bs val : rest) = do
63+ -- At the top level, match a type signature or emit a warning.
64+ when reqd $ case val of
65+ Right TypedValue{} -> return ()
66+ Left _ -> error "desugarTypeDeclarations: cases were not desugared"
67+ _ -> tell (addHint (ErrorInValueDeclaration name) $ errorMessage $ MissingTypeDeclaration name)
68+ let (_, f, _) = everywhereOnValuesTopDownM return go return
69+ f' (Left gs) = Left <$> mapM (pairM return f) gs
70+ f' (Right v) = Right <$> f v
71+ (:) <$> (ValueDeclaration name nameKind bs <$> f' val) <*> desugarTypeDeclarations reqd rest
72+ where
73+ go (Let ds val') = Let <$> desugarTypeDeclarations False ds <*> pure val'
74+ go other = return other
75+ desugarTypeDeclarations reqd (d:ds) = (:) d <$> desugarTypeDeclarations reqd ds
76+ desugarTypeDeclarations _ [] = return []
src/Language/PureScript/TypeChecker.hs+15−27
@@ -51,7 +51,7 @@ addDataType moduleName dtype name args dctors ctorKind = do
5151 env <- getEnv
5252 putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (ctorKind, DataType args dctors) (types env) }
5353 forM_ dctors $ \(dctor, tys) ->
54− warnAndRethrow (onErrorMessages (ErrorInDataConstructor dctor)) $
54+ warnAndRethrow (addHint (ErrorInDataConstructor dctor)) $
5555 addDataConstructor moduleName dtype name (map fst args) dctor tys
5656
5757addDataConstructor :: ModuleName -> DataDeclType -> ProperName -> [String] -> ProperName -> [Type] -> Check ()
@@ -132,12 +132,12 @@ checkTypeSynonyms = void . replaceAllTypeSynonyms
132132--
133133-- * Process module imports
134134--
135−typeCheckAll :: Maybe ModuleName -> ModuleName -> [DeclarationRef] -> [Declaration] -> Check [Declaration]
136−typeCheckAll mainModuleName moduleName _ ds = mapM go ds <* mapM_ checkOrphanFixities ds
135+typeCheckAll :: ModuleName -> [DeclarationRef] -> [Declaration] -> Check [Declaration]
136+typeCheckAll moduleName _ ds = mapM go ds <* mapM_ checkOrphanFixities ds
137137 where
138138 go :: Declaration -> Check Declaration
139139 go (DataDeclaration dtype name args dctors) = do
140− warnAndRethrow (onErrorMessages (ErrorInTypeConstructor name)) $ do
140+ warnAndRethrow (addHint (ErrorInTypeConstructor name)) $ do
141141 when (dtype == Newtype) $ checkNewtype dctors
142142 checkDuplicateTypeArguments $ map fst args
143143 ctorKind <- kindsOf True moduleName name args (concatMap snd dctors)
@@ -150,7 +150,7 @@ typeCheckAll mainModuleName moduleName _ ds = mapM go ds <* mapM_ checkOrphanFix
150150 checkNewtype [(_, _)] = throwError . errorMessage $ InvalidNewtype
151151 checkNewtype _ = throwError . errorMessage $ InvalidNewtype
152152 go (d@(DataBindingGroupDeclaration tys)) = do
153− warnAndRethrow (onErrorMessages ErrorInDataBindingGroup) $ do
153+ warnAndRethrow (addHint ErrorInDataBindingGroup) $ do
154154 let syns = mapMaybe toTypeSynonym tys
155155 let dataDecls = mapMaybe toDataDecl tys
156156 (syn_ks, data_ks) <- kindsOfAll moduleName syns (map (\(_, name, args, dctors) -> (name, args, concatMap snd dctors)) dataDecls)
@@ -171,7 +171,7 @@ typeCheckAll mainModuleName moduleName _ ds = mapM go ds <* mapM_ checkOrphanFix
171171 toDataDecl (PositionedDeclaration _ _ d') = toDataDecl d'
172172 toDataDecl _ = Nothing
173173 go (TypeSynonymDeclaration name args ty) = do
174− warnAndRethrow (onErrorMessages (ErrorInTypeSynonym name)) $ do
174+ warnAndRethrow (addHint (ErrorInTypeSynonym name)) $ do
175175 checkDuplicateTypeArguments $ map fst args
176176 kind <- kindsOf False moduleName name args [ty]
177177 let args' = args `withKinds` kind
@@ -179,17 +179,17 @@ typeCheckAll mainModuleName moduleName _ ds = mapM go ds <* mapM_ checkOrphanFix
179179 return $ TypeSynonymDeclaration name args ty
180180 go (TypeDeclaration{}) = error "Type declarations should have been removed"
181181 go (ValueDeclaration name nameKind [] (Right val)) =
182− warnAndRethrow (onErrorMessages (ErrorInValueDeclaration name)) $ do
182+ warnAndRethrow (addHint (ErrorInValueDeclaration name)) $ do
183183 valueIsNotDefined moduleName name
184− [(_, (val', ty))] <- typesOf mainModuleName moduleName [(name, val)]
184+ [(_, (val', ty))] <- typesOf moduleName [(name, val)]
185185 addValue moduleName name ty nameKind
186186 return $ ValueDeclaration name nameKind [] $ Right val'
187187 go (ValueDeclaration{}) = error "Binders were not desugared"
188188 go (BindingGroupDeclaration vals) =
189− warnAndRethrow (onErrorMessages (ErrorInBindingGroup (map (\(ident, _, _) -> ident) vals))) $ do
189+ warnAndRethrow (addHint (ErrorInBindingGroup (map (\(ident, _, _) -> ident) vals))) $ do
190190 forM_ (map (\(ident, _, _) -> ident) vals) $ \name ->
191191 valueIsNotDefined moduleName name
192− tys <- typesOf mainModuleName moduleName $ map (\(ident, _, ty) -> (ident, ty)) vals
192+ tys <- typesOf moduleName $ map (\(ident, _, ty) -> (ident, ty)) vals
193193 vals' <- forM [ (name, val, nameKind, ty)
194194 | (name, nameKind, _) <- vals
195195 , (name', (val, ty)) <- tys
@@ -203,7 +203,7 @@ typeCheckAll mainModuleName moduleName _ ds = mapM go ds <* mapM_ checkOrphanFix
203203 putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (kind, ExternData) (types env) }
204204 return d
205205 go (d@(ExternDeclaration name ty)) = do
206− warnAndRethrow (onErrorMessages (ErrorInForeignImport name)) $ do
206+ warnAndRethrow (addHint (ErrorInForeignImport name)) $ do
207207 env <- getEnv
208208 kind <- kindOf moduleName ty
209209 guardWith (errorMessage (ExpectedType ty kind)) $ kind == Star
@@ -267,13 +267,12 @@ typeCheckAll mainModuleName moduleName _ ds = mapM go ds <* mapM_ checkOrphanFix
267267-- Type check an entire module and ensure all types and classes defined within the module that are
268268-- required by exported members are also exported.
269269--
270−typeCheckModule :: Maybe ModuleName -> Module -> Check Module
271−typeCheckModule _ (Module _ _ _ _ Nothing) = error "exports should have been elaborated"
272−typeCheckModule mainModuleName (Module ss coms mn decls (Just exps)) = warnAndRethrow (onErrorMessages (ErrorInModule mn)) $ do
270+typeCheckModule :: Module -> Check Module
271+typeCheckModule (Module _ _ _ _ Nothing) = error "exports should have been elaborated"
272+typeCheckModule (Module ss coms mn decls (Just exps)) = warnAndRethrow (addHint (ErrorInModule mn)) $ do
273273 modify (\s -> s { checkCurrentModule = Just mn })
274− decls' <- typeCheckAll mainModuleName mn exps decls
274+ decls' <- typeCheckAll mn exps decls
275275 forM_ exps $ \e -> do
276− checkTypesAreExported e
277276 checkClassMembersAreExported e
278277 checkClassesAreExported e
279278 return $ Module ss coms mn decls' (Just exps)
@@ -295,17 +294,6 @@ typeCheckModule mainModuleName (Module ss coms mn decls (Just exps)) = warnAndRe
295294 exports _ _ = False
296295 checkMemberExport _ _ = return ()
297296
298− -- Check that all the type constructors defined in the current module that appear in member types
299− -- have also been exported from the module
300− checkTypesAreExported :: DeclarationRef -> Check ()
301− checkTypesAreExported = checkMemberExport findTcons
302− where
303− findTcons :: Type -> [DeclarationRef]
304− findTcons = everythingOnTypes (++) go
305− where
306− go (TypeConstructor (Qualified (Just mn') name)) | mn' == mn = [TypeRef name (error "Data constructors unused in checkTypesAreExported")]
307− go _ = []
308−
309297 -- Check that all the classes defined in the current module that appear in member types have also
310298 -- been exported from the module
311299 checkClassesAreExported :: DeclarationRef -> Check ()
src/Language/PureScript/TypeChecker/Entailment.hs+15−25
@@ -13,7 +13,6 @@
1313--
1414-----------------------------------------------------------------------------
1515
16−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
1716{-# LANGUAGE CPP #-}
1817
1918module Language.PureScript.TypeChecker.Entailment (
@@ -38,10 +37,8 @@ import Control.Monad.Writer.Class (tell)
3837
3938import Language.PureScript.AST
4039import Language.PureScript.Errors
41−import Language.PureScript.Environment
4240import Language.PureScript.Names
4341import Language.PureScript.TypeChecker.Monad
44−import Language.PureScript.TypeChecker.Synonyms
4542import Language.PureScript.TypeChecker.Unify
4643import Language.PureScript.TypeClassDictionaries
4744import Language.PureScript.Types
@@ -51,8 +48,8 @@ import qualified Language.PureScript.Constants as C
5148-- Check that the current set of type class dictionaries entail the specified type class goal, and, if so,
5249-- return a type class dictionary reference.
5350--
54−entails :: Environment -> ModuleName -> M.Map (Maybe ModuleName) (M.Map (Qualified ProperName) (M.Map (Qualified Ident) TypeClassDictionaryInScope)) -> Constraint -> Check Expr
55−entails env moduleName context = solve
51+entails :: ModuleName -> M.Map (Maybe ModuleName) (M.Map (Qualified ProperName) (M.Map (Qualified Ident) TypeClassDictionaryInScope)) -> Constraint -> Check Expr
52+entails moduleName context = solve
5653 where
5754 forClassName :: Qualified ProperName -> [Type] -> [TypeClassDictionaryInScope]
5855 forClassName cn@(Qualified (Just mn) _) tys = concatMap (findDicts cn) (Nothing : Just mn : map Just (mapMaybe ctorModules tys))
@@ -75,14 +72,10 @@ entails env moduleName context = solve
7572 go :: Int -> Qualified ProperName -> [Type] -> Check DictionaryValue
7673 go work className' tys' | work > 1000 = throwError . errorMessage $ PossiblyInfiniteInstance className' tys'
7774 go work className' tys' = do
78− -- We need to desugar synonyms here so that forClassName can find the correct modules
79− -- in types hidden inside the synonyms.
80− -- TODO: this can go away when synonyms get desugared up front.
81− tys'' <- mapM expandAllTypeSynonyms tys'
8275 let instances = do
83− tcd <- forClassName className' tys''
76+ tcd <- forClassName className' tys'
8477 -- Make sure the type unifies with the type in the type instance definition
85− subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys'' (tcdInstanceTypes tcd)
78+ subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName) tys' (tcdInstanceTypes tcd)
8679 return (subst, tcd)
8780 (subst, tcd) <- unique instances
8881 -- Solve any necessary subgoals
@@ -140,7 +133,7 @@ entails env moduleName context = solve
140133 verifySubstitution :: [(String, Type)] -> Maybe [(String, Type)]
141134 verifySubstitution subst = do
142135 let grps = groupBy ((==) `on` fst) . sortBy (compare `on` fst) $ subst
143− guard (all (pairwise (unifiesWith env) . map snd) grps)
136+ guard (all (pairwise unifiesWith . map snd) grps)
144137 return $ map head grps
145138
146139 valUndefined :: Expr
@@ -150,24 +143,21 @@ entails env moduleName context = solve
150143-- Check whether the type heads of two types are equal (for the purposes of type class dictionary lookup),
151144-- and return a substitution from type variables to types which makes the type heads unify.
152145--
153−typeHeadsAreEqual :: ModuleName -> Environment -> Type -> Type -> Maybe [(String, Type)]
154−typeHeadsAreEqual _ _ (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = Just []
155−typeHeadsAreEqual _ _ t (TypeVar v) = Just [(v, t)]
156−typeHeadsAreEqual _ _ (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = Just []
157−typeHeadsAreEqual m e (TypeApp h1 t1) (TypeApp h2 t2) = (++) <$> typeHeadsAreEqual m e h1 h2
158− <*> typeHeadsAreEqual m e t1 t2
159−typeHeadsAreEqual m e (SaturatedTypeSynonym name args) t2 = case expandTypeSynonym' e name args of
160− Left _ -> Nothing
161− Right t1 -> typeHeadsAreEqual m e t1 t2
162−typeHeadsAreEqual _ _ REmpty REmpty = Just []
163−typeHeadsAreEqual m e r1@(RCons _ _ _) r2@(RCons _ _ _) =
146+typeHeadsAreEqual :: ModuleName -> Type -> Type -> Maybe [(String, Type)]
147+typeHeadsAreEqual _ (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = Just []
148+typeHeadsAreEqual _ t (TypeVar v) = Just [(v, t)]
149+typeHeadsAreEqual _ (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = Just []
150+typeHeadsAreEqual m (TypeApp h1 t1) (TypeApp h2 t2) = (++) <$> typeHeadsAreEqual m h1 h2
151+ <*> typeHeadsAreEqual m t1 t2
152+typeHeadsAreEqual _ REmpty REmpty = Just []
153+typeHeadsAreEqual m r1@RCons{} r2@RCons{} =
164154 let (s1, r1') = rowToList r1
165155 (s2, r2') = rowToList r2
166156
167157 int = [ (t1, t2) | (name, t1) <- s1, (name', t2) <- s2, name == name' ]
168158 sd1 = [ (name, t1) | (name, t1) <- s1, name `notElem` map fst s2 ]
169159 sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ]
170− in (++) <$> foldMap (\(t1, t2) -> typeHeadsAreEqual m e t1 t2) int
160+ in (++) <$> foldMap (uncurry (typeHeadsAreEqual m)) int
171161 <*> go sd1 r1' sd2 r2'
172162 where
173163 go :: [(String, Type)] -> Type -> [(String, Type)] -> Type -> Maybe [(String, Type)]
@@ -177,7 +167,7 @@ typeHeadsAreEqual m e r1@(RCons _ _ _) r2@(RCons _ _ _) =
177167 go [] (Skolem _ s1 _) [] (Skolem _ s2 _) | s1 == s2 = Just []
178168 go sd r [] (TypeVar v) = Just [(v, rowFromList (sd, r))]
179169 go _ _ _ _ = Nothing
180−typeHeadsAreEqual _ _ _ _ = Nothing
170+typeHeadsAreEqual _ _ _ = Nothing
181171
182172-- |
183173-- Check all values in a list pairwise match a predicate
src/Language/PureScript/TypeChecker/Kinds.hs+2−2
@@ -83,7 +83,7 @@ kindOf _ ty = fst <$> kindOfWithScopedVars ty
8383--
8484kindOfWithScopedVars :: Type -> Check (Kind, [(String, Kind)])
8585kindOfWithScopedVars ty =
86− rethrow (onErrorMessages (ErrorCheckingKind ty)) $
86+ rethrow (addHint (ErrorCheckingKind ty)) $
8787 fmap tidyUp . liftUnify $ infer ty
8888 where
8989 tidyUp ((k, args), sub) = ( starIfUnknown (sub $? k)
@@ -161,7 +161,7 @@ starIfUnknown k = k
161161-- Infer a kind for a type
162162--
163163infer :: Type -> UnifyT Kind Check (Kind, [(String, Kind)])
164−infer ty = rethrow (onErrorMessages (ErrorCheckingKind ty)) $ infer' ty
164+infer ty = rethrow (addHint (ErrorCheckingKind ty)) $ infer' ty
165165
166166infer' :: Type -> UnifyT Kind Check (Kind, [(String, Kind)])
167167infer' (ForAll ident ty _) = do
src/Language/PureScript/TypeChecker/Rows.hs−1
@@ -46,7 +46,6 @@ checkDuplicateLabels =
4646 where
4747 checkDups :: Type -> Check ()
4848 checkDups (TypeApp t1 t2) = checkDups t1 >> checkDups t2
49− checkDups (SaturatedTypeSynonym _ ts) = mapM_ checkDups ts
5049 checkDups (ForAll _ t _) = checkDups t
5150 checkDups (ConstrainedType args t) = do
5251 mapM_ checkDups $ concatMap snd args
src/Language/PureScript/TypeChecker/Skolems.hs+1−1
@@ -92,7 +92,7 @@ skolemEscapeCheck root@TypedValue{} =
9292 let (_, f, _, _, _) = everythingWithContextOnValues [] [] (++) def go def def def
9393 in case f root of
9494 [] -> return ()
95− ((binding, val) : _) -> throwError . singleError $ ErrorInExpression val $ SimpleErrorWrapper $ EscapedSkolem binding
95+ ((binding, val) : _) -> throwError . singleError $ ErrorMessage [ ErrorInExpression val ] $ EscapedSkolem binding
9696 where
9797 def s _ = (s, [])
9898
src/Language/PureScript/TypeChecker/Subsumption.hs+1−9
@@ -20,7 +20,6 @@ module Language.PureScript.TypeChecker.Subsumption (
2020import Data.List (sortBy)
2121import Data.Ord (comparing)
2222
23−import Control.Monad
2423import Control.Monad.Error.Class (MonadError(..))
2524import Control.Monad.Unify
2625
@@ -29,7 +28,6 @@ import Language.PureScript.Environment
2928import Language.PureScript.Errors
3029import Language.PureScript.TypeChecker.Monad
3130import Language.PureScript.TypeChecker.Skolems
32−import Language.PureScript.TypeChecker.Synonyms
3331import Language.PureScript.TypeChecker.Unify
3432import Language.PureScript.Types
3533
@@ -37,7 +35,7 @@ import Language.PureScript.Types
3735-- Check whether one type subsumes another, rethrowing errors to provide a better error message
3836--
3937subsumes :: Maybe Expr -> Type -> Type -> UnifyT Type Check (Maybe Expr)
40−subsumes val ty1 ty2 = rethrow (onErrorMessages (ErrorInSubsumption ty1 ty2)) $ subsumes' val ty1 ty2
38+subsumes val ty1 ty2 = rethrow (addHint (ErrorInSubsumption ty1 ty2)) $ subsumes' val ty1 ty2
4139
4240-- |
4341-- Check whether one type subsumes another
@@ -57,12 +55,6 @@ subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2)
5755 _ <- subsumes Nothing arg2 arg1
5856 _ <- subsumes Nothing ret1 ret2
5957 return val
60−subsumes' val (SaturatedTypeSynonym name tyArgs) ty2 = do
61− ty1 <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
62− subsumes val ty1 ty2
63−subsumes' val ty1 (SaturatedTypeSynonym name tyArgs) = do
64− ty2 <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
65− subsumes val ty1 ty2
6658subsumes' val (KindedType ty1 _) ty2 =
6759 subsumes val ty1 ty2
6860subsumes' val ty1 (KindedType ty2 _) =
src/Language/PureScript/TypeChecker/Synonyms.hs+20−66
@@ -9,22 +9,18 @@
99-- Portability :
1010--
1111-- |
12−-- Functions for replacing fully applied type synonyms with the @SaturatedTypeSynonym@ data constructor
12+-- Functions for replacing fully applied type synonyms
1313--
1414-----------------------------------------------------------------------------
1515
1616{-# LANGUAGE FlexibleContexts #-}
1717{-# LANGUAGE MultiParamTypeClasses #-}
18+{-# LANGUAGE PatternGuards #-}
1819{-# LANGUAGE GADTs #-}
1920{-# LANGUAGE CPP #-}
2021
2122module Language.PureScript.TypeChecker.Synonyms (
22− saturateAllTypeSynonyms,
23− desaturateAllTypeSynonyms,
24− replaceAllTypeSynonyms,
25− expandAllTypeSynonyms,
26− expandTypeSynonym,
27− expandTypeSynonym'
23+ replaceAllTypeSynonyms
2824) where
2925
3026import Data.Maybe (fromMaybe)
@@ -38,73 +34,31 @@ import Control.Monad.State
3834
3935import Language.PureScript.Environment
4036import Language.PureScript.Errors
41−import Language.PureScript.Names
4237import Language.PureScript.TypeChecker.Monad
4338import Language.PureScript.Types
4439
4540-- |
46−-- Build a type substitution for a type synonym
41+-- Replace fully applied type synonyms.
4742--
48−buildTypeSubstitution :: M.Map (Qualified ProperName) Int -> Type -> Either ErrorMessage (Maybe Type)
49−buildTypeSubstitution m = go 0 []
43+replaceAllTypeSynonyms' :: Environment -> Type -> Either MultipleErrors Type
44+replaceAllTypeSynonyms' env = everywhereOnTypesTopDownM try
5045 where
51− go :: Int -> [Type] -> Type -> Either ErrorMessage (Maybe Type)
52− go c args (TypeConstructor ctor) | M.lookup ctor m == Just c = return (Just $ SaturatedTypeSynonym ctor args)
53− go c _ (TypeConstructor ctor) | M.lookup ctor m > Just c = throwError $ SimpleErrorWrapper $ PartiallyAppliedSynonym ctor
54− go c args (TypeApp f arg) = go (c + 1) (arg:args) f
55− go _ _ _ = return Nothing
56−
57−-- |
58−-- Replace all type synonyms with the @SaturatedTypeSynonym@ data constructor
59−--
60−saturateAllTypeSynonyms :: M.Map (Qualified ProperName) Int -> Type -> Either ErrorMessage Type
61−saturateAllTypeSynonyms syns = everywhereOnTypesTopDownM replace
62− where
63− replace t = fromMaybe t <$> buildTypeSubstitution syns t
46+ try :: Type -> Either MultipleErrors Type
47+ try t = fromMaybe t <$> go 0 [] t
6448
65−-- |
66−-- \"Desaturate\" @SaturatedTypeSynonym@s
67−--
68−desaturateAllTypeSynonyms :: Type -> Type
69−desaturateAllTypeSynonyms = everywhereOnTypes replaceSaturatedTypeSynonym
70− where
71− replaceSaturatedTypeSynonym (SaturatedTypeSynonym name args) = foldl TypeApp (TypeConstructor name) args
72− replaceSaturatedTypeSynonym t = t
73−
74−-- |
75−-- Replace fully applied type synonyms with the @SaturatedTypeSynonym@ data constructor, which helps generate
76−-- better error messages during unification.
77−--
78−replaceAllTypeSynonyms' :: Environment -> Type -> Either ErrorMessage Type
79−replaceAllTypeSynonyms' env d =
80− let
81− syns = length . fst <$> typeSynonyms env
82− in
83− saturateAllTypeSynonyms syns d
49+ go :: Int -> [Type] -> Type -> Either MultipleErrors (Maybe Type)
50+ go c args (TypeConstructor ctor)
51+ | Just (synArgs, body) <- M.lookup ctor (typeSynonyms env)
52+ , c == length synArgs
53+ = let repl = replaceAllTypeVars (zip (map fst synArgs) args) body
54+ in Just <$> try repl
55+ | Just (synArgs, _) <- M.lookup ctor (typeSynonyms env)
56+ , length synArgs > c
57+ = throwError . errorMessage $ PartiallyAppliedSynonym ctor
58+ go c args (TypeApp f arg) = go (c + 1) (arg : args) f
59+ go _ _ _ = return Nothing
8460
8561replaceAllTypeSynonyms :: (e ~ MultipleErrors, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
8662replaceAllTypeSynonyms d = do
8763 env <- getEnv
88− either (throwError . singleError) return $ replaceAllTypeSynonyms' env d
89−
90−-- |
91−-- Replace a type synonym and its arguments with the aliased type
92−--
93−expandTypeSynonym' :: Environment -> Qualified ProperName -> [Type] -> Either ErrorMessage Type
94−expandTypeSynonym' env name args =
95− case M.lookup name (typeSynonyms env) of
96− Just (synArgs, body) -> do
97− let repl = replaceAllTypeVars (zip (map fst synArgs) args) body
98− replaceAllTypeSynonyms' env repl
99− Nothing -> error "Type synonym was not defined"
100−
101−expandTypeSynonym :: (e ~ MultipleErrors, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Qualified ProperName -> [Type] -> m Type
102−expandTypeSynonym name args = do
103− env <- getEnv
104− either (throwError . singleError) return $ expandTypeSynonym' env name args
105−
106−expandAllTypeSynonyms :: (e ~ MultipleErrors, Functor m, Applicative m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
107−expandAllTypeSynonyms = everywhereOnTypesTopDownM go
108− where
109− go (SaturatedTypeSynonym name args) = expandTypeSynonym name args
110− go other = return other
64+ either throwError return $ replaceAllTypeSynonyms' env d
src/Language/PureScript/TypeChecker/Types.hs+15−67
@@ -67,24 +67,17 @@ import Language.PureScript.TypeChecker.Synonyms
6767import Language.PureScript.TypeChecker.Unify
6868import Language.PureScript.TypeClassDictionaries
6969import Language.PureScript.Types
70−import qualified Language.PureScript.Constants as C
7170
7271-- |
7372-- Infer the types of multiple mutually-recursive values, and return elaborated values including
7473-- type class dictionaries and type annotations.
7574--
76−typesOf :: Maybe ModuleName -> ModuleName -> [(Ident, Expr)] -> Check [(Ident, (Expr, Type))]
77−typesOf mainModuleName moduleName vals = do
75+typesOf :: ModuleName -> [(Ident, Expr)] -> Check [(Ident, (Expr, Type))]
76+typesOf moduleName vals = do
7877 tys <- fmap tidyUp . liftUnifyWarnings replace $ do
7978 (untyped, typed, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName vals
80− ds1 <- parU typed $ \e -> do
81− triple@(_, (_, ty)) <- checkTypedBindingGroupElement moduleName e dict
82− checkMain (fst e) ty
83− return triple
84− ds2 <- forM untyped $ \e -> do
85− triple@(_, (_, ty)) <- typeForBindingGroupElement e dict untypedDict
86− checkMain (fst e) ty
87− return triple
79+ ds1 <- parU typed $ \e -> checkTypedBindingGroupElement moduleName e dict
80+ ds2 <- forM untyped $ \e -> typeForBindingGroupElement e dict untypedDict
8881 return $ ds1 ++ ds2
8982
9083 forM tys $ \(ident, (val, ty)) -> do
@@ -94,21 +87,13 @@ typesOf mainModuleName moduleName vals = do
9487 skolemEscapeCheck val'
9588 -- Check rows do not contain duplicate labels
9689 checkDuplicateLabels val'
97− -- Remove type synonyms placeholders, and replace
98− -- top-level unification variables with named type variables.
99− let val'' = overTypes desaturateAllTypeSynonyms val'
100− ty' = varIfUnknown . desaturateAllTypeSynonyms $ ty
101− return (ident, (val'', ty'))
90+ return (ident, (val', varIfUnknown ty))
10291 where
10392 -- Apply the substitution that was returned from runUnify to both types and (type-annotated) values
10493 tidyUp (ts, sub) = map (\(i, (val, ty)) -> (i, (overTypes (sub $?) val, sub $? ty))) ts
10594 -- Replace all the wildcards types with their inferred types
106− replace sub (SimpleErrorWrapper (WildcardInferredType ty)) = SimpleErrorWrapper $ WildcardInferredType (sub $? ty)
95+ replace sub (ErrorMessage hints (WildcardInferredType ty)) = ErrorMessage hints $ WildcardInferredType (sub $? ty)
10796 replace _ em = em
108− -- If --main is enabled, need to check that `main` has type Eff eff a for some eff, a
109− checkMain nm ty = when (Just moduleName == mainModuleName && nm == Ident C.main) $ do
110− [eff, a] <- replicateM 2 fresh
111− ty =?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Control", ProperName "Monad", ProperName "Eff"])) (ProperName "Eff"))) eff) a
11297
11398type TypeData = M.Map (ModuleName, Ident) (Type, NameKind, NameVisibility)
11499
@@ -182,9 +167,7 @@ replaceTypeClassDictionaries mn =
182167 let (_, f, _) = everywhereOnValuesTopDownM return go return
183168 in f
184169 where
185− go (TypeClassDictionary constraint dicts) = do
186− env <- getEnv
187− entails env mn dicts constraint
170+ go (TypeClassDictionary constraint dicts) = entails mn dicts constraint
188171 go other = return other
189172
190173-- |
@@ -214,7 +197,7 @@ instantiatePolyTypeWithUnknowns val ty = return (val, ty)
214197-- Infer a type for a value, rethrowing any error to provide a more useful error message
215198--
216199infer :: Expr -> UnifyT Type Check Expr
217−infer val = rethrow (onErrorMessages (ErrorInferringType val)) $ infer' val
200+infer val = rethrow (addHint (ErrorInferringType val)) $ infer' val
218201
219202-- |
220203-- Infer a type for a value
@@ -246,15 +229,10 @@ infer' (ObjectUpdate o ps) = do
246229 o' <- TypedValue True <$> check o oldTy <*> pure oldTy
247230 return $ TypedValue True (ObjectUpdate o' newVals) $ TypeApp tyObject $ rowFromList (newTys, row)
248231infer' (Accessor prop val) = do
249− typed@(TypedValue _ _ objTy) <- infer val
250− propTy <- inferProperty objTy prop
251− case propTy of
252− Nothing -> do
253− field <- fresh
254− rest <- fresh
255− _ <- subsumes Nothing objTy (TypeApp tyObject (RCons prop field rest))
256− return $ TypedValue True (Accessor prop typed) field
257− Just ty -> return $ TypedValue True (Accessor prop typed) ty
232+ field <- fresh
233+ rest <- fresh
234+ typed <- check val (TypeApp tyObject (RCons prop field rest))
235+ return $ TypedValue True (Accessor prop typed) field
258236infer' (Abs (Left arg) ret) = do
259237 ty <- fresh
260238 Just moduleName <- checkCurrentModule <$> get
@@ -339,21 +317,6 @@ inferLetBinding seen (PositionedDeclaration pos com d : ds) ret j = warnAndRethr
339317 return (PositionedDeclaration pos com d' : ds', val')
340318inferLetBinding _ _ _ _ = error "Invalid argument to inferLetBinding"
341319
342−-- |
343−-- Infer the type of a property inside a record with a given type
344−--
345−inferProperty :: Type -> String -> UnifyT Type Check (Maybe Type)
346−inferProperty (TypeApp obj row) prop | obj == tyObject = do
347− let (props, _) = rowToList row
348− return $ lookup prop props
349−inferProperty (SaturatedTypeSynonym name args) prop = do
350− replaced <- introduceSkolemScope <=< expandTypeSynonym name $ args
351− inferProperty replaced prop
352−inferProperty (ForAll ident ty _) prop = do
353− replaced <- replaceVarWithUnknown ident ty
354− inferProperty replaced prop
355−inferProperty _ _ = return Nothing
356−
357320-- |
358321-- Infer the types of variables brought into scope by a binder
359322--
@@ -420,7 +383,7 @@ binderRequiresMonotype _ = True
420383
421384-- | Instantiate polytypes only when necessitated by a binder.
422385instantiateForBinders :: [Expr] -> [CaseAlternative] -> UnifyT Type Check ([Expr], [Type])
423−instantiateForBinders vals cas = fmap unzip $ zipWithM (\val inst -> do
386+instantiateForBinders vals cas = unzip <$> zipWithM (\val inst -> do
424387 TypedValue _ val' ty <- infer val
425388 if inst
426389 then instantiatePolyTypeWithUnknowns val' ty
@@ -458,7 +421,7 @@ checkBinders nvals ret (CaseAlternative binders result : bs) = do
458421-- Check the type of a value, rethrowing errors to provide a better error message
459422--
460423check :: Expr -> Type -> UnifyT Type Check Expr
461−check val ty = rethrow (onErrorMessages (ErrorCheckingType val ty)) $ check' val ty
424+check val ty = rethrow (addHint (ErrorCheckingType val ty)) $ check' val ty
462425
463426-- |
464427-- Check the type of a value
@@ -494,9 +457,6 @@ check' val t@(ConstrainedType constraints ty) = do
494457
495458 instantiateSuperclass :: [String] -> [Type] -> [Type] -> [Type]
496459 instantiateSuperclass args supArgs tys = map (replaceAllTypeVars (zip args tys)) supArgs
497−check' val (SaturatedTypeSynonym name args) = do
498− ty <- introduceSkolemScope <=< expandTypeSynonym name $ args
499− check val ty
500460check' val u@(TUnknown _) = do
501461 val'@(TypedValue _ _ ty) <- infer val
502462 -- Don't unify an unknown with an inferred polytype
@@ -600,9 +560,6 @@ check' v@(Constructor c) ty = do
600560check' (Let ds val) ty = do
601561 (ds', val') <- inferLetBinding [] ds val (`check` ty)
602562 return $ TypedValue True (Let ds' val') ty
603−check' val ty | containsTypeSynonyms ty = do
604− ty' <- introduceSkolemScope <=< expandAllTypeSynonyms <=< replaceTypeWildcards $ ty
605− check val ty'
606563check' val kt@(KindedType ty kind) = do
607564 checkTypeKind ty kind
608565 val' <- check' val ty
@@ -616,12 +573,6 @@ check' val ty = do
616573 Nothing -> throwError . errorMessage $ SubsumptionCheckFailed
617574 Just v' -> return $ TypedValue True v' ty
618575
619−containsTypeSynonyms :: Type -> Bool
620−containsTypeSynonyms = everythingOnTypes (||) go where
621− go (SaturatedTypeSynonym _ _) = True
622− go _ = False
623−
624−
625576-- |
626577-- Check the type of a collection of named record fields
627578--
@@ -656,7 +607,7 @@ checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
656607-- Check the type of a function application, rethrowing errors to provide a better error message
657608--
658609checkFunctionApplication :: Expr -> Type -> Expr -> Maybe Type -> UnifyT Type Check (Type, Expr)
659−checkFunctionApplication fn fnTy arg ret = rethrow (onErrorMessages (ErrorInApplication fn fnTy arg)) $ do
610+checkFunctionApplication fn fnTy arg ret = rethrow (addHint (ErrorInApplication fn fnTy arg)) $ do
660611 subst <- unifyCurrentSubstitution <$> UnifyT get
661612 checkFunctionApplication' fn (subst $? fnTy) arg (($?) subst <$> ret)
662613
@@ -684,9 +635,6 @@ checkFunctionApplication' fn u@(TUnknown _) arg ret = do
684635 ret' <- maybe fresh return ret
685636 u =?= function ty ret'
686637 return (ret', App fn arg')
687−checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do
688− ty <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
689− checkFunctionApplication fn ty arg ret
690638checkFunctionApplication' fn (KindedType ty _) arg ret =
691639 checkFunctionApplication fn ty arg ret
692640checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
src/Language/PureScript/TypeChecker/Unify.hs+11−26
@@ -36,11 +36,9 @@ import Control.Monad.Unify
3636import Control.Monad.Writer
3737import Control.Monad.Error.Class (MonadError(..))
3838
39−import Language.PureScript.Environment
4039import Language.PureScript.Errors
4140import Language.PureScript.TypeChecker.Monad
4241import Language.PureScript.TypeChecker.Skolems
43−import Language.PureScript.TypeChecker.Synonyms
4442import Language.PureScript.Types
4543
4644instance Partial Type where
@@ -63,16 +61,12 @@ instance Unifiable Check Type where
6361-- Unify two types, updating the current substitution
6462--
6563unifyTypes :: Type -> Type -> UnifyT Type Check ()
66−unifyTypes t1 t2 = rethrow (onErrorMessages (ErrorUnifyingTypes t1 t2)) $
64+unifyTypes t1 t2 = rethrow (addHint (ErrorUnifyingTypes t1 t2)) $
6765 unifyTypes' t1 t2
6866 where
6967 unifyTypes' (TUnknown u1) (TUnknown u2) | u1 == u2 = return ()
7068 unifyTypes' (TUnknown u) t = u =:= t
7169 unifyTypes' t (TUnknown u) = u =:= t
72− unifyTypes' (SaturatedTypeSynonym name args) ty = do
73− ty1 <- introduceSkolemScope <=< expandTypeSynonym name $ args
74− ty1 `unifyTypes` ty
75− unifyTypes' ty s@(SaturatedTypeSynonym _ _) = s `unifyTypes` ty
7670 unifyTypes' (ForAll ident1 ty1 sc1) (ForAll ident2 ty2 sc2) =
7771 case (sc1, sc2) of
7872 (Just sc1', Just sc2') -> do
@@ -132,10 +126,6 @@ unifyRows r1 r2 =
132126 rest <- fresh
133127 u1 =:= rowFromList (sd2, rest)
134128 u2 =:= rowFromList (sd1, rest)
135− unifyRows' sd1 (SaturatedTypeSynonym name args) sd2 r2' = do
136− r1' <- expandTypeSynonym name $ args
137− unifyRows (rowFromList (sd1, r1')) (rowFromList (sd2, r2'))
138− unifyRows' sd1 r1' sd2 r2'@(SaturatedTypeSynonym _ _) = unifyRows' sd2 r2' sd1 r1'
139129 unifyRows' [] REmpty [] REmpty = return ()
140130 unifyRows' [] (TypeVar v1) [] (TypeVar v2) | v1 == v2 = return ()
141131 unifyRows' [] (Skolem _ s1 _) [] (Skolem _ s2 _) | s1 == s2 = return ()
@@ -144,26 +134,21 @@ unifyRows r1 r2 =
144134-- |
145135-- Check that two types unify
146136--
147−unifiesWith :: Environment -> Type -> Type -> Bool
148−unifiesWith _ (TUnknown u1) (TUnknown u2) | u1 == u2 = True
149−unifiesWith _ (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = True
150−unifiesWith _ (TypeVar v1) (TypeVar v2) | v1 == v2 = True
151−unifiesWith _ (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = True
152−unifiesWith e (TypeApp h1 t1) (TypeApp h2 t2) = unifiesWith e h1 h2 && unifiesWith e t1 t2
153−unifiesWith e (SaturatedTypeSynonym name args) t2 =
154− case expandTypeSynonym' e name args of
155− Left _ -> False
156− Right t1 -> unifiesWith e t1 t2
157−unifiesWith e t1 t2@(SaturatedTypeSynonym _ _) = unifiesWith e t2 t1
158−unifiesWith _ REmpty REmpty = True
159−unifiesWith e r1@(RCons _ _ _) r2@(RCons _ _ _) =
137+unifiesWith :: Type -> Type -> Bool
138+unifiesWith (TUnknown u1) (TUnknown u2) | u1 == u2 = True
139+unifiesWith (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = True
140+unifiesWith (TypeVar v1) (TypeVar v2) | v1 == v2 = True
141+unifiesWith (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = True
142+unifiesWith (TypeApp h1 t1) (TypeApp h2 t2) = h1 `unifiesWith` h2 && t1 `unifiesWith` t2
143+unifiesWith REmpty REmpty = True
144+unifiesWith r1@RCons{} r2@RCons{} =
160145 let (s1, r1') = rowToList r1
161146 (s2, r2') = rowToList r2
162147
163148 int = [ (t1, t2) | (name, t1) <- s1, (name', t2) <- s2, name == name' ]
164149 sd1 = [ (name, t1) | (name, t1) <- s1, name `notElem` map fst s2 ]
165150 sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ]
166− in all (\(t1, t2) -> unifiesWith e t1 t2) int && go sd1 r1' sd2 r2'
151+ in all (uncurry unifiesWith) int && go sd1 r1' sd2 r2'
167152 where
168153 go :: [(String, Type)] -> Type -> [(String, Type)] -> Type -> Bool
169154 go [] REmpty [] REmpty = True
@@ -173,7 +158,7 @@ unifiesWith e r1@(RCons _ _ _) r2@(RCons _ _ _) =
173158 go _ _ [] (TUnknown _) = True
174159 go _ (TUnknown _) _ (TUnknown _) = True
175160 go _ _ _ _ = False
176−unifiesWith _ _ _ = False
161+unifiesWith _ _ = False
177162
178163-- |
179164-- Replace a single type variable with a new unification variable
src/Language/PureScript/Types.hs+2−16
@@ -22,6 +22,7 @@ module Language.PureScript.Types where
2222
2323import Data.Data
2424import Data.List (nub)
25+import Data.Maybe (fromMaybe)
2526import qualified Data.Aeson as A
2627import qualified Data.Aeson.TH as A
2728
@@ -66,10 +67,6 @@ data Type
6667 --
6768 | TypeApp Type Type
6869 -- |
69− -- A type synonym which is \"saturated\", i.e. fully applied
70− --
71− | SaturatedTypeSynonym (Qualified ProperName) [Type]
72− -- |
7370 -- Forall quantifier
7471 --
7572 | ForAll String Type (Maybe SkolemScope)
@@ -156,12 +153,8 @@ replaceAllTypeVars = go []
156153 where
157154
158155 go :: [String] -> [(String, Type)] -> Type -> Type
159− go _ m (TypeVar v) =
160− case v `lookup` m of
161− Just r -> r
162− Nothing -> TypeVar v
156+ go _ m (TypeVar v) = fromMaybe (TypeVar v) (v `lookup` m)
163157 go bs m (TypeApp t1 t2) = TypeApp (go bs m t1) (go bs m t2)
164− go bs m (SaturatedTypeSynonym name' ts) = SaturatedTypeSynonym name' $ map (go bs m) ts
165158 go bs m f@(ForAll v t sco) | v `elem` keys = go bs (filter ((/= v) . fst) m) f
166159 | v `elem` usedVars =
167160 let v' = genName v (keys ++ bs ++ usedVars)
@@ -200,7 +193,6 @@ freeTypeVariables = nub . go []
200193 go :: [String] -> Type -> [String]
201194 go bound (TypeVar v) | v `notElem` bound = [v]
202195 go bound (TypeApp t1 t2) = go bound t1 ++ go bound t2
203− go bound (SaturatedTypeSynonym _ ts) = concatMap (go bound) ts
204196 go bound (ForAll v t _) = go (v : bound) t
205197 go bound (ConstrainedType cs t) = concatMap (concatMap (go bound) . snd) cs ++ go bound t
206198 go bound (RCons _ t r) = go bound t ++ go bound r
@@ -247,7 +239,6 @@ everywhereOnTypes :: (Type -> Type) -> Type -> Type
247239everywhereOnTypes f = go
248240 where
249241 go (TypeApp t1 t2) = f (TypeApp (go t1) (go t2))
250− go (SaturatedTypeSynonym name tys) = f (SaturatedTypeSynonym name (map go tys))
251242 go (ForAll arg ty sco) = f (ForAll arg (go ty) sco)
252243 go (ConstrainedType cs ty) = f (ConstrainedType (map (fmap (map go)) cs) (go ty))
253244 go (RCons name ty rest) = f (RCons name (go ty) (go rest))
@@ -261,7 +252,6 @@ everywhereOnTypesTopDown :: (Type -> Type) -> Type -> Type
261252everywhereOnTypesTopDown f = go . f
262253 where
263254 go (TypeApp t1 t2) = TypeApp (go (f t1)) (go (f t2))
264− go (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym name (map (go . f) tys)
265255 go (ForAll arg ty sco) = ForAll arg (go (f ty)) sco
266256 go (ConstrainedType cs ty) = ConstrainedType (map (fmap (map (go . f))) cs) (go (f ty))
267257 go (RCons name ty rest) = RCons name (go (f ty)) (go (f rest))
@@ -275,7 +265,6 @@ everywhereOnTypesM :: (Functor m, Applicative m, Monad m) => (Type -> m Type) ->
275265everywhereOnTypesM f = go
276266 where
277267 go (TypeApp t1 t2) = (TypeApp <$> go t1 <*> go t2) >>= f
278− go (SaturatedTypeSynonym name tys) = (SaturatedTypeSynonym name <$> mapM go tys) >>= f
279268 go (ForAll arg ty sco) = (ForAll arg <$> go ty <*> pure sco) >>= f
280269 go (ConstrainedType cs ty) = (ConstrainedType <$> mapM (sndM (mapM go)) cs <*> go ty) >>= f
281270 go (RCons name ty rest) = (RCons name <$> go ty <*> go rest) >>= f
@@ -289,7 +278,6 @@ everywhereOnTypesTopDownM :: (Functor m, Applicative m, Monad m) => (Type -> m T
289278everywhereOnTypesTopDownM f = go <=< f
290279 where
291280 go (TypeApp t1 t2) = TypeApp <$> (f t1 >>= go) <*> (f t2 >>= go)
292− go (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym name <$> mapM (go <=< f) tys
293281 go (ForAll arg ty sco) = ForAll arg <$> (f ty >>= go) <*> pure sco
294282 go (ConstrainedType cs ty) = ConstrainedType <$> mapM (sndM (mapM (go <=< f))) cs <*> (f ty >>= go)
295283 go (RCons name ty rest) = RCons name <$> (f ty >>= go) <*> (f rest >>= go)
@@ -303,7 +291,6 @@ everythingOnTypes :: (r -> r -> r) -> (Type -> r) -> Type -> r
303291everythingOnTypes (<>) f = go
304292 where
305293 go t@(TypeApp t1 t2) = f t <> go t1 <> go t2
306− go t@(SaturatedTypeSynonym _ tys) = foldl (<>) (f t) (map go tys)
307294 go t@(ForAll _ ty _) = f t <> go ty
308295 go t@(ConstrainedType cs ty) = foldl (<>) (f t) (map go $ concatMap snd cs) <> go ty
309296 go t@(RCons _ ty rest) = f t <> go ty <> go rest
@@ -318,7 +305,6 @@ everythingWithContextOnTypes s0 r0 (<>) f = go' s0
318305 where
319306 go' s t = let (s', r) = f s t in r <> go s' t
320307 go s (TypeApp t1 t2) = go' s t1 <> go' s t2
321− go s (SaturatedTypeSynonym _ tys) = foldl (<>) r0 (map (go' s) tys)
322308 go s (ForAll _ ty _) = go' s ty
323309 go s (ConstrainedType cs ty) = foldl (<>) r0 (map (go' s) $ concatMap snd cs) <> go' s ty
324310 go s (RCons _ ty rest) = go' s ty <> go' s rest
src/System/IO/UTF8.hsnew file+9
@@ -0,0 +1,9 @@
1+module System.IO.UTF8
2+where
3+import System.IO (hGetContents, hSetEncoding, openFile, utf8, IOMode (..))
4+
5+readUTF8File :: FilePath -> IO String
6+readUTF8File inFile = do
7+ h <- openFile inFile ReadMode
8+ hSetEncoding h utf8
9+ hGetContents h
stack-lts-3.yaml+1−1
@@ -2,4 +2,4 @@ flags: {}
22packages:
33- '.'
44extra-deps:
5−resolver: lts-3.4
5+resolver: lts-3.6
stack-nightly.yaml+1−1
@@ -2,4 +2,4 @@ flags: {}
22packages:
33- '.'
44extra-deps:
5−resolver: nightly-2015-09-09
5+resolver: nightly-2015-09-29
tests/Main.hs+4−3
@@ -66,6 +66,7 @@ import System.Exit
6666import System.Process
6767import System.FilePath
6868import System.Directory
69+import System.IO.UTF8
6970import qualified System.Info
7071import qualified System.FilePath.Glob as Glob
7172
@@ -97,7 +98,7 @@ makeActions foreigns = (P.buildMakeActions modulesDir (error "makeActions: input
9798
9899readInput :: [FilePath] -> IO [(FilePath, String)]
99100readInput inputFiles = forM inputFiles $ \inputFile -> do
100− text <- readFile inputFile
101+ text <- readUTF8File inputFile
101102 return (inputFile, text)
102103
103104type TestM = WriterT [(FilePath, String)] IO
@@ -157,7 +158,7 @@ assertDoesNotCompile inputFiles foreigns = do
157158
158159 where
159160 getShouldFailWith =
160− readFile
161+ readUTF8File
161162 >>> liftIO
162163 >>> fmap ( lines
163164 >>> mapMaybe (stripPrefix "-- @shouldFailWith ")
@@ -184,7 +185,7 @@ main = do
184185 supportPurs <- supportFiles "purs"
185186 supportJS <- supportFiles "js"
186187
187− foreignFiles <- forM supportJS (\f -> (f,) <$> readFile f)
188+ foreignFiles <- forM supportJS (\f -> (f,) <$> readUTF8File f)
188189 Right (foreigns, _) <- runExceptT $ runWriterT $ P.parseForeignModulesFromFiles foreignFiles
189190
190191 let passing = cwd </> "examples" </> "passing"