Split into packages (#3793) · purescript/purescript@183fc22 · GitHub
Skip to content

Commit 183fc22

Browse files
authored
Split into packages (#3793)
* Move `SimpleErrorMessage` to `Errors` In 4828b5d, we moved `Language.PureScript.Errors.SimpleErrorMessage` to `Language.PureScript.AST.Declarations`. Per the comment in the Pull Request: #2230 (comment), we did this because we wanted to move `Language.PureScript.Errors.ErrorMessageHint` into `Language.PureScript.AST.Declarations.Expr`. Thing is, we didn't have to move everything just to move `Language.PureScript.Errors.ErrorMessageHint`. In fact, by making this move, we forced the AST to require knowledge about every type of error that can be created. For example, the AST has to know about parse errors (something that should happen before creating an AST) and code generation errors (something that should happen after creating an AST). In an ideal world, the AST would only know about errors that come about from modifications to the AST itself. The real issue that this led to was that the AST had to know about the errors that came about from the CST. Given that the CST is the surface syntax of the AST, that requirement seems a bit off. With the dependencies inverted this way, it's hard to decouple the AST from the CST. We take a step towards the ideal world by moving `Language.PureScript.AST.Declarations.SimpleErrorMessage` back into `Language.PureScript.Errors`. This should allow us to extract the AST from the `purescript` package itself such that it can be built upon in isolation from the rest of the package. We should revisit why `Language.PureScript.AST.Declarations.SimpleErrorMessage` is so massive in the future. It will probably make sense to separate the data type into the different categories of errors so those errors can live closer to where they should be constructed. * Split the constants based on Prim and Prelude Prim stuff is part of PureScript the language, Prelude is part of the PureScript conventions. PureScript the language doesn't require an existence of Prelude in order to work properly. Instead of mixing these two levels, we separate the constants so we can pull the Prim constants out with the AST. In order to not break everything, we re-export the constants from the original module. We should put a timer on this and remove the re-exports after that point so we don't wind up with a bunch of cruft like the other re-export modules. * Extract AST to its own package We've gone quite a ways with a sinle package for everything PureScript related. This has led to incredibly long compile times if you want to consume PureScript the library, as you have to compile everything no matter how much you want to really use. To help with downstream consumers, we start splitting into packages of useful functionality. We start with the AST as this _should_ be the very basis of everything PureScript related. From the AST, someone ought to be able to build packages atop it that add more functionality to the PureScript language. For instance, we can split out the CST as a package that builds atop the AST and adds more functionality (namely, parsing). It's maybe a little disheartening that there don't appear to be any tests around the AST. Maybe with things separated out a bit more, it'll be more inviting to write some tests. The modules we move here might not be all that intuitive, but they seem to be the core of what the PureScript AST is all about. The only questionable modules are the `Control.Monad.Supply` and `Control.Monad.Supply.Class` modules. We could flip the dependency in `Language.PureScript.Names` and move those values into the `Control.Monad.Supply.Class` module. It's unclear which way to go. Since the `Control.Monad.Supply.Class` module isn't in the `Language.PureScript` hierarchy, it might make sense for it to stay in the top-level. However, it might be too general for that and should ideally live in its own package (maybe even outside the project?). We also use PackageImports judiciously. When trying to figure out which dependencies went where, it was much harder than it should have been to figure this stuff out. When trying to figure out which dependencies were used and necessary, it was even harder to figure what the situation was. Finally, when trying to figure out where `Control.Monad.Supply.Class` came from, it took a frustratingly long amount of time to realize it was a module we had defined in the project. For all of these reasons, we use PackageImports to help future us know which dependencies are used, and where. Of course there are tools like weeder (https://github.com/ndmitchell/weeder) to help with finding unused dependencies and whatnot. But, it's also good to know statically what is being used and to allow other tools to be used. Finally, we update the license-generator to work with this split off package. We might have to do more work before we're done, but we can at least generate the license file in a similar manner to how we do at the top-level. * Extract the CST to a package We extract out the CST to its own package that builds atop the AST. This should make it a bit easier to build other tooling atop the CST. In particular, anything that might need to parse PureScript files can now depend on this package to do so. Since this new package only depends on `purescript-ast` (and its transitive dependencies), it can be built in a reasonable amount of time. It's important to note that we don't pull out `Language.PureScript.CST`. That module is straddling the line between a re-exporting "prelude" and an adapter between `purescript-ast` and `purescript`. Since it deals with errors, and errors currently exist at the top-level, we cannot yet move this module down into `purescript-cst`. Probably what needs to happen is that we make a split between `Language.PureScript.CST` being a re-exporter and `Language.PureScript.CST` doing adapter work. Not clear which way to go on this one as both seem viable avenues. It's really great to see a test suite around some of this deep down functionality. Maybe we can use this example to feed back into the AST and make a test suite there. * Move sensible extensions into `default-extensions` Per review, we want our extension strategy to be that we have a uniform language across the codebase with the exception of questionable extensions like `TemplateHaskell`. We move as many sensible extensions to the `default-extensions` field in `package.yaml` so we start building up our uniform language. There are three other extensions we don't move at the moment: `CPP`, `DeriveAnyClass`, and `ImplicitParams`. * `CPP` - This extension is just as questionable (if not more so) as `TemplateHaskell`. Following a similar reasoning, we force people to turn it on explicitly. It's only used in the `Language.PureScript.Crash` module. That module might be better off if we stopped casing on the compiler version. It doesn't seem like we support older versions of GHC anymore, so we might be better off dumping the extension outright. * `DeriveAnyClass` - This extension is known to interact weirdly with `GeneralizedNewtypeDeriving`: https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/deriving-strategies. Since we use `GeneralizedNewtypeDeriving` in more places, and `DerivingStrategies` exists to address the issues with `DeriveAnyClass`, we don't turn this on across the entire codebase. * `ImplicitParams` - Similar to `CPP`, this extension is only used in the `Language.PureScript.Crash` module. And similarly, if we don't support older versions of GHC, we can drop this extension outright. If any of this is the wrong decision, we can always change it. * Move sensible extensions to `default-extensions` Similar to the motivation behind moving `purescript-ast`s extensions to the `default-extensions` field of its `package.yaml`, we follow suit and move the sensible extensions to `purescript-cst`s `default-extensions` field of its `package.yaml`. We ended up dropping `MonoLocalBinds`, as the module compiles without the extension. * Only generate license for `purescript` package The license generator exists for the sake of distributing the licenses that the `purescript` binary uses. We don't need to use the generator for the other packages. We want the other packages to have a normal license file. We also roll back the changes to the `Makefile`. * Move `purescript-ast` to version 0.1.0.0 Per review, this seems like a way to go that should foster each package being able to evolve in a way that isn't hindered by the rest of the packages at large. * Move `purescript-cst` to version 0.1.0.0 Per review, this seems like a way to go that should foster each package being able to evolve in a way that isn't hindered by the rest of the packages at large. * Remove re-export compatibility module We only kept `Language.PureScript.Constants` around so we could figure out the changes while we were splitting out `purescript-ast`. Now that things have settled down a bit, we remove the module and use the other imports directly. * Setup sdists for each package Now that we have more than one package, we have to do things a little different. `stack sdist` will create an sdist for each package. This means we end up with a directory that looks like: ```console $ tree sdist-test sdist-test ├── purescript-0.13.6.tar.gz ├── purescript-ast-0.1.0.0.tar.gz └── purescript-cst-0.1.0.0.tar.gz 0 directories, 3 files ``` If we try to use `tar -xzf sdist-test/purescript-*.tar.gz -C sdist-test --strip-components=1`, the glob will expand to all three sdists and fail with a cryptic error: ```console $ tar -xzf sdist-test/purescript-0.13.6.tar.gz sdist-test/purescript-ast-0.1.0.0.tar.gz sdist-test/purescript-cst-0.1.0.0.tar.gz -C sdist-test --strip-components=1 tar: sdist-test/purescript-ast-0.1.0.0.tar.gz: Not found in archive tar: sdist-test/purescript-cst-0.1.0.0.tar.gz: Not found in archive tar: Exiting with failure status due to previous errors ``` We change to mirroring the directory structure within the `sdist-test` directory, and running that way. It's a bit unfortunate that the top-level package has to be handled differently, but this should help us move forward.
1 parent 281eb3c commit 183fc22

101 files changed

Lines changed: 917 additions & 714 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎Makefile‎

Lines changed: 1 addition & 2 deletions

‎ci/build.sh‎

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,11 @@ fi
3434
$STACK build --only-snapshot $STACK_OPTS
3535

3636
# Test in a source distribution (see above)
37-
$STACK sdist --tar-dir sdist-test;
37+
$STACK sdist lib/purescript-ast --tar-dir sdist-test/lib/purescript-ast
38+
tar -xzf sdist-test/lib/purescript-ast/purescript-ast-*.tar.gz -C sdist-test/lib/purescript-ast --strip-components=1
39+
$STACK sdist lib/purescript-cst --tar-dir sdist-test/lib/purescript-cst
40+
tar -xzf sdist-test/lib/purescript-cst/purescript-cst-*.tar.gz -C sdist-test/lib/purescript-cst --strip-components=1
41+
$STACK sdist . --tar-dir sdist-test;
3842
tar -xzf sdist-test/purescript-*.tar.gz -C sdist-test --strip-components=1
3943
pushd sdist-test
4044
$STACK build --pedantic $STACK_OPTS

‎lib/purescript-ast/.gitignore‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
purescript-ast.cabal

‎lib/purescript-ast/LICENSE‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
Copyright (c) 2013-17 Phil Freeman, (c) 2014-2017 Gary Burgess, and other
2+
contributors
3+
All rights reserved.
4+
5+
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6+
7+
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8+
9+
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
10+
11+
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
12+
13+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

‎lib/purescript-ast/README.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# purescript-ast
2+
3+
Defines the underlying syntax of the PureScript Programming Language.
4+
5+
## Compiler compatibility
6+
7+
We provide a table to make it a bit easier to map between versions of `purescript` and `purescript-ast`.
8+
9+
| `purescript` | `purescript-ast` |
10+
| --- | --- |
11+
| `0.13.6` | `0.1.0.0` |

‎lib/purescript-ast/Setup.hs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Main where
2+
3+
import Distribution.Simple
4+
5+
main :: IO ()
6+
main = defaultMain

‎lib/purescript-ast/package.yaml‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: purescript-ast
2+
version: '0.1.0.0'
3+
synopsis: PureScript Programming Language Abstract Syntax Tree
4+
description: Defines the underlying syntax of the PureScript Programming Language.
5+
category: Language
6+
author: Phil Freeman <paf31@cantab.net>
7+
maintainer: >
8+
Gary Burgess <gary.burgess@gmail.com>,
9+
Hardy Jones <jones3.hardy@gmail.com>,
10+
Harry Garrood <harry@garrood.me>,
11+
Christoph Hegemann <christoph.hegemann1337@gmail.com>,
12+
Liam Goodacre <goodacre.liam@gmail.com>,
13+
Nathan Faubion <nathan@n-son.com>
14+
copyright: (c) 2013-17 Phil Freeman, (c) 2014-19 Gary Burgess, (c) other contributors (see CONTRIBUTORS.md)
15+
license: BSD3
16+
github: purescript/purescript
17+
homepage: http://www.purescript.org/
18+
extra-source-files:
19+
- README.md
20+
dependencies:
21+
- aeson >=1.0 && <1.5
22+
- base >=4.11 && <4.13
23+
- base-compat >=0.6.0
24+
- bytestring
25+
- containers
26+
- deepseq
27+
- filepath
28+
- microlens-platform >=0.3.9.0 && <0.4
29+
- mtl >=2.1.0 && <2.3.0
30+
- protolude >=0.1.6 && <0.2.4
31+
- scientific >=0.3.4.9 && <0.4
32+
- text
33+
- vector
34+
35+
library:
36+
source-dirs: src
37+
ghc-options: -Wall -O2
38+
default-extensions:
39+
- ConstraintKinds
40+
- DataKinds
41+
- DefaultSignatures
42+
- DeriveFunctor
43+
- DeriveFoldable
44+
- DeriveTraversable
45+
- DeriveGeneric
46+
- DerivingStrategies
47+
- EmptyDataDecls
48+
- FlexibleContexts
49+
- FlexibleInstances
50+
- GeneralizedNewtypeDeriving
51+
- KindSignatures
52+
- LambdaCase
53+
- MultiParamTypeClasses
54+
- NoImplicitPrelude
55+
- PackageImports
56+
- PatternGuards
57+
- PatternSynonyms
58+
- RankNTypes
59+
- RecordWildCards
60+
- OverloadedStrings
61+
- ScopedTypeVariables
62+
- TupleSections
63+
- TypeFamilies
64+
- ViewPatterns
65+
66+
stability: experimental

src/Control/Monad/Supply.hs renamed to lib/purescript-ast/src/Control/Monad/Supply.hs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
1-
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2-
31
-- |
42
-- Fresh variable supply
53
--
64
module Control.Monad.Supply where
75

8-
import Prelude.Compat
6+
import "base-compat" Prelude.Compat
97

10-
import Control.Applicative
11-
import Control.Monad.Error.Class (MonadError(..))
12-
import Control.Monad.Reader
13-
import Control.Monad.State
14-
import Control.Monad.Writer
8+
import "base" Control.Applicative
9+
import "mtl" Control.Monad.Error.Class (MonadError(..))
10+
import "mtl" Control.Monad.Reader
11+
import "mtl" Control.Monad.State
12+
import "mtl" Control.Monad.Writer
1513

16-
import Data.Functor.Identity
14+
import "base" Data.Functor.Identity
1715

1816
newtype SupplyT m a = SupplyT { unSupplyT :: StateT Integer m a }
1917
deriving (Functor, Applicative, Monad, MonadTrans, MonadError e, MonadWriter w, MonadReader r, Alternative, MonadPlus)

src/Control/Monad/Supply/Class.hs renamed to lib/purescript-ast/src/Control/Monad/Supply/Class.hs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,14 @@
22
-- A class for monads supporting a supply of fresh names
33
--
44

5-
{-# LANGUAGE DefaultSignatures #-}
6-
{-# LANGUAGE TypeFamilies #-}
7-
85
module Control.Monad.Supply.Class where
96

10-
import Prelude.Compat
7+
import "base-compat" Prelude.Compat
118

12-
import Control.Monad.Supply
13-
import Control.Monad.State
14-
import Control.Monad.Writer
15-
import Data.Text (Text, pack)
9+
import "this" Control.Monad.Supply
10+
import "mtl" Control.Monad.State
11+
import "mtl" Control.Monad.Writer
12+
import "text" Data.Text (Text, pack)
1613

1714
class Monad m => MonadSupply m where
1815
fresh :: m Integer
Lines changed: 14 additions & 0 deletions

0 commit comments

Comments
 (0)