git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
Merge branch 'master' into pure11
commit5962d9f7e6ff34bfb9d9c7a598b7449f027f9071 authorAndy Arvanitis <andyarvanitis@gmail.com> dateSun 17 Apr 2016, 11:50 (11 years ago) parentc7b74128bab509
55 files changed+936−244
examples/passing/2018.purs+25 examples/passing/CaseInputWildcard.purs+18 examples/passing/DctorOperatorAlias.purs+5 examples/passing/IfWildcard.purs+19 examples/passing/TypeOperators.purs+34 psc-ide-server/Main.hs+1−1 psc-ide-server/PROTOCOL.md+24 psc/Main.hs+1−2 psci/PSCi.hs+2−1 purescript.cabal+7−1 src/Language/PureScript/AST/Declarations.hs+23−1 src/Language/PureScript/AST/Exported.hs+4−1 src/Language/PureScript/CoreFn/Desugar.hs+7−5 src/Language/PureScript/Docs/Render.hs+10−8 src/Language/PureScript/Docs/Types.hs+2−2 src/Language/PureScript/Errors.hs+30−2 psc/JSON.hs → src/Language/PureScript/Errors/JSON.hs+7−7 src/Language/PureScript/Externs.hs+2−1 src/Language/PureScript/Ide.hs+3−2 src/Language/PureScript/Ide/Command.hs+5−1 src/Language/PureScript/Ide/Error.hs+12−6 src/Language/PureScript/Ide/Imports.hs+2−2 src/Language/PureScript/Ide/Rebuild.hs src/Language/PureScript/Ide/State.hs+4 src/Language/PureScript/Ide/Types.hs+3 src/Language/PureScript/Linter/Imports.hs+9−2 src/Language/PureScript/Make.hs+45−22 src/Language/PureScript/ModuleDependencies.hs+37−25 src/Language/PureScript/Parser/Declarations.hs+6−4 src/Language/PureScript/Parser/Types.hs+6−2 src/Language/PureScript/Sugar/Names.hs+56−5 src/Language/PureScript/Sugar/Names/Env.hs+22−3 src/Language/PureScript/Sugar/Names/Exports.hs+38−6 src/Language/PureScript/Sugar/Names/Imports.hs+11−2 src/Language/PureScript/Sugar/ObjectWildcards.hs+24−7 src/Language/PureScript/Sugar/Operators.hs+175−42 src/Language/PureScript/Sugar/Operators/Binders.hs+14−30 src/Language/PureScript/Sugar/Operators/Common.hs+31 src/Language/PureScript/Sugar/Operators/Expr.hs+27−31 src/Language/PureScript/Sugar/Operators/Types.hs+28 src/Language/PureScript/TypeChecker.hs+10−12 src/Language/PureScript/TypeChecker/Kinds.hs+1−1 src/Language/PureScript/TypeChecker/Types.hs+1−1 src/Language/PureScript/Types.hs+34 tests/Language/PureScript/Ide/Integration.hs+14 tests/Language/PureScript/Ide/RebuildSpec.hs+62 tests/Main.hs+5 tests/TestDocs.hs+6−6 tests/support/pscide/src/RebuildSpecDep.purs+3 tests/support/pscide/src/RebuildSpecSingleModule.fail+3 tests/support/pscide/src/RebuildSpecSingleModule.purs+4 tests/support/pscide/src/RebuildSpecWithDeps.purs+5 tests/support/pscide/src/RebuildSpecWithForeign.js+3 tests/support/pscide/src/RebuildSpecWithForeign.purs+3 tests/support/pscide/src/RebuildSpecWithMissingForeign.fail+3
examples/passing/2018.pursnew file+25
@@ -0,0 +1,25 @@
1+module B where
2+
3+ data Foo = X | Y
4+
5+module A where
6+
7+ import B as Main
8+
9+ -- Prior to the 2018 fix this would be detected as a cycle between A and Main.
10+ foo ∷ Main.Foo → Main.Foo
11+ foo x = x
12+
13+module Main where
14+
15+import Prelude
16+import A (foo)
17+import B (Foo(..))
18+import Control.Monad.Eff (Eff)
19+import Control.Monad.Eff.Console (CONSOLE, log)
20+
21+main :: forall e. Eff (console :: CONSOLE | e) Unit
22+main = do
23+ let tmp = foo X
24+ log "Done"
25+
examples/passing/CaseInputWildcard.pursnew file+18
@@ -0,0 +1,18 @@
1+module Main where
2+
3+import Prelude
4+import Control.Monad.Eff (Eff)
5+import Control.Monad.Eff.Console (log, CONSOLE)
6+
7+data Foo = X | Y
8+
9+what ∷ Foo → Int → Boolean → Foo
10+what x = case _, x, _ of
11+ 0, X, true → X
12+ 0, Y, true → X
13+ _, _, _ → Y
14+
15+main :: forall e. Eff (console :: CONSOLE | e) Unit
16+main = do
17+ let tmp = what Y 0 true
18+ log "Done"
examples/passing/DctorOperatorAlias.purs+5
@@ -11,9 +11,14 @@ module Main where
1111 import Control.Monad.Eff.Console (CONSOLE, log)
1212 import Test.Assert (ASSERT, assert')
1313 import Data.List (List(..), (:))
14+ import Data.List as L
1415
16+ -- unqualified
1517 infixl 6 Cons as !
1618
19+ -- qualified
20+ infixl 6 L.Cons as !!
21+
1722 get1 ∷ ∀ a. a → List a → a
1823 get1 y xs = case xs of
1924 _ : x : _ → x
examples/passing/IfWildcard.pursnew file+19
@@ -0,0 +1,19 @@
1+module Main where
2+
3+import Prelude
4+import Control.Monad.Eff (Eff)
5+import Control.Monad.Eff.Console (log, CONSOLE)
6+
7+data Foo = X | Y
8+
9+cond ∷ ∀ a. Boolean → a → a → a
10+cond = if _ then _ else _
11+
12+what ∷ Boolean → Foo
13+what = if _ then X else Y
14+
15+main :: forall e. Eff (console :: CONSOLE | e) Unit
16+main = do
17+ let tmp1 = what true
18+ tmp2 = cond true 0 1
19+ log "Done"
examples/passing/TypeOperators.pursnew file+34
@@ -0,0 +1,34 @@
1+module A
2+ ( Tuple(..)
3+ , type (/\)
4+ , (/\)
5+ , Natural
6+ , type (~>)
7+ ) where
8+
9+ data Tuple a b = Tuple a b
10+
11+ infixl 6 Tuple as /\
12+ infixl 6 type Tuple as /\
13+
14+ type Natural f g = ∀ a. f a → g a
15+
16+ infixr 0 type Natural as ~>
17+
18+ tup ∷ ∀ a b. a → b → b /\ a
19+ tup a b = b /\ a
20+
21+ tupX ∷ ∀ a b c. a /\ b /\ c → c
22+ tupX (a /\ b /\ c) = c
23+
24+module Main where
25+
26+ import A (type (~>), type (/\), (/\))
27+
28+ natty ∷ ∀ f. f ~> f
29+ natty x = x
30+
31+ swap ∷ ∀ a b. a /\ b → b /\ a
32+ swap (a /\ b) = b /\ a
33+
34+ main = Control.Monad.Eff.Console.log "Done"
psc-ide-server/Main.hs+1−1
@@ -125,7 +125,7 @@ startServer port env = withSocketsDo $ do
125125 case decodeT cmd of
126126 Just cmd' -> do
127127 result <- runExceptT (handleCommand cmd')
128− $(logDebug) ("Answer was: " <> T.pack (show result))
128+ -- $(logDebug) ("Answer was: " <> T.pack (show result))
129129 liftIO (hFlush stdout)
130130 case result of
131131 -- What function can I use to clean this up?
psc-ide-server/PROTOCOL.md+24
@@ -240,6 +240,30 @@ Example:
240240}
241241```
242242
243+### Rebuild
244+
245+The `rebuild` command provides a fast rebuild for a single module. It doesn't
246+recompile the entire project though. All the modules dependencies need to be
247+loaded.
248+
249+Arguments:
250+- `file :: String` the path to the module to rebuild
251+
252+```json
253+{
254+ "command": "rebuild",
255+ "params": {
256+ "file": "/path/to/file.purs"
257+ }
258+}
259+```
260+
261+**Result**
262+
263+In the Success case you get a list of warnings in the compilers json format.
264+
265+In the Error case you get the errors in the compilers json format
266+
243267### Pursuit
244268The `pursuit` command looks up the packages/completions for a given identifier from Pursuit.
245269
psc/Main.hs+1−2
@@ -28,8 +28,7 @@ import qualified Language.PureScript as P
2828import qualified Paths_purescript as Paths
2929
3030import Language.PureScript.Make
31−
32−import JSON
31+import Language.PureScript.Errors.JSON
3332
3433data PSCMakeOptions = PSCMakeOptions
3534 { pscmInput :: [FilePath]
psci/PSCi.hs+2−1
@@ -253,8 +253,9 @@ handleShowImportedModules = do
253253
254254 showRef :: P.DeclarationRef -> String
255255 showRef (P.TypeRef pn dctors) = N.runProperName pn ++ "(" ++ maybe ".." (commaList . map N.runProperName) dctors ++ ")"
256+ showRef (P.TypeOpRef ident) = "type (" ++ N.runIdent ident ++ ")"
256257 showRef (P.ValueRef ident) = N.runIdent ident
257− showRef (P.TypeClassRef pn) = N.runProperName pn
258+ showRef (P.TypeClassRef pn) = "class " ++ N.runProperName pn
258259 showRef (P.ProperRef pn) = pn
259260 showRef (P.TypeInstanceRef ident) = N.runIdent ident
260261 showRef (P.ModuleRef name) = "module " ++ N.runModuleName name
purescript.cabal+7−1
@@ -37,6 +37,8 @@ extra-source-files: examples/passing/*.purs
3737 , tests/support/flattened/*.js
3838 , tests/support/psci/*.purs
3939 , tests/support/pscide/src/*.purs
40+ , tests/support/pscide/src/*.js
41+ , tests/support/pscide/src/*.fail
4042 , stack.yaml
4143 , stack-lts-5.yaml
4244 , stack-nightly.yaml
@@ -143,6 +145,7 @@ library
143145 Language.PureScript.Comments
144146 Language.PureScript.Environment
145147 Language.PureScript.Errors
148+ Language.PureScript.Errors.JSON
146149 Language.PureScript.Kinds
147150 Language.PureScript.Linter
148151 Language.PureScript.Linter.Exhaustive
@@ -179,6 +182,7 @@ library
179182 Language.PureScript.Sugar.Operators.Common
180183 Language.PureScript.Sugar.Operators.Expr
181184 Language.PureScript.Sugar.Operators.Binders
185+ Language.PureScript.Sugar.Operators.Types
182186 Language.PureScript.Sugar.TypeClasses
183187 Language.PureScript.Sugar.TypeClasses.Deriving
184188 Language.PureScript.Sugar.TypeDeclarations
@@ -230,6 +234,7 @@ library
230234 Language.PureScript.Ide.Reexports
231235 Language.PureScript.Ide.Imports
232236 Language.PureScript.Ide.Util
237+ Language.PureScript.Ide.Rebuild
233238
234239 Control.Monad.Logger
235240 Control.Monad.Supply
@@ -253,7 +258,7 @@ executable psc
253258 main-is: Main.hs
254259 buildable: True
255260 hs-source-dirs: psc
256− other-modules: JSON, Paths_purescript
261+ other-modules: Paths_purescript
257262 ghc-options: -Wall -O2 -fno-warn-unused-do-bind -threaded -rtsopts "-with-rtsopts=-N"
258263
259264executable psci
@@ -397,6 +402,7 @@ test-suite tests
397402 Language.PureScript.Ide.Imports.IntegrationSpec
398403 Language.PureScript.Ide.Integration
399404 Language.PureScript.Ide.MatcherSpec
405+ Language.PureScript.Ide.RebuildSpec
400406 Language.PureScript.Ide.ReexportsSpec
401407 Language.PureScript.IdeSpec
402408 PSCi.Completion
src/Language/PureScript/AST/Declarations.hs+23−1
@@ -62,6 +62,10 @@ data DeclarationRef
6262 --
6363 = TypeRef (ProperName 'TypeName) (Maybe [ProperName 'ConstructorName])
6464 -- |
65+ -- A type operator
66+ --
67+ | TypeOpRef Ident
68+ -- |
6569 -- A value
6670 --
6771 | ValueRef Ident
@@ -89,6 +93,7 @@ data DeclarationRef
8993
9094instance Eq DeclarationRef where
9195 (TypeRef name dctors) == (TypeRef name' dctors') = name == name' && dctors == dctors'
96+ (TypeOpRef name) == (TypeOpRef name') = name == name'
9297 (ValueRef name) == (ValueRef name') = name == name'
9398 (TypeClassRef name) == (TypeClassRef name') = name == name'
9499 (TypeInstanceRef name) == (TypeInstanceRef name') = name == name'
@@ -190,7 +195,7 @@ data Declaration
190195 -- |
191196 -- A fixity declaration (fixity data, operator name, value the operator is an alias for)
192197 --
193− | FixityDeclaration Fixity String (Maybe (Either (Qualified Ident) (Qualified (ProperName 'ConstructorName))))
198+ | FixityDeclaration Fixity String (Maybe (Qualified FixityAlias))
194199 -- |
195200 -- A module import (module name, qualified/unqualified/hiding, optional "qualified as" name)
196201 -- TODO: also a boolean specifying whether the old `qualified` syntax was used, so a warning can be raised in desugaring (remove for 0.9)
@@ -211,6 +216,22 @@ data Declaration
211216 | PositionedDeclaration SourceSpan [Comment] Declaration
212217 deriving (Show, Read)
213218
219+data FixityAlias
220+ = AliasValue Ident
221+ | AliasConstructor (ProperName 'ConstructorName)
222+ | AliasType (ProperName 'TypeName)
223+ deriving (Eq, Ord, Show, Read)
224+
225+foldFixityAlias
226+ :: (Ident -> a)
227+ -> (ProperName 'ConstructorName -> a)
228+ -> (ProperName 'TypeName -> a)
229+ -> FixityAlias
230+ -> a
231+foldFixityAlias f _ _ (AliasValue name) = f name
232+foldFixityAlias _ g _ (AliasConstructor name) = g name
233+foldFixityAlias _ _ h (AliasType name) = h name
234+
214235-- | The members of a type class instance declaration
215236data TypeInstanceBody
216237 -- | This is a derived instance
@@ -453,3 +474,4 @@ data DoNotationElement
453474
454475$(deriveJSON (defaultOptions { sumEncoding = ObjectWithSingleField }) ''DeclarationRef)
455476$(deriveJSON (defaultOptions { sumEncoding = ObjectWithSingleField }) ''ImportDeclarationType)
477+$(deriveJSON (defaultOptions { sumEncoding = ObjectWithSingleField }) ''FixityAlias)
src/Language/PureScript/AST/Exported.hs+4−1
@@ -127,7 +127,6 @@ isExported (Just exps) decl = any (matches decl) exps
127127 matches (TypeDeclaration ident _) (ValueRef ident') = ident == ident'
128128 matches (ValueDeclaration ident _ _ _) (ValueRef ident') = ident == ident'
129129 matches (ExternDeclaration ident _) (ValueRef ident') = ident == ident'
130− matches (FixityDeclaration _ name _) (ValueRef ident') = name == runIdent ident'
131130 matches (DataDeclaration _ ident _ _) (TypeRef ident' _) = ident == ident'
132131 matches (ExternDataDeclaration ident _) (TypeRef ident' _) = ident == ident'
133132 matches (TypeSynonymDeclaration ident _ _) (TypeRef ident' _) = ident == ident'
@@ -136,6 +135,10 @@ isExported (Just exps) decl = any (matches decl) exps
136135 matches (DataDeclaration _ ident _ _) (ProperRef ident') = runProperName ident == ident'
137136 matches (TypeClassDeclaration ident _ _ _) (ProperRef ident') = runProperName ident == ident'
138137
138+ matches (FixityDeclaration _ name (Just (Qualified _ (AliasValue _)))) (ValueRef ident') = name == runIdent ident'
139+ matches (FixityDeclaration _ name (Just (Qualified _ (AliasConstructor _)))) (ValueRef ident') = name == runIdent ident'
140+ matches (FixityDeclaration _ name (Just (Qualified _ (AliasType _)))) (TypeOpRef ident') = name == runIdent ident'
141+
139142 matches (PositionedDeclaration _ _ d) r = d `matches` r
140143 matches d (PositionedDeclarationRef _ _ r) = d `matches` r
141144 matches _ _ = False
src/Language/PureScript/CoreFn/Desugar.hs+7−5
@@ -72,10 +72,12 @@ moduleToCoreFn env (A.Module _ coms mn decls (Just exps)) =
7272 declToCoreFn ss _ (A.DataBindingGroupDeclaration ds) = concatMap (declToCoreFn ss []) ds
7373 declToCoreFn ss com (A.ValueDeclaration name _ _ (Right e)) =
7474 [NonRec (ssA ss) name (exprToCoreFn ss com Nothing e)]
75− declToCoreFn ss com (A.FixityDeclaration _ name (Just alias)) =
76− let meta = either getValueMeta (Just . getConstructorMeta) alias
77− alias' = either id (fmap properToIdent) alias
78− in [NonRec (ssA ss) (Op name) (Var (ss, com, Nothing, meta) alias')]
75+ declToCoreFn ss com (A.FixityDeclaration _ name (Just (Qualified mn' (A.AliasValue name')))) =
76+ let meta = getValueMeta (Qualified mn' name')
77+ in [NonRec (ssA ss) (Op name) (Var (ss, com, Nothing, meta) (Qualified mn' name'))]
78+ declToCoreFn ss com (A.FixityDeclaration _ name (Just (Qualified mn' (A.AliasConstructor name')))) =
79+ let meta = Just $ getConstructorMeta (Qualified mn' name')
80+ in [NonRec (ssA ss) (Op name) (Var (ss, com, Nothing, meta) (Qualified mn' (properToIdent name')))]
7981 declToCoreFn ss _ (A.BindingGroupDeclaration ds) =
8082 [Rec $ map (\(name, _, e) -> ((ssA ss, name), exprToCoreFn ss [] Nothing e)) ds]
8183 declToCoreFn ss com (A.TypeClassDeclaration name _ supers members) =
@@ -208,7 +210,7 @@ findQualModules decls =
208210 where
209211 fqDecls :: A.Declaration -> [(Ann, ModuleName)]
210212 fqDecls (A.TypeInstanceDeclaration _ _ q _ _) = getQual q
211− fqDecls (A.FixityDeclaration _ _ (Just eq)) = either getQual getQual eq
213+ fqDecls (A.FixityDeclaration _ _ (Just q)) = getQual q
212214 fqDecls _ = []
213215
214216 fqValues :: A.Expr -> [(Ann, ModuleName)]
src/Language/PureScript/Docs/Render.hs+10−8
@@ -61,20 +61,22 @@ renderDeclarationWithOptions opts Declaration{..} =
6161 AliasDeclaration for (P.Fixity associativity precedence) ->
6262 [ keywordFixity associativity
6363 , syntax $ show precedence
64− , ident $
65− either
66− (P.showQualified P.runIdent . dequalifyCurrentModule)
67− (P.showQualified P.runProperName . dequalifyCurrentModule)
68− for
64+ , ident $ renderAlias for
6965 , keyword "as"
7066 , ident . tail . init $ declTitle
7167 ]
7268
7369 where
7470 renderType' = renderTypeWithOptions opts
75− dequalifyCurrentModule (P.Qualified mn a)
76− | mn == currentModule opts = P.Qualified Nothing a
77− | otherwise = P.Qualified mn a
71+ renderAlias (P.Qualified mn alias)
72+ | mn == currentModule opts =
73+ P.foldFixityAlias P.runIdent P.runProperName P.runProperName alias
74+ | otherwise =
75+ P.foldFixityAlias
76+ (P.showQualified P.runIdent . P.Qualified mn)
77+ (P.showQualified P.runProperName . P.Qualified mn)
78+ (P.showQualified P.runProperName . P.Qualified mn)
79+ alias
7880
7981renderChildDeclaration :: ChildDeclaration -> RenderedCode
8082renderChildDeclaration = renderChildDeclarationWithOptions defaultRenderTypeOptions
src/Language/PureScript/Docs/Types.hs+2−2
@@ -133,7 +133,7 @@ data DeclarationInfo
133133 -- An operator alias declaration, with the member the alias is for and the
134134 -- operator's fixity.
135135 --
136− | AliasDeclaration (Either (P.Qualified P.Ident) (P.Qualified (P.ProperName 'P.ConstructorName))) P.Fixity
136+ | AliasDeclaration (P.Qualified P.FixityAlias) P.Fixity
137137 deriving (Show, Eq, Ord)
138138
139139declInfoToString :: DeclarationInfo -> String
@@ -411,7 +411,7 @@ asDeclarationInfo = do
411411 other ->
412412 throwCustomError (InvalidDeclarationType other)
413413
414−asAliasFor :: Parse e (Either (P.Qualified P.Ident) (P.Qualified (P.ProperName 'P.ConstructorName)))
414+asAliasFor :: Parse e (P.Qualified P.FixityAlias)
415415asAliasFor = fromAesonParser
416416
417417asTypeArguments :: Parse PackageError [(String, Maybe P.Kind)]
src/Language/PureScript/Errors.hs+30−2
@@ -46,6 +46,7 @@ data SimpleErrorMessage
4646 | UnnecessaryFFIModule ModuleName FilePath
4747 | MissingFFIImplementations ModuleName [Ident]
4848 | UnusedFFIImplementations ModuleName [Ident]
49+ | InvalidFFIIdentifier ModuleName String
4950 | CannotGetFileInfo FilePath
5051 | CannotReadFile FilePath
5152 | CannotWriteFile FilePath
@@ -59,12 +60,15 @@ data SimpleErrorMessage
5960 | OverlappingNamesInLet
6061 | UnknownModule ModuleName
6162 | UnknownType (Qualified (ProperName 'TypeName))
63+ | UnknownTypeOp (Qualified Ident)
6264 | UnknownTypeClass (Qualified (ProperName 'ClassName))
6365 | UnknownValue (Qualified Ident)
6466 | UnknownDataConstructor (Qualified (ProperName 'ConstructorName)) (Maybe (Qualified (ProperName 'ConstructorName)))
6567 | UnknownTypeConstructor (Qualified (ProperName 'TypeName))
6668 | UnknownImportType ModuleName (ProperName 'TypeName)
6769 | UnknownExportType (ProperName 'TypeName)
70+ | UnknownImportTypeOp ModuleName Ident
71+ | UnknownExportTypeOp Ident
6872 | UnknownImportTypeClass ModuleName (ProperName 'ClassName)
6973 | UnknownExportTypeClass (ProperName 'ClassName)
7074 | UnknownImportValue ModuleName Ident
@@ -83,6 +87,7 @@ data SimpleErrorMessage
8387 | DuplicateModuleName ModuleName
8488 | DuplicateClassExport (ProperName 'ClassName)
8589 | DuplicateValueExport Ident
90+ | DuplicateTypeOpExport Ident
8691 | DuplicateTypeArgument String
8792 | InvalidDoBind
8893 | InvalidDoLet
@@ -229,6 +234,7 @@ errorCode em = case unwrapErrorMessage em of
229234 UnnecessaryFFIModule{} -> "UnnecessaryFFIModule"
230235 MissingFFIImplementations{} -> "MissingFFIImplementations"
231236 UnusedFFIImplementations{} -> "UnusedFFIImplementations"
237+ InvalidFFIIdentifier{} -> "InvalidFFIIdentifier"
232238 CannotGetFileInfo{} -> "CannotGetFileInfo"
233239 CannotReadFile{} -> "CannotReadFile"
234240 CannotWriteFile{} -> "CannotWriteFile"
@@ -242,12 +248,15 @@ errorCode em = case unwrapErrorMessage em of
242248 OverlappingNamesInLet -> "OverlappingNamesInLet"
243249 UnknownModule{} -> "UnknownModule"
244250 UnknownType{} -> "UnknownType"
251+ UnknownTypeOp{} -> "UnknownTypeOp"
245252 UnknownTypeClass{} -> "UnknownTypeClass"
246253 UnknownValue{} -> "UnknownValue"
247254 UnknownDataConstructor{} -> "UnknownDataConstructor"
248255 UnknownTypeConstructor{} -> "UnknownTypeConstructor"
249256 UnknownImportType{} -> "UnknownImportType"
257+ UnknownImportTypeOp{} -> "UnknownImportTypeOp"
250258 UnknownExportType{} -> "UnknownExportType"
259+ UnknownExportTypeOp{} -> "UnknownExportTypeOp"
251260 UnknownImportTypeClass{} -> "UnknownImportTypeClass"
252261 UnknownExportTypeClass{} -> "UnknownExportTypeClass"
253262 UnknownImportValue{} -> "UnknownImportValue"
@@ -266,6 +275,7 @@ errorCode em = case unwrapErrorMessage em of
266275 DuplicateModuleName{} -> "DuplicateModuleName"
267276 DuplicateClassExport{} -> "DuplicateClassExport"
268277 DuplicateValueExport{} -> "DuplicateValueExport"
278+ DuplicateTypeOpExport{} -> "DuplicateTypeOpExport"
269279 DuplicateTypeArgument{} -> "DuplicateTypeArgument"
270280 InvalidDoBind -> "InvalidDoBind"
271281 InvalidDoLet -> "InvalidDoLet"
@@ -552,6 +562,13 @@ prettyPrintSingleError full level showWiki e = flip evalState defaultUnknownMap
552562 paras [ line $ "The following definitions in the foreign module for module " ++ runModuleName mn ++ " are unused: "
553563 , indent . paras $ map (line . runIdent) idents
554564 ]
565+ renderSimpleErrorMessage (InvalidFFIIdentifier mn ident) =
566+ paras [ line $ "In the FFI module for " ++ runModuleName mn ++ ":"
567+ , indent . paras $
568+ [ line $ "The identifier `" ++ ident ++ "` is not valid in PureScript."
569+ , line "Note that exported identifiers in FFI modules must be valid PureScript identifiers."
570+ ]
571+ ]
555572 renderSimpleErrorMessage (MultipleFFIModules mn paths) =
556573 paras [ line $ "Multiple foreign module implementations have been provided for module " ++ runModuleName mn ++ ": "
557574 , indent . paras $ map line paths
@@ -586,6 +603,8 @@ prettyPrintSingleError full level showWiki e = flip evalState defaultUnknownMap
586603 line $ "Unknown module " ++ runModuleName mn
587604 renderSimpleErrorMessage (UnknownType name) =
588605 line $ "Unknown type " ++ showQualified runProperName name
606+ renderSimpleErrorMessage (UnknownTypeOp name) =
607+ line $ "Unknown type operator " ++ showQualified showIdent name
589608 renderSimpleErrorMessage (UnknownTypeClass name) =
590609 line $ "Unknown type class " ++ showQualified runProperName name
591610 renderSimpleErrorMessage (UnknownValue name) =
@@ -600,6 +619,12 @@ prettyPrintSingleError full level showWiki e = flip evalState defaultUnknownMap
600619 ]
601620 renderSimpleErrorMessage (UnknownExportType name) =
602621 line $ "Cannot export unknown type " ++ runProperName name
622+ renderSimpleErrorMessage (UnknownImportTypeOp mn name) =
623+ paras [ line $ "Cannot import type operator " ++ showIdent name ++ " from module " ++ runModuleName mn
624+ , line "It either does not exist or the module does not export it."
625+ ]
626+ renderSimpleErrorMessage (UnknownExportTypeOp name) =
627+ line $ "Cannot export unknown type operator " ++ showIdent name
603628 renderSimpleErrorMessage (UnknownImportTypeClass mn name) =
604629 paras [ line $ "Cannot import type class " ++ runProperName name ++ " from module " ++ runModuleName mn
605630 , line "It either does not exist or the module does not export it."
@@ -649,6 +674,8 @@ prettyPrintSingleError full level showWiki e = flip evalState defaultUnknownMap
649674 line $ "Duplicate export declaration for type class " ++ runProperName nm
650675 renderSimpleErrorMessage (DuplicateValueExport nm) =
651676 line $ "Duplicate export declaration for value " ++ showIdent nm
677+ renderSimpleErrorMessage (DuplicateTypeOpExport nm) =
678+ line $ "Duplicate export declaration for type operator " ++ showIdent nm
652679 renderSimpleErrorMessage (CycleInDeclaration nm) =
653680 line $ "The value of " ++ showIdent nm ++ " is undefined here, so this reference is not allowed."
654681 renderSimpleErrorMessage (CycleInModules mns) =
@@ -987,8 +1014,8 @@ prettyPrintSingleError full level showWiki e = flip evalState defaultUnknownMap
9871014
9881015 renderSimpleErrorMessage (InvalidOperatorInBinder op fn) =
9891016 paras [ line $ "Operator " ++ showIdent op ++ " cannot be used in a pattern as it is an alias for function " ++ showIdent fn ++ "."
990− , line "Only aliases for data constructors may be used in patterns."
991− ]
1017+ , line "Only aliases for data constructors may be used in patterns."
1018+ ]
9921019
9931020 renderSimpleErrorMessage DeprecatedRequirePath =
9941021 line "The require-path option is deprecated and will be removed in PureScript 0.9."
@@ -1196,6 +1223,7 @@ prettyPrintRef :: DeclarationRef -> String
11961223prettyPrintRef (TypeRef pn Nothing) = runProperName pn ++ "(..)"
11971224prettyPrintRef (TypeRef pn (Just [])) = runProperName pn
11981225prettyPrintRef (TypeRef pn (Just dctors)) = runProperName pn ++ "(" ++ intercalate ", " (map runProperName dctors) ++ ")"
1226+prettyPrintRef (TypeOpRef ident) = "type " ++ showIdent ident
11991227prettyPrintRef (ValueRef ident) = showIdent ident
12001228prettyPrintRef (TypeClassRef pn) = "class " ++ runProperName pn
12011229prettyPrintRef (ProperRef name) = name
psc/JSON.hs → src/Language/PureScript/Errors/JSON.hsrenamed+7−7
@@ -1,6 +1,6 @@
11-----------------------------------------------------------------------------
22--
3−-- Module : Main
3+-- Module : Language.PureScript.Errors.JSON
44-- Copyright : (c) 2013-15 Phil Freeman, (c) 2014-15 Gary Burgess
55-- License : MIT (http://opensource.org/licenses/MIT)
66--
@@ -14,7 +14,7 @@
1414
1515{-# LANGUAGE TemplateHaskell #-}
1616
17−module JSON where
17+module Language.PureScript.Errors.JSON where
1818
1919import Prelude ()
2020import Prelude.Compat
@@ -28,9 +28,9 @@ data ErrorPosition = ErrorPosition
2828 , startColumn :: Int
2929 , endLine :: Int
3030 , endColumn :: Int
31− }
31+ } deriving (Show, Eq, Ord)
3232
33−data ErrorSuggestion = ErrorSuggestion { replacement :: String }
33+data ErrorSuggestion = ErrorSuggestion { replacement :: String } deriving (Show, Eq)
3434
3535data JSONError = JSONError
3636 { position :: Maybe ErrorPosition
@@ -40,12 +40,12 @@ data JSONError = JSONError
4040 , filename :: Maybe String
4141 , moduleName :: Maybe String
4242 , suggestion :: Maybe ErrorSuggestion
43− }
43+ } deriving (Show, Eq)
4444
4545data JSONResult = JSONResult
4646 { warnings :: [JSONError]
4747 , errors :: [JSONError]
48− }
48+ } deriving (Show, Eq)
4949
5050$(A.deriveJSON A.defaultOptions ''ErrorPosition)
5151$(A.deriveJSON A.defaultOptions ''JSONError)
@@ -64,7 +64,7 @@ toJSONError verbose level e =
6464 (P.wikiUri e)
6565 (P.spanName <$> sspan)
6666 (P.runModuleName <$> P.errorModule e)
67− (toSuggestion <$> (P.errorSuggestion $ P.unwrapErrorMessage e))
67+ (toSuggestion <$> P.errorSuggestion (P.unwrapErrorMessage e))
6868 where
6969 sspan :: Maybe P.SourceSpan
7070 sspan = P.errorSpan e
src/Language/PureScript/Externs.hs+2−1
@@ -73,7 +73,7 @@ data ExternsFixity = ExternsFixity
7373 -- | The operator symbol
7474 , efOperator :: String
7575 -- | The value the operator is an alias for
76− , efAlias :: Maybe (Either (Qualified Ident) (Qualified (ProperName 'ConstructorName)))
76+ , efAlias :: Maybe (Qualified FixityAlias)
7777 } deriving (Show, Read)
7878
7979-- | A type or value declaration appearing in an externs file
@@ -159,6 +159,7 @@ moduleToExternsFile (Module _ _ mn ds (Just exps)) env = ExternsFile{..}
159159 exportsOp :: DeclarationRef -> Bool
160160 exportsOp (PositionedDeclarationRef _ _ r) = exportsOp r
161161 exportsOp (ValueRef ident') = ident' == Op op
162+ exportsOp (TypeOpRef ident') = ident' == Op op
162163 exportsOp _ = False
163164 fixityDecl (PositionedDeclaration _ _ d) = fixityDecl d
164165 fixityDecl _ = Nothing
src/Language/PureScript/Ide.hs+3−2
@@ -53,11 +53,11 @@ import Language.PureScript.Ide.SourceFile
5353import Language.PureScript.Ide.State
5454import Language.PureScript.Ide.Types
5555import Language.PureScript.Ide.Util
56+import Language.PureScript.Ide.Rebuild
5657import System.Directory
5758import System.FilePath
5859import System.Exit
5960
60−
6161handleCommand :: (PscIde m, MonadLogger m, MonadError PscIdeError m) =>
6262 Command -> m Success
6363handleCommand (Load [] []) = loadAllModules
@@ -89,6 +89,8 @@ handleCommand (Import fp outfp filters (AddImportForIdentifier ident)) = do
8989 case rs of
9090 Right rs' -> answerRequest outfp rs'
9191 Left question -> pure $ CompletionResult (mapMaybe completionFromMatch question)
92+handleCommand (Rebuild file) =
93+ rebuildFile file
9294handleCommand Cwd =
9395 TextResult . T.pack <$> liftIO getCurrentDirectory
9496handleCommand Quit = liftIO exitSuccess
@@ -238,4 +240,3 @@ filePathFromModule moduleName = do
238240 if ex
239241 then pure path
240242 else throwError (ModuleFileNotFound moduleName)
241−
src/Language/PureScript/Ide/Command.hs+5−1
@@ -63,6 +63,7 @@ data Command
6363 -- Import InputFile OutputFile
6464 | Import FilePath (Maybe FilePath) [Filter] ImportCommand
6565 | List { listType :: ListType }
66+ | Rebuild FilePath -- ^ Rebuild the specified file using the loaded externs
6667 | Cwd
6768 | Quit
6869
@@ -149,5 +150,8 @@ instance FromJSON Command where
149150 filters <- params .:? "filters"
150151 importCommand <- params .: "importCommand"
151152 pure $ Import fp out (fromMaybe [] filters) importCommand
153+ "rebuild" -> do
154+ params <- o .: "params"
155+ filePath <- params .: "file"
156+ return $ Rebuild filePath
152157 _ -> mzero
153−
src/Language/PureScript/Ide/Error.hs+12−6
@@ -20,6 +20,7 @@ module Language.PureScript.Ide.Error
2020import Data.Aeson
2121import Data.Monoid
2222import Data.Text (Text, pack)
23+import Language.PureScript.Errors.JSON
2324import Language.PureScript.Ide.Types (ModuleIdent)
2425import qualified Text.Parsec.Error as P
2526
@@ -31,9 +32,13 @@ data PscIdeError
3132 | ModuleNotFound ModuleIdent
3233 | ModuleFileNotFound ModuleIdent
3334 | ParseError P.ParseError ErrorMsg
34− deriving (Show, Eq)
35+ | RebuildError [JSONError]
3536
3637instance ToJSON PscIdeError where
38+ toJSON (RebuildError errs) = object
39+ [ "resultType" .= ("error" :: Text)
40+ , "result" .= errs
41+ ]
3742 toJSON err = object
3843 [ "resultType" .= ("error" :: Text)
3944 , "result" .= textError err
@@ -44,8 +49,9 @@ textError (GeneralError msg) = pack msg
4449textError (NotFound ident) = "Symbol '" <> ident <> "' not found."
4550textError (ModuleNotFound ident) = "Module '" <> ident <> "' not found."
4651textError (ModuleFileNotFound ident) = "Extern file for module " <> ident <>" could not be found"
47−textError (ParseError parseError msg) = pack $ msg <> ": " <> show (escape parseError)
48− where
49− -- escape newlines and other special chars so we can send the error over the socket as a single line
50− escape :: P.ParseError -> String
51− escape = show
52+textError (ParseError parseError msg) = let escape = show
53+ -- escape newlines and other special
54+ -- chars so we can send the error
55+ -- over the socket as a single line
56+ in pack $ msg <> ": " <> show (escape parseError)
57+textError (RebuildError err) = pack (show err)
src/Language/PureScript/Ide/Imports.hs+2−2
@@ -76,8 +76,8 @@ compImport (Import n i q) (Import n' i' q')
7676 | compImportType i i' /= EQ = compImportType i i'
7777 -- This means that for a stable sort, the first implicit import will stay
7878 -- the first implicit import
79− | P.isImplicit i && isNothing q = LT
80− | P.isImplicit i && isNothing q' = GT
79+ | not (P.isExplicit i) && isNothing q = LT
80+ | not (P.isExplicit i) && isNothing q' = GT
8181 | otherwise = compare n n'
8282
8383-- | Reads a file and returns the (lines before the imports, the imports, the
src/Language/PureScript/Ide/Rebuild.hsnew file

Binary file not shown.

src/Language/PureScript/Ide/State.hs+4
@@ -51,6 +51,10 @@ getExternFiles = do
5151 stateVar <- envStateVar <$> ask
5252 liftIO (externsFiles <$> readTVarIO stateVar)
5353
54+getExternFile :: (PscIde m) =>
55+ ModuleName -> m (Maybe ExternsFile)
56+getExternFile mn = M.lookup mn <$> getExternFiles
57+
5458getAllDecls :: (PscIde m) => m [ExternDecl]
5559getAllDecls = concat <$> getPscIdeState
5660
src/Language/PureScript/Ide/Types.hs+3
@@ -33,6 +33,7 @@ import Data.Maybe (maybeToList)
3333import Data.Text (Text (), pack, unpack)
3434import qualified Language.PureScript.AST.Declarations as D
3535import Language.PureScript.Externs
36+import qualified Language.PureScript.Errors.JSON as P
3637import qualified Language.PureScript.Names as N
3738import qualified Language.PureScript as P
3839
@@ -144,6 +145,7 @@ data Success =
144145 | PursuitResult [PursuitResponse]
145146 | ImportList [ModuleImport]
146147 | ModuleList [ModuleIdent]
148+ | RebuildSuccess [P.JSONError]
147149 deriving(Show, Eq)
148150
149151encodeSuccess :: (ToJSON a) => a -> Value
@@ -157,6 +159,7 @@ instance ToJSON Success where
157159 toJSON (PursuitResult resp) = encodeSuccess resp
158160 toJSON (ImportList decls) = encodeSuccess decls
159161 toJSON (ModuleList modules) = encodeSuccess modules
162+ toJSON (RebuildSuccess modules) = encodeSuccess modules
160163
161164newtype PursuitQuery = PursuitQuery Text
162165 deriving (Show, Eq)
src/Language/PureScript/Linter/Imports.hs+9−2
@@ -35,6 +35,7 @@ import qualified Language.PureScript.Constants as C
3535data Name
3636 = IdentName (Qualified Ident)
3737 | TyName (Qualified (ProperName 'TypeName))
38+ | TyOpName (Qualified Ident)
3839 | DctorName (Qualified (ProperName 'ConstructorName))
3940 | TyClassName (Qualified (ProperName 'ClassName))
4041 deriving (Eq, Show)
@@ -43,6 +44,10 @@ getIdentName :: Maybe ModuleName -> Name -> Maybe Ident
4344getIdentName q (IdentName (Qualified q' name)) | q == q' = Just name
4445getIdentName _ _ = Nothing
4546
47+getTypeOpName :: Maybe ModuleName -> Name -> Maybe Ident
48+getTypeOpName q (TyOpName (Qualified q' name)) | q == q' = Just name
49+getTypeOpName _ _ = Nothing
50+
4651getTypeName :: Maybe ModuleName -> Name -> Maybe (ProperName 'TypeName)
4752getTypeName q (TyName (Qualified q' name)) | q == q' = Just name
4853getTypeName _ _ = Nothing
@@ -190,7 +195,7 @@ lintImportDecl env mni qualifierName names declType allowImplicit =
190195 Just q ->
191196 let usedModuleNames = mapMaybe extractQualName names
192197 in unless (q `elem` usedModuleNames) unused
193− Hiding _ -> checkImplicit HidingImport
198+ Hiding _ -> unless allowImplicit (checkImplicit HidingImport)
194199 Explicit [] -> unused
195200 Explicit declrefs -> checkExplicit declrefs
196201
@@ -265,6 +270,7 @@ findUsedRefs env mni qualifierName names =
265270 let
266271 classRefs = TypeClassRef <$> mapMaybe (getClassName qualifierName) names
267272 valueRefs = ValueRef <$> mapMaybe (getIdentName qualifierName) names
273+ typeOpRefs = TypeOpRef <$> mapMaybe (getTypeOpName qualifierName) names
268274 types = mapMaybe (getTypeName qualifierName) names
269275 dctors = mapMaybe (matchDctor qualifierName) names
270276 typesWithDctors = reconstructTypeRefs dctors
@@ -272,7 +278,7 @@ findUsedRefs env mni qualifierName names =
272278 typesRefs
273279 = map (flip TypeRef (Just [])) typesWithoutDctors
274280 ++ map (\(ty, ds) -> TypeRef ty (Just ds)) (M.toList typesWithDctors)
275− in classRefs ++ typesRefs ++ valueRefs
281+ in classRefs ++ typeOpRefs ++ typesRefs ++ valueRefs
276282
277283 where
278284
@@ -309,6 +315,7 @@ matchName _ _ _ = Nothing
309315extractQualName :: Name -> Maybe ModuleName
310316extractQualName (IdentName (Qualified q _)) = q
311317extractQualName (TyName (Qualified q _)) = q
318+extractQualName (TyOpName (Qualified q _)) = q
312319extractQualName (TyClassName (Qualified q _)) = q
313320extractQualName (DctorName (Qualified q _)) = q
314321
src/Language/PureScript/Make.hs+45−22
@@ -14,6 +14,7 @@ module Language.PureScript.Make
1414 , ProgressMessage(..), renderProgressMessage
1515 , MakeActions(..)
1616 , Externs()
17+ , rebuildModule
1718 , make
1819
1920 -- * Implementation of Make API using files on disk
@@ -42,6 +43,7 @@ import Control.Concurrent.Lifted as C
4243
4344import Data.List (foldl', sort)
4445import Data.Maybe (fromMaybe, catMaybes, isJust)
46+import Data.Either (partitionEithers)
4547import Data.Time.Clock
4648import Data.String (fromString)
4749import Data.Foldable (for_)
@@ -146,6 +148,28 @@ data RebuildPolicy
146148 -- | Always rebuild this module
147149 | RebuildAlways deriving (Show, Read, Eq, Ord)
148150
151+-- | Rebuild a single module
152+rebuildModule :: forall m. (Monad m, MonadBaseControl IO m, MonadReader Options m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)
153+ => MakeActions m
154+ -> [ExternsFile]
155+ -> Module
156+ -> m ExternsFile
157+rebuildModule MakeActions{..} externs m@(Module _ _ moduleName _ _) = do
158+ progress $ CompilingModule moduleName
159+ let env = foldl' (flip applyExternsFileToEnvironment) initEnvironment externs
160+ lint m
161+ ((checked@(Module ss coms _ elaborated exps), env'), nextVar) <- runSupplyT 0 $ do
162+ [desugared] <- desugar externs [m]
163+ runCheck' env $ typeCheckModule desugared
164+ checkExhaustiveModule env' checked
165+ regrouped <- createBindingGroups moduleName . collapseBindingGroups $ elaborated
166+ let mod' = Module ss coms moduleName regrouped exps
167+ corefn = CF.moduleToCoreFn env' mod'
168+ [renamed] = renameInModules [corefn]
169+ exts = moduleToExternsFile mod' env'
170+ evalSupplyT nextVar . codegen renamed env' . BU8.toString . B.toStrict . encode $ exts
171+ return exts
172+
149173-- |
150174-- Compiles in "make" mode, compiling each module separately to a js files and an externs file
151175--
@@ -156,7 +180,7 @@ make :: forall m. (Monad m, MonadBaseControl IO m, MonadReader Options m, MonadE
156180 => MakeActions m
157181 -> [Module]
158182 -> m Environment
159−make MakeActions{..} ms = do
183+make ma@MakeActions{..} ms = do
160184 requirePath <- asks optionsRequirePath
161185 when (isJust requirePath) $ tell $ errorMessage DeprecatedRequirePath
162186
@@ -220,21 +244,7 @@ make MakeActions{..} ms = do
220244 _ -> True
221245
222246 let rebuild = do
223− (exts, warnings) <- listen $ do
224− progress $ CompilingModule moduleName
225− let env = foldl' (flip applyExternsFileToEnvironment) initEnvironment externs
226− lint m
227− ((checked@(Module ss coms _ elaborated exps), env'), nextVar) <- runSupplyT 0 $ do
228− [desugared] <- desugar externs [m]
229− runCheck' env $ typeCheckModule desugared
230− checkExhaustiveModule env' checked
231− regrouped <- createBindingGroups moduleName . collapseBindingGroups $ elaborated
232− let mod' = Module ss coms moduleName regrouped exps
233− corefn = CF.moduleToCoreFn env' mod'
234− [renamed] = renameInModules [corefn]
235− exts = moduleToExternsFile mod' env'
236− evalSupplyT nextVar . codegen renamed env' . BU8.toString . B.toStrict . encode $ exts
237− return exts
247+ (exts, warnings) <- listen $ rebuildModule ma externs m
238248 markComplete (Just (warnings, exts)) Nothing
239249
240250 if shouldRebuild
@@ -417,11 +427,10 @@ checkForeignDecls m path = do
417427 js <- either (errorParsingModule . Bundle.UnableToParseModule) pure $ JS.parse jsStr path
418428
419429 foreignIdentsStrs <- either errorParsingModule pure $ getExps js
420− let foreignIdents =
421− either
422− (internalError . ("checkForeignDecls: unexpected idents: " ++) . show)
423− S.fromList
424− (traverse parseIdent foreignIdentsStrs)
430+ foreignIdents <- either
431+ errorInvalidForeignIdentifiers
432+ (pure . S.fromList)
433+ (parseIdents foreignIdentsStrs)
425434 let importedIdents = S.fromList $ map fst (CF.moduleForeign m)
426435
427436 let unusedFFI = foreignIdents S.\\ importedIdents
@@ -443,10 +452,24 @@ checkForeignDecls m path = do
443452 getExps :: JS.JSAST -> Either Bundle.ErrorMessage [String]
444453 getExps = Bundle.getExportedIdentifiers (runModuleName mname)
445454
455+ errorInvalidForeignIdentifiers :: [String] -> SupplyT Make a
456+ errorInvalidForeignIdentifiers =
457+ throwError . mconcat . map (errorMessage . InvalidFFIIdentifier mname)
458+
459+ parseIdents :: [String] -> Either [String] [Ident]
460+ parseIdents strs =
461+ case partitionEithers (map parseIdent strs) of
462+ ([], idents) ->
463+ Right idents
464+ (errs, _) ->
465+ Left errs
466+
446467 -- TODO: Handling for parenthesised operators should be removed after 0.9.
468+ -- We ignore the error message here, just being told it's an invalid
469+ -- identifier should be enough.
447470 parseIdent :: String -> Either String Ident
448471 parseIdent str = try str <|> try ("(" ++ str ++ ")")
449472 where
450− try s = either (Left . show) Right $ do
473+ try s = either (const (Left str)) Right $ do
451474 ts <- PSParser.lex "" s
452475 PSParser.runTokenParser "" (PSParser.parseIdent <* Parsec.eof) ts
src/Language/PureScript/ModuleDependencies.hs+37−25
@@ -1,19 +1,8 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.ModuleDependencies
4−-- Copyright : (c) 2013-15 Phil Freeman, (c) 2014-15 Gary Burgess
5−-- License : MIT (http://opensource.org/licenses/MIT)
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- | Provides the ability to sort modules based on module dependencies
12−--
13−-----------------------------------------------------------------------------
14−
151{-# LANGUAGE FlexibleContexts #-}
162
3+-- |
4+-- Provides the ability to sort modules based on module dependencies
5+--
176module Language.PureScript.ModuleDependencies (
187 sortModules,
198 ModuleGraph
@@ -40,7 +29,7 @@ type ModuleGraph = [(ModuleName, [ModuleName])]
4029--
4130sortModules :: (MonadError MultipleErrors m) => [Module] -> m ([Module], ModuleGraph)
4231sortModules ms = do
43− let verts = map (\m@(Module _ _ _ ds _) -> (m, getModuleName m, nub (concatMap usedModules ds))) ms
32+ let verts = map goModule ms
4433 ms' <- mapM toModule $ stronglyConnComp verts
4534 let (graph, fromVertex, toVertex) = graphFromEdges verts
4635 moduleGraph = do (_, mn, _) <- verts
@@ -49,30 +38,53 @@ sortModules ms = do
4938 toKey i = case fromVertex i of (_, key, _) -> key
5039 return (mn, filter (/= mn) (map toKey deps))
5140 return (ms', moduleGraph)
41+ where
42+ goModule :: Module -> (Module, ModuleName, [ModuleName])
43+ goModule m@(Module _ _ _ ds _) =
44+ let ams = concatMap extractQualAs ds
45+ in (m, getModuleName m, nub (concatMap (usedModules ams) ds))
46+
47+ -- Extract module names that have been brought into scope by an `as` import.
48+ extractQualAs :: Declaration -> [ModuleName]
49+ extractQualAs (PositionedDeclaration _ _ d) = extractQualAs d
50+ extractQualAs (ImportDeclaration _ _ (Just am) _) = [am]
51+ extractQualAs _ = []
5252
5353-- |
54−-- Calculate a list of used modules based on explicit imports and qualified names
54+-- Calculate a list of used modules based on explicit imports and qualified
55+-- names. `ams` is a list of `ModuleNames` that refer to names brought into
56+-- scope by importing with `as` - this ensures that when building the list we
57+-- don't inadvertantly assume a dependency on an actual module, if there is a
58+-- module that has the same name as the qualified import.
5559--
56−usedModules :: Declaration -> [ModuleName]
57−usedModules d =
60+usedModules :: [ModuleName] -> Declaration -> [ModuleName]
61+usedModules ams d =
5862 let (f, _, _, _, _) = everythingOnValues (++) forDecls forValues (const []) (const []) (const [])
5963 (g, _, _, _, _) = accumTypes (everythingOnTypes (++) forTypes)
6064 in nub (f d ++ g d)
6165 where
66+
6267 forDecls :: Declaration -> [ModuleName]
63− forDecls (ImportDeclaration mn _ _ _) = [mn]
64− forDecls (FixityDeclaration _ _ (Just (Left (Qualified (Just mn) _)))) = [mn]
65− forDecls (FixityDeclaration _ _ (Just (Right (Qualified (Just mn) _)))) = [mn]
66− forDecls (TypeInstanceDeclaration _ _ (Qualified (Just mn) _) _ _) = [mn]
68+ forDecls (ImportDeclaration mn _ _ _) =
69+ -- Regardless of whether an imported module is qualified we still need to
70+ -- take into account its import to build an accurate list of dependencies.
71+ [mn]
72+ forDecls (FixityDeclaration _ _ (Just (Qualified (Just mn) _)))
73+ | mn `notElem` ams = [mn]
74+ forDecls (TypeInstanceDeclaration _ _ (Qualified (Just mn) _) _ _)
75+ | mn `notElem` ams = [mn]
6776 forDecls _ = []
6877
6978 forValues :: Expr -> [ModuleName]
70− forValues (Var (Qualified (Just mn) _)) = [mn]
71− forValues (Constructor (Qualified (Just mn) _)) = [mn]
79+ forValues (Var (Qualified (Just mn) _))
80+ | mn `notElem` ams = [mn]
81+ forValues (Constructor (Qualified (Just mn) _))
82+ | mn `notElem` ams = [mn]
7283 forValues _ = []
7384
7485 forTypes :: Type -> [ModuleName]
75− forTypes (TypeConstructor (Qualified (Just mn) _)) = [mn]
86+ forTypes (TypeConstructor (Qualified (Just mn) _))
87+ | mn `notElem` ams = [mn]
7688 forTypes _ = []
7789
7890-- |
src/Language/PureScript/Parser/Declarations.hs+6−4
@@ -122,12 +122,13 @@ parseFixityDeclaration :: TokenParser Declaration
122122parseFixityDeclaration = do
123123 fixity <- parseFixity
124124 indented
125− alias <- P.optionMaybe $ aliased <* reserved "as"
125+ alias <- P.optionMaybe $ parseQualified aliased <* reserved "as"
126126 name <- symbol
127127 return $ FixityDeclaration fixity name alias
128128 where
129− aliased = (Left <$> parseQualified (Ident <$> identifier))
130− <|> (Right <$> parseQualified (ProperName <$> uname))
129+ aliased = (AliasValue . Ident <$> identifier)
130+ <|> (AliasConstructor <$> properName)
131+ <|> reserved "type" *> (AliasType <$> properName)
131132
132133parseImportDeclaration :: TokenParser Declaration
133134parseImportDeclaration = do
@@ -164,6 +165,7 @@ parseDeclarationRef =
164165 <|> parseProperRef
165166 <|> (TypeClassRef <$> (reserved "class" *> properName))
166167 <|> (ModuleRef <$> (indented *> reserved "module" *> moduleName))
168+ <|> (TypeOpRef <$> (indented *> reserved "type" *> parens (Op <$> symbol)))
167169 where
168170 parseProperRef = do
169171 name <- properName
@@ -483,7 +485,7 @@ parseConstructorBinder :: TokenParser Binder
483485parseConstructorBinder = ConstructorBinder <$> C.parseQualified C.properName <*> many (C.indented *> parseBinderNoParens)
484486
485487parseObjectBinder:: TokenParser Binder
486−parseObjectBinder= LiteralBinder <$> parseObjectLiteral (C.indented *> parseIdentifierAndBinder)
488+parseObjectBinder = LiteralBinder <$> parseObjectLiteral (C.indented *> parseIdentifierAndBinder)
487489
488490parseArrayBinder :: TokenParser Binder
489491parseArrayBinder = LiteralBinder <$> parseArrayLiteral (C.indented *> parseBinder)
src/Language/PureScript/Parser/Types.hs+6−2
@@ -8,6 +8,7 @@ module Language.PureScript.Parser.Types (
88import Control.Applicative
99import Control.Monad (when, unless)
1010
11+import Language.PureScript.Names
1112import Language.PureScript.Types
1213import Language.PureScript.Parser.Common
1314import Language.PureScript.Parser.Kinds
@@ -53,7 +54,7 @@ parseTypeAtom = indented *> P.choice
5354 , parseTypeConstructor
5455 -- This try is needed due to some unfortunate ambiguities between rows and kinded types
5556 , P.try (parens parseRow)
56− , parens parsePolyType
57+ , ParensInType <$> parens parsePolyType
5758 ]
5859
5960parseConstrainedType :: TokenParser Type
@@ -74,7 +75,10 @@ parseConstrainedType = do
7475parseAnyType :: TokenParser Type
7576parseAnyType = P.buildExpressionParser operators (buildPostfixParser postfixTable parseTypeAtom) P.<?> "type"
7677 where
77− operators = [ [ P.Infix (return TypeApp) P.AssocLeft ]
78+ operators = [ [ P.Infix (P.try (parseQualified (Op <$> symbol)) >>= \ident ->
79+ return (BinaryNoParensType (TypeOp ident))) P.AssocRight
80+ ]
81+ , [ P.Infix (return TypeApp) P.AssocLeft ]
7882 , [ P.Infix (rarrow >> return function) P.AssocRight ]
7983 ]
8084 postfixTable = [ \t -> KindedType t <$> (indented *> doubleColon *> parseKind)
src/Language/PureScript/Sugar/Names.hs+56−5
@@ -85,6 +85,12 @@ desugarImportsWithEnv externs modules = do
8585 forTyCon _ = Nothing
8686 toExportedType (PositionedDeclarationRef _ _ r) = toExportedType r
8787 toExportedType _ = Nothing
88+ exportedTypeOps :: [(Ident, ModuleName)]
89+ exportedTypeOps = mapMaybe toExportedTypeOp efExports
90+ where
91+ toExportedTypeOp (TypeOpRef ident) = Just (ident, efModuleName)
92+ toExportedTypeOp (PositionedDeclarationRef _ _ r) = toExportedTypeOp r
93+ toExportedTypeOp _ = Nothing
8894 exportedTypeClasses :: [(ProperName 'ClassName, ModuleName)]
8995 exportedTypeClasses = mapMaybe toExportedTypeClass efExports
9096 where
@@ -126,6 +132,7 @@ elaborateExports :: Exports -> Module -> Module
126132elaborateExports exps (Module ss coms mn decls refs) =
127133 Module ss coms mn decls $
128134 Just $ map (\(ctor, dctors) -> TypeRef ctor (Just dctors)) (my exportedTypes) ++
135+ map TypeOpRef (my exportedTypeOps) ++
129136 map TypeClassRef (my exportedTypeClasses) ++
130137 map ValueRef (my exportedValues) ++
131138 maybe [] (filter isModuleRef) refs
@@ -171,7 +178,15 @@ renameInModule env imports (Module ss coms mn decls exps) =
171178 updateDecl (pos, bound) (ExternDeclaration name ty) =
172179 (,) (pos, name : bound) <$> (ExternDeclaration name <$> updateTypesEverywhere pos ty)
173180 updateDecl (pos, bound) (FixityDeclaration fx name alias) =
174− (,) (pos, bound) <$> (FixityDeclaration fx name <$> traverse (eitherM (`updateValueName` pos) (`updateDataConstructorName` pos)) alias)
181+ (,) (pos, bound) <$> (FixityDeclaration fx name <$> traverse updateAlias alias)
182+ where
183+ updateAlias :: Qualified FixityAlias -> m (Qualified FixityAlias)
184+ updateAlias (Qualified mn' (AliasValue ident)) =
185+ fmap AliasValue <$> updateValueName (Qualified mn' ident) pos
186+ updateAlias (Qualified mn' (AliasConstructor ctor)) =
187+ fmap AliasConstructor <$> updateDataConstructorName (Qualified mn' ctor) pos
188+ updateAlias (Qualified mn' (AliasType ty)) =
189+ fmap AliasType <$> updateTypeName (Qualified mn' ty) pos
175190 updateDecl s d = return (s, d)
176191
177192 updateValue
@@ -231,6 +246,7 @@ renameInModule env imports (Module ss coms mn decls exps) =
231246 updateTypesEverywhere pos = everywhereOnTypesM updateType
232247 where
233248 updateType :: Type -> m Type
249+ updateType (TypeOp name) = TypeOp <$> updateTypeOpName name pos
234250 updateType (TypeConstructor name) = TypeConstructor <$> updateTypeName name pos
235251 updateType (ConstrainedType cs t) = ConstrainedType <$> updateConstraints pos cs <*> pure t
236252 updateType t = return t
@@ -242,22 +258,57 @@ renameInModule env imports (Module ss coms mn decls exps) =
242258 :: Qualified (ProperName 'TypeName)
243259 -> Maybe SourceSpan
244260 -> m (Qualified (ProperName 'TypeName))
245− updateTypeName = update UnknownType (importedTypes imports) (resolveType . exportedTypes) TyName (("type " ++) . runProperName)
261+ updateTypeName =
262+ update UnknownType
263+ (importedTypes imports)
264+ (resolveType . exportedTypes)
265+ TyName
266+ (("type " ++) . runProperName)
267+
268+ updateTypeOpName
269+ :: Qualified Ident
270+ -> Maybe SourceSpan
271+ -> m (Qualified Ident)
272+ updateTypeOpName =
273+ update
274+ UnknownTypeOp
275+ (importedTypeOps imports)
276+ (resolve . exportedTypeOps)
277+ TyOpName
278+ (("type operator" ++) . runIdent)
246279
247280 updateDataConstructorName
248281 :: Qualified (ProperName 'ConstructorName)
249282 -> Maybe SourceSpan
250283 -> m (Qualified (ProperName 'ConstructorName))
251− updateDataConstructorName = update (flip UnknownDataConstructor Nothing) (importedDataConstructors imports) (resolveDctor . exportedTypes) DctorName (("data constructor " ++) . runProperName)
284+ updateDataConstructorName =
285+ update
286+ (flip UnknownDataConstructor Nothing)
287+ (importedDataConstructors imports)
288+ (resolveDctor . exportedTypes)
289+ DctorName
290+ (("data constructor " ++) . runProperName)
252291
253292 updateClassName
254293 :: Qualified (ProperName 'ClassName)
255294 -> Maybe SourceSpan
256295 -> m (Qualified (ProperName 'ClassName))
257− updateClassName = update UnknownTypeClass (importedTypeClasses imports) (resolve . exportedTypeClasses) TyClassName (("class " ++) . runProperName)
296+ updateClassName =
297+ update
298+ UnknownTypeClass
299+ (importedTypeClasses imports)
300+ (resolve . exportedTypeClasses)
301+ TyClassName
302+ (("class " ++) . runProperName)
258303
259304 updateValueName :: Qualified Ident -> Maybe SourceSpan -> m (Qualified Ident)
260− updateValueName = update UnknownValue (importedValues imports) (resolve . exportedValues) IdentName (("value " ++) . runIdent)
305+ updateValueName =
306+ update
307+ UnknownValue
308+ (importedValues imports)
309+ (resolve . exportedValues)
310+ IdentName
311+ (("value " ++) . runIdent)
261312
262313 -- Used when performing an update to qualify values and classes with their
263314 -- module of original definition.
src/Language/PureScript/Sugar/Names/Env.hs+22−3
@@ -14,6 +14,7 @@ module Language.PureScript.Sugar.Names.Env
1414 , envModuleImports
1515 , envModuleExports
1616 , exportType
17+ , exportTypeOp
1718 , exportTypeClass
1819 , exportValue
1920 , getExports
@@ -70,6 +71,10 @@ data Imports = Imports
7071 --
7172 importedTypes :: M.Map (Qualified (ProperName 'TypeName)) [ImportRecord (ProperName 'TypeName)]
7273 -- |
74+ -- Local names for type operators within a module mapped to to their qualified names
75+ --
76+ , importedTypeOps :: M.Map (Qualified Ident) [ImportRecord Ident]
77+ -- |
7378 -- Local names for data constructors within a module mapped to to their qualified names
7479 --
7580 , importedDataConstructors :: M.Map (Qualified (ProperName 'ConstructorName)) [ImportRecord (ProperName 'ConstructorName)]
@@ -96,7 +101,7 @@ data Imports = Imports
96101-- An empty 'Imports' value.
97102--
98103nullImports :: Imports
99−nullImports = Imports M.empty M.empty M.empty M.empty S.empty S.empty
104+nullImports = Imports M.empty M.empty M.empty M.empty M.empty S.empty S.empty
100105
101106-- |
102107-- The exported declarations from a module.
@@ -109,6 +114,11 @@ data Exports = Exports
109114 --
110115 exportedTypes :: [((ProperName 'TypeName, [ProperName 'ConstructorName]), ModuleName)]
111116 -- |
117+ -- The type operators exported from each module along with the module they
118+ -- originally came from.
119+ --
120+ , exportedTypeOps :: [(Ident, ModuleName)]
121+ -- |
112122 -- The classes exported from each module along with the module they originally
113123 -- came from.
114124 --
@@ -124,7 +134,7 @@ data Exports = Exports
124134-- An empty 'Exports' value.
125135--
126136nullExports :: Exports
127−nullExports = Exports [] [] []
137+nullExports = Exports [] [] [] []
128138
129139-- |
130140-- The imports and exports for a collection of modules. The 'SourceSpan' is used
@@ -155,7 +165,7 @@ envModuleExports (_, _, exps) = exps
155165-- The exported types from the @Prim@ module
156166--
157167primExports :: Exports
158−primExports = Exports (mkTypeEntry `map` M.keys primTypes) (mkClassEntry `map` M.keys primClasses) []
168+primExports = Exports (mkTypeEntry `map` M.keys primTypes) [] (mkClassEntry `map` M.keys primClasses) []
159169 where
160170 mkTypeEntry (Qualified mn name) = ((name, []), fromJust mn)
161171 mkClassEntry (Qualified mn name) = (name, fromJust mn)
@@ -183,6 +193,15 @@ exportType exps name dctors mn = do
183193 when (any ((== coerceProperName dctor) . fst) exClasses) $ throwConflictError CtorConflictsWithClass dctor
184194 return $ exps { exportedTypes = nub $ ((name, dctors), mn) : exTypes' }
185195
196+-- |
197+-- Safely adds a type operator to some exports, returning an error if a
198+-- conflict occurs.
199+--
200+exportTypeOp :: (MonadError MultipleErrors m) => Exports -> Ident -> ModuleName -> m Exports
201+exportTypeOp exps name mn = do
202+ typeOps <- addExport DuplicateTypeOpExport name mn (exportedTypeOps exps)
203+ return $ exps { exportedTypeOps = typeOps }
204+
186205-- |
187206-- Safely adds a class to some exports, returning an error if a conflict occurs.
188207--
src/Language/PureScript/Sugar/Names/Exports.hs+38−6
@@ -47,6 +47,7 @@ findExportable (Module _ _ mn ds _) =
4747 updateExports exps (TypeSynonymDeclaration tn _ _) = exportType exps tn [] mn
4848 updateExports exps (ExternDataDeclaration tn _) = exportType exps tn [] mn
4949 updateExports exps (ValueDeclaration name _ _ _) = exportValue exps name mn
50+ updateExports exps (FixityDeclaration _ name (Just (Qualified _ (AliasType _)))) = exportTypeOp exps (Op name) mn
5051 updateExports exps (FixityDeclaration _ name (Just _)) = exportValue exps (Op name) mn
5152 updateExports exps (ExternDeclaration name _) = exportValue exps name mn
5253 updateExports exps (PositionedDeclaration pos _ d) = rethrowWithPosition pos $ updateExports exps d
@@ -70,6 +71,7 @@ resolveExports env mn imps exps refs =
7071 warnDupeRefs :: [DeclarationRef] -> m ()
7172 warnDupeRefs = traverse_ $ \case
7273 TypeRef name _ -> warnDupe $ "type " ++ runProperName name
74+ TypeOpRef name -> warnDupe $ "type operator " ++ runIdent name
7375 ValueRef name -> warnDupe $ "value " ++ runIdent name
7476 TypeClassRef name -> warnDupe $ "class " ++ runProperName name
7577 ModuleRef name -> warnDupe $ "module " ++ runModuleName name
@@ -89,22 +91,28 @@ resolveExports env mn imps exps refs =
8991 rethrowWithPosition pos $ elaborateModuleExports result r
9092 elaborateModuleExports result (ModuleRef name) | name == mn = do
9193 let types' = exportedTypes result ++ exportedTypes exps
94+ let typeOps' = exportedTypeOps result ++ exportedTypeOps exps
9295 let classes' = exportedTypeClasses result ++ exportedTypeClasses exps
9396 let values' = exportedValues result ++ exportedValues exps
94− return result { exportedTypes = types'
95− , exportedTypeClasses = classes'
96− , exportedValues = values' }
97+ return result
98+ { exportedTypes = types'
99+ , exportedTypeOps = typeOps'
100+ , exportedTypeClasses = classes'
101+ , exportedValues = values'
102+ }
97103 elaborateModuleExports result (ModuleRef name) = do
98104 let isPseudo = isPseudoModule name
99105 when (not isPseudo && not (isImportedModule name)) $
100106 throwError . errorMessage . UnknownExportModule $ name
101107 reTypes <- extract isPseudo name (("type " ++) . runProperName) (importedTypes imps)
108+ reTypeOps <- extract isPseudo name (("type operator " ++) . runIdent) (importedTypeOps imps)
102109 reDctors <- extract isPseudo name (("data constructor " ++) . runProperName) (importedDataConstructors imps)
103110 reClasses <- extract isPseudo name (("class " ++) . runProperName) (importedTypeClasses imps)
104111 reValues <- extract isPseudo name (("value " ++) . runIdent) (importedValues imps)
105112 result' <- foldM (\exps' ((tctor, dctors), mn') -> exportType exps' tctor dctors mn') result (resolveTypeExports reTypes reDctors)
106− result'' <- foldM (uncurry . exportTypeClass) result' (map resolveClass reClasses)
107− foldM (uncurry . exportValue) result'' (map resolveValue reValues)
113+ result'' <- foldM (uncurry . exportTypeOp) result' (map resolveTypeOp reTypeOps)
114+ result''' <- foldM (uncurry . exportTypeClass) result'' (map resolveClass reClasses)
115+ foldM (uncurry . exportValue) result''' (map resolveValue reValues)
108116 elaborateModuleExports result _ = return result
109117
110118 -- Extracts a list of values for a module based on a lookup table. If the
@@ -163,6 +171,11 @@ resolveExports env mn imps exps refs =
163171 return ((name, relevantDctors `intersect` dctors'), mnOrig)
164172 go (Qualified Nothing _) = internalError "Unqualified value in resolveTypeExports"
165173
174+ -- Looks up an imported type operator and re-qualifies it with the original
175+ -- module it came from.
176+ resolveTypeOp :: Qualified Ident -> (Ident, ModuleName)
177+ resolveTypeOp ident = splitQual $ fromMaybe (internalError "Missing value in resolveValue") $
178+ resolve exportedTypeOps ident
166179
167180 -- Looks up an imported class and re-qualifies it with the original module it
168181 -- came from.
@@ -202,9 +215,15 @@ filterModule
202215 -> m Exports
203216filterModule mn exps refs = do
204217 types <- foldM (filterTypes $ exportedTypes exps) [] refs
218+ typeOps <- foldM (filterTypeOps $ exportedTypeOps exps) [] refs
205219 values <- foldM (filterValues $ exportedValues exps) [] refs
206220 classes <- foldM (filterClasses $ exportedTypeClasses exps) [] refs
207− return exps { exportedTypes = types , exportedTypeClasses = classes , exportedValues = values }
221+ return $ exps
222+ { exportedTypes = types
223+ , exportedTypeOps = typeOps
224+ , exportedTypeClasses = classes
225+ , exportedValues = values
226+ }
208227
209228 where
210229
@@ -241,6 +260,19 @@ filterModule mn exps refs = do
241260 unless (name `elem` exps') $
242261 throwError . errorMessage $ UnknownExportDataConstructor tcon name
243262
263+ -- Takes a list of all the exportable type operators, the accumulated list of
264+ -- filtered exports, and a `DeclarationRef` for an explicit export. When the
265+ -- ref refers to a value in the list of exportable values, the value is
266+ -- included in the result.
267+ filterTypeOps :: [(Ident, ModuleName)] -> [(Ident, ModuleName)] -> DeclarationRef -> m [(Ident, ModuleName)]
268+ filterTypeOps exps' result (PositionedDeclarationRef pos _ r) =
269+ rethrowWithPosition pos $ filterTypeOps exps' result r
270+ filterTypeOps exps' result (TypeOpRef name) =
271+ if (name, mn) `elem` exps'
272+ then return $ (name, mn) : result
273+ else throwError . errorMessage . UnknownExportTypeOp $ name
274+ filterTypeOps _ result _ = return result
275+
244276 -- Takes a list of all the exportable classes, the accumulated list of
245277 -- filtered exports, and a `DeclarationRef` for an explicit export. When the
246278 -- ref refers to a class in the list of exportable classes, the class is
src/Language/PureScript/Sugar/Names/Imports.hs+11−2
@@ -97,6 +97,7 @@ resolveImports env (Module ss coms currentModule decls exps) =
9797 let imports' = M.map (map (\(ss', dt, mmn) -> (ss', Just dt, mmn))) imports
9898 scope = M.insert currentModule [(Nothing, Nothing, Nothing)] imports'
9999 resolved <- foldM (resolveModuleImport env) nullImports (M.toList scope)
100+
100101 return (Module ss coms currentModule decls' exps, resolved)
101102
102103 where
@@ -118,6 +119,7 @@ resolveImports env (Module ss coms currentModule decls exps) =
118119 warnDupeRefs :: Maybe SourceSpan -> [DeclarationRef] -> m ()
119120 warnDupeRefs pos = traverse_ $ \case
120121 TypeRef name _ -> warnDupe pos $ "type " ++ runProperName name
122+ TypeOpRef name -> warnDupe pos $ "type operator " ++ runIdent name
121123 ValueRef name -> warnDupe pos $ "value " ++ runIdent name
122124 TypeClassRef name -> warnDupe pos $ "class " ++ runProperName name
123125 ModuleRef name -> warnDupe pos $ "module " ++ runModuleName name
@@ -203,6 +205,7 @@ resolveImport importModule exps imps impQual = resolveByType
203205 imps' <- checkRefs True refs >> importAll (importNonHidden refs)
204206 let isEmptyImport
205207 = M.null (importedTypes imps')
208+ && M.null (importedTypeOps imps')
206209 && M.null (importedDataConstructors imps')
207210 && M.null (importedTypeClasses imps')
208211 && M.null (importedValues imps')
@@ -221,6 +224,8 @@ resolveImport importModule exps imps impQual = resolveByType
221224 checkImportExists UnknownImportType ((fst . fst) `map` exportedTypes exps) name
222225 let allDctors = fst `map` allExportedDataConstructors name
223226 maybe (return ()) (traverse_ $ checkDctorExists name allDctors) dctors
227+ check (TypeOpRef name) =
228+ checkImportExists UnknownImportTypeOp (fst `map` exportedTypeOps exps) name
224229 check (TypeClassRef name) =
225230 checkImportExists UnknownImportTypeClass (fst `map` exportedTypeClasses exps) name
226231 check (ModuleRef name) | isHiding =
@@ -267,8 +272,9 @@ resolveImport importModule exps imps impQual = resolveByType
267272 importAll :: (Imports -> DeclarationRef -> m Imports) -> m Imports
268273 importAll importer = do
269274 imp' <- foldM (\m ((name, dctors), _) -> importer m (TypeRef name (Just dctors))) imps (exportedTypes exps)
270− imp'' <- foldM (\m (name, _) -> importer m (ValueRef name)) imp' (exportedValues exps)
271− foldM (\m (name, _) -> importer m (TypeClassRef name)) imp'' (exportedTypeClasses exps)
275+ imp'' <- foldM (\m (name, _) -> importer m (TypeOpRef name)) imp' (exportedTypeOps exps)
276+ imp''' <- foldM (\m (name, _) -> importer m (ValueRef name)) imp'' (exportedValues exps)
277+ foldM (\m (name, _) -> importer m (TypeClassRef name)) imp''' (exportedTypeClasses exps)
272278
273279 importRef :: ImportProvenance -> Imports -> DeclarationRef -> m Imports
274280 importRef prov imp (PositionedDeclarationRef pos _ r) =
@@ -286,6 +292,9 @@ resolveImport importModule exps imps impQual = resolveByType
286292 when (null dctorNames && isNothing dctors) . tell . errorMessage $ MisleadingEmptyTypeImport importModule name
287293 let dctors' = foldl (\m d -> updateImports m exportedDctors d prov) (importedDataConstructors imp) (fromMaybe dctorNames dctors)
288294 return $ imp { importedTypes = types', importedDataConstructors = dctors' }
295+ importRef prov imp (TypeOpRef name) = do
296+ let ops' = updateImports (importedTypeOps imp) (exportedTypeOps exps) name prov
297+ return $ imp { importedTypeOps = ops' }
289298 importRef prov imp (TypeClassRef name) = do
290299 let typeClasses' = updateImports (importedTypeClasses imp) (exportedTypeClasses exps) name prov
291300 return $ imp { importedTypeClasses = typeClasses' }
src/Language/PureScript/Sugar/ObjectWildcards.hs+24−7
@@ -9,6 +9,7 @@ module Language.PureScript.Sugar.ObjectWildcards (
99import Prelude ()
1010import Prelude.Compat
1111
12+import Control.Monad (forM)
1213import Control.Monad.Error.Class (MonadError(..))
1314import Control.Monad.Supply.Class
1415
@@ -45,11 +46,21 @@ desugarObjectConstructors (Module ss coms mn ds exts) = Module ss coms mn <$> ma
4546 desugarExpr (Literal (ObjectLiteral ps)) = wrapLambda (Literal . ObjectLiteral) ps
4647 desugarExpr (ObjectUpdate u ps) | isAnonymousArgument u = do
4748 obj <- freshIdent'
48− Abs (Left obj) <$> wrapLambda (ObjectUpdate (Var (Qualified Nothing obj))) ps
49+ Abs (Left obj) <$> wrapLambda (ObjectUpdate (argToExpr obj)) ps
4950 desugarExpr (ObjectUpdate obj ps) = wrapLambda (ObjectUpdate obj) ps
5051 desugarExpr (Accessor prop u) | isAnonymousArgument u = do
5152 arg <- freshIdent'
52− return $ Abs (Left arg) (Accessor prop (Var (Qualified Nothing arg)))
53+ return $ Abs (Left arg) (Accessor prop (argToExpr arg))
54+ desugarExpr (Case args cas) | any isAnonymousArgument args = do
55+ argIdents <- forM args freshIfAnon
56+ let args' = zipWith (\p -> maybe p argToExpr) args argIdents
57+ return $ foldr (Abs . Left) (Case args' cas) (catMaybes argIdents)
58+ desugarExpr (IfThenElse u t f) | any isAnonymousArgument [u, t, f] = do
59+ u' <- freshIfAnon u
60+ t' <- freshIfAnon t
61+ f' <- freshIfAnon f
62+ let if_ = IfThenElse (maybe u argToExpr u') (maybe t argToExpr t') (maybe f argToExpr f')
63+ return $ foldr (Abs . Left) if_ (catMaybes [u', t', f'])
5364 desugarExpr e = return e
5465
5566 wrapLambda :: ([(String, Expr)] -> Expr) -> [(String, Expr)] -> m Expr
@@ -71,8 +82,14 @@ desugarObjectConstructors (Module ss coms mn ds exts) = Module ss coms mn <$> ma
7182 isAnonymousArgument _ = False
7283
7384 mkProp :: (String, Expr) -> m (Maybe Ident, (String, Expr))
74− mkProp (name, e)
75− | isAnonymousArgument e = do
76− arg <- freshIdent'
77− return (Just arg, (name, Var (Qualified Nothing arg)))
78− | otherwise = return (Nothing, (name, e))
85+ mkProp (name, e) = do
86+ arg <- freshIfAnon e
87+ return (arg, (name, maybe e argToExpr arg))
88+
89+ freshIfAnon :: Expr -> m (Maybe Ident)
90+ freshIfAnon u
91+ | isAnonymousArgument u = Just <$> freshIdent'
92+ | otherwise = return Nothing
93+
94+ argToExpr :: Ident -> Expr
95+ argToExpr = Var . Qualified Nothing
src/Language/PureScript/Sugar/Operators.hs+175−42
@@ -1,4 +1,3 @@
1−{-# LANGUAGE Rank2Types #-}
21{-# LANGUAGE FlexibleContexts #-}
32{-# LANGUAGE ScopedTypeVariables #-}
43{-# LANGUAGE RecordWildCards #-}
@@ -11,11 +10,11 @@
1110-- The value parser ignores fixity data when parsing binary operator applications, so
1211-- it is necessary to reorder them here.
1312--
14−module Language.PureScript.Sugar.Operators (
15− rebracket,
16− removeSignedLiterals,
17− desugarOperatorSections
18−) where
13+module Language.PureScript.Sugar.Operators
14+ ( rebracket
15+ , removeSignedLiterals
16+ , desugarOperatorSections
17+ ) where
1918
2019import Prelude ()
2120import Prelude.Compat
@@ -27,30 +26,29 @@ import Language.PureScript.Externs
2726import Language.PureScript.Names
2827import Language.PureScript.Sugar.Operators.Binders
2928import Language.PureScript.Sugar.Operators.Expr
30−import Language.PureScript.Traversals (defS)
29+import Language.PureScript.Sugar.Operators.Types
30+import Language.PureScript.Traversals (defS, sndM)
31+import Language.PureScript.Types
3132
33+import Control.Monad ((<=<))
3234import Control.Monad.Error.Class (MonadError(..))
3335import Control.Monad.Supply.Class
3436
3537import Data.Function (on)
36−import Data.List (groupBy, sortBy)
38+import Data.Functor.Identity
39+import Data.List (partition, groupBy, sortBy)
3740import Data.Maybe (mapMaybe)
3841import qualified Data.Map as M
3942
4043import qualified Language.PureScript.Constants as C
4144
42−-- TODO: in 0.9 operators names can have their own type rather than being in a sum with `Ident`, and `AliasName` no longer needs to be optional
45+-- TODO: in 0.9 operators names can have their own type rather than being in a sum with `Ident`, and `FixityAlias` no longer needs to be optional
4346
4447-- |
4548-- An operator associated with its declaration position, fixity, and the name
4649-- of the function or data constructor it is an alias for.
4750--
48−type FixityRecord = (Qualified Ident, SourceSpan, Fixity, Maybe AliasName)
49−
50−-- |
51−-- An operator can be an alias for a function or a data constructor.
52−--
53−type AliasName = Either (Qualified Ident) (Qualified (ProperName 'ConstructorName))
51+type FixityRecord = (Qualified Ident, SourceSpan, Fixity, Maybe (Qualified FixityAlias))
5452
5553-- |
5654-- Remove explicit parentheses and reorder binary operator applications
@@ -62,23 +60,57 @@ rebracket
6260 -> [Module]
6361 -> m [Module]
6462rebracket externs ms = do
65− let fixities = concatMap externsFixities externs ++ concatMap collectFixities ms
66− ensureNoDuplicates $ map (\(i, pos, _, _) -> (i, pos)) fixities
67− let opTable = customOperatorTable $ map (\(i, _, f, _) -> (i, f)) fixities
68− ms' <- traverse (rebracketModule opTable) ms
69− let aliased = M.fromList (mapMaybe makeLookupEntry fixities)
70− mapM (renameAliasedOperators aliased) ms'
63+ let (typeFixities, valueFixities) = partition isTypeFixity $
64+ concatMap externsFixities externs ++ concatMap collectFixities ms
65+
66+ ensureNoDuplicates' $ valueFixities
67+ ensureNoDuplicates' $ typeFixities
68+
69+ let valueOpTable = customOperatorTable' valueFixities
70+ typeOpTable = customOperatorTable' typeFixities
71+ ms' <- traverse (rebracketModule valueOpTable typeOpTable) ms
72+
73+ let valueAliased = M.fromList (mapMaybe makeLookupEntry valueFixities)
74+ typeAliased = M.fromList (mapMaybe makeLookupEntry typeFixities)
75+ mapM (renameAliasedOperators valueAliased typeAliased) ms'
7176
7277 where
7378
74− makeLookupEntry :: FixityRecord -> Maybe (Qualified Ident, AliasName)
79+ isTypeFixity :: FixityRecord -> Bool
80+ -- Nothing case for FixityAlias can only ever be a value fixity, as it's not
81+ -- possible to define types with operator names aside through aliasing.
82+ -- TODO: This comment is redundant after 0.9.
83+ isTypeFixity (_, _, _, Just (Qualified _ (AliasType _))) = True
84+ isTypeFixity _ = False
85+
86+ ensureNoDuplicates' :: [FixityRecord] -> m ()
87+ ensureNoDuplicates' =
88+ ensureNoDuplicates . map (\(i, pos, _, _) -> (i, pos))
89+
90+ customOperatorTable' :: [FixityRecord] -> [[(Qualified Ident, Associativity)]]
91+ customOperatorTable' =
92+ customOperatorTable . map (\(i, _, f, _) -> (i, f))
93+
94+ makeLookupEntry :: FixityRecord -> Maybe (Qualified Ident, Qualified FixityAlias)
7595 makeLookupEntry (qname, _, _, alias) = (qname, ) <$> alias
7696
77− renameAliasedOperators :: M.Map (Qualified Ident) AliasName -> Module -> m Module
78− renameAliasedOperators aliased (Module ss coms mn ds exts) =
97+ renameAliasedOperators
98+ :: M.Map (Qualified Ident) (Qualified FixityAlias)
99+ -> M.Map (Qualified Ident) (Qualified FixityAlias)
100+ -> Module
101+ -> m Module
102+ renameAliasedOperators valueAliased typeAliased (Module ss coms mn ds exts) =
79103 Module ss coms mn <$> mapM f' ds <*> pure exts
80104 where
81− (f', _, _, _, _) = everywhereWithContextOnValuesM Nothing goDecl goExpr goBinder defS defS
105+ (goDecl', goExpr') = updateTypes goType
106+ (f', _, _, _, _) =
107+ everywhereWithContextOnValuesM
108+ Nothing
109+ (\pos -> uncurry goDecl <=< goDecl' pos)
110+ (\pos -> uncurry goExpr <=< goExpr' pos)
111+ goBinder
112+ defS
113+ defS
82114
83115 goDecl :: Maybe SourceSpan -> Declaration -> m (Maybe SourceSpan, Declaration)
84116 goDecl _ d@(PositionedDeclaration pos _ _) = return (Just pos, d)
@@ -86,27 +118,39 @@ rebracket externs ms = do
86118
87119 goExpr :: Maybe SourceSpan -> Expr -> m (Maybe SourceSpan, Expr)
88120 goExpr _ e@(PositionedValue pos _ _) = return (Just pos, e)
89− goExpr pos (Var name) = return (pos, case name `M.lookup` aliased of
90− Just (Left alias) -> Var alias
91− Just (Right alias) -> Constructor alias
92− Nothing -> Var name)
121+ goExpr pos (Var name) = return (pos, case name `M.lookup` valueAliased of
122+ Just (Qualified mn' (AliasValue alias)) -> Var (Qualified mn' alias)
123+ Just (Qualified mn' (AliasConstructor alias)) -> Constructor (Qualified mn' alias)
124+ _ -> Var name)
93125 goExpr pos other = return (pos, other)
94126
95127 goBinder :: Maybe SourceSpan -> Binder -> m (Maybe SourceSpan, Binder)
96128 goBinder _ b@(PositionedBinder pos _ _) = return (Just pos, b)
97− goBinder pos (BinaryNoParensBinder (OpBinder name) lhs rhs) = case name `M.lookup` aliased of
98− Just (Left alias) ->
129+ goBinder pos (BinaryNoParensBinder (OpBinder name) lhs rhs) = case name `M.lookup` valueAliased of
130+ Just (Qualified _ (AliasValue alias)) ->
99131 maybe id rethrowWithPosition pos $
100− throwError . errorMessage $ InvalidOperatorInBinder (disqualify name) (disqualify alias)
101− Just (Right alias) ->
102− return (pos, ConstructorBinder alias [lhs, rhs])
103− Nothing ->
132+ throwError . errorMessage $ InvalidOperatorInBinder (disqualify name) alias
133+ Just (Qualified mn' (AliasConstructor alias)) ->
134+ return (pos, ConstructorBinder (Qualified mn' alias) [lhs, rhs])
135+ _ ->
104136 maybe id rethrowWithPosition pos $
105137 throwError . errorMessage $ UnknownValue name
106138 goBinder _ (BinaryNoParensBinder {}) =
107139 internalError "BinaryNoParensBinder has no OpBinder"
108140 goBinder pos other = return (pos, other)
109141
142+ goType :: Maybe SourceSpan -> Type -> m Type
143+ goType pos = everywhereOnTypesM go
144+ where
145+ go :: Type -> m Type
146+ go (BinaryNoParensType (TypeOp name) lhs rhs) = case name `M.lookup` typeAliased of
147+ Just (Qualified mn' (AliasType alias)) ->
148+ return $ TypeApp (TypeApp (TypeConstructor (Qualified mn' alias)) lhs) rhs
149+ _ ->
150+ maybe id rethrowWithPosition pos $
151+ throwError . errorMessage $ UnknownTypeOp name
152+ go other = return other
153+
110154removeSignedLiterals :: Module -> Module
111155removeSignedLiterals (Module ss coms mn ds exts) = Module ss coms mn (map f' ds) exts
112156 where
@@ -116,24 +160,64 @@ removeSignedLiterals (Module ss coms mn ds exts) = Module ss coms mn (map f' ds)
116160 go other = other
117161
118162rebracketModule
119− :: (MonadError MultipleErrors m)
163+ :: forall m
164+ . (MonadError MultipleErrors m)
120165 => [[(Qualified Ident, Associativity)]]
166+ -> [[(Qualified Ident, Associativity)]]
121167 -> Module
122168 -> m Module
123−rebracketModule opTable (Module ss coms mn ds exts) =
124− let (f, _, _) = everywhereOnValuesTopDownM return (matchExprOperators opTable) (matchBinderOperators opTable)
125− in Module ss coms mn <$> (map removeParens <$> parU ds f) <*> pure exts
169+rebracketModule valueOpTable typeOpTable (Module ss coms mn ds exts) =
170+ Module ss coms mn <$> (map removeParens <$> parU ds f) <*> pure exts
171+ where
172+ (f, _, _) =
173+ everywhereOnValuesTopDownM
174+ (decontextify goDecl)
175+ (goExpr <=< decontextify goExpr')
176+ goBinder
177+
178+ (goDecl, goExpr') = updateTypes (\_ -> goType)
179+
180+ goExpr :: Expr -> m Expr
181+ goExpr = return . matchExprOperators valueOpTable
182+
183+ goBinder :: Binder -> m Binder
184+ goBinder = return . matchBinderOperators valueOpTable
185+
186+ goType :: Type -> m Type
187+ goType = return . matchTypeOperators typeOpTable
188+
189+ decontextify :: (Maybe SourceSpan -> a -> m (Maybe SourceSpan, a)) -> a -> m a
190+ decontextify ctxf = fmap snd . ctxf Nothing
126191
127192removeParens :: Declaration -> Declaration
128−removeParens =
129− let (f, _, _) = everywhereOnValues id goExpr goBinder
130− in f
193+removeParens = f
131194 where
195+ (f, _, _) =
196+ everywhereOnValues
197+ (decontextify goDecl)
198+ (goExpr . decontextify goExpr')
199+ goBinder
200+
201+ (goDecl, goExpr') = updateTypes (\_ -> return . goType)
202+
203+ goExpr :: Expr -> Expr
132204 goExpr (Parens val) = val
133205 goExpr val = val
206+
207+ goBinder :: Binder -> Binder
134208 goBinder (ParensInBinder b) = b
135209 goBinder b = b
136210
211+ goType :: Type -> Type
212+ goType (ParensInType t) = t
213+ goType t = t
214+
215+ decontextify
216+ :: (Maybe SourceSpan -> a -> Identity (Maybe SourceSpan, a))
217+ -> a
218+ -> a
219+ decontextify ctxf = snd . runIdentity . ctxf Nothing
220+
137221externsFixities
138222 :: ExternsFile
139223 -> [FixityRecord]
@@ -197,3 +281,52 @@ desugarOperatorSections (Module ss coms mn ds exts) =
197281 Left val -> f2 val var
198282 Right val -> f2 var val
199283 goExpr other = return other
284+
285+updateTypes
286+ :: forall m
287+ . Monad m
288+ => (Maybe SourceSpan -> Type -> m Type)
289+ -> ( Maybe SourceSpan -> Declaration -> m (Maybe SourceSpan, Declaration)
290+ , Maybe SourceSpan -> Expr -> m (Maybe SourceSpan, Expr)
291+ )
292+updateTypes goType = (goDecl, goExpr)
293+ where
294+
295+ goType' :: Maybe SourceSpan -> Type -> m Type
296+ goType' = everywhereOnTypesM . goType
297+
298+ goDecl :: Maybe SourceSpan -> Declaration -> m (Maybe SourceSpan, Declaration)
299+ goDecl _ d@(PositionedDeclaration pos _ _) = return (Just pos, d)
300+ goDecl pos (DataDeclaration ddt name args dctors) = do
301+ dctors' <- traverse (sndM (traverse (goType' pos))) dctors
302+ return (pos, DataDeclaration ddt name args dctors')
303+ goDecl pos (ExternDeclaration name ty) = do
304+ ty' <- goType' pos ty
305+ return (pos, ExternDeclaration name ty')
306+ goDecl pos (TypeClassDeclaration name args implies decls) = do
307+ implies' <- traverse (sndM (traverse (goType' pos))) implies
308+ return (pos, TypeClassDeclaration name args implies' decls)
309+ goDecl pos (TypeInstanceDeclaration name cs className tys impls) = do
310+ cs' <- traverse (sndM (traverse (goType' pos))) cs
311+ tys' <- traverse (goType' pos) tys
312+ return (pos, TypeInstanceDeclaration name cs' className tys' impls)
313+ goDecl pos (TypeSynonymDeclaration name args ty) = do
314+ ty' <- goType' pos ty
315+ return (pos, TypeSynonymDeclaration name args ty')
316+ goDecl pos (TypeDeclaration expr ty) = do
317+ ty' <- goType' pos ty
318+ return (pos, TypeDeclaration expr ty')
319+ goDecl pos other = return (pos, other)
320+
321+ goExpr :: Maybe SourceSpan -> Expr -> m (Maybe SourceSpan, Expr)
322+ goExpr _ e@(PositionedValue pos _ _) = return (Just pos, e)
323+ goExpr pos (TypeClassDictionary (name, tys) dicts) = do
324+ tys' <- traverse (goType' pos) tys
325+ return (pos, TypeClassDictionary (name, tys') dicts)
326+ goExpr pos (SuperClassDictionary cls tys) = do
327+ tys' <- traverse (goType' pos) tys
328+ return (pos, SuperClassDictionary cls tys')
329+ goExpr pos (TypedValue check v ty) = do
330+ ty' <- goType' pos ty
331+ return (pos, TypedValue check v ty')
332+ goExpr pos other = return (pos, other)
src/Language/PureScript/Sugar/Operators/Binders.hs+14−30
@@ -1,43 +1,27 @@
1−{-# LANGUAGE FlexibleContexts #-}
2−{-# LANGUAGE ScopedTypeVariables #-}
3−
41module Language.PureScript.Sugar.Operators.Binders where
52
63import Prelude ()
74import Prelude.Compat
85
9−import Control.Monad.Error.Class (MonadError(..))
10−
11−import qualified Text.Parsec as P
12−import qualified Text.Parsec.Expr as P
13−
14−import Language.PureScript.Crash
156import Language.PureScript.AST
16−import Language.PureScript.Errors
177import Language.PureScript.Names
188import Language.PureScript.Sugar.Operators.Common
199
20−matchBinderOperators
21− :: forall m
22− . MonadError MultipleErrors m
23− => [[(Qualified Ident, Associativity)]]
24− -> Binder
25− -> m Binder
26−matchBinderOperators ops = parseChains
10+matchBinderOperators :: [[(Qualified Ident, Associativity)]] -> Binder -> Binder
11+matchBinderOperators = matchOperators isBinOp extractOp fromOp reapply id
2712 where
28− parseChains :: Binder -> m Binder
29− parseChains b@BinaryNoParensBinder{} = bracketChain (extendChain b)
30− parseChains other = return other
31− extendChain :: Binder -> Chain Binder
32− extendChain (BinaryNoParensBinder op l r) = Left l : Right op : extendChain r
33− extendChain other = [Left other]
34− bracketChain :: Chain Binder -> m Binder
35− bracketChain =
36− either
37− (\_ -> internalError "matchBinderOperators: cannot reorder operators")
38− return
39− . P.parse opParser "operator expression"
40− opParser = P.buildExpressionParser (opTable ops fromOp reapply) parseValue <* P.eof
13+
14+ isBinOp :: Binder -> Bool
15+ isBinOp BinaryNoParensBinder{} = True
16+ isBinOp _ = False
17+
18+ extractOp :: Binder -> Maybe (Binder, Binder, Binder)
19+ extractOp (BinaryNoParensBinder op l r) = Just (op, l, r)
20+ extractOp _ = Nothing
21+
22+ fromOp :: Binder -> Maybe (Qualified Ident)
4123 fromOp (OpBinder q@(Qualified _ (Op _))) = Just q
4224 fromOp _ = Nothing
25+
26+ reapply :: Qualified Ident -> Binder -> Binder -> Binder
4327 reapply = BinaryNoParensBinder . OpBinder
src/Language/PureScript/Sugar/Operators/Common.hs+31
@@ -1,5 +1,6 @@
11{-# LANGUAGE FlexibleContexts #-}
22{-# LANGUAGE ScopedTypeVariables #-}
3+{-# LANGUAGE PatternGuards #-}
34
45module Language.PureScript.Sugar.Operators.Common where
56
@@ -15,6 +16,7 @@ import qualified Text.Parsec.Pos as P
1516import qualified Text.Parsec.Expr as P
1617
1718import Language.PureScript.AST
19+import Language.PureScript.Crash
1820import Language.PureScript.Names
1921
2022type Chain a = [Either a a]
@@ -51,3 +53,32 @@ opTable
5153opTable ops fromOp reapply =
5254 map (map (\(name, a) -> P.Infix (P.try (matchOp fromOp name) >> return (reapply name)) (toAssoc a))) ops
5355 ++ [[ P.Infix (P.try (parseOp fromOp >>= \ident -> return (reapply ident))) P.AssocLeft ]]
56+
57+matchOperators
58+ :: forall a
59+ . Show a
60+ => (a -> Bool)
61+ -> (a -> Maybe (a, a, a))
62+ -> (a -> Maybe (Qualified Ident))
63+ -> (Qualified Ident -> a -> a -> a)
64+ -> ([[P.Operator (Chain a) () Identity a]] -> P.OperatorTable (Chain a) () Identity a)
65+ -> [[(Qualified Ident, Associativity)]]
66+ -> a
67+ -> a
68+matchOperators isBinOp extractOp fromOp reapply modOpTable ops = parseChains
69+ where
70+ parseChains :: a -> a
71+ parseChains ty
72+ | True <- isBinOp ty = bracketChain (extendChain ty)
73+ | otherwise = ty
74+ extendChain :: a -> Chain a
75+ extendChain ty
76+ | Just (op, l, r) <- extractOp ty = Left l : Right op : extendChain r
77+ | otherwise = [Left ty]
78+ bracketChain :: Chain a -> a
79+ bracketChain =
80+ either
81+ (\_ -> internalError "matchTypeOperators: cannot reorder operators")
82+ id
83+ . P.parse opParser "operator expression"
84+ opParser = P.buildExpressionParser (modOpTable (opTable ops fromOp reapply)) parseValue <* P.eof
src/Language/PureScript/Sugar/Operators/Expr.hs+27−31
@@ -6,47 +6,43 @@ module Language.PureScript.Sugar.Operators.Expr where
66import Prelude ()
77import Prelude.Compat
88
9−import Control.Monad.Error.Class (MonadError(..))
9+import Data.Functor.Identity
1010
1111import qualified Text.Parsec as P
1212import qualified Text.Parsec.Expr as P
1313
14−import Language.PureScript.Crash
1514import Language.PureScript.AST
16−import Language.PureScript.Errors
1715import Language.PureScript.Names
1816import Language.PureScript.Sugar.Operators.Common
1917
20−matchExprOperators
21− :: forall m
22− . MonadError MultipleErrors m
23− => [[(Qualified Ident, Associativity)]]
24− -> Expr
25− -> m Expr
26−matchExprOperators ops = parseChains
18+matchExprOperators :: [[(Qualified Ident, Associativity)]] -> Expr -> Expr
19+matchExprOperators = matchOperators isBinOp extractOp fromOp reapply modOpTable
2720 where
28− parseChains :: Expr -> m Expr
29− parseChains b@BinaryNoParens{} = bracketChain (extendChain b)
30− parseChains other = return other
31− extendChain :: Expr -> Chain Expr
32− extendChain (BinaryNoParens op l r) = Left l : Right op : extendChain r
33− extendChain other = [Left other]
34− bracketChain :: Chain Expr -> m Expr
35− bracketChain =
36− either
37− (\_ -> internalError "matchExprOperators: cannot reorder operators")
38− return
39− . P.parse opParser "operator expression"
40− opParser = P.buildExpressionParser opTable' parseValue <* P.eof
41− opTable' =
42− [ P.Infix (P.try (parseTicks >>= \op -> return (\t1 t2 -> App (App op t1) t2))) P.AssocLeft ]
43− : opTable ops fromOp reapply
21+
22+ isBinOp :: Expr -> Bool
23+ isBinOp BinaryNoParens{} = True
24+ isBinOp _ = False
25+
26+ extractOp :: Expr -> Maybe (Expr, Expr, Expr)
27+ extractOp (BinaryNoParens op l r) = Just (op, l, r)
28+ extractOp _ = Nothing
29+
30+ fromOp :: Expr -> Maybe (Qualified Ident)
4431 fromOp (Var q@(Qualified _ (Op _))) = Just q
4532 fromOp _ = Nothing
33+
34+ reapply :: Qualified Ident -> Expr -> Expr -> Expr
4635 reapply op t1 t2 = App (App (Var op) t1) t2
4736
48−parseTicks :: P.Parsec (Chain Expr) () Expr
49−parseTicks = token (either (const Nothing) fromOther) P.<?> "infix function"
50− where
51− fromOther (Var (Qualified _ (Op _))) = Nothing
52− fromOther v = Just v
37+ modOpTable
38+ :: [[P.Operator (Chain Expr) () Identity Expr]]
39+ -> [[P.Operator (Chain Expr) () Identity Expr]]
40+ modOpTable table =
41+ [ P.Infix (P.try (parseTicks >>= \op -> return (\t1 t2 -> App (App op t1) t2))) P.AssocLeft ]
42+ : table
43+
44+ parseTicks :: P.Parsec (Chain Expr) () Expr
45+ parseTicks = token (either (const Nothing) fromOther) P.<?> "infix function"
46+ where
47+ fromOther (Var (Qualified _ (Op _))) = Nothing
48+ fromOther v = Just v
src/Language/PureScript/Sugar/Operators/Types.hsnew file+28
@@ -0,0 +1,28 @@
1+module Language.PureScript.Sugar.Operators.Types where
2+
3+import Prelude ()
4+import Prelude.Compat
5+
6+import Language.PureScript.AST
7+import Language.PureScript.Names
8+import Language.PureScript.Sugar.Operators.Common
9+import Language.PureScript.Types
10+
11+matchTypeOperators :: [[(Qualified Ident, Associativity)]] -> Type -> Type
12+matchTypeOperators = matchOperators isBinOp extractOp fromOp reapply id
13+ where
14+
15+ isBinOp :: Type -> Bool
16+ isBinOp BinaryNoParensType{} = True
17+ isBinOp _ = False
18+
19+ extractOp :: Type -> Maybe (Type, Type, Type)
20+ extractOp (BinaryNoParensType op l r) = Just (op, l, r)
21+ extractOp _ = Nothing
22+
23+ fromOp :: Type -> Maybe (Qualified Ident)
24+ fromOp (TypeOp q@(Qualified _ (Op _))) = Just q
25+ fromOp _ = Nothing
26+
27+ reapply :: Qualified Ident -> Type -> Type -> Type
28+ reapply = BinaryNoParensType . TypeOp
src/Language/PureScript/TypeChecker.hs+10−12
@@ -277,15 +277,16 @@ typeCheckAll moduleName _ ds = traverse go ds <* traverse_ checkFixities ds
277277 warnAndRethrowWithPosition pos $ PositionedDeclaration pos com <$> go d
278278
279279 checkFixities :: Declaration -> m ()
280− checkFixities (FixityDeclaration _ name (Just (Left alias))) = do
281− ty <- lookupVariable moduleName alias
280+ checkFixities (FixityDeclaration _ name (Just (Qualified mn' (AliasValue ident)))) = do
281+ ty <- lookupVariable moduleName (Qualified mn' ident)
282282 addValue moduleName (Op name) ty Public
283− checkFixities (FixityDeclaration _ name (Just (Right alias))) = do
283+ checkFixities (FixityDeclaration _ name (Just (Qualified mn' (AliasConstructor ctor)))) = do
284284 env <- getEnv
285+ let alias = Qualified mn' ctor
285286 case M.lookup alias (dataConstructors env) of
286287 Nothing -> throwError . errorMessage $ UnknownDataConstructor alias Nothing
287288 Just (_, _, ty, _) -> addValue moduleName (Op name) ty Public
288− checkFixities (FixityDeclaration _ name _) = do
289+ checkFixities (FixityDeclaration _ name Nothing) = do
289290 env <- getEnv
290291 guardWith (errorMessage (OrphanFixityDeclaration name)) $ M.member (moduleName, Op name) $ names env
291292 checkFixities (PositionedDeclaration pos _ d) =
@@ -438,21 +439,18 @@ typeCheckModule (Module ss coms mn decls (Just exps)) = warnAndRethrow (addHint
438439 checkNonAliasesAreExported :: [ProperName 'ConstructorName] -> DeclarationRef -> m ()
439440 checkNonAliasesAreExported exportedDctors dr@(ValueRef (Op name)) =
440441 case listToMaybe (mapMaybe getAlias decls) of
441− Just (Left ident) ->
442+ Just (AliasValue ident) ->
442443 unless (ValueRef ident `elem` exps) $
443444 throwError . errorMessage $ TransitiveExportError dr [ValueRef ident]
444− Just (Right ctor) ->
445+ Just (AliasConstructor ctor) ->
445446 unless (ctor `elem` exportedDctors) $
446447 throwError . errorMessage $ TransitiveDctorExportError dr ctor
447448 _ -> return ()
448449 where
449− getAlias :: Declaration -> Maybe (Either Ident (ProperName 'ConstructorName))
450+ getAlias :: Declaration -> Maybe FixityAlias
450451 getAlias (PositionedDeclaration _ _ d) = getAlias d
451− getAlias (FixityDeclaration _ name' (Just alias)) | name == name' =
452− case alias of
453− Left (Qualified (Just mn') ident) | mn == mn' -> Just (Left ident)
454− Right (Qualified (Just mn') ctor) | mn == mn' -> Just (Right ctor)
455− _ -> Nothing
452+ getAlias (FixityDeclaration _ name' (Just (Qualified (Just mn') alias)))
453+ | name == name' && mn == mn' = Just alias
456454 getAlias _ = Nothing
457455 checkNonAliasesAreExported _ _ = return ()
458456
src/Language/PureScript/TypeChecker/Kinds.hs+1−1
@@ -268,4 +268,4 @@ infer' other = (, []) <$> go other
268268 k <- go ty
269269 unifyKinds k Star
270270 return Star
271− go _ = internalError "Invalid argument to infer"
271+ go ty = internalError $ "Invalid argument to infer: " ++ show ty
src/Language/PureScript/TypeChecker/Types.hs+1−1
@@ -319,7 +319,7 @@ infer' (TypedValue checkType val ty) = do
319319infer' (PositionedValue pos c val) = warnAndRethrowWithPosition pos $ do
320320 TypedValue t v ty <- infer' val
321321 return $ TypedValue t (PositionedValue pos c v) ty
322−infer' _ = internalError "Invalid argument to infer"
322+infer' v = internalError $ "Invalid argument to infer: " ++ show v
323323
324324inferLetBinding ::
325325 (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>
src/Language/PureScript/Types.hs+34
@@ -49,6 +49,11 @@ data Type
4949 --
5050 | TypeConstructor (Qualified (ProperName 'TypeName))
5151 -- |
52+ -- A type operator. This will be desugared into a type constructor during the
53+ -- "operators" phase of desugaring.
54+ --
55+ | TypeOp (Qualified Ident)
56+ -- |
5257 -- A type application
5358 --
5459 | TypeApp Type Type
@@ -89,6 +94,19 @@ data Type
8994 -- A placeholder used in pretty printing
9095 --
9196 | PrettyPrintForAll [String] Type
97+ -- |
98+ -- Binary operator application. During the rebracketing phase of desugaring,
99+ -- this data constructor will be removed.
100+ --
101+ | BinaryNoParensType Type Type Type
102+ -- |
103+ -- Explicit parentheses. During the rebracketing phase of desugaring, this
104+ -- data constructor will be removed.
105+ --
106+ -- Note: although it seems this constructor is not used, it _is_ useful,
107+ -- since it prevents certain traversals from matching.
108+ --
109+ | ParensInType Type
92110 deriving (Show, Read, Eq, Ord)
93111
94112-- |
@@ -154,6 +172,8 @@ replaceAllTypeVars = go []
154172 go bs m (ConstrainedType cs t) = ConstrainedType (map (second $ map (go bs m)) cs) (go bs m t)
155173 go bs m (RCons name' t r) = RCons name' (go bs m t) (go bs m r)
156174 go bs m (KindedType t k) = KindedType (go bs m t) k
175+ go bs m (BinaryNoParensType t1 t2 t3) = BinaryNoParensType (go bs m t1) (go bs m t2) (go bs m t3)
176+ go bs m (ParensInType t) = ParensInType (go bs m t)
157177 go _ _ ty = ty
158178
159179 genName orig inUse = try 0
@@ -184,6 +204,8 @@ freeTypeVariables = nub . go []
184204 go bound (ConstrainedType cs t) = concatMap (concatMap (go bound) . snd) cs ++ go bound t
185205 go bound (RCons _ t r) = go bound t ++ go bound r
186206 go bound (KindedType t _) = go bound t
207+ go bound (BinaryNoParensType t1 t2 t3) = go bound t1 ++ go bound t2 ++ go bound t3
208+ go bound (ParensInType t) = go bound t
187209 go _ _ = []
188210
189211-- |
@@ -233,6 +255,8 @@ everywhereOnTypes f = go
233255 go (PrettyPrintFunction t1 t2) = f (PrettyPrintFunction (go t1) (go t2))
234256 go (PrettyPrintObject t) = f (PrettyPrintObject (go t))
235257 go (PrettyPrintForAll args t) = f (PrettyPrintForAll args (go t))
258+ go (BinaryNoParensType t1 t2 t3) = f (BinaryNoParensType (go t1) (go t2) (go t3))
259+ go (ParensInType t) = f (ParensInType (go t))
236260 go other = f other
237261
238262everywhereOnTypesTopDown :: (Type -> Type) -> Type -> Type
@@ -246,6 +270,8 @@ everywhereOnTypesTopDown f = go . f
246270 go (PrettyPrintFunction t1 t2) = PrettyPrintFunction (go (f t1)) (go (f t2))
247271 go (PrettyPrintObject t) = PrettyPrintObject (go (f t))
248272 go (PrettyPrintForAll args t) = PrettyPrintForAll args (go (f t))
273+ go (BinaryNoParensType t1 t2 t3) = BinaryNoParensType (f (go t1)) (f (go t2)) (f (go t3))
274+ go (ParensInType t) = ParensInType (f (go t))
249275 go other = f other
250276
251277everywhereOnTypesM :: Monad m => (Type -> m Type) -> Type -> m Type
@@ -259,6 +285,8 @@ everywhereOnTypesM f = go
259285 go (PrettyPrintFunction t1 t2) = (PrettyPrintFunction <$> go t1 <*> go t2) >>= f
260286 go (PrettyPrintObject t) = (PrettyPrintObject <$> go t) >>= f
261287 go (PrettyPrintForAll args t) = (PrettyPrintForAll args <$> go t) >>= f
288+ go (BinaryNoParensType t1 t2 t3) = (BinaryNoParensType <$> go t1 <*> go t2 <*> go t3) >>= f
289+ go (ParensInType t) = (ParensInType <$> go t) >>= f
262290 go other = f other
263291
264292everywhereOnTypesTopDownM :: Monad m => (Type -> m Type) -> Type -> m Type
@@ -272,6 +300,8 @@ everywhereOnTypesTopDownM f = go <=< f
272300 go (PrettyPrintFunction t1 t2) = PrettyPrintFunction <$> (f t1 >>= go) <*> (f t2 >>= go)
273301 go (PrettyPrintObject t) = PrettyPrintObject <$> (f t >>= go)
274302 go (PrettyPrintForAll args t) = PrettyPrintForAll args <$> (f t >>= go)
303+ go (BinaryNoParensType t1 t2 t3) = BinaryNoParensType <$> (f t1 >>= go) <*> (f t2 >>= go) <*> (f t3 >>= go)
304+ go (ParensInType t) = ParensInType <$> (f t >>= go)
275305 go other = f other
276306
277307everythingOnTypes :: (r -> r -> r) -> (Type -> r) -> Type -> r
@@ -285,6 +315,8 @@ everythingOnTypes (<>) f = go
285315 go t@(PrettyPrintFunction t1 t2) = f t <> go t1 <> go t2
286316 go t@(PrettyPrintObject t1) = f t <> go t1
287317 go t@(PrettyPrintForAll _ t1) = f t <> go t1
318+ go t@(BinaryNoParensType t1 t2 t3) = f t <> go t1 <> go t2 <> go t3
319+ go t@(ParensInType t1) = f t <> go t1
288320 go other = f other
289321
290322everythingWithContextOnTypes :: s -> r -> (r -> r -> r) -> (s -> Type -> (s, r)) -> Type -> r
@@ -299,4 +331,6 @@ everythingWithContextOnTypes s0 r0 (<>) f = go' s0
299331 go s (PrettyPrintFunction t1 t2) = go' s t1 <> go' s t2
300332 go s (PrettyPrintObject t1) = go' s t1
301333 go s (PrettyPrintForAll _ t1) = go' s t1
334+ go s (BinaryNoParensType t1 t2 t3) = go' s t1 <> go' s t2 <> go' s t3
335+ go s (ParensInType t1) = go' s t1
302336 go _ _ = r0
tests/Language/PureScript/Ide/Integration.hs+14
@@ -27,11 +27,13 @@ module Language.PureScript.Ide.Integration
2727 , projectDirectory
2828 , deleteFileIfExists
2929 -- sending commands
30+ , loadModule
3031 , loadModuleWithDeps
3132 , getFlexCompletions
3233 , getType
3334 , addImport
3435 , addImplicitImport
36+ , rebuildModule
3537 -- checking results
3638 , resultIsSuccess
3739 , parseCompletions
@@ -131,6 +133,9 @@ quitServer = do
131133loadModuleWithDeps :: String -> IO String
132134loadModuleWithDeps m = sendCommand $ load [] [m]
133135
136+loadModule :: String -> IO String
137+loadModule m = sendCommand $ load [m] []
138+
134139getFlexCompletions :: String -> IO [(String, String, String)]
135140getFlexCompletions q = parseCompletions <$> sendCommand (completion [] (Just (flexMatcher q)))
136141
@@ -143,6 +148,9 @@ addImport identifier fp outfp = sendCommand (addImportC identifier fp outfp)
143148addImplicitImport :: String -> FilePath -> FilePath -> IO String
144149addImplicitImport mn fp outfp = sendCommand (addImplicitImportC mn fp outfp)
145150
151+rebuildModule :: FilePath -> IO String
152+rebuildModule m = sendCommand (rebuildC m Nothing)
153+
146154-- Command Encoding
147155
148156commandWrapper :: String -> Value -> Value
@@ -166,6 +174,12 @@ addImplicitImportC mn = addImportW $
166174 , "module" .= mn
167175 ]
168176
177+rebuildC :: FilePath -> Maybe FilePath -> Value
178+rebuildC file outFile =
179+ commandWrapper "rebuild" (object [ "file" .= file
180+ , "outfile" .= outFile
181+ ])
182+
169183addImportW :: Value -> FilePath -> FilePath -> Value
170184addImportW importCommand fp outfp =
171185 commandWrapper "import" (object [ "file" .= fp
tests/Language/PureScript/Ide/RebuildSpec.hsnew file+62
@@ -0,0 +1,62 @@
1+module Language.PureScript.Ide.RebuildSpec where
2+
3+import Control.Monad
4+import qualified Language.PureScript.Ide.Integration as Integration
5+import Test.Hspec
6+
7+import System.FilePath
8+
9+compile :: IO ()
10+compile = do
11+ Integration.deleteOutputFolder
12+ s <- Integration.compileTestProject
13+ unless s $ fail "Failed to compile .purs sources"
14+
15+teardown :: IO ()
16+teardown = Integration.quitServer
17+
18+restart :: IO ()
19+restart = Integration.quitServer *> (void Integration.startServer)
20+
21+shouldBeSuccess :: String -> IO ()
22+shouldBeSuccess = shouldBe True . Integration.resultIsSuccess
23+
24+shouldBeFailure :: String -> IO ()
25+shouldBeFailure = shouldBe False . Integration.resultIsSuccess
26+
27+spec :: Spec
28+spec = beforeAll_ compile $ afterAll_ teardown $ before_ restart $ do
29+ describe "Rebuilding single modules" $ do
30+ it "rebuilds a correct module without dependencies successfully" $ do
31+ _ <- Integration.loadModuleWithDeps "RebuildSpecSingleModule"
32+ pdir <- Integration.projectDirectory
33+ let file = pdir </> "src" </> "RebuildSpecSingleModule.purs"
34+ Integration.rebuildModule file >>= shouldBeSuccess
35+ it "fails to rebuild an incorrect module without dependencies and returns the errors" $ do
36+ pdir <- Integration.projectDirectory
37+ let file = pdir </> "src" </> "RebuildSpecSingleModule.fail"
38+ Integration.rebuildModule file >>= shouldBeFailure
39+ it "rebuilds a correct module with its dependencies successfully" $ do
40+ _ <- Integration.loadModuleWithDeps "RebuildSpecWithDeps"
41+ pdir <- Integration.projectDirectory
42+ let file = pdir </> "src" </> "RebuildSpecWithDeps.purs"
43+ Integration.rebuildModule file >>= shouldBeSuccess
44+ it "rebuilds a correct module that has reverse dependencies" $ do
45+ _ <- Integration.loadModuleWithDeps "RebuildSpecWithDeps"
46+ pdir <- Integration.projectDirectory
47+ let file = pdir </> "src" </> "RebuildSpecDep.purs"
48+ Integration.rebuildModule file >>= shouldBeSuccess
49+ it "fails to rebuild a module if its dependencies are not loaded" $ do
50+ _ <- Integration.loadModule "RebuildSpecWithDeps"
51+ pdir <- Integration.projectDirectory
52+ let file = pdir </> "src" </> "RebuildSpecWithDeps.purs"
53+ Integration.rebuildModule file >>= shouldBeFailure
54+ it "rebuilds a correct module with a foreign file" $ do
55+ _ <- Integration.loadModuleWithDeps "RebuildSpecWithForeign"
56+ pdir <- Integration.projectDirectory
57+ let file = pdir </> "src" </> "RebuildSpecWithForeign.purs"
58+ Integration.rebuildModule file >>= shouldBeSuccess
59+ it "fails to rebuild a module with a foreign import but no file" $ do
60+ pdir <- Integration.projectDirectory
61+ let file = pdir </> "src" </> "RebuildSpecWithMissingForeign.fail"
62+ Integration.rebuildModule file >>= shouldBeFailure
tests/Main.hs+5
@@ -27,8 +27,13 @@ import qualified TestDocs
2727import qualified TestPsci
2828import qualified TestPscIde
2929
30+import System.IO (hSetEncoding, stdout, stderr, utf8)
31+
3032main :: IO ()
3133main = do
34+ hSetEncoding stdout utf8
35+ hSetEncoding stderr utf8
36+
3237 heading "Main compiler test suite"
3338 TestCompiler.main
3439 heading "Documentation test suite"
tests/TestDocs.hs+6−6
@@ -285,12 +285,12 @@ testCases =
285285 , ValueShouldHaveTypeSignature (n "ExplicitTypeSignatures") "aNumber" (ShowFn (P.tyNumber ==))
286286 ])
287287
288− , ("ConstrainedArgument",
289− [ TypeSynonymShouldRenderAs (n "ConstrainedArgument") "WithoutArgs" "forall a. (Partial => a) -> a"
290− , TypeSynonymShouldRenderAs (n "ConstrainedArgument") "WithArgs" "forall a. (Foo a => a) -> a"
291− , TypeSynonymShouldRenderAs (n "ConstrainedArgument") "MultiWithoutArgs" "forall a. ((Partial, Partial) => a) -> a"
292− , TypeSynonymShouldRenderAs (n "ConstrainedArgument") "MultiWithArgs" "forall a b. ((Foo a, Foo b) => a) -> a"
293− ])
288+ --, ("ConstrainedArgument",
289+ -- [ TypeSynonymShouldRenderAs (n "ConstrainedArgument") "WithoutArgs" "forall a. (Partial => a) -> a"
290+ -- , TypeSynonymShouldRenderAs (n "ConstrainedArgument") "WithArgs" "forall a. (Foo a => a) -> a"
291+ -- , TypeSynonymShouldRenderAs (n "ConstrainedArgument") "MultiWithoutArgs" "forall a. ((Partial, Partial) => a) -> a"
292+ -- , TypeSynonymShouldRenderAs (n "ConstrainedArgument") "MultiWithArgs" "forall a b. ((Foo a, Foo b) => a) -> a"
293+ -- ])
294294 ]
295295
296296 where
tests/support/pscide/src/RebuildSpecDep.pursnew file+3
@@ -0,0 +1,3 @@
1+module RebuildSpecDep where
2+
3+dep = 42
tests/support/pscide/src/RebuildSpecSingleModule.failnew file+3
@@ -0,0 +1,3 @@
1+module RebuildSpecSingleModule where
2+
3+let anerror
tests/support/pscide/src/RebuildSpecSingleModule.pursnew file+4
@@ -0,0 +1,4 @@
1+module RebuildSpecSingleModule where
2+
3+id x = x
4+const x y = x
tests/support/pscide/src/RebuildSpecWithDeps.pursnew file+5
@@ -0,0 +1,5 @@
1+module RebuildSpecWithDeps where
2+
3+import RebuildSpecDep (dep)
4+
5+x = dep
tests/support/pscide/src/RebuildSpecWithForeign.jsnew file+3
@@ -0,0 +1,3 @@
1+// module RebuildSpecWithForeign
2+
3+exports.f = 5;
tests/support/pscide/src/RebuildSpecWithForeign.pursnew file+3
@@ -0,0 +1,3 @@
1+module RebuildSpecWithForeign where
2+
3+foreign import f :: Int
tests/support/pscide/src/RebuildSpecWithMissingForeign.failnew file+3
@@ -0,0 +1,3 @@
1+module RebuildSpecWithMissingForeign where
2+
3+foreign import f :: Int