git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
236 files changed+2723−15359
since splitsnapshots
unifiedsplit
.gitignore+13 .travis.yml−3 CONTRIBUTING.md−18 ChangeLog.md+3 LICENSE+26−16 README-go.md+48 README.md+38−10 RELEASE-0.2.md−85 RELEASE-0.3.md−85 RELEASE-0.4.md−60 Setup.hs+1−37 app/Main.hs+250 default.nix+23 docgen/Main.hs−226 docs/.gitignore−1 docs/Makefile−177 docs/source/conf.py−258 docs/source/ffi.rst−40 docs/source/images/Prelude.png docs/source/index.rst−31 docs/source/intro.rst−106 docs/source/kinds.rst−21 docs/source/modules.rst−57 docs/source/patterns.rst−139 docs/source/prelude.rst−365 docs/source/start.rst−62 docs/source/syntax.rst−266 docs/source/typeclasses.rst−48 docs/source/types.rst−158 examples/.gitignore−1 examples/failing/ArrayType.purs−11 examples/failing/Arrays.purs−5 examples/failing/Do.purs−8 examples/failing/KindError.purs−3 examples/failing/Let.purs−3 examples/failing/MPTCs.purs−7 examples/failing/MutRec.purs−5 examples/failing/MutRec2.purs−3 examples/failing/NoOverlap.purs−11 examples/failing/NullaryAbs.purs−3 examples/failing/Object.purs−5 examples/failing/OverlappingVars.purs−12 examples/failing/Rank2Types.purs−7 examples/failing/Reserved.purs−4 examples/failing/SkolemEscape.purs−5 examples/failing/SkolemEscape2.purs−9 examples/failing/Superclasses1.purs−11 examples/failing/Superclasses2.purs−9 examples/failing/Superclasses3.purs−5 examples/failing/Superclasses4.purs−12 examples/failing/TypeClassInstances.purs−8 examples/failing/TypeClasses2.purs−8 examples/failing/TypeError.purs−5 examples/failing/TypeSynonyms.purs−5 examples/failing/TypeSynonyms2.purs−9 examples/failing/TypeSynonyms3.purs−9 examples/failing/UnifyInTypeInstanceLookup.purs−17 examples/failing/UnknownType.purs−4 examples/failing/UnknownValue.purs−25 examples/manual/failing/ArgLengthMismatch.purs−4 examples/manual/failing/ExportExplicit.purs−5 examples/manual/failing/ExportExplicit1.purs−14 examples/manual/failing/ExportExplicit2.purs−5 examples/manual/failing/ExportExplicit3.purs−13 examples/manual/failing/ImportExplicit.purs−7 examples/manual/failing/ImportExplicit2.purs−7 examples/manual/failing/ImportModule.purs−7 examples/manual/failing/OrphanTypeDecl.purs−3 examples/manual/failing/RedefinedFixity.purs−6 examples/manual/failing/RequiredHiddenType.purs−8 examples/manual/passing/ExportExplicit.purs−20 examples/manual/passing/ExportExplicit2.purs−15 examples/manual/passing/Import.purs−19 examples/manual/passing/ImportExplicit.purs−14 examples/manual/passing/ImportQualified.purs−12 examples/manual/passing/Module.purs−28 examples/manual/passing/ModuleDeps.purs−17 examples/manual/passing/RedefinedFixity.purs−24 examples/passing/Applicative.purs−16 examples/passing/ArrayType.purs−9 examples/passing/Arrays.purs−24 examples/passing/Auto.purs−13 examples/passing/AutoPrelude.purs−8 examples/passing/AutoPrelude2.purs−9 examples/passing/BindersInFunctions.purs−16 examples/passing/CheckSynonymBug.purs−14 examples/passing/Church.purs−18 examples/passing/Collatz.purs−18 examples/passing/Conditional.purs−9 examples/passing/Console.purs−13 examples/passing/DataAndType.purs−7 examples/passing/Do.purs−67 examples/passing/Dollar.purs−16 examples/passing/Eff.purs−19 examples/passing/EmptyDataDecls.purs−30 examples/passing/EmptyTypeClass.purs−12 examples/passing/EqOrd.purs−14 examples/passing/ExternData.purs−13 examples/passing/ExternRaw.purs−13 examples/passing/FFI.purs−11 examples/passing/Fib.purs−15 examples/passing/FinalTagless.purs−22 examples/passing/ForeignInstance.purs−16 examples/passing/FunctionScope.purs−17 examples/passing/Functions.purs−15 examples/passing/Functions2.purs−17 examples/passing/Guards.purs−14 examples/passing/InferRecFunWithConstrainedArgument.purs−8 examples/passing/JSReserved.purs−12 examples/passing/Let.purs−64 examples/passing/LetInInstance.purs−12 examples/passing/LiberalTypeSynonyms.purs−19 examples/passing/MPTCs.purs−20 examples/passing/Match.purs−7 examples/passing/Monad.purs−32 examples/passing/MonadState.purs−48 examples/passing/MultiArgFunctions.purs−14 examples/passing/MultipleConstructorArgs.purs−21 examples/passing/MutRec.purs−19 examples/passing/NamedPatterns.purs−7 examples/passing/Nested.purs−7 examples/passing/NestedTypeSynonyms.purs−11 examples/passing/ObjectSynonym.purs−13 examples/passing/ObjectUpdate.purs−18 examples/passing/Objects.purs−30 examples/passing/OneConstructor.purs−7 examples/passing/Operators.purs−80 examples/passing/OptimizerBug.purs−9 examples/passing/Patterns.purs−28 examples/passing/Person.purs−16 examples/passing/Rank2Data.purs−29 examples/passing/Rank2Types.purs−11 examples/passing/Recursion.purs−10 examples/passing/RuntimeScopeIssue.purs−19 examples/passing/STArray.purs−25 examples/passing/Sequence.purs−12 examples/passing/SignedNumericLiterals.purs−15 examples/passing/Superclasses1.purs−18 examples/passing/Superclasses2.purs−23 examples/passing/Superclasses3.purs−41 examples/passing/TailCall.purs−15 examples/passing/Tick.purs−5 examples/passing/TopLevelCase.purs−18 examples/passing/TypeClasses.purs−69 examples/passing/TypeClassesInOrder.purs−11 examples/passing/TypeClassesWithOverlappingTypeVariables.purs−11 examples/passing/TypeDecl.purs−12 examples/passing/TypeSynonymInData.purs−9 examples/passing/TypeSynonyms.purs−25 examples/passing/TypedWhere.purs−13 examples/passing/Unit.purs−6 examples/passing/UnknownInTypeClassLookup.purs−12 examples/passing/Where.purs−49 examples/passing/iota.purs−9 examples/passing/s.purs−5 hierarchy/Main.hs−103 package.yaml+86 prelude/README.md−321 prelude/images/Prelude.png prelude/prelude.purs−797 prelude/updateDocs.sh−11 psc-make/Main.hs−145 psc/Main.hs−154 psci/Commands.hs−68 psci/Main.hs−400 psci/Parser.hs−92 psgo.cabal+145 purescript.cabal−147 src/CodeGen/IL.hs+321 src/CodeGen/IL/Common.hs+196 src/CodeGen/IL/Optimizer.hs+81 src/CodeGen/IL/Optimizer/Common.hs+18 src/CodeGen/IL/Optimizer/Inliner.hs+435 src/CodeGen/IL/Optimizer/MagicDo.hs+146 src/CodeGen/IL/Optimizer/TCO.hs+141 src/CodeGen/IL/Printer.hs+527 src/Language/PureScript.hs−256 src/Language/PureScript/CodeGen.hs−25 src/Language/PureScript/CodeGen/Common.hs−141 src/Language/PureScript/CodeGen/Externs.hs−96 src/Language/PureScript/CodeGen/JS.hs−357 src/Language/PureScript/CodeGen/JS/AST.hs−317 src/Language/PureScript/Constants.hs−201 src/Language/PureScript/DeadCodeElimination.hs−105 src/Language/PureScript/Declarations.hs−820 src/Language/PureScript/Environment.hs−191 src/Language/PureScript/Errors.hs−111 src/Language/PureScript/Kinds.hs−60 src/Language/PureScript/ModuleDependencies.hs−76 src/Language/PureScript/Names.hs−85 src/Language/PureScript/Optimizer.hs−73 src/Language/PureScript/Optimizer/Blocks.hs−33 src/Language/PureScript/Optimizer/Common.hs−77 src/Language/PureScript/Optimizer/Inliner.hs−152 src/Language/PureScript/Optimizer/MagicDo.hs−157 src/Language/PureScript/Optimizer/TCO.hs−103 src/Language/PureScript/Optimizer/Unused.hs−30 src/Language/PureScript/Options.hs−70 src/Language/PureScript/Parser.hs−34 src/Language/PureScript/Parser/Common.hs−378 src/Language/PureScript/Parser/Declarations.hs−430 src/Language/PureScript/Parser/Kinds.hs−45 src/Language/PureScript/Parser/State.hs−30 src/Language/PureScript/Parser/Types.hs−116 src/Language/PureScript/Pretty.hs−32 src/Language/PureScript/Pretty/Common.hs−69 src/Language/PureScript/Pretty/JS.hs−255 src/Language/PureScript/Pretty/Kinds.hs−59 src/Language/PureScript/Pretty/Types.hs−119 src/Language/PureScript/Pretty/Values.hs−226 src/Language/PureScript/Sugar.hs−59 src/Language/PureScript/Sugar/BindingGroups.hs−149 src/Language/PureScript/Sugar/CaseDeclarations.hs−115 src/Language/PureScript/Sugar/DoNotation.hs−74 src/Language/PureScript/Sugar/Names.hs−468 src/Language/PureScript/Sugar/Operators.hs−152 src/Language/PureScript/Sugar/TypeClasses.hs−219 src/Language/PureScript/Sugar/TypeDeclarations.hs−66 src/Language/PureScript/Supply.hs−56 src/Language/PureScript/Traversals.hs−34 src/Language/PureScript/TypeChecker.hs−209 src/Language/PureScript/TypeChecker/Kinds.hs−185 src/Language/PureScript/TypeChecker/Monad.hs−204 src/Language/PureScript/TypeChecker/Synonyms.hs−55 src/Language/PureScript/TypeChecker/Types.hs−1121 src/Language/PureScript/TypeClassDictionaries.hs−62 src/Language/PureScript/Types.hs−276 src/Tests.hs+141 stack.nix+23 stack.yaml+24 support/ffi-loader.go+30 support/go.mod.ffi-loader+2 support/go.mod.output+2 support/go.mod.working+1 test/Spec.hs+2 tests/Main.hs−103
.gitignore+13
@@ -8,3 +8,16 @@ cabal.sandbox.config
88*.chs.h
99*.lksh*
1010.virthualenv
11+.psci_modules/
12+.test_modules/
13+bower_components/
14+node_modules
15+tmp/
16+.stack-work/
17+stack.yaml.lock
18+output
19+examples/docs/docs/
20+core-tests/full-core-docs.md
21+.psc-ide-port
22+.vscode/
23+result
.travis.ymldeleted−3
@@ -1,3 +0,0 @@
1−language: haskell
2−notifications:
3− email: true
CONTRIBUTING.mddeleted−18
@@ -1,18 +0,0 @@
1−An introductory overview of the compiler is available [here](https://www.youtube.com/watch?v=Y3P1dxqwFiE).
2−
3−Pull requests are encouraged.
4−
5−Please follow the following guidelines:
6−
7−- Add at least a test to `examples/passing/` and possibly to `examples/failing`.
8−- Build the binaries and libs with `cabal build`
9−- Install the binaries and libs with `cabal install`.
10−- Run `cabal configure --enable-tests && cabal build && cabal test` to build the test suite.
11−- Run `purescript-test-everything` to make sure you haven't broken any core library builds.
12−- Run `starter-kit` to make sure the starter kit has not been broken.
13−
14−If you would like to contribute, please consider the issues in the current milestone first.
15−
16−Finally, if you have made code changes and would like to be included in the copyright notice in the cabal file, please include that change in your pull request.
17−
18−To prevent core libraries from getting broken, every change must be reviewed. A pull request will be merged as long as one other team member has verified the changes.
ChangeLog.mdnew file+3
@@ -0,0 +1,3 @@
1+# Changelog for pscpp
2+
3+## Unreleased changes
LICENSE+26−16
@@ -1,20 +1,30 @@
1−The MIT License (MIT)
1+Copyright Andy Arvanitis (c) 2018
22
3−Copyright (c) 2013 Phil Freeman
3+All rights reserved.
44
5−Permission is hereby granted, free of charge, to any person obtaining a copy of
6−this software and associated documentation files (the "Software"), to deal in
7−the Software without restriction, including without limitation the rights to
8−use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9−the Software, and to permit persons to whom the Software is furnished to do so,
10−subject to the following conditions:
5+Redistribution and use in source and binary forms, with or without
6+modification, are permitted provided that the following conditions are met:
117
12−The above copyright notice and this permission notice shall be included in all
13−copies or substantial portions of the Software.
8+ * Redistributions of source code must retain the above copyright
9+ notice, this list of conditions and the following disclaimer.
1410
15−THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16−IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17−FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18−COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19−IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20−CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
11+ * Redistributions in binary form must reproduce the above
12+ copyright notice, this list of conditions and the following
13+ disclaimer in the documentation and/or other materials provided
14+ with the distribution.
15+
16+ * Neither the name of Author name here nor the names of other
17+ contributors may be used to endorse or promote products derived
18+ from this software without specific prior written permission.
19+
20+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
README-go.mdnew file+48
@@ -0,0 +1,48 @@
1+
2+### psgo
3+
4+#### Performance
5+
6+* No runtime system beyond some support types and functions
7+* Uses PureScript's normal tail call optimization techniques for generated Go code
8+
9+#### Differences from PureScript:
10+
11+* Foreign imports/exports are Go instead of JavaScript – see [standard library foreign implementations](https://github.com/andyarvanitis/purescript-native-go-ffi)
12+* No Go-specific REPL
13+
14+#### Other notes:
15+
16+* The provided `Any` type is just an alias for `interface{}`
17+* PureScript types are represented in Go with:
18+
19+ | PureScript | Go |
20+ |------------|----|
21+ |`Array` | `[]Any`|
22+ |`String` | `string`|
23+ |`Number` | `float64`|
24+ |`Int` | `int`|
25+ |`Char` | `string` (single UTF-8 entity)|
26+ |`Boolean` | `bool`|
27+ |Records | `map[string]Any`|
28+
29+#### Future ideas:
30+
31+* Nice facilities (modules) for concurrency/parallelism, using goroutines
32+
33+
34+#### Getting Started
35+This assumes you are running macOS (OS X) or a Unix-like system (Linux, *BSD, etc.).
36+
37+1. Choose a working directory wherever you like. Then create a `src` subdirectory under it, which will be where you will place your own PureScript source files.
38+
39+1. Initialize your project with `spago init`, and install any dependencies with `spago install` (please see their instructions if you haven't used it before).
40+
41+1. Add the `backend = "psgo"` option to your `spago.dhall` file. That way `spago` will use the psgo backend when compiling.
42+
43+1. You should now be ready to build a PureScript program:
44+ * As stated above, place your source file(s) in the working directory's `src` subdirectory and execute `spago build`.
45+
46+ * This will generate the Go source tree for your program and then build an executable binary. The resulting executable will be in your working directory and will be named `Main`. The generated source files will be under `output/`.
47+
48+---
README.md+38−10
@@ -1,13 +1,41 @@
1−[![Build Status](https://secure.travis-ci.org/purescript/purescript.png?branch=master)](http://travis-ci.org/purescript/purescript)
2−[![Hackage](https://budueba.com/hackage/purescript)](http://hackage.haskell.org/package/purescript)
1+[![PureScript](https://raw.githubusercontent.com/purescript/purescript/master/logo.png)](http://purescript.org)
32
4−PureScript is a small strongly, statically typed programming language with expressive types, written in and inspired by Haskell, and compiling to Javascript.
3+This is a platform-native compiler backend for [PureScript](https://github.com/purescript/purescript). It attempts to generate "sane", debuggable, and portable [C++11](https://isocpp.org/wiki/faq/cpp11) (or later) or [Go](https://golang.org/) code as an intermediate language, which is then compiled to a native executable binary. This also enables easy interoperability with existing C/C++ or Go frameworks and libraries on a number of platforms.
54
6−## Resources
5+There are two utilities in the purescript-native "suite": `pscpp` and `psgo`. The source code in this branch is for `psgo`, the purescript-to-Go transpiler. For the source code of the `pscpp` purescript-to-C++ transpiler, please see the [cpp branch](https://github.com/andyarvanitis/purescript-native/tree/cpp).
76
8−- [Documentation](http://purescript.readthedocs.org/)
9−- [#purescript IRC @ FreeNode](irc://irc.freenode.net/#purescript)
10−- [Twitter](http://twitter.com/purescript)
11−- [Try PureScript!](http://tryps.functorial.com/)
12−- [Release Notes](https://github.com/purescript/purescript/blob/master/RELEASE.md)
13−- [Contributing to PureScript](https://github.com/purescript/purescript/blob/master/CONTRIBUTING.md)
7+#### Platforms
8+* Although purescript-native should work on any platform supporting PureScript and modern C++ or Go, the generated code and resulting binary executables have been tested on:
9+ * macOS Mojave 10.14.5 – full test suite
10+ * For C++, Xcode 10.2.1's `clang` was used
11+ * For Go, `go` version 1.12.7 was used
12+ * Windows 10 x64 – full test suite
13+ * C++: Visual Studio 2017 and `clang`
14+ * Go: `go` version 1.12.7
15+ * Linux Debian 9.5 amd64 – full test suite (C++)
16+ * Default versions of `clang` and `gcc`
17+ * Linux Debian 10 amd64 – full test suite (Go)
18+ * Default version of `go`
19+ * Raspberry Pi 3 B+ Raspbian official build (ARM), default versions of `clang` and `gcc`
20+
21+
22+#### Requirements for building `pscpp` and `psgo`
23+
24+* [Haskell Stack](https://docs.haskellstack.org/en/stable/README/) (if you're running macOS 10.14.5+, you can use pre-built binaries from [here](https://github.com/andyarvanitis/purescript-native/releases/))
25+
26+#### Requirements for using PureScript + purescript-native
27+
28+* A recent version (0.13+) of [purescript](https://github.com/purescript/purescript/releases).
29+
30+* For `pscpp`, a C++11-capable toolchain, e.g. recent versions of clang, gcc, Microsoft Visual Studio
31+ * GNU Make + `psc-package` is the default supported build tool, but you should be able to use your favorite package manager, C++ build system, tools, debuggers, etc.
32+* For `psgo`, the [Go toolchain](https://golang.org) for your system
33+ * You can use your favorite PureScript package manager and build tools – but for simplicity, [`spago`](https://github.com/spacchetti/spago) is recommended.
34+
35+
36+#### For more information and a Getting Started guide, please see
37+* [`pscpp`](https://github.com/andyarvanitis/purescript-native/blob/cpp/README-cpp.md)
38+* [`psgo`](https://github.com/andyarvanitis/purescript-native/blob/golang/README-go.md)
39+
40+
41+---
RELEASE-0.2.mddeleted−85
@@ -1,85 +0,0 @@
1−## 0.2.0 Changes
2−
3−Many thanks to the [contributors](https://github.com/purescript/purescript/graphs/contributors) who helped with this release.
4−
5−- Full language guide can be found [here](http://functorial.com/purescript).
6−- Try out the latest features [here](http://tryps.functorial.com).
7−
8−### New Features
9−
10−- RankNTypes
11−
12− This experimental feature allows polymorphic types (introduced with `forall`) to appear on the left of a function arrow, or as the type of a record field, etc. For example:
13−
14− rank2 :: (forall a. a -> a) -> Number
15− rank2 = \f -> if f true then f 1 else f 2
16−
17−- Modules
18−- Polymorphic Object Update
19−
20− Records now support member update in which the type of the field changes during the update. For example:
21−
22− data Wrap a = Wrap a
23−
24− update = \o -> o { prop = Wrap o.prop }
25−
26−### Enhancements
27−
28−- Naked expressions as statements
29−
30− Naked expressions of type `{}` can now be used as statements.
31−
32−- Split code generation into `AST -> JS` and `JS -> String`
33−
34− JavaScript generation is now split into the generation of a JavaScript AST, and the pretty-printing of that AST. This enables some optimizations, and a better JavaScript pretty-printer.
35−
36−- Syntactic sugar for introducing curried functions
37−
38− Single-argument functions and multiple-argument functions can now be introduced in the same way:
39−
40− test = \a (b, c) d -> a + b + c + d
41−
42−- JavaScript optimizations
43−
44− Some basic dead-variable elimination, inlining and eta-conversion are now performed on the generated JavaScript.
45−
46−- Generate formatted Javascript
47−
48− The generated JavaScript is now formatted to be more readable. In particular, newlines get generated, and the correct indentation is used.
49−
50−- More valid infix operators
51−
52− The colon and period characters are now valid in infix operator names.
53−
54−### Syntax Changes
55−
56−- Avoid 'do' keyword for blocks
57−
58− `do` will be used later for Haskell-like monad comprehensions, so its previous use in introducing blocks of statements is now invalid. The `do` keyword is still reserved.
59−
60−- Member foreign import syntax
61−
62− A small syntactic addition to the FFI, to support a common use case.
63−
64−- Make FFI syntax match Haskell
65−
66− Use `foreign import` instead of `extern`.
67−
68−- Make record declaration syntax match Haskell
69−- Simplify array binders
70−
71− There are now two types of array binders: cons binders `x : xs -> ...` and array binders `[x, y, z] -> ...` instead of the previously confusing `[x:xs]`.
72−
73−- Array indexing syntax is ambiguous
74−
75− Array elements are now accessed using the `!!` operator: `arr !! 0` etc.
76−
77−### Bug Fixes
78−
79−- Allow guards access to current scope
80−
81−### Libraries
82−
83−- Prelude
84−
85− There is now a basic prelude in the `libraries/prelude` folder.
RELEASE-0.3.mddeleted−85
@@ -1,85 +0,0 @@
1−## 0.3.0 Changes
2−
3−Many thanks to the [contributors](https://github.com/purescript/purescript/graphs/contributors) who helped with this release.
4−
5−- Full language guide can be found [here](http://functorial.com/purescript).
6−- Try out the latest features [here](http://tryps.functorial.com).
7−
8−## New Features / Enhancements
9−
10−- Mutually recursive functions and types are now allowed within a module.
11−- Syntactic sugar for patterns in top-level declarations has been added. For example:
12−
13− sum [] = 0
14− sum (x:xs) = x + sum xs
15−
16−- Basic support for type classes has been added. Polymorphic types of the form `forall a. (C a) => ...` will not be inferred but can be checked. Type inference still works if all type class instances can be determined. There is not yet support for functionality like GHC's `FlexibleInstances`, `FlexibleContexts` or `MultiParamTypesClasses`. For example:
17−
18− class Truthy a where
19− isTrue :: a -> Boolean
20−
21− instance Truthy Boolean where
22− isTrue b = b
23−
24− instance Truthy String where
25− isTrue "" = false
26− isTrue _ = true
27−
28− ifThenElse :: forall a b. (Truthy a) => a -> b -> b -> b
29− ifThenElse a tr fa = if isTrue a then tr else fa
30−
31−- There is now support for `do` notation, using the `Monad` type class from the `Prelude` module. For example:
32−
33− data Maybe = Nothing | Just a
34−
35− instance Prelude.Monad Maybe where
36− ret = Just
37− (>>=) Nothing _ = Nothing
38− (>>=) (Just a) f = f a
39−
40− test = do
41− x <- Just 1
42− y <- Just 2
43− ret $ x + y
44−
45−- There is now a better story for side-effects. The `Eff` module in the `Prelude` defines a monad `Eff e` where e is a row of effect types. The kind system now defines a new kind `!` of effects. Row polymorphism allows different native effects to be interleaved. For example:
46−
47− test = do
48− trace "Testing"
49− throwError "Error!"
50−
51− has inferred type `forall eff. Eff (trace :: Trace | error :: Error String | eff)`.
52− See the `/examples/passing/Eff.purs` file for a more in-depth set of examples.
53− Supported native effects currently include `ST`, `Trace`, `Error` and `DOM` (via the `libraries/jquery` module).
54−- There is a new flag `--run-main` which will check the type of the `Main.main` function and emit the call to `main();` after all other generated Javascript.
55−- The `Prelude` module is now automatically included, unless the `--no-prelude` flag is specified.
56−- The class of accepted operator names has been expanded. Specifically, `$` is now a valid operator, and is defined in the `Prelude` module.
57−- Tail calls can be eliminated using the `--tco` flag.
58−- There is basic support for checking the types of values at runtime, using the `--runtime-type-checks` flag. Right now, this only works for primitive types, and so is a work-in-progress.
59−- GHCJS/Fay-style foreign imports are now supported. An example is
60−
61− foreign import "function(n) { \
62− \ return function(p) {\
63− \ return Math.pow(n, p);\
64− \ }\
65− \ }" pow :: Number -> Number -> Number
66−- Data constructors now get imported along with their type definitions.
67−- The `-s` flag will now cause the compiler to use `stdin` for input.
68−- There is a new executable `psci` which provides simple REPL-like functionality - it parses expressions, passes the generated Javascript to Node for execution, and prints the result. This is a work-in-progress.
69−- The JQuery example (`libraries/jquery/test`) has been improved to use the new `Eff` monad and `do` notation.
70−
71−## Regressions
72−
73−- `foreach` is no longer supported. The `Prelude` module defines `map` which should provide the same functionality.
74−- Support for naked expressions as statements has been removed.
75−
76−## Bug Fixes
77−
78−- Operator precedence rules now work across modules.
79−- A bug in which expressions involving non-qualified names did not typecheck was fixed.
80−- Trailing spaces have been removed in the generated Javascript, thanks to @utkarshkukreti.
81−- Type synonyms now work properly across modules.
82−- Module imports are not transitive, which was previously leading to some unexpected error messages.
83−- A bug which caused the optimizer to break generated Javascript for mutually recursive values was fixed.
84−- Some `Prelude` functions which called methods in the standard Javascript library have been fixed.
85−
RELEASE-0.4.mddeleted−60
@@ -1,60 +0,0 @@
1−## 0.4.0 Changes
2−
3−This release focussed mainly on bug fixes and minor enhancements, in order to provide a stable release of the compiler.
4−
5−This release saw major contributions from [a number of new contributors](https://github.com/purescript/purescript/graphs/contributors). Thank you very much to everyone who submitted pull requests, issues and suggestions, and also to the users of the #purescript FreeNode channel for their valuable feedback. As always, new contributors are always welcome!
6−
7−- The full language guide can be found [here](http://purescript.readthedocs.org).
8−- Try out the latest features [here](http://tryps.functorial.com).
9−
10−## Breaking Changes
11−
12−- Multiple argument functions are no longer available.
13−- When used in the browser, PureScript modules are now accessed through `window.PS.<ModuleName>`. The `PS` object name can be changed via the `--browser-namespace` compiler argument.
14−- The `--run-main` argument has been replaced with `--main` which can now accept a module name in which to find the `main` function.
15−
16−### New Features
17−
18−- Dead code elimination. The new compiler argument `--module=` can be used to specify one or more modules that should be kept in the generated code along with their dependencies. If no modules are specified, all code is exported.
19−
20−### Enhancements
21−
22−- The `->` and `[]` types are now usable in type class instances.
23−- The file path is included in syntax error messages.
24−- Most reserved Javascript names (`return`, `const`, etc) are now usable.
25−- Generated code for operators is more user friendly (for example, `Prelude[">>="]`). Where this transformation cannot be applied, human-readable variable names (e.g. `$greater$greater$eq`) are generated.
26−- The typechecker's function application judgement was greatly simplified, and as a result, more valid things now typecheck.
27−- Data constructors with multiple arguments can now be defined.
28−- It is no longer necessary to sort modules in order of dependencies manually.
29−- Case statements matching data constructors no longer generate unnecessary constructor checks at runtime if there is only a single data constructor.
30−- New optimizer rules were added to inline JavaScript's built-in operators.
31−
32−### Bug Fixes
33−
34−- Floats parse correctly.
35−- Using data constructors in pattern matches now works properly across modules.
36−- PureScript modules no longer overwrite global objects with the same name.
37−- Show problems with shadowing of names were fixed.
38−- Problems with recursive non-function values were fixed.
39−- Type synonyms can now expand to types containing more type synonyms.
40−- A bug in capture-avoiding type variable substitution which was affecting the `Functor (Either e)` instance was fixed.
41−- Type synonym instances are now disallowed.
42−- Precedence rules for some basic operators were corrected.
43−- A bug which allowed skolem variables to escape their scope was add (thanks to Brian McKenna).
44−- Modules containing mutually recursive type synonyms and data declarations now compile correctly.
45−- A number of bugs in the optimizer were addressed.
46−
47−### Libraries
48−
49−- The `Prelude` has been greatly expanded. Definitions for built-in JavaScript operators have been moved into the Prelude.
50−- Gary Burgess has released the [grunt-purescript library](https://github.com/purescript/grunt-purescript) to build PureScript code using Grunt.
51−- The [purescript-parsing](https://github.com/purescript/purescript-parsing) library provides Parsec-like parsing combinators.
52−- The [purescript-promises](https://github.com/purescript/purescript-promises) library provides `Monad` and `Applicative` instances for promises.
53−- The [purescript-quickcheck](https://github.com/purescript/purescript-quickcheck) library provides a very basic implementation of a QuickCheck-style testing harness.
54−- The [purescript-json](https://github.com/purescript/purescript-json) library aims to provide a safe way to consume JSON data.
55−
56−### Documentation
57−
58−- Documentation for the `Prelude` modules is now automatically generated and can be found [here](http://purescript.readthedocs.org/en/latest/prelude.html).
59−- There is now Hackage documentation.
60−- Code comments have been improved.
Setup.hs+1−37
@@ -1,38 +1,2 @@
1−{-# LANGUAGE CPP #-}
2−
3−#ifndef POSIX_LIKE
4−#define POSIX_LIKE !(defined(_WIN32_HOST_OS) || defined(_WIN64_HOST_OS)) && \
5− (defined(unix_HOST_OS) || defined(__unix___HOST_OS) || \
6− defined(__unix_HOST_OS) || defined(linux_HOST_OS) || \
7− defined(__linux___HOST_OS) || defined(__linux_HOST_OS) || \
8− (defined(__APPLE___HOST_OS) && defined(__MACH___HOST_OS)))
9−#endif
10−
11−module Main where
12−
13−import Control.Monad
14−
15−import Distribution.PackageDescription
161import Distribution.Simple
17−import Distribution.Simple.LocalBuildInfo
18−import Distribution.Simple.Setup
19−
20−import System.Directory
21−import System.Environment.XDG.BaseDir
22−#if POSIX_LIKE
23−import System.Posix.Files
24−#endif
25−
26−main :: IO ()
27−main = defaultMainWithHooks $ simpleUserHooks {postInst = setupXDG}
28−
29−setupXDG :: Args -> InstallFlags -> PackageDescription -> LocalBuildInfo -> IO ()
30−setupXDG _ _ _ _ = do
31− configDir <- getUserConfigDir "purescript"
32− configExists <- doesDirectoryExist configDir
33− unless configExists $ do
34− createDirectoryIfMissing True configDir
35−#if POSIX_LIKE
36− setFileMode configDir ownerModes
37−#endif
38−#undef POSIX_LIKE
2+main = defaultMain
app/Main.hsnew file+250
@@ -0,0 +1,250 @@
1+{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE RankNTypes #-}
3+{-# LANGUAGE TemplateHaskell #-}
4+
5+module Main where
6+
7+import Control.Monad (when)
8+import qualified Control.Monad.Parallel as Par
9+import Data.Aeson
10+import Data.Aeson.Types
11+import Data.Char
12+import Data.FileEmbed (embedFile)
13+import Data.List (delete, intercalate, isPrefixOf, nub, partition, (\\))
14+import Data.Maybe
15+import Data.Monoid ((<>))
16+import Data.Version
17+import Control.Monad.Supply
18+import Control.Monad.Supply.Class
19+import Text.Printf
20+
21+import System.Environment
22+import System.Directory (createDirectoryIfMissing, doesDirectoryExist, doesFileExist, getCurrentDirectory, getModificationTime)
23+import System.FilePath ((</>), joinPath, splitDirectories, takeDirectory)
24+import System.FilePath.Find
25+import System.Process
26+
27+import Data.Text (Text)
28+import qualified Data.Text as T
29+import qualified Data.Text.Encoding as T
30+import qualified Data.Text.Lazy as L
31+import qualified Data.Text.Lazy.Encoding as L
32+import qualified Data.ByteString as B
33+
34+import Development.GitRev
35+
36+import Language.PureScript.AST.Literals
37+import Language.PureScript.CoreFn
38+import Language.PureScript.CoreFn.FromJSON
39+
40+import CodeGen.IL
41+import CodeGen.IL.Common
42+import CodeGen.IL.Printer
43+
44+import Tests
45+
46+data Command = Build | Run (Maybe String)
47+
48+parseJson :: Text -> Value
49+parseJson text
50+ | Just fileJson <- decode . L.encodeUtf8 $ L.fromStrict text = fileJson
51+ | otherwise = error "Bad json"
52+
53+jsonToModule :: Value -> Module Ann
54+jsonToModule value =
55+ case parse moduleFromJSON value of
56+ Success (_, r) -> r
57+ _ -> error "Failed parsing corefn. Psgo currently supports purescript <= 0.13.8"
58+
59+splitArgs :: [String] -> ([String], Maybe String, [String])
60+splitArgs args =
61+ let (opts, files) = partition (isPrefixOf "--") args
62+ opts' = (map . map) toLower opts
63+ (moduleName, files') =
64+ if null files
65+ then (Nothing, files)
66+ else
67+ if "--run" `elem` opts' && length (files) >= 1
68+ then do
69+ let file0 = head files
70+ files' = tail files
71+ case file0 of
72+ "Main.main" -> (Just "Main", files')
73+ "Test.Main.main" -> (Just "Test.Main", files')
74+ _ -> (Nothing, files)
75+ else (Nothing, files)
76+ in (opts, moduleName, files')
77+
78+main :: IO ()
79+main = do
80+ args <- getArgs
81+ -- let (opts, files) = partition (isPrefixOf "--") args
82+ let (opts, moduleName, files) = splitArgs args
83+ opts' = (map . map) toLower opts
84+ if "--tests" `elem` opts'
85+ then runTests
86+ else do
87+ if "--help" `elem` opts' || "--version" `elem` opts'
88+ then do
89+ when ("--help" `elem` opts') $ do
90+ putStrLn help
91+ when ("--version" `elem` opts') $ do
92+ let branch = $(gitBranch)
93+ details | branch == "golang" = "master, commit " ++ $(gitHash)
94+ | otherwise = branch
95+ putStrLn $ details ++ if $(gitDirty) then " (DIRTY)" else ""
96+ else do
97+ if null files
98+ then do
99+ currentDir <- getCurrentDirectory
100+ processFiles opts' [currentDir]
101+ else
102+ processFiles opts' files
103+ if "--run" `elem` opts
104+ then runBuildTool $ Run moduleName
105+ else when ("--no-build" `notElem` opts) $
106+ runBuildTool Build
107+ return ()
108+ where
109+ processFiles :: [String] -> [FilePath] -> IO ()
110+ processFiles opts [file] = do
111+ isDir <- doesDirectoryExist file
112+ if isDir then do
113+ files <- find always (fileName ==? corefn) file
114+ if null files
115+ then errorNoCorefnFiles
116+ else generateFiles opts files
117+ else generateFiles opts [file]
118+ processFiles opts files = do
119+ generateFiles opts files
120+ basePath :: [FilePath] -> FilePath
121+ basePath files =
122+ let filepath = takeDirectory (head files) in
123+ joinPath $ (init $ splitDirectories filepath)
124+ generateFiles :: [String] -> [FilePath] -> IO ()
125+ generateFiles opts files = do
126+ let baseOutpath = basePath files
127+ writeSupportFiles baseOutpath
128+ Par.mapM (generateCode opts baseOutpath) files
129+ return ()
130+ runBuildTool :: Command -> IO ()
131+ runBuildTool cmd = do
132+ project <- projectEnv
133+ case cmd of
134+ Build -> do
135+ callProcess "go" ["build", T.unpack project </> modPrefix' </> "Main"]
136+ Run moduleName -> do
137+ callProcess "go" ["run", T.unpack project </> modPrefix' </> fromMaybe "Main" moduleName]
138+ return ()
139+
140+generateCode :: [String] -> FilePath -> FilePath -> IO ()
141+generateCode opts baseOutpath jsonFile = do
142+ jsonModTime <- getModificationTime jsonFile
143+ let filepath = takeDirectory jsonFile
144+ dirparts = splitDirectories $ filepath
145+ mname = last dirparts
146+ basedir = joinPath $ init dirparts
147+ mname' = T.pack mname
148+ possibleFileName = basedir </> (T.unpack mname') </> implFileName mname'
149+ exists <- doesFileExist possibleFileName
150+ if exists
151+ then do
152+ modTime <- getModificationTime possibleFileName
153+ when (modTime < jsonModTime) $
154+ transpile opts baseOutpath jsonFile
155+ else transpile opts baseOutpath jsonFile
156+
157+transpile :: [String] -> FilePath -> FilePath -> IO ()
158+transpile opts baseOutpath jsonFile = do
159+ jsonText <- T.decodeUtf8 <$> B.readFile jsonFile
160+ project <- projectEnv
161+ let module' = jsonToModule $ parseJson jsonText
162+ ((_, foreigns, asts, implHeader, implFooter), _) <- runSupplyT 5 (moduleToIL module' project)
163+ let mn = moduleNameToIL' $ moduleName module'
164+ implementation = prettyPrintIL asts
165+ outpath = joinPath [baseOutpath, T.unpack mn]
166+ implPath = outpath </> implFileName mn
167+ createDirectoryIfMissing True outpath
168+ putStrLn implPath
169+ B.writeFile implPath $ T.encodeUtf8 (implHeader <> implementation <> implFooter)
170+
171+writeSupportFiles :: FilePath -> IO ()
172+writeSupportFiles baseOutpath = do
173+ currentDir <- getCurrentDirectory
174+ let outputdir = T.pack $ baseOutpath \\ currentDir
175+ ffiOutpath = currentDir </> subdir
176+ createDirectoryIfMissing True baseOutpath
177+ createDirectoryIfMissing True ffiOutpath
178+ writeModuleFile outputdir currentDir $(embedFile "support/go.mod.working")
179+ writeModuleFile outputdir baseOutpath $(embedFile "support/go.mod.output")
180+ writeModuleFile outputdir ffiOutpath $(embedFile "support/go.mod.ffi-loader")
181+ writeLoaderFile ffiOutpath $(embedFile "support/ffi-loader.go")
182+ where
183+ writeModuleFile :: Text -> FilePath -> B.ByteString -> IO ()
184+ writeModuleFile outputdir path modText = do
185+ let goModSource = path </> "go.mod"
186+ goModSourceExists <- doesFileExist goModSource
187+ when (not goModSourceExists) $ do
188+ project <- projectEnv
189+ let project' = T.unpack project
190+ outputdir' = tail $ T.unpack outputdir
191+ modText' = T.replace "$PROJECT" project $ T.decodeUtf8 modText
192+ replaceLoader = project' </> ffiLoader' <> "=." </> subdir
193+ replaceOutput = project' </> modPrefix' <> "=." </> outputdir'
194+ B.writeFile goModSource $ T.encodeUtf8 modText'
195+ callProcess "go" ["mod", "edit", "-replace", replaceLoader]
196+ callProcess "go" ["mod", "edit", "-replace", replaceOutput]
197+ callProcess "go" ["clean", "-modcache"]
198+ writeLoaderFile :: FilePath -> B.ByteString -> IO ()
199+ writeLoaderFile ffiOutpath loaderText = do
200+ let loaderSource = ffiOutpath </> "ffi_loader.go"
201+ loaderSourceExists <- doesFileExist loaderSource
202+ when (not loaderSourceExists) $ do
203+ B.writeFile loaderSource loaderText
204+
205+implFileName :: Text -> FilePath
206+implFileName mn = ((\c -> if c == '.' then '_' else c) <$> T.unpack mn) <> ".go"
207+
208+projectEnv :: IO Text
209+projectEnv = do
210+ T.pack . fromMaybe defaultProject <$> lookupEnv goproject
211+
212+help :: String
213+help = "Usage: psgo OPTIONS COREFN-FILES\n\
214+ \ PureScript to native (via go) compiler\n\n\
215+ \Available options:\n\
216+ \ --help Show this help text\n\n\
217+ \ --version Show the version number\n\n\
218+ \ --run Run the generated go code directly, without building an\n\
219+ \ executable\n\
220+ \ --no-build Generate go source files, but do not build an executable\n\
221+ \ --tests Run test cases (under construction)\n\n\
222+ \See also:\n\
223+ \ purs compile --help\n"
224+
225+corefn :: String
226+corefn = "corefn.json"
227+
228+goSrc :: String
229+goSrc = ".go"
230+
231+goproject :: String
232+goproject = "GOPROJECT"
233+
234+defaultProject :: String
235+defaultProject = "project.localhost"
236+
237+modPrefix' :: String
238+modPrefix' = T.unpack modPrefix
239+
240+ffiLoader' :: String
241+ffiLoader' = T.unpack ffiLoader
242+
243+subdir :: String
244+subdir = T.unpack modLabel
245+
246+errorNoCorefnFiles :: IO ()
247+errorNoCorefnFiles = do
248+ ioError . userError $ "no compiled purescript '" <> corefn <> "' files found –\n" <>
249+ " make sure to use the '--codegen corefn' option with your purs\n" <>
250+ " project build tool"
default.nixnew file+23
@@ -0,0 +1,23 @@
1+let
2+ haskellNix = import (builtins.fetchTarball https://github.com/input-output-hk/haskell.nix/archive/master.tar.gz) {};
3+ nixpkgsSrc = haskellNix.sources.nixpkgs-1903; # has hsc2hs-0.68.4
4+
5+ hsc2hsOverlay = self: super: {
6+ buildPackages = super.buildPackages // {
7+ hsc2hs = super.haskellPackages.hsc2hs;
8+ };
9+ };
10+
11+ nixpkgsArgs = haskellNix.nixpkgsArgs // {
12+ overlays = haskellNix.nixpkgsArgs.overlays ++ [ hsc2hsOverlay ];
13+ };
14+in
15+{ pkgs ? import nixpkgsSrc nixpkgsArgs
16+}:
17+
18+pkgs.haskell-nix.stackProject {
19+ src = pkgs.haskell-nix.haskellLib.cleanGit {
20+ name = "purescript-native";
21+ src = ./.;
22+ };
23+}
docgen/Main.hsdeleted−226
@@ -1,226 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Main
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−module Main where
16−
17−import Control.Applicative
18−import Control.Monad
19−import Control.Monad.Writer
20−import Data.Function (on)
21−import Data.List
22−import Data.Version (showVersion)
23−import qualified Language.PureScript as P
24−import qualified Paths_purescript as Paths
25−import qualified System.IO.UTF8 as U
26−import System.Console.CmdTheLine
27−import System.Exit (exitSuccess, exitFailure)
28−
29−docgen :: Bool -> [FilePath] -> IO ()
30−docgen showHierarchy input = do
31− ms <- mapM parseFile (nub input)
32− U.putStrLn . runDocs $ (renderModules showHierarchy) (concat ms)
33− exitSuccess
34−
35−parseFile :: FilePath -> IO [P.Module]
36−parseFile input = do
37− text <- U.readFile input
38− case P.runIndentParser input P.parseModules text of
39− Left err -> do
40− U.print err
41− exitFailure
42− Right ms -> do
43− return ms
44−
45−type Docs = Writer [String] ()
46−
47−runDocs :: Docs -> String
48−runDocs = unlines . execWriter
49−
50−spacer :: Docs
51−spacer = tell [""]
52−
53−headerLevel :: Int -> String -> Docs
54−headerLevel level hdr = tell [replicate level '#' ++ ' ' : hdr]
55−
56−atIndent :: Int -> String -> Docs
57−atIndent indent text =
58− let ls = lines text in
59− forM_ ls $ \l -> tell [replicate indent ' ' ++ l]
60−
61−renderModules :: Bool -> [P.Module] -> Docs
62−renderModules showHierarchy ms = do
63− headerLevel 1 "Module Documentation"
64− spacer
65− mapM_ (renderModule showHierarchy) ms
66−
67−renderModule :: Bool -> P.Module -> Docs
68−renderModule showHierarchy (P.Module moduleName ds exps) =
69− let exported = filter (isExported exps) ds
70− hasTypes = any isTypeDeclaration ds
71− hasTypeclasses = any isTypeClassDeclaration ds
72− hasTypeclassInstances = any isTypeInstanceDeclaration ds
73− hasValues = any isValueDeclaration ds
74− in do
75− headerLevel 2 $ "Module " ++ P.runModuleName moduleName
76− spacer
77− when hasTypes $ do
78− headerLevel 3 "Types"
79− spacer
80− renderTopLevel exps (filter isTypeDeclaration exported)
81− spacer
82− when hasTypeclasses $ do
83− headerLevel 3 "Type Classes"
84− spacer
85− when showHierarchy $ do
86− renderTypeclassImage moduleName
87− spacer
88− renderTopLevel exps (filter isTypeClassDeclaration exported)
89− spacer
90− when hasTypeclassInstances $ do
91− headerLevel 3 "Type Class Instances"
92− spacer
93− renderTopLevel exps (filter isTypeInstanceDeclaration ds)
94− spacer
95− when hasValues $ do
96− headerLevel 3 "Values"
97− spacer
98− renderTopLevel exps (filter isValueDeclaration exported)
99− spacer
100−
101−isExported :: Maybe [P.DeclarationRef] -> P.Declaration -> Bool
102−isExported Nothing _ = True
103−isExported _ P.TypeInstanceDeclaration{} = True
104−isExported exps (P.PositionedDeclaration _ d) = isExported exps d
105−isExported (Just exps) decl = any (matches decl) exps
106− where
107− matches (P.TypeDeclaration ident _) (P.ValueRef ident') = ident == ident'
108− matches (P.ExternDeclaration _ ident _ _) (P.ValueRef ident') = ident == ident'
109− matches (P.DataDeclaration ident _ _) (P.TypeRef ident' _) = ident == ident'
110− matches (P.ExternDataDeclaration ident _) (P.TypeRef ident' _) = ident == ident'
111− matches (P.TypeSynonymDeclaration ident _ _) (P.TypeRef ident' _) = ident == ident'
112− matches (P.TypeClassDeclaration ident _ _ _) (P.TypeClassRef ident') = ident == ident'
113− matches (P.PositionedDeclaration _ d) r = d `matches` r
114− matches d (P.PositionedDeclarationRef _ r) = d `matches` r
115− matches _ _ = False
116−
117−isDctorExported :: P.ProperName -> Maybe [P.DeclarationRef] -> P.ProperName -> Bool
118−isDctorExported _ Nothing _ = True
119−isDctorExported ident (Just exps) ctor = test `any` exps
120− where
121− test (P.PositionedDeclarationRef _ d) = test d
122− test (P.TypeRef ident' Nothing) = ident == ident'
123− test (P.TypeRef ident' (Just ctors)) = ident == ident' && ctor `elem` ctors
124− test _ = False
125−
126−renderTopLevel :: Maybe [P.DeclarationRef] -> [P.Declaration] -> Docs
127−renderTopLevel exps decls = forM_ (sortBy (compare `on` getName) decls) $ \decl -> do
128− renderDeclaration 4 exps decl
129− spacer
130−
131−renderTypeclassImage :: P.ModuleName -> Docs
132−renderTypeclassImage name =
133− let name' = P.runModuleName name
134− in tell ["![" ++ name' ++ "](images/" ++ name' ++ ".png)"]
135−
136−renderDeclaration :: Int -> Maybe [P.DeclarationRef] -> P.Declaration -> Docs
137−renderDeclaration n _ (P.TypeDeclaration ident ty) =
138− atIndent n $ show ident ++ " :: " ++ prettyPrintType' ty
139−renderDeclaration n _ (P.ExternDeclaration _ ident _ ty) =
140− atIndent n $ show ident ++ " :: " ++ prettyPrintType' ty
141−renderDeclaration n exps (P.DataDeclaration name args ctors) = do
142− let typeName = P.runProperName name ++ (if null args then "" else " " ++ unwords args)
143− let exported = filter (isDctorExported name exps . fst) ctors
144− atIndent n $ "data " ++ typeName ++ (if null exported then "" else " where")
145− forM_ exported $ \(ctor, tys) ->
146− atIndent (n + 2) $ P.runProperName ctor ++ " :: " ++ concatMap (\ty -> prettyPrintType' ty ++ " -> ") tys ++ typeName
147−renderDeclaration n _ (P.ExternDataDeclaration name kind) =
148− atIndent n $ "data " ++ P.runProperName name ++ " :: " ++ P.prettyPrintKind kind
149−renderDeclaration n _ (P.TypeSynonymDeclaration name args ty) = do
150− let typeName = P.runProperName name ++ " " ++ unwords args
151− atIndent n $ "type " ++ typeName ++ " = " ++ prettyPrintType' ty
152−renderDeclaration n exps (P.TypeClassDeclaration name args implies ds) = do
153− let impliesText = case implies of
154− [] -> ""
155− is -> "(" ++ intercalate ", " (map (\(pn, tys') -> show pn ++ " " ++ unwords (map P.prettyPrintTypeAtom tys')) is) ++ ") <= "
156− atIndent n $ "class " ++ impliesText ++ P.runProperName name ++ " " ++ unwords args ++ " where"
157− mapM_ (renderDeclaration (n + 2) exps) ds
158−renderDeclaration n _ (P.TypeInstanceDeclaration name constraints className tys _) = do
159− let constraintsText = case constraints of
160− [] -> ""
161− cs -> "(" ++ intercalate ", " (map (\(pn, tys') -> show pn ++ " " ++ unwords (map P.prettyPrintTypeAtom tys')) cs) ++ ") => "
162− atIndent n $ "instance " ++ show name ++ " :: " ++ constraintsText ++ show className ++ " " ++ unwords (map P.prettyPrintTypeAtom tys)
163−renderDeclaration n exps (P.PositionedDeclaration _ d) =
164− renderDeclaration n exps d
165−renderDeclaration _ _ _ = return ()
166−
167−prettyPrintType' :: P.Type -> String
168−prettyPrintType' = P.prettyPrintType . P.everywhereOnTypes dePrim
169− where
170− dePrim ty@(P.TypeConstructor (P.Qualified _ name))
171− | ty == P.tyBoolean || ty == P.tyNumber || ty == P.tyString =
172− P.TypeConstructor $ P.Qualified Nothing name
173− dePrim other = other
174−
175−getName :: P.Declaration -> String
176−getName (P.TypeDeclaration ident _) = show ident
177−getName (P.ExternDeclaration _ ident _ _) = show ident
178−getName (P.DataDeclaration name _ _) = P.runProperName name
179−getName (P.ExternDataDeclaration name _) = P.runProperName name
180−getName (P.TypeSynonymDeclaration name _ _) = P.runProperName name
181−getName (P.TypeClassDeclaration name _ _ _) = P.runProperName name
182−getName (P.TypeInstanceDeclaration name _ _ _ _) = show name
183−getName (P.PositionedDeclaration _ d) = getName d
184−getName _ = error "Invalid argument to getName"
185−
186−isValueDeclaration :: P.Declaration -> Bool
187−isValueDeclaration P.TypeDeclaration{} = True
188−isValueDeclaration P.ExternDeclaration{} = True
189−isValueDeclaration (P.PositionedDeclaration _ d) = isValueDeclaration d
190−isValueDeclaration _ = False
191−
192−isTypeDeclaration :: P.Declaration -> Bool
193−isTypeDeclaration P.DataDeclaration{} = True
194−isTypeDeclaration P.ExternDataDeclaration{} = True
195−isTypeDeclaration P.TypeSynonymDeclaration{} = True
196−isTypeDeclaration (P.PositionedDeclaration _ d) = isTypeDeclaration d
197−isTypeDeclaration _ = False
198−
199−isTypeClassDeclaration :: P.Declaration -> Bool
200−isTypeClassDeclaration P.TypeClassDeclaration{} = True
201−isTypeClassDeclaration (P.PositionedDeclaration _ d) = isTypeClassDeclaration d
202−isTypeClassDeclaration _ = False
203−
204−isTypeInstanceDeclaration :: P.Declaration -> Bool
205−isTypeInstanceDeclaration P.TypeInstanceDeclaration{} = True
206−isTypeInstanceDeclaration (P.PositionedDeclaration _ d) = isTypeInstanceDeclaration d
207−isTypeInstanceDeclaration _ = False
208−
209−inputFiles :: Term [FilePath]
210−inputFiles = value $ posAny [] $ posInfo { posName = "file(s)", posDoc = "The input .purs file(s)" }
211−
212−includeHeirarcy :: Term Bool
213−includeHeirarcy = value $ flag $ (optInfo [ "h", "hierarchy-images" ]) { optDoc = "Include markdown for type class hierarchy images in the output." }
214−
215−term :: Term (IO ())
216−term = docgen <$> includeHeirarcy <*> inputFiles
217−
218−termInfo :: TermInfo
219−termInfo = defTI
220− { termName = "docgen"
221− , version = showVersion Paths.version
222− , termDoc = "Generate Markdown documentation from PureScript extern files"
223− }
224−
225−main :: IO ()
226−main = run (term, termInfo)
docs/.gitignoredeleted−1
@@ -1 +0,0 @@
1−build
docs/Makefiledeleted−177
@@ -1,177 +0,0 @@
1−# Makefile for Sphinx documentation
2−#
3−
4−# You can set these variables from the command line.
5−SPHINXOPTS =
6−SPHINXBUILD = sphinx-build
7−PAPER =
8−BUILDDIR = build
9−
10−# User-friendly check for sphinx-build
11−ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
12−$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
13−endif
14−
15−# Internal variables.
16−PAPEROPT_a4 = -D latex_paper_size=a4
17−PAPEROPT_letter = -D latex_paper_size=letter
18−ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
19−# the i18n builder cannot share the environment and doctrees with the others
20−I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
21−
22−.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
23−
24−help:
25− @echo "Please use \`make <target>' where <target> is one of"
26− @echo " html to make standalone HTML files"
27− @echo " dirhtml to make HTML files named index.html in directories"
28− @echo " singlehtml to make a single large HTML file"
29− @echo " pickle to make pickle files"
30− @echo " json to make JSON files"
31− @echo " htmlhelp to make HTML files and a HTML help project"
32− @echo " qthelp to make HTML files and a qthelp project"
33− @echo " devhelp to make HTML files and a Devhelp project"
34− @echo " epub to make an epub"
35− @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
36− @echo " latexpdf to make LaTeX files and run them through pdflatex"
37− @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
38− @echo " text to make text files"
39− @echo " man to make manual pages"
40− @echo " texinfo to make Texinfo files"
41− @echo " info to make Texinfo files and run them through makeinfo"
42− @echo " gettext to make PO message catalogs"
43− @echo " changes to make an overview of all changed/added/deprecated items"
44− @echo " xml to make Docutils-native XML files"
45− @echo " pseudoxml to make pseudoxml-XML files for display purposes"
46− @echo " linkcheck to check all external links for integrity"
47− @echo " doctest to run all doctests embedded in the documentation (if enabled)"
48−
49−clean:
50− rm -rf $(BUILDDIR)/*
51−
52−html:
53− $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
54− @echo
55− @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
56−
57−dirhtml:
58− $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
59− @echo
60− @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
61−
62−singlehtml:
63− $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
64− @echo
65− @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
66−
67−pickle:
68− $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
69− @echo
70− @echo "Build finished; now you can process the pickle files."
71−
72−json:
73− $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
74− @echo
75− @echo "Build finished; now you can process the JSON files."
76−
77−htmlhelp:
78− $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
79− @echo
80− @echo "Build finished; now you can run HTML Help Workshop with the" \
81− ".hhp project file in $(BUILDDIR)/htmlhelp."
82−
83−qthelp:
84− $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
85− @echo
86− @echo "Build finished; now you can run "qcollectiongenerator" with the" \
87− ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
88− @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/PureScript.qhcp"
89− @echo "To view the help file:"
90− @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PureScript.qhc"
91−
92−devhelp:
93− $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
94− @echo
95− @echo "Build finished."
96− @echo "To view the help file:"
97− @echo "# mkdir -p $$HOME/.local/share/devhelp/PureScript"
98− @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/PureScript"
99− @echo "# devhelp"
100−
101−epub:
102− $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
103− @echo
104− @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
105−
106−latex:
107− $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
108− @echo
109− @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
110− @echo "Run \`make' in that directory to run these through (pdf)latex" \
111− "(use \`make latexpdf' here to do that automatically)."
112−
113−latexpdf:
114− $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
115− @echo "Running LaTeX files through pdflatex..."
116− $(MAKE) -C $(BUILDDIR)/latex all-pdf
117− @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
118−
119−latexpdfja:
120− $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
121− @echo "Running LaTeX files through platex and dvipdfmx..."
122− $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
123− @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
124−
125−text:
126− $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
127− @echo
128− @echo "Build finished. The text files are in $(BUILDDIR)/text."
129−
130−man:
131− $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
132− @echo
133− @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
134−
135−texinfo:
136− $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
137− @echo
138− @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
139− @echo "Run \`make' in that directory to run these through makeinfo" \
140− "(use \`make info' here to do that automatically)."
141−
142−info:
143− $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
144− @echo "Running Texinfo files through makeinfo..."
145− make -C $(BUILDDIR)/texinfo info
146− @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
147−
148−gettext:
149− $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
150− @echo
151− @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
152−
153−changes:
154− $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
155− @echo
156− @echo "The overview file is in $(BUILDDIR)/changes."
157−
158−linkcheck:
159− $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
160− @echo
161− @echo "Link check complete; look for any errors in the above output " \
162− "or in $(BUILDDIR)/linkcheck/output.txt."
163−
164−doctest:
165− $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
166− @echo "Testing of doctests in the sources finished, look at the " \
167− "results in $(BUILDDIR)/doctest/output.txt."
168−
169−xml:
170− $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
171− @echo
172− @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
173−
174−pseudoxml:
175− $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
176− @echo
177− @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
docs/source/conf.pydeleted−258
@@ -1,258 +0,0 @@
1−# -*- coding: utf-8 -*-
2−#
3−# PureScript documentation build configuration file, created by
4−# sphinx-quickstart on Wed Jan 22 22:04:23 2014.
5−#
6−# This file is execfile()d with the current directory set to its
7−# containing dir.
8−#
9−# Note that not all possible configuration values are present in this
10−# autogenerated file.
11−#
12−# All configuration values have a default; values that are commented out
13−# serve to show the default.
14−
15−import sys
16−import os
17−
18−# If extensions (or modules to document with autodoc) are in another directory,
19−# add these directories to sys.path here. If the directory is relative to the
20−# documentation root, use os.path.abspath to make it absolute, like shown here.
21−#sys.path.insert(0, os.path.abspath('.'))
22−
23−# -- General configuration ------------------------------------------------
24−
25−# If your documentation needs a minimal Sphinx version, state it here.
26−#needs_sphinx = '1.0'
27−
28−# Add any Sphinx extension module names here, as strings. They can be
29−# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
30−# ones.
31−extensions = []
32−
33−# Add any paths that contain templates here, relative to this directory.
34−templates_path = ['_templates']
35−
36−# The suffix of source filenames.
37−source_suffix = '.rst'
38−
39−# The encoding of source files.
40−#source_encoding = 'utf-8-sig'
41−
42−# The master toctree document.
43−master_doc = 'index'
44−
45−# General information about the project.
46−project = u'PureScript'
47−copyright = u'2014, Phil Freeman'
48−
49−# The version info for the project you're documenting, acts as replacement for
50−# |version| and |release|, also used in various other places throughout the
51−# built documents.
52−#
53−# The short X.Y version.
54−version = '0.5.0'
55−# The full version, including alpha/beta/rc tags.
56−release = '0.5.0'
57−
58−# The language for content autogenerated by Sphinx. Refer to documentation
59−# for a list of supported languages.
60−#language = None
61−
62−# There are two options for replacing |today|: either, you set today to some
63−# non-false value, then it is used:
64−#today = ''
65−# Else, today_fmt is used as the format for a strftime call.
66−#today_fmt = '%B %d, %Y'
67−
68−# List of patterns, relative to source directory, that match files and
69−# directories to ignore when looking for source files.
70−exclude_patterns = []
71−
72−# The reST default role (used for this markup: `text`) to use for all
73−# documents.
74−#default_role = None
75−
76−# If true, '()' will be appended to :func: etc. cross-reference text.
77−#add_function_parentheses = True
78−
79−# If true, the current module name will be prepended to all description
80−# unit titles (such as .. function::).
81−#add_module_names = True
82−
83−# If true, sectionauthor and moduleauthor directives will be shown in the
84−# output. They are ignored by default.
85−#show_authors = False
86−
87−# The name of the Pygments (syntax highlighting) style to use.
88−pygments_style = 'sphinx'
89−
90−# A list of ignored prefixes for module index sorting.
91−#modindex_common_prefix = []
92−
93−# If true, keep warnings as "system message" paragraphs in the built documents.
94−#keep_warnings = False
95−
96−
97−# -- Options for HTML output ----------------------------------------------
98−
99−# The theme to use for HTML and HTML Help pages. See the documentation for
100−# a list of builtin themes.
101−html_theme = 'default'
102−
103−# Theme options are theme-specific and customize the look and feel of a theme
104−# further. For a list of options available for each theme, see the
105−# documentation.
106−#html_theme_options = {}
107−
108−# Add any paths that contain custom themes here, relative to this directory.
109−#html_theme_path = []
110−
111−# The name for this set of Sphinx documents. If None, it defaults to
112−# "<project> v<release> documentation".
113−#html_title = None
114−
115−# A shorter title for the navigation bar. Default is the same as html_title.
116−#html_short_title = None
117−
118−# The name of an image file (relative to this directory) to place at the top
119−# of the sidebar.
120−#html_logo = None
121−
122−# The name of an image file (within the static path) to use as favicon of the
123−# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
124−# pixels large.
125−#html_favicon = None
126−
127−# Add any paths that contain custom static files (such as style sheets) here,
128−# relative to this directory. They are copied after the builtin static files,
129−# so a file named "default.css" will overwrite the builtin "default.css".
130−html_static_path = ['_static']
131−
132−# Add any extra paths that contain custom files (such as robots.txt or
133−# .htaccess) here, relative to this directory. These files are copied
134−# directly to the root of the documentation.
135−#html_extra_path = []
136−
137−# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
138−# using the given strftime format.
139−#html_last_updated_fmt = '%b %d, %Y'
140−
141−# If true, SmartyPants will be used to convert quotes and dashes to
142−# typographically correct entities.
143−#html_use_smartypants = True
144−
145−# Custom sidebar templates, maps document names to template names.
146−#html_sidebars = {}
147−
148−# Additional templates that should be rendered to pages, maps page names to
149−# template names.
150−#html_additional_pages = {}
151−
152−# If false, no module index is generated.
153−#html_domain_indices = True
154−
155−# If false, no index is generated.
156−#html_use_index = True
157−
158−# If true, the index is split into individual pages for each letter.
159−#html_split_index = False
160−
161−# If true, links to the reST sources are added to the pages.
162−#html_show_sourcelink = True
163−
164−# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
165−#html_show_sphinx = True
166−
167−# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
168−#html_show_copyright = True
169−
170−# If true, an OpenSearch description file will be output, and all pages will
171−# contain a <link> tag referring to it. The value of this option must be the
172−# base URL from which the finished HTML is served.
173−#html_use_opensearch = ''
174−
175−# This is the file name suffix for HTML files (e.g. ".xhtml").
176−#html_file_suffix = None
177−
178−# Output file base name for HTML help builder.
179−htmlhelp_basename = 'PureScriptdoc'
180−
181−
182−# -- Options for LaTeX output ---------------------------------------------
183−
184−latex_elements = {
185−# The paper size ('letterpaper' or 'a4paper').
186−#'papersize': 'letterpaper',
187−
188−# The font size ('10pt', '11pt' or '12pt').
189−#'pointsize': '10pt',
190−
191−# Additional stuff for the LaTeX preamble.
192−#'preamble': '',
193−}
194−
195−# Grouping the document tree into LaTeX files. List of tuples
196−# (source start file, target name, title,
197−# author, documentclass [howto, manual, or own class]).
198−latex_documents = [
199− ('index', 'PureScript.tex', u'PureScript Documentation',
200− u'Phil Freeman', 'manual'),
201−]
202−
203−# The name of an image file (relative to this directory) to place at the top of
204−# the title page.
205−#latex_logo = None
206−
207−# For "manual" documents, if this is true, then toplevel headings are parts,
208−# not chapters.
209−#latex_use_parts = False
210−
211−# If true, show page references after internal links.
212−#latex_show_pagerefs = False
213−
214−# If true, show URL addresses after external links.
215−#latex_show_urls = False
216−
217−# Documents to append as an appendix to all manuals.
218−#latex_appendices = []
219−
220−# If false, no module index is generated.
221−#latex_domain_indices = True
222−
223−
224−# -- Options for manual page output ---------------------------------------
225−
226−# One entry per manual page. List of tuples
227−# (source start file, name, description, authors, manual section).
228−man_pages = [
229− ('index', 'purescript', u'PureScript Documentation',
230− [u'Phil Freeman'], 1)
231−]
232−
233−# If true, show URL addresses after external links.
234−#man_show_urls = False
235−
236−
237−# -- Options for Texinfo output -------------------------------------------
238−
239−# Grouping the document tree into Texinfo files. List of tuples
240−# (source start file, target name, title, author,
241−# dir menu entry, description, category)
242−texinfo_documents = [
243− ('index', 'PureScript', u'PureScript Documentation',
244− u'Phil Freeman', 'PureScript', 'One line description of project.',
245− 'Miscellaneous'),
246−]
247−
248−# Documents to append as an appendix to all manuals.
249−#texinfo_appendices = []
250−
251−# If false, no module index is generated.
252−#texinfo_domain_indices = True
253−
254−# How to display URL addresses: 'footnote', 'no', or 'inline'.
255−#texinfo_show_urls = 'footnote'
256−
257−# If true, do not generate a @detailmenu in the "Top" node's menu.
258−#texinfo_no_detailmenu = False
docs/source/ffi.rstdeleted−40
@@ -1,40 +0,0 @@
1−Foreign Function Interface
2−==========================
3−
4−Importing Values
5−----------------
6−
7−The ``foreign import`` keywords declare a value which is defined in Javascript, and its type::
8−
9− foreign import pow :: Number -> Number -> Number
10−
11−Inline Javascript
12−-----------------
13−
14−A foreign import declaration may optionally contain its definition in Javascript as a string literal. If this is provided, the string will be inserted directly into the generated Javascript before the current module definition::
15−
16− foreign import pow
17− "function pow(n) {\
18− \ return function(p) {\
19− \ return Math.pow(n, p);\
20− \ };\
21− \}" :: Number -> Number -> Number
22−
23−Importing Types
24−---------------
25−
26−To declare a new type with no constructors, use ``foreign import data`` and provide the kind::
27−
28− foreign import data DOM :: *
29−
30− foreign import document :: {
31− createElement :: String -> DOM
32− }
33−
34−Importing Type Class Instances
35−------------------------------
36−
37−Type class instances can be imported with ``foreign import instance``::
38−
39− foreign import instance showString :: Prelude.Show String
40−
docs/source/images/Prelude.pngdeleted

Binary file not shown.

docs/source/index.rstdeleted−31
@@ -1,31 +0,0 @@
1−.. PureScript documentation master file, created by
2− sphinx-quickstart on Wed Jan 22 22:04:23 2014.
3− You can adapt this file completely to your liking, but it should at least
4− contain the root `toctree` directive.
5−
6−Welcome to PureScript's documentation!
7−======================================
8−
9−Contents:
10−
11−.. toctree::
12− :maxdepth: 2
13−
14− intro
15− start
16− types
17− kinds
18− syntax
19− typeclasses
20− patterns
21− modules
22− ffi
23− prelude
24−
25−Indices and tables
26−==================
27−
28−* :ref:`genindex`
29−* :ref:`modindex`
30−* :ref:`search`
31−
docs/source/intro.rstdeleted−106
@@ -1,106 +0,0 @@
1−Introduction
2−============
3−
4−PureScript is a small strongly, statically typed compile-to-JS language with a number of interesting features, such as:
5−
6−- Type Inference
7−- Higher Kinded Polymorphism
8−- Support for basic Javascript types
9−- Extensible records
10−- Extensible effects
11−- Optimizer rules for generation of efficient Javascript
12−- Pattern matching
13−- Simple FFI
14−- Modules
15−- Rank N Types
16−- Do Notation
17−- Tail-call elimination
18−- Type Classes
19−
20−Motivation
21−----------
22−
23−I was looking for a simple functional language which would compile to JavaScript and have the following characteristics:
24−
25−- Generate simple readable Javascript
26−- Provide the ability to compile to tight loops if necessary
27−- Reasonable type system
28−- Ideally, written in a programming language I would enjoy working in
29−- Provides a simple interface to existing Javascript code
30−
31−I didn't find exactly what I was looking for, so I wrote PureScript. It doesn't have everything right now, but it should serve as a simple core on which to develop new ideas.
32−
33−PureScript was originally designed to implement purely functional core logic. However, recent additions to the compiler and libraries now also make it a good option for general-purpose programming.
34−
35−PureScript can also be seen as a trade-off between a theoretically ideal language and one which generates reasonably high performance code.
36−
37−Hello, PureScript!
38−------------------
39−
40−As an introductory example, here is the usual "Hello World" written in PureScript::
41−
42− module Main where
43−
44− import Debug.Trace
45−
46− main = trace "Hello, World!"
47−
48−which compiles to the following Javascript, ignoring the Prelude::
49−
50− var Main;
51− (function (Main) {
52− var main = trace("Hello, World!");
53− Main.main = main;
54− })(Main = Main || {});
55−
56−The following command will compile and execute the PureScript code above::
57−
58− psc input.purs --main | node
59−
60−Another Example
61−---------------
62−
63−The following code defines a ``Person`` data type and a function to generate a string representation for a ``Person``::
64−
65− data Person = Person { name :: String, age :: Number }
66−
67− showPerson :: Person -> String
68− showPerson (Person o) = o.name ++ ", aged " ++ show o.age
69−
70− examplePerson :: Person
71− examplePerson = Person { name: "Bonnie", age: 26 }
72−
73−Line by line, this reads as follows:
74−
75−- ``Person`` is a data type with one constructor, also called ``Person``
76−- The ``Person`` constructor takes an object with two properties, ``name`` which is a ``String``, and ``age`` which is a ``Number``
77−- The ``showPerson`` function takes a ``Person`` and returns a ``String``
78−- ``showPerson`` works by case analysis on its argument, first matching the constructor ``Person`` and then using string concatenation and object accessors to return its result.
79−- ``examplePerson`` is a Person object, made with the ``Person`` constructor and given the String "Bonnie" for the name value and the Number 26 for the age value.
80−
81−The generated Javascript looks like this::
82−
83− var Person = function (value) {
84− return { ctor: 'Person', values: [value] };
85− };
86−
87− function showPerson(_1) {
88− return _1.values[0].name + ", aged " + numberToString(_1.values[0].age);
89− };
90−
91− var examplePerson = Person({
92− name: "Bonnie",
93− age: 26
94− });
95−
96−Related Projects
97−----------------
98−
99−PureScript might be compared to other AltJS projects such as Roy, Haste, Fay, Elm and GHCJS. Certainly, there is a lot of overlap in terms of syntax, but the goals of PureScript listed above separate it in one or more ways from each of these languages.
100−
101−Roy is probably the most similar language on the list, and was a large influence on the development of PureScript. There are however, key differences in the foreign function interface, the type system and the choice of development language (Haskell vs. Javascript)
102−
103−Projects such as Haste, Fay and GHCJS aim to use some combination of the GHC compiler itself and/or its intermediate representation, Core, to perform some of the tasks involved in compilation such as parsing and type checking. This usually gives the advantage that tools and libraries can be shared with Haskell, but often at the cost of the size of the generated Javascript. This is the main practical difference between PureScript and these projects.
104−
105−Elm also shares a lot in terms of functionality with PureScript. Elm is designed for functional reactive programming, and focusses on tools and language features suitable for that domain, while PureScript focusses on the development of purely functional core application logic. Another difference between PureScript and Elm is PureScript's lack of a runtime system.
106−
docs/source/kinds.rstdeleted−21
@@ -1,21 +0,0 @@
1−Kind System
2−===========
3−
4−The kind system defines the following kinds:
5−
6−- ``*``, the kind of types.
7−- ``!``, the kind of effects.
8−- Arrow kinds ``k1 -> k2``
9−- Row kinds ``# k``
10−
11−Row Kinds
12−---------
13−
14−The kind ``# k`` of rows is used to classify labelled, unordered collections of types of kind ``k``.
15−
16−For example ``# *`` is the kind of rows of types, as used to define records, and ``# !`` is the kind of rows of effects, used to define the monad ``Eff`` of extensible effects.
17−
18−Quantification
19−--------------
20−
21−A type variable can refer to not only a type or a row, but a type constructor, or row constructor etc., and type variables with those kinds can be bound inside a ``forall`` quantifier.
docs/source/modules.rstdeleted−57
@@ -1,57 +0,0 @@
1−Modules
2−=======
3−
4−All code in PureScript is contained in a module. Modules are introduced using the ``module`` keyword::
5−
6− module A where
7−
8− id x = x
9−
10−When referencing values or data types in another module, names may be qualified by using a dot::
11−
12− module B where
13−
14− foo = A.id
15−
16−Importing Modules
17−-----------------
18−
19−A module can be imported using the ``import`` keyword. This will create aliases for all of the values and types in the imported module::
20−
21− module B where
22−
23− import A
24−
25−Alternatively, a list of names to import can be provided in parentheses::
26−
27− module B where
28−
29− import A (runFoo)
30−
31−Values, type constructors and data constructors can all be explicitly imported. A type constructor should be followed by a list of associated data constructors to import in parentheses. A double dot (``..``) can be used to import all data constructors for a given type constructor::
32−
33− module B where
34−
35− import A (runFoo, Foo(..), Bar(Bar))
36−
37−Qualified Imports
38−-----------------
39−
40−Modules can also be imported `qualified`, which means that their names will not be brought directly into scope, but rather, aliased to a different module name. This can be helpful when avoiding naming conflicts::
41−
42− module Main where
43−
44− import qualified Data.Array as A
45−
46− null = ...
47−
48−Here, the name ``null`` would ordinarily conflict with ``null`` from ``Data.Array``, but the qualified import solves this problem. ``Data.Array.null`` can be referenced using ``A.null`` instead.
49−
50−Module Exports
51−--------------
52−
53−Module exports can be restricted to a set of names by providing that set in parentheses in the module declaration::
54−
55− module A (runFoo, Foo(..)) where
56−
57−The types of names which can be exported is the same as for module imports.
docs/source/patterns.rstdeleted−139
@@ -1,139 +0,0 @@
1−Pattern Matching
2−================
3−
4−Pattern matching deconstructs a value to bring zero or more expressions into scope. Pattern matches are introduced with the `case` keyword.
5−
6−Pattern matches have the following general form::
7−
8− case value of
9− pattern -> result
10− ...
11− pattern -> result
12−
13−Pattern matching can also be used in the declaration of functions, as we have already seen::
14−
15− fn pattern_1 ... pattern_n = result
16−
17−Patterns can also be used when introducing functions. For example::
18−
19− example x y z = x * y + z
20−
21−The following pattern types are supported:
22−
23−- Wildcard pattern
24−- Literal patterns
25−- Variable pattern
26−- Array patterns
27−- Cons patterns
28−- Constructor patterns
29−- Record patterns
30−- Named patterns
31−- Guards
32−
33−Patterns need not be exhaustive. A pattern match failed exception will be thrown at runtime if no pattern matches the input.
34−
35−Wildcard Patterns
36−-----------------
37−
38−The wilcard `_` matches any input and brings nothing into scope::
39−
40− f _ = 0
41−
42−Literal Patterns
43−----------------
44−
45−Literal patterns are provided to match on primitives::
46−
47− f true = 0
48− f false = 1
49−
50− g "Foo" = 0
51− g _ = 1
52−
53− h 0 = 0
54− h _ = 1
55−
56−Variable Patterns
57−-----------------
58−
59−A variable pattern matches any input and binds that input to its name::
60−
61− double x = x * 2
62−
63−Array Patterns
64−--------------
65−
66−Array patterns match an input which is an array, and bring its elements into scope. For example::
67−
68− f [x] = x
69− f [x, y] = x * y
70− f _ = 0
71−
72−Here, the first pattern only matches arrays of length one, and brings the first element of the array into scope.
73−
74−The second pattern matches arrays with two elements, and brings the first and second elements into scope.
75−
76−Cons Patterns
77−-------------
78−
79−The head and tail of a non-empty array can be matched by using a cons pattern::
80−
81− sum [] = 0
82− sum (x : xs) = x + sum xs
83−
84−``:`` associates to the right::
85−
86− addPairs (x : y : xs) = x * y + addPairs xs
87− addPairs _ = 0
88−
89−
90−Constructor patterns
91−--------------------
92−
93−Constructor patterns match a data constructor and its arguments::
94−
95− data Foo = Foo String | Bar Number Boolean
96−
97− foo (Foo s) = true
98− foo (Bar _ b) = b
99−
100−Record Patterns
101−---------------
102−
103−Record patterns match an input which is a record, and bring its properties into scope::
104−
105− f { foo = "Foo", bar = n } = n
106− f _ = 0
107−
108−Nested Patterns
109−---------------
110−
111−The patterns above can be combined to create larger patterns. For example::
112−
113− f { arr = x : _, take = "car" } = x
114− f { arr = _ : x : _, take = "cadr" } = x
115− f _ = 0
116−
117−Named Patterns
118−--------------
119−
120−Named patterns bring additional names into scope when using nested patterns. Any pattern can be named by using the ``@`` symbol::
121−
122− f a@(_ : _ : _) = true
123− f _ = false
124−
125−Here, in the first pattern, any array with two or more elements will be matched and bound to the variable ``a``.
126−
127−Guards
128−------
129−
130−Guards are used to impose additional constraints inside a pattern using boolean-valued expressions, and are introduced with a pipe after the pattern::
131−
132− evens [] = 0
133− evens (x : xs) | x % 2 == 0 = 1 + evens xs
134− evens (_ : xs) = evens xs
135−
136−When using patterns to define a function at the top level, guards appear after all patterns::
137−
138− greater x y | x > y = true
139− greater _ _ = false
docs/source/prelude.rstdeleted−365
@@ -1,365 +0,0 @@
1−Module Documentation
2−====================
3−
4−Module Prelude
5−--------------
6−
7−Types
8−~~~~~
9−
10−::
11−
12− data Ordering where
13− LT :: Ordering
14− GT :: Ordering
15− EQ :: Ordering
16−
17−Type Classes
18−~~~~~~~~~~~~
19−
20−.. figure:: images/Prelude.png
21− :alt: Prelude
22−
23− Prelude
24−::
25−
26− class Alternative f where
27− empty :: forall a. f a
28− (<|>) :: forall a. f a -> f a -> f a
29−
30− class (Apply f) <= Applicative f where
31− pure :: forall a. a -> f a
32−
33− class (Functor f) <= Apply f where
34− (<*>) :: forall a b. f (a -> b) -> f a -> f b
35−
36− class (Apply m) <= Bind m where
37− (>>=) :: forall a b. m a -> (a -> m b) -> m b
38−
39− class Bits b where
40− (&) :: b -> b -> b
41− (|) :: b -> b -> b
42− (^) :: b -> b -> b
43− shl :: b -> Prim.Number -> b
44− shr :: b -> Prim.Number -> b
45− zshr :: b -> Prim.Number -> b
46− complement :: b -> b
47−
48− class BoolLike b where
49− (&&) :: b -> b -> b
50− (||) :: b -> b -> b
51− not :: b -> b
52−
53− class (Semigroupoid a) <= Category a where
54− id :: forall t. a t t
55−
56− class Eq a where
57− (==) :: a -> a -> Prim.Boolean
58− (/=) :: a -> a -> Prim.Boolean
59−
60− class Functor f where
61− (<$>) :: forall a b. (a -> b) -> f a -> f b
62−
63− class (Applicative m, Bind m) <= Monad m where
64−
65− class Num a where
66− (+) :: a -> a -> a
67− (-) :: a -> a -> a
68− (*) :: a -> a -> a
69− (/) :: a -> a -> a
70− (%) :: a -> a -> a
71− negate :: a -> a
72−
73− class (Eq a) <= Ord a where
74− compare :: a -> a -> Ordering
75−
76− class Semigroup a where
77− (<>) :: a -> a -> a
78−
79− class Semigroupoid a where
80− (<<<) :: forall b c d. a c d -> a b c -> a b d
81−
82− class Show a where
83− show :: a -> Prim.String
84−
85−Type Class Instances
86−~~~~~~~~~~~~~~~~~~~~
87−
88−::
89−
90− instance bitsNumber :: Bits Prim.Number
91−
92− instance boolLikeBoolean :: BoolLike Prim.Boolean
93−
94− instance categoryArr :: Category Prim.Function
95−
96− instance eqArray :: (Eq a) => Eq [a]
97−
98− instance eqBoolean :: Eq Prim.Boolean
99−
100− instance eqNumber :: Eq Prim.Number
101−
102− instance eqOrdering :: Eq Ordering
103−
104− instance eqString :: Eq Prim.String
105−
106− instance numNumber :: Num Prim.Number
107−
108− instance ordNumber :: Ord Prim.Number
109−
110− instance semigroupString :: Semigroup Prim.String
111−
112− instance semigroupoidArr :: Semigroupoid Prim.Function
113−
114− instance showArray :: (Show a) => Show [a]
115−
116− instance showBoolean :: Show Prim.Boolean
117−
118− instance showNumber :: Show Prim.Number
119−
120− instance showOrdering :: Show Ordering
121−
122− instance showString :: Show Prim.String
123−
124−Values
125−~~~~~~
126−
127−::
128−
129− (#) :: forall a b. a -> (a -> b) -> b
130−
131− ($) :: forall a b. (a -> b) -> a -> b
132−
133− (++) :: forall s. (Semigroup s) => s -> s -> s
134−
135− (:) :: forall a. a -> [a] -> [a]
136−
137− (<) :: forall a. (Ord a) => a -> a -> Prim.Boolean
138−
139− (<=) :: forall a. (Ord a) => a -> a -> Prim.Boolean
140−
141− (>) :: forall a. (Ord a) => a -> a -> Prim.Boolean
142−
143− (>=) :: forall a. (Ord a) => a -> a -> Prim.Boolean
144−
145− (>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d
146−
147− ap :: forall m a b. (Monad m) => m (a -> b) -> m a -> m b
148−
149− asTypeOf :: forall a. a -> a -> a
150−
151− boolAnd :: Prim.Boolean -> Prim.Boolean -> Prim.Boolean
152−
153− boolNot :: Prim.Boolean -> Prim.Boolean
154−
155− boolOr :: Prim.Boolean -> Prim.Boolean -> Prim.Boolean
156−
157− concatString :: Prim.String -> Prim.String -> Prim.String
158−
159− cons :: forall a. a -> [a] -> [a]
160−
161− const :: forall a b. a -> b -> a
162−
163− flip :: forall a b c. (a -> b -> c) -> b -> a -> c
164−
165− liftA1 :: forall f a b. (Applicative f) => (a -> b) -> f a -> f b
166−
167− liftM1 :: forall m a b. (Monad m) => (a -> b) -> m a -> m b
168−
169− numAdd :: Prim.Number -> Prim.Number -> Prim.Number
170−
171− numAnd :: Prim.Number -> Prim.Number -> Prim.Number
172−
173− numCompare :: Prim.Number -> Prim.Number -> Ordering
174−
175− numComplement :: Prim.Number -> Prim.Number
176−
177− numDiv :: Prim.Number -> Prim.Number -> Prim.Number
178−
179− numMod :: Prim.Number -> Prim.Number -> Prim.Number
180−
181− numMul :: Prim.Number -> Prim.Number -> Prim.Number
182−
183− numNegate :: Prim.Number -> Prim.Number
184−
185− numOr :: Prim.Number -> Prim.Number -> Prim.Number
186−
187− numShl :: Prim.Number -> Prim.Number -> Prim.Number
188−
189− numShr :: Prim.Number -> Prim.Number -> Prim.Number
190−
191− numSub :: Prim.Number -> Prim.Number -> Prim.Number
192−
193− numXor :: Prim.Number -> Prim.Number -> Prim.Number
194−
195− numZshr :: Prim.Number -> Prim.Number -> Prim.Number
196−
197− refEq :: forall a. a -> a -> Prim.Boolean
198−
199− refIneq :: forall a. a -> a -> Prim.Boolean
200−
201− return :: forall m a. (Monad m) => a -> m a
202−
203− showArrayImpl :: forall a. (a -> Prim.String) -> [a] -> Prim.String
204−
205− showNumberImpl :: Prim.Number -> Prim.String
206−
207− showStringImpl :: Prim.String -> Prim.String
208−
209−Module Data.Function
210−--------------------
211−
212−Values
213−~~~~~~
214−
215−::
216−
217− on :: forall a b c. (b -> b -> c) -> (a -> b) -> a -> a -> c
218−
219−Module Data.Eq
220−--------------
221−
222−Types
223−~~~~~
224−
225−::
226−
227− data Ref a where
228− Ref :: a -> Ref a
229−
230−Type Class Instances
231−~~~~~~~~~~~~~~~~~~~~
232−
233−::
234−
235− instance eqRef :: Eq (Ref a)
236−
237−Values
238−~~~~~~
239−
240−::
241−
242− liftRef :: forall a b. (a -> a -> b) -> Ref a -> Ref a -> b
243−
244−Module Prelude.Unsafe
245−---------------------
246−
247−Values
248−~~~~~~
249−
250−::
251−
252− unsafeIndex :: forall a. [a] -> Prim.Number -> a
253−
254−Module Control.Monad.Eff
255−------------------------
256−
257−Types
258−~~~~~
259−
260−::
261−
262− data Eff :: # ! -> * -> *
263−
264− type Pure a = forall e. Eff e a
265−
266−Type Class Instances
267−~~~~~~~~~~~~~~~~~~~~
268−
269−::
270−
271− instance applicativeEff :: Applicative (Eff e)
272−
273− instance applyEff :: Apply (Eff e)
274−
275− instance bindEff :: Bind (Eff e)
276−
277− instance functorEff :: Functor (Eff e)
278−
279− instance monadEff :: Monad (Eff e)
280−
281−Values
282−~~~~~~
283−
284−::
285−
286− bindE :: forall e a b. Eff e a -> (a -> Eff e b) -> Eff e b
287−
288− forE :: forall e. Prim.Number -> Prim.Number -> (Prim.Number -> Eff e { }) -> Eff e { }
289−
290− foreachE :: forall e a. [a] -> (a -> Eff e { }) -> Eff e { }
291−
292− returnE :: forall e a. a -> Eff e a
293−
294− runPure :: forall a. Pure a -> a
295−
296− untilE :: forall e. Eff e Prim.Boolean -> Eff e { }
297−
298− whileE :: forall e a. Eff e Prim.Boolean -> Eff e a -> Eff e { }
299−
300−Module Control.Monad.Eff.Unsafe
301−-------------------------------
302−
303−Values
304−~~~~~~
305−
306−::
307−
308− unsafeInterleaveEff :: forall eff1 eff2 a. Eff eff1 a -> Eff eff2 a
309−
310−Module Debug.Trace
311−------------------
312−
313−Types
314−~~~~~
315−
316−::
317−
318− data Trace :: !
319−
320−Values
321−~~~~~~
322−
323−::
324−
325− print :: forall a r. (Show a) => a -> Eff (trace :: Trace | r) { }
326−
327− trace :: forall r. Prim.String -> Eff (trace :: Trace | r) { }
328−
329−Module Control.Monad.ST
330−-----------------------
331−
332−Types
333−~~~~~
334−
335−::
336−
337− data ST :: * -> !
338−
339− data STArray :: * -> * -> *
340−
341− data STRef :: * -> * -> *
342−
343−Values
344−~~~~~~
345−
346−::
347−
348− modifySTRef :: forall a h r. STRef h a -> (a -> a) -> Eff (st :: ST h | r) a
349−
350− newSTArray :: forall a h r. Prim.Number -> a -> Eff (st :: ST h | r) (STArray h a)
351−
352− newSTRef :: forall a h r. a -> Eff (st :: ST h | r) (STRef h a)
353−
354− peekSTArray :: forall a h r. STArray h a -> Eff (st :: ST h | r) a
355−
356− pokeSTArray :: forall a h r. STArray h a -> Prim.Number -> a -> Eff (st :: ST h | r) a
357−
358− readSTRef :: forall a h r. STRef h a -> Eff (st :: ST h | r) a
359−
360− runST :: forall a r. (forall h. Eff (st :: ST h | r) a) -> Eff r a
361−
362− runSTArray :: forall a r. (forall h. Eff (st :: ST h | r) (STArray h a)) -> Eff r [a]
363−
364− writeSTRef :: forall a h r. STRef h a -> a -> Eff (st :: ST h | r) a
365−
docs/source/start.rstdeleted−62
@@ -1,62 +0,0 @@
1−Getting Started
2−===============
3−
4−Compiler Installation
5−---------------------
6−
7−If you have the Haskell Plaform installed, then you can install the latest released version from Hackage::
8−
9− cabal update
10− cabal install purescript
11−
12−If you would like to build the latest version of the code, clone this repository and build::
13−
14− git clone git://github.com:paf31/purescript.git
15− cabal configure --enable-tests
16− cabal build
17− cabal test
18− cabal install
19−
20−Alternatively, consider installing PureScript in a Cabal sandbox using ``cabal sandbox init``.
21−
22−Creating a new PureScript project
23−---------------------------------
24−
25−You can create a new PureScript project using ``grunt-init`` and `this PureScript project template <https://github.com/purescript-contrib/grunt-init-purescript>`_. This will give you a project that uses `Grunt <http://gruntjs.com>`_ as its build tool and `Bower <http://bower.io>`_ for dependency management. See the `README <https://github.com/purescript-contrib/grunt-init-purescript>`_ for step-by-step instructions.
26−
27−Compiler usage
28−--------------
29−
30−The `psc` executable takes a list of PureScript source files as arguments and by default writes out its errors or output to the console.
31−
32−The following options are supported:
33−
34−--stdin Read input from standard input instead of from files.
35−--output Write the generated Javascript to the specified file.
36−--externs Write a list of foreign imports declarations to the specified file in addition to generating Javascript output.
37−--runtime-type-checks Generate simple runtime type checks for function arguments with simple types.
38−--no-tco Turn off tail-call elimination.
39−--no-prelude Do not include the Prelude in the generated Javascript.
40−--no-magic-do Turn off optimizations which inline calls to ``>>=`` for the ``Eff`` monad.
41−--no-opts Disable all optimizations.
42−--main Generate a call to ``main`` in the specified module after all other generated Javascript. Defaults to ``Main`` if the option is used but no value is provided.
43−--module If specified, any code which is not referenced transitively from this module will be removed. This argument can be used multiple times.
44−--codegen A list of modules for which Javascript and externs should be generated. This argument can be used multiple times.
45−--browser-namespace Specify the namespace that PureScript modules will be exported to when running in the browser.
46−--verbose-errors Generate verbose error messages.
47−
48−psc-make
49−--------
50−
51−The ``psc-make`` executable makes CommonJS modules and supports incremental compilation. Unlike ``psc``, it does not do dead code elimination.
52−
53−The following command line options are supported:
54−
55−--output=VAL The output directory. Default: ``output``.
56−--runtime-type-checks Generate runtime type checks
57−--verbose-errors Display verbose error messages.
58−--help=FMT Show this help in format FMT (``pager``, ``plain``, or ``groff``). Default: ``pager``.
59−--no-magic-do Disable the optimization that overloads the ``do`` keyword to generate efficient code specifically for the ``Eff`` monad.
60−--no-opts Skip the optimization phase.
61−--no-prelude Omit the Prelude.
62−--no-tco Disable tail call optimizations
docs/source/syntax.rstdeleted−266
@@ -1,266 +0,0 @@
1−Syntax
2−======
3−
4−Whitespace Rules
5−----------------
6−
7−Syntax is whitespace sensitive. The general rule of thumb is that declarations which span multiple lines should be indented past the column on which they were first defined on their subsequent lines.
8−
9−That is, the following is valid::
10−
11− foo = bar(x) +
12− baz(x)
13−
14−But this is not::
15−
16− foo = bar(x) +
17− baz(x)
18−
19−Operators
20−---------
21−
22−Binary operators in PureScript are just regular functions. The Prelude defines a number of operators which correspond to Javascript's operators.
23−
24−The Prelude defines the following functions which correspond to Javascript's unary operators:
25−
26−========== ======== =======================
27−Function Operator Meaning
28−========== ======== =======================
29−negate \- Numeric negation
30−not ! Boolean negation
31−complement ~ Binary negation
32−========== ======== =======================
33−
34−and the following binary operators:
35−
36−========== =========== =====================
37−Function JS Operator Meaning
38−========== =========== =====================
39−\+ \+ Numeric addition
40−\- \- Numeric subtraction
41−\* \* Numeric multiplication
42−/ / Numeric division
43−% % Numeric modulus
44−== == Equality check
45−/= != Inequality check
46−< < Less than
47−<= <= Less than or equal
48−> > Greater than
49−>= >= Greater than or equal
50−&& && Boolean AND
51−|| || Boolean OR
52−& & Binary AND
53−\| \| Binary OR
54−^ ^ Binary XOR
55−shl << Shift Left
56−shr >> Shift Right
57−zshr \>>> Zero-Fill Shift Right
58−++ \+ String concatenation
59−========== =========== =====================
60−
61−Literal Values
62−--------------
63−
64−Numeric literals can be integers or floating point numbers. Numbers in hexadecimal notation should be preceded by the characters ``0x``::
65−
66− 16
67− 16.0
68− 0xF0
69−
70−String literals are enclosed in double-quotes and may extend over multiple lines. Line breaks should be surrounded by slashes as follows::
71−
72− "Hello World"
73−
74− "Hello \
75− \World"
76−
77−The two boolean literals are ``true`` and ``false``.
78−
79−Array Literals
80−--------------
81−
82−Array literals are surrounded by square brackets, as in Javascript::
83−
84− []
85− [1, 2, 3]
86−
87−Record Literals
88−---------------
89−
90−Record literals are surrounded by braces, as in Javascript::
91−
92− {}
93− { foo: "Foo", bar: 1 }
94−
95−Array Indexing
96−--------------
97−
98−The ``Prelude.Unsafe`` module defines the ``unsafeIndex`` function which retrieves the element of an array at an index::
99−
100− unsafeIndex :: forall a. [a] -> Number -> a
101−
102−The code generator will turn the expression ``unsafeIndex arr index`` into the simplified Javascript ``arr[index]``.
103−
104−The ``purescript-array`` core library defines an alternative safe version ``!!`` of ``unsafeIndex`` which checks arrays bounds and returns a value of type ``Maybe a``.
105−
106−Property Accessors
107−------------------
108−
109−To access a property of a record, use a dot, followed by the property name, as in Javascript::
110−
111− rec.propertyName
112−
113−Functions
114−---------
115−
116−Functions are introduced by using a backslash followed by a list of argument names::
117−
118− example1 = \a b -> a + b
119−
120−which would correspond to the following Javascript::
121−
122− function example1(a) {
123− return function (b) {
124− return a + b;
125− }
126− }
127−
128−Function application is indicated by just the juxtaposition of a function with its arugments::
129−
130− example1 10 20
131−
132−Functions can also be defined at the top level by providing a list of patterns and an optional guard on the left hand side of the equals sign::
133−
134− f [] [] = []
135− f (x:xs) (y:ys) = x + y : f xs ys
136−
137−If-Then-Else Expressions
138−------------------------
139−
140−The ``if``, ``then`` and ``else`` keywords can be used to create conditional expressions. In this case, the ``else`` block is always required.
141−
142−For example::
143−
144− conditional = if 2 > 1 then "ok" else "oops"
145−
146−Do Notation
147−-----------
148−
149−The ``do`` keyword introduces simple syntactic sugar for monadic expressions.
150−
151−Here is an example, using the maybe monad::
152−
153− data Maybe a = Nothing | Just a
154−
155− isEven :: Number -> Maybe {}
156− isEven n | n % 2 == 0 = Just {}
157− isEven _ = Nothing
158−
159− evenSum a b = do
160− n <- a
161− m <- b
162− let sum = n + m
163− isEven sum
164− return sum
165−
166−``isEven`` adds two values of type ``Maybe Number`` and returns their sum, if the sum is even. If the sum is odd, ``evenSum`` returns ``Nothing``.
167−
168−When using ``do`` notation, the corresponding type constructor must be an instance of the ``Prelude.Monad`` type class.
169−
170−Statements can have the following form:
171−
172−- ``a <- x`` which desugars to ``x >>= \a -> ...``
173−- ``x`` which desugars to ``x >>= \_ -> ...`` or just ``x`` if this is the last statement.
174−- A let binding ``let a = x`` where ``a`` can be either a name or a binder. Note the lack of the ``in`` keyword.
175−
176−The example ``evenSum`` desugars to::
177−
178− evenSum a b =
179− a >>= \n ->
180− b >>= \m ->
181− let sum = n + m in
182− isEven sum >>= \_ ->
183− return sum
184−
185−Binders can be used on the left hand side of ``<-`` or ``=``. For example::
186−
187− test arr = do
188− (x:y:_) <- arr
189− ret (x + y)
190−
191−A pattern match failure will generate a runtime exception, just as in the case of a regular ``case`` statement.
192−
193−Operators
194−---------
195−
196−User-defined infix operators can be created by enclosing names in parentheses.
197−
198−E.g. to create an infix synonym for the ``Data.Array.range`` function::
199−
200− (..) :: Number -> Number -> [Number]
201− (..) = Data.Array.range
202−
203−This function can be used as follows::
204−
205− oneToTen = 1 .. 10
206−
207−Regular functions can be used as operators by enclosing their names in backticks::
208−
209− foo x y = x * y + y
210−
211− test = 10 `foo` 20
212−
213−Fixity declarations can associate a precedence level, which is a natural number, to a user-defined operator, and specify which way it associates::
214−
215− infix 5 ..
216− infixl 7 %%
217− infixr 9 ^^
218−
219−Record Updates
220−--------------
221−
222−Properties on records can be updated using the following syntax::
223−
224− o { key = value, ..., key = value }
225−
226−For example, the following function increments the ``foo`` property on its argument::
227−
228− incr o = o { foo = o.foo + 1 }
229−
230−Let Bindings
231−------------
232−
233−The ``let`` keywords a collection of local declarations, which may be mutually recursive, and which may include type declarations::
234−
235− factorial :: Number -> Number
236− factorial =
237− let
238− go :: Number -> Number -> Number
239− go acc 1 = acc
240− go acc n = go (acc * n) (n - 1)
241− in
242− go 1
243−
244−The ``where`` keyword can also be used to introduce local declarations `at the end of a value declaration`::
245−
246− factorial :: Number -> Number
247− factorial = go 1
248− where
249− go :: Number -> Number -> Number
250− go acc 1 = acc
251− go acc n = go (acc * n) (n - 1)
252−
253−Comments
254−--------
255−
256−A single line comment starts with ``--``::
257−
258− -- This is a comment
259−
260−Multi-line comments are enclosed in ``{-`` and ``-}``. These can be nested::
261−
262− {- Comment {- nested comment -} continued comment -}
263−
264−
265−
266−
docs/source/typeclasses.rstdeleted−48
@@ -1,48 +0,0 @@
1−Type Classes
2−============
3−
4−PureScript has basic support for type classes via the ``class`` and ``instance`` keywords.
5−
6−Types appearing in class instances are must be of the form ``String``, ``Number``, ``Boolean``, or ``C t1 ... tn`` where ``C`` is a type constructor (including ``[]`` and ``->`` and ``t_i`` are types of the same form).
7−
8−Type class instances are resolved based on the order in which they appeared in the source files. Overlapping instances will result in a compilation error.
9−
10−Example
11−-------
12−
13−Here is an example of the ``Show`` typeclass, with instances for ``String``, ``Booleans`` and ``[]``::
14−
15− class Show a where
16− show :: a -> String
17−
18− instance showString :: Show String where
19− show s = s
20−
21− instance showBoolean :: Show Boolean where
22− show true = "true"
23− show false = "false"
24−
25− instance showArray :: (Show a) => Show [a] where
26− show [] = "[]"
27− show (x:xs) = show x ++ " : " ++ showArray xs
28−
29− example = show [true, false]
30−
31−Superclasses
32−------------
33−
34−Superclass implications can be indicated in a class declaration with a backwards fat arrow ``<=``::
35−
36− class (Monad m) <= MonadFail m where
37− fail :: forall a. String -> m a
38−
39−Superclass instances will be used when searching for an instance of a subclass. For example, in the code below, the ``Monad`` constraint introduced by the ``return`` function can be discharged since ``Monad`` is a superclass of ``MonadFail``::
40−
41− assert :: forall m. (MonadFail m) => Bool -> m {}
42− assert true = return {}
43− assert false = fail "Assertion failed"
44−
45−Type Annotations
46−----------------
47−
48−A constrained type will never be inferred for a top-level declaration without an explicit type signature.
docs/source/types.rstdeleted−158
@@ -1,158 +0,0 @@
1−Types
2−=====
3−
4−The type system defines the following types:
5−
6−- Primitive Types: Number, String, Boolean
7−- Arrays
8−- Records
9−- Tagged Unions
10−- Functions
11−- Polymorphic Types
12−- Constrained Types
13−- Type Synonyms
14−- Rows
15−
16−Primitive Types
17−---------------
18−
19−The three primitive types ``String``, ``Number`` and ``Boolean`` correspond to their Javascript equivalents at runtime.
20−
21−Arrays
22−------
23−
24−PureScript arrays correspond to Javascript arrays at runtime, but all elements in an array must have the same type.
25−
26−Records
27−-------
28−
29−PureScript records correspond to Javascript objects. They may have zero or more named fields, each with their own types.
30−
31−Tagged Unions
32−-------------
33−
34−Tagged unions consist of one or more constructors, each of which takes zero or more arguments.
35−
36−Tagged unions can only be created using their constructors, and deconstructed through pattern matching (see later).
37−
38−For example::
39−
40− data Foo a = Foo | Bar String
41−
42− runFoo Foo = "It's a Foo"
43− runFoo (Bar s) = "It's a Bar. The string is " ++ s
44−
45− test = runFoo Foo ++ runFoo (Bar "Test")
46−
47−In the example, Foo is a tagged union type which has two constructors. It's first constructor ``Foo`` takes no argument, and it's second ``Bar`` takes one, which must be a String.
48−
49−``runFoo`` is an example of pattern matching on a tagged union type to discover its constructor, and the last line shows how to construct values of type ``Foo``.
50−
51−Functions
52−---------
53−
54−Functions in PureScript are like their Javascript counterparts, but always have exactly one argument.
55−
56−Polymorphic Types
57−-----------------
58−
59−Expressions defined at the top level may have polymorphic types.
60−
61−Here is an example::
62−
63− identity x = x
64−
65−``identity`` is inferred to have (polymorphic) type ``forall t0. t0 -> t0``. This means that for any type ``t0``, ``identity`` can be given a value of type ``t0`` and will give back a value of the same type.
66−
67−A type annotation can also be provided::
68−
69− identity :: forall a. a -> a
70− identity x = x
71−
72−Row Polymorphism
73−----------------
74−
75−Polymorphism is not limited to abstracting over types. Values may also be polymorphic in types with other kinds, such as rows or effects (see "Kind System").
76−
77−For example, the following function accesses two properties on a record::
78−
79− addProps o = o.foo + o.bar
80−
81−The inferred type of ``addProps`` is::
82−
83− forall r. { foo :: Number, bar :: Number | r } -> Number
84−
85−Here, the type variable ``r`` has kind ``# *`` - it represents a `row` of `types`. It can be instantiated with any row of named types.
86−
87−In other words, ``addProps`` accepts any record which has properties ``foo`` and ``bar``, and *any other record properties*.
88−
89−Therefore, the following application compiles::
90−
91− addProps { foo: 1, bar: 2, baz: 3 }
92−
93−even though the type of ``addProps`` does not mention the property ``baz``. However, the following does not compile::
94−
95− addProps { foo: 1 }
96−
97−since the ``bar`` property is missing.
98−
99−Rank N Types
100−------------
101−
102−It is also possible for the ``forall`` quantifier to appear on the left of a function arrow, inside types record fields and data constructors, and in type synonyms.
103−
104−In most cases, a type annotation is necessary when using this feature.
105−
106−As an example, we can pass a polymorphic function as an argument to another function::
107−
108− poly :: (forall a. a -> a) -> Boolean
109− poly f = (f 0 < 1) == f true
110−
111−Notice that the polymorphic function's type argument is instantiated to both ``Number`` and ``Boolean``.
112−
113−An argument to ``poly`` must indeed be polymorphic. For example, the following fails::
114−
115− test = poly (\n -> n + 1)
116−
117−since the skolemized type variable ``a`` does not unify with ``Number``.
118−
119−Rows
120−----
121−
122−A row of types represents an unordered collection of named types without duplicates.
123−
124−Rows have kind ``# k`` for some kind ``k``, and so values do not have types which are rows. Rather, rows can be used in type signatures to define record types or other type where labelled, unordered types are useful.
125−
126−To denote a closed row, separate the fields with commas, with each label separated from its type with a double colon::
127−
128− (name :: String, age :: Number)
129−
130−It may be necessary, depending on the context, to surround a row in parentheses.
131−
132−To denote an open row (i.e. one which may unify with another row to add new fields), separate the specified terms from a row variable by a pipe::
133−
134− (name :: String, age :: Number | r)
135−
136−Type Synonyms
137−-------------
138−
139−For convenience, it is possible to declare a synonym for a type using the ``type`` keyword. Type synonyms can include type arguments.
140−
141−For example::
142−
143− type Foo = { foo :: Number, bar :: Number }
144−
145− addFoo :: Foo -> Number
146− addFoo = \o -> o.foo + o.bar
147−
148−Constrained Types
149−-----------------
150−
151−Polymorphic types may be predicated on one or more ``constraints``. See the chapter on type classes for more information.
152−
153−Type Annotations
154−----------------
155−
156−Most types can be inferred (not including Rank N Types and constrained types), but annotations can optionally be provided using a double-colon::
157−
158− one = 1 :: Number
examples/.gitignoredeleted−1
@@ -1 +0,0 @@
1−shelltest/tests
examples/failing/ArrayType.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Main where
2−
3−import Debug.Trace
4−
5−bar :: Number -> Number -> Number
6−bar n m = n + m
7−
8−foo = x `bar` y
9− where
10− x = 1
11− y = []
examples/failing/Arrays.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− test = \arr -> arr !! (0 !! 0)
examples/failing/Do.pursdeleted−8
@@ -1,8 +0,0 @@
1−module Main where
2−
3−test1 = do let x = 1
4−
5−test2 y = do x <- y
6−
7−test3 = do return 1
8− return 2
examples/failing/KindError.pursdeleted−3
@@ -1,3 +0,0 @@
1−module Main where
2−
3− data KindError f a = One f | Two (f a)
examples/failing/Let.pursdeleted−3
@@ -1,3 +0,0 @@
1−module Main where
2−
3−test = let x = x in x
examples/failing/MPTCs.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Main where
2−
3−class Foo a where
4− f :: a -> a
5−
6−instance Foo String String where
7− f a = a
examples/failing/MutRec.pursdeleted−5
@@ -1,5 +0,0 @@
1−module MutRec where
2−
3−x = y
4−
5−y = x
examples/failing/MutRec2.pursdeleted−3
@@ -1,3 +0,0 @@
1−module Main where
2−
3−x = x
examples/failing/NoOverlap.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Main where
2−
3−data Foo = Foo
4−
5−instance showFoo1 :: Show Foo where
6− show _ = "Foo"
7−
8−instance showFoo2 :: Show Foo where
9− show _ = "Bar"
10−
11−test = show Foo
examples/failing/NullaryAbs.pursdeleted−3
@@ -1,3 +0,0 @@
1−module Main where
2−
3− func = \ -> "no"
examples/failing/Object.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Main where
2−
3−test o = o.foo
4−
5−test1 = test {}
examples/failing/OverlappingVars.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3−class OverlappingVars a where
4− f :: a -> a
5−
6−data Foo a b = Foo a b
7−
8−instance OverlappingVars (Foo a a) where
9− f a = a
10−
11−test = f (Foo "" 0)
12−
examples/failing/Rank2Types.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− foreign import test :: (forall a. a -> a) -> Number
6−
7− test1 = test (\n -> n + 1)
examples/failing/Reserved.pursdeleted−4
@@ -1,4 +0,0 @@
1−module Main where
2−
3−(<) :: Number -> Number -> Number
4−(<) a b = !(a >= b)
examples/failing/SkolemEscape.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Main where
2−
3− foreign import foo :: (forall a. a -> a) -> Number
4−
5− test = \x -> foo x
examples/failing/SkolemEscape2.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Control.Monad.ST
6−
7−test _ = do
8− r <- runST (newSTRef 0)
9− return 0
examples/failing/Superclasses1.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Main where
2−
3−class Su a where
4− su :: a -> a
5−
6−class (Su a) <= Cl a where
7− cl :: a -> a -> a
8−
9−instance clNumber :: Cl Number where
10− cl n m = n + m
11−
examples/failing/Superclasses2.pursdeleted−9
@@ -1,9 +0,0 @@
1−module CycleInSuperclasses where
2−
3−class (Foo a) <= Bar a
4−
5−class (Bar a) <= Foo a
6−
7−instance barString :: Bar String
8−
9−instance fooString :: Foo String
examples/failing/Superclasses3.pursdeleted−5
@@ -1,5 +0,0 @@
1−module UnknownSuperclassTypeVar where
2−
3−class Foo a
4−
5−class (Foo b) <= Bar a
examples/failing/Superclasses4.pursdeleted−12
@@ -1,12 +0,0 @@
1−module OverlappingInstances where
2−
3−class Foo a
4−
5−instance foo1 :: Foo Number
6−
7−instance foo2 :: Foo Number
8−
9−test :: forall a. (Foo a) => a -> a
10−test a = a
11−
12−test1 = test 0
examples/failing/TypeClassInstances.pursdeleted−8
@@ -1,8 +0,0 @@
1−module Main where
2−
3−class A a where
4− a :: a -> String
5− b :: a -> Number
6−
7−instance A String where
8− a s = s
examples/failing/TypeClasses2.pursdeleted−8
@@ -1,8 +0,0 @@
1−module Main where
2−
3−import Prelude ()
4−
5−class Show a where
6− show :: a -> String
7−
8−test = show "testing"
examples/failing/TypeError.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− test = 1 ++ "A"
examples/failing/TypeSynonyms.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Main where
2−
3−type T1 = [T2]
4−
5−type T2 = T1
examples/failing/TypeSynonyms2.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3−class Foo a where
4− foo :: a -> String
5−
6−type Bar = String
7−
8−instance Foo Bar where
9− foo s = s
examples/failing/TypeSynonyms3.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3−class Foo a where
4− foo :: a -> String
5−
6−type Bar = String
7−
8−instance Foo Bar where
9− foo s = s
examples/failing/UnifyInTypeInstanceLookup.pursdeleted−17
@@ -1,17 +0,0 @@
1−module Main where
2−
3−data Z = Z
4−data S n = S n
5−
6−data T
7−data F
8−
9−class EQ x y b
10−instance eqT :: EQ x x T
11−instance eqF :: EQ x y F
12−
13−foreign import test :: forall a b. (EQ a b T) => a -> b -> a
14−
15−foreign import anyNat :: forall a. a
16−
17−test1 = test anyNat (S Z)
examples/failing/UnknownType.pursdeleted−4
@@ -1,4 +0,0 @@
1−module Main where
2−
3−test :: Number -> Something
4−test = {}
examples/failing/UnknownValue.pursdeleted−25
@@ -1,25 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Control.Monad.ST
6−import Debug.Trace
7−
8−test = runSTArray (do
9− a <- newSTArray 2 0
10− pokeSTArray a 0 1
11− pokeSTArray a 1 2
12− return a)
13−
14−fromTo lo hi = runSTArray (do
15− arr <- newSTArray (hi - lo + 1) 0
16− (let
17− go lo hi _ arr | lo > hi = return arr
18− go lo hi i arr = do
19− pokeSTArray arrr i lo
20− go (lo + 1) hi (i + 1) arr
21− in go lo hi 0 arr))
22−
23−main = do
24− let t1 = runPure (fromTo 10 20)
25− trace "Done"
examples/manual/failing/ArgLengthMismatch.pursdeleted−4
@@ -1,4 +0,0 @@
1−module ArgLengthMismatch where
2−
3− f x y = true
4− f = false
examples/manual/failing/ExportExplicit.pursdeleted−5
@@ -1,5 +0,0 @@
1−-- should fail as z does not exist in the module
2−module M1 (x, y, z) where
3−
4− x = 1
5− y = 2
examples/manual/failing/ExportExplicit1.pursdeleted−14
@@ -1,14 +0,0 @@
1−module M1 (X(X)) where
2−
3− data X = X | Y
4−
5−module Main where
6−
7− import M1
8−
9− testX = X
10−
11− -- should fail as Y constructor is not exported from M1
12− testY = Y
13−
14− main = Debug.Trace.trace "Done"
examples/manual/failing/ExportExplicit2.pursdeleted−5
@@ -1,5 +0,0 @@
1−-- should fail as Y is not a data constructor for X
2−module M1 (X(Y)) where
3−
4− data X = X
5− data Y = Y
examples/manual/failing/ExportExplicit3.pursdeleted−13
@@ -1,13 +0,0 @@
1−module M1 (X(..)) where
2−
3− data X = X | Y
4− data Z = Z
5−
6−module Main where
7−
8− import M1
9−
10− -- should fail as Z is not exported from M1
11− testZ = M1.Z
12−
13− main = Debug.Trace.trace "Done"
examples/manual/failing/ImportExplicit.pursdeleted−7
@@ -1,7 +0,0 @@
1−module M1 where
2−
3− foo = "foo"
4−
5−module Main where
6−
7− import M1 (X(..))
examples/manual/failing/ImportExplicit2.pursdeleted−7
@@ -1,7 +0,0 @@
1−module M1 where
2−
3− data X = Y
4−
5−module Main where
6−
7− import M1 (X(Z, Q))
examples/manual/failing/ImportModule.pursdeleted−7
@@ -1,7 +0,0 @@
1−module M2 where
2−
3− data X = X
4−
5−module Main where
6−
7− import M1
examples/manual/failing/OrphanTypeDecl.pursdeleted−3
@@ -1,3 +0,0 @@
1−module OrphanTypeDecl where
2−
3− fn :: Number -> Boolean
examples/manual/failing/RedefinedFixity.pursdeleted−6
@@ -1,6 +0,0 @@
1−module RedefinedFixity where
2−
3− (!?) x y = x + y
4−
5− infix 2 !?
6− infix 2 !?
examples/manual/failing/RequiredHiddenType.pursdeleted−8
@@ -1,8 +0,0 @@
1−-- exporting `a` should fail as `A` is hidden
2−module Foo (B(..), a, b) where
3−
4− data A = A
5− data B = B
6−
7− a = A
8− b = B
examples/manual/passing/ExportExplicit.pursdeleted−20
@@ -1,20 +0,0 @@
1−module M1 (X(X), Z(..), foo) where
2−
3− data X = X | Y
4− data Z = Z
5−
6− foo :: Number
7− foo = 0
8−
9− bar :: Number
10− bar = 1
11−
12−module Main where
13−
14− import M1
15−
16− testX = X
17− testZ = Z
18− testFoo = foo
19−
20− main = Debug.Trace.trace "Done"
examples/manual/passing/ExportExplicit2.pursdeleted−15
@@ -1,15 +0,0 @@
1−module M1 (bar) where
2−
3− foo :: Number
4− foo = 0
5−
6− bar :: Number
7− bar = foo
8−
9−module Main where
10−
11− import M1
12−
13− testBar = bar
14−
15− main = Debug.Trace.trace "Done"
examples/manual/passing/Import.pursdeleted−19
@@ -1,19 +0,0 @@
1−module M1 where
2−
3− import Prelude ()
4−
5− id :: forall a. a -> a
6− id = \x -> x
7−
8− foo = id
9−
10−module M2 where
11−
12− import Prelude ()
13− import M1
14−
15− main = \_ -> foo 42
16−
17−module Main where
18−
19−main = Debug.Trace.trace "Done"
examples/manual/passing/ImportExplicit.pursdeleted−14
@@ -1,14 +0,0 @@
1−module M1 where
2−
3− data X = X | Y
4− data Z = Z
5−
6−module Main where
7−
8− import M1 (X(..))
9−
10− testX :: X
11− testX = X
12− testY = Y
13−
14− main = Debug.Trace.trace "Done"
examples/manual/passing/ImportQualified.pursdeleted−12
@@ -1,12 +0,0 @@
1−module M1 where
2−
3− trace x = x
4−
5−module Main where
6−
7− import Prelude
8− import Control.Monad.Eff
9− import M1
10− import qualified Debug.Trace as T
11−
12− main = T.trace (trace "Done")
examples/manual/passing/Module.pursdeleted−28
@@ -1,28 +0,0 @@
1−module M1 where
2−
3− import Prelude
4−
5− data Foo = Foo String
6−
7− foo :: M1.Foo -> String
8− foo = \f -> case f of Foo s -> s ++ "foo"
9−
10− bar :: Foo -> String
11− bar = foo
12−
13− incr :: Number -> Number
14− incr x = x + 1
15−
16−module M2 where
17−
18− import Prelude
19−
20− baz :: M1.Foo -> String
21− baz = M1.foo
22−
23− match :: M1.Foo -> String
24− match = \f -> case f of M1.Foo s -> s ++ "foo"
25−
26−module Main where
27−
28−main = Debug.Trace.trace "Done"
examples/manual/passing/ModuleDeps.pursdeleted−17
@@ -1,17 +0,0 @@
1−module M1 where
2−
3−import M2
4−
5−foo = M3.baz
6−
7−module M2 where
8−
9−bar = M3.baz
10−
11−module M3 where
12−
13−baz = 1
14−
15−module Main where
16−
17−main = Debug.Trace.trace "Done"
examples/manual/passing/RedefinedFixity.pursdeleted−24
@@ -1,24 +0,0 @@
1−module M1 where
2−
3−import Prelude ()
4−
5−($) f a = f a
6−
7−infixr 1000 $
8−
9−module M2 where
10−
11−import Prelude ()
12−
13−import M1
14−
15−module M3 where
16−
17−import Prelude ()
18−
19−import M1
20−import M2
21−
22−module Main where
23−
24−main = Debug.Trace.trace "Done"
examples/passing/Applicative.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Main where
2−
3−import Prelude ()
4−
5−class Applicative f where
6− pure :: forall a. a -> f a
7− (<*>) :: forall a b. f (a -> b) -> f a -> f b
8−
9−data Maybe a = Nothing | Just a
10−
11−instance applicativeMaybe :: Applicative Maybe where
12− pure = Just
13− (<*>) (Just f) (Just a) = Just (f a)
14− (<*>) _ _ = Nothing
15−
16−main = Debug.Trace.trace "Done"
examples/passing/ArrayType.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3−class Pointed p where
4− point :: forall a. a -> p a
5−
6−instance pointedArray :: Pointed [] where
7− point a = [a]
8−
9−main = Debug.Trace.trace "Done"
examples/passing/Arrays.pursdeleted−24
@@ -1,24 +0,0 @@
1−module Main where
2−
3−import Prelude.Unsafe (unsafeIndex)
4−
5−test1 arr = arr `unsafeIndex` 0 + arr `unsafeIndex` 1 + 1
6−
7−test2 = \arr -> case arr of
8− [x, y] -> x + y
9− [x] -> x
10− [] -> 0
11− (x : y : _) -> x + y
12−
13−data Tree = One Number | Some [Tree]
14−
15−test3 = \tree sum -> case tree of
16− One n -> n
17− Some (n1 : n2 : rest) -> test3 n1 sum * 10 + test3 n2 sum * 5 + sum rest
18−
19−test4 = \arr -> case arr of
20− [] -> 0
21− [_] -> 0
22− x : y : xs -> x * y + test4 xs
23−
24−main = Debug.Trace.trace "Done"
examples/passing/Auto.pursdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3− data Auto s i o = Auto { state :: s, step :: s -> i -> o }
4−
5− type SomeAuto i o = forall r. (forall s. Auto s i o -> r) -> r
6−
7− exists :: forall s i o. s -> (s -> i -> o) -> SomeAuto i o
8− exists = \state step f -> f (Auto { state: state, step: step })
9−
10− run :: forall i o. SomeAuto i o -> i -> o
11− run = \s i -> s (\a -> case a of Auto a -> a.step a.state i)
12−
13− main = Debug.Trace.trace "Done"
examples/passing/AutoPrelude.pursdeleted−8
@@ -1,8 +0,0 @@
1−module Main where
2−
3−import Debug.Trace
4−
5−f x = x * 10
6−g y = y - 10
7−
8−main = trace $ show $ (f <<< g) 100
examples/passing/AutoPrelude2.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3−import qualified Prelude as P
4−import Debug.Trace
5−
6−f :: forall a. a -> a
7−f = P.id
8−
9−main = P.($) trace ((f P.<<< f) "Done")
examples/passing/BindersInFunctions.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−tail = \(_:xs) -> xs
6−
7−foreign import error
8− "function error(msg) {\
9− \ throw msg;\
10− \}" :: forall a. String -> a
11−
12−main =
13− let ts = tail [1, 2, 3] in
14− if ts == [2, 3]
15− then Debug.Trace.trace "Done"
16− else error "Incorrect result from 'tails'."
examples/passing/CheckSynonymBug.pursdeleted−14
@@ -1,14 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− type Foo a = [a]
6−
7− foreign import length
8− "function length(a) {\
9− \ return a.length;\
10− \}" :: forall a. [a] -> Number
11−
12− foo _ = length ([] :: Foo Number)
13−
14− main = Debug.Trace.trace "Done"
examples/passing/Church.pursdeleted−18
@@ -1,18 +0,0 @@
1−module Main where
2−
3− import Prelude ()
4−
5− type List a = forall r. r -> (a -> r -> r) -> r
6−
7− empty :: forall a. List a
8− empty = \r f -> r
9−
10− cons :: forall a. a -> List a -> List a
11− cons = \a l r f -> f a (l r f)
12−
13− append :: forall a. List a -> List a -> List a
14− append = \l1 l2 r f -> l2 (l1 r f) f
15−
16− test = append (cons 1 empty) (cons 2 empty)
17−
18− main = Debug.Trace.trace "Done"
examples/passing/Collatz.pursdeleted−18
@@ -1,18 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Control.Monad.ST
6−
7−collatz :: Number -> Number
8−collatz n = runPure (runST (do
9− r <- newSTRef n
10− count <- newSTRef 0
11− untilE $ do
12− modifySTRef count $ (+) 1
13− m <- readSTRef r
14− writeSTRef r $ if m % 2 == 0 then m / 2 else 3 * m + 1
15− return $ m == 1
16− readSTRef count))
17−
18−main = Debug.Trace.print $ collatz 1000
examples/passing/Conditional.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3− import Prelude ()
4−
5− fns = \f -> if f true then f else \x -> x
6−
7− not = \x -> if x then false else true
8−
9− main = Debug.Trace.trace "Done"
examples/passing/Console.pursdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Debug.Trace
6−
7−replicateM_ :: forall m a. (Monad m) => Number -> m a -> m {}
8−replicateM_ 0 _ = return {}
9−replicateM_ n act = do
10− act
11− replicateM_ (n - 1) act
12−
13−main = replicateM_ 10 (trace "Hello World!")
examples/passing/DataAndType.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Main where
2−
3−data A = A B
4−
5−type B = A
6−
7−main = Debug.Trace.trace "Done"
examples/passing/Do.pursdeleted−67
@@ -1,67 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−data Maybe a = Nothing | Just a
6−
7−instance functorMaybe :: Functor Maybe where
8− (<$>) f Nothing = Nothing
9− (<$>) f (Just x) = Just (f x)
10−
11−instance applyMaybe :: Apply Maybe where
12− (<*>) (Just f) (Just x) = Just (f x)
13− (<*>) _ _ = Nothing
14−
15−instance applicativeMaybe :: Applicative Maybe where
16− pure = Just
17−
18−instance bindMaybe :: Bind Maybe where
19− (>>=) Nothing _ = Nothing
20− (>>=) (Just a) f = f a
21−
22−instance monadMaybe :: Prelude.Monad Maybe
23−
24−test1 = \_ -> do
25− Just "abc"
26−
27−test2 = \_ -> do
28− (x : _) <- Just [1, 2, 3]
29− (y : _) <- Just [4, 5, 6]
30− Just (x + y)
31−
32−test3 = \_ -> do
33− Just 1
34− Nothing :: Maybe Number
35− Just 2
36−
37−test4 mx my = do
38− x <- mx
39− y <- my
40− Just (x + y + 1)
41−
42−test5 mx my mz = do
43− x <- mx
44− y <- my
45− let sum = x + y
46− z <- mz
47− Just (z + sum + 1)
48−
49−test6 mx = \_ -> do
50− let
51− f :: forall a. Maybe a -> a
52− f (Just x) = x
53− Just (f mx)
54−
55−test8 = \_ -> do
56− Just (do
57− Just 1)
58−
59−test9 = \_ -> (+) <$> Just 1 <*> Just 2
60−
61−test10 _ = do
62− let
63− f x = g x * 3
64− g x = f x / 2
65− Just (f 10)
66−
67−main = Debug.Trace.trace "Done"
examples/passing/Dollar.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Main where
2−
3−import Prelude ()
4−
5−($) :: forall a b. (a -> b) -> a -> b
6−($) f x = f x
7−
8−infixr 1000 $
9−
10−id x = x
11−
12−test1 x = id $ id $ id $ id $ x
13−
14−test2 x = id id $ id x
15−
16−main = Debug.Trace.trace "Done"
examples/passing/Eff.pursdeleted−19
@@ -1,19 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Control.Monad.ST
6−import Debug.Trace
7−
8−test1 = do
9− trace "Line 1"
10− trace "Line 2"
11−
12−test2 = runPure (runST (do
13− ref <- newSTRef 0
14− modifySTRef ref $ \n -> n + 1
15− readSTRef ref))
16−
17−main = do
18− test1
19− Debug.Trace.print test2
examples/passing/EmptyDataDecls.pursdeleted−30
@@ -1,30 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−data Z
6−data S n
7−
8−data ArrayBox n a = ArrayBox [a]
9−
10−nil :: forall a. ArrayBox Z a
11−nil = ArrayBox []
12−
13−foreign import concat
14− "function concat(l1) {\
15− \ return function (l2) {\
16− \ return l1.concat(l2);\
17− \ };\
18− \}" :: forall a. [a] -> [a] -> [a]
19−
20−cons' :: forall a n. a -> ArrayBox n a -> ArrayBox (S n) a
21−cons' x (ArrayBox xs) = ArrayBox $ concat [x] xs
22−
23−foreign import error
24− "function error(msg) {\
25− \ throw msg;\
26− \}" :: forall a. String -> a
27−
28−main = case cons' 1 $ cons' 2 $ cons' 3 nil of
29− ArrayBox [1, 2, 3] -> Debug.Trace.trace "Done"
30− _ -> error "Failed"
examples/passing/EmptyTypeClass.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−class Partial
6−
7−head :: forall a. (Partial) => [a] -> a
8−head (x:xs) = x
9−
10−instance allowPartials :: Partial
11−
12−main = Debug.Trace.trace $ head ["Done"]
examples/passing/EqOrd.pursdeleted−14
@@ -1,14 +0,0 @@
1−module Main where
2−
3−data Pair a b = Pair a b
4−
5−instance ordPair :: (Ord a, Ord b) => Ord (Pair a b) where
6− compare (Pair a1 b1) (Pair a2 b2) = case compare a1 a2 of
7− EQ -> compare b1 b2
8− r -> r
9−
10−instance eqPair :: (Eq a, Eq b) => Eq (Pair a b) where
11− (==) (Pair a1 b1) (Pair a2 b2) = a1 == a2 && b1 == b2
12− (/=) (Pair a1 b1) (Pair a2 b2) = a1 /= a2 || b1 /= b2
13−
14−main = Debug.Trace.print $ Pair 1 2 == Pair 1 2
examples/passing/ExternData.pursdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3− foreign import data IO :: * -> *
4−
5− foreign import bind "function bind() {}" :: forall a b. IO a -> (a -> IO b) -> IO b
6−
7− foreign import showMessage "function showMessage() {}" :: String -> IO { }
8−
9− foreign import prompt "function prompt() {}" :: IO String
10−
11− test _ = prompt `bind` \s -> showMessage s
12−
13− main = Debug.Trace.trace "Done"
examples/passing/ExternRaw.pursdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3−foreign import first "function first(xs) { return xs[0]; }" :: forall a. [a] -> a
4−
5−foreign import loop "function loop() { while (true) {} }" :: forall a. a
6−
7−foreign import concat "function concat(xs) { \
8− \ return function(ys) { \
9− \ return xs.concat(ys); \
10− \ };\
11− \}" :: forall a. [a] -> [a] -> [a]
12−
13−main = Debug.Trace.trace "Done"
examples/passing/FFI.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Main where
2−
3−foreign import foo
4− "function foo(s) {\
5− \ return s;\
6− \}" :: String -> String
7−
8−bar :: String -> String
9−bar _ = foo "test"
10−
11−main = Debug.Trace.trace "Done"
examples/passing/Fib.pursdeleted−15
@@ -1,15 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Control.Monad.ST
6−
7−main = runST (do
8− n1 <- newSTRef 1
9− n2 <- newSTRef 1
10− whileE ((>) 1000 <$> readSTRef n1) $ do
11− n1' <- readSTRef n1
12− n2' <- readSTRef n2
13− writeSTRef n2 $ n1' + n2'
14− writeSTRef n1 n2'
15− Debug.Trace.print n2')
examples/passing/FinalTagless.pursdeleted−22
@@ -1,22 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−class E e where
6− num :: Number -> e Number
7− add :: e Number -> e Number -> e Number
8−
9−type Expr a = forall e. (E e) => e a
10−
11−data Id a = Id a
12−
13−instance exprId :: E Id where
14− num = Id
15− add (Id n) (Id m) = Id (n + m)
16−
17−runId (Id a) = a
18−
19−three :: Expr Number
20−three = add (num 1) (num 2)
21−
22−main = Debug.Trace.print $ runId three
examples/passing/ForeignInstance.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Main where
2−
3−class Foo a where
4− foo :: a -> String
5−
6−foreign import instance fooArray :: (Foo a) => Foo [a]
7−
8−foreign import instance fooNumber :: Foo Number
9−
10−foreign import instance fooString :: Foo String
11−
12−test1 _ = foo [1, 2, 3]
13−
14−test2 _ = foo "Test"
15−
16−main = Debug.Trace.trace "Done"
examples/passing/FunctionScope.pursdeleted−17
@@ -1,17 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− mkValue :: Number -> Number
6− mkValue id = id
7−
8− foreign import error
9− "function error(msg) {\
10− \ throw msg;\
11− \}" :: forall a. String -> a
12−
13− main = do
14− let value = mkValue 1
15− if value == 1
16− then Debug.Trace.trace "Done"
17− else error "Not done"
examples/passing/Functions.pursdeleted−15
@@ -1,15 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− test1 = \_ -> 0
6−
7− test2 = \a b -> a + b + 1
8−
9− test3 = \a -> a
10−
11− test4 = \(%%) -> 1 %% 2
12−
13− test5 = \(+++) (***) -> 1 +++ 2 *** 3
14−
15− main = Debug.Trace.trace "Done"
examples/passing/Functions2.pursdeleted−17
@@ -1,17 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− test :: forall a b. a -> b -> a
6− test = \const _ -> const
7−
8− foreign import error
9− "function error(msg) {\
10− \ throw msg;\
11− \}" :: forall a. String -> a
12−
13− main = do
14− let value = test "Done" {}
15− if value == "Done"
16− then Debug.Trace.trace "Done"
17− else error "Not done"
examples/passing/Guards.pursdeleted−14
@@ -1,14 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− collatz = \x -> case x of
6− y | y % 2 == 0 -> y / 2
7− y -> y * 3 + 1
8−
9− -- Guards have access to current scope
10− collatz2 = \x y -> case x of
11− z | y > 0 -> z / 2
12− z -> z * 3 + 1
13−
14− main = Debug.Trace.trace "Done"
examples/passing/InferRecFunWithConstrainedArgument.pursdeleted−8
@@ -1,8 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−test 100 = 100
6−test n = test(1 + n)
7−
8−main = Debug.Trace.print $ test 0
examples/passing/JSReserved.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− yield = 0
6− member = 1
7−
8− public = \return -> return
9−
10− this catch = catch
11−
12− main = Debug.Trace.trace "Done"
examples/passing/Let.pursdeleted−64
@@ -1,64 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Control.Monad.ST
6−
7−test1 x = let
8− y :: Number
9− y = x + 1
10− in y
11−
12−test2 x y =
13− let x' = x + 1 in
14− let y' = y + 1 in
15− x' + y'
16−
17−test3 = let f x y z = x + y + z in
18− f 1 2 3
19−
20−test4 = let f x [y, z] = x y z in
21− f (+) [1, 2]
22−
23−test5 = let
24− f x | x > 0 = g (x / 2) + 1
25− f x = 0
26− g x = f (x - 1) + 1
27− in f 10
28−
29−test6 = runPure (runST (do
30− r <- newSTRef 0
31− (let
32− go [] = readSTRef r
33− go (n : ns) = do
34− modifySTRef r ((+) n)
35− go ns
36− in go [1, 2, 3, 4, 5])
37− ))
38−
39−test7 = let
40− f :: forall a. a -> a
41− f x = x
42− in if f true then f 1 else f 2
43−
44−test8 :: Number -> Number
45−test8 x = let
46− go y | (x - 0.1 < y * y) && (y * y < x + 0.1) = y
47− go y = go $ (y + x / y) / 2
48− in go x
49−
50−test10 _ =
51− let
52− f x = g x * 3
53− g x = f x / 2
54− in f 10
55−
56−main = do
57− Debug.Trace.print (test1 1)
58− Debug.Trace.print (test2 1 2)
59− Debug.Trace.print test3
60− Debug.Trace.print test4
61− Debug.Trace.print test5
62− Debug.Trace.print test6
63− Debug.Trace.print test7
64− Debug.Trace.print (test8 100)
examples/passing/LetInInstance.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3−class Foo a where
4− foo :: a -> String
5−
6−instance fooString :: Foo String where
7− foo = go
8− where
9− go :: String -> String
10− go s = s
11−
12−main = Debug.Trace.trace "Done"
examples/passing/LiberalTypeSynonyms.pursdeleted−19
@@ -1,19 +0,0 @@
1−module Main where
2−
3−type Reader = (->) String
4−
5−foo :: Reader String
6−foo s = s
7−
8−type AndFoo r = (foo :: String | r)
9−
10−getFoo :: forall r. Prim.Object (AndFoo r) -> String
11−getFoo o = o.foo
12−
13−type F r = { | r } -> { | r }
14−
15−f :: (forall r. F r) -> String
16−f g = case g { x: "Hello" } of
17− { x = x } -> x
18−
19−main = Debug.Trace.trace "Done"
examples/passing/MPTCs.pursdeleted−20
@@ -1,20 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−class NullaryTypeClass where
6− greeting :: String
7−
8−instance nullaryTypeClass :: NullaryTypeClass where
9− greeting = "Hello, World!"
10−
11−class Coerce a b where
12− coerce :: a -> b
13−
14−instance coerceRefl :: Coerce a a where
15− coerce a = a
16−
17−instance coerceShow :: (Prelude.Show a) => Coerce a String where
18− coerce = show
19−
20−main = Debug.Trace.trace "Done"
examples/passing/Match.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Main where
2−
3− data Foo a = Foo
4−
5− foo = \f -> case f of Foo -> "foo"
6−
7− main = Debug.Trace.trace "Done"
examples/passing/Monad.pursdeleted−32
@@ -1,32 +0,0 @@
1−module Main where
2−
3− import Prelude ()
4−
5− type Monad m = { return :: forall a. a -> m a
6− , bind :: forall a b. m a -> (a -> m b) -> m b }
7−
8− data Id a = Id a
9−
10− id :: Monad Id
11− id = { return : Id
12− , bind : \ma f -> case ma of Id a -> f a }
13−
14− data Maybe a = Nothing | Just a
15−
16− maybe :: Monad Maybe
17− maybe = { return : Just
18− , bind : \ma f -> case ma of
19− Nothing -> Nothing
20− Just a -> f a
21− }
22−
23− test :: forall m. Monad m -> m Number
24− test = \m -> m.bind (m.return 1) (\n1 ->
25− m.bind (m.return "Test") (\n2 ->
26− m.return n1))
27−
28− test1 = test id
29−
30− test2 = test maybe
31−
32− main = Debug.Trace.trace "Done"
examples/passing/MonadState.pursdeleted−48
@@ -1,48 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−data Tuple a b = Tuple a b
6−
7−class MonadState s m where
8− get :: m s
9− put :: s -> m {}
10−
11−data State s a = State (s -> Tuple s a)
12−
13−runState s (State f) = f s
14−
15−instance functorState :: Functor (State s) where
16− (<$>) = liftM1
17−
18−instance applyState :: Apply (State s) where
19− (<*>) = ap
20−
21−instance applicativeState :: Applicative (State s) where
22− pure a = State $ \s -> Tuple s a
23−
24−instance bindState :: Bind (State s) where
25− (>>=) f g = State $ \s -> case runState s f of
26− Tuple s1 a -> runState s1 (g a)
27−
28−instance monadState :: Monad (State s)
29−
30−instance monadStateState :: MonadState s (State s) where
31− get = State (\s -> Tuple s s)
32− put s = State (\_ -> Tuple s {})
33−
34−modify :: forall m s. (Prelude.Monad m, MonadState s m) => (s -> s) -> m {}
35−modify f = do
36− s <- get
37− put (f s)
38−
39−test :: Tuple String String
40−test = runState "" $ do
41− modify $ (++) "World!"
42− modify $ (++) "Hello, "
43− get
44−
45−main = do
46− let t1 = test
47− Debug.Trace.trace "Done"
48−
examples/passing/MultiArgFunctions.pursdeleted−14
@@ -1,14 +0,0 @@
1−module Main where
2−
3−import Data.Function
4−import Control.Monad.Eff
5−import Debug.Trace
6−
7−main = do
8− runFn0 (mkFn0 $ \_ -> trace $ show 0)
9− runFn1 (mkFn1 $ \a -> trace $ show a) 1
10− runFn2 (mkFn2 $ \a b -> trace $ show [a, b]) 1 2
11− runFn3 (mkFn3 $ \a b c -> trace $ show [a, b, c]) 1 2 3
12− runFn4 (mkFn4 $ \a b c d -> trace $ show [a, b, c, d]) 1 2 3 4
13− runFn5 (mkFn5 $ \a b c d e -> trace $ show [a, b, c, d, e]) 1 2 3 4 5
14− trace "Done!"
examples/passing/MultipleConstructorArgs.pursdeleted−21
@@ -1,21 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−
6−data P a b = P a b
7−
8−runP :: forall a b r. (a -> b -> r) -> P a b -> r
9−runP f (P a b) = f a b
10−
11−idP = runP P
12−
13−testCase = \p -> case p of
14− P (x:xs) (y:ys) -> x + y
15− P _ _ -> 0
16−
17−test1 = testCase (P [1, 2, 3] [4, 5, 6])
18−
19−main = do
20− Debug.Trace.trace (runP (\s n -> s ++ show n) (P "Test" 1))
21− Debug.Trace.print test1
examples/passing/MutRec.pursdeleted−19
@@ -1,19 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− f 0 = 0
6− f x = g x + 1
7−
8− g x = f (x / 2)
9−
10− data Even = Zero | Even Odd
11−
12− data Odd = Odd Even
13−
14− evenToNumber Zero = 0
15− evenToNumber (Even n) = oddToNumber n + 1
16−
17− oddToNumber (Odd n) = evenToNumber n + 1
18−
19− main = Debug.Trace.trace "Done"
examples/passing/NamedPatterns.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Main where
2−
3− foo = \x -> case x of
4− y@{ foo = "Foo" } -> y
5− y -> y
6−
7− main = Debug.Trace.trace "Done"
examples/passing/Nested.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Main where
2−
3− data Extend r a = Extend { prev :: r a, next :: a }
4−
5− data Matrix r a = Square (r (r a)) | Bigger (Matrix (Extend r) a)
6−
7− main = Debug.Trace.trace "Done"
examples/passing/NestedTypeSynonyms.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− type X = String
6− type Y = X -> X
7−
8− fn :: Y
9− fn a = a
10−
11− main = Debug.Trace.print (fn "Done")
examples/passing/ObjectSynonym.pursdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3−type Inner = Number
4−
5−inner :: Inner
6−inner = 0
7−
8−type Outer = { inner :: Inner }
9−
10−outer :: Outer
11−outer = { inner: inner }
12−
13−main = Debug.Trace.trace "Done"
examples/passing/ObjectUpdate.pursdeleted−18
@@ -1,18 +0,0 @@
1−module Main where
2−
3− update1 = \o -> o { foo = "Foo" }
4−
5− update2 :: forall r. { foo :: String | r } -> { foo :: String | r }
6− update2 = \o -> o { foo = "Foo" }
7−
8− replace = \o -> case o of
9− { foo = "Foo" } -> o { foo = "Bar" }
10− { foo = "Bar" } -> o { bar = "Baz" }
11− o -> o
12−
13− polyUpdate :: forall a r. { foo :: a | r } -> { foo :: String | r }
14− polyUpdate = \o -> o { foo = "Foo" }
15−
16− inferPolyUpdate = \o -> o { foo = "Foo" }
17−
18− main = Debug.Trace.trace ((update1 {foo: ""}).foo)
examples/passing/Objects.pursdeleted−30
@@ -1,30 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− test = \x -> x.foo + x.bar + 1
6−
7− append = \o -> { foo: o.foo, bar: 1 }
8−
9− apTest = append({foo : "Foo", baz: "Baz"})
10−
11− f = (\a -> a.b.c) { b: { c: 1, d: "Hello" }, e: "World" }
12−
13− g = (\a -> a.f { x: 1, y: "y" }) { f: \o -> o.x + 1 }
14−
15− typed :: { foo :: Number }
16− typed = { foo: 0 }
17−
18− test2 = \x -> x."!@#"
19−
20− test3 = typed."foo"
21−
22− test4 = test2 weirdObj
23− where
24− weirdObj :: { "!@#" :: Number }
25− weirdObj = { "!@#": 1 }
26−
27− test5 = case { "***": 1 } of
28− { "***" = n } -> n
29−
30− main = Debug.Trace.trace "Done"
examples/passing/OneConstructor.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Main where
2−
3−data One a = One a
4−
5−one (One a) = a
6−
7−main = Debug.Trace.trace "Done"
examples/passing/Operators.pursdeleted−80
@@ -1,80 +0,0 @@
1−module Main where
2−
3− import Control.Monad.Eff
4− import Debug.Trace
5−
6− (?!) :: forall a. a -> a -> a
7− (?!) x _ = x
8−
9− bar :: String -> String -> String
10− bar = \s1 s2 -> s1 ++ s2
11−
12− test1 :: forall n. (Num n) => n -> n -> (n -> n -> n) -> n
13− test1 x y z = x * y + z x y
14−
15− test2 = (\x -> x.foo false) { foo : \_ -> 1 }
16−
17− test3 = (\x y -> x)(1 + 2 * (1 + 2)) (true && (false || false))
18−
19− k = \x -> \y -> x
20−
21− test4 = 1 `k` 2
22−
23− infixl 5 %%
24−
25− (%%) :: Number -> Number -> Number
26− (%%) x y = x * y + y
27−
28− test5 = 1 %% 2 %% 3
29−
30− test6 = ((\x -> x) `k` 2) 3
31−
32− (<+>) :: String -> String -> String
33− (<+>) = \s1 s2 -> s1 ++ s2
34−
35− test7 = "Hello" <+> "World!"
36−
37− (@@) :: forall a b. (a -> b) -> a -> b
38− (@@) = \f x -> f x
39−
40− foo :: String -> String
41− foo = \s -> s
42−
43− test8 = foo @@ "Hello World"
44−
45− test9 = Main.foo @@ "Hello World"
46−
47− test10 = "Hello" `Main.bar` "World"
48−
49− (...) :: forall a. [a] -> [a] -> [a]
50− (...) = \as -> \bs -> as
51−
52− test11 = [1, 2, 3] ... [4, 5, 6]
53−
54− test12 (<%>) a b = a <%> b
55−
56− test13 = \(<%>) a b -> a <%> b
57−
58− test14 :: Number -> Number -> Boolean
59− test14 a b = a < b
60−
61− test15 :: Number -> Number -> Boolean
62− test15 a b = const false $ a `test14` b
63−
64− main = do
65− let t1 = test1 1 2 (\x y -> x + y)
66− let t2 = test2
67− let t3 = test3
68− let t4 = test4
69− let t5 = test5
70− let t6 = test6
71− let t7 = test7
72− let t8 = test8
73− let t9 = test9
74− let t10 = test10
75− let t11 = test11
76− let t12 = test12 k 1 2
77− let t13 = test13 k 1 2
78− let t14 = test14 1 2
79− let t15 = test15 1 2
80− trace "Done"
examples/passing/OptimizerBug.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−x a = 1 + y a
6−
7−y a = x a
8−
9−main = Debug.Trace.trace "Done"
examples/passing/Patterns.pursdeleted−28
@@ -1,28 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− test = \x -> case x of
6− { str = "Foo", bool = true } -> true
7− { str = "Bar", bool = b } -> b
8− _ -> false
9−
10− f = \o -> case o of
11− { foo = "Foo" } -> o.bar
12− _ -> 0
13−
14− g = \o -> case o of
15− { arr = [x : xs], take = "car" } -> x
16− { arr = [_, x : xs], take = "cadr" } -> x
17− _ -> 0
18−
19−
20− h = \o -> case o of
21− a@[_,_,_] -> a
22− _ -> []
23−
24− isDesc :: [Number] -> Boolean
25− isDesc [x, y] | x > y = true
26− isDesc _ = false
27−
28− main = Debug.Trace.trace "Done"
examples/passing/Person.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Main where
2−
3− import Prelude ((++))
4−
5− data Person = Person { name :: String, age :: Number }
6−
7− foreign import itoa
8− "function itoa(n) {\
9− \ return n.toString();\
10− \}" :: Number -> String
11−
12− showPerson :: Person -> String
13− showPerson = \p -> case p of
14− Person o -> o.name ++ ", aged " ++ itoa(o.age)
15−
16− main = Debug.Trace.trace "Done"
examples/passing/Rank2Data.pursdeleted−29
@@ -1,29 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− data Id = Id forall a. a -> a
6−
7− runId = \id a -> case id of
8− Id f -> f a
9−
10− data Nat = Nat forall r. r -> (r -> r) -> r
11−
12− runNat = \nat -> case nat of
13− Nat f -> f 0 (\n -> n + 1)
14−
15− zero = Nat (\zero _ -> zero)
16−
17− succ = \n -> case n of
18− Nat f -> Nat (\zero succ -> succ (f zero succ))
19−
20− add = \n m -> case n of
21− Nat f -> case m of
22− Nat g -> Nat (\zero succ -> g (f zero succ) succ)
23−
24− one = succ zero
25− two = succ zero
26− four = add two two
27− fourNumber = runNat four
28−
29− main = Debug.Trace.trace "Done"
examples/passing/Rank2Types.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− test1 :: (forall a. (a -> a)) -> Number
6− test1 = \f -> f 0
7−
8− forever :: forall m a b. (forall a b. m a -> (a -> m b) -> m b) -> m a -> m b
9− forever = \bind action -> bind action $ \_ -> forever bind action
10−
11− main = Debug.Trace.trace "Done"
examples/passing/Recursion.pursdeleted−10
@@ -1,10 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− fib = \n -> case n of
6− 0 -> 1
7− 1 -> 1
8− n -> fib (n - 1) + fib (n - 2)
9−
10− main = Debug.Trace.trace "Done"
examples/passing/RuntimeScopeIssue.pursdeleted−19
@@ -1,19 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−class A a where
6− a :: a -> Boolean
7−
8−class B a where
9− b :: a -> Boolean
10−
11−instance aNumber :: A Number where
12− a 0 = true
13− a n = b (n - 1)
14−
15−instance bNumber :: B Number where
16− b 0 = false
17− b n = a (n - 1)
18−
19−main = Debug.Trace.print $ a 10
examples/passing/STArray.pursdeleted−25
@@ -1,25 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Control.Monad.ST
6−import Debug.Trace
7−
8−test = runSTArray (do
9− a <- newSTArray 2 0
10− pokeSTArray a 0 1
11− pokeSTArray a 1 2
12− return a)
13−
14−fromTo lo hi = runSTArray (do
15− arr <- newSTArray (hi - lo + 1) 0
16− (let
17− go lo hi _ arr | lo > hi = return arr
18− go lo hi i arr = do
19− pokeSTArray arr i lo
20− go (lo + 1) hi (i + 1) arr
21− in go lo hi 0 arr))
22−
23−main = do
24− let t1 = runPure (fromTo 10 20)
25− trace "Done"
examples/passing/Sequence.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3−import Control.Monad.Eff
4−
5−class Sequence t where
6− sequence :: forall m a. (Monad m) => t (m a) -> m (t a)
7−
8−instance sequenceArray :: Sequence [] where
9− sequence [] = pure []
10− sequence (x:xs) = (:) <$> x <*> sequence xs
11−
12−main = sequence $ [Debug.Trace.trace "Done"]
examples/passing/SignedNumericLiterals.pursdeleted−15
@@ -1,15 +0,0 @@
1−module Main where
2−
3− p = 0.5
4− q = 1
5− x = -1
6− y = -0.5
7− z = 0.5
8− w = 1
9−
10− f :: Number -> Number
11− f x = -x
12−
13− test1 = 2 - 1
14−
15− main = Debug.Trace.trace "Done"
examples/passing/Superclasses1.pursdeleted−18
@@ -1,18 +0,0 @@
1−module Main where
2−
3−class Su a where
4− su :: a -> a
5−
6−class (Su a) <= Cl a where
7− cl :: a -> a -> a
8−
9−instance suNumber :: Su Number where
10− su n = n + 1
11−
12−instance clNumber :: Cl Number where
13− cl n m = n + m
14−
15−test :: forall a. (Cl a) => a -> a
16−test a = su (cl a a)
17−
18−main = Debug.Trace.print $ test 10
examples/passing/Superclasses2.pursdeleted−23
@@ -1,23 +0,0 @@
1−module Main where
2−
3−import Prelude.Unsafe (unsafeIndex)
4−
5−class Su a where
6− su :: a -> a
7−
8−class (Su [a]) <= Cl a where
9− cl :: a -> a -> a
10−
11−instance suNumber :: Su Number where
12− su n = n + 1
13−
14−instance suArray :: (Su a) => Su [a] where
15− su (x : _) = [su x]
16−
17−instance clNumber :: Cl Number where
18− cl n m = n + m
19−
20−test :: forall a. (Cl a) => a -> [a]
21−test x = su [cl x x]
22−
23−main = Debug.Trace.print $ test 10 `unsafeIndex` 0
examples/passing/Superclasses3.pursdeleted−41
@@ -1,41 +0,0 @@
1−module Main where
2−
3−import Debug.Trace
4−
5−import Control.Monad.Eff
6−
7−class (Monad m) <= MonadWriter w m where
8− tell :: w -> m Unit
9−
10−testFunctor :: forall m. (Monad m) => m Number -> m Number
11−testFunctor n = (+) 1 <$> n
12−
13−test :: forall w m. (Monad m, MonadWriter w m) => w -> m Unit
14−test w = do
15− tell w
16− tell w
17− tell w
18−
19−data MTrace a = MTrace (Eff (trace :: Trace) a)
20−
21−runMTrace :: forall a. MTrace a -> Eff (trace :: Trace) a
22−runMTrace (MTrace a) = a
23−
24−instance functorMTrace :: Functor MTrace where
25− (<$>) = liftM1
26−
27−instance applyMTrace :: Apply MTrace where
28− (<*>) = ap
29−
30−instance applicativeMTrace :: Applicative MTrace where
31− pure = MTrace <<< return
32−
33−instance bindMTrace :: Bind MTrace where
34− (>>=) m f = MTrace (runMTrace m >>= (runMTrace <<< f))
35−
36−instance monadMTrace :: Monad MTrace
37−
38−instance writerMTrace :: MonadWriter String MTrace where
39− tell s = MTrace (trace s)
40−
41−main = runMTrace $ test "Done"
examples/passing/TailCall.pursdeleted−15
@@ -1,15 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−test :: Number -> [Number] -> Number
6−test n [] = n
7−test n (x:xs) = test (n + x) xs
8−
9−loop :: forall a. Number -> a
10−loop x = loop (x + 1)
11−
12−notATailCall = \x ->
13− (\notATailCall -> notATailCall x) (\x -> x)
14−
15−main = Debug.Trace.print (test 0 [1, 2, 3])
examples/passing/Tick.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Main where
2−
3−test' x = x
4−
5−main = Debug.Trace.trace "Done"
examples/passing/TopLevelCase.pursdeleted−18
@@ -1,18 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− gcd :: Number -> Number -> Number
6− gcd 0 x = x
7− gcd x 0 = x
8− gcd x y | x > y = gcd (x % y) y
9− gcd x y = gcd (y % x) x
10−
11− guardsTest (x:xs) | x > 0 = guardsTest xs
12− guardsTest xs = xs
13−
14− data A = A
15−
16− parseTest A 0 = 0
17−
18− main = Debug.Trace.trace "Done"
examples/passing/TypeClasses.pursdeleted−69
@@ -1,69 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−test1 = \_ -> show "testing"
6−
7−f :: forall a. (Prelude.Show a) => a -> String
8−f x = show x
9−
10−test2 = \_ -> f "testing"
11−
12−test7 :: forall a. (Prelude.Show a) => a -> String
13−test7 = show
14−
15−test8 = \_ -> show $ "testing"
16−
17−data Data a = Data a
18−
19−instance showData :: (Prelude.Show a) => Prelude.Show (Data a) where
20− show (Data a) = "Data (" ++ show a ++ ")"
21−
22−test3 = \_ -> show (Data "testing")
23−
24−instance functorData :: Functor Data where
25− (<$>) = liftM1
26−
27−instance applyData :: Apply Data where
28− (<*>) = ap
29−
30−instance applicativeData :: Applicative Data where
31− pure = Data
32−
33−instance bindData :: Bind Data where
34− (>>=) (Data a) f = f a
35−
36−instance monadData :: Monad Data
37−
38−data Maybe a = Nothing | Just a
39−
40−instance functorMaybe :: Functor Maybe where
41− (<$>) = liftM1
42−
43−instance applyMaybe :: Apply Maybe where
44− (<*>) = ap
45−
46−instance applicativeMaybe :: Applicative Maybe where
47− pure = Just
48−
49−instance bindMaybe :: Bind Maybe where
50− (>>=) Nothing _ = Nothing
51− (>>=) (Just a) f = f a
52−
53−instance monadMaybe :: Monad Maybe
54−
55−test4 :: forall a m. (Monad m) => a -> m Number
56−test4 = \_ -> return 1
57−
58−test5 = \_ -> Just 1 >>= \n -> return (n + 1)
59−
60−ask r = r
61−
62−runReader r f = f r
63−
64−test9 _ = runReader 0 $ do
65− n <- ask
66− return $ n + 1
67−
68−main = Debug.Trace.trace (test7 "Done")
69−
examples/passing/TypeClassesInOrder.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Main where
2−
3−import Prelude
4−
5−class Foo a where
6− foo :: a -> String
7−
8−instance fooString :: Foo String where
9− foo s = s
10−
11−main = Debug.Trace.trace $ foo "Done"
examples/passing/TypeClassesWithOverlappingTypeVariables.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− data Either a b = Left a | Right b
6−
7− instance functorEither :: Prelude.Functor (Either a) where
8− (<$>) _ (Left x) = Left x
9− (<$>) f (Right y) = Right (f y)
10−
11− main = Debug.Trace.trace "Done"
examples/passing/TypeDecl.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3− import Prelude
4−
5− k :: String -> Number -> String
6− k x y = x
7−
8− iterate :: forall a. Number -> (a -> a) -> a -> a
9− iterate 0 f a = a
10− iterate n f a = iterate (n - 1) f (f a)
11−
12− main = Debug.Trace.trace "Done"
examples/passing/TypeSynonymInData.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3−type A a = [a]
4−
5−data Foo a = Foo (A a) | Bar
6−
7−foo (Foo []) = Bar
8−
9−main = Debug.Trace.trace "Done"
examples/passing/TypeSynonyms.pursdeleted−25
@@ -1,25 +0,0 @@
1−module Main where
2−
3− type Lens a b =
4− { get :: a -> b
5− , set :: a -> b -> a
6− }
7−
8− composeLenses :: forall a b c. Lens a b -> Lens b c -> Lens a c
9− composeLenses = \l1 -> \l2 ->
10− { get: \a -> l2.get (l1.get a)
11− , set: \a c -> l1.set a (l2.set (l1.get a) c)
12− }
13−
14− type Pair a b = { fst :: a, snd :: b }
15−
16− fst :: forall a b. Lens (Pair a b) a
17− fst =
18− { get: \p -> p.fst
19− , set: \p a -> { fst: a, snd: p.snd }
20− }
21−
22− test1 :: forall a b c. Lens (Pair (Pair a b) c) a
23− test1 = composeLenses fst fst
24−
25− main = Debug.Trace.trace "Done"
examples/passing/TypedWhere.pursdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3−data E a b = L a | R b
4−
5−lefts :: forall a b. [E a b] -> [a]
6−lefts = go []
7− where
8− go :: forall a b. [a] -> [E a b] -> [a]
9− go ls [] = ls
10− go ls (L a : rest) = go (a : ls) rest
11− go ls (_ : rest) = go ls rest
12−
13−main = Debug.Trace.trace "Done"
examples/passing/Unit.pursdeleted−6
@@ -1,6 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Debug.Trace
5−
6−main = print (const unit $ "Hello world")
examples/passing/UnknownInTypeClassLookup.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3−class EQ a b
4−
5−instance eqAA :: EQ a a
6−
7−test :: forall a b. (EQ a b) => a -> b -> String
8−test _ _ = "Done"
9−
10−runTest a = test a a
11−
12−main = Debug.Trace.trace $ runTest 0
examples/passing/Where.pursdeleted−49
@@ -1,49 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Control.Monad.Eff
5−import Control.Monad.ST
6−
7−test1 x = y
8− where
9− y :: Number
10− y = x + 1
11−
12−test2 x y = x' + y'
13− where
14− x' = x + 1
15− y' = y + 1
16−
17−
18−test3 = f 1 2 3
19− where f x y z = x + y + z
20−
21−
22−test4 = f (+) [1, 2]
23− where f x [y, z] = x y z
24−
25−
26−test5 = g 10
27− where
28− f x | x > 0 = g (x / 2) + 1
29− f x = 0
30− g x = f (x - 1) + 1
31−
32−test6 = if f true then f 1 else f 2
33− where f :: forall a. a -> a
34− f x = x
35−
36−test7 :: Number -> Number
37−test7 x = go x
38− where
39− go y | (x - 0.1 < y * y) && (y * y < x + 0.1) = y
40− go y = go $ (y + x / y) / 2
41−
42−main = do
43− Debug.Trace.print (test1 1)
44− Debug.Trace.print (test2 1 2)
45− Debug.Trace.print test3
46− Debug.Trace.print test4
47− Debug.Trace.print test5
48− Debug.Trace.print test6
49− Debug.Trace.print (test7 100)
examples/passing/iota.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Main where
2−
3− s = \x -> \y -> \z -> x z (y z)
4−
5− k = \x -> \y -> x
6−
7− iota = \x -> x s k
8−
9− main = Debug.Trace.trace "Done"
examples/passing/s.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Main where
2−
3− s = \x y z -> x z (y z)
4−
5− main = Debug.Trace.trace "Done"
hierarchy/Main.hsdeleted−103
@@ -1,103 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Main
4−-- Copyright : (c) Hardy Jones 2014
5−-- License : MIT
6−--
7−-- Maintainer : Hardy Jones <jones3.hardy@gmail.com>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Generate Directed Graphs of PureScript TypeClasses
13−--
14−-----------------------------------------------------------------------------
15−
16−module Main where
17−
18−import Control.Applicative ((<*>), (<$>))
19−import Control.Monad (unless)
20−
21−import Data.List (intercalate,nub,sort)
22−import Data.Foldable (for_)
23−import Data.Version (showVersion)
24−
25−import System.Console.CmdTheLine
26−import System.Directory (createDirectoryIfMissing)
27−import System.FilePath ((</>))
28−import System.Exit (exitFailure, exitSuccess)
29−
30−import Text.Parsec (ParseError)
31−
32−import qualified Language.PureScript as P
33−import qualified Paths_purescript as Paths
34−import qualified System.IO.UTF8 as U
35−
36−newtype SuperMap = SuperMap { unSuperMap :: Either P.ProperName (P.ProperName, P.ProperName) }
37− deriving Eq
38−
39−instance Show SuperMap where
40− show (SuperMap (Left sub)) = show sub
41− show (SuperMap (Right (super, sub))) = show super ++ " -> " ++ show sub
42−
43−instance Ord SuperMap where
44− compare (SuperMap s) (SuperMap s') = getCls s `compare` getCls s'
45− where
46− getCls = either id snd
47−
48−runModuleName :: P.ModuleName -> String
49−runModuleName (P.ModuleName pns) = intercalate "_" (P.runProperName `map` pns)
50−
51−readInput :: FilePath -> IO (Either ParseError [P.Module])
52−readInput p = do
53− text <- U.readFile p
54− return $ P.runIndentParser p P.parseModules text
55−
56−compile :: FilePath -> Maybe FilePath -> IO ()
57−compile input mOutput = do
58− modules <- readInput input
59− case modules of
60− Left err -> U.print err >> exitFailure
61− Right ms -> do
62− for_ ms $ \(P.Module moduleName decls _) ->
63− let name = runModuleName moduleName
64− tcs = filter P.isTypeClassDeclaration decls
65− supers = sort . nub . filter (not . null) $ fmap superClasses tcs
66− prologue = "digraph " ++ name ++ " {\n"
67− body = intercalate "\n" (concatMap (fmap (\s -> " " ++ show s ++ ";")) supers)
68− epilogue = "\n}"
69− hier = prologue ++ body ++ epilogue
70− in unless (null supers) $ case mOutput of
71− Just output -> do
72− createDirectoryIfMissing True output
73− U.writeFile (output </> name) hier
74− Nothing -> U.putStrLn hier
75− exitSuccess
76−
77−superClasses :: P.Declaration -> [SuperMap]
78−superClasses (P.TypeClassDeclaration sub _ supers@(_:_) _) =
79− fmap (\(P.Qualified _ super, _) -> SuperMap (Right (super, sub))) supers
80−superClasses (P.TypeClassDeclaration sub _ _ _) = [SuperMap (Left sub)]
81−superClasses (P.PositionedDeclaration _ decl) = superClasses decl
82−superClasses _ = []
83−
84−outputFile :: Term (Maybe FilePath)
85−outputFile = value $ opt Nothing $ (optInfo [ "o", "output" ])
86− { optDoc = "The output directory" }
87−
88−inputFile :: Term FilePath
89−inputFile = value $ pos 0 "main.purs" $ posInfo
90− { posDoc = "The input file to generate a hierarchy from" }
91−
92−term :: Term (IO ())
93−term = compile <$> inputFile <*> outputFile
94−
95−termInfo :: TermInfo
96−termInfo = defTI
97− { termName = "hierarchy"
98− , version = showVersion Paths.version
99− , termDoc = "Creates a GraphViz directed graph of PureScript TypeClasses"
100− }
101−
102−main :: IO ()
103−main = run (term, termInfo)
package.yamlnew file+86
@@ -0,0 +1,86 @@
1+name: psgo
2+version: 0.1.0.0
3+github: "andyarvanitis/purescript-native"
4+license: BSD3
5+author: "Andy Arvanitis"
6+maintainer: "example@example.com"
7+copyright: "2018 Andy Arvanitis"
8+
9+extra-source-files:
10+- README.md
11+- ChangeLog.md
12+- stack.yaml
13+- support/*
14+
15+# Metadata used when publishing your package
16+# synopsis: Short description of your package
17+# category: Web
18+
19+# To avoid duplicated efforts in documentation and dealing with the
20+# complications of embedding Haddock markup inside cabal files, it is
21+# common to point users to the README.md file.
22+description: Please see the README on Github at <https://github.com/andyarvanitis/purescript-native#readme>
23+
24+dependencies:
25+- base >= 4.7 && < 5
26+- bytestring >= 0.10.8.2 && < 0.11
27+- purescript
28+- base-compat >=0.6.0
29+- protolude >=0.1.6
30+- text
31+- containers
32+- filepath
33+- monad-parallel >= 0.7.2.2 && <0.8
34+- pattern-arrows >=0.0.2 && <0.1
35+- safe >=0.3.9 && <0.4
36+- transformers >=0.3.0 && <0.6
37+- mtl >=2.1.0 && <2.3.0
38+- aeson >=1.0 && <1.5
39+- directory
40+- process
41+- file-embed
42+- filemanip
43+- gitrev
44+
45+library:
46+ source-dirs: src
47+ default-extensions:
48+ - ConstraintKinds
49+ - DataKinds
50+ - DeriveFunctor
51+ - EmptyDataDecls
52+ - FlexibleContexts
53+ - KindSignatures
54+ - LambdaCase
55+ - MultiParamTypeClasses
56+ - NoImplicitPrelude
57+ - PatternGuards
58+ - PatternSynonyms
59+ - RankNTypes
60+ - RecordWildCards
61+ - OverloadedStrings
62+ - ScopedTypeVariables
63+ - TupleSections
64+ - ViewPatterns
65+
66+executables:
67+ psgo:
68+ main: Main.hs
69+ source-dirs: app
70+ ghc-options:
71+ - -threaded
72+ - -rtsopts
73+ - -with-rtsopts=-N
74+ dependencies:
75+ - psgo
76+
77+tests:
78+ psgo-test:
79+ main: Spec.hs
80+ source-dirs: test
81+ ghc-options:
82+ - -threaded
83+ - -rtsopts
84+ - -with-rtsopts=-N
85+ dependencies:
86+ - psgo
prelude/README.mddeleted−321
@@ -1,321 +0,0 @@
1−# Module Documentation
2−
3−## Module Prelude
4−
5−### Types
6−
7− data Ordering where
8− LT :: Ordering
9− GT :: Ordering
10− EQ :: Ordering
11−
12−
13−### Type Classes
14−
15−![Prelude](images/Prelude.png)
16−
17− class Alternative f where
18− empty :: forall a. f a
19− (<|>) :: forall a. f a -> f a -> f a
20−
21− class (Apply f) <= Applicative f where
22− pure :: forall a. a -> f a
23−
24− class (Functor f) <= Apply f where
25− (<*>) :: forall a b. f (a -> b) -> f a -> f b
26−
27− class (Apply m) <= Bind m where
28− (>>=) :: forall a b. m a -> (a -> m b) -> m b
29−
30− class Bits b where
31− (&) :: b -> b -> b
32− (|) :: b -> b -> b
33− (^) :: b -> b -> b
34− shl :: b -> Prim.Number -> b
35− shr :: b -> Prim.Number -> b
36− zshr :: b -> Prim.Number -> b
37− complement :: b -> b
38−
39− class BoolLike b where
40− (&&) :: b -> b -> b
41− (||) :: b -> b -> b
42− not :: b -> b
43−
44− class (Semigroupoid a) <= Category a where
45− id :: forall t. a t t
46−
47− class Eq a where
48− (==) :: a -> a -> Prim.Boolean
49− (/=) :: a -> a -> Prim.Boolean
50−
51− class Functor f where
52− (<$>) :: forall a b. (a -> b) -> f a -> f b
53−
54− class (Applicative m, Bind m) <= Monad m where
55−
56− class Num a where
57− (+) :: a -> a -> a
58− (-) :: a -> a -> a
59− (*) :: a -> a -> a
60− (/) :: a -> a -> a
61− (%) :: a -> a -> a
62− negate :: a -> a
63−
64− class (Eq a) <= Ord a where
65− compare :: a -> a -> Ordering
66−
67− class Semigroup a where
68− (<>) :: a -> a -> a
69−
70− class Semigroupoid a where
71− (<<<) :: forall b c d. a c d -> a b c -> a b d
72−
73− class Show a where
74− show :: a -> Prim.String
75−
76−
77−### Type Class Instances
78−
79− instance bitsNumber :: Bits Prim.Number
80−
81− instance boolLikeBoolean :: BoolLike Prim.Boolean
82−
83− instance categoryArr :: Category Prim.Function
84−
85− instance eqArray :: (Eq a) => Eq [a]
86−
87− instance eqBoolean :: Eq Prim.Boolean
88−
89− instance eqNumber :: Eq Prim.Number
90−
91− instance eqOrdering :: Eq Ordering
92−
93− instance eqString :: Eq Prim.String
94−
95− instance numNumber :: Num Prim.Number
96−
97− instance ordNumber :: Ord Prim.Number
98−
99− instance semigroupString :: Semigroup Prim.String
100−
101− instance semigroupoidArr :: Semigroupoid Prim.Function
102−
103− instance showArray :: (Show a) => Show [a]
104−
105− instance showBoolean :: Show Prim.Boolean
106−
107− instance showNumber :: Show Prim.Number
108−
109− instance showOrdering :: Show Ordering
110−
111− instance showString :: Show Prim.String
112−
113−
114−### Values
115−
116− (#) :: forall a b. a -> (a -> b) -> b
117−
118− ($) :: forall a b. (a -> b) -> a -> b
119−
120− (++) :: forall s. (Semigroup s) => s -> s -> s
121−
122− (:) :: forall a. a -> [a] -> [a]
123−
124− (<) :: forall a. (Ord a) => a -> a -> Prim.Boolean
125−
126− (<=) :: forall a. (Ord a) => a -> a -> Prim.Boolean
127−
128− (>) :: forall a. (Ord a) => a -> a -> Prim.Boolean
129−
130− (>=) :: forall a. (Ord a) => a -> a -> Prim.Boolean
131−
132− (>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d
133−
134− ap :: forall m a b. (Monad m) => m (a -> b) -> m a -> m b
135−
136− asTypeOf :: forall a. a -> a -> a
137−
138− boolAnd :: Prim.Boolean -> Prim.Boolean -> Prim.Boolean
139−
140− boolNot :: Prim.Boolean -> Prim.Boolean
141−
142− boolOr :: Prim.Boolean -> Prim.Boolean -> Prim.Boolean
143−
144− concatString :: Prim.String -> Prim.String -> Prim.String
145−
146− cons :: forall a. a -> [a] -> [a]
147−
148− const :: forall a b. a -> b -> a
149−
150− flip :: forall a b c. (a -> b -> c) -> b -> a -> c
151−
152− liftA1 :: forall f a b. (Applicative f) => (a -> b) -> f a -> f b
153−
154− liftM1 :: forall m a b. (Monad m) => (a -> b) -> m a -> m b
155−
156− numAdd :: Prim.Number -> Prim.Number -> Prim.Number
157−
158− numAnd :: Prim.Number -> Prim.Number -> Prim.Number
159−
160− numCompare :: Prim.Number -> Prim.Number -> Ordering
161−
162− numComplement :: Prim.Number -> Prim.Number
163−
164− numDiv :: Prim.Number -> Prim.Number -> Prim.Number
165−
166− numMod :: Prim.Number -> Prim.Number -> Prim.Number
167−
168− numMul :: Prim.Number -> Prim.Number -> Prim.Number
169−
170− numNegate :: Prim.Number -> Prim.Number
171−
172− numOr :: Prim.Number -> Prim.Number -> Prim.Number
173−
174− numShl :: Prim.Number -> Prim.Number -> Prim.Number
175−
176− numShr :: Prim.Number -> Prim.Number -> Prim.Number
177−
178− numSub :: Prim.Number -> Prim.Number -> Prim.Number
179−
180− numXor :: Prim.Number -> Prim.Number -> Prim.Number
181−
182− numZshr :: Prim.Number -> Prim.Number -> Prim.Number
183−
184− refEq :: forall a. a -> a -> Prim.Boolean
185−
186− refIneq :: forall a. a -> a -> Prim.Boolean
187−
188− return :: forall m a. (Monad m) => a -> m a
189−
190− showArrayImpl :: forall a. (a -> Prim.String) -> [a] -> Prim.String
191−
192− showNumberImpl :: Prim.Number -> Prim.String
193−
194− showStringImpl :: Prim.String -> Prim.String
195−
196−
197−## Module Data.Function
198−
199−### Values
200−
201− on :: forall a b c. (b -> b -> c) -> (a -> b) -> a -> a -> c
202−
203−
204−## Module Data.Eq
205−
206−### Types
207−
208− data Ref a where
209− Ref :: a -> Ref a
210−
211−
212−### Type Class Instances
213−
214− instance eqRef :: Eq (Ref a)
215−
216−
217−### Values
218−
219− liftRef :: forall a b. (a -> a -> b) -> Ref a -> Ref a -> b
220−
221−
222−## Module Prelude.Unsafe
223−
224−### Values
225−
226− unsafeIndex :: forall a. [a] -> Prim.Number -> a
227−
228−
229−## Module Control.Monad.Eff
230−
231−### Types
232−
233− data Eff :: # ! -> * -> *
234−
235− type Pure a = forall e. Eff e a
236−
237−
238−### Type Class Instances
239−
240− instance applicativeEff :: Applicative (Eff e)
241−
242− instance applyEff :: Apply (Eff e)
243−
244− instance bindEff :: Bind (Eff e)
245−
246− instance functorEff :: Functor (Eff e)
247−
248− instance monadEff :: Monad (Eff e)
249−
250−
251−### Values
252−
253− bindE :: forall e a b. Eff e a -> (a -> Eff e b) -> Eff e b
254−
255− forE :: forall e. Prim.Number -> Prim.Number -> (Prim.Number -> Eff e { }) -> Eff e { }
256−
257− foreachE :: forall e a. [a] -> (a -> Eff e { }) -> Eff e { }
258−
259− returnE :: forall e a. a -> Eff e a
260−
261− runPure :: forall a. Pure a -> a
262−
263− untilE :: forall e. Eff e Prim.Boolean -> Eff e { }
264−
265− whileE :: forall e a. Eff e Prim.Boolean -> Eff e a -> Eff e { }
266−
267−
268−## Module Control.Monad.Eff.Unsafe
269−
270−### Values
271−
272− unsafeInterleaveEff :: forall eff1 eff2 a. Eff eff1 a -> Eff eff2 a
273−
274−
275−## Module Debug.Trace
276−
277−### Types
278−
279− data Trace :: !
280−
281−
282−### Values
283−
284− print :: forall a r. (Show a) => a -> Eff (trace :: Trace | r) { }
285−
286− trace :: forall r. Prim.String -> Eff (trace :: Trace | r) { }
287−
288−
289−## Module Control.Monad.ST
290−
291−### Types
292−
293− data ST :: * -> !
294−
295− data STArray :: * -> * -> *
296−
297− data STRef :: * -> * -> *
298−
299−
300−### Values
301−
302− modifySTRef :: forall a h r. STRef h a -> (a -> a) -> Eff (st :: ST h | r) a
303−
304− newSTArray :: forall a h r. Prim.Number -> a -> Eff (st :: ST h | r) (STArray h a)
305−
306− newSTRef :: forall a h r. a -> Eff (st :: ST h | r) (STRef h a)
307−
308− peekSTArray :: forall a h r. STArray h a -> Eff (st :: ST h | r) a
309−
310− pokeSTArray :: forall a h r. STArray h a -> Prim.Number -> a -> Eff (st :: ST h | r) a
311−
312− readSTRef :: forall a h r. STRef h a -> Eff (st :: ST h | r) a
313−
314− runST :: forall a r. (forall h. Eff (st :: ST h | r) a) -> Eff r a
315−
316− runSTArray :: forall a r. (forall h. Eff (st :: ST h | r) (STArray h a)) -> Eff r [a]
317−
318− writeSTRef :: forall a h r. STRef h a -> a -> Eff (st :: ST h | r) a
319−
320−
321−
prelude/images/Prelude.pngdeleted

Binary file not shown.

prelude/prelude.pursdeleted−797
@@ -1,797 +0,0 @@
1−module Prelude
2− ( flip
3− , const
4− , asTypeOf
5− , Semigroupoid, (<<<), (>>>)
6− , Category, id
7− , ($), (#)
8− , (:), cons
9− , Show, show
10− , Functor, (<$>), void
11− , Apply, (<*>)
12− , Applicative, pure, liftA1
13− , Alternative, empty, (<|>)
14− , Bind, (>>=)
15− , Monad, return, liftM1, ap
16− , Num, (+), (-), (*), (/), (%)
17− , negate
18− , Eq, (==), (/=), refEq, refIneq
19− , Ord, Ordering(..), compare, (<), (>), (<=), (>=)
20− , Bits, (&), (|), (^), shl, shr, zshr, complement
21− , BoolLike, (&&), (||)
22− , not
23− , Semigroup, (<>), (++)
24− , Unit(..), unit
25− ) where
26−
27− flip :: forall a b c. (a -> b -> c) -> b -> a -> c
28− flip f b a = f a b
29−
30− const :: forall a b. a -> b -> a
31− const a _ = a
32−
33− asTypeOf :: forall a. a -> a -> a
34− asTypeOf x _ = x
35−
36− infixr 9 >>>
37− infixr 9 <<<
38−
39− class Semigroupoid a where
40− (<<<) :: forall b c d. a c d -> a b c -> a b d
41−
42− instance semigroupoidArr :: Semigroupoid (->) where
43− (<<<) f g x = f (g x)
44−
45− (>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d
46− (>>>) f g = g <<< f
47−
48− class (Semigroupoid a) <= Category a where
49− id :: forall t. a t t
50−
51− instance categoryArr :: Category (->) where
52− id x = x
53−
54− infixr 0 $
55− infixl 0 #
56−
57− ($) :: forall a b. (a -> b) -> a -> b
58− ($) f x = f x
59−
60− (#) :: forall a b. a -> (a -> b) -> b
61− (#) x f = f x
62−
63− infixr 6 :
64−
65− (:) :: forall a. a -> [a] -> [a]
66− (:) = cons
67−
68− foreign import cons
69− "function cons(e) {\
70− \ return function (l) {\
71− \ return [e].concat(l);\
72− \ };\
73− \}" :: forall a. a -> [a] -> [a]
74−
75− class Show a where
76− show :: a -> String
77−
78− foreign import showStringImpl
79− "function showStringImpl(s) {\
80− \ return JSON.stringify(s);\
81− \}" :: String -> String
82−
83− instance showUnit :: Show Unit where
84− show (Unit {}) = "Unit {}"
85−
86− instance showString :: Show String where
87− show = showStringImpl
88−
89− instance showBoolean :: Show Boolean where
90− show true = "true"
91− show false = "false"
92−
93− foreign import showNumberImpl "function showNumberImpl(n) {\
94− \ return n.toString();\
95− \}" :: Number -> String
96−
97− instance showNumber :: Show Number where
98− show = showNumberImpl
99−
100− foreign import showArrayImpl
101− "function showArrayImpl (f) {\
102− \ return function (xs) {\
103− \ var ss = [];\
104− \ for (var i = 0, l = xs.length; i < l; i++) {\
105− \ ss[i] = f(xs[i]);\
106− \ }\
107− \ return '[' + ss.join(',') + ']';\
108− \ };\
109− \}" :: forall a. (a -> String) -> [a] -> String
110−
111− instance showArray :: (Show a) => Show [a] where
112− show = showArrayImpl show
113−
114− infixl 4 <$>
115−
116− class Functor f where
117− (<$>) :: forall a b. (a -> b) -> f a -> f b
118−
119− void :: forall f a. (Functor f) => f a -> f Unit
120− void fa = const unit <$> fa
121−
122− infixl 4 <*>
123−
124− class (Functor f) <= Apply f where
125− (<*>) :: forall a b. f (a -> b) -> f a -> f b
126−
127− class (Apply f) <= Applicative f where
128− pure :: forall a. a -> f a
129−
130− liftA1 :: forall f a b. (Applicative f) => (a -> b) -> f a -> f b
131− liftA1 f a = pure f <*> a
132−
133− infixl 3 <|>
134−
135− class Alternative f where
136− empty :: forall a. f a
137− (<|>) :: forall a. f a -> f a -> f a
138−
139− infixl 1 >>=
140−
141− class (Apply m) <= Bind m where
142− (>>=) :: forall a b. m a -> (a -> m b) -> m b
143−
144− class (Applicative m, Bind m) <= Monad m
145−
146− return :: forall m a. (Monad m) => a -> m a
147− return = pure
148−
149− liftM1 :: forall m a b. (Monad m) => (a -> b) -> m a -> m b
150− liftM1 f a = do
151− a' <- a
152− return (f a')
153−
154− ap :: forall m a b. (Monad m) => m (a -> b) -> m a -> m b
155− ap f a = do
156− f' <- f
157− a' <- a
158− return (f' a')
159−
160− instance functorArr :: Functor ((->) r) where
161− (<$>) = (<<<)
162−
163− instance applyArr :: Apply ((->) r) where
164− (<*>) f g x = f x (g x)
165−
166− instance applicativeArr :: Applicative ((->) r) where
167− pure = const
168−
169− instance bindArr :: Bind ((->) r) where
170− (>>=) m f x = f (m x) x
171−
172− instance monadArr :: Monad ((->) r)
173−
174− infixl 7 *
175− infixl 7 /
176− infixl 7 %
177−
178− infixl 6 -
179− infixl 6 +
180−
181− class Num a where
182− (+) :: a -> a -> a
183− (-) :: a -> a -> a
184− (*) :: a -> a -> a
185− (/) :: a -> a -> a
186− (%) :: a -> a -> a
187− negate :: a -> a
188−
189− foreign import numAdd "function numAdd(n1) {\
190− \ return function(n2) {\
191− \ return n1 + n2;\
192− \ };\
193− \}" :: Number -> Number -> Number
194−
195− foreign import numSub "function numSub(n1) {\
196− \ return function(n2) {\
197− \ return n1 - n2;\
198− \ };\
199− \}" :: Number -> Number -> Number
200−
201− foreign import numMul "function numMul(n1) {\
202− \ return function(n2) {\
203− \ return n1 * n2;\
204− \ };\
205− \}" :: Number -> Number -> Number
206−
207− foreign import numDiv "function numDiv(n1) {\
208− \ return function(n2) {\
209− \ return n1 / n2;\
210− \ };\
211− \}" :: Number -> Number -> Number
212−
213− foreign import numMod "function numMod(n1) {\
214− \ return function(n2) {\
215− \ return n1 % n2;\
216− \ };\
217− \}" :: Number -> Number -> Number
218−
219− foreign import numNegate "function numNegate(n) {\
220− \ return -n;\
221− \}" :: Number -> Number
222−
223− instance numNumber :: Num Number where
224− (+) = numAdd
225− (-) = numSub
226− (*) = numMul
227− (/) = numDiv
228− (%) = numMod
229− negate = numNegate
230−
231− data Unit = Unit {}
232−
233− unit :: Unit
234− unit = Unit {}
235−
236− infix 4 ==
237− infix 4 /=
238−
239− class Eq a where
240− (==) :: a -> a -> Boolean
241− (/=) :: a -> a -> Boolean
242−
243− foreign import refEq
244− "function refEq(r1) {\
245− \ return function(r2) {\
246− \ return r1 === r2;\
247− \ };\
248− \}" :: forall a. a -> a -> Boolean
249−
250− foreign import refIneq
251− "function refIneq(r1) {\
252− \ return function(r2) {\
253− \ return r1 !== r2;\
254− \ };\
255− \}" :: forall a. a -> a -> Boolean
256−
257− instance eqUnit :: Eq Unit where
258− (==) (Unit {}) (Unit {}) = true
259− (/=) (Unit {}) (Unit {}) = false
260−
261− instance eqString :: Eq String where
262− (==) = refEq
263− (/=) = refIneq
264−
265− instance eqNumber :: Eq Number where
266− (==) = refEq
267− (/=) = refIneq
268−
269− instance eqBoolean :: Eq Boolean where
270− (==) = refEq
271− (/=) = refIneq
272−
273− foreign import eqArrayImpl
274− "function eqArrayImpl(f) {\
275− \ return function(xs) {\
276− \ return function(ys) {\
277− \ if (xs.length !== ys.length) return false;\
278− \ for (var i = 0; i < xs.length; i++) {\
279− \ if (!f(xs[i])(ys[i])) return false;\
280− \ }\
281− \ return true;\
282− \ };\
283− \ };\
284− \}" :: forall a. (a -> a -> Boolean) -> [a] -> [a] -> Boolean
285−
286− instance eqArray :: (Eq a) => Eq [a] where
287− (==) xs ys = eqArrayImpl (==) xs ys
288− (/=) xs ys = not (xs == ys)
289−
290− data Ordering = LT | GT | EQ
291−
292− instance eqOrdering :: Eq Ordering where
293− (==) LT LT = true
294− (==) GT GT = true
295− (==) EQ EQ = true
296− (==) _ _ = false
297− (/=) x y = not (x == y)
298−
299− instance showOrdering :: Show Ordering where
300− show LT = "LT"
301− show GT = "GT"
302− show EQ = "EQ"
303−
304− class (Eq a) <= Ord a where
305− compare :: a -> a -> Ordering
306−
307− infixl 4 <
308−
309− (<) :: forall a. (Ord a) => a -> a -> Boolean
310− (<) a1 a2 = case a1 `compare` a2 of
311− LT -> true
312− _ -> false
313−
314− infixl 4 >
315−
316− (>) :: forall a. (Ord a) => a -> a -> Boolean
317− (>) a1 a2 = case a1 `compare` a2 of
318− GT -> true
319− _ -> false
320−
321− infixl 4 <=
322−
323− (<=) :: forall a. (Ord a) => a -> a -> Boolean
324− (<=) a1 a2 = case a1 `compare` a2 of
325− GT -> false
326− _ -> true
327−
328− infixl 4 >=
329−
330− (>=) :: forall a. (Ord a) => a -> a -> Boolean
331− (>=) a1 a2 = case a1 `compare` a2 of
332− LT -> false
333− _ -> true
334−
335− foreign import unsafeCompare
336− "function unsafeCompare(n1) {\
337− \ return function(n2) {\
338− \ return n1 < n2 ? LT : n1 > n2 ? GT : EQ;\
339− \ };\
340− \}" :: forall a. a -> a -> Ordering
341−
342− instance ordUnit :: Ord Unit where
343− compare (Unit {}) (Unit {}) = EQ
344−
345− instance ordBoolean :: Ord Boolean where
346− compare false false = EQ
347− compare false true = LT
348− compare true true = EQ
349− compare true false = GT
350−
351− instance ordNumber :: Ord Number where
352− compare = unsafeCompare
353−
354− instance ordString :: Ord String where
355− compare = unsafeCompare
356−
357− instance ordArray :: (Ord a) => Ord [a] where
358− compare [] [] = EQ
359− compare [] _ = LT
360− compare _ [] = GT
361− compare (x:xs) (y:ys) = case compare x y of
362− EQ -> compare xs ys
363− other -> other
364−
365− infixl 10 &
366− infixl 10 |
367− infixl 10 ^
368−
369− class Bits b where
370− (&) :: b -> b -> b
371− (|) :: b -> b -> b
372− (^) :: b -> b -> b
373− shl :: b -> Number -> b
374− shr :: b -> Number -> b
375− zshr :: b -> Number -> b
376− complement :: b -> b
377−
378− foreign import numShl "function numShl(n1) {\
379− \ return function(n2) {\
380− \ return n1 << n2;\
381− \ };\
382− \}" :: Number -> Number -> Number
383−
384− foreign import numShr "function numShr(n1) {\
385− \ return function(n2) {\
386− \ return n1 >> n2;\
387− \ };\
388− \}" :: Number -> Number -> Number
389−
390− foreign import numZshr "function numZshr(n1) {\
391− \ return function(n2) {\
392− \ return n1 >>> n2;\
393− \ };\
394− \}" :: Number -> Number -> Number
395−
396− foreign import numAnd "function numAnd(n1) {\
397− \ return function(n2) {\
398− \ return n1 & n2;\
399− \ };\
400− \}" :: Number -> Number -> Number
401−
402− foreign import numOr "function numOr(n1) {\
403− \ return function(n2) {\
404− \ return n1 | n2;\
405− \ };\
406− \}" :: Number -> Number -> Number
407−
408− foreign import numXor "function numXor(n1) {\
409− \ return function(n2) {\
410− \ return n1 ^ n2;\
411− \ };\
412− \}" :: Number -> Number -> Number
413−
414− foreign import numComplement "function numComplement(n) {\
415− \ return ~n;\
416− \}" :: Number -> Number
417−
418− instance bitsNumber :: Bits Number where
419− (&) = numAnd
420− (|) = numOr
421− (^) = numXor
422− shl = numShl
423− shr = numShr
424− zshr = numZshr
425− complement = numComplement
426−
427− infixr 2 ||
428− infixr 3 &&
429−
430− class BoolLike b where
431− (&&) :: b -> b -> b
432− (||) :: b -> b -> b
433− not :: b -> b
434−
435− foreign import boolAnd "function boolAnd(b1) {\
436− \ return function(b2) {\
437− \ return b1 && b2;\
438− \ };\
439− \}" :: Boolean -> Boolean -> Boolean
440−
441− foreign import boolOr "function boolOr(b1) {\
442− \ return function(b2) {\
443− \ return b1 || b2;\
444− \ };\
445− \}" :: Boolean -> Boolean -> Boolean
446−
447− foreign import boolNot "function boolNot(b) {\
448− \ return !b;\
449− \}" :: Boolean -> Boolean
450−
451− instance boolLikeBoolean :: BoolLike Boolean where
452− (&&) = boolAnd
453− (||) = boolOr
454− not = boolNot
455−
456− infixr 5 <>
457−
458− class Semigroup a where
459− (<>) :: a -> a -> a
460−
461− foreign import concatString
462− "function concatString(s1) {\
463− \ return function(s2) {\
464− \ return s1 + s2;\
465− \ };\
466− \}" :: String -> String -> String
467−
468− instance semigroupUnit :: Semigroup Unit where
469− (<>) (Unit {}) (Unit {}) = Unit {}
470−
471− instance semigroupString :: Semigroup String where
472− (<>) = concatString
473−
474− instance semigroupArr :: (Semigroup s') => Semigroup (s -> s') where
475− (<>) f g = \x -> f x <> g x
476−
477− infixr 5 ++
478−
479− (++) :: forall s. (Semigroup s) => s -> s -> s
480− (++) = (<>)
481−
482−module Data.Function where
483−
484− on :: forall a b c. (b -> b -> c) -> (a -> b) -> a -> a -> c
485− on f g x y = g x `f` g y
486−
487− foreign import data Fn0 :: * -> *
488− foreign import data Fn1 :: * -> * -> *
489− foreign import data Fn2 :: * -> * -> * -> *
490− foreign import data Fn3 :: * -> * -> * -> * -> *
491− foreign import data Fn4 :: * -> * -> * -> * -> * -> *
492− foreign import data Fn5 :: * -> * -> * -> * -> * -> * -> *
493−
494− foreign import mkFn0
495− "function mkFn0(f) {\
496− \ return function() {\
497− \ return f({});\
498− \ };\
499− \}" :: forall a. (Unit -> a) -> Fn0 a
500−
501− foreign import mkFn1
502− "function mkFn1(f) {\
503− \ return function(a) {\
504− \ return f(a);\
505− \ };\
506− \}" :: forall a b. (a -> b) -> Fn1 a b
507−
508− foreign import mkFn2
509− "function mkFn2(f) {\
510− \ return function(a, b) {\
511− \ return f(a)(b);\
512− \ };\
513− \}" :: forall a b c. (a -> b -> c) -> Fn2 a b c
514−
515− foreign import mkFn3
516− "function mkFn3(f) {\
517− \ return function(a, b, c) {\
518− \ return f(a)(b)(c);\
519− \ };\
520− \}" :: forall a b c d. (a -> b -> c -> d) -> Fn3 a b c d
521−
522− foreign import mkFn4
523− "function mkFn4(f) {\
524− \ return function(a, b, c, d) {\
525− \ return f(a)(b)(c)(d);\
526− \ };\
527− \}" :: forall a b c d e. (a -> b -> c -> d -> e) -> Fn4 a b c d e
528−
529− foreign import mkFn5
530− "function mkFn5(f) {\
531− \ return function(a, b, c, d, e) {\
532− \ return f(a)(b)(c)(d)(e);\
533− \ };\
534− \}" :: forall a b c d e f. (a -> b -> c -> d -> e -> f) -> Fn5 a b c d e f
535−
536− foreign import runFn0
537− "function runFn0(f) {\
538− \ return f();\
539− \}" :: forall a. Fn0 a -> a
540−
541− foreign import runFn1
542− "function runFn1(f) {\
543− \ return function(a) {\
544− \ return f(a);\
545− \ };\
546− \}" :: forall a b. Fn1 a b -> a -> b
547−
548− foreign import runFn2
549− "function runFn2(f) {\
550− \ return function(a) {\
551− \ return function(b) {\
552− \ return f(a, b);\
553− \ };\
554− \ };\
555− \}" :: forall a b c. Fn2 a b c -> a -> b -> c
556−
557− foreign import runFn3
558− "function runFn3(f) {\
559− \ return function(a) {\
560− \ return function(b) {\
561− \ return function(c) {\
562− \ return f(a, b, c);\
563− \ };\
564− \ };\
565− \ };\
566− \}" :: forall a b c d. Fn3 a b c d -> a -> b -> c -> d
567−
568− foreign import runFn4
569− "function runFn4(f) {\
570− \ return function(a) {\
571− \ return function(b) {\
572− \ return function(c) {\
573− \ return function(d) {\
574− \ return f(a, b, c, d);\
575− \ };\
576− \ };\
577− \ };\
578− \ };\
579− \}" :: forall a b c d e. Fn4 a b c d e -> a -> b -> c -> d -> e
580−
581− foreign import runFn5
582− "function runFn5(f) {\
583− \ return function(a) {\
584− \ return function(b) {\
585− \ return function(c) {\
586− \ return function(d) {\
587− \ return function(e) {\
588− \ return f(a, b, c, d, e);\
589− \ };\
590− \ };\
591− \ };\
592− \ };\
593− \ };\
594− \}" :: forall a b c d e f. Fn5 a b c d e f -> a -> b -> c -> d -> e -> f
595−
596−module Data.Eq where
597−
598− data Ref a = Ref a
599−
600− liftRef :: forall a b. (a -> a -> b) -> Ref a -> Ref a -> b
601− liftRef f (Ref x) (Ref y) = f x y
602−
603− instance eqRef :: Eq (Ref a) where
604− (==) = liftRef refEq
605− (/=) = liftRef refIneq
606−
607− instance functorRef :: Functor Ref where
608− (<$>) f (Ref x) = Ref (f x)
609−
610−module Prelude.Unsafe where
611−
612− foreign import unsafeIndex
613− "function unsafeIndex(xs) {\
614− \ return function(n) {\
615− \ return xs[n];\
616− \ };\
617− \}" :: forall a. [a] -> Number -> a
618−
619−module Control.Monad.Eff where
620−
621− foreign import data Eff :: # ! -> * -> *
622−
623− foreign import returnE "function returnE(a) {\
624− \ return function() {\
625− \ return a;\
626− \ };\
627− \}" :: forall e a. a -> Eff e a
628−
629− foreign import bindE "function bindE(a) {\
630− \ return function(f) {\
631− \ return function() {\
632− \ return f(a())();\
633− \ };\
634− \ };\
635− \}" :: forall e a b. Eff e a -> (a -> Eff e b) -> Eff e b
636−
637− type Pure a = forall e. Eff e a
638−
639− foreign import runPure "function runPure(f) {\
640− \ return f();\
641− \}" :: forall a. Pure a -> a
642−
643− instance functorEff :: Functor (Eff e) where
644− (<$>) = liftA1
645−
646− instance applyEff :: Apply (Eff e) where
647− (<*>) = ap
648−
649− instance applicativeEff :: Applicative (Eff e) where
650− pure = returnE
651−
652− instance bindEff :: Bind (Eff e) where
653− (>>=) = bindE
654−
655− instance monadEff :: Monad (Eff e)
656−
657− foreign import untilE "function untilE(f) {\
658− \ return function() {\
659− \ while (!f()) { }\
660− \ return {};\
661− \ };\
662− \}" :: forall e. Eff e Boolean -> Eff e Unit
663−
664− foreign import whileE "function whileE(f) {\
665− \ return function(a) {\
666− \ return function() {\
667− \ while (f()) {\
668− \ a();\
669− \ }\
670− \ return {};\
671− \ };\
672− \ };\
673− \}" :: forall e a. Eff e Boolean -> Eff e a -> Eff e Unit
674−
675− foreign import forE "function forE(lo) {\
676− \ return function(hi) {\
677− \ return function(f) {\
678− \ return function() {\
679− \ for (var i = lo; i < hi; i++) {\
680− \ f(i)();\
681− \ }\
682− \ };\
683− \ };\
684− \ };\
685− \}" :: forall e. Number -> Number -> (Number -> Eff e Unit) -> Eff e Unit
686−
687−
688− foreign import foreachE "function foreachE(as) {\
689− \ return function(f) {\
690− \ return function() {\
691− \ for (var i = 0; i < as.length; i++) {\
692− \ f(as[i])();\
693− \ }\
694− \ };\
695− \ };\
696− \}" :: forall e a. [a] -> (a -> Eff e Unit) -> Eff e Unit
697−
698−module Control.Monad.Eff.Unsafe where
699−
700− import Control.Monad.Eff
701−
702− foreign import unsafeInterleaveEff
703− "function unsafeInterleaveEff(f) {\
704− \ return f;\
705− \}" :: forall eff1 eff2 a. Eff eff1 a -> Eff eff2 a
706−
707−module Debug.Trace where
708−
709− import Control.Monad.Eff
710−
711− foreign import data Trace :: !
712−
713− foreign import trace "function trace(s) {\
714− \ return function() {\
715− \ console.log(s);\
716− \ return {};\
717− \ };\
718− \}" :: forall r. String -> Eff (trace :: Trace | r) Unit
719−
720− print :: forall a r. (Show a) => a -> Eff (trace :: Trace | r) Unit
721− print o = trace (show o)
722−
723−module Control.Monad.ST where
724−
725− import Control.Monad.Eff
726−
727− foreign import data ST :: * -> !
728−
729− foreign import data STRef :: * -> * -> *
730−
731− foreign import data STArray :: * -> * -> *
732−
733− foreign import newSTRef "function newSTRef(val) {\
734− \ return function () {\
735− \ return { value: val };\
736− \ };\
737− \}" :: forall a h r. a -> Eff (st :: ST h | r) (STRef h a)
738−
739− foreign import readSTRef "function readSTRef(ref) {\
740− \ return function() {\
741− \ return ref.value;\
742− \ };\
743− \}" :: forall a h r. STRef h a -> Eff (st :: ST h | r) a
744−
745− foreign import modifySTRef "function modifySTRef(ref) {\
746− \ return function(f) {\
747− \ return function() {\
748− \ return ref.value = f(ref.value);\
749− \ };\
750− \ };\
751− \}" :: forall a h r. STRef h a -> (a -> a) -> Eff (st :: ST h | r) a
752−
753− foreign import writeSTRef "function writeSTRef(ref) {\
754− \ return function(a) {\
755− \ return function() {\
756− \ return ref.value = a;\
757− \ };\
758− \ };\
759− \}" :: forall a h r. STRef h a -> a -> Eff (st :: ST h | r) a
760−
761− foreign import newSTArray "function newSTArray(len) {\
762− \ return function(a) {\
763− \ return function() {\
764− \ var arr = [];\
765− \ for (var i = 0; i < len; i++) {\
766− \ arr[i] = a;\
767− \ };\
768− \ return arr;\
769− \ };\
770− \ };\
771− \}" :: forall a h r. Number -> a -> Eff (st :: ST h | r) (STArray h a)
772−
773− foreign import peekSTArray "function peekSTArray(arr) {\
774− \ return function(i) {\
775− \ return function() {\
776− \ return arr[i];\
777− \ };\
778− \ };\
779− \}" :: forall a h r. STArray h a -> Eff (st :: ST h | r) a
780−
781− foreign import pokeSTArray "function pokeSTArray(arr) {\
782− \ return function(i) {\
783− \ return function(a) {\
784− \ return function() {\
785− \ return arr[i] = a;\
786− \ };\
787− \ };\
788− \ };\
789− \}" :: forall a h r. STArray h a -> Number -> a -> Eff (st :: ST h | r) a
790−
791− foreign import runST "function runST(f) {\
792− \ return f;\
793− \}" :: forall a r. (forall h. Eff (st :: ST h | r) a) -> Eff r a
794−
795− foreign import runSTArray "function runSTArray(f) {\
796− \ return f;\
797− \}" :: forall a r. (forall h. Eff (st :: ST h | r) (STArray h a)) -> Eff r [a]
prelude/updateDocs.shdeleted−11
@@ -1,11 +0,0 @@
1−../dist/build/docgen/docgen --hierarchy-images prelude.purs > README.md
2−../dist/build/hierarchy/hierarchy prelude.purs -o prelude
3−mkdir -p images
4−mkdir -p ../docs/source/images
5−for f in prelude/*; do
6− BASE=$(basename "$f")
7− dot -Tpng -o images/"$BASE".png "$f"
8− cp images/"$BASE".png ../docs/source/images/"$BASE".png
9−done
10−rm -r prelude
11−pandoc -o ../docs/source/prelude.rst README.md
psc-make/Main.hsdeleted−145
@@ -1,145 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Main
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
16−
17−module Main where
18−
19−import Control.Applicative
20−import Control.Monad.Error
21−
22−import Data.Version (showVersion)
23−
24−import System.Console.CmdTheLine
25−import System.Directory
26− (doesFileExist, getModificationTime, createDirectoryIfMissing)
27−import System.FilePath (takeDirectory)
28−import System.Exit (exitSuccess, exitFailure)
29−import System.IO.Error (tryIOError)
30−
31−import Text.Parsec (ParseError)
32−
33−import qualified Language.PureScript as P
34−import qualified Paths_purescript as Paths
35−import qualified System.IO.UTF8 as U
36−
37−preludeFilename :: IO FilePath
38−preludeFilename = Paths.getDataFileName "prelude/prelude.purs"
39−
40−readInput :: [FilePath] -> IO (Either ParseError [(FilePath, P.Module)])
41−readInput input = fmap collect $ forM input $ \inputFile -> do
42− text <- U.readFile inputFile
43− return $ (inputFile, P.runIndentParser inputFile P.parseModules text)
44− where
45− collect :: [(FilePath, Either ParseError [P.Module])] -> Either ParseError [(FilePath, P.Module)]
46− collect = fmap concat . sequence . map (\(fp, e) -> fmap (map ((,) fp)) e)
47−
48−newtype Make a = Make { unMake :: ErrorT String IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadError String)
49−
50−runMake :: Make a -> IO (Either String a)
51−runMake = runErrorT . unMake
52−
53−makeIO :: IO a -> Make a
54−makeIO = Make . ErrorT . fmap (either (Left . show) Right) . tryIOError
55−
56−instance P.MonadMake Make where
57− getTimestamp path = makeIO $ do
58− exists <- doesFileExist path
59− case exists of
60− True -> Just <$> getModificationTime path
61− False -> return Nothing
62− readTextFile path = makeIO $ do
63− U.putStrLn $ "Reading " ++ path
64− U.readFile path
65− writeTextFile path text = makeIO $ do
66− mkdirp path
67− U.putStrLn $ "Writing " ++ path
68− U.writeFile path text
69− liftError = either throwError return
70− progress = makeIO . U.putStrLn
71−
72−compile :: FilePath -> P.Options -> [FilePath] -> IO ()
73−compile outputDir opts input = do
74− modules <- readInput input
75− case modules of
76− Left err -> do
77− U.print err
78− exitFailure
79− Right ms -> do
80− e <- runMake $ P.make outputDir opts ms
81− case e of
82− Left err -> do
83− U.putStrLn err
84− exitFailure
85− Right _ -> do
86− exitSuccess
87−
88−mkdirp :: FilePath -> IO ()
89−mkdirp = createDirectoryIfMissing True . takeDirectory
90−
91−inputFiles :: Term [FilePath]
92−inputFiles = value $ posAny [] $ posInfo
93− { posDoc = "The input .ps files" }
94−
95−outputDirectory :: Term FilePath
96−outputDirectory = value $ opt "output" $ (optInfo [ "o", "output" ])
97− { optDoc = "The output directory" }
98−
99−noTco :: Term Bool
100−noTco = value $ flag $ (optInfo [ "no-tco" ])
101− { optDoc = "Disable tail call optimizations" }
102−
103−performRuntimeTypeChecks :: Term Bool
104−performRuntimeTypeChecks = value $ flag $ (optInfo [ "runtime-type-checks" ])
105− { optDoc = "Generate runtime type checks" }
106−
107−noPrelude :: Term Bool
108−noPrelude = value $ flag $ (optInfo [ "no-prelude" ])
109− { optDoc = "Omit the Prelude" }
110−
111−noMagicDo :: Term Bool
112−noMagicDo = value $ flag $ (optInfo [ "no-magic-do" ])
113− { optDoc = "Disable the optimization that overloads the do keyword to generate efficient code specifically for the Eff monad." }
114−
115−noOpts :: Term Bool
116−noOpts = value $ flag $ (optInfo [ "no-opts" ])
117− { optDoc = "Skip the optimization phase." }
118−
119−verboseErrors :: Term Bool
120−verboseErrors = value $ flag $ (optInfo [ "v", "verbose-errors" ])
121− { optDoc = "Display verbose error messages" }
122−
123−options :: Term P.Options
124−options = P.Options <$> noPrelude <*> noTco <*> performRuntimeTypeChecks <*> noMagicDo <*> pure Nothing <*> noOpts <*> pure Nothing <*> pure [] <*> pure [] <*> verboseErrors
125−
126−inputFilesAndPrelude :: FilePath -> Term [FilePath]
127−inputFilesAndPrelude prelude = combine <$> (not <$> noPrelude) <*> inputFiles
128− where
129− combine True input = prelude : input
130− combine False input = input
131−
132−term :: FilePath -> Term (IO ())
133−term prelude = compile <$> outputDirectory <*> options <*> inputFilesAndPrelude prelude
134−
135−termInfo :: TermInfo
136−termInfo = defTI
137− { termName = "psc-make"
138− , version = showVersion Paths.version
139− , termDoc = "Compiles PureScript to Javascript"
140− }
141−
142−main :: IO ()
143−main = do
144− prelude <- preludeFilename
145− run (term prelude, termInfo)
psc/Main.hsdeleted−154
@@ -1,154 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Main
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
16−
17−module Main where
18−
19−import Control.Applicative
20−import Control.Monad.Error
21−
22−import Data.Version (showVersion)
23−
24−import System.Console.CmdTheLine
25−import System.Directory (createDirectoryIfMissing)
26−import System.FilePath (takeDirectory)
27−import System.Exit (exitSuccess, exitFailure)
28−import System.IO (stderr)
29−
30−import Text.Parsec (ParseError)
31−
32−import qualified Language.PureScript as P
33−import qualified Paths_purescript as Paths
34−import qualified System.IO.UTF8 as U
35−
36−preludeFilename :: IO FilePath
37−preludeFilename = Paths.getDataFileName "prelude/prelude.purs"
38−
39−readInput :: Maybe [FilePath] -> IO (Either ParseError [(FilePath, P.Module)])
40−readInput Nothing = do
41− text <- getContents
42− return $ map ((,) undefined) <$> P.runIndentParser "" P.parseModules text
43−readInput (Just input) = fmap collect $ forM input $ \inputFile -> do
44− text <- U.readFile inputFile
45− return $ (inputFile, P.runIndentParser inputFile P.parseModules text)
46− where
47− collect :: [(FilePath, Either ParseError [P.Module])] -> Either ParseError [(FilePath, P.Module)]
48− collect = fmap concat . sequence . map (\(fp, e) -> fmap (map ((,) fp)) e)
49−
50−compile :: P.Options -> Maybe [FilePath] -> Maybe FilePath -> Maybe FilePath -> IO ()
51−compile opts input output externs = do
52− modules <- readInput input
53− case modules of
54− Left err -> do
55− U.hPutStr stderr $ show err
56− exitFailure
57− Right ms -> do
58− case P.compile opts (map snd ms) of
59− Left err -> do
60− U.hPutStrLn stderr err
61− exitFailure
62− Right (js, exts, _) -> do
63− case output of
64− Just path -> mkdirp path >> U.writeFile path js
65− Nothing -> U.putStrLn js
66− case externs of
67− Just path -> mkdirp path >> U.writeFile path exts
68− Nothing -> return ()
69− exitSuccess
70−
71−mkdirp :: FilePath -> IO ()
72−mkdirp = createDirectoryIfMissing True . takeDirectory
73−
74−useStdIn :: Term Bool
75−useStdIn = value . flag $ (optInfo [ "s", "stdin" ])
76− { optDoc = "Read from standard input" }
77−
78−inputFiles :: Term [FilePath]
79−inputFiles = value $ posAny [] $ posInfo
80− { posDoc = "The input .ps files" }
81−
82−outputFile :: Term (Maybe FilePath)
83−outputFile = value $ opt Nothing $ (optInfo [ "o", "output" ])
84− { optDoc = "The output .js file" }
85−
86−externsFile :: Term (Maybe FilePath)
87−externsFile = value $ opt Nothing $ (optInfo [ "e", "externs" ])
88− { optDoc = "The output .e.ps file" }
89−
90−noTco :: Term Bool
91−noTco = value $ flag $ (optInfo [ "no-tco" ])
92− { optDoc = "Disable tail call optimizations" }
93−
94−performRuntimeTypeChecks :: Term Bool
95−performRuntimeTypeChecks = value $ flag $ (optInfo [ "runtime-type-checks" ])
96− { optDoc = "Generate runtime type checks" }
97−
98−noPrelude :: Term Bool
99−noPrelude = value $ flag $ (optInfo [ "no-prelude" ])
100− { optDoc = "Omit the Prelude" }
101−
102−noMagicDo :: Term Bool
103−noMagicDo = value $ flag $ (optInfo [ "no-magic-do" ])
104− { optDoc = "Disable the optimization that overloads the do keyword to generate efficient code specifically for the Eff monad." }
105−
106−runMain :: Term (Maybe String)
107−runMain = value $ defaultOpt (Just "Main") Nothing $ (optInfo [ "main" ])
108− { optDoc = "Generate code to run the main method in the specified module." }
109−
110−noOpts :: Term Bool
111−noOpts = value $ flag $ (optInfo [ "no-opts" ])
112− { optDoc = "Skip the optimization phase." }
113−
114−browserNamespace :: Term String
115−browserNamespace = value $ opt "PS" $ (optInfo [ "browser-namespace" ])
116− { optDoc = "Specify the namespace that PureScript modules will be exported to when running in the browser." }
117−
118−dceModules :: Term [String]
119−dceModules = value $ optAll [] $ (optInfo [ "m", "module" ])
120− { optDoc = "Enables dead code elimination, all code which is not a transitive dependency of a specified module will be removed. This argument can be used multiple times." }
121−
122−codeGenModules :: Term [String]
123−codeGenModules = value $ optAll [] $ (optInfo [ "codegen" ])
124− { optDoc = "A list of modules for which Javascript and externs should be generated. This argument can be used multiple times." }
125−
126−verboseErrors :: Term Bool
127−verboseErrors = value $ flag $ (optInfo [ "v", "verbose-errors" ])
128− { optDoc = "Display verbose error messages" }
129−
130−options :: Term P.Options
131−options = P.Options <$> noPrelude <*> noTco <*> performRuntimeTypeChecks <*> noMagicDo <*> runMain <*> noOpts <*> (Just <$> browserNamespace) <*> dceModules <*> codeGenModules <*> verboseErrors
132−
133−stdInOrInputFiles :: FilePath -> Term (Maybe [FilePath])
134−stdInOrInputFiles prelude = combine <$> useStdIn <*> (not <$> noPrelude) <*> inputFiles
135− where
136− combine False True input = Just (prelude : input)
137− combine False False input = Just input
138− combine True _ _ = Nothing
139−
140−term :: FilePath -> Term (IO ())
141−term prelude = compile <$> options <*> stdInOrInputFiles prelude <*> outputFile <*> externsFile
142−
143−termInfo :: TermInfo
144−termInfo = defTI
145− { termName = "psc"
146− , version = showVersion Paths.version
147− , termDoc = "Compiles PureScript to Javascript"
148− }
149−
150−main :: IO ()
151−main = do
152− prelude <- preludeFilename
153− run (term prelude, termInfo)
154−
psci/Commands.hsdeleted−68
@@ -1,68 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Commands
4−-- Copyright : (c) Phil Freeman 2014
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Commands for PSCI.
13−--
14−-----------------------------------------------------------------------------
15−
16−module Commands where
17−
18−import Language.PureScript
19−
20−-- |
21−-- Valid Meta-commands for PSCI
22−--
23−data Command
24− -- |
25− -- A purescript expression
26− --
27− = Expression Value
28− -- |
29− -- Show the help command
30− --
31− | Help
32− -- |
33− -- Import a module from a loaded file
34− --
35− | Import ModuleName
36− -- |
37− -- Load a file for use with importing
38− --
39− | LoadFile FilePath
40− -- |
41− -- Exit PSCI
42− --
43− | Quit
44− -- |
45− -- Reset the state of the REPL
46− --
47− | Reset
48− -- |
49− -- Binds a value to a name
50− --
51− | Let (Value -> Value)
52− -- |
53− -- Find the type of an expression
54− --
55− | TypeOf Value
56−
57−-- |
58−-- The help menu.
59−--
60−help :: [[String]]
61−help =
62− [ [":? ", "Show this help menu"]
63− , [":i <module> ", "Import <module> for use in PSCI"]
64− , [":m <file> ", "Load <file> for importing"]
65− , [":q ", "Quit PSCi"]
66− , [":r ", "Reset"]
67− , [":t <expr> ", "Show the type of <expr>"]
68− ]
psci/Main.hsdeleted−400
@@ -1,400 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Main
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- PureScript Compiler Interactive.
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE DoAndIfThenElse, FlexibleContexts, GeneralizedNewtypeDeriving #-}
17−
18−module Main where
19−
20−import Commands
21−
22−import Control.Applicative
23−import Control.Monad
24−import Control.Monad.Trans.Class
25−import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
26−import Control.Monad.Trans.State.Strict
27−import Control.Monad.Error (ErrorT(..), MonadError)
28−import Control.Monad.Error.Class (MonadError(..))
29−
30−import Data.List (intercalate, isPrefixOf, nub, sortBy)
31−import Data.Maybe (mapMaybe)
32−import Data.Foldable (traverse_)
33−import Data.Version (showVersion)
34−import Data.Traversable (traverse)
35−
36−import Parser
37−
38−import System.IO.Error (tryIOError)
39−import System.Console.Haskeline
40−import System.Directory
41− (createDirectoryIfMissing, getModificationTime, doesFileExist,
42− findExecutable, getHomeDirectory, getCurrentDirectory)
43−import System.Process (readProcessWithExitCode)
44−import System.Exit
45−import System.Environment.XDG.BaseDir
46−import System.FilePath
47− (pathSeparator, takeDirectory, (</>), isPathSeparator)
48−import qualified System.Console.CmdTheLine as Cmd
49−
50−import Text.Parsec (ParseError)
51−
52−import qualified Data.Map as M
53−import qualified Language.PureScript as P
54−import qualified Paths_purescript as Paths
55−import qualified System.IO.UTF8 as U
56− (writeFile, putStrLn, print, readFile)
57−
58−-- |
59−-- The PSCI state.
60−-- Holds a list of imported modules, loaded files, and partial let bindings.
61−-- The let bindings are partial,
62−-- because it makes more sense to apply the binding to the final evaluated expression.
63−--
64−data PSCiState = PSCiState
65− { psciImportedFilenames :: [FilePath]
66− , psciImportedModuleNames :: [P.ModuleName]
67− , psciLoadedModules :: [(FilePath, P.Module)]
68− , psciLetBindings :: [P.Value -> P.Value]
69− }
70−
71−-- State helpers
72−
73−-- |
74−-- Updates the state to have more imported modules.
75−--
76−updateImportedFiles :: FilePath -> PSCiState -> PSCiState
77−updateImportedFiles filename st = st { psciImportedFilenames = filename : psciImportedFilenames st }
78−
79−-- |
80−-- Updates the state to have more imported modules.
81−--
82−updateImports :: P.ModuleName -> PSCiState -> PSCiState
83−updateImports name st = st { psciImportedModuleNames = name : psciImportedModuleNames st }
84−
85−-- |
86−-- Updates the state to have more loaded files.
87−--
88−updateModules :: [(FilePath, P.Module)] -> PSCiState -> PSCiState
89−updateModules modules st = st { psciLoadedModules = psciLoadedModules st ++ modules }
90−
91−-- |
92−-- Updates the state to have more let bindings.
93−--
94−updateLets :: (P.Value -> P.Value) -> PSCiState -> PSCiState
95−updateLets name st = st { psciLetBindings = name : psciLetBindings st }
96−
97−-- File helpers
98−-- |
99−-- Load the necessary modules.
100−--
101−defaultImports :: [P.ModuleName]
102−defaultImports = [P.ModuleName [P.ProperName "Prelude"]]
103−
104−-- |
105−-- Locates the node executable.
106−-- Checks for either @nodejs@ or @node@.
107−--
108−findNodeProcess :: IO (Maybe String)
109−findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names
110− where names = ["nodejs", "node"]
111−
112−-- |
113−-- Grabs the filename where the history is stored.
114−--
115−getHistoryFilename :: IO FilePath
116−getHistoryFilename = getUserConfigFile "purescript" "psci_history"
117−
118−-- |
119−-- Grabs the filename where prelude is.
120−--
121−getPreludeFilename :: IO FilePath
122−getPreludeFilename = Paths.getDataFileName "prelude/prelude.purs"
123−
124−-- |
125−-- Loads a file for use with imports.
126−--
127−loadModule :: FilePath -> IO (Either String [P.Module])
128−loadModule filename = either (Left . show) Right . P.runIndentParser filename P.parseModules <$> U.readFile filename
129−
130−-- |
131−-- Expands tilde in path.
132−--
133−expandTilde :: FilePath -> IO FilePath
134−expandTilde ('~':p:rest) | isPathSeparator p = (</> rest) <$> getHomeDirectory
135−expandTilde p = return p
136−-- Messages
137−
138−-- |
139−-- The help message.
140−--
141−helpMessage :: String
142−helpMessage = "The following commands are available:\n\n " ++
143− intercalate "\n " (map (intercalate " ") help)
144−
145−-- |
146−-- The welcome prologue.
147−--
148−prologueMessage :: String
149−prologueMessage = intercalate "\n"
150− [ " ____ ____ _ _ "
151− , "| _ \\ _ _ _ __ ___/ ___| ___ _ __(_)_ __ | |_ "
152− , "| |_) | | | | '__/ _ \\___ \\ / __| '__| | '_ \\| __|"
153− , "| __/| |_| | | | __/___) | (__| | | | |_) | |_ "
154− , "|_| \\__,_|_| \\___|____/ \\___|_| |_| .__/ \\__|"
155− , " |_| "
156− , ""
157− , ":? shows help"
158− , ""
159− , "Expressions are terminated using Ctrl+D"
160− ]
161−
162−-- |
163−-- The quit message.
164−--
165−quitMessage :: String
166−quitMessage = "See ya!"
167−
168−-- Haskeline completions
169−
170−-- |
171−-- Loads module, function, and file completions.
172−--
173−completion :: CompletionFunc (StateT PSCiState IO)
174−completion = completeWord Nothing " \t\n\r" findCompletions
175− where
176− findCompletions :: String -> StateT PSCiState IO [Completion]
177− findCompletions str = do
178− ms <- map snd . psciLoadedModules <$> get
179− files <- listFiles str
180− let matches = filter (isPrefixOf str) (names ms)
181− return $ sortBy sorter $ map simpleCompletion matches ++ files
182− getDeclName :: Maybe [P.DeclarationRef] -> P.Declaration -> Maybe P.Ident
183− getDeclName Nothing (P.ValueDeclaration ident _ _ _ _) = Just ident
184− getDeclName (Just exts) (P.ValueDeclaration ident _ _ _ _) | isExported = Just ident
185− where
186− isExported = any exports exts
187− exports (P.ValueRef ident') = ident == ident'
188− exports (P.PositionedDeclarationRef _ r) = exports r
189− exports _ = False
190− getDeclName exts (P.PositionedDeclaration _ d) = getDeclName exts d
191− getDeclName _ _ = Nothing
192− names :: [P.Module] -> [String]
193− names ms = nub [ show qual
194− | P.Module moduleName ds exts <- ms
195− , ident <- mapMaybe (getDeclName exts) ds
196− , qual <- [ P.Qualified Nothing ident
197− , P.Qualified (Just moduleName) ident]
198− ]
199− sorter :: Completion -> Completion -> Ordering
200− sorter (Completion _ d1 _) (Completion _ d2 _) = compare d1 d2
201−
202−-- Compilation
203−
204−-- | Compilation options.
205−--
206−options :: P.Options
207−options = P.Options False True False True Nothing True Nothing [] [] False
208−
209−-- |
210−-- PSCI monad
211−--
212−newtype PSCI a = PSCI { runPSCI :: InputT (StateT PSCiState IO) a } deriving (Functor, Applicative, Monad)
213−
214−psciIO :: IO a -> PSCI a
215−psciIO io = PSCI (lift (lift io))
216−
217−newtype Make a = Make { unMake :: ErrorT String IO a } deriving (Functor, Applicative, Monad, MonadError String)
218−
219−runMake :: Make a -> IO (Either String a)
220−runMake = runErrorT . unMake
221−
222−makeIO :: IO a -> Make a
223−makeIO = Make . ErrorT . fmap (either (Left . show) Right) . tryIOError
224−
225−instance P.MonadMake Make where
226− getTimestamp path = makeIO $ do
227− exists <- doesFileExist path
228− case exists of
229− True -> Just <$> getModificationTime path
230− False -> return Nothing
231− readTextFile path = makeIO $ U.readFile path
232− writeTextFile path text = makeIO $ do
233− mkdirp path
234− U.writeFile path text
235− liftError = either throwError return
236− progress s = unless (s == "Compiling Main") $ makeIO . U.putStrLn $ s
237−
238−mkdirp :: FilePath -> IO ()
239−mkdirp = createDirectoryIfMissing True . takeDirectory
240−
241−-- |
242−-- Makes a volatile module to execute the current expression.
243−--
244−createTemporaryModule :: Bool -> PSCiState -> P.Value -> P.Module
245−createTemporaryModule exec PSCiState{psciImportedModuleNames = imports, psciLetBindings = lets} value =
246− let
247− moduleName = P.ModuleName [P.ProperName "Main"]
248− importDecl m = P.ImportDeclaration m Nothing Nothing
249− traceModule = P.ModuleName [P.ProperName "Debug", P.ProperName "Trace"]
250− trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))
251− itValue = foldl (\x f -> f x) value lets
252− mainValue = P.App trace (P.Var (P.Qualified Nothing (P.Ident "it")))
253− itDecl = P.ValueDeclaration (P.Ident "it") P.Value [] Nothing itValue
254− mainDecl = P.ValueDeclaration (P.Ident "main") P.Value [] Nothing mainValue
255− decls = if exec then [itDecl, mainDecl] else [itDecl]
256− in
257− P.Module moduleName ((importDecl `map` imports) ++ decls) Nothing
258−
259−modulesDir :: FilePath
260−modulesDir = ".psci_modules" ++ pathSeparator : "node_modules"
261−
262−indexFile :: FilePath
263−indexFile = ".psci_modules" ++ pathSeparator : "index.js"
264−
265−-- |
266−-- Takes a value declaration and evaluates it with the current state.
267−--
268−handleDeclaration :: P.Value -> PSCI ()
269−handleDeclaration value = do
270− st <- PSCI $ lift get
271− let m = createTemporaryModule True st value
272− e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [("Main.purs", m)])
273− case e of
274− Left err -> PSCI $ outputStrLn err
275− Right _ -> do
276− psciIO $ writeFile indexFile $ "require('Main').main();"
277− process <- psciIO findNodeProcess
278− result <- psciIO $ traverse (\node -> readProcessWithExitCode node [indexFile] "") process
279− case result of
280− Just (ExitSuccess, out, _) -> PSCI $ outputStrLn out
281− Just (ExitFailure _, _, err) -> PSCI $ outputStrLn err
282− Nothing -> PSCI $ outputStrLn "Couldn't find node.js"
283−
284−-- |
285−-- Takes a value and prints its type
286−--
287−handleTypeOf :: P.Value -> PSCI ()
288−handleTypeOf value = do
289− st <- PSCI $ lift get
290− let m = createTemporaryModule False st value
291− e <- psciIO . runMake $ P.make modulesDir options (psciLoadedModules st ++ [("Main.purs", m)])
292− case e of
293− Left err -> PSCI $ outputStrLn err
294− Right env' ->
295− case M.lookup (P.ModuleName [P.ProperName "Main"], P.Ident "it") (P.names env') of
296− Just (ty, _) -> PSCI . outputStrLn . P.prettyPrintType $ ty
297− Nothing -> PSCI $ outputStrLn "Could not find type"
298−
299−-- Commands
300−
301−-- |
302−-- Parses the input and returns either a Metacommand or an expression.
303−--
304−getCommand :: InputT (StateT PSCiState IO) (Either ParseError (Maybe Command))
305−getCommand = do
306− firstLine <- getInputLine "> "
307− case firstLine of
308− Nothing -> return (Right Nothing)
309− Just s@ (':' : _) -> return . either Left (Right . Just) $ parseCommand s -- The start of a command
310− Just s -> either Left (Right . Just) . parseCommand <$> go [s]
311− where
312− go :: [String] -> InputT (StateT PSCiState IO) String
313− go ls = maybe (return . unlines $ reverse ls) (go . (:ls)) =<< getInputLine " "
314−
315−-- |
316−-- Performs an action for each meta-command given, and also for expressions..
317−--
318−handleCommand :: Command -> PSCI ()
319−handleCommand (Expression val) = handleDeclaration val
320−handleCommand Help = PSCI $ outputStrLn helpMessage
321−handleCommand (Import moduleName) = PSCI $ lift $ modify (updateImports moduleName)
322−handleCommand (Let l) = PSCI $ lift $ modify (updateLets l)
323−handleCommand (LoadFile filePath) = do
324− absPath <- psciIO $ expandTilde filePath
325− exists <- psciIO $ doesFileExist absPath
326− if exists then do
327− PSCI . lift $ modify (updateImportedFiles absPath)
328− m <- psciIO $ loadModule absPath
329− case m of
330− Left err -> PSCI $ outputStrLn err
331− Right mods -> PSCI . lift $ modify (updateModules (map ((,) absPath) mods))
332− else
333− PSCI . outputStrLn $ "Couldn't locate: " ++ filePath
334−handleCommand Reset = do
335− files <- psciImportedFilenames <$> PSCI (lift get)
336− filesAndModules <- mapM (\file -> fmap (fmap (map ((,) file))) . psciIO . loadModule $ file) files
337− let modulesOrFirstError = fmap concat $ sequence filesAndModules
338− case modulesOrFirstError of
339− Left err -> psciIO $ putStrLn err >> exitFailure
340− Right modules -> PSCI . lift $ put (PSCiState files defaultImports modules [])
341−handleCommand (TypeOf val) = handleTypeOf val
342−handleCommand _ = PSCI $ outputStrLn "Unknown command"
343−
344−inputFiles :: Cmd.Term [FilePath]
345−inputFiles = Cmd.value $ Cmd.posAny [] $ Cmd.posInfo { Cmd.posName = "file(s)"
346− , Cmd.posDoc = "Optional .purs files to load on start" }
347−
348−loadUserConfig :: IO (Maybe [Command])
349−loadUserConfig = do
350− configFile <- (</> ".psci") <$> getCurrentDirectory
351− exists <- doesFileExist configFile
352− if exists
353− then do
354− ls <- lines <$> U.readFile configFile
355− case mapM parseCommand ls of
356− Left err -> U.print err >> exitFailure
357− Right cs -> return $ Just cs
358− else
359− return Nothing
360−
361−-- |
362−-- The PSCI main loop.
363−--
364−loop :: [FilePath] -> IO ()
365−loop files = do
366− config <- loadUserConfig
367− preludeFilename <- getPreludeFilename
368− filesAndModules <- mapM (\file -> fmap (fmap (map ((,) file))) . loadModule $ file) (preludeFilename : files)
369− let modulesOrFirstError = fmap concat $ sequence filesAndModules
370− case modulesOrFirstError of
371− Left err -> putStrLn err >> exitFailure
372− Right modules -> do
373− historyFilename <- getHistoryFilename
374− let settings = defaultSettings {historyFile = Just historyFilename}
375− flip evalStateT (PSCiState (preludeFilename : files) defaultImports modules []) . runInputT (setComplete completion settings) $ do
376− outputStrLn prologueMessage
377− traverse_ (mapM_ (runPSCI . handleCommand)) config
378− go
379− where
380− go :: InputT (StateT PSCiState IO) ()
381− go = do
382− c <- getCommand
383− case c of
384− Left err -> outputStrLn (show err) >> go
385− Right Nothing -> go
386− Right (Just Quit) -> outputStrLn quitMessage
387− Right (Just c') -> runPSCI (handleCommand c') >> go
388−
389−term :: Cmd.Term (IO ())
390−term = loop <$> inputFiles
391−
392−termInfo :: Cmd.TermInfo
393−termInfo = Cmd.defTI
394− { Cmd.termName = "psci"
395− , Cmd.version = showVersion Paths.version
396− , Cmd.termDoc = "Interactive mode for PureScript"
397− }
398−
399−main :: IO ()
400−main = Cmd.run (term, termInfo)
psci/Parser.hsdeleted−92
@@ -1,92 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Parser
4−-- Copyright : (c) Phil Freeman 2014
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Parser for PSCI.
13−--
14−-----------------------------------------------------------------------------
15−
16−module Parser (
17− parseCommand
18− ) where
19−
20−import Commands
21−
22−import Data.Char (isSpace)
23−
24−import Control.Applicative hiding (many)
25−
26−import Text.Parsec hiding ((<|>))
27−
28−import qualified Language.PureScript as P
29−import qualified Language.PureScript.Parser.Common as C (mark, same)
30−
31−-- |
32−-- PSCI version of @let@.
33−-- This is essentially let from do-notation.
34−-- However, since we don't support the @Eff@ monad,
35−-- we actually want the normal @let@.
36−--
37−psciLet :: Parsec String P.ParseState Command
38−psciLet = Let <$> (P.Let <$> (P.reserved "let" *> P.indented *> C.mark (many1 (C.same *> P.parseDeclaration))))
39−
40−-- |
41−-- Parses PSCI metacommands or expressions input from the user.
42−--
43−parseCommand :: String -> Either ParseError Command
44−parseCommand = P.runIndentParser "" $ choice
45− [ P.whiteSpace *> char ':' *> (psciHelp <|> psciImport <|> psciLoadFile <|> psciQuit <|> psciReload <|> psciTypeOf)
46− , try psciLet
47− , psciExpression
48− ] <* eof
49−
50−-- |
51−-- Parses expressions entered at the PSCI repl.
52−--
53−psciExpression :: Parsec String P.ParseState Command
54−psciExpression = Expression <$> P.parseValue
55−
56−-- |
57−-- Parses 'Commands.Help' command.
58−--
59−psciHelp :: Parsec String P.ParseState Command
60−psciHelp = Help <$ char '?'
61−
62−-- |
63−-- Parses 'Commands.Import' command.
64−--
65−psciImport :: Parsec String P.ParseState Command
66−psciImport = Import <$> (char 'i' *> P.whiteSpace *> P.moduleName)
67−
68−-- |
69−-- Parses 'Commands.LoadFile' command.
70−--
71−psciLoadFile :: Parsec String P.ParseState Command
72−psciLoadFile = LoadFile . trimEnd <$> (char 'm' *> P.whiteSpace *> manyTill anyChar eof)
73− where
74− trimEnd = reverse . dropWhile isSpace . reverse
75−
76−-- |
77−-- Parses 'Commands.Quit' command.
78−--
79−psciQuit :: Parsec String P.ParseState Command
80−psciQuit = Quit <$ char 'q'
81−
82−-- |
83−-- Parses 'Commands.Reload' command.
84−--
85−psciReload :: Parsec String P.ParseState Command
86−psciReload = Reset <$ char 'r'
87−
88−-- |
89−-- Parses 'Commands.TypeOf' command.
90−--
91−psciTypeOf :: Parsec String P.ParseState Command
92−psciTypeOf = TypeOf <$> (char 't' *> P.whiteSpace *> P.parseValue)
psgo.cabalnew file+145
@@ -0,0 +1,145 @@
1+cabal-version: 1.12
2+
3+-- This file has been generated from package.yaml by hpack version 0.35.0.
4+--
5+-- see: https://github.com/sol/hpack
6+
7+name: psgo
8+version: 0.1.0.0
9+description: Please see the README on Github at <https://github.com/andyarvanitis/purescript-native#readme>
10+homepage: https://github.com/andyarvanitis/purescript-native#readme
11+bug-reports: https://github.com/andyarvanitis/purescript-native/issues
12+author: Andy Arvanitis
13+maintainer: example@example.com
14+copyright: 2018 Andy Arvanitis
15+license: BSD3
16+license-file: LICENSE
17+build-type: Simple
18+extra-source-files:
19+ README.md
20+ ChangeLog.md
21+ stack.yaml
22+ support/ffi-loader.go
23+ support/go.mod.ffi-loader
24+ support/go.mod.output
25+ support/go.mod.working
26+
27+source-repository head
28+ type: git
29+ location: https://github.com/andyarvanitis/purescript-native
30+
31+library
32+ exposed-modules:
33+ CodeGen.IL
34+ CodeGen.IL.Common
35+ CodeGen.IL.Optimizer
36+ CodeGen.IL.Optimizer.Common
37+ CodeGen.IL.Optimizer.Inliner
38+ CodeGen.IL.Optimizer.MagicDo
39+ CodeGen.IL.Optimizer.TCO
40+ CodeGen.IL.Printer
41+ Tests
42+ other-modules:
43+ Paths_psgo
44+ hs-source-dirs:
45+ src
46+ default-extensions:
47+ ConstraintKinds
48+ DataKinds
49+ DeriveFunctor
50+ EmptyDataDecls
51+ FlexibleContexts
52+ KindSignatures
53+ LambdaCase
54+ MultiParamTypeClasses
55+ NoImplicitPrelude
56+ PatternGuards
57+ PatternSynonyms
58+ RankNTypes
59+ RecordWildCards
60+ OverloadedStrings
61+ ScopedTypeVariables
62+ TupleSections
63+ ViewPatterns
64+ build-depends:
65+ aeson >=1.0 && <1.5
66+ , base >=4.7 && <5
67+ , base-compat >=0.6.0
68+ , bytestring >=0.10.8.2 && <0.11
69+ , containers
70+ , directory
71+ , file-embed
72+ , filemanip
73+ , filepath
74+ , gitrev
75+ , monad-parallel >=0.7.2.2 && <0.8
76+ , mtl >=2.1.0 && <2.3.0
77+ , pattern-arrows >=0.0.2 && <0.1
78+ , process
79+ , protolude >=0.1.6
80+ , purescript
81+ , safe >=0.3.9 && <0.4
82+ , text
83+ , transformers >=0.3.0 && <0.6
84+ default-language: Haskell2010
85+
86+executable psgo
87+ main-is: Main.hs
88+ other-modules:
89+ Paths_psgo
90+ hs-source-dirs:
91+ app
92+ ghc-options: -threaded -rtsopts -with-rtsopts=-N
93+ build-depends:
94+ aeson >=1.0 && <1.5
95+ , base >=4.7 && <5
96+ , base-compat >=0.6.0
97+ , bytestring >=0.10.8.2 && <0.11
98+ , containers
99+ , directory
100+ , file-embed
101+ , filemanip
102+ , filepath
103+ , gitrev
104+ , monad-parallel >=0.7.2.2 && <0.8
105+ , mtl >=2.1.0 && <2.3.0
106+ , pattern-arrows >=0.0.2 && <0.1
107+ , process
108+ , protolude >=0.1.6
109+ , psgo
110+ , purescript
111+ , safe >=0.3.9 && <0.4
112+ , text
113+ , transformers >=0.3.0 && <0.6
114+ default-language: Haskell2010
115+
116+test-suite psgo-test
117+ type: exitcode-stdio-1.0
118+ main-is: Spec.hs
119+ other-modules:
120+ Paths_psgo
121+ hs-source-dirs:
122+ test
123+ ghc-options: -threaded -rtsopts -with-rtsopts=-N
124+ build-depends:
125+ aeson >=1.0 && <1.5
126+ , base >=4.7 && <5
127+ , base-compat >=0.6.0
128+ , bytestring >=0.10.8.2 && <0.11
129+ , containers
130+ , directory
131+ , file-embed
132+ , filemanip
133+ , filepath
134+ , gitrev
135+ , monad-parallel >=0.7.2.2 && <0.8
136+ , mtl >=2.1.0 && <2.3.0
137+ , pattern-arrows >=0.0.2 && <0.1
138+ , process
139+ , protolude >=0.1.6
140+ , psgo
141+ , purescript
142+ , safe >=0.3.9 && <0.4
143+ , text
144+ , transformers >=0.3.0 && <0.6
145+ default-language: Haskell2010
purescript.cabaldeleted−147
@@ -1,147 +0,0 @@
1−name: purescript
2−version: 0.5.3
3−cabal-version: >=1.8
4−build-type: Custom
5−license: MIT
6−license-file: LICENSE
7−copyright: (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
8−maintainer: Phil Freeman <paf31@cantab.net>
9−stability: experimental
10−synopsis: PureScript Programming Language Compiler
11−description: A small strongly, statically typed programming language with expressive types, inspired by Haskell and compiling to Javascript.
12−category: Language
13−Homepage: http://www.purescript.org/
14−author: Phil Freeman <paf31@cantab.net>,
15− Gary Burgess <gary.burgess@gmail.com>,
16− Hardy Jones <jones3.hardy@gmail.com>
17−data-files: prelude/prelude.purs
18−data-dir: ""
19−
20−source-repository head
21− type: git
22− location: https://github.com/purescript/purescript.git
23−
24−library
25− build-depends: base >=4 && <5, cmdtheline == 0.2.*, containers -any, unordered-containers -any,
26− directory >= 1.2, filepath -any, mtl >= 2.1.0 && < 2.2.0, parsec -any,
27− transformers >= 0.3 && < 0.4, utf8-string -any,
28− pattern-arrows >= 0.0.2 && < 0.1,
29− monad-unify >= 0.2.2 && < 0.3,
30− xdg-basedir -any, time -any
31− if (!os(windows))
32− build-depends: unix -any
33− exposed-modules: Language.PureScript
34− Language.PureScript.Constants
35− Language.PureScript.Options
36− Language.PureScript.Declarations
37− Language.PureScript.Environment
38− Language.PureScript.Errors
39− Language.PureScript.Kinds
40− Language.PureScript.Names
41− Language.PureScript.Supply
42− Language.PureScript.Types
43− Language.PureScript.Traversals
44− Language.PureScript.TypeClassDictionaries
45− Language.PureScript.DeadCodeElimination
46− Language.PureScript.Sugar
47− Language.PureScript.ModuleDependencies
48− Language.PureScript.Sugar.CaseDeclarations
49− Language.PureScript.Sugar.DoNotation
50− Language.PureScript.Sugar.TypeDeclarations
51− Language.PureScript.Sugar.BindingGroups
52− Language.PureScript.Sugar.Operators
53− Language.PureScript.Sugar.TypeClasses
54− Language.PureScript.Sugar.Names
55− Language.PureScript.CodeGen
56− Language.PureScript.CodeGen.Common
57− Language.PureScript.CodeGen.Externs
58− Language.PureScript.CodeGen.JS
59− Language.PureScript.CodeGen.JS.AST
60− Language.PureScript.Optimizer
61− Language.PureScript.Optimizer.Common
62− Language.PureScript.Optimizer.MagicDo
63− Language.PureScript.Optimizer.TCO
64− Language.PureScript.Optimizer.Inliner
65− Language.PureScript.Optimizer.Unused
66− Language.PureScript.Optimizer.Blocks
67− Language.PureScript.Parser
68− Language.PureScript.Parser.Common
69− Language.PureScript.Parser.Declarations
70− Language.PureScript.Parser.Kinds
71− Language.PureScript.Parser.State
72− Language.PureScript.Parser.Types
73− Language.PureScript.Pretty
74− Language.PureScript.Pretty.Common
75− Language.PureScript.Pretty.JS
76− Language.PureScript.Pretty.Kinds
77− Language.PureScript.Pretty.Types
78− Language.PureScript.Pretty.Values
79− Language.PureScript.TypeChecker
80− Language.PureScript.TypeChecker.Kinds
81− Language.PureScript.TypeChecker.Monad
82− Language.PureScript.TypeChecker.Synonyms
83− Language.PureScript.TypeChecker.Types
84− exposed: True
85− buildable: True
86− hs-source-dirs: src
87− other-modules:
88− ghc-options: -Wall -O2
89−
90−executable psc
91− build-depends: base >=4 && <5, cmdtheline -any, containers -any,
92− directory -any, filepath -any, mtl -any, parsec -any,
93− purescript -any, transformers -any, utf8-string -any
94− main-is: Main.hs
95− buildable: True
96− hs-source-dirs: psc
97− other-modules:
98− ghc-options: -Wall -O2 -fno-warn-unused-do-bind
99−
100−executable psc-make
101− build-depends: base >=4 && <5, cmdtheline -any, containers -any,
102− directory -any, filepath -any, mtl -any, parsec -any,
103− purescript -any, transformers -any, utf8-string -any
104− main-is: Main.hs
105− buildable: True
106− hs-source-dirs: psc-make
107− other-modules:
108− ghc-options: -Wall -O2 -fno-warn-unused-do-bind
109−
110−executable psci
111− build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,
112− mtl -any, parsec -any, haskeline >= 0.7.0.0, purescript -any,
113− transformers -any, utf8-string -any, process -any,
114− xdg-basedir -any, cmdtheline -any
115− main-is: Main.hs
116− buildable: True
117− hs-source-dirs: psci
118− other-modules: Commands
119− Parser
120− ghc-options: -Wall -O2
121−
122−executable docgen
123− build-depends: base >=4 && <5, cmdtheline -any, purescript -any, utf8-string -any,
124− process -any, mtl -any
125− main-is: Main.hs
126− buildable: True
127− hs-source-dirs: docgen
128− other-modules:
129− ghc-options: -Wall -O2
130−
131−executable hierarchy
132− build-depends: base >=4 && <5, cmdtheline -any, purescript -any, utf8-string -any,
133− process -any, mtl -any, parsec -any, filepath -any, directory -any
134− main-is: Main.hs
135− buildable: True
136− hs-source-dirs: hierarchy
137− other-modules:
138− ghc-options: -Wall -O2
139−
140−test-suite tests
141− build-depends: base >=4 && <5, containers -any, directory -any,
142− filepath -any, mtl -any, parsec -any, purescript -any,
143− transformers -any, utf8-string -any, process -any
144− type: exitcode-stdio-1.0
145− main-is: Main.hs
146− buildable: True
147− hs-source-dirs: tests
src/CodeGen/IL.hsnew file+321
@@ -0,0 +1,321 @@
1+-- | This module generates code in the core imperative representation from
2+-- elaborated PureScript code.
3+module CodeGen.IL
4+ ( module AST
5+ , module Common
6+ , moduleToIL
7+ ) where
8+
9+import Prelude.Compat
10+import Protolude (ordNub)
11+
12+import Control.Arrow ((&&&))
13+import Control.Monad (forM, liftM, replicateM, void)
14+import Control.Monad.Supply.Class
15+
16+import Data.List ((\\), delete, intersect, nub)
17+import qualified Data.Foldable as F
18+import qualified Data.Map as M
19+import Data.Maybe (fromMaybe, isNothing, mapMaybe)
20+import Data.Monoid ((<>))
21+import Data.String (fromString)
22+import Data.Text (Text)
23+import qualified Data.Text as T
24+
25+import Language.PureScript.AST.SourcePos
26+import Language.PureScript.CoreImp.AST (AST)
27+import qualified Language.PureScript.CoreImp.AST as AST
28+import Language.PureScript.CoreFn
29+import Language.PureScript.Crash
30+import Language.PureScript.Names
31+import Language.PureScript.Options
32+import Language.PureScript.PSString (PSString, mkString)
33+import Language.PureScript.Traversals (sndM)
34+import qualified Language.PureScript.Constants as C
35+
36+import System.FilePath.Posix ((</>))
37+
38+import CodeGen.IL.Common as Common
39+import CodeGen.IL.Optimizer
40+import CodeGen.IL.Printer
41+
42+data DeclType = ModuleDecl | LetDecl | RecLetDecl deriving (Eq)
43+
44+-- | Generate code in the simplified intermediate representation for all declarations in a
45+-- module.
46+moduleToIL
47+ :: forall m
48+ -- . (Monad m, MonadReader Options m, MonadSupply m, MonadError MultipleErrors m)
49+ . (Monad m, MonadSupply m)
50+ => Module Ann
51+ -> Text
52+ -> m (Text, [Text], [AST], Text, Text)
53+moduleToIL (Module _ coms mn _ imps _ foreigns decls) project =
54+ do
55+ ilDecls <- mapM (bindToIL ModuleDecl) decls
56+ optimized <- traverse (traverse (optimize modName')) ilDecls
57+ let optimized' = concat optimized
58+ values = annotValue <$> optimized'
59+ foreigns' = moduleIdentToIL <$> foreigns
60+ interface = interfaceSource modName values foreigns
61+ imports = nub . concat $ importToIL <$> optimized'
62+ implHeader = implHeaderSource modName imports project
63+ implFooter = implFooterSource (runModuleName mn) foreigns
64+ return $ (interface, foreigns', optimized', implHeader, implFooter)
65+ where
66+ modName = moduleNameToIL mn
67+ modName' = AST.Var Nothing modName
68+
69+ annotValue :: AST -> (Text, Bool)
70+ annotValue (AST.Function _ (Just name) [] (AST.Block _ [AST.Return _ ret]))
71+ | isLiteral ret = (name, True)
72+ annotValue (AST.Function _ (Just name) [] _) = (name, False)
73+ annotValue _ = error "Unexpected top-level value form"
74+
75+ -- | Extracts all declaration names from a binding group.
76+ getNames :: Bind Ann -> [Ident]
77+ getNames (NonRec _ ident _) = [ident]
78+ getNames (Rec vals) = map (snd . fst) vals
79+
80+ -- | Generates IL code for a module import
81+ --
82+ importToIL :: AST -> [Text]
83+ importToIL = AST.everything (++) modRef
84+ where
85+ modRef (AST.Indexer _ (AST.Var _ _) (AST.Var _ mname))
86+ | not $ T.null mname = [extract mname]
87+ modRef _ = []
88+ extract :: Text -> Text
89+ extract = T.replace "_" "." . T.dropWhileEnd (=='_')
90+
91+ -- |
92+ -- Generate code in the simplified intermediate representation for a declaration
93+ --
94+ bindToIL :: DeclType -> Bind Ann -> m [AST]
95+ bindToIL dt (NonRec ann ident val) = return <$> nonRecToIL dt ann ident val
96+ bindToIL dt (Rec vals) = forM vals (uncurry . uncurry $ nonRecToIL dt')
97+ where
98+ dt' = if dt == LetDecl then RecLetDecl else dt
99+
100+ -- | Generate code in the simplified intermediate representation for a single non-recursive
101+ -- declaration.
102+ --
103+ -- The main purpose of this function is to handle code generation for comments.
104+ nonRecToIL :: DeclType -> Ann -> Ident -> Expr Ann -> m AST
105+ nonRecToIL dt a i e@(extractAnn -> (_, com, _, _)) | not (null com) = do
106+ -- withoutComment <- asks optionsNoComments
107+ let withoutComment = False
108+ if withoutComment
109+ then nonRecToIL dt a i (modifyAnn removeComments e)
110+ else AST.Comment Nothing com <$> nonRecToIL dt a i (modifyAnn removeComments e)
111+ nonRecToIL ModuleDecl (ss, _, _, _) ident val = do
112+ il <- valueToIL val
113+ pure $ AST.Function Nothing (Just $ moduleIdentToIL ident) [] (AST.Block Nothing [AST.Return Nothing il])
114+ nonRecToIL RecLetDecl (ss, _, _, _) ident val = do
115+ ilExpr <- valueToIL val
116+ pure $ AST.Assignment Nothing (AST.Var Nothing $ identToIL ident) ilExpr
117+ nonRecToIL _ (ss, _, _, _) ident val = do
118+ il <- valueToIL val
119+ pure $ AST.VariableIntroduction Nothing (identToIL ident) (Just il)
120+
121+ -- | Generate code in the simplified intermediate representation for a variable based on a
122+ -- PureScript identifier.
123+ var :: Ident -> AST
124+ var = AST.Var Nothing . identToIL
125+
126+ accessorString :: PSString -> AST -> AST
127+ accessorString prop = AST.Indexer Nothing (AST.StringLiteral Nothing prop)
128+
129+ -- | Generate code in the simplified intermediate representation for a value or expression.
130+
131+ valueToIL :: Expr Ann -> m AST
132+ valueToIL (Literal (pos, _, _, _) l) = literalToValueIL pos l
133+ valueToIL (Accessor _ prop val) =
134+ accessorString prop <$> valueToIL val
135+ valueToIL (ObjectUpdate _ o ps) = do
136+ obj <- valueToIL o
137+ updates <- mapM (sndM valueToIL) ps
138+ obj' <- freshName'
139+ let objVar = AST.Var Nothing obj'
140+ copy = AST.VariableIntroduction Nothing obj' (Just $ copyDict obj)
141+ assign (k, v) = AST.Assignment Nothing (accessorString k objVar) v
142+ sts = copy : (assign <$> updates) ++ [AST.Return Nothing objVar]
143+ return $ AST.App Nothing (AST.Function Nothing Nothing [] (AST.Block Nothing sts)) []
144+ valueToIL (Abs _ arg val) = do
145+ ret <- valueToIL val
146+ let ilArg = case arg of
147+ UnusedIdent -> []
148+ _ -> [identToIL arg]
149+ return $ AST.Function Nothing Nothing ilArg (AST.Block Nothing [AST.Return Nothing ret])
150+ valueToIL e@App{} = do
151+ let (f, args) = unApp e []
152+ args' <- mapM valueToIL args
153+ fn <- valueToIL f
154+ case f of
155+ Var (_, _, _, Just IsNewtype) _ -> return (head args')
156+ _ -> flip (foldl (\fn a -> AST.App Nothing fn [a])) args' <$> valueToIL f
157+ where
158+ unApp :: Expr Ann -> [Expr Ann] -> (Expr Ann, [Expr Ann])
159+ unApp (App _ val arg) args = unApp val (arg : args)
160+ unApp other args = (other, args)
161+ valueToIL (Var _ ident) = return $ varToIL ident
162+ valueToIL (Case (ss, _, _, _) values binders) = do
163+ vals <- mapM valueToIL values
164+ bindersToIL ss binders vals
165+ valueToIL (Let _ ds val) = do
166+ let recurs = concatMap getNames $ filter isRec ds
167+ recurDs = (\v -> AST.VariableIntroduction Nothing (identToIL v) Nothing) <$> recurs
168+ ds' <- concat <$> mapM (bindToIL LetDecl) ds
169+ ret <- valueToIL val
170+ return $ AST.App Nothing (AST.Function Nothing Nothing [] (AST.Block Nothing (recurDs ++ ds' ++ [AST.Return Nothing ret]))) []
171+ where
172+ isRec :: Bind Ann -> Bool
173+ isRec (Rec _) = True
174+ isRec _ = False
175+ valueToIL (Constructor (_, _, _, Just IsNewtype) _ (ProperName ctor) _) = error "IsNewtype"
176+ valueToIL (Constructor _ _ (ProperName ctor) fields) =
177+ let body = AST.ObjectLiteral Nothing $ (mkString ctor, AST.BooleanLiteral Nothing True) :
178+ ((\field -> (mkString (identToIL field), var field)) `map` fields)
179+ fn = foldr (\f inner -> AST.Function Nothing Nothing [identToIL f] (AST.Block Nothing [AST.Return Nothing inner])) body fields
180+ in return fn
181+
182+
183+ iife :: Text -> [AST] -> AST
184+ iife v exprs = AST.App Nothing (AST.Function Nothing Nothing [] (AST.Block Nothing $ exprs ++ [AST.Return Nothing $ AST.Var Nothing v])) []
185+
186+ literalToValueIL :: SourceSpan -> Literal (Expr Ann) -> m AST
187+ literalToValueIL ss (NumericLiteral (Left i)) = return $ AST.NumericLiteral (Just ss) (Left i)
188+ literalToValueIL ss (NumericLiteral (Right n)) = return $ AST.NumericLiteral (Just ss) (Right n)
189+ literalToValueIL ss (StringLiteral s) = return $ AST.StringLiteral (Just ss) s
190+ literalToValueIL ss (CharLiteral c) = return $ AST.StringLiteral (Just ss) (fromString [c])
191+ literalToValueIL ss (BooleanLiteral b) = return $ AST.BooleanLiteral (Just ss) b
192+ literalToValueIL ss (ArrayLiteral xs) = AST.ArrayLiteral (Just ss) <$> mapM valueToIL xs
193+ literalToValueIL ss (ObjectLiteral ps) = AST.ObjectLiteral (Just ss) <$> mapM (sndM valueToIL) ps
194+
195+ -- | Generate code in the simplified intermediate representation for a reference to a
196+ -- variable.
197+ varToIL :: Qualified Ident -> AST
198+ varToIL (Qualified Nothing ident) = var ident
199+ varToIL qual = qualifiedToIL id qual
200+
201+ -- | Generate code in the simplified intermediate representation for a reference to a
202+ -- variable that may have a qualified name.
203+ qualifiedToIL :: (a -> Ident) -> Qualified a -> AST
204+ qualifiedToIL f (Qualified (Just (ModuleName mn')) a) | mn' == C.prim = AST.Var Nothing . moduleIdentToIL $ f a
205+ qualifiedToIL f (Qualified (Just mn') a) | mn /= mn' = AST.Indexer Nothing (AST.Var Nothing . moduleIdentToIL $ f a) (AST.Var Nothing (moduleNameToIL mn'))
206+ qualifiedToIL f (Qualified _ a) = AST.Indexer Nothing (AST.Var Nothing . moduleIdentToIL $ f a) (AST.Var Nothing "")
207+
208+ -- foreignIdent :: Ident -> AST
209+ -- foreignIdent ident = accessorString (mkString $ runIdent ident) (AST.Var Nothing "$foreign")
210+
211+ -- | Generate code in the simplified intermediate representation for pattern match binders
212+ -- and guards.
213+ bindersToIL :: SourceSpan -> [CaseAlternative Ann] -> [AST] -> m AST
214+ bindersToIL ss binders vals = do
215+ valNames <- replicateM (length vals) freshName'
216+ let assignments = zipWith (AST.VariableIntroduction Nothing) valNames (map Just vals)
217+ ils <- forM binders $ \(CaseAlternative bs result) -> do
218+ ret <- guardsToIL result
219+ go valNames ret bs
220+ return $ AST.App Nothing (AST.Function Nothing Nothing [] (AST.Block Nothing (assignments ++ concat ils ++ [AST.Throw Nothing (AST.StringLiteral Nothing $ mkString failedPatternMessage)])))
221+ []
222+ where
223+ go :: [Text] -> [AST] -> [Binder Ann] -> m [AST]
224+ go _ done [] = return done
225+ go (v:vs) done' (b:bs) = do
226+ done'' <- go vs done' bs
227+ binderToIL v done'' b
228+ go _ _ _ = internalError "Invalid arguments to bindersToIL"
229+
230+ failedPatternMessage :: Text
231+ failedPatternMessage = "Failed pattern match at " <> runModuleName mn <> " " <> displayStartEndPos ss
232+
233+ guardsToIL :: Either [(Guard Ann, Expr Ann)] (Expr Ann) -> m [AST]
234+ guardsToIL (Left gs) = traverse genGuard gs where
235+ genGuard (cond, val) = do
236+ cond' <- valueToIL cond
237+ val' <- valueToIL val
238+ return
239+ (AST.IfElse Nothing (AST.Binary Nothing AST.EqualTo cond' (AST.BooleanLiteral Nothing True))
240+ (AST.Block Nothing [AST.Return Nothing val']) Nothing)
241+
242+ guardsToIL (Right v) = return . AST.Return Nothing <$> valueToIL v
243+
244+ -- | Generate code in the simplified intermediate representation for a pattern match
245+ -- binder.
246+ binderToIL :: Text -> [AST] -> Binder Ann -> m [AST]
247+ binderToIL _ done NullBinder{} = return done
248+ binderToIL varName done (LiteralBinder _ l) =
249+ literalToBinderIL varName done l
250+ binderToIL varName done (VarBinder _ ident) =
251+ return (AST.VariableIntroduction Nothing (identToIL ident) (Just (AST.Var Nothing varName)) : done)
252+ binderToIL varName done (ConstructorBinder (_, _, _, Just IsNewtype) _ _ [b]) =
253+ binderToIL varName done b
254+ binderToIL varName done (ConstructorBinder (_, _, _, Just (IsConstructor ctorType fields)) _ (Qualified _ (ProperName ctor)) bs) = do
255+ il <- go (zip fields bs) done
256+ return $ case ctorType of
257+ ProductType -> il
258+ SumType ->
259+ [AST.IfElse Nothing (AST.InstanceOf Nothing (AST.Var Nothing varName) (AST.StringLiteral Nothing (mkString ctor)))
260+ (AST.Block Nothing il)
261+ Nothing]
262+ where
263+ go :: [(Ident, Binder Ann)] -> [AST] -> m [AST]
264+ go [] done' = return done'
265+ go ((field, binder) : remain) done' = do
266+ argVar <- freshName'
267+ done'' <- go remain done'
268+ il <- binderToIL argVar done'' binder
269+ return (AST.VariableIntroduction Nothing argVar (Just $ accessorString (mkString $ identToIL field) $ AST.Var Nothing varName) : il)
270+
271+ binderToIL _ _ ConstructorBinder{} =
272+ internalError "binderToIL: Invalid ConstructorBinder in binderToIL"
273+ binderToIL varName done (NamedBinder _ ident binder) = do
274+ il <- binderToIL varName done binder
275+ return (AST.VariableIntroduction Nothing (identToIL ident) (Just (AST.Var Nothing varName)) : il)
276+
277+ literalToBinderIL :: Text -> [AST] -> Literal (Binder Ann) -> m [AST]
278+ literalToBinderIL varName done (NumericLiteral num) =
279+ return [AST.IfElse Nothing (AST.Binary Nothing AST.EqualTo (AST.Var Nothing varName) (AST.NumericLiteral Nothing num)) (AST.Block Nothing done) Nothing]
280+ literalToBinderIL varName done (CharLiteral c) =
281+ return [AST.IfElse Nothing (AST.Binary Nothing AST.EqualTo (AST.Var Nothing varName) (AST.StringLiteral Nothing (fromString [c]))) (AST.Block Nothing done) Nothing]
282+ literalToBinderIL varName done (StringLiteral str) =
283+ return [AST.IfElse Nothing (AST.Binary Nothing AST.EqualTo (AST.Var Nothing varName) (AST.StringLiteral Nothing str)) (AST.Block Nothing done) Nothing]
284+ literalToBinderIL varName done (BooleanLiteral True) =
285+ return [AST.IfElse Nothing (AST.Binary Nothing AST.EqualTo (AST.Var Nothing varName) (AST.BooleanLiteral Nothing True)) (AST.Block Nothing done) Nothing]
286+ literalToBinderIL varName done (BooleanLiteral False) =
287+ return [AST.IfElse Nothing (AST.Binary Nothing AST.EqualTo (AST.Var Nothing varName) (AST.BooleanLiteral Nothing False)) (AST.Block Nothing done) Nothing]
288+ -- return [AST.IfElse Nothing (AST.Unary Nothing AST.Not (AST.Var Nothing varName)) (AST.Block Nothing done) Nothing]
289+ literalToBinderIL varName done (ObjectLiteral bs) = go done bs
290+ where
291+ go :: [AST] -> [(PSString, Binder Ann)] -> m [AST]
292+ go done' [] = return done'
293+ go done' ((prop, binder):bs') = do
294+ propVar <- freshName'
295+ done'' <- go done' bs'
296+ il <- binderToIL propVar done'' binder
297+ return (AST.VariableIntroduction Nothing propVar (Just (accessorString prop (AST.Var Nothing varName))) : il)
298+ literalToBinderIL varName done (ArrayLiteral bs) = do
299+ il <- go done 0 bs
300+ return [AST.IfElse Nothing (AST.Binary Nothing AST.EqualTo
301+ (arrayLength $ AST.Var Nothing varName)
302+ (AST.NumericLiteral Nothing (Left (fromIntegral $ length bs))))
303+ (AST.Block Nothing il) Nothing]
304+ where
305+ go :: [AST] -> Integer -> [Binder Ann] -> m [AST]
306+ go done' _ [] = return done'
307+ go done' index (binder:bs') = do
308+ elVar <- freshName'
309+ done'' <- go done' (index + 1) bs'
310+ il <- binderToIL elVar done'' binder
311+ return (AST.VariableIntroduction Nothing elVar (Just (AST.Indexer Nothing (AST.NumericLiteral Nothing (Left index)) (AST.Var Nothing varName))) : il)
312+
313+emptyAnn :: Ann
314+emptyAnn = (SourceSpan "" (SourcePos 0 0) (SourcePos 0 0), [], Nothing, Nothing)
315+
316+arrayLength :: AST -> AST
317+arrayLength a = AST.App Nothing (AST.Var Nothing arrayLengthFn) [a]
318+-- arrayLength a = AST.Var Nothing (arrayLengthFn <> "(" <> prettyPrintIL1 a <> ")")
319+
320+copyDict :: AST -> AST
321+copyDict a = AST.App Nothing (AST.Var Nothing copyDictFn) [a]
src/CodeGen/IL/Common.hsnew file+196
@@ -0,0 +1,196 @@
1+-- | Common code generation utility functions
2+module CodeGen.IL.Common where
3+
4+import Prelude.Compat
5+
6+import Control.Monad.Supply.Class (MonadSupply, freshName)
7+import Data.Char
8+import Data.Maybe (maybe)
9+import Data.Monoid ((<>))
10+import Data.Text (Text)
11+import qualified Data.Text as T
12+
13+import Language.PureScript.Crash
14+import Language.PureScript.Names
15+
16+import qualified Language.PureScript.Constants as C
17+
18+moduleNameToIL :: ModuleName -> Text
19+moduleNameToIL (ModuleName mn) =
20+ let name = T.replace "." "_" mn
21+ in if nameIsILBuiltIn name then (name <> moduleRenamerMarker) else name
22+
23+moduleNameToIL' :: ModuleName -> Text
24+moduleNameToIL' (ModuleName mn) = T.replace "_" "." mn
25+
26+-- | Convert an 'Ident' into a valid IL identifier:
27+--
28+-- * Alphanumeric characters are kept unmodified.
29+--
30+-- * Reserved IL identifiers are wrapped with '_'.
31+--
32+identToIL :: Ident -> Text
33+identToIL UnusedIdent = unusedName
34+identToIL (Ident "$__unused") = unusedName
35+identToIL (Ident name) | name == C.undefined = undefinedName -- Note: done in Printer.hs too
36+identToIL (Ident name) = properToIL name
37+identToIL (GenIdent _ _) = internalError "GenIdent in identToIL"
38+
39+moduleIdentToIL :: Ident -> Text
40+moduleIdentToIL UnusedIdent = unusedName
41+moduleIdentToIL (Ident name) | name == C.undefined = undefinedName
42+moduleIdentToIL (Ident name) = moduleProperToIL name
43+moduleIdentToIL (GenIdent _ _) = internalError "GenIdent in identToIL"
44+
45+undefinedName :: Text
46+undefinedName = "Undefined"
47+
48+unusedName :: Text
49+unusedName = "_"
50+
51+properToIL :: Text -> Text
52+properToIL name
53+ | nameIsILReserved name = "ˉ" <> name
54+ | otherwise = T.concatMap identCharToText name
55+
56+-- | Attempts to find a human-readable name for a symbol, if none has been specified returns the
57+-- ordinal value.
58+identCharToText :: Char -> Text
59+identCharToText 'ṩ' = "_ṩ"
60+identCharToText c | isAlphaNum c = T.singleton c
61+identCharToText '_' = "_"
62+identCharToText '\'' = "ꞌ" -- lowercase saltillo
63+identCharToText c = error (show (ord c)) -- TODO: should never occur now(?)
64+
65+moduleProperToIL :: Text -> Text
66+moduleProperToIL = T.concatMap identCharToText
67+
68+-- | Checks whether an identifier name is reserved in IL.
69+nameIsILReserved :: Text -> Bool
70+nameIsILReserved name =
71+ name `elem` ilAnyReserved
72+
73+-- | Checks whether a name matches a built-in value in IL.
74+nameIsILBuiltIn :: Text -> Bool
75+nameIsILBuiltIn name =
76+ name `elem`
77+ [ "Any"
78+ , "Apply"
79+ , "Contains"
80+ , "CopyDict"
81+ , "Dict"
82+ , "EffFn"
83+ , "Fn"
84+ , "Foreign"
85+ , "Get"
86+ , "Index"
87+ , "Is"
88+ , "Length"
89+ , "Once"
90+ , "Run"
91+ , "Undefined"
92+ ]
93+
94+ilAnyReserved :: [Text]
95+ilAnyReserved =
96+ concat
97+ [ ilKeywords
98+ , ilLiterals
99+ ]
100+
101+ilKeywords :: [Text]
102+ilKeywords =
103+ [ "break"
104+ , "case"
105+ , "chan"
106+ , "const"
107+ , "continue"
108+ , "default"
109+ , "defer"
110+ , "else"
111+ , "fallthrough"
112+ , "for"
113+ , "func"
114+ , "go"
115+ , "goto"
116+ , "if"
117+ , "import"
118+ , "interface"
119+ , "map"
120+ , "package"
121+ , "range"
122+ , "return"
123+ , "select"
124+ , "struct"
125+ , "switch"
126+ , "type"
127+ , "var"
128+ ]
129+
130+ilLiterals :: [Text]
131+ilLiterals =
132+ [ "init"
133+ , "nil"
134+ , "int"
135+ , "int8"
136+ , "int16"
137+ , "int32"
138+ , "int64"
139+ , "uint"
140+ , "uint8"
141+ , "uint16"
142+ , "uint32"
143+ , "uint64"
144+ , "uintptr"
145+ , "float32"
146+ , "float64"
147+ , "complex64"
148+ , "complex128"
149+ , "byte"
150+ , "rune"
151+ , "string"
152+ ]
153+
154+withPrefix :: Text -> Text
155+withPrefix s = "Ꞌ" <> s -- uppercase saltillo
156+
157+anyType :: Text
158+anyType = "Any"
159+
160+dictType :: Text
161+dictType = "Dict"
162+
163+arrayType :: Text
164+arrayType = "[]" <> anyType
165+
166+uncurriedFnType :: Int -> Text
167+uncurriedFnType i = "Fn" <> (T.pack . show $ i)
168+
169+int :: Text
170+int = "int"
171+
172+float :: Text
173+float = "float64"
174+
175+bool :: Text
176+bool = "bool"
177+
178+string :: Text
179+string = "string"
180+
181+arrayLengthFn :: Text
182+arrayLengthFn = "Length"
183+
184+indexFn :: Text
185+indexFn = "Index"
186+
187+copyDictFn :: Text
188+copyDictFn = "CopyDict"
189+
190+freshName' :: MonadSupply m => m Text
191+freshName' = do
192+ name <- freshName
193+ return $ T.replace "$" "ṩ" name
194+
195+moduleRenamerMarker :: Text
196+moduleRenamerMarker = "__"
src/CodeGen/IL/Optimizer.hsnew file+81
@@ -0,0 +1,81 @@
1+-- | This module optimizes code in the intermediate representation.
2+module CodeGen.IL.Optimizer (optimize) where
3+
4+import Prelude.Compat
5+
6+import Control.Monad.Supply.Class (MonadSupply)
7+import Data.Text (Text)
8+import Language.PureScript.CoreImp.AST
9+import Language.PureScript.CoreImp.Optimizer.Blocks
10+import Language.PureScript.CoreImp.Optimizer.Common hiding (isDict)
11+import Language.PureScript.CoreImp.Optimizer.Inliner (etaConvert, evaluateIifes, inlineVariables, unThunk)
12+import Language.PureScript.CoreImp.Optimizer.Unused
13+
14+import CodeGen.IL.Common (unusedName)
15+import CodeGen.IL.Optimizer.Inliner
16+import CodeGen.IL.Optimizer.MagicDo
17+import CodeGen.IL.Optimizer.TCO
18+
19+import qualified Language.PureScript.Constants as C
20+
21+-- | Apply a series of optimizer passes to simplified IL code
22+optimize :: MonadSupply m => AST -> AST -> m AST
23+optimize mn il = do
24+ il' <- untilFixedPoint (inlineFnComposition . inlineUnsafeCoerce . inlineUnsafePartial . tidyUp) il
25+ il'' <- untilFixedPoint (return . ignoreUnusedResults . inlineCommonValues . inlineCommonOperators . tidyUp) . tco mn . inlineST
26+ =<< untilFixedPoint (return . magicDoST)
27+ =<< untilFixedPoint (return . magicDoEff)
28+ =<< untilFixedPoint (return . magicDoEffect) il'
29+ untilFixedPoint (return . collapseVarDeclarations) il''
30+ where
31+ tidyUp :: AST -> AST
32+ tidyUp = applyAll
33+ [ collapseNestedBlocks
34+ , collapseNestedIfs
35+ , collapseIfChecks
36+ , removeCodeAfterReturnStatements
37+ , unThunk
38+ , etaConvert
39+ , evaluateIifes
40+ , inlineVariables
41+ ]
42+
43+untilFixedPoint :: (Monad m, Eq a) => (a -> m a) -> a -> m a
44+untilFixedPoint f = go
45+ where
46+ go a = do
47+ a' <- f a
48+ if a' == a then return a' else go a'
49+
50+collapseIfChecks :: AST -> AST
51+collapseIfChecks = everywhere collapse where
52+ collapse :: AST -> AST
53+ collapse (IfElse _ (Binary _ EqualTo (BooleanLiteral _ True) (BooleanLiteral _ True)) (Block _ [exprs]) _) = exprs
54+ collapse (IfElse _ (Binary _ EqualTo (Indexer _ (Var _ prop) (Var _ val)) (BooleanLiteral _ True)) (Block _ [exprs]) _)
55+ | prop == "otherwise" && val == "Data_Boolean" = exprs
56+ collapse exprs = exprs
57+
58+collapseVarDeclarations :: AST -> AST
59+collapseVarDeclarations = everywhere collapse where
60+ collapse :: AST -> AST
61+ collapse (Block ss sts) = Block ss (go Nothing sts)
62+ collapse s = s
63+
64+ go :: Maybe Text -> [AST] -> [AST]
65+ go _ [] = []
66+ go Nothing (decl@(VariableIntroduction _ var (Just _)) : sts) = decl : go (Just var) (go Nothing sts)
67+ go (Just var') ((VariableIntroduction ss var (Just val)) : sts)
68+ | var == var' = (Assignment ss (Var Nothing var) val) : go (Just var') sts
69+ go var' (s:sts) = s : go var' sts
70+
71+ignoreUnusedResults :: AST -> AST
72+ignoreUnusedResults = everywhere $ removeFromBlock go
73+ where
74+ go :: [AST] -> [AST]
75+ go [] = []
76+ go (VariableIntroduction ss var (Just s) : sts)
77+ | not $ any (everything (||) (isUsed var)) sts = sts'
78+ where
79+ sts' | App{} <- s = s : (go sts)
80+ | otherwise = go sts
81+ go (s:sts) = s : go sts
src/CodeGen/IL/Optimizer/Common.hsnew file+18
@@ -0,0 +1,18 @@
1+-- | Common functions used by the various optimizer phases
2+module CodeGen.IL.Optimizer.Common where
3+
4+import Prelude.Compat
5+
6+import Data.Text (Text)
7+
8+import Language.PureScript.CoreImp.AST
9+import Language.PureScript.PSString (PSString, decodeString)
10+
11+isDict :: (Text, PSString) -> AST -> Bool
12+isDict (moduleName, dictName) (Indexer _ (Var _ x) (Var _ y)) =
13+ Just x == decodeString dictName && y == moduleName
14+isDict _ _ = False
15+
16+isDict' :: [(Text, PSString)] -> AST -> Bool
17+isDict' xs il = any (`isDict` il) xs
18+
src/CodeGen/IL/Optimizer/Inliner.hsnew file+435
@@ -0,0 +1,435 @@
1+-- | This module performs basic inlining of known functions
2+module CodeGen.IL.Optimizer.Inliner
3+ ( inlineCommonValues
4+ , inlineCommonOperators
5+ , inlineFnComposition
6+ , inlineUnsafeCoerce
7+ , inlineUnsafePartial
8+ ) where
9+
10+import Prelude.Compat
11+
12+import Control.Monad.Supply.Class (MonadSupply)
13+
14+import Data.Either (rights)
15+import Data.Maybe (fromMaybe)
16+import Data.String (IsString, fromString)
17+import Data.Text (Text)
18+import qualified Data.Text as T
19+
20+import Language.PureScript.PSString (PSString, decodeString, mkString)
21+import Language.PureScript.CoreImp.AST
22+import Language.PureScript.CoreImp.Optimizer.Common hiding (isDict, isDict')
23+import Language.PureScript.AST (SourceSpan(..))
24+import qualified Language.PureScript.Constants as C
25+
26+import CodeGen.IL.Common
27+import CodeGen.IL.Optimizer.Common
28+
29+-- TODO: Potential bug:
30+-- Shouldn't just inline this case: { var x = 0; x.toFixed(10); }
31+-- Needs to be: { 0..toFixed(10); }
32+-- Probably needs to be fixed in pretty-printer instead.
33+shouldInline :: AST -> Bool
34+shouldInline (Var _ _) = True
35+shouldInline (NumericLiteral _ _) = True
36+shouldInline (StringLiteral _ _) = True
37+shouldInline (BooleanLiteral _ _) = True
38+shouldInline (Indexer _ index val) = shouldInline index && shouldInline val
39+shouldInline _ = False
40+
41+inlineCommonValues :: AST -> AST
42+inlineCommonValues = everywhere convert
43+ where
44+ convert :: AST -> AST
45+ convert (App ss fn [dict])
46+ | isDict' [semiringNumber, semiringInt] dict && isDict fnZero fn = NumericLiteral ss (Left 0)
47+ | isDict' [semiringNumber, semiringInt] dict && isDict fnOne fn = NumericLiteral ss (Left 1)
48+ | isDict boundedBoolean dict && isDict fnBottom fn = BooleanLiteral ss False
49+ | isDict boundedBoolean dict && isDict fnTop fn = BooleanLiteral ss True
50+ convert (App ss (App _ fn [dict]) [x])
51+ | isDict ringInt dict && isDict fnNegate fn = Unary ss Negate (unbox x $ snd ringInt)
52+ convert (App ss (App _ (App _ fn [dict]) [x]) [y])
53+ | isDict semiringInt dict && isDict fnAdd fn = intOp ss Add semiringInt x y
54+ | isDict semiringInt dict && isDict fnMultiply fn = intOp ss Multiply semiringInt x y
55+ | isDict ringInt dict && isDict fnSubtract fn = intOp ss Subtract ringInt x y
56+ convert other = other
57+ fnZero = (C.dataSemiring, C.zero)
58+ fnOne = (C.dataSemiring, C.one)
59+ fnBottom = (C.dataBounded, C.bottom)
60+ fnTop = (C.dataBounded, C.top)
61+ fnAdd = (C.dataSemiring, C.add)
62+ fnMultiply = (C.dataSemiring, C.mul)
63+ fnSubtract = (C.dataRing, C.sub)
64+ fnNegate = (C.dataRing, C.negate)
65+ intOp ss op (_, d) x y = Binary ss op (unbox x d) (unbox y d)
66+
67+inlineCommonOperators :: AST -> AST
68+inlineCommonOperators = everywhereTopDown $ applyAll $
69+ [ binary semiringNumber opAdd Add
70+ , binary semiringNumber opMul Multiply
71+
72+ , binary ringNumber opSub Subtract
73+ , unary ringNumber opNegate Negate
74+
75+ , binary euclideanRingNumber opDiv Divide
76+
77+ -- , binary eqNumber opEq EqualTo
78+ -- , binary eqNumber opNotEq NotEqualTo
79+ , binary eqInt opEq EqualTo
80+ , binary eqInt opNotEq NotEqualTo
81+ , binary eqString opEq EqualTo
82+ , binary eqString opNotEq NotEqualTo
83+ , binary eqChar opEq EqualTo
84+ , binary eqChar opNotEq NotEqualTo
85+ , binary eqBoolean opEq EqualTo
86+ , binary eqBoolean opNotEq NotEqualTo
87+
88+ , binary ordBoolean opLessThan LessThan
89+ , binary ordBoolean opLessThanOrEq LessThanOrEqualTo
90+ , binary ordBoolean opGreaterThan GreaterThan
91+ , binary ordBoolean opGreaterThanOrEq GreaterThanOrEqualTo
92+ , binary ordChar opLessThan LessThan
93+ , binary ordChar opLessThanOrEq LessThanOrEqualTo
94+ , binary ordChar opGreaterThan GreaterThan
95+ , binary ordChar opGreaterThanOrEq GreaterThanOrEqualTo
96+ , binary ordInt opLessThan LessThan
97+ , binary ordInt opLessThanOrEq LessThanOrEqualTo
98+ , binary ordInt opGreaterThan GreaterThan
99+ , binary ordInt opGreaterThanOrEq GreaterThanOrEqualTo
100+ , binary ordNumber opLessThan LessThan
101+ , binary ordNumber opLessThanOrEq LessThanOrEqualTo
102+ , binary ordNumber opGreaterThan GreaterThan
103+ , binary ordNumber opGreaterThanOrEq GreaterThanOrEqualTo
104+ , binary ordString opLessThan LessThan
105+ , binary ordString opLessThanOrEq LessThanOrEqualTo
106+ , binary ordString opGreaterThan GreaterThan
107+ , binary ordString opGreaterThanOrEq GreaterThanOrEqualTo
108+
109+ , binary semigroupString opAppend Add
110+
111+ , binary heytingAlgebraBoolean opConj And
112+ , binary heytingAlgebraBoolean opDisj Or
113+ , unary heytingAlgebraBoolean opNot Not
114+
115+ , binary' C.dataIntBits C.or BitwiseOr
116+ , binary' C.dataIntBits C.and BitwiseAnd
117+ , binary' C.dataIntBits C.xor BitwiseXor
118+ , binary' C.dataIntBits C.shl ShiftLeft
119+ , binary' C.dataIntBits C.shr ShiftRight
120+ , unary' C.dataIntBits C.complement BitwiseNot
121+
122+ , inlineNonClassFunction (isModFn (C.dataFunction, C.apply)) $ \f x -> App Nothing f [x]
123+ , inlineNonClassFunction (isModFn (C.dataFunction, C.applyFlipped)) $ \x f -> App Nothing f [x]
124+ , inlineUnsafeIndex (isModFnWithDict (C.dataArray, C.unsafeIndex)) $ flip (Indexer Nothing)
125+ ] ++
126+ [ fn | i <- [0..10], fn <- [ mkFn i, runFn i ] ] ++
127+ [ fn | i <- [0..10], fn <- [ mkEffFn C.controlMonadEffUncurried C.mkEffFn i, runEffFn C.controlMonadEffUncurried C.runEffFn i ] ] ++
128+ [ fn | i <- [0..10], fn <- [ mkEffFn C.effectUncurried C.mkEffectFn i, runEffFn C.effectUncurried C.runEffectFn i ] ]
129+ where
130+ binary :: (Text, PSString) -> (Text, PSString) -> BinaryOperator -> AST -> AST
131+ binary dict@(_, d) fns op = convert where
132+ convert :: AST -> AST
133+ convert (App ss (App _ (App _ fn [dict']) [x]) [y])
134+ | isDict dict dict' && isDict fns fn = Binary ss op (unbox x d) (unbox y d)
135+ convert other = other
136+ binary' :: Text -> PSString -> BinaryOperator -> AST -> AST
137+ binary' moduleName opString op = convert where
138+ convert :: AST -> AST
139+ convert (App ss (App _ fn [x]) [y]) | isDict (moduleName, opString) fn = Binary ss op (unbox x mn) (unbox y mn)
140+ convert other = other
141+ mn :: PSString
142+ mn = mkString moduleName
143+ unary :: (Text, PSString) -> (Text, PSString) -> UnaryOperator -> AST -> AST
144+ unary dicts@(_, d) fns op = convert where
145+ convert :: AST -> AST
146+ convert (App ss (App _ fn [dict']) [x]) | isDict dicts dict' && isDict fns fn = Unary ss op (unbox x d)
147+ convert other = other
148+ unary' :: Text -> PSString -> UnaryOperator -> AST -> AST
149+ unary' moduleName fnName op = convert where
150+ convert :: AST -> AST
151+ convert (App ss fn [x]) | isDict (moduleName, fnName) fn = Unary ss op (unbox x fnName)
152+ convert other = other
153+
154+ mkFn :: Int -> AST -> AST
155+ mkFn = mkFn' C.dataFunctionUncurried C.mkFn $ \ss1 ss2 ss3 args il ->
156+ Function ss1 Nothing args (Block ss2 [Return ss3 il])
157+
158+ mkEffFn :: Text -> Text -> Int -> AST -> AST
159+ mkEffFn modName fnName = mkFn' modName fnName $ \ss1 ss2 ss3 args il ->
160+ Function ss1 Nothing args (Block ss2 [Return ss3 (App ss3 il [])])
161+
162+ mkFn' :: Text -> Text -> (Maybe SourceSpan -> Maybe SourceSpan -> Maybe SourceSpan -> [Text] -> AST -> AST) -> Int -> AST -> AST
163+ mkFn' modName fnName res 0 = convert where
164+ convert :: AST -> AST
165+ convert (App _ mkFnN [Function s1 Nothing [_] (Block s2 [Return s3 il])]) | isNFn modName fnName 0 mkFnN =
166+ res s1 s2 s3 [] il
167+ convert other = other
168+ mkFn' modName fnName res n = convert where
169+ convert :: AST -> AST
170+ convert orig@(App ss mkFnN [fn]) | isNFn modName fnName n mkFnN =
171+ case collectArgs n [] fn of
172+ Just (args, [Return ss' ret]) -> res ss ss ss' args ret
173+ _ -> orig
174+ convert other = other
175+ collectArgs :: Int -> [Text] -> AST -> Maybe ([Text], [AST])
176+ collectArgs 1 acc (Function _ Nothing [oneArg] (Block _ il)) | length acc == n - 1 = Just (reverse (oneArg : acc), il)
177+ collectArgs m acc (Function _ Nothing [oneArg] (Block _ [Return _ ret])) = collectArgs (m - 1) (oneArg : acc) ret
178+ collectArgs _ _ _ = Nothing
179+
180+ isNFn :: Text -> Text -> Int -> AST -> Bool
181+ isNFn expectMod prefix n (Indexer _ (Var _ name) (Var _ modName)) | modName == expectMod =
182+ name == fromString (T.unpack prefix <> show n)
183+ isNFn _ _ _ _ = False
184+
185+ runFn :: Int -> AST -> AST
186+ runFn = runFn' C.dataFunctionUncurried C.runFn (\ss f args ->
187+ let len = length args
188+ typ = mkString $ uncurriedFnType len in
189+ if len > 0
190+ then App ss (App Nothing (StringLiteral Nothing typ) [f]) args
191+ else App ss f args)
192+ runEffFn :: Text -> Text -> Int -> AST -> AST
193+ runEffFn modName fnName = runFn' modName fnName $ \ss fn acc ->
194+ let typ = mkString . uncurriedFnType $ length acc in
195+ Function ss Nothing [] (Block ss [Return ss (App ss (App Nothing (StringLiteral Nothing typ) [fn]) acc)])
196+
197+ runFn' :: Text -> Text -> (Maybe SourceSpan -> AST -> [AST] -> AST) -> Int -> AST -> AST
198+ runFn' modName runFnName res n = convert where
199+ convert :: AST -> AST
200+ convert il = fromMaybe il $ go n [] il
201+
202+ go :: Int -> [AST] -> AST -> Maybe AST
203+ go 0 acc (App ss runFnN [fn]) | isNFn modName runFnName n runFnN && length acc == n =
204+ Just $ res ss fn acc
205+ go m acc (App _ lhs [arg]) = go (m - 1) (arg : acc) lhs
206+ go _ _ _ = Nothing
207+
208+ inlineNonClassFunction :: (AST -> Bool) -> (AST -> AST -> AST) -> AST -> AST
209+ inlineNonClassFunction p f = convert where
210+ convert :: AST -> AST
211+ convert (App _ (App _ op' [x]) [y]) | p op' = f x y
212+ convert other = other
213+
214+ inlineUnsafeIndex :: (AST -> Bool) -> (AST -> AST -> AST) -> AST -> AST
215+ inlineUnsafeIndex p _ = convert where
216+ convert :: AST -> AST
217+ convert (App _ (App ss op' [x]) [y@NumericLiteral{}])
218+ | p op' = Indexer ss y x
219+ convert (App _ (App ss op' [x]) [y])
220+ | p op' = App ss (Var Nothing indexFn) [x, y]
221+ convert other = other
222+
223+ isModFn :: (Text, PSString) -> AST -> Bool
224+ isModFn (m, op) (Indexer _ (Var _ op') (Var _ m')) =
225+ m == m' && decodeString op == Just op'
226+ isModFn _ _ = False
227+
228+ isModFnWithDict :: (Text, PSString) -> AST -> Bool
229+ isModFnWithDict (m, op) (App _ (Indexer _ (Var _ op') (Var _ m')) [Var _ _]) =
230+ m == m' && decodeString op == Just op'
231+ isModFnWithDict _ _ = False
232+
233+-- (f <<< g $ x) = f (g x)
234+-- (f <<< g) = \x -> f (g x)
235+inlineFnComposition :: forall m. MonadSupply m => AST -> m AST
236+inlineFnComposition = everywhereTopDownM convert where
237+ convert :: AST -> m AST
238+ convert (App s1 (App s2 (App _ (App _ fn [dict']) [x]) [y]) [z])
239+ | isFnCompose dict' fn = return $ App s1 x [App s2 y [z]]
240+ | isFnComposeFlipped dict' fn = return $ App s2 y [App s1 x [z]]
241+ convert app@(App ss (App _ (App _ fn [dict']) _) _)
242+ | isFnCompose dict' fn || isFnComposeFlipped dict' fn = mkApps ss <$> goApps app <*> freshName'
243+ convert other = return other
244+
245+ mkApps :: Maybe SourceSpan -> [Either AST (Text, AST)] -> Text -> AST
246+ mkApps ss fns a = App ss (Function ss Nothing [] (Block ss $ vars <> [Return Nothing comp])) []
247+ where
248+ vars = uncurry (VariableIntroduction ss) . fmap Just <$> rights fns
249+ comp = Function ss Nothing [a] (Block ss [Return Nothing apps])
250+ apps = foldr (\fn acc -> App ss (mkApp fn) [acc]) (Var ss a) fns
251+
252+ mkApp :: Either AST (Text, AST) -> AST
253+ mkApp = either id $ \(name, arg) -> Var (getSourceSpan arg) name
254+
255+ goApps :: AST -> m [Either AST (Text, AST)]
256+ goApps (App _ (App _ (App _ fn [dict']) [x]) [y])
257+ | isFnCompose dict' fn = mappend <$> goApps x <*> goApps y
258+ | isFnComposeFlipped dict' fn = mappend <$> goApps y <*> goApps x
259+ goApps app@(App {}) = pure . Right . (,app) <$> freshName'
260+ goApps other = pure [Left other]
261+
262+ isFnCompose :: AST -> AST -> Bool
263+ isFnCompose dict' fn = isDict semigroupoidFn dict' && isDict fnCompose fn
264+
265+ isFnComposeFlipped :: AST -> AST -> Bool
266+ isFnComposeFlipped dict' fn = isDict semigroupoidFn dict' && isDict fnComposeFlipped fn
267+
268+ fnCompose :: forall a b. (IsString a, IsString b) => (a, b)
269+ fnCompose = (C.controlSemigroupoid, C.compose)
270+
271+ fnComposeFlipped :: forall a b. (IsString a, IsString b) => (a, b)
272+ fnComposeFlipped = (C.controlSemigroupoid, C.composeFlipped)
273+
274+inlineUnsafeCoerce :: AST -> AST
275+inlineUnsafeCoerce = everywhereTopDown convert where
276+ convert (App _ (Indexer _ (Var _ unsafeCoerceFn) (Var _ unsafeCoerce)) [ comp ])
277+ | unsafeCoerceFn == C.unsafeCoerceFn && unsafeCoerce == C.unsafeCoerce
278+ = comp
279+ convert other = other
280+
281+inlineUnsafePartial :: AST -> AST
282+inlineUnsafePartial = everywhereTopDown convert where
283+ convert (App ss fn [ comp ])
284+ | isDict fnUnsafePartial fn
285+ = App ss comp []
286+ where
287+ fnUnsafePartial :: forall a b. (IsString a, IsString b) => (a, b)
288+ fnUnsafePartial = (C.partialUnsafe, C.unsafePartial)
289+ convert other = other
290+
291+semiringNumber :: forall a b. (IsString a, IsString b) => (a, b)
292+semiringNumber = (C.dataSemiring, C.semiringNumber)
293+
294+semiringInt :: forall a b. (IsString a, IsString b) => (a, b)
295+semiringInt = (C.dataSemiring, C.semiringInt)
296+
297+ringNumber :: forall a b. (IsString a, IsString b) => (a, b)
298+ringNumber = (C.dataRing, C.ringNumber)
299+
300+ringInt :: forall a b. (IsString a, IsString b) => (a, b)
301+ringInt = (C.dataRing, C.ringInt)
302+
303+euclideanRingNumber :: forall a b. (IsString a, IsString b) => (a, b)
304+euclideanRingNumber = (C.dataEuclideanRing, C.euclideanRingNumber)
305+
306+-- eqNumber :: forall a b. (IsString a, IsString b) => (a, b)
307+-- eqNumber = (C.dataEq, C.eqNumber)
308+
309+eqInt :: forall a b. (IsString a, IsString b) => (a, b)
310+eqInt = (C.dataEq, C.eqInt)
311+
312+eqString :: forall a b. (IsString a, IsString b) => (a, b)
313+eqString = (C.dataEq, C.eqString)
314+
315+eqChar :: forall a b. (IsString a, IsString b) => (a, b)
316+eqChar = (C.dataEq, C.eqChar)
317+
318+eqBoolean :: forall a b. (IsString a, IsString b) => (a, b)
319+eqBoolean = (C.dataEq, C.eqBoolean)
320+
321+ordBoolean :: forall a b. (IsString a, IsString b) => (a, b)
322+ordBoolean = (C.dataOrd, C.ordBoolean)
323+
324+ordNumber :: forall a b. (IsString a, IsString b) => (a, b)
325+ordNumber = (C.dataOrd, C.ordNumber)
326+
327+ordInt :: forall a b. (IsString a, IsString b) => (a, b)
328+ordInt = (C.dataOrd, C.ordInt)
329+
330+ordString :: forall a b. (IsString a, IsString b) => (a, b)
331+ordString = (C.dataOrd, C.ordString)
332+
333+ordChar :: forall a b. (IsString a, IsString b) => (a, b)
334+ordChar = (C.dataOrd, C.ordChar)
335+
336+semigroupString :: forall a b. (IsString a, IsString b) => (a, b)
337+semigroupString = (C.dataSemigroup, C.semigroupString)
338+
339+boundedBoolean :: forall a b. (IsString a, IsString b) => (a, b)
340+boundedBoolean = (C.dataBounded, C.boundedBoolean)
341+
342+heytingAlgebraBoolean :: forall a b. (IsString a, IsString b) => (a, b)
343+heytingAlgebraBoolean = (C.dataHeytingAlgebra, C.heytingAlgebraBoolean)
344+
345+semigroupoidFn :: forall a b. (IsString a, IsString b) => (a, b)
346+semigroupoidFn = (C.controlSemigroupoid, C.semigroupoidFn)
347+
348+opAdd :: forall a b. (IsString a, IsString b) => (a, b)
349+opAdd = (C.dataSemiring, C.add)
350+
351+opMul :: forall a b. (IsString a, IsString b) => (a, b)
352+opMul = (C.dataSemiring, C.mul)
353+
354+opEq :: forall a b. (IsString a, IsString b) => (a, b)
355+opEq = (C.dataEq, C.eq)
356+
357+opNotEq :: forall a b. (IsString a, IsString b) => (a, b)
358+opNotEq = (C.dataEq, C.notEq)
359+
360+opLessThan :: forall a b. (IsString a, IsString b) => (a, b)
361+opLessThan = (C.dataOrd, C.lessThan)
362+
363+opLessThanOrEq :: forall a b. (IsString a, IsString b) => (a, b)
364+opLessThanOrEq = (C.dataOrd, C.lessThanOrEq)
365+
366+opGreaterThan :: forall a b. (IsString a, IsString b) => (a, b)
367+opGreaterThan = (C.dataOrd, C.greaterThan)
368+
369+opGreaterThanOrEq :: forall a b. (IsString a, IsString b) => (a, b)
370+opGreaterThanOrEq = (C.dataOrd, C.greaterThanOrEq)
371+
372+opAppend :: forall a b. (IsString a, IsString b) => (a, b)
373+opAppend = (C.dataSemigroup, C.append)
374+
375+opSub :: forall a b. (IsString a, IsString b) => (a, b)
376+opSub = (C.dataRing, C.sub)
377+
378+opNegate :: forall a b. (IsString a, IsString b) => (a, b)
379+opNegate = (C.dataRing, C.negate)
380+
381+opDiv :: forall a b. (IsString a, IsString b) => (a, b)
382+opDiv = (C.dataEuclideanRing, C.div)
383+
384+opConj :: forall a b. (IsString a, IsString b) => (a, b)
385+opConj = (C.dataHeytingAlgebra, C.conj)
386+
387+opDisj :: forall a b. (IsString a, IsString b) => (a, b)
388+opDisj = (C.dataHeytingAlgebra, C.disj)
389+
390+opNot :: forall a b. (IsString a, IsString b) => (a, b)
391+opNot = (C.dataHeytingAlgebra, C.not)
392+
393+unbox :: AST -> PSString -> AST
394+unbox e d = select . inlineCommonValues $ inlineCommonOperators e
395+ where
396+ select :: AST -> AST
397+ select e' =
398+ case e' of
399+ Var{} -> unbox' e'
400+ App{} -> unbox' e'
401+ Indexer{} -> unbox' e'
402+ _ -> e'
403+ unbox' :: AST -> AST
404+ unbox' e' = maybe e' (\t -> App Nothing (StringLiteral Nothing t) [e']) $ unboxType d
405+
406+unboxType :: PSString -> Maybe PSString
407+unboxType s = do
408+ t <- decodeString s
409+ t' <- unboxType' t
410+ return $ mkString t'
411+ where
412+ unboxType' :: Text -> Maybe Text
413+ unboxType' t
414+ | t == C.eqInt ||
415+ t == C.semiringInt ||
416+ t == C.ringInt ||
417+ t == C.ordInt ||
418+ t == C.dataIntBits
419+ = Just int
420+ | t == C.semiringNumber ||
421+ t == C.ringNumber ||
422+ t == C.ordNumber ||
423+ t == C.euclideanRingNumber
424+ = Just float
425+ | t == C.eqBoolean ||
426+ t == C.ordBoolean ||
427+ t == C.heytingAlgebraBoolean
428+ = Just bool
429+ | t == C.eqChar ||
430+ t == C.eqString ||
431+ t == C.ordChar ||
432+ t == C.ordString ||
433+ t == C.semigroupString
434+ = Just string
435+ | otherwise = Nothing
src/CodeGen/IL/Optimizer/MagicDo.hsnew file+146
@@ -0,0 +1,146 @@
1+-- | This module implements the "Magic Do" optimization, which inlines calls to return
2+-- and bind for the Eff monad, as well as some of its actions.
3+module CodeGen.IL.Optimizer.MagicDo (magicDoEffect, magicDoEff, magicDoST, inlineST) where
4+
5+import Prelude.Compat
6+import Protolude (ordNub)
7+
8+import Data.Maybe (fromJust, isJust)
9+import Data.Text (Text)
10+
11+import Language.PureScript.CoreImp.AST
12+import Language.PureScript.CoreImp.Optimizer.Common hiding (isDict)
13+import Language.PureScript.PSString (PSString, decodeString, mkString)
14+import qualified Language.PureScript.Constants as C
15+
16+import CodeGen.IL.Common (undefinedName, unusedName)
17+import CodeGen.IL.Optimizer.Common
18+
19+-- | Inline type class dictionaries for >>= and return for the Eff monad
20+--
21+-- E.g.
22+--
23+-- Prelude[">>="](dict)(m1)(function(x) {
24+-- return ...;
25+-- })
26+--
27+-- becomes
28+--
29+-- function __do {
30+-- var x = m1();
31+-- ...
32+-- }
33+magicDoEff :: AST -> AST
34+magicDoEff = magicDo C.eff C.effDictionaries
35+
36+magicDoEffect :: AST -> AST
37+magicDoEffect = magicDo C.effect C.effectDictionaries
38+
39+magicDoST :: AST -> AST
40+magicDoST = magicDo C.st C.stDictionaries
41+
42+magicDo :: Text -> C.EffectDictionaries -> AST -> AST
43+magicDo effectModule C.EffectDictionaries{..} = everywhereTopDown convert
44+ where
45+ -- Desugar monomorphic calls to >>= and return for the Eff monad
46+ convert :: AST -> AST
47+ -- Desugar pure
48+ convert (App _ (App _ pure' [val]) []) | isPure pure' = val
49+ -- Desugar discard
50+ convert (App _ (App _ bind [m]) [Function s1 Nothing [unused] (Block s2 il)]) | isDiscard bind && unused == unusedName =
51+ Function s1 Nothing [] $ Block s2 (App s2 m [] : map applyReturns il )
52+ -- Desugar bind
53+ convert (App _ (App _ bind [m]) [Function s1 Nothing [arg] (Block s2 il)]) | isBind bind =
54+ Function s1 Nothing [] $ Block s2 (VariableIntroduction s2 arg (Just (App s2 m [])) : map applyReturns il)
55+ -- Desugar untilE
56+ convert (App s1 (App _ f [arg]) []) | isEffFunc edUntil f =
57+ App s1 (Function s1 Nothing [] (Block s1 [ While s1 (Unary s1 Not (App s1 arg [])) (Block s1 []), Return s1 $ ObjectLiteral s1 []])) []
58+ -- Desugar whileE
59+ convert (App _ (App _ (App s1 f [arg1]) [arg2]) []) | isEffFunc edWhile f =
60+ App s1 (Function s1 Nothing [] (Block s1 [ While s1 (App s1 arg1 []) (Block s1 [ App s1 arg2 [] ]), Return s1 $ ObjectLiteral s1 []])) []
61+ -- -- Inline __do returns
62+ -- convert (Return _ (App _ (Function _ (Just ident) [] body) [])) | ident == fnName = body
63+ -- Inline double applications
64+ convert (App _ (App s1 (Function s2 Nothing [] (Block ss body)) []) []) =
65+ App s1 (Function s2 Nothing [] (Block ss (applyReturns `fmap` body))) []
66+ convert other = other
67+ -- Check if an expression represents a monomorphic call to >>= for the Eff monad
68+ isBind (App _ fn [dict]) | isDict (effectModule, edBindDict) dict && isBindPoly fn = True
69+ isBind _ = False
70+ -- Check if an expression represents a call to @discard@
71+ isDiscard (App _ (App _ fn [dict1]) [dict2])
72+ | isDict (C.controlBind, C.discardUnitDictionary) dict1 &&
73+ isDict (effectModule, edBindDict) dict2 &&
74+ isDiscardPoly fn = True
75+ isDiscard _ = False
76+
77+ -- Check if an expression represents a monomorphic call to pure or return for the Eff applicative
78+ isPure (App _ fn [dict]) | isDict (effectModule, edApplicativeDict) dict && isPurePoly fn = True
79+ isPure _ = False
80+ -- Check if an expression represents the polymorphic >>= function
81+ isBindPoly = isDict (C.controlBind, C.bind)
82+ -- Check if an expression represents the polymorphic pure function
83+ isPurePoly = isDict (C.controlApplicative, C.pure')
84+ -- Check if an expression represents the polymorphic discard function
85+ isDiscardPoly = isDict (C.controlBind, C.discard)
86+ -- Check if an expression represents a function in the Effect module
87+ isEffFunc name (Indexer _ (StringLiteral _ name') (Var _ eff)) = eff == effectModule && name == name'
88+ isEffFunc _ _ = False
89+
90+ applyReturns :: AST -> AST
91+ applyReturns (Return ss ret) = Return ss (App ss ret [])
92+ applyReturns (Block ss ils) = Block ss (map applyReturns ils)
93+ applyReturns (While ss cond il) = While ss cond (applyReturns il)
94+ applyReturns (For ss v lo hi il) = For ss v lo hi (applyReturns il)
95+ applyReturns (ForIn ss v xs il) = ForIn ss v xs (applyReturns il)
96+ applyReturns (IfElse ss cond t f) = IfElse ss cond (applyReturns t) (applyReturns `fmap` f)
97+ applyReturns other = other
98+
99+-- | Inline functions in the ST module
100+inlineST :: AST -> AST
101+inlineST = everywhere convertBlock
102+ where
103+ -- Look for runST blocks and inline the STRefs there.
104+ -- If all STRefs are used in the scope of the same runST, only using { read, write, modify }STRef then
105+ -- we can be more aggressive about inlining, and actually turn STRefs into local variables.
106+ convertBlock (App s1 f [arg]) | isSTFunc C.runST f =
107+ let refs = ordNub . findSTRefsIn $ arg
108+ usages = findAllSTUsagesIn arg
109+ allUsagesAreLocalVars = all (\u -> let v = toVar u in isJust v && fromJust v `elem` refs) usages
110+ localVarsDoNotEscape = all (\r -> length (r `appearingIn` arg) == length (filter (\u -> let v = toVar u in v == Just r) usages)) refs
111+ in App s1 (everywhere (convert (allUsagesAreLocalVars && localVarsDoNotEscape)) arg) []
112+ convertBlock other = other
113+ -- Convert a block in a safe way, preserving object wrappers of references,
114+ -- or in a more aggressive way, turning wrappers into local variables depending on the
115+ -- agg(ressive) parameter.
116+ convert agg (App s1 f [arg]) | isSTFunc C.newSTRef f =
117+ Function s1 Nothing [] (Block s1 [Return s1 $ if agg then arg else ObjectLiteral s1 [(mkString C.stRefValue, arg)]])
118+ convert agg (App _ (App s1 f [ref]) []) | isSTFunc C.readSTRef f =
119+ if agg then ref else Indexer s1 (StringLiteral s1 C.stRefValue) ref
120+ convert agg (App _ (App _ (App s1 f [arg]) [ref]) []) | isSTFunc C.writeSTRef f =
121+ if agg then Assignment s1 ref arg else Assignment s1 (Indexer s1 (StringLiteral s1 C.stRefValue) ref) arg
122+ convert agg (App _ (App _ (App s1 f [func]) [ref]) []) | isSTFunc C.modifySTRef f =
123+ if agg then Assignment s1 ref (App s1 func [ref]) else Assignment s1 (Indexer s1 (StringLiteral s1 C.stRefValue) ref) (App s1 func [Indexer s1 (StringLiteral s1 C.stRefValue) ref])
124+ convert _ other = other
125+ -- Check if an expression represents a function in the ST module
126+ isSTFunc name (Indexer _ (StringLiteral _ name') (Var _ st)) = st == C.st && name == name'
127+ isSTFunc _ _ = False
128+ -- Find all ST Refs initialized in this block
129+ findSTRefsIn = everything (++) isSTRef
130+ where
131+ isSTRef (VariableIntroduction _ ident (Just (App _ (App _ f [_]) []))) | isSTFunc C.newSTRef f = [ident]
132+ isSTRef _ = []
133+ -- Find all STRefs used as arguments to readSTRef, writeSTRef, modifySTRef
134+ findAllSTUsagesIn = everything (++) isSTUsage
135+ where
136+ isSTUsage (App _ (App _ f [ref]) []) | isSTFunc C.readSTRef f = [ref]
137+ isSTUsage (App _ (App _ (App _ f [_]) [ref]) []) | isSTFunc C.writeSTRef f || isSTFunc C.modifySTRef f = [ref]
138+ isSTUsage _ = []
139+ -- Find all uses of a variable
140+ appearingIn ref = everything (++) isVar
141+ where
142+ isVar e@(Var _ v) | v == ref = [e]
143+ isVar _ = []
144+ -- Convert a AST value to a String if it is a Var
145+ toVar (Var _ v) = Just v
146+ toVar _ = Nothing
src/CodeGen/IL/Optimizer/TCO.hsnew file+141
@@ -0,0 +1,141 @@
1+module CodeGen.IL.Optimizer.TCO (tco, tcoLoop) where
2+
3+import Prelude.Compat
4+
5+import Data.Text (Text)
6+import Data.Monoid ((<>))
7+import Language.PureScript.CoreImp.AST
8+import Language.PureScript.AST.SourcePos (SourceSpan)
9+import Safe (headDef, tailSafe)
10+import CodeGen.IL.Common
11+
12+import qualified Language.PureScript.Constants as C
13+
14+tcoLoop :: Text
15+tcoLoop = "ṩtco_loop"
16+
17+tco :: AST -> AST -> AST
18+tco mn = everywhere convert where
19+ tcoVar :: Text -> Text
20+ tcoVar arg = "ṩtco_var_" <> arg
21+
22+ copyVar :: Text -> Text
23+ copyVar arg = "ṩcopy_" <> arg
24+
25+ tcoDone :: Text
26+ tcoDone = "ṩtco_done"
27+
28+ tcoResult :: Text
29+ tcoResult = "ṩtco_result"
30+
31+ convert :: AST -> AST
32+ convert fn@(Function ss (Just name) args _)
33+ | isTailRecursive name body'
34+ = replace (toLoop name outerArgs innerArgs body')
35+ where
36+ innerArgs = headDef [] argss
37+ outerArgs = concat . reverse $ tailSafe argss
38+ (argss, body', replace) = collectAllFunctionArgs [] id fn
39+ convert (Assignment ss (Var _ name) fn@(Function _ Nothing _ _))
40+ | isTailRecursive name body'
41+ = Assignment ss (Var ss name) (replace (toLoop name outerArgs innerArgs body'))
42+ where
43+ innerArgs = headDef [] argss
44+ outerArgs = concat . reverse $ tailSafe argss
45+ (argss, body', replace) = collectAllFunctionArgs [] id fn
46+ convert js = js
47+
48+ collectAllFunctionArgs :: [[Text]] -> (AST -> AST) -> AST -> ([[Text]], AST, AST -> AST)
49+ collectAllFunctionArgs allArgs f (Function s1 ident args (Block s2 (body@(Return _ _):_))) =
50+ collectAllFunctionArgs (args : allArgs) (\b -> f (Function s1 ident (map copyVar args) (Block s2 [b]))) body
51+ collectAllFunctionArgs allArgs f (Function ss ident args body@(Block _ _)) =
52+ (args : allArgs, body, f . Function ss ident (map copyVar args))
53+ collectAllFunctionArgs allArgs f (Return s1 (Function s2 ident args (Block s3 [body]))) =
54+ collectAllFunctionArgs (args : allArgs) (\b -> f (Return s1 (Function s2 ident (map copyVar args) (Block s3 [b])))) body
55+ collectAllFunctionArgs allArgs f (Return s1 (Function s2 ident args body@(Block _ _))) =
56+ (args : allArgs, body, f . Return s1 . Function s2 ident (map copyVar args))
57+ collectAllFunctionArgs allArgs f body = (allArgs, body, f)
58+
59+ isTailRecursive :: Text -> AST -> Bool
60+ isTailRecursive ident js = countSelfReferences js > 0 && allInTailPosition js where
61+ countSelfReferences = everything (+) match where
62+ match :: AST -> Int
63+ match (Var _ ident') | ident == ident' = 1
64+ match _ = 0
65+
66+ allInTailPosition (Return _ expr)
67+ | isSelfCall ident expr = countSelfReferences expr == 1
68+ | otherwise = countSelfReferences expr == 0
69+ allInTailPosition (While _ js1 body)
70+ = countSelfReferences js1 == 0 && allInTailPosition body
71+ allInTailPosition (For _ _ js1 js2 body)
72+ = countSelfReferences js1 == 0 && countSelfReferences js2 == 0 && allInTailPosition body
73+ allInTailPosition (ForIn _ _ js1 body)
74+ = countSelfReferences js1 == 0 && allInTailPosition body
75+ allInTailPosition (IfElse _ js1 body el)
76+ = countSelfReferences js1 == 0 && allInTailPosition body && all allInTailPosition el
77+ allInTailPosition (Block _ body)
78+ = all allInTailPosition body
79+ allInTailPosition (Throw _ js1)
80+ = countSelfReferences js1 == 0
81+ allInTailPosition (ReturnNoResult _)
82+ = True
83+ allInTailPosition (VariableIntroduction _ _ js1)
84+ = all ((== 0) . countSelfReferences) js1
85+ allInTailPosition (Assignment _ _ js1)
86+ = countSelfReferences js1 == 0
87+ allInTailPosition (Comment _ _ js1)
88+ = allInTailPosition js1
89+ allInTailPosition _
90+ = False
91+
92+ toLoop :: Text -> [Text] -> [Text] -> AST -> AST
93+ toLoop ident outerArgs innerArgs js =
94+ Block rootSS $
95+ concatMap (\arg -> [ VariableIntroduction rootSS (tcoVar arg) . Just $
96+ Var rootSS (copyVar arg) ]) (outerArgs ++ innerArgs) ++
97+ [ Assignment rootSS (Var rootSS $ "var " <> tcoDone) $ BooleanLiteral Nothing False
98+ , VariableIntroduction rootSS tcoResult Nothing
99+ , Assignment rootSS (Var rootSS $ "var " <> tcoLoop) (Function rootSS (Just tcoLoop) (outerArgs ++ innerArgs) (Block rootSS [loopify js]))
100+ , While rootSS (Unary Nothing Not (Var rootSS tcoDone))
101+ (Block rootSS
102+ [(Assignment rootSS (Var rootSS tcoResult) (App rootSS (Var rootSS tcoLoop) ((map (Var rootSS . tcoVar) outerArgs) ++ (map (Var rootSS . copyVar) innerArgs))))])
103+ , Return rootSS (Var rootSS tcoResult)
104+ ]
105+ where
106+ rootSS = Nothing
107+
108+ loopify :: AST -> AST
109+ loopify (Return ss ret)
110+ | isSelfCall ident ret =
111+ let
112+ allArgumentValues = concat $ collectArgs [] ret
113+ in
114+ Block ss $
115+ zipWith (\val arg ->
116+ Assignment ss (Var ss (tcoVar arg)) val) allArgumentValues outerArgs
117+ ++ zipWith (\val arg ->
118+ Assignment ss (Var ss (copyVar arg)) val) (drop (length outerArgs) allArgumentValues) innerArgs
119+ ++ [ ReturnNoResult ss ]
120+ | otherwise = Block ss [ markDone ss, Return ss ret ]
121+ loopify (ReturnNoResult ss) = Block ss [ markDone ss, ReturnNoResult ss ]
122+ loopify (While ss cond body) = While ss cond (loopify body)
123+ loopify (For ss i js1 js2 body) = For ss i js1 js2 (loopify body)
124+ loopify (ForIn ss i js1 body) = ForIn ss i js1 (loopify body)
125+ loopify (IfElse ss cond body el) = IfElse ss cond (loopify body) (fmap loopify el)
126+ loopify (Block ss body) = Block ss (map loopify body)
127+ loopify other = other
128+
129+ markDone :: Maybe SourceSpan -> AST
130+ markDone ss = Assignment ss (Var ss tcoDone) (BooleanLiteral ss True)
131+
132+ collectArgs :: [[AST]] -> AST -> [[AST]]
133+ collectArgs acc (App _ fn args') = collectArgs (args' : acc) fn
134+ collectArgs acc _ = acc
135+
136+ isSelfCall :: Text -> AST -> Bool
137+ isSelfCall ident (App _ (Var _ ident') _) = ident == ident'
138+ isSelfCall ident (App _ (Indexer _ (Var _ ident') (Var _ mn')) _) = mn' == "" && ident == ident'
139+ isSelfCall ident (App _ (Indexer _ (Var _ ident') mn') _) = mn' == mn && ident == ident'
140+ isSelfCall ident (App _ fn _) = isSelfCall ident fn
141+ isSelfCall _ _ = False
src/CodeGen/IL/Printer.hsnew file+527
@@ -0,0 +1,527 @@
1+-- | Pretty printer for the AST
2+module CodeGen.IL.Printer
3+ ( prettyPrintIL
4+ , prettyPrintIL1
5+ , prettyPrintILWithSourceMaps
6+ , interfaceSource
7+ , implHeaderSource
8+ , implFooterSource
9+ , isLiteral
10+ , modLabel
11+ , modPrefix
12+ , ffiLoader
13+ ) where
14+
15+import Prelude.Compat
16+
17+import Control.Arrow ((<+>))
18+import Control.Monad (forM, mzero)
19+import Control.Monad.State (StateT, evalStateT)
20+import Control.PatternArrows
21+import Data.List (filter, (\\))
22+import qualified Control.Arrow as A
23+
24+import Data.Maybe (fromMaybe)
25+import Data.Monoid ((<>))
26+import Data.Text (Text)
27+import qualified Data.Text as T
28+
29+import Language.PureScript.AST (SourceSpan(..))
30+import Language.PureScript.CoreImp.AST
31+import Language.PureScript.Comments
32+import Language.PureScript.Crash
33+import Language.PureScript.Names (Ident, runIdent)
34+import Language.PureScript.Pretty.Common
35+import Language.PureScript.PSString (PSString, decodeString, mkString)
36+
37+import CodeGen.IL.Common
38+import CodeGen.IL.Optimizer.TCO (tcoLoop)
39+
40+import qualified Language.PureScript.Constants as C
41+
42+-- TODO (Christoph): Get rid of T.unpack / pack
43+
44+literals :: (Emit gen) => Pattern PrinterState AST gen
45+literals = mkPattern' match'
46+ where
47+ match' :: (Emit gen) => AST -> StateT PrinterState Maybe gen
48+ match' il = (addMapping' (getSourceSpan il) <>) <$> match il
49+
50+ match :: (Emit gen) => AST -> StateT PrinterState Maybe gen
51+ match (NumericLiteral _ n) = return $ emit $ T.pack $ either show show n
52+ match (StringLiteral _ s) = return $ emit $ stringLiteral s
53+ match (BooleanLiteral _ True) = return $ emit "true"
54+ match (BooleanLiteral _ False) = return $ emit "false"
55+ match (ArrayLiteral _ xs) = mconcat <$> sequence
56+ [ return . emit $ arrayType <> "{"
57+ , intercalate (emit ", ") <$> forM xs prettyPrintIL'
58+ , return $ emit "}"
59+ ]
60+ -- match (ObjectLiteral _ []) = return $ emit "std::initializer_list<std::pair<const string, boxed>>{}"
61+ match (ObjectLiteral _ ps) = mconcat <$> sequence
62+ [ return . emit $ dictType <> "{"
63+ , withIndent $ do
64+ ils <- forM ps $ \(key, value) -> do
65+ value' <- prettyPrintIL' value
66+ return $ objectPropertyToString key <> value'
67+ return $ intercalate (emit " ") $ map (<> emit ",") ils
68+ , return $ emit "}"
69+ ]
70+ where
71+ objectPropertyToString :: (Emit gen) => PSString -> gen
72+ objectPropertyToString s = emit $ stringLiteral s <> ": "
73+ match (Block _ sts) = mconcat <$> sequence
74+ [ return $ emit "{\n"
75+ , withIndent $ prettyStatements sts
76+ , return $ emit "\n"
77+ , currentIndent
78+ , return $ emit "}"
79+ ]
80+ match (Var _ ident) | ident == C.undefined = return $ emit undefinedName
81+ match (Var _ ident) = return $ emit ident
82+ match (VariableIntroduction _ ident value) = mconcat <$> sequence
83+ [ return . emit $ varDecl <> " " <> ident <> " " <> anyType
84+ , maybe (return mempty) (fmap (emit " = " <>) . prettyPrintIL') value
85+ ]
86+ match (Assignment _ target value) = mconcat <$> sequence
87+ [ prettyPrintIL' target
88+ , return $ emit " = "
89+ , prettyPrintIL' value
90+ ]
91+ match (App _ val []) = mconcat <$> sequence
92+ [ return $ emit "Run("
93+ , prettyPrintIL' val
94+ , return $ emit ")"
95+ ]
96+ match (App _ (StringLiteral _ u) [arg])
97+ | Just ty <- decodeString u = mconcat <$> sequence
98+ [ prettyPrintIL' arg
99+ , return $ emit ".("
100+ , return $ emit ty
101+ , return $ emit ")"
102+ ]
103+ match (App _ (Var _ fn) [arg]) | fn == arrayLengthFn = mconcat <$> sequence
104+ [ return $ emit fn
105+ , return $ emit "("
106+ , prettyPrintIL' arg
107+ , return $ emit ")"
108+ ]
109+ match (App _ (Var _ fn) args) | fn == indexFn = mconcat <$> sequence
110+ [ return $ emit fn
111+ , return $ emit "("
112+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
113+ , return $ emit ")"
114+ ]
115+ match (App _ (Var _ fn) args) | fn == tcoLoop = mconcat <$> sequence
116+ [ return $ emit fn
117+ , return $ emit "("
118+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
119+ , return $ emit ")"
120+ ]
121+ match (App _ (App Nothing (StringLiteral Nothing fnx) [fn@Function{}]) args)
122+ | Just ftype <- decodeString fnx
123+ , "Fn" `T.isPrefixOf` ftype = mconcat <$> sequence
124+ [ prettyPrintIL' fn
125+ , return $ emit "("
126+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
127+ , return $ emit ")"
128+ ]
129+ match (App _ (App Nothing (StringLiteral Nothing fnx) [fn]) args)
130+ | Just ftype <- decodeString fnx
131+ , "Fn" `T.isPrefixOf` ftype = mconcat <$> sequence
132+ [ prettyPrintIL' fn
133+ , return $ emit ".("
134+ , return $ emit ftype
135+ , return $ emit ")("
136+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
137+ , return $ emit ")"
138+ ]
139+ match app@(App{})
140+ | (val, args) <- unApp app []
141+ , length args > 1
142+ = mconcat <$> sequence
143+ [ return $ emit "Apply("
144+ , prettyPrintIL' val
145+ , return $ emit ", "
146+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
147+ , return $ emit ")"
148+ ]
149+ match (App _ val args) = mconcat <$> sequence
150+ [ return $ emit "Apply("
151+ , prettyPrintIL' val
152+ , return $ emit ", "
153+ , intercalate (emit ", ") <$> forM args prettyPrintIL'
154+ , return $ emit ")"
155+ ]
156+ match (Function _ (Just name) [] (Block _ [Return _ ret]))
157+ | isComplexLiteral ret = mconcat <$> sequence
158+ [ return $ emit "\n"
159+ , return . emit $ varDecl <> " " <> initName name <> " Once\n"
160+ , prettyPrintIL' $ VariableIntroduction Nothing (valueName name) Nothing
161+ , return $ emit "\n\n"
162+ , return $ emit "func "
163+ , return . emit $ withPrefix name
164+ , return . emit $ "() " <> anyType <> " "
165+ , return $ emit "{\n"
166+ , withIndent $ do
167+ indentString <- currentIndent
168+ return $ indentString <> (emit $ initName name <> ".Do(func() {\n") <>
169+ indentString <> indentString <> (emit $ valueName name <> " = ")
170+ , withIndent $ do
171+ case ret of
172+ Function _ Nothing args body -> mconcat <$> sequence
173+ [ return $ emit "func("
174+ , return . emit $ intercalate ", " (renderArg anyType <$> args)
175+ , return . emit $ ") " <> anyType <> " "
176+ , prettyPrintIL' body
177+ ]
178+ _ -> do
179+ prettyPrintIL' ret
180+ , return $ emit "\n"
181+ , withIndent $ do
182+ indentString <- currentIndent
183+ return $ indentString <> (emit $ "})\n" <> "return " <> valueName name <>"\n")
184+ , return $ emit "}\n\n"
185+ ]
186+ match (Function _ (Just name) [] ret) = mconcat <$> sequence
187+ [ return $ emit "func "
188+ , return . emit $ withPrefix name
189+ , return . emit $ "() " <> anyType <> " "
190+ , prettyPrintIL' ret
191+ ]
192+ match (Function _ _ args ret) = mconcat <$> sequence
193+ [ return $ emit "func("
194+ , return . emit $ intercalate ", " (renderArg anyType <$> args)
195+ , return . emit $ ") " <> anyType <> " "
196+ , prettyPrintIL' ret
197+ ]
198+ match (Indexer _ (Var _ name) (Var _ "")) = mconcat <$> sequence
199+ [ prettyPrintIL' (Var Nothing $ withPrefix name)
200+ , return $ emit "()"
201+ ]
202+ match (Indexer _ (Var _ name) val) = mconcat <$> sequence
203+ [ prettyPrintIL' val
204+ , return $ emit "."
205+ , prettyPrintIL' (Var Nothing $ withPrefix name)
206+ , return $ emit "()"
207+ ]
208+ match (Indexer _ prop@StringLiteral{} val@ObjectLiteral{}) = mconcat <$> sequence
209+ [ prettyPrintIL' val
210+ , return $ emit "["
211+ , prettyPrintIL' prop
212+ , return $ emit "]"
213+ ]
214+ match (Indexer _ prop@StringLiteral{} val) = mconcat <$> sequence
215+ [ prettyPrintIL' val
216+ , return $ emit ".("
217+ , return $ emit dictType
218+ , return $ emit ")["
219+ , prettyPrintIL' prop
220+ , return $ emit "]"
221+ ]
222+ match (Indexer _ index val@ArrayLiteral{}) = mconcat <$> sequence
223+ [ prettyPrintIL' val
224+ , return $ emit "["
225+ , prettyPrintIL' index
226+ , return $ emit "]"
227+ ]
228+ match (Indexer _ index val) = mconcat <$> sequence
229+ [ prettyPrintIL' val
230+ , return $ emit ".("
231+ , return $ emit arrayType
232+ , return $ emit ")["
233+ , prettyPrintIL' index
234+ , return $ emit "]"
235+ ]
236+ match (InstanceOf _ val ty) = mconcat <$> sequence
237+ [ return $ emit "Is("
238+ , prettyPrintIL' val
239+ , return $ emit ", "
240+ , prettyPrintIL' ty
241+ , return $ emit ")"
242+ ]
243+ match (While _ cond sts) = mconcat <$> sequence
244+ [ return $ emit "for "
245+ , prettyPrintIL' cond
246+ , return $ emit " "
247+ , prettyPrintIL' sts
248+ ]
249+ match (For _ ident start end sts) = mconcat <$> sequence
250+ [ return $ emit $ "for var " <> ident <> " = "
251+ , prettyPrintIL' start
252+ , return $ emit $ "; " <> ident <> " < "
253+ , prettyPrintIL' end
254+ , return $ emit $ "; " <> ident <> "++ "
255+ , prettyPrintIL' sts
256+ ]
257+ match (ForIn _ ident obj sts) = mconcat <$> sequence
258+ [ return $ emit $ "for var " <> ident <> " in "
259+ , prettyPrintIL' obj
260+ , return $ emit " "
261+ , prettyPrintIL' sts
262+ ]
263+ match (IfElse _ (Binary _ EqualTo cond@Binary{} (BooleanLiteral Nothing True)) thens elses) = mconcat <$> sequence
264+ [ return $ emit "if "
265+ , prettyPrintIL' cond
266+ , return $ emit " "
267+ , prettyPrintIL' thens
268+ , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
269+ ]
270+ match (IfElse _ (Binary _ EqualTo cond@Binary{} (BooleanLiteral Nothing False)) thens elses) = mconcat <$> sequence
271+ [ return $ emit "if !("
272+ , prettyPrintIL' cond
273+ , return $ emit ") "
274+ , prettyPrintIL' thens
275+ , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
276+ ]
277+ match (IfElse _ cond thens elses) = mconcat <$> sequence
278+ [ return $ emit "if "
279+ , prettyPrintIL' cond
280+ , return $ emit " "
281+ , prettyPrintIL' thens
282+ , maybe (return mempty) (fmap (emit " else " <>) . prettyPrintIL') elses
283+ ]
284+ match (Return _ value) = mconcat <$> sequence
285+ [ return $ emit "return "
286+ , prettyPrintIL' value
287+ ]
288+ match (ReturnNoResult _) = return . emit $ "return " <> undefinedName
289+ -- match (Throw _ _) = return mempty
290+ match (Throw _ value) = mconcat <$> sequence
291+ [ return $ emit "panic("
292+ , prettyPrintIL' value
293+ , return $ emit ")"
294+ ]
295+ match (Comment _ com il) = mconcat <$> sequence
296+ [ return $ emit "\n"
297+ , mconcat <$> forM com comment
298+ , prettyPrintIL' il
299+ ]
300+ match _ = mzero
301+
302+ comment :: (Emit gen) => Comment -> StateT PrinterState Maybe gen
303+ comment (LineComment com) = fmap mconcat $ sequence $
304+ [ currentIndent
305+ , return $ emit "//" <> emit com <> emit "\n"
306+ ]
307+ comment (BlockComment com) = fmap mconcat $ sequence $
308+ [ currentIndent
309+ , return $ emit "/**\n"
310+ ] ++
311+ map asLine (T.lines com) ++
312+ [ currentIndent
313+ , return $ emit " */\n"
314+ , currentIndent
315+ ]
316+ where
317+ asLine :: (Emit gen) => Text -> StateT PrinterState Maybe gen
318+ asLine s = do
319+ i <- currentIndent
320+ return $ i <> emit " * " <> (emit . removeComments) s <> emit "\n"
321+
322+ removeComments :: Text -> Text
323+ removeComments t =
324+ case T.stripPrefix "*/" t of
325+ Just rest -> removeComments rest
326+ Nothing -> case T.uncons t of
327+ Just (x, xs) -> x `T.cons` removeComments xs
328+ Nothing -> ""
329+
330+unary' :: (Emit gen) => UnaryOperator -> (AST -> Text) -> Operator PrinterState AST gen
331+unary' op mkStr = Wrap match (<>)
332+ where
333+ match :: (Emit gen) => Pattern PrinterState AST (gen, AST)
334+ match = mkPattern match'
335+ where
336+ match' (Unary _ op' val) | op' == op = Just (emit $ mkStr val, val)
337+ match' _ = Nothing
338+
339+unary :: (Emit gen) => UnaryOperator -> Text -> Operator PrinterState AST gen
340+unary op str = unary' op (const str)
341+
342+negateOperator :: (Emit gen) => Operator PrinterState AST gen
343+negateOperator = unary' Negate (\v -> if isNegate v then "- " else "-")
344+ where
345+ isNegate (Unary _ Negate _) = True
346+ isNegate _ = False
347+
348+binary :: (Emit gen) => BinaryOperator -> Text -> Operator PrinterState AST gen
349+binary op str = AssocL match (\v1 v2 -> v1 <> emit (" " <> str <> " ") <> v2)
350+ where
351+ match :: Pattern PrinterState AST (AST, AST)
352+ match = mkPattern match'
353+ where
354+ match' (Binary _ op' v1 v2) | op' == op = Just (v1, v2)
355+ match' _ = Nothing
356+
357+isLiteral :: AST -> Bool
358+isLiteral Function{} = True
359+isLiteral NumericLiteral{} = True
360+isLiteral StringLiteral{} = True
361+isLiteral BooleanLiteral{} = True
362+isLiteral ObjectLiteral{} = True
363+isLiteral ArrayLiteral{} = True
364+isLiteral _ = False
365+
366+isComplexLiteral :: AST -> Bool
367+-- isComplexLiteral Function{} = True
368+isComplexLiteral ObjectLiteral{} = True
369+isComplexLiteral ArrayLiteral{} = True
370+isComplexLiteral _ = False
371+
372+unApp :: AST -> [AST] -> (AST, [AST])
373+unApp (App _ val [arg]) args = unApp val (arg : args)
374+unApp other args = (other, args)
375+
376+prettyStatements :: (Emit gen) => [AST] -> StateT PrinterState Maybe gen
377+prettyStatements sts = do
378+ ils <- forM sts prettyPrintIL'
379+ indentString <- currentIndent
380+ return $ intercalate (emit "\n") $ map (indentString <>) ils
381+
382+-- | Generate a pretty-printed string representing a collection of C++ expressions at the same indentation level
383+prettyPrintILWithSourceMaps :: [AST] -> (Text, [SMap])
384+prettyPrintILWithSourceMaps il =
385+ let StrPos (_, s, mp) = (fromMaybe (internalError "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyStatements) il
386+ in (s, mp)
387+
388+prettyPrintIL :: [AST] -> Text
389+prettyPrintIL = maybe (internalError "Incomplete pattern") runPlainString . flip evalStateT (PrinterState 0) . prettyStatements
390+
391+-- | Generate an indented, pretty-printed string representing a C++ expression
392+prettyPrintIL' :: (Emit gen) => AST -> StateT PrinterState Maybe gen
393+prettyPrintIL' = A.runKleisli $ runPattern matchValue
394+ where
395+ matchValue :: (Emit gen) => Pattern PrinterState AST gen
396+ matchValue = buildPrettyPrinter operators (literals <+> fmap parensPos matchValue)
397+ operators :: (Emit gen) => OperatorTable PrinterState AST gen
398+ operators =
399+ OperatorTable [ [ unary New "?" ]
400+ , [ unary Not "!"
401+ , unary BitwiseNot "~"
402+ , unary Positive "+"
403+ , negateOperator ]
404+ , [ binary Multiply "*"
405+ , binary Divide "/"
406+ , binary Modulus "%" ]
407+ , [ binary Add "+"
408+ , binary Subtract "-" ]
409+ , [ binary ShiftLeft "<<"
410+ , binary ShiftRight ">>" ]
411+ , [ binary LessThan "<"
412+ , binary LessThanOrEqualTo "<="
413+ , binary GreaterThan ">"
414+ , binary GreaterThanOrEqualTo ">=" ]
415+ , [ binary EqualTo "=="
416+ , binary NotEqualTo "!=" ]
417+ , [ binary BitwiseAnd "&" ]
418+ , [ binary BitwiseXor "^" ]
419+ , [ binary BitwiseOr "|" ]
420+ , [ binary And "&&" ]
421+ , [ binary Or "||" ]
422+ ]
423+
424+prettyPrintIL1 :: AST -> Text
425+prettyPrintIL1 = maybe (internalError "Incomplete pattern") runPlainString . flip evalStateT (PrinterState 0) . prettyPrintIL'
426+
427+stringLiteral :: PSString -> Text
428+stringLiteral pss | Just s <- decodeString pss = stringLiteral' s
429+ where
430+ stringLiteral' :: Text -> Text
431+ stringLiteral' s = "\"" <> T.concatMap encodeChar s <> "\""
432+ encodeChar :: Char -> Text
433+ encodeChar '\0' = "\\x00"
434+ encodeChar '\b' = "\\b"
435+ encodeChar '\t' = "\\t"
436+ encodeChar '\n' = "\\n"
437+ encodeChar '\v' = "\\v"
438+ encodeChar '\f' = "\\f"
439+ encodeChar '\r' = "\\r"
440+ encodeChar '"' = "\\\""
441+ encodeChar '\\' = "\\\\"
442+ encodeChar c = T.singleton $ c
443+stringLiteral _ = "\"\\uFFFD\""
444+
445+interfaceSource :: Text -> [(Text,Bool)] -> [Ident] -> Text
446+interfaceSource _ _ _ = ""
447+
448+implHeaderSource :: Text -> [Text] -> Text -> Text
449+implHeaderSource mn imports otherPrefix =
450+ "// Code generated by psgo. DO NOT EDIT.\n\n" <>
451+ "package " <> (if mn == "Main" || mn == "Test_Main" then "main" else mn) <> "\n\n" <>
452+ "import . \"" <> runtime <> "\"\n" <>
453+ (if mn == "Main" || mn == "Test_Main"
454+ then "import _ \"" <> otherPrefix <> "/" <> ffiLoader <> "\"\n"
455+ else "\n") <>
456+ "import (\n" <>
457+ (T.concat $ formatImport <$> imports) <> ")\n\n" <>
458+ "type _ = Any\n\n"
459+ where
460+ formatImport :: Text -> Text
461+ formatImport s =
462+ "\t\"" <> otherPrefix <> "/" <> modPrefix <> "/" <> moduleRenamer s <> "\"\n"
463+ moduleRenamer :: Text -> Text
464+ moduleRenamer s
465+ | (s', sfx) <- T.breakOn moduleRenamerMarker s,
466+ not $ T.null sfx = s'
467+ moduleRenamer s = s
468+
469+implFooterSource :: Text -> [Ident] -> Text
470+implFooterSource mn foreigns =
471+ "\n\n\n" <>
472+ (if null foreigns
473+ then ""
474+ else ("// Foreign values\n\n" <>
475+ "var " <> foreignDict <> " = "<> foreignMod <> "(\"" <> mn <> "\")\n\n" <>
476+ (T.concat $ (\foreign' ->
477+ let name = moduleIdentToIL foreign' in
478+ varDecl <> " " <> initName name <> " Once\n" <>
479+ varDecl <> " " <> valueName name <> " " <> anyType <> "\n\n" <>
480+ "func " <>
481+ withPrefix name <>
482+ "() Any { \n" <>
483+ " " <> initName name <> ".Do(func() {\n" <>
484+ " " <> valueName name <> " = " <>
485+ "Get(" <> foreignDict <> ", " <>
486+ (stringLiteral . mkString $ runIdent foreign') <> ")\n" <>
487+ " })\n" <>
488+ " return " <> valueName name <> "\n" <>
489+ "}\n\n") <$> foreigns))) <>
490+ if mn == "Main" || mn == "Test.Main" then mainSource else "\n"
491+ where
492+ mainSource :: Text
493+ mainSource = "\
494+ \func main() {\n\
495+ \ Run(Ꞌmain())\n\
496+ \}\n\n\
497+ \"
498+
499+varDecl :: Text
500+varDecl = "var"
501+
502+renderArg :: Text -> Text -> Text
503+renderArg decl arg = arg <> " " <> decl
504+
505+foreignMod :: Text
506+foreignMod = "Foreign"
507+
508+foreignDict :: Text
509+foreignDict = "foreign"
510+
511+modLabel :: Text
512+modLabel = "purescript-native"
513+
514+modPrefix :: Text
515+modPrefix = modLabel <> "/output"
516+
517+runtime :: Text
518+runtime = "github.com/" <> modLabel <> "/go-runtime"
519+
520+ffiLoader :: Text
521+ffiLoader = modLabel <> "/ffi-loader"
522+
523+initName :: Text -> Text
524+initName s = "ᛌ" <> s <> "_once"
525+
526+valueName :: Text -> Text
527+valueName s = "ᛧ" <> s
src/Language/PureScript.hsdeleted−256
@@ -1,256 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- The main compiler module
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript (module P, compile, compile', MonadMake(..), make) where
17−
18−import Language.PureScript.Types as P
19−import Language.PureScript.Kinds as P
20−import Language.PureScript.Declarations as P
21−import Language.PureScript.Names as P
22−import Language.PureScript.Parser as P
23−import Language.PureScript.CodeGen as P
24−import Language.PureScript.CodeGen.Common as P
25−import Language.PureScript.TypeChecker as P
26−import Language.PureScript.Pretty as P
27−import Language.PureScript.Sugar as P
28−import Language.PureScript.Options as P
29−import Language.PureScript.ModuleDependencies as P
30−import Language.PureScript.Environment as P
31−import Language.PureScript.Errors as P
32−import Language.PureScript.DeadCodeElimination as P
33−import Language.PureScript.Supply as P
34−
35−import qualified Language.PureScript.Constants as C
36−
37−import Data.List (find, sortBy, groupBy, intercalate)
38−import Data.Time.Clock
39−import Data.Function (on)
40−import Data.Maybe (fromJust, fromMaybe)
41−import Control.Monad.Error
42−import Control.Monad.State.Lazy
43−import Control.Arrow ((&&&))
44−import Control.Applicative
45−import qualified Data.Map as M
46−import qualified Data.Set as S
47−import System.FilePath (pathSeparator)
48−
49−-- |
50−-- Compile a collection of modules
51−--
52−-- The compilation pipeline proceeds as follows:
53−--
54−-- * Sort the modules based on module dependencies, checking for cyclic dependencies.
55−--
56−-- * Perform a set of desugaring passes.
57−--
58−-- * Type check, and elaborate values to include type annotations and type class dictionaries.
59−--
60−-- * Regroup values to take into account new value dependencies introduced by elaboration.
61−--
62−-- * Eliminate dead code.
63−--
64−-- * Generate Javascript, and perform optimization passes.
65−--
66−-- * Pretty-print the generated Javascript
67−--
68−compile :: Options -> [Module] -> Either String (String, String, Environment)
69−compile = compile' initEnvironment
70−
71−compile' :: Environment -> Options -> [Module] -> Either String (String, String, Environment)
72−compile' env opts ms = do
73− (sorted, _) <- sortModules $ if optionsNoPrelude opts then ms else (map importPrelude ms)
74− (desugared, nextVar) <- stringifyErrorStack True $ runSupplyT 0 $ desugar sorted
75− (elaborated, env') <- runCheck' opts env $ forM desugared $ typeCheckModule mainModuleIdent
76− regrouped <- stringifyErrorStack True $ createBindingGroupsModule . collapseBindingGroupsModule $ elaborated
77− let entryPoints = moduleNameFromString `map` optionsModules opts
78− let elim = if null entryPoints then regrouped else eliminateDeadCode entryPoints regrouped
79− let codeGenModules = moduleNameFromString `map` optionsCodeGenModules opts
80− let modulesToCodeGen = if null codeGenModules then elim else filter (\(Module mn _ _) -> mn `elem` codeGenModules) elim
81− let js = evalSupply nextVar $ concat <$> mapM (\m -> moduleToJs Globals opts m env') modulesToCodeGen
82− let exts = intercalate "\n" . map (`moduleToPs` env') $ modulesToCodeGen
83− js' <- generateMain env' opts js
84− return (prettyPrintJS js', exts, env')
85− where
86− mainModuleIdent = moduleNameFromString <$> optionsMain opts
87−
88−typeCheckModule :: Maybe ModuleName -> Module -> Check Module
89−typeCheckModule mainModuleName (Module mn decls exps) = do
90− modify (\s -> s { checkCurrentModule = Just mn })
91− decls' <- typeCheckAll mainModuleName mn decls
92− mapM_ checkTypesAreExported exps'
93− return $ Module mn decls' exps
94− where
95−
96− exps' = fromMaybe (error "exports should have been elaborated") exps
97−
98− -- Check that all the type constructors defined in the current module that appear in member types
99− -- have also been exported from the module
100− checkTypesAreExported :: DeclarationRef -> Check ()
101− checkTypesAreExported (ValueRef name) = do
102− ty <- lookupVariable mn (Qualified (Just mn) name)
103− case find isTconHidden (findTcons ty) of
104− Just hiddenType -> throwError . strMsg $
105− "Error in module '" ++ show mn ++ "':\n\
106− \Exporting declaration '" ++ show name ++ "' requires type '" ++ show hiddenType ++ "' to be exported as well"
107− Nothing -> return ()
108− checkTypesAreExported _ = return ()
109−
110− -- Find the type constructors exported from the current module used in a type
111− findTcons :: Type -> [ProperName]
112− findTcons = everythingOnTypes (++) go
113− where
114− go (TypeConstructor (Qualified (Just mn') name)) | mn' == mn = [name]
115− go _ = []
116−
117− -- Checks whether a type constructor is not being exported from the current module
118− isTconHidden :: ProperName -> Bool
119− isTconHidden tyName = all go exps'
120− where
121− go (TypeRef tyName' _) = tyName' /= tyName
122− go _ = True
123−
124−
125−generateMain :: Environment -> Options -> [JS] -> Either String [JS]
126−generateMain env opts js =
127− case moduleNameFromString <$> optionsMain opts of
128− Just mmi -> do
129− when ((mmi, Ident C.main) `M.notMember` names env) $
130− Left $ show mmi ++ "." ++ C.main ++ " is undefined"
131− return $ js ++ [JSApp (JSAccessor C.main (JSAccessor (moduleNameToJs mmi) (JSVar (fromJust (optionsBrowserNamespace opts))))) []]
132− _ -> return js
133−
134−-- |
135−-- A type class which collects the IO actions we need to be able to run in "make" mode
136−--
137−class MonadMake m where
138− -- |
139− -- Get a file timestamp
140− --
141− getTimestamp :: FilePath -> m (Maybe UTCTime)
142−
143− -- |
144− -- Read a file as a string
145− --
146− readTextFile :: FilePath -> m String
147−
148− -- |
149− -- Write a text file
150− --
151− writeTextFile :: FilePath -> String -> m ()
152−
153− -- |
154− -- Report an error
155− --
156− liftError :: Either String a -> m a
157−
158− -- |
159− -- Respond to a progress update
160− --
161− progress :: String -> m ()
162−
163−-- |
164−-- Compiles in "make" mode, compiling each module separately to a js files and an externs file
165−--
166−-- If timestamps have not changed, the externs file can be used to provide the module's types without
167−-- having to typecheck the module again.
168−--
169−make :: (Functor m, Applicative m, Monad m, MonadMake m) => FilePath -> Options -> [(FilePath, Module)] -> m Environment
170−make outputDir opts ms = do
171− let filePathMap = M.fromList (map (\(fp, Module mn _ _) -> (mn, fp)) ms)
172−
173− (sorted, graph) <- liftError $ sortModules $ if optionsNoPrelude opts then map snd ms else (map (importPrelude . snd) ms)
174−
175− toRebuild <- foldM (\s (Module moduleName' _ _) -> do
176− let filePath = runModuleName moduleName'
177−
178− jsFile = outputDir ++ pathSeparator : filePath ++ pathSeparator : "index.js"
179− externsFile = outputDir ++ pathSeparator : filePath ++ pathSeparator : "externs.purs"
180− inputFile = fromMaybe (error "Input file is undefined in make") $ M.lookup moduleName' filePathMap
181−
182− jsTimestamp <- getTimestamp jsFile
183− externsTimestamp <- getTimestamp externsFile
184− inputTimestamp <- getTimestamp inputFile
185−
186− return $ case (inputTimestamp, jsTimestamp, externsTimestamp) of
187− (Just t1, Just t2, Just t3) | t1 < min t2 t3 -> s
188− _ -> S.insert moduleName' s) S.empty sorted
189−
190− marked <- rebuildIfNecessary (reverseDependencies graph) toRebuild sorted
191−
192− (desugared, nextVar) <- liftError $ stringifyErrorStack True $ runSupplyT 0 $ zip (map fst marked) <$> desugar (map snd marked)
193−
194− evalSupplyT nextVar (go initEnvironment desugared)
195−
196− where
197− go :: (Functor m, Applicative m, Monad m, MonadMake m) => Environment -> [(Bool, Module)] -> SupplyT m Environment
198− go env [] = return env
199− go env ((False, m) : ms') = do
200− (_, env') <- lift . liftError . runCheck' opts env $ typeCheckModule Nothing m
201−
202− go env' ms'
203− go env ((True, m@(Module moduleName' _ exps)) : ms') = do
204− let filePath = runModuleName moduleName'
205− jsFile = outputDir ++ pathSeparator : filePath ++ pathSeparator : "index.js"
206− externsFile = outputDir ++ pathSeparator : filePath ++ pathSeparator : "externs.purs"
207−
208− lift . progress $ "Compiling " ++ runModuleName moduleName'
209−
210− (Module _ elaborated _, env') <- lift . liftError . runCheck' opts env $ typeCheckModule Nothing m
211−
212− regrouped <- lift . liftError . stringifyErrorStack True . createBindingGroups moduleName' . collapseBindingGroups $ elaborated
213−
214− let mod' = Module moduleName' regrouped exps
215− js <- prettyPrintJS <$> moduleToJs CommonJS opts mod' env'
216− let exts = moduleToPs mod' env'
217−
218− lift $ writeTextFile jsFile js
219− lift $ writeTextFile externsFile exts
220−
221− go env' ms'
222−
223− rebuildIfNecessary :: (Functor m, Monad m, MonadMake m) => M.Map ModuleName [ModuleName] -> S.Set ModuleName -> [Module] -> m [(Bool, Module)]
224− rebuildIfNecessary _ _ [] = return []
225− rebuildIfNecessary graph toRebuild (m@(Module moduleName' _ _) : ms') | moduleName' `S.member` toRebuild = do
226− let deps = fromMaybe [] $ moduleName' `M.lookup` graph
227− toRebuild' = toRebuild `S.union` S.fromList deps
228− (:) (True, m) <$> rebuildIfNecessary graph toRebuild' ms'
229− rebuildIfNecessary graph toRebuild (Module moduleName' _ _ : ms') = do
230− let externsFile = outputDir ++ pathSeparator : runModuleName moduleName' ++ pathSeparator : "externs.purs"
231− externs <- readTextFile externsFile
232− externsModules <- liftError . either (Left . show) Right $ P.runIndentParser externsFile P.parseModules externs
233− case externsModules of
234− [m'@(Module moduleName'' _ _)] | moduleName'' == moduleName' -> (:) (False, m') <$> rebuildIfNecessary graph toRebuild ms'
235− _ -> liftError . Left $ "Externs file " ++ externsFile ++ " was invalid"
236−
237−reverseDependencies :: ModuleGraph -> M.Map ModuleName [ModuleName]
238−reverseDependencies g = combine [ (dep, mn) | (mn, deps) <- g, dep <- deps ]
239− where
240− combine :: (Ord a) => [(a, b)] -> M.Map a [b]
241− combine = M.fromList . map ((fst . head) &&& map snd) . groupBy ((==) `on` fst) . sortBy (compare `on` fst)
242−
243−-- |
244−-- Add an import declaration for the Prelude to a module if it does not already explicitly import
245−-- it.
246−--
247−importPrelude :: Module -> Module
248−importPrelude m@(Module mn decls exps) =
249− if isPreludeImport `any` decls || mn == prelude then m
250− else Module mn (preludeImport : decls) exps
251− where
252− prelude = ModuleName [ProperName C.prelude]
253− isPreludeImport (ImportDeclaration (ModuleName [ProperName mn']) _ _) | mn' == C.prelude = True
254− isPreludeImport (PositionedDeclaration _ d) = isPreludeImport d
255− isPreludeImport _ = False
256− preludeImport = ImportDeclaration prelude Nothing Nothing
src/Language/PureScript/CodeGen.hsdeleted−25
@@ -1,25 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.CodeGen
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- A collection of modules related to code generation:
13−--
14−-- [@Language.PureScript.CodeGen.JS@] Code generator for Javascript
15−--
16−-- [@Language.PureScript.CodeGen.Externs@] Code generator for extern (foreign import) files
17−--
18−-- [@Language.PureScript.CodeGen.Optimize@] Optimization passes for generated Javascript
19−--
20−-----------------------------------------------------------------------------
21−
22−module Language.PureScript.CodeGen (module C) where
23−
24−import Language.PureScript.CodeGen.JS as C
25−import Language.PureScript.CodeGen.Externs as C
src/Language/PureScript/CodeGen/Common.hsdeleted−141
@@ -1,141 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.CodeGen.Common
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Common code generation utility functions
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.CodeGen.Common where
17−
18−import Data.Char
19−import Data.List (intercalate)
20−import Language.PureScript.Names
21−
22−-- |
23−-- Convert an Ident into a valid Javascript identifier:
24−--
25−-- * Alphanumeric characters are kept unmodified.
26−--
27−-- * Reserved javascript identifiers are prefixed with '$$'.
28−--
29−-- * Symbols are prefixed with '$' followed by a symbol name or their ordinal value.
30−--
31−identToJs :: Ident -> String
32−identToJs (Ident name) | nameIsJsReserved name = "$$" ++ name
33−identToJs (Ident name) = concatMap identCharToString name
34−identToJs (Op op) = concatMap identCharToString op
35−
36−-- |
37−-- Attempts to find a human-readable name for a symbol, if none has been specified returns the
38−-- ordinal value.
39−--
40−identCharToString :: Char -> String
41−identCharToString c | isAlphaNum c = [c]
42−identCharToString '_' = "_"
43−identCharToString '.' = "$dot"
44−identCharToString '$' = "$dollar"
45−identCharToString '~' = "$tilde"
46−identCharToString '=' = "$eq"
47−identCharToString '<' = "$less"
48−identCharToString '>' = "$greater"
49−identCharToString '!' = "$bang"
50−identCharToString '#' = "$hash"
51−identCharToString '%' = "$percent"
52−identCharToString '^' = "$up"
53−identCharToString '&' = "$amp"
54−identCharToString '|' = "$bar"
55−identCharToString '*' = "$times"
56−identCharToString '/' = "$div"
57−identCharToString '+' = "$plus"
58−identCharToString '-' = "$minus"
59−identCharToString ':' = "$colon"
60−identCharToString '\\' = "$bslash"
61−identCharToString '?' = "$qmark"
62−identCharToString '@' = "$at"
63−identCharToString '\'' = "$prime"
64−identCharToString c = '$' : show (ord c)
65−
66−-- |
67−-- Checks whether an identifier name is reserved in Javascript.
68−--
69−nameIsJsReserved :: String -> Bool
70−nameIsJsReserved name =
71− name `elem` [ "abstract"
72− , "arguments"
73− , "boolean"
74− , "break"
75− , "byte"
76− , "case"
77− , "catch"
78− , "char"
79− , "class"
80− , "const"
81− , "continue"
82− , "debugger"
83− , "default"
84− , "delete"
85− , "do"
86− , "double"
87− , "else"
88− , "enum"
89− , "eval"
90− , "export"
91− , "extends"
92− , "final"
93− , "finally"
94− , "float"
95− , "for"
96− , "function"
97− , "goto"
98− , "if"
99− , "implements"
100− , "import"
101− , "in"
102− , "instanceof"
103− , "int"
104− , "interface"
105− , "let"
106− , "long"
107− , "native"
108− , "new"
109− , "null"
110− , "package"
111− , "private"
112− , "protected"
113− , "public"
114− , "return"
115− , "short"
116− , "static"
117− , "super"
118− , "switch"
119− , "synchronized"
120− , "this"
121− , "throw"
122− , "throws"
123− , "transient"
124− , "try"
125− , "typeof"
126− , "var"
127− , "void"
128− , "volatile"
129− , "while"
130− , "with"
131− , "yield" ]
132−
133−-- |
134−-- Test if a string is a valid JS identifier (may return false negatives)
135−--
136−isIdent :: String -> Bool
137−isIdent s@(first : rest) | not (nameIsJsReserved s) && isAlpha first && all isAlphaNum rest = True
138−isIdent _ = False
139−
140−moduleNameToJs :: ModuleName -> String
141−moduleNameToJs (ModuleName pns) = intercalate "_" (runProperName `map` pns)
src/Language/PureScript/CodeGen/Externs.hsdeleted−96
@@ -1,96 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.CodeGen.Externs
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module generates code for \"externs\" files, i.e. files containing only foreign import declarations.
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.CodeGen.Externs (
17− moduleToPs
18−) where
19−
20−import Data.Maybe (fromMaybe, mapMaybe)
21−import Data.List (intercalate, find)
22−
23−import qualified Data.Map as M
24−
25−import Control.Monad.Writer
26−
27−import Language.PureScript.TypeClassDictionaries
28−import Language.PureScript.Declarations
29−import Language.PureScript.Pretty
30−import Language.PureScript.Names
31−import Language.PureScript.Environment
32−
33−-- |
34−-- Generate foreign imports for all declarations in a module
35−--
36−moduleToPs :: Module -> Environment -> String
37−moduleToPs (Module _ _ Nothing) _ = error "Module exports were not elaborated in moduleToPs"
38−moduleToPs (Module moduleName ds (Just exts)) env = intercalate "\n" . execWriter $ do
39− tell [ "module " ++ runModuleName moduleName ++ " where"]
40− mapM_ declToPs ds
41− mapM_ exportToPs exts
42− where
43−
44− declToPs :: Declaration -> Writer [String] ()
45− declToPs (ImportDeclaration mn _ _) = tell ["import " ++ show mn ++ " ()"]
46− declToPs (FixityDeclaration (Fixity assoc prec) ident) =
47− tell [ unwords [ show assoc, show prec, ident ] ]
48− declToPs (PositionedDeclaration _ d) = declToPs d
49− declToPs _ = return ()
50−
51− exportToPs :: DeclarationRef -> Writer [String] ()
52− exportToPs (PositionedDeclarationRef _ r) = exportToPs r
53− exportToPs (TypeRef pn dctors) = do
54− case Qualified (Just moduleName) pn `M.lookup` types env of
55− Nothing -> error $ show pn ++ " has no kind in exportToPs"
56− Just (kind, ExternData) ->
57− tell ["foreign import data " ++ show pn ++ " :: " ++ prettyPrintKind kind]
58− Just (_, DataType args tys) -> do
59− let dctors' = fromMaybe (map fst tys) dctors
60− printDctor dctor = case dctor `lookup` tys of
61− Nothing -> Nothing
62− Just tyArgs -> Just $ show dctor ++ " " ++ unwords (map prettyPrintTypeAtom tyArgs)
63− tell ["data " ++ show pn ++ " " ++ unwords args ++ (if null dctors' then "" else " = " ++ intercalate " | " (mapMaybe printDctor dctors'))]
64− Just (_, TypeSynonym) ->
65− case Qualified (Just moduleName) pn `M.lookup` typeSynonyms env of
66− Nothing -> error $ show pn ++ " has no type synonym info in exportToPs"
67− Just (args, synTy) ->
68− tell ["type " ++ show pn ++ " " ++ unwords args ++ " = " ++ prettyPrintType synTy]
69− _ -> error "Invalid input in exportToPs"
70−
71− exportToPs (ValueRef ident) =
72− case (moduleName, ident) `M.lookup` names env of
73− Nothing -> error $ show ident ++ " has no type in exportToPs"
74− Just (ty, nameKind) | nameKind == Value || nameKind == Extern ForeignImport || nameKind == Extern InlineJavascript ->
75− tell ["foreign import " ++ show ident ++ " :: " ++ prettyPrintType ty]
76− _ -> return ()
77− exportToPs (TypeClassRef className) =
78− case Qualified (Just moduleName) className `M.lookup` typeClasses env of
79− Nothing -> error $ show className ++ " has no type class definition in exportToPs"
80− Just (args, members, implies) -> do
81− let impliesString = if null implies then "" else "(" ++ intercalate ", " (map (\(pn, tys') -> show pn ++ " " ++ unwords (map prettyPrintTypeAtom tys')) implies) ++ ") <= "
82− tell ["class " ++ impliesString ++ show className ++ " " ++ unwords args ++ " where"]
83− forM_ (filter (isValueExported . fst) members) $ \(member ,ty) ->
84− tell [ " " ++ show member ++ " :: " ++ prettyPrintType ty ]
85−
86− exportToPs (TypeInstanceRef ident) = do
87− let TypeClassDictionaryInScope { tcdClassName = className, tcdInstanceTypes = tys, tcdDependencies = deps} =
88− fromMaybe (error $ "Type class instance has no dictionary in exportToPs") . find ((== Qualified (Just moduleName) ident) . tcdName) $ M.elems $ typeClassDictionaries env
89− let constraintsText = case fromMaybe [] deps of
90− [] -> ""
91− cs -> "(" ++ intercalate ", " (map (\(pn, tys') -> show pn ++ " " ++ unwords (map prettyPrintTypeAtom tys')) cs) ++ ") => "
92− tell ["foreign import instance " ++ show ident ++ " :: " ++ constraintsText ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)]
93−
94− isValueExported :: Ident -> Bool
95− isValueExported ident = ValueRef ident `elem` exts
96−
src/Language/PureScript/CodeGen/JS.hsdeleted−357
@@ -1,357 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.CodeGen.JS
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module generates code in the simplified Javascript intermediate representation from Purescript code
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE DoAndIfThenElse #-}
17−
18−module Language.PureScript.CodeGen.JS (
19− module AST,
20− ModuleType(..),
21− declToJs,
22− moduleToJs,
23− isIdent
24−) where
25−
26−import Data.Maybe (catMaybes, fromJust, fromMaybe)
27−import Data.Function (on)
28−import Data.List (nub, (\\))
29−
30−import Control.Monad (replicateM, forM)
31−import Control.Applicative
32−
33−import qualified Data.Map as M
34−
35−import Language.PureScript.Names
36−import Language.PureScript.Declarations
37−import Language.PureScript.Options
38−import Language.PureScript.CodeGen.JS.AST as AST
39−import Language.PureScript.Types
40−import Language.PureScript.Optimizer
41−import Language.PureScript.CodeGen.Common
42−import Language.PureScript.Environment
43−import Language.PureScript.Supply
44−import Language.PureScript.Traversals (sndM)
45−
46−-- |
47−-- Different types of modules which are supported
48−--
49−data ModuleType = CommonJS | Globals
50−
51−-- |
52−-- Generate code in the simplified Javascript intermediate representation for all declarations in a
53−-- module.
54−--
55−moduleToJs :: (Functor m, Applicative m, Monad m) => ModuleType -> Options -> Module -> Environment -> SupplyT m [JS]
56−moduleToJs mt opts (Module name decls (Just exps)) env = do
57− let jsImports = map (importToJs mt opts) . (\\ [name]) . nub $ concatMap imports decls
58− jsDecls <- mapM (\decl -> declToJs opts name decl env) decls
59− let optimized = concat $ map (map $ optimize opts) $ catMaybes jsDecls
60− let isModuleEmpty = null optimized
61− let moduleBody = JSStringLiteral "use strict" : jsImports ++ optimized
62− let moduleExports = JSObjectLiteral $ concatMap exportToJs exps
63− return $ case mt of
64− CommonJS -> moduleBody ++ [JSAssignment (JSAccessor "exports" (JSVar "module")) moduleExports]
65− Globals | not isModuleEmpty ->
66− [ JSVariableIntroduction (fromJust (optionsBrowserNamespace opts))
67− (Just (JSBinary Or (JSVar (fromJust (optionsBrowserNamespace opts))) (JSObjectLiteral [])) )
68− , JSAssignment (JSAccessor (moduleNameToJs name) (JSVar (fromJust (optionsBrowserNamespace opts))))
69− (JSApp (JSFunction Nothing [] (JSBlock (moduleBody ++ [JSReturn moduleExports]))) [])
70− ]
71− _ -> []
72−moduleToJs _ _ _ _ = error "Exports should have been elaborated in name desugaring"
73−
74−importToJs :: ModuleType -> Options -> ModuleName -> JS
75−importToJs mt opts mn = JSVariableIntroduction (moduleNameToJs mn) (Just moduleBody)
76− where
77− moduleBody = case mt of
78− CommonJS -> JSApp (JSVar "require") [JSStringLiteral (runModuleName mn)]
79− Globals -> JSAccessor (moduleNameToJs mn) (JSVar (fromJust (optionsBrowserNamespace opts)))
80−
81−imports :: Declaration -> [ModuleName]
82−imports =
83− let (f, _, _, _, _) = everythingOnValues (++) (const []) collect (const []) (const []) (const [])
84− in f
85− where
86− collect :: Value -> [ModuleName]
87− collect (Var (Qualified (Just mn) _)) = [mn]
88− collect (Constructor (Qualified (Just mn) _)) = [mn]
89− collect _ = []
90−
91−-- |
92−-- Generate code in the simplified Javascript intermediate representation for a declaration
93−--
94−declToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Declaration -> Environment -> SupplyT m (Maybe [JS])
95−declToJs opts mp (ValueDeclaration ident _ _ _ val) e = do
96− js <- valueToJs opts mp e val
97− return $ Just [JSVariableIntroduction (identToJs ident) (Just js)]
98−declToJs opts mp (BindingGroupDeclaration vals) e = do
99− jss <- flip mapM vals $ \(ident, _, val) -> do
100− js <- valueToJs opts mp e val
101− return $ JSVariableIntroduction (identToJs ident) (Just js)
102− return $ Just jss
103−declToJs _ mp (DataDeclaration _ _ ctors) _ = do
104− return $ Just $ flip concatMap ctors $ \(pn@(ProperName ctor), tys) ->
105− [JSVariableIntroduction ctor (Just (go pn 0 tys []))]
106− where
107− go :: ProperName -> Integer -> [Type] -> [JS] -> JS
108− go pn _ [] values =
109− JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn))), ("values", JSArrayLiteral $ reverse values) ]
110− go pn index (_ : tys') values =
111− JSFunction Nothing ["value" ++ show index]
112− (JSBlock [JSReturn (go pn (index + 1) tys' (JSVar ("value" ++ show index) : values))])
113−declToJs opts mp (DataBindingGroupDeclaration ds) e = do
114− jss <- mapM (\decl -> declToJs opts mp decl e) ds
115− return $ Just $ concat $ catMaybes jss
116−declToJs _ _ (ExternDeclaration _ _ (Just js) _) _ = return $ Just [js]
117−declToJs opts mp (PositionedDeclaration _ d) e = declToJs opts mp d e
118−declToJs _ _ _ _ = return Nothing
119−
120−-- |
121−-- Generate key//value pairs for an object literal exporting values from a module.
122−--
123−exportToJs :: DeclarationRef -> [(String, JS)]
124−exportToJs (TypeRef _ (Just dctors)) = map ((\n -> (n, var (Ident n))) . runProperName) dctors
125−exportToJs (ValueRef name) = [(runIdent name, var name)]
126−exportToJs (TypeInstanceRef name) = [(runIdent name, var name)]
127−exportToJs _ = []
128−
129−-- |
130−-- Generate code in the simplified Javascript intermediate representation for a variable based on a
131−-- PureScript identifier.
132−--
133−var :: Ident -> JS
134−var = JSVar . identToJs
135−
136−-- |
137−-- Generate code in the simplified Javascript intermediate representation for an accessor based on
138−-- a PureScript identifier. If the name is not valid in Javascript (symbol based, reserved name) an
139−-- indexer is returned.
140−--
141−accessor :: Ident -> JS -> JS
142−accessor (Ident prop) = accessorString prop
143−accessor (Op op) = JSIndexer (JSStringLiteral op)
144−
145−accessorString :: String -> JS -> JS
146−accessorString prop | isIdent prop = JSAccessor prop
147− | otherwise = JSIndexer (JSStringLiteral prop)
148−
149−-- |
150−-- Generate code in the simplified Javascript intermediate representation for a value or expression.
151−--
152−valueToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Environment -> Value -> SupplyT m JS
153−valueToJs _ _ _ (NumericLiteral n) = return $ JSNumericLiteral n
154−valueToJs _ _ _ (StringLiteral s) = return $ JSStringLiteral s
155−valueToJs _ _ _ (BooleanLiteral b) = return $ JSBooleanLiteral b
156−valueToJs opts m e (ArrayLiteral xs) = JSArrayLiteral <$> mapM (valueToJs opts m e) xs
157−valueToJs opts m e (ObjectLiteral ps) = JSObjectLiteral <$> mapM (sndM (valueToJs opts m e)) ps
158−valueToJs opts m e (ObjectUpdate o ps) = do
159− obj <- valueToJs opts m e o
160− sts <- mapM (sndM (valueToJs opts m e)) ps
161− extendObj obj sts
162−valueToJs _ m _ (Constructor name) = return $ qualifiedToJS m (Ident . runProperName) name
163−valueToJs opts m e (Case values binders) = do
164− vals <- mapM (valueToJs opts m e) values
165− bindersToJs opts m e binders vals
166−valueToJs opts m e (IfThenElse cond th el) = JSConditional <$> valueToJs opts m e cond <*> valueToJs opts m e th <*> valueToJs opts m e el
167−valueToJs opts m e (Accessor prop val) = accessorString prop <$> valueToJs opts m e val
168−valueToJs opts m e (App val arg) = JSApp <$> valueToJs opts m e val <*> (return <$> valueToJs opts m e arg)
169−valueToJs opts m e (Let ds val) = do
170− decls <- concat . catMaybes <$> mapM (flip (declToJs opts m) e) ds
171− ret <- valueToJs opts m e val
172− return $ JSApp (JSFunction Nothing [] (JSBlock (decls ++ [JSReturn ret]))) []
173−valueToJs opts m e (Abs (Left arg) val) = do
174− ret <- valueToJs opts m e val
175− return $ JSFunction Nothing [identToJs arg] (JSBlock [JSReturn ret])
176−valueToJs opts m e (TypedValue _ (Abs (Left arg) val) ty) | optionsPerformRuntimeTypeChecks opts = do
177− let arg' = identToJs arg
178− ret <- valueToJs opts m e val
179− return $ JSFunction Nothing [arg'] (JSBlock $ runtimeTypeChecks arg' ty ++ [JSReturn ret])
180−valueToJs _ m _ (Var ident) = return $ varToJs m ident
181−valueToJs opts m e (TypedValue _ val _) = valueToJs opts m e val
182−valueToJs opts m e (PositionedValue _ val) = valueToJs opts m e val
183−valueToJs _ _ _ (TypeClassDictionary _ _ _) = error "Type class dictionary was not replaced"
184−valueToJs _ _ _ _ = error "Invalid argument to valueToJs"
185−
186−-- |
187−-- Shallow copy an object.
188−--
189−extendObj :: (Functor m, Applicative m, Monad m) => JS -> [(String, JS)] -> SupplyT m JS
190−extendObj obj sts = do
191− newObj <- freshName
192− key <- freshName
193− let
194− jsKey = JSVar key
195− jsNewObj = JSVar newObj
196− block = JSBlock (objAssign:copy:extend ++ [JSReturn jsNewObj])
197− objAssign = JSVariableIntroduction newObj (Just $ JSObjectLiteral [])
198− copy = JSForIn key obj $ JSBlock [JSIfElse cond assign Nothing]
199− cond = JSApp (JSAccessor "hasOwnProperty" obj) [jsKey]
200− assign = JSBlock [JSAssignment (JSIndexer jsKey jsNewObj) (JSIndexer jsKey obj)]
201− stToAssign (s, js) = JSAssignment (JSAccessor s jsNewObj) js
202− extend = map stToAssign sts
203− return $ JSApp (JSFunction Nothing [] block) []
204−
205−-- |
206−-- Generate code in the simplified Javascript intermediate representation for runtime type checks.
207−--
208−runtimeTypeChecks :: String -> Type -> [JS]
209−runtimeTypeChecks arg ty =
210− let
211− argTy = getFunctionArgumentType ty
212− in
213− maybe [] (argumentCheck (JSVar arg)) argTy
214− where
215− getFunctionArgumentType :: Type -> Maybe Type
216− getFunctionArgumentType (TypeApp (TypeApp t funArg) _) | t == tyFunction = Just funArg
217− getFunctionArgumentType (ForAll _ ty' _) = getFunctionArgumentType ty'
218− getFunctionArgumentType _ = Nothing
219− argumentCheck :: JS -> Type -> [JS]
220− argumentCheck val t | t == tyNumber = [typeCheck val "number"]
221− argumentCheck val t | t == tyString = [typeCheck val "string"]
222− argumentCheck val t | t == tyBoolean = [typeCheck val "boolean"]
223− argumentCheck val (TypeApp t _) | t == tyArray = [arrayCheck val]
224− argumentCheck val (TypeApp t row) | t == tyObject =
225− let
226− (pairs, _) = rowToList row
227− in
228− typeCheck val "object" : concatMap (\(prop, ty') -> argumentCheck (accessorString prop val) ty') pairs
229− argumentCheck val (TypeApp (TypeApp t _) _) | t == tyFunction = [typeCheck val "function"]
230− argumentCheck val (ForAll _ ty' _) = argumentCheck val ty'
231− argumentCheck _ _ = []
232− typeCheck :: JS -> String -> JS
233− typeCheck js ty' = JSIfElse (JSBinary NotEqualTo (JSTypeOf js) (JSStringLiteral ty')) (JSBlock [JSThrow (JSStringLiteral $ ty' ++ " expected")]) Nothing
234− arrayCheck :: JS -> JS
235− arrayCheck js = JSIfElse (JSUnary Not (JSApp (JSAccessor "isArray" (JSVar "Array")) [js])) (JSBlock [JSThrow (JSStringLiteral "Array expected")]) Nothing
236−
237−-- |
238−-- Generate code in the simplified Javascript intermediate representation for a reference to a
239−-- variable.
240−--
241−varToJs :: ModuleName -> Qualified Ident -> JS
242−varToJs _ (Qualified Nothing ident) = var ident
243−varToJs m qual = qualifiedToJS m id qual
244−
245−-- |
246−-- Generate code in the simplified Javascript intermediate representation for a reference to a
247−-- variable that may have a qualified name.
248−--
249−qualifiedToJS :: ModuleName -> (a -> Ident) -> Qualified a -> JS
250−qualifiedToJS m f (Qualified (Just m') a) | m /= m' = accessor (f a) (JSVar (moduleNameToJs m'))
251−qualifiedToJS _ f (Qualified _ a) = JSVar $ identToJs (f a)
252−
253−-- |
254−-- Generate code in the simplified Javascript intermediate representation for pattern match binders
255−-- and guards.
256−--
257−bindersToJs :: (Functor m, Applicative m, Monad m) => Options -> ModuleName -> Environment -> [CaseAlternative] -> [JS] -> SupplyT m JS
258−bindersToJs opts m e binders vals = do
259− valNames <- replicateM (length vals) freshName
260− jss <- forM binders $ \(CaseAlternative bs grd result) -> do
261− ret <- valueToJs opts m e result
262− go valNames [JSReturn ret] bs grd
263− return $ JSApp (JSFunction Nothing valNames (JSBlock (concat jss ++ [JSThrow (JSStringLiteral "Failed pattern match")])))
264− vals
265− where
266− go :: (Functor m, Applicative m, Monad m) => [String] -> [JS] -> [Binder] -> Maybe Guard -> SupplyT m [JS]
267− go _ done [] Nothing = return done
268− go _ done [] (Just cond) = do
269− cond' <- valueToJs opts m e cond
270− return [JSIfElse cond' (JSBlock done) Nothing]
271− go (v:vs) done' (b:bs) grd = do
272− done'' <- go vs done' bs grd
273− binderToJs m e v done'' b
274− go _ _ _ _ = error "Invalid arguments to bindersToJs"
275−
276−-- |
277−-- Generate code in the simplified Javascript intermediate representation for a pattern match
278−-- binder.
279−--
280−binderToJs :: (Functor m, Applicative m, Monad m) => ModuleName -> Environment -> String -> [JS] -> Binder -> SupplyT m [JS]
281−binderToJs _ _ _ done NullBinder = return done
282−binderToJs _ _ varName done (StringBinder str) =
283− return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSStringLiteral str)) (JSBlock done) Nothing]
284−binderToJs _ _ varName done (NumberBinder num) =
285− return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSNumericLiteral num)) (JSBlock done) Nothing]
286−binderToJs _ _ varName done (BooleanBinder True) =
287− return [JSIfElse (JSVar varName) (JSBlock done) Nothing]
288−binderToJs _ _ varName done (BooleanBinder False) =
289− return [JSIfElse (JSUnary Not (JSVar varName)) (JSBlock done) Nothing]
290−binderToJs _ _ varName done (VarBinder ident) =
291− return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : done)
292−binderToJs m e varName done (ConstructorBinder ctor bs) = do
293− js <- go 0 done bs
294− if isOnlyConstructor e ctor
295− then
296− return js
297− else
298− return [JSIfElse (JSBinary EqualTo (JSAccessor "ctor" (JSVar varName)) (JSStringLiteral (show ctor)))
299− (JSBlock js)
300− Nothing]
301− where
302− go :: (Functor m, Applicative m, Monad m) => Integer -> [JS] -> [Binder] -> SupplyT m [JS]
303− go _ done' [] = return done'
304− go index done' (binder:bs') = do
305− argVar <- freshName
306− done'' <- go (index + 1) done' bs'
307− js <- binderToJs m e argVar done'' binder
308− return (JSVariableIntroduction argVar (Just (JSIndexer (JSNumericLiteral (Left index)) (JSAccessor "values" (JSVar varName)))) : js)
309−binderToJs m e varName done (ObjectBinder bs) = go done bs
310− where
311− go :: (Functor m, Applicative m, Monad m) => [JS] -> [(String, Binder)] -> SupplyT m [JS]
312− go done' [] = return done'
313− go done' ((prop, binder):bs') = do
314− propVar <- freshName
315− done'' <- go done' bs'
316− js <- binderToJs m e propVar done'' binder
317− return (JSVariableIntroduction propVar (Just (accessorString prop (JSVar varName))) : js)
318−binderToJs m e varName done (ArrayBinder bs) = do
319− js <- go done 0 bs
320− return [JSIfElse (JSBinary EqualTo (JSAccessor "length" (JSVar varName)) (JSNumericLiteral (Left (fromIntegral $ length bs)))) (JSBlock js) Nothing]
321− where
322− go :: (Functor m, Applicative m, Monad m) => [JS] -> Integer -> [Binder] -> SupplyT m [JS]
323− go done' _ [] = return done'
324− go done' index (binder:bs') = do
325− elVar <- freshName
326− done'' <- go done' (index + 1) bs'
327− js <- binderToJs m e elVar done'' binder
328− return (JSVariableIntroduction elVar (Just (JSIndexer (JSNumericLiteral (Left index)) (JSVar varName))) : js)
329−binderToJs m e varName done (ConsBinder headBinder tailBinder) = do
330− headVar <- freshName
331− tailVar <- freshName
332− js1 <- binderToJs m e headVar done headBinder
333− js2 <- binderToJs m e tailVar js1 tailBinder
334− return [JSIfElse (JSBinary GreaterThan (JSAccessor "length" (JSVar varName)) (JSNumericLiteral (Left 0))) (JSBlock
335− ( JSVariableIntroduction headVar (Just (JSIndexer (JSNumericLiteral (Left 0)) (JSVar varName))) :
336− JSVariableIntroduction tailVar (Just (JSApp (JSAccessor "slice" (JSVar varName)) [JSNumericLiteral (Left 1)])) :
337− js2
338− )) Nothing]
339−binderToJs m e varName done (NamedBinder ident binder) = do
340− js <- binderToJs m e varName done binder
341− return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : js)
342−binderToJs m e varName done (PositionedBinder _ binder) =
343− binderToJs m e varName done binder
344−
345−-- |
346−-- Checks whether a data constructor is the only constructor for that type, used to simplify the
347−-- check when generating code for binders.
348−--
349−isOnlyConstructor :: Environment -> Qualified ProperName -> Bool
350−isOnlyConstructor e ctor =
351− let ty = fromMaybe (error "Data constructor not found") $ ctor `M.lookup` dataConstructors e
352− in numConstructors (ctor, ty) == 1
353− where
354− numConstructors ty = length $ filter (((==) `on` typeConstructor) ty) $ M.toList $ dataConstructors e
355− typeConstructor (Qualified (Just moduleName) _, (tyCtor, _)) = (moduleName, tyCtor)
356− typeConstructor _ = error "Invalid argument to isOnlyConstructor"
357−
src/Language/PureScript/CodeGen/JS/AST.hsdeleted−317
@@ -1,317 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.CodeGen.JS.AST
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Data types for the intermediate simplified-Javascript AST
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE DeriveDataTypeable #-}
17−
18−module Language.PureScript.CodeGen.JS.AST where
19−
20−import Data.Data
21−
22−-- |
23−-- Built-in unary operators
24−--
25−data UnaryOperator
26− -- |
27− -- Numeric negation
28− --
29− = Negate
30− -- |
31− -- Boolean negation
32− --
33− | Not
34− -- |
35− -- Bitwise negation
36− --
37− | BitwiseNot
38− -- |
39− -- Numeric unary \'plus\'
40− --
41− | Positive deriving (Show, Eq, Data, Typeable)
42−
43−-- |
44−-- Built-in binary operators
45−--
46−data BinaryOperator
47− -- |
48− -- Numeric addition
49− --
50− = Add
51− -- |
52− -- Numeric subtraction
53− --
54− | Subtract
55− -- |
56− -- Numeric multiplication
57− --
58− | Multiply
59− -- |
60− -- Numeric division
61− --
62− | Divide
63− -- |
64− -- Remainder
65− --
66− | Modulus
67− -- |
68− -- Generic equality test
69− --
70− | EqualTo
71− -- |
72− -- Generic inequality test
73− --
74− | NotEqualTo
75− -- |
76− -- Numeric less-than
77− --
78− | LessThan
79− -- |
80− -- Numeric less-than-or-equal
81− --
82− | LessThanOrEqualTo
83− -- |
84− -- Numeric greater-than
85− --
86− | GreaterThan
87− -- |
88− -- Numeric greater-than-or-equal
89− --
90− | GreaterThanOrEqualTo
91− -- |
92− -- Boolean and
93− --
94− | And
95− -- |
96− -- Boolean or
97− --
98− | Or
99− -- |
100− -- Bitwise and
101− --
102− | BitwiseAnd
103− -- |
104− -- Bitwise or
105− --
106− | BitwiseOr
107− -- |
108− -- Bitwise xor
109− --
110− | BitwiseXor
111− -- |
112− -- Bitwise left shift
113− --
114− | ShiftLeft
115− -- |
116− -- Bitwise right shift
117− --
118− | ShiftRight
119− -- |
120− -- Bitwise right shift with zero-fill
121− --
122− | ZeroFillShiftRight deriving (Show, Eq, Data, Typeable)
123−
124−-- |
125−-- Data type for simplified Javascript expressions
126−--
127−data JS
128− -- |
129− -- A numeric literal
130− --
131− = JSNumericLiteral (Either Integer Double)
132− -- |
133− -- A string literal
134− --
135− | JSStringLiteral String
136− -- |
137− -- A boolean literal
138− --
139− | JSBooleanLiteral Bool
140− -- |
141− -- A unary operator application
142− --
143− | JSUnary UnaryOperator JS
144− -- |
145− -- A binary operator application
146− --
147− | JSBinary BinaryOperator JS JS
148− -- |
149− -- An array literal
150− --
151− | JSArrayLiteral [JS]
152− -- |
153− -- An array indexer expression
154− --
155− | JSIndexer JS JS
156− -- |
157− -- An object literal
158− --
159− | JSObjectLiteral [(String, JS)]
160− -- |
161− -- An object property accessor expression
162− --
163− | JSAccessor String JS
164− -- |
165− -- A function introduction (optional name, arguments, body)
166− --
167− | JSFunction (Maybe String) [String] JS
168− -- |
169− -- Function application
170− --
171− | JSApp JS [JS]
172− -- |
173− -- Variable
174− --
175− | JSVar String
176− -- |
177− -- Conditional expression
178− --
179− | JSConditional JS JS JS
180− -- |
181− -- A block of expressions in braces
182− --
183− | JSBlock [JS]
184− -- |
185− -- A variable introduction and optional initialization
186− --
187− | JSVariableIntroduction String (Maybe JS)
188− -- |
189− -- A variable assignment
190− --
191− | JSAssignment JS JS
192− -- |
193− -- While loop
194− --
195− | JSWhile JS JS
196− -- |
197− -- For loop
198− --
199− | JSFor String JS JS JS
200− -- |
201− -- ForIn loop
202− --
203− | JSForIn String JS JS
204− -- |
205− -- If-then-else statement
206− --
207− | JSIfElse JS JS (Maybe JS)
208− -- |
209− -- Return statement
210− --
211− | JSReturn JS
212− -- |
213− -- Throw statement
214− --
215− | JSThrow JS
216− -- |
217− -- Type-Of operator
218− --
219− | JSTypeOf JS
220− -- |
221− -- Labelled statement
222− --
223− | JSLabel String JS
224− -- |
225− -- Break statement
226− --
227− | JSBreak String
228− -- |
229− -- Continue statement
230− --
231− | JSContinue String
232− -- |
233− -- Raw Javascript (generated when parsing fails for an inline foreign import declaration)
234− --
235− | JSRaw String deriving (Show, Eq, Data, Typeable)
236−
237−--
238−-- Traversals
239−--
240−
241−everywhereOnJS :: (JS -> JS) -> JS -> JS
242−everywhereOnJS f = go
243− where
244− go :: JS -> JS
245− go (JSUnary op j) = f (JSUnary op (go j))
246− go (JSBinary op j1 j2) = f (JSBinary op (go j1) (go j2))
247− go (JSArrayLiteral js) = f (JSArrayLiteral (map go js))
248− go (JSIndexer j1 j2) = f (JSIndexer (go j1) (go j2))
249− go (JSObjectLiteral js) = f (JSObjectLiteral (map (fmap go) js))
250− go (JSAccessor prop j) = f (JSAccessor prop (go j))
251− go (JSFunction name args j) = f (JSFunction name args (go j))
252− go (JSApp j js) = f (JSApp (go j) (map go js))
253− go (JSConditional j1 j2 j3) = f (JSConditional (go j1) (go j2) (go j3))
254− go (JSBlock js) = f (JSBlock (map go js))
255− go (JSVariableIntroduction name j) = f (JSVariableIntroduction name (fmap go j))
256− go (JSAssignment j1 j2) = f (JSAssignment (go j1) (go j2))
257− go (JSWhile j1 j2) = f (JSWhile (go j1) (go j2))
258− go (JSFor name j1 j2 j3) = f (JSFor name (go j1) (go j2) (go j3))
259− go (JSForIn name j1 j2) = f (JSForIn name (go j1) (go j2))
260− go (JSIfElse j1 j2 j3) = f (JSIfElse (go j1) (go j2) (fmap go j3))
261− go (JSReturn js) = f (JSReturn (go js))
262− go (JSThrow js) = f (JSThrow (go js))
263− go (JSTypeOf js) = f (JSTypeOf (go js))
264− go (JSLabel name js) = f (JSLabel name (go js))
265− go other = f other
266−
267−everywhereOnJSTopDown :: (JS -> JS) -> JS -> JS
268−everywhereOnJSTopDown f = go . f
269− where
270− go :: JS -> JS
271− go (JSUnary op j) = JSUnary op (go (f j))
272− go (JSBinary op j1 j2) = JSBinary op (go (f j1)) (go (f j2))
273− go (JSArrayLiteral js) = JSArrayLiteral (map (go . f) js)
274− go (JSIndexer j1 j2) = JSIndexer (go (f j1)) (go (f j2))
275− go (JSObjectLiteral js) = JSObjectLiteral (map (fmap (go . f)) js)
276− go (JSAccessor prop j) = JSAccessor prop (go (f j))
277− go (JSFunction name args j) = JSFunction name args (go (f j))
278− go (JSApp j js) = JSApp (go (f j)) (map (go . f) js)
279− go (JSConditional j1 j2 j3) = JSConditional (go (f j1)) (go (f j2)) (go (f j3))
280− go (JSBlock js) = JSBlock (map (go . f) js)
281− go (JSVariableIntroduction name j) = JSVariableIntroduction name (fmap (go . f) j)
282− go (JSAssignment j1 j2) = JSAssignment (go (f j1)) (go (f j2))
283− go (JSWhile j1 j2) = JSWhile (go (f j1)) (go (f j2))
284− go (JSFor name j1 j2 j3) = JSFor name (go (f j1)) (go (f j2)) (go (f j3))
285− go (JSForIn name j1 j2) = JSForIn name (go (f j1)) (go (f j2))
286− go (JSIfElse j1 j2 j3) = JSIfElse (go (f j1)) (go (f j2)) (fmap (go . f) j3)
287− go (JSReturn j) = JSReturn (go (f j))
288− go (JSThrow j) = JSThrow (go (f j))
289− go (JSTypeOf j) = JSTypeOf (go (f j))
290− go (JSLabel name j) = JSLabel name (go (f j))
291− go other = f other
292−
293−everythingOnJS :: (r -> r -> r) -> (JS -> r) -> JS -> r
294−everythingOnJS (<>) f = go
295− where
296− go j@(JSUnary _ j1) = f j <> go j1
297− go j@(JSBinary _ j1 j2) = f j <> go j1 <> go j2
298− go j@(JSArrayLiteral js) = foldl (<>) (f j) (map go js)
299− go j@(JSIndexer j1 j2) = f j <> go j1 <> go j2
300− go j@(JSObjectLiteral js) = foldl (<>) (f j) (map (go . snd) js)
301− go j@(JSAccessor _ j1) = f j <> go j1
302− go j@(JSFunction _ _ j1) = f j <> go j1
303− go j@(JSApp j1 js) = foldl (<>) (f j <> go j1) (map go js)
304− go j@(JSConditional j1 j2 j3) = f j <> go j1 <> go j2 <> go j3
305− go j@(JSBlock js) = foldl (<>) (f j) (map go js)
306− go j@(JSVariableIntroduction _ (Just j1)) = f j <> go j1
307− go j@(JSAssignment j1 j2) = f j <> go j1 <> go j2
308− go j@(JSWhile j1 j2) = f j <> go j1 <> go j2
309− go j@(JSFor _ j1 j2 j3) = f j <> go j1 <> go j2 <> go j3
310− go j@(JSForIn _ j1 j2) = f j <> go j1 <> go j2
311− go j@(JSIfElse j1 j2 Nothing) = f j <> go j1 <> go j2
312− go j@(JSIfElse j1 j2 (Just j3)) = f j <> go j1 <> go j2 <> go j3
313− go j@(JSReturn j1) = f j <> go j1
314− go j@(JSThrow j1) = f j <> go j1
315− go j@(JSTypeOf j1) = f j <> go j1
316− go j@(JSLabel _ j1) = f j <> go j1
317− go other = f other
src/Language/PureScript/Constants.hsdeleted−201
@@ -1,201 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Constants
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Various constants which refer to things in the Prelude
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Constants where
17−
18−-- Prelude Operators
19−
20−($) :: String
21−($) = "$"
22−
23−(#) :: String
24−(#) = "#"
25−
26−(++) :: String
27−(++) = "++"
28−
29−(>>=) :: String
30−(>>=) = ">>="
31−
32−(+) :: String
33−(+) = "+"
34−
35−(-) :: String
36−(-) = "-"
37−
38−(*) :: String
39−(*) = "*"
40−
41−(/) :: String
42−(/) = "/"
43−
44−(%) :: String
45−(%) = "%"
46−
47−(<) :: String
48−(<) = "<"
49−
50−(>) :: String
51−(>) = ">"
52−
53−(<=) :: String
54−(<=) = "<="
55−
56−(>=) :: String
57−(>=) = ">="
58−
59−(==) :: String
60−(==) = "=="
61−
62−(/=) :: String
63−(/=) = "/="
64−
65−(&) :: String
66−(&) = "&"
67−
68−bar :: String
69−bar = "|"
70−
71−(^) :: String
72−(^) = "^"
73−
74−(&&) :: String
75−(&&) = "&&"
76−
77−(||) :: String
78−(||) = "||"
79−
80−unsafeIndex :: String
81−unsafeIndex = "unsafeIndex"
82−
83−-- Prelude Operator Functions
84−
85−negate :: String
86−negate = "negate"
87−
88−shl :: String
89−shl = "shl"
90−
91−shr :: String
92−shr = "shr"
93−
94−zshr :: String
95−zshr = "zshr"
96−
97−complement :: String
98−complement = "complement"
99−
100−not :: String
101−not = "not"
102−
103−-- Prelude Values
104−
105−return :: String
106−return = "return"
107−
108−returnEscaped :: String
109−returnEscaped = "$return"
110−
111−untilE :: String
112−untilE = "untilE"
113−
114−whileE :: String
115−whileE = "whileE"
116−
117−runST :: String
118−runST = "runST"
119−
120−runSTArray :: String
121−runSTArray = "runSTArray"
122−
123−stRefValue :: String
124−stRefValue = "value"
125−
126−newSTRef :: String
127−newSTRef = "newSTRef"
128−
129−readSTRef :: String
130−readSTRef = "readSTRef"
131−
132−writeSTRef :: String
133−writeSTRef = "writeSTRef"
134−
135−modifySTRef :: String
136−modifySTRef = "modifySTRef"
137−
138−peekSTArray :: String
139−peekSTArray = "peekSTArray"
140−
141−pokeSTArray :: String
142−pokeSTArray = "pokeSTArray"
143−
144−-- Type Class Dictionary Names
145−
146−monadEffDictionary :: String
147−monadEffDictionary = "monadEff"
148−
149−bindEffDictionary :: String
150−bindEffDictionary = "bindEff"
151−
152−numNumber :: String
153−numNumber = "numNumber"
154−
155−ordNumber :: String
156−ordNumber = "ordNumber"
157−
158−eqNumber :: String
159−eqNumber = "eqNumber"
160−
161−eqString :: String
162−eqString = "eqString"
163−
164−eqBoolean :: String
165−eqBoolean = "eqBoolean"
166−
167−bitsNumber :: String
168−bitsNumber = "bitsNumber"
169−
170−boolLikeBoolean :: String
171−boolLikeBoolean = "boolLikeBoolean"
172−
173−semigroupString :: String
174−semigroupString = "semigroupString"
175−
176−-- Main module
177−
178−main :: String
179−main = "main"
180−
181−-- Code Generation
182−
183−__superclasses :: String
184−__superclasses = "__superclasses"
185−
186−-- Modules
187−
188−prim :: String
189−prim = "Prim"
190−
191−prelude :: String
192−prelude = "Prelude"
193−
194−preludeUnsafe :: String
195−preludeUnsafe = "Prelude_Unsafe"
196−
197−eff :: String
198−eff = "Control_Monad_Eff"
199−
200−st :: String
201−st = "Control_Monad_ST"
src/Language/PureScript/DeadCodeElimination.hsdeleted−105
@@ -1,105 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.DeadCodeElimination
4−-- Copyright : (c) 2014 Phil Freeman
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−module Language.PureScript.DeadCodeElimination (
16− eliminateDeadCode
17−) where
18−
19−import Data.List
20−import Data.Graph
21−import Data.Maybe (mapMaybe)
22−
23−import Language.PureScript.Names
24−import Language.PureScript.Declarations
25−
26−-- |
27−-- Eliminate all declarations which are not a transitive dependency of the entry point module
28−--
29−eliminateDeadCode :: [ModuleName] -> [Module] -> [Module]
30−eliminateDeadCode entryPoints ms = map go ms
31− where
32− go (Module moduleName ds (Just exps)) = Module moduleName ds' (Just exps')
33− where
34− ds' = filter (isUsed moduleName graph vertexFor entryPointVertices) ds
35− exps' = mapMaybe (filterExport ds') exps
36− go _ = error "Exports should have been elaborated in name desugaring"
37− declarations = concatMap declarationsByModule ms
38− (graph, _, vertexFor) = graphFromEdges $ map (\(key, deps) -> (key, key, deps)) declarations
39− entryPointVertices = mapMaybe (vertexFor . fst) . filter (\((mn, _), _) -> mn `elem` entryPoints) $ declarations
40−
41− filterExport :: [Declaration] -> DeclarationRef -> Maybe DeclarationRef
42− filterExport decls r@(TypeRef name _) | (any $ typeExists name) decls = Just r
43− filterExport decls r@(ValueRef name) | (any $ valueExists name) decls = Just r
44− filterExport decls r@(TypeInstanceRef name) | (any $ valueExists name) decls = Just r
45− filterExport _ _ = Nothing
46−
47− valueExists :: Ident -> Declaration -> Bool
48− valueExists name (ValueDeclaration name' _ _ _ _) = name == name'
49− valueExists name (ExternDeclaration _ name' _ _) = name == name'
50− valueExists name (BindingGroupDeclaration decls) = any (\(name', _, _) -> name == name') decls
51− valueExists name (PositionedDeclaration _ d) = valueExists name d
52− valueExists _ _ = False
53−
54− typeExists :: ProperName -> Declaration -> Bool
55− typeExists name (DataDeclaration name' _ _) = name == name'
56− typeExists name (DataBindingGroupDeclaration decls) = any (typeExists name) decls
57− typeExists name (PositionedDeclaration _ d) = typeExists name d
58− typeExists _ _ = False
59−
60−type Key = (ModuleName, Either Ident ProperName)
61−
62−declarationsByModule :: Module -> [(Key, [Key])]
63−declarationsByModule (Module moduleName ds _) = concatMap go ds
64− where
65− go :: Declaration -> [(Key, [Key])]
66− go d@(ValueDeclaration name _ _ _ _) = [((moduleName, Left name), dependencies moduleName d)]
67− go (DataDeclaration _ _ dctors) = map (\(name, _) -> ((moduleName, Right name), [])) dctors
68− go (ExternDeclaration _ name _ _) = [((moduleName, Left name), [])]
69− go d@(BindingGroupDeclaration names') = map (\(name, _, _) -> ((moduleName, Left name), dependencies moduleName d)) names'
70− go (DataBindingGroupDeclaration ds') = concatMap go ds'
71− go (PositionedDeclaration _ d) = go d
72− go _ = []
73−
74−dependencies :: ModuleName -> Declaration -> [Key]
75−dependencies moduleName =
76− let (f, _, _, _, _) = everythingOnValues (++) (const []) values (const []) (const []) (const [])
77− in nub . f
78− where
79− values :: Value -> [Key]
80− values (Var ident) = let (mn, name) = qualify moduleName ident in [(mn, Left name)]
81− values (Constructor (Qualified (Just mn) name)) = [(mn, Right name)]
82− values (Constructor (Qualified Nothing _)) = error "Found unqualified data constructor"
83− values _ = []
84−
85−isUsed :: ModuleName -> Graph -> (Key -> Maybe Vertex) -> [Vertex] -> Declaration -> Bool
86−isUsed moduleName graph vertexFor entryPointVertices (ValueDeclaration name _ _ _ _) =
87− let Just v' = vertexFor (moduleName, Left name)
88− in any (\v -> path graph v v') entryPointVertices
89−isUsed moduleName graph vertexFor entryPointVertices (FixityDeclaration _ name) =
90− let Just v' = vertexFor (moduleName, Left $ Op name)
91− in any (\v -> path graph v v') entryPointVertices
92−isUsed moduleName graph vertexFor entryPointVertices (DataDeclaration _ _ dctors) =
93− any (\(pn, _) -> let Just v' = vertexFor (moduleName, Right pn)
94− in any (\v -> path graph v v') entryPointVertices) dctors
95−isUsed moduleName graph vertexFor entryPointVertices (ExternDeclaration _ name _ _) =
96− let Just v' = vertexFor (moduleName, Left name)
97− in any (\v -> path graph v v') entryPointVertices
98−isUsed moduleName graph vertexFor entryPointVertices (BindingGroupDeclaration ds) =
99− any (\(name, _, _) -> let Just v' = vertexFor (moduleName, Left name)
100− in any (\v -> path graph v v') entryPointVertices) ds
101−isUsed moduleName graph vertexFor entryPointVertices (DataBindingGroupDeclaration ds) =
102− any (isUsed moduleName graph vertexFor entryPointVertices) ds
103−isUsed moduleName graph vertexFor entryPointVertices (PositionedDeclaration _ d) =
104− isUsed moduleName graph vertexFor entryPointVertices d
105−isUsed _ _ _ _ _ = True
src/Language/PureScript/Declarations.hsdeleted−820
@@ -1,820 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Declarations
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- | Data types for modules and declarations
12−--
13−-----------------------------------------------------------------------------
14−
15−{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables #-}
16−
17−module Language.PureScript.Declarations where
18−
19−import Data.Monoid (Monoid(..), mconcat)
20−
21−import qualified Data.Data as D
22−
23−import Control.Applicative
24−import Control.Monad
25−
26−import Language.PureScript.Types
27−import Language.PureScript.Names
28−import Language.PureScript.Kinds
29−import Language.PureScript.TypeClassDictionaries
30−import Language.PureScript.CodeGen.JS.AST
31−import Language.PureScript.Environment
32−import Language.PureScript.Traversals
33−
34−-- |
35−-- A precedence level for an infix operator
36−--
37−type Precedence = Integer
38−
39−-- |
40−-- Associativity for infix operators
41−--
42−data Associativity = Infixl | Infixr | Infix deriving (D.Data, D.Typeable)
43−
44−instance Show Associativity where
45− show Infixl = "infixl"
46− show Infixr = "infixr"
47− show Infix = "infix"
48−
49−-- |
50−-- Source position information
51−--
52−data SourcePos = SourcePos
53− { -- |
54− -- Source name
55− --
56− sourceName :: String
57− -- |
58− -- Line number
59− --
60− , sourcePosLine :: Int
61− -- |
62− -- Column number
63− --
64− , sourcePosColumn :: Int
65− } deriving (D.Data, D.Typeable)
66−
67−instance Show SourcePos where
68− show sp = (sourceName sp) ++ " line " ++ show (sourcePosLine sp) ++ ", column " ++ show (sourcePosColumn sp)
69−
70−-- |
71−-- Fixity data for infix operators
72−--
73−data Fixity = Fixity Associativity Precedence deriving (Show, D.Data, D.Typeable)
74−
75−-- |
76−-- A module declaration, consisting of a module name, a list of declarations, and a list of the
77−-- declarations that are explicitly exported. If the export list is Nothing, everything is exported.
78−--
79−data Module = Module ModuleName [Declaration] (Maybe [DeclarationRef]) deriving (Show, D.Data, D.Typeable)
80−
81−-- |
82−-- An item in a list of explicit imports or exports
83−--
84−data DeclarationRef
85− -- |
86− -- A type constructor with data constructors
87− --
88− = TypeRef ProperName (Maybe [ProperName])
89− -- |
90− -- A value
91− --
92− | ValueRef Ident
93− -- |
94− -- A type class
95− --
96− | TypeClassRef ProperName
97− -- |
98− -- A type class instance, created during typeclass desugaring (name, class name, instance types)
99− --
100− | TypeInstanceRef Ident
101− -- |
102− -- A declaration reference with source position information
103− --
104− | PositionedDeclarationRef SourcePos DeclarationRef
105− deriving (Show, D.Data, D.Typeable)
106−
107−instance Eq DeclarationRef where
108− (TypeRef name dctors) == (TypeRef name' dctors') = name == name' && dctors == dctors'
109− (ValueRef name) == (ValueRef name') = name == name'
110− (TypeClassRef name) == (TypeClassRef name') = name == name'
111− (TypeInstanceRef name) == (TypeInstanceRef name') = name == name'
112− (PositionedDeclarationRef _ r) == r' = r == r'
113− r == (PositionedDeclarationRef _ r') = r == r'
114− _ == _ = False
115−
116−-- |
117−-- The data type of declarations
118−--
119−data Declaration
120− -- |
121− -- A data type declaration (name, arguments, data constructors)
122− --
123− = DataDeclaration ProperName [String] [(ProperName, [Type])]
124− -- |
125− -- A minimal mutually recursive set of data type declarations
126− --
127− | DataBindingGroupDeclaration [Declaration]
128− -- |
129− -- A type synonym declaration (name, arguments, type)
130− --
131− | TypeSynonymDeclaration ProperName [String] Type
132− -- |
133− -- A type declaration for a value (name, ty)
134− --
135− | TypeDeclaration Ident Type
136− -- |
137− -- A value declaration (name, top-level binders, optional guard, value)
138− --
139− | ValueDeclaration Ident NameKind [Binder] (Maybe Guard) Value
140− -- |
141− -- A minimal mutually recursive set of value declarations
142− --
143− | BindingGroupDeclaration [(Ident, NameKind, Value)]
144− -- |
145− -- A foreign import declaration (type, name, optional inline Javascript, type)
146− --
147− | ExternDeclaration ForeignImportType Ident (Maybe JS) Type
148− -- |
149− -- A data type foreign import (name, kind)
150− --
151− | ExternDataDeclaration ProperName Kind
152− -- |
153− -- A type class instance foreign import
154− --
155− | ExternInstanceDeclaration Ident [(Qualified ProperName, [Type])] (Qualified ProperName) [Type]
156− -- |
157− -- A fixity declaration (fixity data, operator name)
158− --
159− | FixityDeclaration Fixity String
160− -- |
161− -- A module import (module name, optional set of identifiers to import, optional "qualified as"
162− -- name)
163− --
164− | ImportDeclaration ModuleName (Maybe [DeclarationRef]) (Maybe ModuleName)
165− -- |
166− -- A type class declaration (name, argument, implies, member declarations)
167− --
168− | TypeClassDeclaration ProperName [String] [(Qualified ProperName, [Type])] [Declaration]
169− -- |
170− -- A type instance declaration (name, dependencies, class name, instance types, member
171− -- declarations)
172− --
173− | TypeInstanceDeclaration Ident [(Qualified ProperName, [Type])] (Qualified ProperName) [Type] [Declaration]
174− -- |
175− -- A declaration with source position information
176− --
177− | PositionedDeclaration SourcePos Declaration
178− deriving (Show, D.Data, D.Typeable)
179−
180−-- |
181−-- Test if a declaration is a value declaration
182−--
183−isValueDecl :: Declaration -> Bool
184−isValueDecl ValueDeclaration{} = True
185−isValueDecl (PositionedDeclaration _ d) = isValueDecl d
186−isValueDecl _ = False
187−
188−-- |
189−-- Test if a declaration is a data type or type synonym declaration
190−--
191−isDataDecl :: Declaration -> Bool
192−isDataDecl DataDeclaration{} = True
193−isDataDecl TypeSynonymDeclaration{} = True
194−isDataDecl (PositionedDeclaration _ d) = isDataDecl d
195−isDataDecl _ = False
196−
197−-- |
198−-- Test if a declaration is a module import
199−--
200−isImportDecl :: Declaration -> Bool
201−isImportDecl ImportDeclaration{} = True
202−isImportDecl (PositionedDeclaration _ d) = isImportDecl d
203−isImportDecl _ = False
204−
205−-- |
206−-- Test if a declaration is a data type foreign import
207−--
208−isExternDataDecl :: Declaration -> Bool
209−isExternDataDecl ExternDataDeclaration{} = True
210−isExternDataDecl (PositionedDeclaration _ d) = isExternDataDecl d
211−isExternDataDecl _ = False
212−
213−-- |
214−-- Test if a declaration is a type class instance foreign import
215−--
216−isExternInstanceDecl :: Declaration -> Bool
217−isExternInstanceDecl ExternInstanceDeclaration{} = True
218−isExternInstanceDecl (PositionedDeclaration _ d) = isExternInstanceDecl d
219−isExternInstanceDecl _ = False
220−
221−-- |
222−-- Test if a declaration is a fixity declaration
223−--
224−isFixityDecl :: Declaration -> Bool
225−isFixityDecl FixityDeclaration{} = True
226−isFixityDecl (PositionedDeclaration _ d) = isFixityDecl d
227−isFixityDecl _ = False
228−
229−-- |
230−-- Test if a declaration is a foreign import
231−--
232−isExternDecl :: Declaration -> Bool
233−isExternDecl ExternDeclaration{} = True
234−isExternDecl (PositionedDeclaration _ d) = isExternDecl d
235−isExternDecl _ = False
236−
237−-- |
238−-- Test if a declaration is a type class or instance declaration
239−--
240−isTypeClassDeclaration :: Declaration -> Bool
241−isTypeClassDeclaration TypeClassDeclaration{} = True
242−isTypeClassDeclaration TypeInstanceDeclaration{} = True
243−isTypeClassDeclaration (PositionedDeclaration _ d) = isTypeClassDeclaration d
244−isTypeClassDeclaration _ = False
245−
246−-- |
247−-- A guard is just a boolean-valued expression that appears alongside a set of binders
248−--
249−type Guard = Value
250−
251−-- |
252−-- Data type for values
253−--
254−data Value
255− -- |
256− -- A numeric literal
257− --
258− = NumericLiteral (Either Integer Double)
259− -- |
260− -- A string literal
261− --
262− | StringLiteral String
263− -- |
264− -- A boolean literal
265− --
266− | BooleanLiteral Bool
267− -- |
268− -- A prefix -, will be desugared
269− --
270− | UnaryMinus Value
271− -- |
272− -- Binary operator application. During the rebracketing phase of desugaring, this data constructor
273− -- will be removed.
274− --
275− | BinaryNoParens (Qualified Ident) Value Value
276− -- |
277− -- Explicit parentheses. During the rebracketing phase of desugaring, this data constructor
278− -- will be removed.
279− --
280− | Parens Value
281− -- |
282− -- An array literal
283− --
284− | ArrayLiteral [Value]
285− -- |
286− -- An object literal
287− --
288− | ObjectLiteral [(String, Value)]
289− -- |
290− -- An record property accessor expression
291− --
292− | Accessor String Value
293− -- |
294− -- Partial record update
295− --
296− | ObjectUpdate Value [(String, Value)]
297− -- |
298− -- Function introduction
299− --
300− | Abs (Either Ident Binder) Value
301− -- |
302− -- Function application
303− --
304− | App Value Value
305− -- |
306− -- Variable
307− --
308− | Var (Qualified Ident)
309− -- |
310− -- Conditional (if-then-else expression)
311− --
312− | IfThenElse Value Value Value
313− -- |
314− -- A data constructor
315− --
316− | Constructor (Qualified ProperName)
317− -- |
318− -- A case expression. During the case expansion phase of desugaring, top-level binders will get
319− -- desugared into case expressions, hence the need for guards and multiple binders per branch here.
320− --
321− | Case [Value] [CaseAlternative]
322− -- |
323− -- A value with a type annotation
324− --
325− | TypedValue Bool Value Type
326− -- |
327− -- A let binding
328− --
329− | Let [Declaration] Value
330− -- |
331− -- A do-notation block
332− --
333− | Do [DoNotationElement]
334− -- |
335− -- A placeholder for a type class dictionary to be inserted later. At the end of type checking, these
336− -- placeholders will be replaced with actual expressions representing type classes dictionaries which
337− -- can be evaluated at runtime. The constructor arguments represent (in order): whether or not to look
338− -- at superclass implementations when searching for a dictionary, the type class name and
339− -- instance type, and the type class dictionaries in scope.
340− --
341− | TypeClassDictionary Bool (Qualified ProperName, [Type]) [TypeClassDictionaryInScope]
342− -- |
343− -- A placeholder for a superclass dictionary to be turned into a TypeClassDictionary during typechecking
344− --
345− | SuperClassDictionary (Qualified ProperName) [Type]
346− -- |
347− -- A value with source position information
348− --
349− | PositionedValue SourcePos Value deriving (Show, D.Data, D.Typeable)
350−
351−-- |
352−-- An alternative in a case statement
353−--
354−data CaseAlternative = CaseAlternative
355− { -- |
356− -- A collection of binders with which to match the inputs
357− --
358− caseAlternativeBinders :: [Binder]
359− -- |
360− -- An optional guard
361− --
362− , caseAlternativeGuard :: Maybe Guard
363− -- |
364− -- The result expression
365− --
366− , caseAlternativeResult :: Value
367− } deriving (Show, D.Data, D.Typeable)
368−
369−-- |
370−-- Find the original dictionary which a type class dictionary in scope refers to
371−--
372−canonicalizeDictionary :: TypeClassDictionaryInScope -> Qualified Ident
373−canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDRegular, tcdName = nm }) = nm
374−canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDAlias nm }) = nm
375−
376−-- |
377−-- A statement in a do-notation block
378−--
379−data DoNotationElement
380− -- |
381− -- A monadic value without a binder
382− --
383− = DoNotationValue Value
384− -- |
385− -- A monadic value with a binder
386− --
387− | DoNotationBind Binder Value
388− -- |
389− -- A let statement, i.e. a pure value with a binder
390− --
391− | DoNotationLet [Declaration]
392− -- |
393− -- A do notation element with source position information
394− --
395− | PositionedDoNotationElement SourcePos DoNotationElement deriving (Show, D.Data, D.Typeable)
396−
397−-- |
398−-- Data type for binders
399−--
400−data Binder
401− -- |
402− -- Wildcard binder
403− --
404− = NullBinder
405− -- |
406− -- A binder which matches a boolean literal
407− --
408− | BooleanBinder Bool
409− -- |
410− -- A binder which matches a string literal
411− --
412− | StringBinder String
413− -- |
414− -- A binder which matches a numeric literal
415− --
416− | NumberBinder (Either Integer Double)
417− -- |
418− -- A binder which binds an identifier
419− --
420− | VarBinder Ident
421− -- |
422− -- A binder which matches a data constructor
423− --
424− | ConstructorBinder (Qualified ProperName) [Binder]
425− -- |
426− -- A binder which matches a record and binds its properties
427− --
428− | ObjectBinder [(String, Binder)]
429− -- |
430− -- A binder which matches an array and binds its elements
431− --
432− | ArrayBinder [Binder]
433− -- |
434− -- A binder which matches an array and binds its head and tail
435− --
436− | ConsBinder Binder Binder
437− -- |
438− -- A binder which binds its input to an identifier
439− --
440− | NamedBinder Ident Binder
441− -- |
442− -- A binder with source position information
443− --
444− | PositionedBinder SourcePos Binder deriving (Show, D.Data, D.Typeable)
445−
446−-- |
447−-- Collect all names introduced in binders in an expression
448−--
449−binderNames :: Binder -> [Ident]
450−binderNames = go []
451− where
452− go ns (VarBinder name) = name : ns
453− go ns (ConstructorBinder _ bs) = foldl go ns bs
454− go ns (ObjectBinder bs) = foldl go ns (map snd bs)
455− go ns (ArrayBinder bs) = foldl go ns bs
456− go ns (ConsBinder b1 b2) = go (go ns b1) b2
457− go ns (NamedBinder name b) = go (name : ns) b
458− go ns (PositionedBinder _ b) = go ns b
459− go ns _ = ns
460−
461−--
462−-- Traversals
463−--
464−
465−everywhereOnValues :: (Declaration -> Declaration) ->
466− (Value -> Value) ->
467− (Binder -> Binder) ->
468− (Declaration -> Declaration, Value -> Value, Binder -> Binder)
469−everywhereOnValues f g h = (f', g', h')
470− where
471− f' :: Declaration -> Declaration
472− f' (DataBindingGroupDeclaration ds) = f (DataBindingGroupDeclaration (map f' ds))
473− f' (ValueDeclaration name nameKind bs grd val) = f (ValueDeclaration name nameKind (map h' bs) (fmap g' grd) (g' val))
474− f' (BindingGroupDeclaration ds) = f (BindingGroupDeclaration (map (\(name, nameKind, val) -> (name, nameKind, g' val)) ds))
475− f' (TypeClassDeclaration name args implies ds) = f (TypeClassDeclaration name args implies (map f' ds))
476− f' (TypeInstanceDeclaration name cs className args ds) = f (TypeInstanceDeclaration name cs className args (map f' ds))
477− f' (PositionedDeclaration pos d) = f (PositionedDeclaration pos (f' d))
478− f' other = f other
479−
480− g' :: Value -> Value
481− g' (UnaryMinus v) = g (UnaryMinus (g' v))
482− g' (BinaryNoParens op v1 v2) = g (BinaryNoParens op (g' v1) (g' v2))
483− g' (Parens v) = g (Parens (g' v))
484− g' (ArrayLiteral vs) = g (ArrayLiteral (map g' vs))
485− g' (ObjectLiteral vs) = g (ObjectLiteral (map (fmap g') vs))
486− g' (Accessor prop v) = g (Accessor prop (g' v))
487− g' (ObjectUpdate obj vs) = g (ObjectUpdate (g' obj) (map (fmap g') vs))
488− g' (Abs name v) = g (Abs name (g' v))
489− g' (App v1 v2) = g (App (g' v1) (g' v2))
490− g' (IfThenElse v1 v2 v3) = g (IfThenElse (g' v1) (g' v2) (g' v3))
491− g' (Case vs alts) = g (Case (map g' vs) (map handleCaseAlternative alts))
492− g' (TypedValue check v ty) = g (TypedValue check (g' v) ty)
493− g' (Let ds v) = g (Let (map f' ds) (g' v))
494− g' (Do es) = g (Do (map handleDoNotationElement es))
495− g' (PositionedValue pos v) = g (PositionedValue pos (g' v))
496− g' other = g other
497−
498− h' :: Binder -> Binder
499− h' (ConstructorBinder ctor bs) = h (ConstructorBinder ctor (map h' bs))
500− h' (ObjectBinder bs) = h (ObjectBinder (map (fmap h') bs))
501− h' (ArrayBinder bs) = h (ArrayBinder (map h' bs))
502− h' (ConsBinder b1 b2) = h (ConsBinder (h' b1) (h' b2))
503− h' (NamedBinder name b) = h (NamedBinder name (h' b))
504− h' (PositionedBinder pos b) = h (PositionedBinder pos (h' b))
505− h' other = h other
506−
507− handleCaseAlternative :: CaseAlternative -> CaseAlternative
508− handleCaseAlternative ca =
509− ca { caseAlternativeBinders = map h' (caseAlternativeBinders ca)
510− , caseAlternativeGuard = fmap g' (caseAlternativeGuard ca)
511− , caseAlternativeResult = g' (caseAlternativeResult ca)
512− }
513−
514− handleDoNotationElement :: DoNotationElement -> DoNotationElement
515− handleDoNotationElement (DoNotationValue v) = DoNotationValue (g' v)
516− handleDoNotationElement (DoNotationBind b v) = DoNotationBind (h' b) (g' v)
517− handleDoNotationElement (DoNotationLet ds) = DoNotationLet (map f' ds)
518− handleDoNotationElement (PositionedDoNotationElement pos e) = PositionedDoNotationElement pos (handleDoNotationElement e)
519−
520−
521−everywhereOnValuesTopDownM :: (Functor m, Applicative m, Monad m) =>
522− (Declaration -> m Declaration) ->
523− (Value -> m Value) ->
524− (Binder -> m Binder) ->
525− (Declaration -> m Declaration, Value -> m Value, Binder -> m Binder)
526−everywhereOnValuesTopDownM f g h = (f' <=< f, g' <=< g, h' <=< h)
527− where
528− f' (DataBindingGroupDeclaration ds) = DataBindingGroupDeclaration <$> mapM (f' <=< f) ds
529− f' (ValueDeclaration name nameKind bs grd val) = ValueDeclaration name nameKind <$> mapM (h' <=< h) bs <*> maybeM (g' <=< g) grd <*> (g val >>= g')
530− f' (BindingGroupDeclaration ds) = BindingGroupDeclaration <$> mapM (\(name, nameKind, val) -> (,,) name nameKind <$> (g val >>= g')) ds
531− f' (TypeClassDeclaration name args implies ds) = TypeClassDeclaration name args implies <$> mapM (f' <=< f) ds
532− f' (TypeInstanceDeclaration name cs className args ds) = TypeInstanceDeclaration name cs className args <$> mapM (f' <=< f) ds
533− f' (PositionedDeclaration pos d) = PositionedDeclaration pos <$> (f d >>= f')
534− f' other = f other
535−
536− g' (UnaryMinus v) = UnaryMinus <$> (g v >>= g')
537− g' (BinaryNoParens op v1 v2) = BinaryNoParens op <$> (g v1 >>= g') <*> (g v2 >>= g')
538− g' (Parens v) = Parens <$> (g v >>= g')
539− g' (ArrayLiteral vs) = ArrayLiteral <$> mapM (g' <=< g) vs
540− g' (ObjectLiteral vs) = ObjectLiteral <$> mapM (sndM (g' <=< g)) vs
541− g' (Accessor prop v) = Accessor prop <$> (g v >>= g')
542− g' (ObjectUpdate obj vs) = ObjectUpdate <$> (g obj >>= g') <*> mapM (sndM (g' <=< g)) vs
543− g' (Abs name v) = Abs name <$> (g v >>= g')
544− g' (App v1 v2) = App <$> (g v1 >>= g') <*> (g v2 >>= g')
545− g' (IfThenElse v1 v2 v3) = IfThenElse <$> (g v1 >>= g') <*> (g v2 >>= g') <*> (g v3 >>= g')
546− g' (Case vs alts) = Case <$> mapM (g' <=< g) vs <*> mapM handleCaseAlternative alts
547− g' (TypedValue check v ty) = TypedValue check <$> (g v >>= g') <*> pure ty
548− g' (Let ds v) = Let <$> mapM (f' <=< f) ds <*> (g v >>= g')
549− g' (Do es) = Do <$> mapM handleDoNotationElement es
550− g' (PositionedValue pos v) = PositionedValue pos <$> (g v >>= g')
551− g' other = g other
552−
553− h' (ConstructorBinder ctor bs) = ConstructorBinder ctor <$> mapM (h' <=< h) bs
554− h' (ObjectBinder bs) = ObjectBinder <$> mapM (sndM (h' <=< h)) bs
555− h' (ArrayBinder bs) = ArrayBinder <$> mapM (h' <=< h) bs
556− h' (ConsBinder b1 b2) = ConsBinder <$> (h b1 >>= h') <*> (h b2 >>= h')
557− h' (NamedBinder name b) = NamedBinder name <$> (h b >>= h')
558− h' (PositionedBinder pos b) = PositionedBinder pos <$> (h b >>= h')
559− h' other = h other
560−
561− handleCaseAlternative (CaseAlternative bs grd val) = CaseAlternative <$> mapM (h' <=< h) bs
562− <*> maybeM (g' <=< g) grd
563− <*> (g' <=< g) val
564−
565− handleDoNotationElement (DoNotationValue v) = DoNotationValue <$> (g' <=< g) v
566− handleDoNotationElement (DoNotationBind b v) = DoNotationBind <$> (h' <=< h) b <*> (g' <=< g) v
567− handleDoNotationElement (DoNotationLet ds) = DoNotationLet <$> mapM (f' <=< f) ds
568− handleDoNotationElement (PositionedDoNotationElement pos e) = PositionedDoNotationElement pos <$> handleDoNotationElement e
569−
570−everywhereOnValuesM :: (Functor m, Applicative m, Monad m) =>
571− (Declaration -> m Declaration) ->
572− (Value -> m Value) ->
573− (Binder -> m Binder) ->
574− (Declaration -> m Declaration, Value -> m Value, Binder -> m Binder)
575−everywhereOnValuesM f g h = (f' <=< f, g' <=< g, h' <=< h)
576− where
577− f' (DataBindingGroupDeclaration ds) = (DataBindingGroupDeclaration <$> mapM f' ds) >>= f
578− f' (ValueDeclaration name nameKind bs grd val) = (ValueDeclaration name nameKind <$> mapM h' bs <*> maybeM g' grd <*> g' val) >>= f
579− f' (BindingGroupDeclaration ds) = (BindingGroupDeclaration <$> mapM (\(name, nameKind, val) -> (,,) name nameKind <$> g' val) ds) >>= f
580− f' (TypeClassDeclaration name args implies ds) = (TypeClassDeclaration name args implies <$> mapM f' ds) >>= f
581− f' (TypeInstanceDeclaration name cs className args ds) = (TypeInstanceDeclaration name cs className args <$> mapM f' ds) >>= f
582− f' (PositionedDeclaration pos d) = (PositionedDeclaration pos <$> f' d) >>= f
583− f' other = f other
584−
585− g' (UnaryMinus v) = (UnaryMinus <$> g' v) >>= g
586− g' (BinaryNoParens op v1 v2) = (BinaryNoParens op <$> (g' v1) <*> (g' v2)) >>= g
587− g' (Parens v) = (Parens <$> g' v) >>= g
588− g' (ArrayLiteral vs) = (ArrayLiteral <$> mapM g' vs) >>= g
589− g' (ObjectLiteral vs) = (ObjectLiteral <$> mapM (sndM g') vs) >>= g
590− g' (Accessor prop v) = (Accessor prop <$> g' v) >>= g
591− g' (ObjectUpdate obj vs) = (ObjectUpdate <$> g' obj <*> mapM (sndM g') vs) >>= g
592− g' (Abs name v) = (Abs name <$> g' v) >>= g
593− g' (App v1 v2) = (App <$> g' v1 <*> g' v2) >>= g
594− g' (IfThenElse v1 v2 v3) = (IfThenElse <$> g' v1 <*> g' v2 <*> g' v3) >>= g
595− g' (Case vs alts) = (Case <$> mapM g' vs <*> mapM handleCaseAlternative alts) >>= g
596− g' (TypedValue check v ty) = (TypedValue check <$> g' v <*> pure ty) >>= g
597− g' (Let ds v) = (Let <$> mapM f' ds <*> g' v) >>= g
598− g' (Do es) = (Do <$> mapM handleDoNotationElement es) >>= g
599− g' (PositionedValue pos v) = (PositionedValue pos <$> g' v) >>= g
600− g' other = g other
601−
602− h' (ConstructorBinder ctor bs) = (ConstructorBinder ctor <$> mapM h' bs) >>= h
603− h' (ObjectBinder bs) = (ObjectBinder <$> mapM (sndM h') bs) >>= h
604− h' (ArrayBinder bs) = (ArrayBinder <$> mapM h' bs) >>= h
605− h' (ConsBinder b1 b2) = (ConsBinder <$> h' b1 <*> h' b2) >>= h
606− h' (NamedBinder name b) = (NamedBinder name <$> h' b) >>= h
607− h' (PositionedBinder pos b) = (PositionedBinder pos <$> h' b) >>= h
608− h' other = h other
609−
610− handleCaseAlternative (CaseAlternative bs grd val) = CaseAlternative <$> mapM h' bs
611− <*> maybeM g' grd
612− <*> g' val
613−
614− handleDoNotationElement (DoNotationValue v) = DoNotationValue <$> g' v
615− handleDoNotationElement (DoNotationBind b v) = DoNotationBind <$> h' b <*> g' v
616− handleDoNotationElement (DoNotationLet ds) = DoNotationLet <$> mapM f' ds
617− handleDoNotationElement (PositionedDoNotationElement pos e) = PositionedDoNotationElement pos <$> handleDoNotationElement e
618−
619−everythingOnValues :: (r -> r -> r) ->
620− (Declaration -> r) ->
621− (Value -> r) ->
622− (Binder -> r) ->
623− (CaseAlternative -> r) ->
624− (DoNotationElement -> r) ->
625− (Declaration -> r, Value -> r, Binder -> r, CaseAlternative -> r, DoNotationElement -> r)
626−everythingOnValues (<>) f g h i j = (f', g', h', i', j')
627− where
628− f' d@(DataBindingGroupDeclaration ds) = foldl (<>) (f d) (map f' ds)
629− f' d@(ValueDeclaration _ _ bs Nothing val) = foldl (<>) (f d) (map h' bs) <> g' val
630− f' d@(ValueDeclaration _ _ bs (Just grd) val) = foldl (<>) (f d) (map h' bs) <> g' grd <> g' val
631− f' d@(BindingGroupDeclaration ds) = foldl (<>) (f d) (map (\(_, _, val) -> g' val) ds)
632− f' d@(TypeClassDeclaration _ _ _ ds) = foldl (<>) (f d) (map f' ds)
633− f' d@(TypeInstanceDeclaration _ _ _ _ ds) = foldl (<>) (f d) (map f' ds)
634− f' d@(PositionedDeclaration _ d1) = f d <> f' d1
635− f' d = f d
636−
637− g' v@(UnaryMinus v1) = g v <> g' v1
638− g' v@(BinaryNoParens _ v1 v2) = g v <> g' v1 <> g' v2
639− g' v@(Parens v1) = g v <> g' v1
640− g' v@(ArrayLiteral vs) = foldl (<>) (g v) (map g' vs)
641− g' v@(ObjectLiteral vs) = foldl (<>) (g v) (map (g' . snd) vs)
642− g' v@(Accessor _ v1) = g v <> g' v1
643− g' v@(ObjectUpdate obj vs) = foldl (<>) (g v <> g' obj) (map (g' . snd) vs)
644− g' v@(Abs _ v1) = g v <> g' v1
645− g' v@(App v1 v2) = g v <> g' v1 <> g' v2
646− g' v@(IfThenElse v1 v2 v3) = g v <> g' v1 <> g' v2 <> g' v3
647− g' v@(Case vs alts) = foldl (<>) (foldl (<>) (g v) (map g' vs)) (map i' alts)
648− g' v@(TypedValue _ v1 _) = g v <> g' v1
649− g' v@(Let ds v1) = (foldl (<>) (g v) (map f' ds)) <> g' v1
650− g' v@(Do es) = foldl (<>) (g v) (map j' es)
651− g' v@(PositionedValue _ v1) = g v <> g' v1
652− g' v = g v
653−
654− h' b@(ConstructorBinder _ bs) = foldl (<>) (h b) (map h' bs)
655− h' b@(ObjectBinder bs) = foldl (<>) (h b) (map (h' . snd) bs)
656− h' b@(ArrayBinder bs) = foldl (<>) (h b) (map h' bs)
657− h' b@(ConsBinder b1 b2) = h b <> h' b1 <> h' b2
658− h' b@(NamedBinder _ b1) = h b <> h' b1
659− h' b@(PositionedBinder _ b1) = h b <> h' b1
660− h' b = h b
661−
662− i' ca = case caseAlternativeGuard ca of
663− Nothing -> foldl (<>) (i ca) (map h' (caseAlternativeBinders ca)) <> g' (caseAlternativeResult ca)
664− Just grd -> foldl (<>) (i ca) (map h' (caseAlternativeBinders ca)) <> g' grd <> g' (caseAlternativeResult ca)
665−
666− j' e@(DoNotationValue v) = j e <> g' v
667− j' e@(DoNotationBind b v) = j e <> h' b <> g' v
668− j' e@(DoNotationLet ds) = foldl (<>) (j e) (map f' ds)
669− j' e@(PositionedDoNotationElement _ e1) = j e <> j' e1
670−
671−everythingWithContextOnValues ::
672− s ->
673− r ->
674− (r -> r -> r) ->
675− (s -> Declaration -> (s, r)) ->
676− (s -> Value -> (s, r)) ->
677− (s -> Binder -> (s, r)) ->
678− (s -> CaseAlternative -> (s, r)) ->
679− (s -> DoNotationElement -> (s, r)) ->
680− ( Declaration -> r
681− , Value -> r
682− , Binder -> r
683− , CaseAlternative -> r
684− , DoNotationElement -> r)
685−everythingWithContextOnValues s0 r0 (<>) f g h i j = (f'' s0, g'' s0, h'' s0, i'' s0, j'' s0)
686− where
687− f'' s d = let (s', r) = f s d in r <> f' s' d
688−
689− f' s (DataBindingGroupDeclaration ds) = foldl (<>) r0 (map (f'' s) ds)
690− f' s (ValueDeclaration _ _ bs Nothing val) = foldl (<>) r0 (map (h'' s) bs) <> (g'' s) val
691− f' s (ValueDeclaration _ _ bs (Just grd) val) = foldl (<>) r0 (map (h'' s) bs) <> (g'' s) grd <> (g'' s) val
692− f' s (BindingGroupDeclaration ds) = foldl (<>) r0 (map (\(_, _, val) -> (g'' s) val) ds)
693− f' s (TypeClassDeclaration _ _ _ ds) = foldl (<>) r0 (map (f'' s) ds)
694− f' s (TypeInstanceDeclaration _ _ _ _ ds) = foldl (<>) r0 (map (f'' s) ds)
695− f' s (PositionedDeclaration _ d1) = (f'' s) d1
696− f' _ _ = r0
697−
698− g'' s v = let (s', r) = g s v in r <> g' s' v
699−
700− g' s (UnaryMinus v1) = (g'' s) v1
701− g' s (BinaryNoParens _ v1 v2) = (g'' s) v1 <> (g'' s) v2
702− g' s (Parens v1) = (g'' s) v1
703− g' s (ArrayLiteral vs) = foldl (<>) r0 (map (g'' s) vs)
704− g' s (ObjectLiteral vs) = foldl (<>) r0 (map (g'' s . snd) vs)
705− g' s (Accessor _ v1) = (g'' s) v1
706− g' s (ObjectUpdate obj vs) = foldl (<>) ((g'' s) obj) (map (g'' s . snd) vs)
707− g' s (Abs _ v1) = (g'' s) v1
708− g' s (App v1 v2) = (g'' s) v1 <> (g'' s) v2
709− g' s (IfThenElse v1 v2 v3) = (g'' s) v1 <> (g'' s) v2 <> (g'' s) v3
710− g' s (Case vs alts) = foldl (<>) (foldl (<>) r0 (map (g'' s) vs)) (map (i'' s) alts)
711− g' s (TypedValue _ v1 _) = (g'' s) v1
712− g' s (Let ds v1) = (foldl (<>) r0 (map (f'' s) ds)) <> (g'' s) v1
713− g' s (Do es) = foldl (<>) r0 (map (j'' s) es)
714− g' s (PositionedValue _ v1) = (g'' s) v1
715− g' _ _ = r0
716−
717− h'' s b = let (s', r) = h s b in r <> h' s' b
718−
719− h' s (ConstructorBinder _ bs) = foldl (<>) r0 (map (h'' s) bs)
720− h' s (ObjectBinder bs) = foldl (<>) r0 (map (h'' s . snd) bs)
721− h' s (ArrayBinder bs) = foldl (<>) r0 (map (h'' s) bs)
722− h' s (ConsBinder b1 b2) = (h'' s) b1 <> (h'' s) b2
723− h' s (NamedBinder _ b1) = (h'' s) b1
724− h' s (PositionedBinder _ b1) = (h'' s) b1
725− h' _ _ = r0
726−
727− i'' s ca = let (s', r) = i s ca in r <> i' s' ca
728−
729− i' s (CaseAlternative bs Nothing val) = foldl (<>) r0 (map (h'' s) bs) <> (g'' s) val
730− i' s (CaseAlternative bs (Just grd) val) = foldl (<>) r0 (map (h'' s) bs) <> (g'' s) grd <> (g'' s) val
731−
732− j'' s e = let (s', r) = j s e in r <> j' s' e
733−
734− j' s (DoNotationValue v) = (g'' s) v
735− j' s (DoNotationBind b v) = (h'' s) b <> (g'' s) v
736− j' s (DoNotationLet ds) = foldl (<>) r0 (map (f'' s) ds)
737− j' s (PositionedDoNotationElement _ e1) = (j'' s) e1
738−
739−everywhereWithContextOnValuesM :: (Functor m, Applicative m, Monad m) =>
740− s ->
741− (s -> Declaration -> m (s, Declaration)) ->
742− (s -> Value -> m (s, Value)) ->
743− (s -> Binder -> m (s, Binder)) ->
744− (s -> CaseAlternative -> m (s, CaseAlternative)) ->
745− (s -> DoNotationElement -> m (s, DoNotationElement)) ->
746− ( Declaration -> m Declaration
747− , Value -> m Value
748− , Binder -> m Binder
749− , CaseAlternative -> m CaseAlternative
750− , DoNotationElement -> m DoNotationElement)
751−everywhereWithContextOnValuesM s0 f g h i j = (f'' s0, g'' s0, h'' s0, i'' s0, j'' s0)
752− where
753− f'' s = uncurry f' <=< f s
754−
755− f' s (DataBindingGroupDeclaration ds) = DataBindingGroupDeclaration <$> mapM (f'' s) ds
756− f' s (ValueDeclaration name nameKind bs grd val) = ValueDeclaration name nameKind <$> mapM (h'' s) bs <*> maybeM (g'' s) grd <*> g'' s val
757− f' s (BindingGroupDeclaration ds) = BindingGroupDeclaration <$> mapM (thirdM (g'' s)) ds
758− f' s (TypeClassDeclaration name args implies ds) = TypeClassDeclaration name args implies <$> mapM (f'' s) ds
759− f' s (TypeInstanceDeclaration name cs className args ds) = TypeInstanceDeclaration name cs className args <$> mapM (f'' s) ds
760− f' s (PositionedDeclaration pos d1) = PositionedDeclaration pos <$> f'' s d1
761− f' _ other = return other
762−
763− g'' s = uncurry g' <=< g s
764−
765− g' s (UnaryMinus v) = UnaryMinus <$> g'' s v
766− g' s (BinaryNoParens op v1 v2) = BinaryNoParens op <$> g'' s v1 <*> g'' s v2
767− g' s (Parens v) = Parens <$> g'' s v
768− g' s (ArrayLiteral vs) = ArrayLiteral <$> mapM (g'' s) vs
769− g' s (ObjectLiteral vs) = ObjectLiteral <$> mapM (sndM (g'' s)) vs
770− g' s (Accessor prop v) = Accessor prop <$> g'' s v
771− g' s (ObjectUpdate obj vs) = ObjectUpdate <$> g'' s obj <*> mapM (sndM (g'' s)) vs
772− g' s (Abs name v) = Abs name <$> g'' s v
773− g' s (App v1 v2) = App <$> g'' s v1 <*> g'' s v2
774− g' s (IfThenElse v1 v2 v3) = IfThenElse <$> g'' s v1 <*> g'' s v2 <*> g'' s v3
775− g' s (Case vs alts) = Case <$> mapM (g'' s) vs <*> mapM (i'' s) alts
776− g' s (TypedValue check v ty) = TypedValue check <$> g'' s v <*> pure ty
777− g' s (Let ds v) = Let <$> mapM (f'' s) ds <*> g'' s v
778− g' s (Do es) = Do <$> mapM (j'' s) es
779− g' s (PositionedValue pos v) = PositionedValue pos <$> g'' s v
780− g' _ other = return other
781−
782− h'' s = uncurry h' <=< h s
783−
784− h' s (ConstructorBinder ctor bs) = ConstructorBinder ctor <$> mapM (h'' s) bs
785− h' s (ObjectBinder bs) = ObjectBinder <$> mapM (sndM (h'' s)) bs
786− h' s (ArrayBinder bs) = ArrayBinder <$> mapM (h'' s) bs
787− h' s (ConsBinder b1 b2) = ConsBinder <$> h'' s b1 <*> h'' s b2
788− h' s (NamedBinder name b) = NamedBinder name <$> h'' s b
789− h' s (PositionedBinder pos b) = PositionedBinder pos <$> h'' s b
790− h' _ other = return other
791−
792− i'' s = uncurry i' <=< i s
793−
794− i' s (CaseAlternative bs grd val) = CaseAlternative <$> mapM (h'' s) bs <*> maybeM (g'' s) grd <*> g'' s val
795−
796− j'' s = uncurry j' <=< j s
797−
798− j' s (DoNotationValue v) = DoNotationValue <$> g'' s v
799− j' s (DoNotationBind b v) = DoNotationBind <$> h'' s b <*> g'' s v
800− j' s (DoNotationLet ds) = DoNotationLet <$> mapM (f'' s) ds
801− j' s (PositionedDoNotationElement pos e1) = PositionedDoNotationElement pos <$> j'' s e1
802−
803−accumTypes :: (Monoid r) => (Type -> r) -> (Declaration -> r, Value -> r, Binder -> r, CaseAlternative -> r, DoNotationElement -> r)
804−accumTypes f = everythingOnValues mappend forDecls forValues (const mempty) (const mempty) (const mempty)
805− where
806− forDecls (DataDeclaration _ _ dctors) = mconcat (concatMap (map f . snd) dctors)
807− forDecls (ExternDeclaration _ _ _ ty) = f ty
808− forDecls (ExternInstanceDeclaration _ cs _ tys) = mconcat (concatMap (map f . snd) cs) `mappend` mconcat (map f tys)
809− forDecls (TypeClassDeclaration _ _ implies _) = mconcat (concatMap (map f . snd) implies)
810− forDecls (TypeInstanceDeclaration _ cs _ tys _) = mconcat (concatMap (map f . snd) cs) `mappend` mconcat (map f tys)
811− forDecls (TypeSynonymDeclaration _ _ ty) = f ty
812− forDecls (TypeDeclaration _ ty) = f ty
813− forDecls _ = mempty
814−
815− forValues (TypeClassDictionary _ (_, cs) _) = mconcat (map f cs)
816− forValues (SuperClassDictionary _ tys) = mconcat (map f tys)
817− forValues (TypedValue _ _ ty) = f ty
818− forValues _ = mempty
819−
820−
src/Language/PureScript/Environment.hsdeleted−191
@@ -1,191 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Environment
4−-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−{-# LANGUAGE DeriveDataTypeable #-}
16−
17−module Language.PureScript.Environment where
18−
19−import Data.Data
20−
21−import Language.PureScript.Names
22−import Language.PureScript.Types
23−import Language.PureScript.Kinds
24−import Language.PureScript.TypeClassDictionaries
25−import qualified Language.PureScript.Constants as C
26−
27−import qualified Data.Map as M
28−
29−-- |
30−-- The @Environment@ defines all values and types which are currently in scope:
31−--
32−data Environment = Environment {
33− -- |
34− -- Value names currently in scope
35− --
36− names :: M.Map (ModuleName, Ident) (Type, NameKind)
37− -- |
38− -- Type names currently in scope
39− --
40− , types :: M.Map (Qualified ProperName) (Kind, TypeKind)
41− -- |
42− -- Data constructors currently in scope, along with their associated data type constructors
43− --
44− , dataConstructors :: M.Map (Qualified ProperName) (ProperName, Type)
45− -- |
46− -- Type synonyms currently in scope
47− --
48− , typeSynonyms :: M.Map (Qualified ProperName) ([String], Type)
49− -- |
50− -- Available type class dictionaries
51− --
52− , typeClassDictionaries :: M.Map (Qualified Ident, Maybe ModuleName) TypeClassDictionaryInScope
53− -- |
54− -- Type classes
55− --
56− , typeClasses :: M.Map (Qualified ProperName) ([String], [(Ident, Type)], [(Qualified ProperName, [Type])])
57− } deriving (Show)
58−
59−-- |
60−-- The initial environment with no values and only the default javascript types defined
61−--
62−initEnvironment :: Environment
63−initEnvironment = Environment M.empty primTypes M.empty M.empty M.empty M.empty
64−
65−-- |
66−-- The type of a foreign import
67−--
68−data ForeignImportType
69− -- |
70− -- A regular foreign import
71− --
72− = ForeignImport
73− -- |
74− -- A foreign import which contains inline Javascript as a string literal
75− --
76− | InlineJavascript deriving (Show, Eq, Data, Typeable)
77−
78−-- |
79−-- The kind of a name
80−--
81−data NameKind
82− -- |
83− -- A value introduced as a binding in a module
84− --
85− = Value
86− -- |
87− -- A type class dictionary member accessor import, generated during desugaring of type class declarations
88− --
89− | TypeClassAccessorImport
90− -- |
91− -- A foreign import
92− --
93− | Extern ForeignImportType
94− -- |
95− -- A local name introduced using a lambda abstraction, variable introduction or binder
96− --
97− | LocalVariable
98− -- |
99− -- A data constructor
100− --
101− | DataConstructor
102− -- |
103− -- A type class dictionary, generated during desugaring of type class declarations
104− --
105− | TypeInstanceDictionaryValue deriving (Show, Eq, Data, Typeable)
106−
107−-- |
108−-- The kinds of a type
109−--
110−data TypeKind
111− -- |
112− -- Data type
113− --
114− = DataType [String] [(ProperName, [Type])]
115− -- |
116− -- Type synonym
117− --
118− | TypeSynonym
119− -- |
120− -- Foreign data
121− --
122− | ExternData
123− -- |
124− -- A local type variable
125− --
126− | LocalTypeVariable deriving (Show, Eq, Data, Typeable)
127−
128−-- |
129−-- Construct a ProperName in the Prim module
130−--
131−primName :: String -> Qualified ProperName
132−primName = Qualified (Just $ ModuleName [ProperName C.prim]) . ProperName
133−
134−-- |
135−-- Construct a type in the Prim module
136−--
137−primTy :: String -> Type
138−primTy = TypeConstructor . primName
139−
140−-- |
141−-- Type constructor for functions
142−--
143−tyFunction :: Type
144−tyFunction = primTy "Function"
145−
146−-- |
147−-- Type constructor for strings
148−--
149−tyString :: Type
150−tyString = primTy "String"
151−
152−-- |
153−-- Type constructor for numbers
154−--
155−tyNumber :: Type
156−tyNumber = primTy "Number"
157−
158−-- |
159−-- Type constructor for booleans
160−--
161−tyBoolean :: Type
162−tyBoolean = primTy "Boolean"
163−
164−-- |
165−-- Type constructor for arrays
166−--
167−tyArray :: Type
168−tyArray = primTy "Array"
169−
170−-- |
171−-- Type constructor for objects
172−--
173−tyObject :: Type
174−tyObject = primTy "Object"
175−
176−-- |
177−-- Smart constructor for function types
178−--
179−function :: Type -> Type -> Type
180−function t1 = TypeApp (TypeApp tyFunction t1)
181−
182−-- |
183−-- The primitive types in the external javascript environment with their associated kinds.
184−--
185−primTypes :: M.Map (Qualified ProperName) (Kind, TypeKind)
186−primTypes = M.fromList [ (primName "Function" , (FunKind Star (FunKind Star Star), ExternData))
187− , (primName "Array" , (FunKind Star Star, ExternData))
188− , (primName "Object" , (FunKind (Row Star) Star, ExternData))
189− , (primName "String" , (Star, ExternData))
190− , (primName "Number" , (Star, ExternData))
191− , (primName "Boolean" , (Star, ExternData)) ]
src/Language/PureScript/Errors.hsdeleted−111
@@ -1,111 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Error
4−-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−{-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleContexts #-}
16−
17−module Language.PureScript.Errors where
18−
19−import Data.List (intercalate)
20−import Data.Monoid
21−
22−import Control.Monad.Error
23−
24−import Language.PureScript.Declarations
25−import Language.PureScript.Pretty
26−import Language.PureScript.Types
27−
28−-- |
29−-- Type for sources of type checking errors
30−--
31−data ErrorSource
32− -- |
33− -- An error which originated at a Value
34− --
35− = ValueError Value
36− -- |
37− -- An error which originated at a Type
38− --
39− | TypeError Type deriving (Show)
40−
41−-- |
42−-- Compilation errors
43−--
44−data CompileError = CompileError {
45− -- |
46− -- Error message
47− --
48− compileErrorMessage :: String
49− -- |
50− -- The value where the error occurred
51− --
52− , compileErrorValue :: Maybe ErrorSource
53− -- |
54− -- Optional source position information
55− --
56− , compileErrorPosition :: Maybe SourcePos
57− } deriving (Show)
58−
59−-- |
60−-- A stack trace for an error
61−--
62−newtype ErrorStack = ErrorStack { runErrorStack :: [CompileError] } deriving (Show, Monoid)
63−
64−instance Error ErrorStack where
65− strMsg s = ErrorStack [CompileError s Nothing Nothing]
66− noMsg = ErrorStack []
67−
68−prettyPrintErrorStack :: Bool -> ErrorStack -> String
69−prettyPrintErrorStack printFullStack (ErrorStack es) =
70− case mconcat $ map (Last . compileErrorPosition) es of
71− Last (Just sourcePos) -> "Error at " ++ show sourcePos ++ ": \n" ++ prettyPrintErrorStack'
72− _ -> prettyPrintErrorStack'
73− where
74− prettyPrintErrorStack' :: String
75− prettyPrintErrorStack'
76− | printFullStack = intercalate "\n" (map showError (filter isErrorNonEmpty es))
77− | otherwise =
78− let
79− es' = filter isErrorNonEmpty es
80− in case length es' of
81− 1 -> showError (head es')
82− _ -> showError (head es') ++ "\n" ++ showError (last es')
83−
84−stringifyErrorStack :: Bool -> Either ErrorStack a -> Either String a
85−stringifyErrorStack printFullStack = either (Left . prettyPrintErrorStack printFullStack) Right
86−
87−isErrorNonEmpty :: CompileError -> Bool
88−isErrorNonEmpty = not . null . compileErrorMessage
89−
90−showError :: CompileError -> String
91−showError (CompileError msg Nothing _) = msg
92−showError (CompileError msg (Just (ValueError val)) _) = "Error in value " ++ prettyPrintValue val ++ ":\n" ++ msg
93−showError (CompileError msg (Just (TypeError ty)) _) = "Error in type " ++ prettyPrintType ty ++ ":\n" ++ msg
94−
95−mkErrorStack :: String -> Maybe ErrorSource -> ErrorStack
96−mkErrorStack msg t = ErrorStack [CompileError msg t Nothing]
97−
98−positionError :: SourcePos -> ErrorStack
99−positionError pos = ErrorStack [CompileError "" Nothing (Just pos)]
100−
101−-- |
102−-- Rethrow an error with a more detailed error message in the case of failure
103−--
104−rethrow :: (MonadError e m) => (e -> e) -> m a -> m a
105−rethrow f = flip catchError $ \e -> throwError (f e)
106−
107−-- |
108−-- Rethrow an error with source position information
109−--
110−rethrowWithPosition :: (MonadError ErrorStack m) => SourcePos -> m a -> m a
111−rethrowWithPosition pos = rethrow (positionError pos <>)
src/Language/PureScript/Kinds.hsdeleted−60
@@ -1,60 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Kinds
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−{-# LANGUAGE DeriveDataTypeable #-}
16−
17−module Language.PureScript.Kinds where
18−
19−import Data.Data
20−
21−import Control.Monad.Unify (Unknown)
22−
23−-- |
24−-- The data type of kinds
25−--
26−data Kind
27− -- |
28− -- Unification variable of type Kind
29− --
30− = KUnknown Unknown
31− -- |
32− -- The kind of types
33− --
34− | Star
35− -- |
36− -- The kind of effects
37− --
38− | Bang
39− -- |
40− -- Kinds for labelled, unordered rows without duplicates
41− --
42− | Row Kind
43− -- |
44− -- Function kinds
45− --
46− | FunKind Kind Kind deriving (Show, Eq, Data, Typeable)
47−
48−everywhereOnKinds :: (Kind -> Kind) -> Kind -> Kind
49−everywhereOnKinds f = go
50− where
51− go (Row k1) = f (Row (go k1))
52− go (FunKind k1 k2) = f (FunKind (go k1) (go k2))
53− go other = f other
54−
55−everythingOnKinds :: (r -> r -> r) -> (Kind -> r) -> Kind -> r
56−everythingOnKinds (<>) f = go
57− where
58− go k@(Row k1) = f k <> go k1
59− go k@(FunKind k1 k2) = f k <> go k1 <> go k2
60− go other = f other
src/Language/PureScript/ModuleDependencies.hsdeleted−76
@@ -1,76 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.ModuleDependencies
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : 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−
15−module Language.PureScript.ModuleDependencies (
16− sortModules,
17− ModuleGraph
18−) where
19−
20−import Data.Graph
21−import Data.List (nub)
22−import Data.Maybe (mapMaybe)
23−
24−import Language.PureScript.Declarations
25−import Language.PureScript.Names
26−import Language.PureScript.Types
27−
28−-- |
29−-- A list of modules with their dependencies
30−--
31−type ModuleGraph = [(ModuleName, [ModuleName])]
32−
33−-- |
34−-- Sort a collection of modules based on module dependencies.
35−--
36−-- Reports an error if the module graph contains a cycle.
37−--
38−sortModules :: [Module] -> Either String ([Module], ModuleGraph)
39−sortModules ms = do
40− let verts = map (\m@(Module _ ds _) -> (m, getModuleName m, nub (concatMap usedModules ds))) ms
41− ms' <- mapM toModule $ stronglyConnComp verts
42− let moduleGraph = map (\(_, mn, deps) -> (mn, deps)) verts
43− return (ms', moduleGraph)
44−
45−-- |
46−-- Calculate a list of used modules based on explicit imports and qualified names
47−--
48−usedModules :: Declaration -> [ModuleName]
49−usedModules = let (f, _, _, _, _) = everythingOnValues (++) forDecls forValues (const []) (const []) (const []) in nub . f
50− where
51− forDecls :: Declaration -> [ModuleName]
52− forDecls (ImportDeclaration mn _ _) = [mn]
53− forDecls _ = []
54−
55− forValues :: Value -> [ModuleName]
56− forValues (Var (Qualified (Just mn) _)) = [mn]
57− forValues (BinaryNoParens (Qualified (Just mn) _) _ _) = [mn]
58− forValues (Constructor (Qualified (Just mn) _)) = [mn]
59− forValues (TypedValue _ _ ty) = forTypes ty
60− forValues _ = []
61−
62− forTypes :: Type -> [ModuleName]
63− forTypes (TypeConstructor (Qualified (Just mn) _)) = [mn]
64− forTypes (ConstrainedType cs _) = mapMaybe (\(Qualified mn _, _) -> mn) cs
65− forTypes _ = []
66−
67−getModuleName :: Module -> ModuleName
68−getModuleName (Module mn _ _) = mn
69−
70−-- |
71−-- Convert a strongly connected component of the module graph to a module
72−--
73−toModule :: SCC Module -> Either String Module
74−toModule (AcyclicSCC m) = return m
75−toModule (CyclicSCC [m]) = return m
76−toModule (CyclicSCC ms) = Left $ "Cycle in module dependencies: " ++ show (map getModuleName ms)
src/Language/PureScript/Names.hsdeleted−85
@@ -1,85 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Names
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Data types for names
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE DeriveDataTypeable #-}
17−
18−module Language.PureScript.Names where
19−
20−import Data.List
21−import Data.Data
22−
23−-- |
24−-- Names for value identifiers
25−--
26−data Ident
27− -- |
28− -- An alphanumeric identifier
29− --
30− = Ident String
31− -- |
32− -- A symbolic name for an infix operator
33− --
34− | Op String deriving (Eq, Ord, Data, Typeable)
35−
36−runIdent :: Ident -> String
37−runIdent (Ident i) = i
38−runIdent (Op op) = op
39−
40−instance Show Ident where
41− show (Ident s) = s
42− show (Op op) = '(':op ++ ")"
43−
44−-- |
45−-- Proper names, i.e. capitalized names for e.g. module names, type//data constructors.
46−--
47−newtype ProperName = ProperName { runProperName :: String } deriving (Eq, Ord, Data, Typeable)
48−
49−instance Show ProperName where
50− show = runProperName
51−
52−-- |
53−-- Module names
54−--
55−data ModuleName = ModuleName [ProperName] deriving (Eq, Ord, Data, Typeable)
56−
57−runModuleName :: ModuleName -> String
58−runModuleName (ModuleName pns) = intercalate "." (runProperName `map` pns)
59−
60−moduleNameFromString :: String -> ModuleName
61−moduleNameFromString = ModuleName . splitProperNames
62− where
63− splitProperNames s = case dropWhile (== '.') s of
64− "" -> []
65− s' -> ProperName w : splitProperNames s''
66− where (w, s'') = break (== '.') s'
67−
68−instance Show ModuleName where
69− show = runModuleName
70−
71−-- |
72−-- A qualified name, i.e. a name with an optional module name
73−--
74−data Qualified a = Qualified (Maybe ModuleName) a deriving (Eq, Ord, Data, Typeable)
75−
76−instance (Show a) => Show (Qualified a) where
77− show (Qualified Nothing a) = show a
78− show (Qualified (Just name) a) = show name ++ "." ++ show a
79−
80−-- |
81−-- Provide a default module name, if a name is unqualified
82−--
83−qualify :: ModuleName -> Qualified a -> (ModuleName, a)
84−qualify m (Qualified Nothing a) = (m, a)
85−qualify _ (Qualified (Just m) a) = (m, a)
src/Language/PureScript/Optimizer.hsdeleted−73
@@ -1,73 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Optimizer
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module optimizes code in the simplified-Javascript intermediate representation.
13−--
14−-- The following optimizations are supported:
15−--
16−-- * Collapsing nested blocks
17−--
18−-- * Tail call elimination
19−--
20−-- * Inlining of (>>=) and ret for the Eff monad
21−--
22−-- * Removal of unnecessary thunks
23−--
24−-- * Eta conversion
25−--
26−-- * Inlining variables
27−--
28−-- * Inline Prelude.($), Prelude.(#), Prelude.(++), Prelude.(!!)
29−--
30−-- * Inlining primitive Javascript operators
31−--
32−-----------------------------------------------------------------------------
33−
34−module Language.PureScript.Optimizer (
35− optimize
36−) where
37−
38−import Language.PureScript.CodeGen.JS.AST
39−import Language.PureScript.Options
40−import qualified Language.PureScript.Constants as C
41−
42−import Language.PureScript.Optimizer.Common
43−import Language.PureScript.Optimizer.TCO
44−import Language.PureScript.Optimizer.MagicDo
45−import Language.PureScript.Optimizer.Inliner
46−import Language.PureScript.Optimizer.Unused
47−import Language.PureScript.Optimizer.Blocks
48−
49−-- |
50−-- Apply a series of optimizer passes to simplified Javascript code
51−--
52−optimize :: Options -> JS -> JS
53−optimize opts | optionsNoOptimizations opts = id
54− | otherwise = untilFixedPoint (applyAll
55− [ collapseNestedBlocks
56− , tco opts
57− , magicDo opts
58− , removeCodeAfterReturnStatements
59− , unThunk
60− , etaConvert
61− , evaluateIifes
62− , inlineVariables
63− , inlineOperator (C.prelude, (C.$)) $ \f x -> JSApp f [x]
64− , inlineOperator (C.prelude, (C.#)) $ \x f -> JSApp f [x]
65− , inlineOperator (C.preludeUnsafe, C.unsafeIndex) $ flip JSIndexer
66− , inlineCommonOperators ])
67−
68−untilFixedPoint :: (Eq a) => (a -> a) -> a -> a
69−untilFixedPoint f = go
70− where
71− go a = let a' = f a in
72− if a' == a then a' else go a'
73−
src/Language/PureScript/Optimizer/Blocks.hsdeleted−33
@@ -1,33 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Optimizer.Blocks
4−-- Copyright : (c) Phil Freeman 2013-14
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Optimizer steps for simplifying Javascript blocks
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Optimizer.Blocks (
17− collapseNestedBlocks
18−) where
19−
20−import Language.PureScript.CodeGen.JS.AST
21−
22−-- |
23−-- Collapse blocks which appear nested directly below another block
24−--
25−collapseNestedBlocks :: JS -> JS
26−collapseNestedBlocks = everywhereOnJS collapse
27− where
28− collapse :: JS -> JS
29− collapse (JSBlock sts) = JSBlock (concatMap go sts)
30− collapse js = js
31− go :: JS -> [JS]
32− go (JSBlock sts) = sts
33− go s = [s]
src/Language/PureScript/Optimizer/Common.hsdeleted−77
@@ -1,77 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Optimizer.Common
4−-- Copyright : (c) Phil Freeman 2013-14
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Common functions used by the various optimizer phases
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Optimizer.Common where
17−
18−import Data.Maybe (fromMaybe)
19−
20−import Language.PureScript.CodeGen.JS.AST
21−
22−applyAll :: [a -> a] -> a -> a
23−applyAll = foldl1 (.)
24−
25−replaceIdent :: String -> JS -> JS -> JS
26−replaceIdent var1 js = everywhereOnJS replace
27− where
28− replace (JSVar var2) | var1 == var2 = js
29− replace other = other
30−
31−replaceIdents :: [(String, JS)] -> JS -> JS
32−replaceIdents vars = everywhereOnJS replace
33− where
34− replace v@(JSVar var) = fromMaybe v $ lookup var vars
35− replace other = other
36−
37−isReassigned :: String -> JS -> Bool
38−isReassigned var1 = everythingOnJS (||) check
39− where
40− check :: JS -> Bool
41− check (JSFunction _ args _) | var1 `elem` args = True
42− check (JSVariableIntroduction arg _) | var1 == arg = True
43− check (JSAssignment (JSVar arg) _) | var1 == arg = True
44− check (JSFor arg _ _ _) | var1 == arg = True
45− check (JSForIn arg _ _) | var1 == arg = True
46− check _ = False
47−
48−isRebound :: JS -> JS -> Bool
49−isRebound js d = any (\v -> isReassigned v d || isUpdated v d) (everythingOnJS (++) variablesOf js)
50− where
51− variablesOf (JSVar var) = [var]
52− variablesOf _ = []
53−
54−isUsed :: String -> JS -> Bool
55−isUsed var1 = everythingOnJS (||) check
56− where
57− check :: JS -> Bool
58− check (JSVar var2) | var1 == var2 = True
59− check (JSAssignment target _) | var1 == targetVariable target = True
60− check _ = False
61−
62−targetVariable :: JS -> String
63−targetVariable (JSVar var) = var
64−targetVariable (JSAccessor _ tgt) = targetVariable tgt
65−targetVariable (JSIndexer _ tgt) = targetVariable tgt
66−targetVariable _ = error "Invalid argument to targetVariable"
67−
68−isUpdated :: String -> JS -> Bool
69−isUpdated var1 = everythingOnJS (||) check
70− where
71− check :: JS -> Bool
72− check (JSAssignment target _) | var1 == targetVariable target = True
73− check _ = False
74−
75−removeFromBlock :: ([JS] -> [JS]) -> JS -> JS
76−removeFromBlock go (JSBlock sts) = JSBlock (go sts)
77−removeFromBlock _ js = js
src/Language/PureScript/Optimizer/Inliner.hsdeleted−152
@@ -1,152 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Optimizer.Inliner
4−-- Copyright : (c) Phil Freeman 2013-14
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module provides basic inlining capabilities
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Optimizer.Inliner (
17− inlineVariables,
18− inlineOperator,
19− inlineCommonOperators,
20− etaConvert,
21− unThunk,
22− evaluateIifes
23−) where
24−
25−import Language.PureScript.CodeGen.JS.AST
26−import Language.PureScript.CodeGen.Common (identToJs)
27−import Language.PureScript.Optimizer.Common
28−import Language.PureScript.Names
29−
30−import qualified Language.PureScript.Constants as C
31−
32−shouldInline :: JS -> Bool
33−shouldInline (JSVar _) = True
34−shouldInline (JSNumericLiteral _) = True
35−shouldInline (JSStringLiteral _) = True
36−shouldInline (JSBooleanLiteral _) = True
37−shouldInline (JSAccessor _ val) = shouldInline val
38−shouldInline (JSIndexer index val) = shouldInline index && shouldInline val
39−shouldInline _ = False
40−
41−etaConvert :: JS -> JS
42−etaConvert = everywhereOnJS convert
43− where
44− convert :: JS -> JS
45− convert (JSBlock [JSReturn (JSApp (JSFunction Nothing idents block@(JSBlock body)) args)])
46− | all shouldInline args &&
47− not (any (`isRebound` block) (map JSVar idents)) &&
48− not (any (`isRebound` block) args)
49− = JSBlock (map (replaceIdents (zip idents args)) body)
50− convert js = js
51−
52−unThunk :: JS -> JS
53−unThunk = everywhereOnJS convert
54− where
55− convert :: JS -> JS
56− convert (JSBlock []) = JSBlock []
57− convert (JSBlock jss) =
58− case (last jss) of
59− JSReturn (JSApp (JSFunction Nothing [] (JSBlock body)) []) -> JSBlock $ init jss ++ body
60− _ -> JSBlock jss
61− convert js = js
62−
63−evaluateIifes :: JS -> JS
64−evaluateIifes = everywhereOnJS convert
65− where
66− convert :: JS -> JS
67− convert (JSApp (JSFunction Nothing [] (JSBlock [JSReturn ret])) []) = ret
68− convert js = js
69−
70−inlineVariables :: JS -> JS
71−inlineVariables = everywhereOnJS $ removeFromBlock go
72− where
73− go :: [JS] -> [JS]
74− go [] = []
75− go (JSVariableIntroduction var (Just js) : sts)
76− | shouldInline js && not (any (isReassigned var) sts) && not (any (isRebound js) sts) && not (any (isUpdated var) sts) =
77− go (map (replaceIdent var js) sts)
78− go (s:sts) = s : go sts
79−
80−inlineOperator :: (String, String) -> (JS -> JS -> JS) -> JS -> JS
81−inlineOperator (m, op) f = everywhereOnJS convert
82− where
83− convert :: JS -> JS
84− convert (JSApp (JSApp op' [x]) [y]) | isOp op' = f x y
85− convert other = other
86− isOp (JSAccessor longForm (JSVar m')) = m == m' && longForm == identToJs (Op op)
87− isOp (JSIndexer (JSStringLiteral op') (JSVar m')) = m == m' && op == op'
88− isOp _ = False
89−
90−inlineCommonOperators :: JS -> JS
91−inlineCommonOperators = applyAll
92− [ binary C.numNumber (C.+) Add
93− , binary C.numNumber (C.-) Subtract
94− , binary C.numNumber (C.*) Multiply
95− , binary C.numNumber (C./) Divide
96− , binary C.numNumber (C.%) Modulus
97− , unary C.numNumber C.negate Negate
98−
99− , binary C.ordNumber (C.<) LessThan
100− , binary C.ordNumber (C.>) GreaterThan
101− , binary C.ordNumber (C.<=) LessThanOrEqualTo
102− , binary C.ordNumber (C.>=) GreaterThanOrEqualTo
103−
104− , binary C.eqNumber (C.==) EqualTo
105− , binary C.eqNumber (C./=) NotEqualTo
106− , binary C.eqString (C.==) EqualTo
107− , binary C.eqString (C./=) NotEqualTo
108− , binary C.eqBoolean (C.==) EqualTo
109− , binary C.eqBoolean (C./=) NotEqualTo
110−
111− , binary C.semigroupString (C.++) Add
112−
113− , binaryFunction C.bitsNumber C.shl ShiftLeft
114− , binaryFunction C.bitsNumber C.shr ShiftRight
115− , binaryFunction C.bitsNumber C.zshr ZeroFillShiftRight
116− , binary C.bitsNumber (C.&) BitwiseAnd
117− , binary C.bitsNumber C.bar BitwiseOr
118− , binary C.bitsNumber (C.^) BitwiseXor
119− , unary C.bitsNumber C.complement BitwiseNot
120−
121− , binary C.boolLikeBoolean (C.&&) And
122− , binary C.boolLikeBoolean (C.||) Or
123− , unary C.boolLikeBoolean C.not Not
124− ]
125− where
126− binary :: String -> String -> BinaryOperator -> JS -> JS
127− binary dictName opString op = everywhereOnJS convert
128− where
129− convert :: JS -> JS
130− convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isOp fn && isOpDict dictName dict = JSBinary op x y
131− convert other = other
132− isOp (JSAccessor longForm (JSAccessor prelude (JSVar _))) = prelude == C.prelude && longForm == identToJs (Op opString)
133− isOp (JSIndexer (JSStringLiteral op') (JSVar prelude)) = prelude == C.prelude && opString == op'
134− isOp _ = False
135− binaryFunction :: String -> String -> BinaryOperator -> JS -> JS
136− binaryFunction dictName fnName op = everywhereOnJS convert
137− where
138− convert :: JS -> JS
139− convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isOp fn && isOpDict dictName dict = JSBinary op x y
140− convert other = other
141− isOp (JSAccessor fnName' (JSVar prelude)) = prelude == C.prelude && fnName == fnName'
142− isOp _ = False
143− unary :: String -> String -> UnaryOperator -> JS -> JS
144− unary dictName fnName op = everywhereOnJS convert
145− where
146− convert :: JS -> JS
147− convert (JSApp (JSApp fn [dict]) [x]) | isOp fn && isOpDict dictName dict = JSUnary op x
148− convert other = other
149− isOp (JSAccessor fnName' (JSVar prelude)) = prelude == C.prelude && fnName' == fnName
150− isOp _ = False
151− isOpDict dictName (JSApp (JSAccessor prop (JSVar prelude)) [JSObjectLiteral []]) = prelude == C.prelude && prop == dictName
152− isOpDict _ _ = False
src/Language/PureScript/Optimizer/MagicDo.hsdeleted−157
@@ -1,157 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Optimizer.MagicDo
4−-- Copyright : (c) Phil Freeman 2013-14
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the "Magic Do" optimization, which inlines calls to return
13−-- and bind for the Eff monad, as well as some of its actions.
14−--
15−-----------------------------------------------------------------------------
16−
17−module Language.PureScript.Optimizer.MagicDo (
18− magicDo
19−) where
20−
21−import Data.List (nub)
22−import Data.Maybe (fromJust, isJust)
23−
24−import Language.PureScript.Options
25−import Language.PureScript.CodeGen.JS.AST
26−import Language.PureScript.CodeGen.Common (identToJs)
27−import Language.PureScript.Names
28−
29−import qualified Language.PureScript.Constants as C
30−
31−magicDo :: Options -> JS -> JS
32−magicDo opts | optionsNoMagicDo opts = id
33− | otherwise = inlineST . magicDo'
34−
35−-- |
36−-- Inline type class dictionaries for >>= and return for the Eff monad
37−--
38−-- E.g.
39−--
40−-- Prelude[">>="](dict)(m1)(function(x) {
41−-- return ...;
42−-- })
43−--
44−-- becomes
45−--
46−-- function __do {
47−-- var x = m1();
48−-- ...
49−-- }
50−--
51−magicDo' :: JS -> JS
52−magicDo' = everywhereOnJS undo . everywhereOnJSTopDown convert
53− where
54− -- The name of the function block which is added to denote a do block
55− fnName = "__do"
56− -- Desugar monomorphic calls to >>= and return for the Eff monad
57− convert :: JS -> JS
58− -- Desugar return
59− convert (JSApp (JSApp ret [val]) []) | isReturn ret = val
60− -- Desugar >>
61− convert (JSApp (JSApp bind [m]) [JSFunction Nothing ["_"] (JSBlock js)]) | isBind bind && isJSReturn (last js) =
62− let JSReturn ret = last js in
63− JSFunction (Just fnName) [] $ JSBlock (JSApp m [] : init js ++ [JSReturn (JSApp ret [])] )
64− -- Desugar >>=
65− convert (JSApp (JSApp bind [m]) [JSFunction Nothing [arg] (JSBlock js)]) | isBind bind && isJSReturn (last js) =
66− let JSReturn ret = last js in
67− JSFunction (Just fnName) [] $ JSBlock (JSVariableIntroduction arg (Just (JSApp m [])) : init js ++ [JSReturn (JSApp ret [])] )
68− -- Desugar untilE
69− convert (JSApp (JSApp f [arg]) []) | isEffFunc C.untilE f =
70− JSApp (JSFunction Nothing [] (JSBlock [ JSWhile (JSUnary Not (JSApp arg [])) (JSBlock []), JSReturn (JSObjectLiteral []) ])) []
71− -- Desugar whileE
72− convert (JSApp (JSApp (JSApp f [arg1]) [arg2]) []) | isEffFunc C.whileE f =
73− JSApp (JSFunction Nothing [] (JSBlock [ JSWhile (JSApp arg1 []) (JSBlock [ JSApp arg2 [] ]), JSReturn (JSObjectLiteral []) ])) []
74− convert other = other
75− -- Check if an expression represents a monomorphic call to >>= for the Eff monad
76− isBind (JSApp bindPoly [effDict]) | isBindPoly bindPoly && isEffDict C.bindEffDictionary effDict = True
77− isBind _ = False
78− -- Check if an expression represents a monomorphic call to return for the Eff monad
79− isReturn (JSApp retPoly [effDict]) | isRetPoly retPoly && isEffDict C.monadEffDictionary effDict = True
80− isReturn _ = False
81− -- Check if an expression represents the polymorphic >>= function
82− isBindPoly (JSAccessor prop (JSVar prelude)) = prelude == C.prelude && prop == identToJs (Op (C.>>=))
83− isBindPoly (JSIndexer (JSStringLiteral bind) (JSVar prelude)) = prelude == C.prelude && bind == (C.>>=)
84− isBindPoly _ = False
85− -- Check if an expression represents the polymorphic return function
86− isRetPoly (JSAccessor returnEscaped (JSVar prelude)) = prelude == C.prelude && returnEscaped == C.returnEscaped
87− isRetPoly (JSIndexer (JSStringLiteral return') (JSVar prelude)) = prelude == C.prelude && return' == C.return
88− isRetPoly _ = False
89− -- Check if an expression represents a function in the Ef module
90− isEffFunc name (JSAccessor name' (JSVar eff)) = eff == C.eff && name == name'
91− isEffFunc _ _ = False
92− -- Check if an expression represents the Monad Eff dictionary
93− isEffDict name (JSApp (JSVar ident) [JSObjectLiteral []]) | ident == name = True
94− isEffDict name (JSApp (JSAccessor prop (JSVar eff)) [JSObjectLiteral []]) = eff == C.eff && prop == name
95− isEffDict _ _ = False
96− -- Remove __do function applications which remain after desugaring
97− undo :: JS -> JS
98− undo (JSReturn (JSApp (JSFunction (Just ident) [] body) [])) | ident == fnName = body
99− undo other = other
100−
101− isJSReturn (JSReturn _) = True
102− isJSReturn _ = False
103−
104−-- |
105−-- Inline functions in the ST module
106−--
107−inlineST :: JS -> JS
108−inlineST = everywhereOnJS convertBlock
109− where
110− -- Look for runST blocks and inline the STRefs there.
111− -- If all STRefs are used in the scope of the same runST, only using { read, write, modify }STRef then
112− -- we can be more aggressive about inlining, and actually turn STRefs into local variables.
113− convertBlock (JSApp f [arg]) | isSTFunc C.runST f || isSTFunc C.runSTArray f =
114− let refs = nub . findSTRefsIn $ arg
115− usages = findAllSTUsagesIn arg
116− allUsagesAreLocalVars = all (\u -> let v = toVar u in isJust v && fromJust v `elem` refs) usages
117− localVarsDoNotEscape = all (\r -> length (r `appearingIn` arg) == length (filter (\u -> let v = toVar u in v == Just r) usages)) refs
118− in everywhereOnJS (convert (allUsagesAreLocalVars && localVarsDoNotEscape)) arg
119− convertBlock other = other
120− -- Convert a block in a safe way, preserving object wrappers of references,
121− -- or in a more aggressive way, turning wrappers into local variables depending on the
122− -- agg(ressive) parameter.
123− convert agg (JSApp f [arg]) | isSTFunc C.newSTRef f =
124− JSFunction Nothing [] (JSBlock [JSReturn $ if agg then arg else JSObjectLiteral [(C.stRefValue, arg)]])
125− convert agg (JSApp (JSApp f [ref]) []) | isSTFunc C.readSTRef f =
126− if agg then ref else JSAccessor C.stRefValue ref
127− convert agg (JSApp (JSApp (JSApp f [ref]) [arg]) []) | isSTFunc C.writeSTRef f =
128− if agg then JSAssignment ref arg else JSAssignment (JSAccessor C.stRefValue ref) arg
129− convert agg (JSApp (JSApp (JSApp f [ref]) [func]) []) | isSTFunc C.modifySTRef f =
130− if agg then JSAssignment ref (JSApp func [ref]) else JSAssignment (JSAccessor C.stRefValue ref) (JSApp func [JSAccessor C.stRefValue ref])
131− convert _ (JSApp (JSApp (JSApp f [arr]) [i]) []) | isSTFunc C.peekSTArray f =
132− JSIndexer i arr
133− convert _ (JSApp (JSApp (JSApp (JSApp f [arr]) [i]) [val]) []) | isSTFunc C.pokeSTArray f =
134− JSAssignment (JSIndexer i arr) val
135− convert _ other = other
136− -- Check if an expression represents a function in the ST module
137− isSTFunc name (JSAccessor name' (JSVar st)) = st == C.st && name == name'
138− isSTFunc _ _ = False
139− -- Find all ST Refs initialized in this block
140− findSTRefsIn = everythingOnJS (++) isSTRef
141− where
142− isSTRef (JSVariableIntroduction ident (Just (JSApp (JSApp f [_]) []))) | isSTFunc C.newSTRef f = [ident]
143− isSTRef _ = []
144− -- Find all STRefs used as arguments to readSTRef, writeSTRef, modifySTRef
145− findAllSTUsagesIn = everythingOnJS (++) isSTUsage
146− where
147− isSTUsage (JSApp (JSApp f [ref]) []) | isSTFunc C.readSTRef f = [ref]
148− isSTUsage (JSApp (JSApp (JSApp f [ref]) [_]) []) | isSTFunc C.writeSTRef f || isSTFunc C.modifySTRef f = [ref]
149− isSTUsage _ = []
150− -- Find all uses of a variable
151− appearingIn ref = everythingOnJS (++) isVar
152− where
153− isVar e@(JSVar v) | v == ref = [e]
154− isVar _ = []
155− -- Convert a JS value to a String if it is a JSVar
156− toVar (JSVar v) = Just v
157− toVar _ = Nothing
src/Language/PureScript/Optimizer/TCO.hsdeleted−103
@@ -1,103 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Optimizer.TCO
4−-- Copyright : (c) Phil Freeman 2013-14
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements tail call elimination.
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Optimizer.TCO (tco) where
17−
18−import Language.PureScript.Options
19−import Language.PureScript.CodeGen.JS.AST
20−
21−-- |
22−-- Eliminate tail calls
23−--
24−tco :: Options -> JS -> JS
25−tco opts | optionsNoTco opts = id
26− | otherwise = tco'
27−
28−tco' :: JS -> JS
29−tco' = everywhereOnJS convert
30− where
31− tcoLabel :: String
32− tcoLabel = "tco"
33− tcoVar :: String -> String
34− tcoVar arg = "__tco_" ++ arg
35− copyVar :: String -> String
36− copyVar arg = "__copy_" ++ arg
37− convert :: JS -> JS
38− convert js@(JSVariableIntroduction name (Just fn@JSFunction {})) =
39− let
40− (argss, body', replace) = collectAllFunctionArgs [] id fn
41− in case () of
42− _ | isTailCall name body' ->
43− let
44− allArgs = concat $ reverse argss
45− in
46− JSVariableIntroduction name (Just (replace (toLoop name allArgs body')))
47− | otherwise -> js
48− convert js = js
49− collectAllFunctionArgs :: [[String]] -> (JS -> JS) -> JS -> ([[String]], JS, JS -> JS)
50− collectAllFunctionArgs allArgs f (JSFunction ident args (JSBlock (body@(JSReturn _):_))) =
51− collectAllFunctionArgs (args : allArgs) (\b -> f (JSFunction ident (map copyVar args) (JSBlock [b]))) body
52− collectAllFunctionArgs allArgs f (JSFunction ident args body@(JSBlock _)) =
53− (args : allArgs, body, f . JSFunction ident (map copyVar args))
54− collectAllFunctionArgs allArgs f (JSReturn (JSFunction ident args (JSBlock [body]))) =
55− collectAllFunctionArgs (args : allArgs) (\b -> f (JSReturn (JSFunction ident (map copyVar args) (JSBlock [b])))) body
56− collectAllFunctionArgs allArgs f (JSReturn (JSFunction ident args body@(JSBlock _))) =
57− (args : allArgs, body, f . JSReturn . JSFunction ident (map copyVar args))
58− collectAllFunctionArgs allArgs f body = (allArgs, body, f)
59− isTailCall :: String -> JS -> Bool
60− isTailCall ident js =
61− let
62− numSelfCalls = everythingOnJS (+) countSelfCalls js
63− numSelfCallsInTailPosition = everythingOnJS (+) countSelfCallsInTailPosition js
64− numSelfCallsUnderFunctions = everythingOnJS (+) countSelfCallsUnderFunctions js
65− in
66− numSelfCalls > 0
67− && numSelfCalls == numSelfCallsInTailPosition
68− && numSelfCallsUnderFunctions == 0
69− where
70− countSelfCalls :: JS -> Int
71− countSelfCalls (JSApp (JSVar ident') _) | ident == ident' = 1
72− countSelfCalls _ = 0
73− countSelfCallsInTailPosition :: JS -> Int
74− countSelfCallsInTailPosition (JSReturn ret) | isSelfCall ident ret = 1
75− countSelfCallsInTailPosition _ = 0
76− countSelfCallsUnderFunctions (JSFunction _ _ js') = everythingOnJS (+) countSelfCalls js'
77− countSelfCallsUnderFunctions _ = 0
78− toLoop :: String -> [String] -> JS -> JS
79− toLoop ident allArgs js = JSBlock $
80− map (\arg -> JSVariableIntroduction arg (Just (JSVar (copyVar arg)))) allArgs ++
81− [ JSLabel tcoLabel $ JSWhile (JSBooleanLiteral True) (JSBlock [ everywhereOnJS loopify js ]) ]
82− where
83− loopify :: JS -> JS
84− loopify (JSReturn ret) | isSelfCall ident ret =
85− let
86− allArgumentValues = concat $ collectSelfCallArgs [] ret
87− in
88− JSBlock $ zipWith (\val arg ->
89− JSVariableIntroduction (tcoVar arg) (Just val)) allArgumentValues allArgs
90− ++ map (\arg ->
91− JSAssignment (JSVar arg) (JSVar (tcoVar arg))) allArgs
92− ++ [ JSContinue tcoLabel ]
93− loopify other = other
94− collectSelfCallArgs :: [[JS]] -> JS -> [[JS]]
95− collectSelfCallArgs allArgumentValues (JSApp fn args') = collectSelfCallArgs (args' : allArgumentValues) fn
96− collectSelfCallArgs allArgumentValues _ = allArgumentValues
97− isSelfCall :: String -> JS -> Bool
98− isSelfCall ident (JSApp (JSVar ident') args) | ident == ident' && not (any isFunction args) = True
99− isSelfCall ident (JSApp fn args) | not (any isFunction args) = isSelfCall ident fn
100− isSelfCall _ _ = False
101− isFunction :: JS -> Bool
102− isFunction (JSFunction _ _ _) = True
103− isFunction _ = False
src/Language/PureScript/Optimizer/Unused.hsdeleted−30
@@ -1,30 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Optimizer.Unused
4−-- Copyright : (c) Phil Freeman 2013-14
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Removes unused variables
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Optimizer.Unused (
17− removeCodeAfterReturnStatements
18−) where
19−
20−import Language.PureScript.CodeGen.JS.AST
21−import Language.PureScript.Optimizer.Common
22−
23−removeCodeAfterReturnStatements :: JS -> JS
24−removeCodeAfterReturnStatements = everywhereOnJS (removeFromBlock go)
25− where
26− go :: [JS] -> [JS]
27− go jss | not (any isJSReturn jss) = jss
28− | otherwise = let (body, ret : _) = span (not . isJSReturn) jss in body ++ [ret]
29− isJSReturn (JSReturn _) = True
30− isJSReturn _ = False
src/Language/PureScript/Options.hsdeleted−70
@@ -1,70 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Options
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- The data type of compiler options
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Options where
17−
18−-- |
19−-- The data type of compiler options
20−--
21−data Options = Options {
22− -- |
23− -- Disable inclusion of the built in Prelude
24− --
25− optionsNoPrelude :: Bool
26− -- |
27− -- Disable tail-call elimination
28− --
29− , optionsNoTco :: Bool
30− -- |
31− -- Perform type checks at runtime
32− --
33− , optionsPerformRuntimeTypeChecks :: Bool
34− -- |
35− -- Disable inlining of calls to return and bind for the Eff monad
36− --
37− , optionsNoMagicDo :: Bool
38− -- |
39− -- When specified, checks the type of `main` in the module, and generate a call to run main
40− -- after the module definitions.
41− --
42− , optionsMain :: Maybe String
43− -- |
44− -- Skip all optimizations
45− --
46− , optionsNoOptimizations :: Bool
47− -- |
48− -- Specify the namespace that PureScript modules will be exported to when running in the
49− -- browser.
50− --
51− , optionsBrowserNamespace :: Maybe String
52− -- |
53− -- The modules to keep while enabling dead code elimination
54− --
55− , optionsModules :: [String]
56− -- |
57− -- The modules to code gen
58− --
59− , optionsCodeGenModules :: [String]
60− -- |
61− -- Verbose error message
62− --
63− , optionsVerboseErrors :: Bool
64− } deriving Show
65−
66−-- |
67−-- Default compiler options
68−--
69−defaultOptions :: Options
70−defaultOptions = Options False False False False Nothing False Nothing [] [] False
src/Language/PureScript/Parser.hsdeleted−34
@@ -1,34 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- A collection of parsers for core data types:
13−--
14−-- [@Language.PureScript.Parser.Kinds@] Parser for kinds
15−--
16−-- [@Language.PureScript.Parser.Values@] Parser for values
17−--
18−-- [@Language.PureScript.Parser.Types@] Parser for types
19−--
20−-- [@Language.PureScript.Parser.Declaration@] Parsers for declarations and modules
21−--
22−-- [@Language.PureScript.Parser.State@] Parser state, including indentation
23−--
24−-- [@Language.PureScript.Parser.Common@] Common parsing utility functions
25−--
26−-----------------------------------------------------------------------------
27−
28−module Language.PureScript.Parser (module P) where
29−
30−import Language.PureScript.Parser.Common as P
31−import Language.PureScript.Parser.Types as P
32−import Language.PureScript.Parser.State as P
33−import Language.PureScript.Parser.Kinds as P
34−import Language.PureScript.Parser.Declarations as P
src/Language/PureScript/Parser/Common.hsdeleted−378
@@ -1,378 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser.Common
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Constants, and utility functions to be used when parsing
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE FlexibleContexts #-}
17−
18−module Language.PureScript.Parser.Common where
19−
20−import Data.Functor.Identity
21−import Control.Applicative
22−import Control.Monad
23−import Language.PureScript.Parser.State
24−import qualified Text.Parsec as P
25−import qualified Text.Parsec.Token as PT
26−
27−import Language.PureScript.Names
28−
29−-- |
30−-- A list of purescript reserved identifiers
31−--
32−reservedPsNames :: [String]
33−reservedPsNames = [ "data"
34− , "type"
35− , "foreign"
36− , "import"
37− , "infixl"
38− , "infixr"
39− , "infix"
40− , "class"
41− , "instance"
42− , "module"
43− , "case"
44− , "of"
45− , "if"
46− , "then"
47− , "else"
48− , "do"
49− , "let"
50− , "true"
51− , "false"
52− , "in"
53− , "where"
54− ]
55−
56−-- |
57−-- The characters allowed for use in operators
58−--
59−opChars :: [Char]
60−opChars = ":!#$%&*+./<=>?@\\^|-~"
61−
62−-- |
63−-- A list of reserved identifiers for types
64−--
65−reservedTypeNames :: [String]
66−reservedTypeNames = [ "forall"
67− , "where" ]
68−
69−-- |
70−-- A list of reserved operators
71−--
72−reservedOpNames :: [String]
73−reservedOpNames = [ "=>", "->", "=", ".", "\\" ]
74−
75−-- |
76−-- Valid first characters for an identifier
77−--
78−identStart :: P.Parsec String u Char
79−identStart = P.lower <|> P.oneOf "_"
80−
81−-- |
82−-- Valid identifier characters
83−--
84−identLetter :: P.Parsec String u Char
85−identLetter = P.alphaNum <|> P.oneOf "_'"
86−
87−-- |
88−-- Valid first characters for an operator
89−--
90−opStart :: P.Parsec String u Char
91−opStart = P.oneOf opChars
92−
93−-- |
94−-- Valid operators characters
95−--
96−opLetter :: P.Parsec String u Char
97−opLetter = P.oneOf opChars
98−
99−-- |
100−-- The PureScript language definition
101−--
102−langDef :: PT.GenLanguageDef String u Identity
103−langDef = PT.LanguageDef
104− { PT.reservedNames = reservedPsNames
105− , PT.reservedOpNames = reservedOpNames
106− , PT.commentStart = "{-"
107− , PT.commentEnd = "-}"
108− , PT.commentLine = "--"
109− , PT.nestedComments = True
110− , PT.identStart = identStart
111− , PT.identLetter = identLetter
112− , PT.opStart = opStart
113− , PT.opLetter = opLetter
114− , PT.caseSensitive = True
115− }
116−
117−-- |
118−-- A token parser based on the language definition
119−--
120−tokenParser :: PT.GenTokenParser String u Identity
121−tokenParser = PT.makeTokenParser langDef
122−
123−-- |
124−-- Parse a token
125−--
126−lexeme :: P.Parsec String u a -> P.Parsec String u a
127−lexeme = PT.lexeme tokenParser
128−
129−-- |
130−-- Parse an identifier
131−--
132−identifier :: P.Parsec String u String
133−identifier = PT.identifier tokenParser
134−
135−-- |
136−-- Parse a reserved word
137−--
138−reserved :: String -> P.Parsec String u ()
139−reserved = PT.reserved tokenParser
140−
141−-- |
142−-- Parse a reserved operator
143−--
144−reservedOp :: String -> P.Parsec String u ()
145−reservedOp = PT.reservedOp tokenParser
146−
147−-- |
148−-- Parse an operator
149−--
150−operator :: P.Parsec String u String
151−operator = PT.operator tokenParser
152−
153−-- |
154−-- Parse a string literal
155−--
156−stringLiteral :: P.Parsec String u String
157−stringLiteral = PT.stringLiteral tokenParser
158−
159−-- |
160−-- Parse whitespace
161−--
162−whiteSpace :: P.Parsec String u ()
163−whiteSpace = PT.whiteSpace tokenParser
164−
165−-- |
166−-- Semicolon
167−--
168−semi :: P.Parsec String u String
169−semi = PT.semi tokenParser
170−
171−-- |
172−-- Colon
173−--
174−colon :: P.Parsec String u String
175−colon = PT.colon tokenParser
176−
177−-- |
178−-- Period
179−--
180−dot :: P.Parsec String u String
181−dot = PT.dot tokenParser
182−
183−-- |
184−-- Comma
185−--
186−comma :: P.Parsec String u String
187−comma = PT.comma tokenParser
188−
189−-- |
190−-- Backtick
191−--
192−tick :: P.Parsec String u Char
193−tick = lexeme $ P.char '`'
194−
195−-- |
196−-- Pipe character
197−--
198−pipe :: P.Parsec String u Char
199−pipe = lexeme $ P.char '|'
200−
201−-- |
202−-- Natural number
203−--
204−natural :: P.Parsec String u Integer
205−natural = PT.natural tokenParser
206−
207−-- |
208−-- Parse a proper name
209−--
210−properName :: P.Parsec String u ProperName
211−properName = lexeme $ ProperName <$> P.try ((:) <$> P.upper <*> many P.alphaNum P.<?> "name")
212−
213−-- |
214−-- Parse a module name
215−--
216−moduleName :: P.Parsec String ParseState ModuleName
217−moduleName = ModuleName <$> P.try (sepBy properName dot)
218−
219−-- |
220−-- Parse a qualified name, i.e. M.name or just name
221−--
222−parseQualified :: P.Parsec String ParseState a -> P.Parsec String ParseState (Qualified a)
223−parseQualified parser = part []
224− where
225− part path = (do name <- P.try (properName <* delimiter)
226− part (updatePath path name))
227− <|> (Qualified (qual path) <$> P.try parser)
228− delimiter = indented *> dot <* P.notFollowedBy dot
229− updatePath path name = path ++ [name]
230− qual path = if null path then Nothing else Just $ ModuleName path
231−
232−-- |
233−-- Parse an integer or floating point value
234−--
235−integerOrFloat :: P.Parsec String u (Either Integer Double)
236−integerOrFloat = (Right <$> P.try (PT.float tokenParser) <|>
237− Left <$> P.try (PT.natural tokenParser)) P.<?> "number"
238−
239−-- |
240−-- Parse an identifier or parenthesized operator
241−--
242−parseIdent :: P.Parsec String ParseState Ident
243−parseIdent = (Ident <$> identifier) <|> (Op <$> parens operator)
244−
245−-- |
246−-- Parse a token inside square brackets
247−--
248−squares :: P.Parsec String ParseState a -> P.Parsec String ParseState a
249−squares = P.between (lexeme $ P.char '[') (lexeme $ indented *> P.char ']') . (indented *>)
250−
251−-- |
252−-- Parse a token inside parentheses
253−--
254−parens :: P.Parsec String ParseState a -> P.Parsec String ParseState a
255−parens = P.between (lexeme $ P.char '(') (lexeme $ indented *> P.char ')') . (indented *>)
256−
257−-- |
258−-- Parse a token inside braces
259−--
260−braces :: P.Parsec String ParseState a -> P.Parsec String ParseState a
261−braces = P.between (lexeme $ P.char '{') (lexeme $ indented *> P.char '}') . (indented *>)
262−
263−-- |
264−-- Parse a token inside angle brackets
265−--
266−angles :: P.Parsec String ParseState a -> P.Parsec String ParseState a
267−angles = P.between (lexeme $ P.char '<') (lexeme $ indented *> P.char '>') . (indented *>)
268−
269−-- |
270−-- Parse zero or more values separated by a separator token
271−--
272−sepBy :: P.Parsec String ParseState a -> P.Parsec String ParseState sep -> P.Parsec String ParseState [a]
273−sepBy p s = P.sepBy (indented *> p) (indented *> s)
274−
275−-- |
276−-- Parse one or more values separated by a separator token
277−--
278−sepBy1 :: P.Parsec String ParseState a -> P.Parsec String ParseState sep -> P.Parsec String ParseState [a]
279−sepBy1 p s = P.sepBy1 (indented *> p) (indented *> s)
280−
281−-- |
282−-- Parse zero or more values separated by semicolons
283−--
284−semiSep :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
285−semiSep = flip sepBy semi
286−
287−-- |
288−-- Parse one or more values separated by semicolons
289−--
290−semiSep1 :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
291−semiSep1 = flip sepBy1 semi
292−
293−-- |
294−-- Parse zero or more values separated by commas
295−--
296−commaSep :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
297−commaSep = flip sepBy comma
298−
299−-- |
300−-- Parse one or more values separated by commas
301−--
302−commaSep1 :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
303−commaSep1 = flip sepBy1 comma
304−
305−-- |
306−-- Run the first parser, then match the second if possible, applying the specified function on a successful match
307−--
308−augment :: P.Stream s m t => P.ParsecT s u m a -> P.ParsecT s u m b -> (a -> b -> a) -> P.ParsecT s u m a
309−augment p q f = flip (maybe id $ flip f) <$> p <*> P.optionMaybe q
310−
311−-- |
312−-- Run the first parser, then match the second zero or more times, applying the specified function for each match
313−--
314−fold :: P.Stream s m t => P.ParsecT s u m a -> P.ParsecT s u m b -> (a -> b -> a) -> P.ParsecT s u m a
315−fold first more combine = do
316− a <- first
317− bs <- P.many more
318− return $ foldl combine a bs
319−
320−-- |
321−-- Build a parser from a smaller parser and a list of parsers for postfix operators
322−--
323−buildPostfixParser :: P.Stream s m t => [a -> P.ParsecT s u m a] -> P.ParsecT s u m a -> P.ParsecT s u m a
324−buildPostfixParser fs first = do
325− a <- first
326− go a
327− where
328− go a = do
329− maybeA <- P.optionMaybe $ P.choice (map ($ a) fs)
330− case maybeA of
331− Nothing -> return a
332− Just a' -> go a'
333−
334−-- |
335−-- Parse an identifier in backticks or an operator
336−--
337−parseIdentInfix :: P.Parsec String ParseState (Qualified Ident)
338−parseIdentInfix = P.between tick tick (parseQualified (Ident <$> identifier)) <|> (parseQualified (Op <$> operator))
339−
340−-- |
341−-- Mark the current indentation level
342−--
343−mark :: P.Parsec String ParseState a -> P.Parsec String ParseState a
344−mark p = do
345− current <- indentationLevel <$> P.getState
346− pos <- P.sourceColumn <$> P.getPosition
347− P.modifyState $ \st -> st { indentationLevel = pos }
348− a <- p
349− P.modifyState $ \st -> st { indentationLevel = current }
350− return a
351−
352−-- |
353−-- Check that the current identation level matches a predicate
354−--
355−checkIndentation :: (P.Column -> P.Column -> Bool) -> P.Parsec String ParseState ()
356−checkIndentation rel = do
357− col <- P.sourceColumn <$> P.getPosition
358− current <- indentationLevel <$> P.getState
359− guard (col `rel` current)
360−
361−-- |
362−-- Check that the current indentation level is past the current mark
363−--
364−indented :: P.Parsec String ParseState ()
365−indented = checkIndentation (>) P.<?> "indentation"
366−
367−-- |
368−-- Check that the current indentation level is at the same indentation as the current mark
369−--
370−same :: P.Parsec String ParseState ()
371−same = checkIndentation (==) P.<?> "no indentation"
372−
373−-- |
374−-- Run a parser which supports indentation
375−--
376−runIndentParser :: FilePath -> P.Parsec String ParseState a -> String -> Either P.ParseError a
377−runIndentParser filePath p = P.runParser p (ParseState 0) filePath
378−
src/Language/PureScript/Parser/Declarations.hsdeleted−430
@@ -1,430 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser.Declarations
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Parsers for module definitions and declarations
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Parser.Declarations (
17− parseDeclaration,
18− parseModule,
19− parseModules,
20− parseValue,
21− parseGuard,
22− parseBinder,
23− parseBinderNoParens,
24−) where
25−
26−import Data.Maybe (isJust, fromMaybe)
27−import Control.Applicative
28−
29−import Language.PureScript.Parser.State
30−import Language.PureScript.Parser.Common
31−import Language.PureScript.Declarations
32−import Language.PureScript.Parser.Types
33−import Language.PureScript.Parser.Kinds
34−import Language.PureScript.CodeGen.JS.AST
35−import Language.PureScript.Environment
36−
37−import qualified Language.PureScript.Parser.Common as C
38−import qualified Text.Parsec as P
39−import qualified Text.Parsec.Expr as P
40−
41−-- |
42−-- Read source position information
43−--
44−sourcePos :: P.Parsec s u SourcePos
45−sourcePos = toSourcePos <$> P.getPosition
46− where
47− toSourcePos p = SourcePos (P.sourceName p) (P.sourceLine p) (P.sourceColumn p)
48−
49−parseDataDeclaration :: P.Parsec String ParseState Declaration
50−parseDataDeclaration = do
51− reserved "data"
52− name <- indented *> properName
53− tyArgs <- many (indented *> identifier)
54− ctors <- P.option [] $ do
55− _ <- lexeme $ indented *> P.char '='
56− sepBy1 ((,) <$> properName <*> P.many (indented *> parseTypeAtom)) pipe
57− return $ DataDeclaration name tyArgs ctors
58−
59−parseTypeDeclaration :: P.Parsec String ParseState Declaration
60−parseTypeDeclaration =
61− TypeDeclaration <$> P.try (parseIdent <* lexeme (indented *> P.string "::"))
62− <*> parsePolyType
63−
64−parseTypeSynonymDeclaration :: P.Parsec String ParseState Declaration
65−parseTypeSynonymDeclaration =
66− TypeSynonymDeclaration <$> (P.try (reserved "type") *> indented *> properName)
67− <*> many (indented *> identifier)
68− <*> (lexeme (indented *> P.char '=') *> parsePolyType)
69−
70−parseValueDeclaration :: P.Parsec String ParseState Declaration
71−parseValueDeclaration = do
72− name <- parseIdent
73− binders <- P.many parseBinderNoParens
74− guard <- P.optionMaybe parseGuard
75− value <- lexeme (indented *> P.char '=') *> parseValue
76− whereClause <- P.optionMaybe $ do
77− C.indented
78− reserved "where"
79− C.indented
80− C.mark $ P.many1 (C.same *> parseLocalDeclaration)
81− return $ ValueDeclaration name Value binders guard (maybe value (`Let` value) whereClause)
82−
83−parseExternDeclaration :: P.Parsec String ParseState Declaration
84−parseExternDeclaration = P.try (reserved "foreign") *> indented *> reserved "import" *> indented *>
85− (ExternDataDeclaration <$> (P.try (reserved "data") *> indented *> properName)
86− <*> (lexeme (indented *> P.string "::") *> parseKind)
87− <|> (do reserved "instance"
88− name <- parseIdent <* lexeme (indented *> P.string "::")
89− deps <- P.option [] $ do
90− deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many parseTypeAtom))
91− indented
92− reservedOp "=>"
93− return deps
94− className <- indented *> parseQualified properName
95− tys <- P.many (indented *> parseTypeAtom)
96− return $ ExternInstanceDeclaration name deps className tys)
97− <|> (do ident <- parseIdent
98− js <- P.optionMaybe (JSRaw <$> stringLiteral)
99− ty <- lexeme (indented *> P.string "::") *> parsePolyType
100− return $ ExternDeclaration (if isJust js then InlineJavascript else ForeignImport) ident js ty))
101−
102−parseAssociativity :: P.Parsec String ParseState Associativity
103−parseAssociativity =
104− (P.try (reserved "infixl") >> return Infixl) <|>
105− (P.try (reserved "infixr") >> return Infixr) <|>
106− (P.try (reserved "infix") >> return Infix)
107−
108−parseFixity :: P.Parsec String ParseState Fixity
109−parseFixity = Fixity <$> parseAssociativity <*> (indented *> natural)
110−
111−parseFixityDeclaration :: P.Parsec String ParseState Declaration
112−parseFixityDeclaration = do
113− fixity <- parseFixity
114− indented
115− name <- operator
116− return $ FixityDeclaration fixity name
117−
118−parseImportDeclaration :: P.Parsec String ParseState Declaration
119−parseImportDeclaration = do
120− reserved "import"
121− indented
122− qualImport <|> stdImport
123− where
124− stdImport = do
125− moduleName' <- moduleName
126− idents <- P.optionMaybe $ indented *> (parens $ commaSep parseDeclarationRef)
127− return $ ImportDeclaration moduleName' idents Nothing
128− qualImport = do
129− reserved "qualified"
130− indented
131− moduleName' <- moduleName
132− idents <- P.optionMaybe $ indented *> (parens $ commaSep parseDeclarationRef)
133− reserved "as"
134− asQ <- moduleName
135− return $ ImportDeclaration moduleName' idents (Just asQ)
136−
137−parseDeclarationRef :: P.Parsec String ParseState DeclarationRef
138−parseDeclarationRef = PositionedDeclarationRef <$> sourcePos <*>
139− (ValueRef <$> parseIdent
140− <|> do name <- properName
141− dctors <- P.optionMaybe $ parens (lexeme (P.string "..") *> pure Nothing <|> Just <$> commaSep properName)
142− return $ maybe (TypeClassRef name) (TypeRef name) dctors)
143−
144−parseTypeClassDeclaration :: P.Parsec String ParseState Declaration
145−parseTypeClassDeclaration = do
146− reserved "class"
147− implies <- P.option [] $ do
148− indented
149− implies <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many parseTypeAtom))
150− reservedOp "<="
151− return implies
152− className <- indented *> properName
153− idents <- P.many (indented *> identifier)
154− members <- P.option [] . P.try $ do
155− indented *> reserved "where"
156− mark (P.many (same *> positioned parseTypeDeclaration))
157− return $ TypeClassDeclaration className idents implies members
158−
159−parseTypeInstanceDeclaration :: P.Parsec String ParseState Declaration
160−parseTypeInstanceDeclaration = do
161− reserved "instance"
162− name <- parseIdent <* lexeme (indented *> P.string "::")
163− deps <- P.optionMaybe $ do
164− deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many parseTypeAtom))
165− indented
166− reservedOp "=>"
167− return deps
168− className <- indented *> parseQualified properName
169− ty <- P.many (indented *> parseTypeAtom)
170− members <- P.option [] . P.try $ do
171− indented *> reserved "where"
172− mark (P.many (same *> positioned parseValueDeclaration))
173− return $ TypeInstanceDeclaration name (fromMaybe [] deps) className ty members
174−
175−positioned :: P.Parsec String ParseState Declaration -> P.Parsec String ParseState Declaration
176−positioned d = PositionedDeclaration <$> sourcePos <*> d
177−
178−-- |
179−-- Parse a single declaration
180−--
181−parseDeclaration :: P.Parsec String ParseState Declaration
182−parseDeclaration = positioned (P.choice
183− [ parseDataDeclaration
184− , parseTypeDeclaration
185− , parseTypeSynonymDeclaration
186− , parseValueDeclaration
187− , parseExternDeclaration
188− , parseFixityDeclaration
189− , parseImportDeclaration
190− , parseTypeClassDeclaration
191− , parseTypeInstanceDeclaration
192− ]) P.<?> "declaration"
193−
194−parseLocalDeclaration :: P.Parsec String ParseState Declaration
195−parseLocalDeclaration = PositionedDeclaration <$> sourcePos <*> P.choice
196− [ parseTypeDeclaration
197− , parseValueDeclaration
198− ] P.<?> "local declaration"
199−
200−-- |
201−-- Parse a module header and a collection of declarations
202−--
203−parseModule :: P.Parsec String ParseState Module
204−parseModule = do
205− reserved "module"
206− indented
207− name <- moduleName
208− exports <- P.optionMaybe $ parens $ commaSep1 parseDeclarationRef
209− _ <- lexeme $ P.string "where"
210− decls <- mark (P.many (same *> parseDeclaration))
211− return $ Module name decls exports
212−
213−-- |
214−-- Parse a collection of modules
215−--
216−parseModules :: P.Parsec String ParseState [Module]
217−parseModules = whiteSpace *> mark (P.many (same *> parseModule)) <* P.eof
218−
219−booleanLiteral :: P.Parsec String ParseState Bool
220−booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
221−
222−parseNumericLiteral :: P.Parsec String ParseState Value
223−parseNumericLiteral = NumericLiteral <$> C.integerOrFloat
224−
225−parseStringLiteral :: P.Parsec String ParseState Value
226−parseStringLiteral = StringLiteral <$> C.stringLiteral
227−
228−parseBooleanLiteral :: P.Parsec String ParseState Value
229−parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
230−
231−parseArrayLiteral :: P.Parsec String ParseState Value
232−parseArrayLiteral = ArrayLiteral <$> C.squares (C.commaSep parseValue)
233−
234−parseObjectLiteral :: P.Parsec String ParseState Value
235−parseObjectLiteral = ObjectLiteral <$> C.braces (C.commaSep parseIdentifierAndValue)
236−
237−parseIdentifierAndValue :: P.Parsec String ParseState (String, Value)
238−parseIdentifierAndValue = (,) <$> (C.indented *> (C.identifier <|> C.stringLiteral) <* C.indented <* C.colon)
239− <*> (C.indented *> parseValue)
240−
241−parseAbs :: P.Parsec String ParseState Value
242−parseAbs = do
243− C.reservedOp "\\"
244− args <- P.many1 (C.indented *> (Abs <$> (Left <$> P.try C.parseIdent <|> Right <$> parseBinderNoParens)))
245− C.indented *> C.reservedOp "->"
246− value <- parseValue
247− return $ toFunction args value
248− where
249− toFunction :: [Value -> Value] -> Value -> Value
250− toFunction args value = foldr ($) value args
251−
252−parseVar :: P.Parsec String ParseState Value
253−parseVar = Var <$> C.parseQualified C.parseIdent
254−
255−parseConstructor :: P.Parsec String ParseState Value
256−parseConstructor = Constructor <$> C.parseQualified C.properName
257−
258−parseCase :: P.Parsec String ParseState Value
259−parseCase = Case <$> P.between (P.try (C.reserved "case")) (C.indented *> C.reserved "of") (return <$> parseValue)
260− <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
261−
262−parseCaseAlternative :: P.Parsec String ParseState CaseAlternative
263−parseCaseAlternative = CaseAlternative <$> (return <$> parseBinder)
264− <*> P.optionMaybe parseGuard
265− <*> (C.indented *> C.reservedOp "->" *> parseValue)
266− P.<?> "case alternative"
267−
268−parseIfThenElse :: P.Parsec String ParseState Value
269−parseIfThenElse = IfThenElse <$> (P.try (C.reserved "if") *> C.indented *> parseValue)
270− <*> (C.indented *> C.reserved "then" *> C.indented *> parseValue)
271− <*> (C.indented *> C.reserved "else" *> C.indented *> parseValue)
272−
273−parseLet :: P.Parsec String ParseState Value
274−parseLet = do
275− C.reserved "let"
276− C.indented
277− ds <- C.mark $ P.many1 (C.same *> parseLocalDeclaration)
278− C.indented
279− C.reserved "in"
280− result <- parseValue
281− return $ Let ds result
282−
283−parseValueAtom :: P.Parsec String ParseState Value
284−parseValueAtom = P.choice
285− [ P.try parseNumericLiteral
286− , P.try parseStringLiteral
287− , P.try parseBooleanLiteral
288− , parseArrayLiteral
289− , P.try parseObjectLiteral
290− , parseAbs
291− , P.try parseConstructor
292− , P.try parseVar
293− , parseCase
294− , parseIfThenElse
295− , parseDo
296− , parseLet
297− , Parens <$> C.parens parseValue ]
298−
299−parsePropertyUpdate :: P.Parsec String ParseState (String, Value)
300−parsePropertyUpdate = do
301− name <- C.lexeme (C.identifier <|> C.stringLiteral)
302− _ <- C.lexeme $ C.indented *> P.char '='
303− value <- C.indented *> parseValue
304− return (name, value)
305−
306−parseAccessor :: Value -> P.Parsec String ParseState Value
307−parseAccessor (Constructor _) = P.unexpected "constructor"
308−parseAccessor obj = P.try $ Accessor <$> (C.indented *> C.dot *> P.notFollowedBy C.opLetter *> C.indented *> (C.identifier <|> C.stringLiteral)) <*> pure obj
309−
310−parseDo :: P.Parsec String ParseState Value
311−parseDo = do
312− C.reserved "do"
313− C.indented
314− Do <$> C.mark (P.many (C.same *> C.mark parseDoNotationElement))
315−
316−parseDoNotationLet :: P.Parsec String ParseState DoNotationElement
317−parseDoNotationLet = DoNotationLet <$> (C.reserved "let" *> C.indented *> C.mark (P.many1 (C.same *> parseLocalDeclaration)))
318−
319−parseDoNotationBind :: P.Parsec String ParseState DoNotationElement
320−parseDoNotationBind = DoNotationBind <$> parseBinder <*> (C.indented *> C.reservedOp "<-" *> parseValue)
321−
322−parseDoNotationElement :: P.Parsec String ParseState DoNotationElement
323−parseDoNotationElement = P.choice
324− [ P.try parseDoNotationBind
325− , parseDoNotationLet
326− , P.try (DoNotationValue <$> parseValue) ]
327−
328−-- |
329−-- Parse a value
330−--
331−parseValue :: P.Parsec String ParseState Value
332−parseValue = PositionedValue <$> sourcePos <*>
333− (P.buildExpressionParser operators
334− . C.buildPostfixParser postfixTable2
335− $ indexersAndAccessors) P.<?> "expression"
336− where
337− indexersAndAccessors = C.buildPostfixParser postfixTable1 parseValueAtom
338− postfixTable1 = [ parseAccessor
339− , \v -> P.try $ flip ObjectUpdate <$> (C.indented *> C.braces (C.commaSep1 (C.indented *> parsePropertyUpdate))) <*> pure v ]
340− postfixTable2 = [ \v -> P.try (flip App <$> (C.indented *> indexersAndAccessors)) <*> pure v
341− , \v -> flip (TypedValue True) <$> (P.try (C.lexeme (C.indented *> P.string "::")) *> parsePolyType) <*> pure v
342− ]
343− operators = [ [ P.Prefix (C.lexeme (P.try (C.indented *> P.char '-') >> return UnaryMinus))
344− ]
345− , [ P.Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix P.<?> "operator") >>= \ident ->
346− return (BinaryNoParens ident))) P.AssocRight
347− ]
348− ]
349−
350−parseStringBinder :: P.Parsec String ParseState Binder
351−parseStringBinder = StringBinder <$> C.stringLiteral
352−
353−parseBooleanBinder :: P.Parsec String ParseState Binder
354−parseBooleanBinder = BooleanBinder <$> booleanLiteral
355−
356−parseNumberBinder :: P.Parsec String ParseState Binder
357−parseNumberBinder = NumberBinder <$> C.integerOrFloat
358−
359−parseVarBinder :: P.Parsec String ParseState Binder
360−parseVarBinder = VarBinder <$> C.parseIdent
361−
362−parseNullaryConstructorBinder :: P.Parsec String ParseState Binder
363−parseNullaryConstructorBinder = ConstructorBinder <$> C.lexeme (C.parseQualified C.properName) <*> pure []
364−
365−parseConstructorBinder :: P.Parsec String ParseState Binder
366−parseConstructorBinder = ConstructorBinder <$> C.lexeme (C.parseQualified C.properName) <*> many (C.indented *> parseBinderNoParens)
367−
368−parseObjectBinder :: P.Parsec String ParseState Binder
369−parseObjectBinder = ObjectBinder <$> C.braces (C.commaSep (C.indented *> parseIdentifierAndBinder))
370−
371−parseArrayBinder :: P.Parsec String ParseState Binder
372−parseArrayBinder = C.squares $ ArrayBinder <$> C.commaSep (C.indented *> parseBinder)
373−
374−parseNamedBinder :: P.Parsec String ParseState Binder
375−parseNamedBinder = NamedBinder <$> (C.parseIdent <* C.indented <* C.lexeme (P.char '@'))
376− <*> (C.indented *> parseBinder)
377−
378−parseNullBinder :: P.Parsec String ParseState Binder
379−parseNullBinder = C.lexeme (P.char '_') *> P.notFollowedBy C.identLetter *> return NullBinder
380−
381−parseIdentifierAndBinder :: P.Parsec String ParseState (String, Binder)
382−parseIdentifierAndBinder = do
383− name <- C.lexeme (C.identifier <|> C.stringLiteral)
384− _ <- C.lexeme $ C.indented *> P.char '='
385− binder <- C.indented *> parseBinder
386− return (name, binder)
387−
388−-- |
389−-- Parse a binder
390−--
391−parseBinder :: P.Parsec String ParseState Binder
392−parseBinder = PositionedBinder <$> sourcePos <*>
393− P.buildExpressionParser operators parseBinderAtom P.<?> "expression"
394− where
395− operators = [ [ P.Infix ( C.lexeme (P.try $ C.indented *> C.reservedOp ":") >> return ConsBinder) P.AssocRight ] ]
396− parseBinderAtom :: P.Parsec String ParseState Binder
397− parseBinderAtom = P.choice (map P.try
398− [ parseNullBinder
399− , parseStringBinder
400− , parseBooleanBinder
401− , parseNumberBinder
402− , parseNamedBinder
403− , parseVarBinder
404− , parseConstructorBinder
405− , parseObjectBinder
406− , parseArrayBinder
407− , C.parens parseBinder ]) P.<?> "binder"
408−
409−-- |
410−-- Parse a binder as it would appear in a top level declaration
411−--
412−parseBinderNoParens :: P.Parsec String ParseState Binder
413−parseBinderNoParens = P.choice (map P.try
414− [ parseNullBinder
415− , parseStringBinder
416− , parseBooleanBinder
417− , parseNumberBinder
418− , parseNamedBinder
419− , parseVarBinder
420− , parseNullaryConstructorBinder
421− , parseObjectBinder
422− , parseArrayBinder
423− , C.parens parseBinder ]) P.<?> "binder"
424−-- |
425−-- Parse a guard
426−--
427−parseGuard :: P.Parsec String ParseState Guard
428−parseGuard = C.indented *> C.pipe *> C.indented *> parseValue
429−
430−
src/Language/PureScript/Parser/Kinds.hsdeleted−45
@@ -1,45 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser.Kinds
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- A parser for kinds
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Parser.Kinds (
17− parseKind
18−) where
19−
20−import Language.PureScript.Kinds
21−import Language.PureScript.Parser.State
22−import Language.PureScript.Parser.Common
23−import Control.Applicative
24−import qualified Text.Parsec as P
25−import qualified Text.Parsec.Expr as P
26−
27−parseStar :: P.Parsec String ParseState Kind
28−parseStar = const Star <$> lexeme (P.char '*')
29−
30−parseBang :: P.Parsec String ParseState Kind
31−parseBang = const Bang <$> lexeme (P.char '!')
32−
33−parseTypeAtom :: P.Parsec String ParseState Kind
34−parseTypeAtom = indented *> P.choice (map P.try
35− [ parseStar
36− , parseBang
37− , parens parseKind ])
38−-- |
39−-- Parse a kind
40−--
41−parseKind :: P.Parsec String ParseState Kind
42−parseKind = P.buildExpressionParser operators parseTypeAtom P.<?> "kind"
43− where
44− operators = [ [ P.Prefix (lexeme (P.char '#') >> return Row) ]
45− , [ P.Infix (lexeme (P.try (P.string "->")) >> return FunKind) P.AssocRight ] ]
src/Language/PureScript/Parser/State.hsdeleted−30
@@ -1,30 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser.State
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- State for the parser monad
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Parser.State where
17−
18−import qualified Text.Parsec as P
19−
20−-- |
21−-- State for the parser monad
22−--
23−data ParseState = ParseState {
24− -- |
25− -- The most recently marked indentation level
26− --
27− indentationLevel :: P.Column
28− } deriving Show
29−
30−
src/Language/PureScript/Parser/Types.hsdeleted−116
@@ -1,116 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser.Types
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Parsers for types
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Parser.Types (
17− parseType,
18− parsePolyType,
19− parseTypeAtom
20−) where
21−
22−import Control.Applicative
23−import Control.Monad (when, unless)
24−
25−import Language.PureScript.Types
26−import Language.PureScript.Parser.State
27−import Language.PureScript.Parser.Common
28−import Language.PureScript.Environment
29−
30−import qualified Text.Parsec as P
31−import qualified Text.Parsec.Expr as P
32−
33−parseArray :: P.Parsec String ParseState Type
34−parseArray = squares $ return tyArray
35−
36−parseArrayOf :: P.Parsec String ParseState Type
37−parseArrayOf = squares $ TypeApp tyArray <$> parseType
38−
39−parseFunction :: P.Parsec String ParseState Type
40−parseFunction = parens $ P.try (lexeme (P.string "->")) >> return tyFunction
41−
42−parseObject :: P.Parsec String ParseState Type
43−parseObject = braces $ TypeApp tyObject <$> parseRow False
44−
45−parseTypeVariable :: P.Parsec String ParseState Type
46−parseTypeVariable = do
47− ident <- identifier
48− when (ident `elem` reservedTypeNames) $ P.unexpected ident
49− return $ TypeVar ident
50−
51−parseTypeConstructor :: P.Parsec String ParseState Type
52−parseTypeConstructor = TypeConstructor <$> parseQualified properName
53−
54−parseForAll :: P.Parsec String ParseState Type
55−parseForAll = mkForAll <$> (P.try (reserved "forall") *> P.many1 (indented *> identifier) <* indented <* dot)
56− <*> parseConstrainedType
57−
58−-- |
59−-- Parse a type as it appears in e.g. a data constructor
60−--
61−parseTypeAtom :: P.Parsec String ParseState Type
62−parseTypeAtom = indented *> P.choice (map P.try
63− [ parseArray
64− , parseArrayOf
65− , parseFunction
66− , parseObject
67− , parseTypeVariable
68− , parseTypeConstructor
69− , parseForAll
70− , parens (parseRow True)
71− , parens parsePolyType ])
72−
73−parseConstrainedType :: P.Parsec String ParseState Type
74−parseConstrainedType = do
75− constraints <- P.optionMaybe . P.try $ do
76− constraints <- parens . commaSep1 $ do
77− className <- parseQualified properName
78− indented
79− ty <- P.many parseTypeAtom
80− return (className, ty)
81− _ <- lexeme $ P.string "=>"
82− return constraints
83− indented
84− ty <- parseType
85− return $ maybe ty (flip ConstrainedType ty) constraints
86−
87−parseAnyType :: P.Parsec String ParseState Type
88−parseAnyType = P.buildExpressionParser operators parseTypeAtom P.<?> "type"
89− where
90− operators = [ [ P.Infix (return TypeApp) P.AssocLeft ]
91− , [ P.Infix (P.try (lexeme (P.string "->")) >> return function) P.AssocRight ] ]
92−
93−-- |
94−-- Parse a monotype
95−--
96−parseType :: P.Parsec String ParseState Type
97−parseType = do
98− ty <- parseAnyType
99− unless (isMonoType ty) $ P.unexpected "polymorphic type"
100− return ty
101−
102−-- |
103−-- Parse a polytype
104−--
105−parsePolyType :: P.Parsec String ParseState Type
106−parsePolyType = parseAnyType
107−
108−parseNameAndType :: P.Parsec String ParseState t -> P.Parsec String ParseState (String, t)
109−parseNameAndType p = (,) <$> (indented *> (identifier <|> stringLiteral) <* indented <* lexeme (P.string "::")) <*> p
110−
111−parseRowEnding :: P.Parsec String ParseState Type
112−parseRowEnding = P.option REmpty (TypeVar <$> (lexeme (indented *> P.char '|') *> indented *> identifier))
113−
114−parseRow :: Bool -> P.Parsec String ParseState Type
115−parseRow nonEmpty = (curry rowFromList <$> many' (parseNameAndType parsePolyType) <*> parseRowEnding) P.<?> "row"
116− where many' = if nonEmpty then commaSep1 else commaSep
src/Language/PureScript/Pretty.hsdeleted−32
@@ -1,32 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Pretty
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- A collection of pretty printers for core data types:
13−--
14−-- [@Language.PureScript.Pretty.Kinds@] Pretty printer for kinds
15−--
16−-- [@Language.PureScript.Pretty.Values@] Pretty printer for values
17−--
18−-- [@Language.PureScript.Pretty.Types@] Pretty printer for types
19−--
20−-- [@Language.PureScript.Pretty.JS@] Pretty printer for values, used for code generation
21−--
22−-----------------------------------------------------------------------------
23−
24−module Language.PureScript.Pretty (module P) where
25−
26−import Language.PureScript.Pretty.Kinds as P
27−import Language.PureScript.Pretty.Values as P
28−import Language.PureScript.Pretty.Types as P
29−import Language.PureScript.Pretty.JS as P
30−
31−
32−
src/Language/PureScript/Pretty/Common.hsdeleted−69
@@ -1,69 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Pretty.Common
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Common pretty-printing utility functions
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Pretty.Common where
17−
18−import Control.Monad.State
19−import Data.List (intercalate)
20−import Language.PureScript.Parser.Common (reservedPsNames, opChars)
21−
22−-- |
23−-- Wrap a string in parentheses
24−--
25−parens :: String -> String
26−parens s = ('(':s) ++ ")"
27−
28−newtype PrinterState = PrinterState { indent :: Int } deriving (Show, Eq, Ord)
29−
30−-- |
31−-- Number of characters per identation level
32−--
33−blockIndent :: Int
34−blockIndent = 4
35−
36−-- |
37−-- Pretty print with a new indentation level
38−--
39−withIndent :: StateT PrinterState Maybe String -> StateT PrinterState Maybe String
40−withIndent action = do
41− modify $ \st -> st { indent = indent st + blockIndent }
42− result <- action
43− modify $ \st -> st { indent = indent st - blockIndent }
44− return result
45−
46−-- |
47−-- Get the current indentation level
48−--
49−currentIndent :: StateT PrinterState Maybe String
50−currentIndent = do
51− current <- get
52− return $ replicate (indent current) ' '
53−
54−-- |
55−-- Print many lines
56−--
57−prettyPrintMany :: (a -> StateT PrinterState Maybe String) -> [a] -> StateT PrinterState Maybe String
58−prettyPrintMany f xs = do
59− ss <- mapM f xs
60− indentString <- currentIndent
61− return $ intercalate "\n" $ map (indentString ++) ss
62−
63−-- |
64−-- Prints an object key, escaping reserved names.
65−--
66−prettyPrintObjectKey :: String -> String
67−prettyPrintObjectKey s | s `elem` reservedPsNames = show s
68− | head s `elem` opChars = show s
69− | otherwise = s
src/Language/PureScript/Pretty/JS.hsdeleted−255
@@ -1,255 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Pretty.JS
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Pretty printer for the Javascript AST
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Pretty.JS (
17− prettyPrintJS
18−) where
19−
20−import Language.PureScript.Pretty.Common
21−import Language.PureScript.CodeGen.JS (isIdent)
22−import Language.PureScript.CodeGen.JS.AST
23−
24−import Data.List
25−import Data.Maybe (fromMaybe)
26−import qualified Control.Arrow as A
27−import Control.Arrow ((<+>))
28−import Control.PatternArrows
29−import Control.Applicative
30−import Control.Monad.State
31−import Numeric
32−
33−literals :: Pattern PrinterState JS String
34−literals = mkPattern' match
35− where
36− match :: JS -> StateT PrinterState Maybe String
37− match (JSNumericLiteral n) = return $ either show show n
38− match (JSStringLiteral s) = return $ string s
39− match (JSBooleanLiteral True) = return "true"
40− match (JSBooleanLiteral False) = return "false"
41− match (JSArrayLiteral xs) = fmap concat $ sequence
42− [ return "[ "
43− , fmap (intercalate ", ") $ forM xs prettyPrintJS'
44− , return " ]"
45− ]
46− match (JSObjectLiteral []) = return "{}"
47− match (JSObjectLiteral ps) = fmap concat $ sequence
48− [ return "{\n"
49− , withIndent $ do
50− jss <- forM ps $ \(key, value) -> fmap ((objectPropertyToString key ++ ": ") ++) . prettyPrintJS' $ value
51− indentString <- currentIndent
52− return $ intercalate ", \n" $ map (indentString ++) jss
53− , return "\n"
54− , currentIndent
55− , return "}"
56− ]
57− where
58− objectPropertyToString :: String -> String
59− objectPropertyToString s | isIdent s = s
60− | otherwise = show s
61− match (JSBlock sts) = fmap concat $ sequence
62− [ return "{\n"
63− , withIndent $ prettyStatements sts
64− , return "\n"
65− , currentIndent
66− , return "}"
67− ]
68− match (JSVar ident) = return ident
69− match (JSVariableIntroduction ident value) = fmap concat $ sequence
70− [ return "var "
71− , return ident
72− , maybe (return "") (fmap (" = " ++) . prettyPrintJS') value
73− ]
74− match (JSAssignment target value) = fmap concat $ sequence
75− [ prettyPrintJS' target
76− , return " = "
77− , prettyPrintJS' value
78− ]
79− match (JSWhile cond sts) = fmap concat $ sequence
80− [ return "while ("
81− , prettyPrintJS' cond
82− , return ") "
83− , prettyPrintJS' sts
84− ]
85− match (JSFor ident start end sts) = fmap concat $ sequence
86− [ return $ "for (var " ++ ident ++ " = "
87− , prettyPrintJS' start
88− , return $ "; " ++ ident ++ " < "
89− , prettyPrintJS' end
90− , return $ "; " ++ ident ++ "++) "
91− , prettyPrintJS' sts
92− ]
93− match (JSForIn ident obj sts) = fmap concat $ sequence
94− [ return $ "for (var " ++ ident ++ " in "
95− , prettyPrintJS' obj
96− , return ") "
97− , prettyPrintJS' sts
98− ]
99− match (JSIfElse cond thens elses) = fmap concat $ sequence
100− [ return "if ("
101− , prettyPrintJS' cond
102− , return ") "
103− , prettyPrintJS' thens
104− , maybe (return "") (fmap (" else " ++) . prettyPrintJS') elses
105− ]
106− match (JSReturn value) = fmap concat $ sequence
107− [ return "return "
108− , prettyPrintJS' value
109− ]
110− match (JSThrow value) = fmap concat $ sequence
111− [ return "throw "
112− , prettyPrintJS' value
113− ]
114− match (JSBreak lbl) = return $ "break " ++ lbl
115− match (JSContinue lbl) = return $ "continue " ++ lbl
116− match (JSLabel lbl js) = fmap concat $ sequence
117− [ return $ lbl ++ ": "
118− , prettyPrintJS' js
119− ]
120− match (JSRaw js) = return js
121− match _ = mzero
122−
123−string :: String -> String
124−string s = '"' : concatMap encodeChar s ++ "\""
125− where
126− encodeChar :: Char -> String
127− encodeChar '\b' = "\\b"
128− encodeChar '\t' = "\\t"
129− encodeChar '\n' = "\\n"
130− encodeChar '\v' = "\\v"
131− encodeChar '\f' = "\\f"
132− encodeChar '\r' = "\\r"
133− encodeChar '"' = "\\\""
134− encodeChar '\\' = "\\\\"
135− encodeChar c | fromEnum c > 0xFFF = "\\u" ++ showHex (fromEnum c) ""
136− encodeChar c | fromEnum c > 0xFF = "\\u0" ++ showHex (fromEnum c) ""
137− encodeChar c = [c]
138−
139−conditional :: Pattern PrinterState JS ((JS, JS), JS)
140−conditional = mkPattern match
141− where
142− match (JSConditional cond th el) = Just ((th, el), cond)
143− match _ = Nothing
144−
145−accessor :: Pattern PrinterState JS (String, JS)
146−accessor = mkPattern match
147− where
148− match (JSAccessor prop val) = Just (prop, val)
149− match _ = Nothing
150−
151−indexer :: Pattern PrinterState JS (String, JS)
152−indexer = mkPattern' match
153− where
154− match (JSIndexer index val) = (,) <$> prettyPrintJS' index <*> pure val
155− match _ = mzero
156−
157−lam :: Pattern PrinterState JS ((Maybe String, [String]), JS)
158−lam = mkPattern match
159− where
160− match (JSFunction name args ret) = Just ((name, args), ret)
161− match _ = Nothing
162−
163−app :: Pattern PrinterState JS (String, JS)
164−app = mkPattern' match
165− where
166− match (JSApp val args) = do
167− jss <- mapM prettyPrintJS' args
168− return (intercalate ", " jss, val)
169− match _ = mzero
170−
171−typeOf :: Pattern PrinterState JS ((), JS)
172−typeOf = mkPattern match
173− where
174− match (JSTypeOf val) = Just ((), val)
175− match _ = Nothing
176−
177−unary :: UnaryOperator -> String -> Operator PrinterState JS String
178−unary op str = Wrap match (++)
179− where
180− match :: Pattern PrinterState JS (String, JS)
181− match = mkPattern match'
182− where
183− match' (JSUnary op' val) | op' == op = Just (str, val)
184− match' _ = Nothing
185−
186−binary :: BinaryOperator -> String -> Operator PrinterState JS String
187−binary op str = AssocR match (\v1 v2 -> v1 ++ " " ++ str ++ " " ++ v2)
188− where
189− match :: Pattern PrinterState JS (JS, JS)
190− match = mkPattern match'
191− where
192− match' (JSBinary op' v1 v2) | op' == op = Just (v1, v2)
193− match' _ = Nothing
194−
195−prettyStatements :: [JS] -> StateT PrinterState Maybe String
196−prettyStatements sts = do
197− jss <- forM sts prettyPrintJS'
198− indentString <- currentIndent
199− return $ intercalate "\n" $ map ((++ ";") . (indentString ++)) jss
200−
201−-- |
202−-- Generate a pretty-printed string representing a Javascript expression
203−--
204−prettyPrintJS1 :: JS -> String
205−prettyPrintJS1 = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyPrintJS'
206−
207−-- |
208−-- Generate a pretty-printed string representing a collection of Javascript expressions at the same indentation level
209−--
210−prettyPrintJS :: [JS] -> String
211−prettyPrintJS = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyStatements
212−
213−-- |
214−-- Generate an indented, pretty-printed string representing a Javascript expression
215−--
216−prettyPrintJS' :: JS -> StateT PrinterState Maybe String
217−prettyPrintJS' = A.runKleisli $ runPattern matchValue
218− where
219− matchValue :: Pattern PrinterState JS String
220− matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
221− operators :: OperatorTable PrinterState JS String
222− operators =
223− OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "." ++ prop ]
224− , [ Wrap indexer $ \index val -> val ++ "[" ++ index ++ "]" ]
225− , [ Wrap app $ \args val -> val ++ "(" ++ args ++ ")" ]
226− , [ Wrap lam $ \(name, args) ret -> "function "
227− ++ fromMaybe "" name
228− ++ "(" ++ intercalate ", " args ++ ") "
229− ++ ret ]
230− , [ binary LessThan "<" ]
231− , [ binary LessThanOrEqualTo "<=" ]
232− , [ binary GreaterThan ">" ]
233− , [ binary GreaterThanOrEqualTo ">=" ]
234− , [ Wrap typeOf $ \_ s -> "typeof " ++ s ]
235− , [ unary Not "!" ]
236− , [ unary BitwiseNot "~" ]
237− , [ unary Negate "-" ]
238− , [ unary Positive "+" ]
239− , [ binary Multiply "*" ]
240− , [ binary Divide "/" ]
241− , [ binary Modulus "%" ]
242− , [ binary Add "+" ]
243− , [ binary Subtract "-" ]
244− , [ binary ShiftLeft "<<" ]
245− , [ binary ShiftRight ">>" ]
246− , [ binary ZeroFillShiftRight ">>>" ]
247− , [ binary EqualTo "===" ]
248− , [ binary NotEqualTo "!==" ]
249− , [ binary BitwiseAnd "&" ]
250− , [ binary BitwiseXor "^" ]
251− , [ binary BitwiseOr "|" ]
252− , [ binary And "&&" ]
253− , [ binary Or "||" ]
254− , [ Wrap conditional $ \(th, el) cond -> cond ++ " ? " ++ prettyPrintJS1 th ++ " : " ++ prettyPrintJS1 el ]
255− ]
src/Language/PureScript/Pretty/Kinds.hsdeleted−59
@@ -1,59 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Pretty.Kinds
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Pretty printer for kinds
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Pretty.Kinds (
17− prettyPrintKind
18−) where
19−
20−import Data.Maybe (fromMaybe)
21−
22−import Control.Arrow (ArrowPlus(..))
23−import Control.PatternArrows
24−
25−import Language.PureScript.Kinds
26−import Language.PureScript.Pretty.Common
27−
28−typeLiterals :: Pattern () Kind String
29−typeLiterals = mkPattern match
30− where
31− match Star = Just "*"
32− match Bang = Just "!"
33− match (KUnknown u) = Just $ 'u' : show u
34− match _ = Nothing
35−
36−matchRow :: Pattern () Kind ((), Kind)
37−matchRow = mkPattern match
38− where
39− match (Row k) = Just ((), k)
40− match _ = Nothing
41−
42−funKind :: Pattern () Kind (Kind, Kind)
43−funKind = mkPattern match
44− where
45− match (FunKind arg ret) = Just (arg, ret)
46− match _ = Nothing
47−
48−-- |
49−-- Generate a pretty-printed string representing a Kind
50−--
51−prettyPrintKind :: Kind -> String
52−prettyPrintKind = fromMaybe (error "Incomplete pattern") . pattern matchKind ()
53− where
54− matchKind :: Pattern () Kind String
55− matchKind = buildPrettyPrinter operators (typeLiterals <+> fmap parens matchKind)
56− operators :: OperatorTable () Kind String
57− operators =
58− OperatorTable [ [ Wrap matchRow $ \_ k -> "# " ++ k]
59− , [ AssocR funKind $ \arg ret -> arg ++ " -> " ++ ret ] ]
src/Language/PureScript/Pretty/Types.hsdeleted−119
@@ -1,119 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Pretty.Types
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Pretty printer for Types
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Pretty.Types (
17− prettyPrintType,
18− prettyPrintTypeAtom,
19− prettyPrintRow
20−) where
21−
22−import Data.Maybe (fromMaybe)
23−import Data.List (intercalate)
24−
25−import Control.Arrow ((<+>))
26−import Control.PatternArrows
27−
28−import Language.PureScript.Types
29−import Language.PureScript.Pretty.Common
30−import Language.PureScript.Environment
31−
32−typeLiterals :: Pattern () Type String
33−typeLiterals = mkPattern match
34− where
35− match (TypeVar var) = Just var
36− match (PrettyPrintObject row) = Just $ "{ " ++ prettyPrintRow row ++ " }"
37− match (PrettyPrintArray ty) = Just $ "[" ++ prettyPrintType ty ++ "]"
38− match (TypeConstructor ctor) = Just $ show ctor
39− match (TUnknown u) = Just $ 'u' : show u
40− match (Skolem name s _) = Just $ name ++ show s
41− match (ConstrainedType deps ty) = Just $ "(" ++ intercalate ", " (map (\(pn, ty') -> show pn ++ " " ++ unwords (map prettyPrintTypeAtom ty')) deps) ++ ") => " ++ prettyPrintType ty
42− match (SaturatedTypeSynonym name args) = Just $ show name ++ "<" ++ intercalate "," (map prettyPrintTypeAtom args) ++ ">"
43− match REmpty = Just "()"
44− match row@RCons{} = Just $ '(' : prettyPrintRow row ++ ")"
45− match _ = Nothing
46−
47−-- |
48−-- Generate a pretty-printed string representing a Row
49−--
50−prettyPrintRow :: Type -> String
51−prettyPrintRow = (\(tys, rest) -> intercalate ", " (map (uncurry nameAndTypeToPs) tys) ++ tailToPs rest) . toList []
52− where
53− nameAndTypeToPs :: String -> Type -> String
54− nameAndTypeToPs name ty = prettyPrintObjectKey name ++ " :: " ++ prettyPrintType ty
55− tailToPs :: Type -> String
56− tailToPs REmpty = ""
57− tailToPs other = " | " ++ prettyPrintType other
58− toList :: [(String, Type)] -> Type -> ([(String, Type)], Type)
59− toList tys (RCons name ty row) = toList ((name, ty):tys) row
60− toList tys r = (tys, r)
61−
62−typeApp :: Pattern () Type (Type, Type)
63−typeApp = mkPattern match
64− where
65− match (TypeApp f x) = Just (f, x)
66− match _ = Nothing
67−
68−appliedFunction :: Pattern () Type (Type, Type)
69−appliedFunction = mkPattern match
70− where
71− match (PrettyPrintFunction arg ret) = Just (arg, ret)
72− match _ = Nothing
73−
74−insertPlaceholders :: Type -> Type
75−insertPlaceholders = everywhereOnTypesTopDown convertForAlls . everywhereOnTypes convert
76− where
77− convert (TypeApp (TypeApp f arg) ret) | f == tyFunction = PrettyPrintFunction arg ret
78− convert (TypeApp a el) | a == tyArray = PrettyPrintArray el
79− convert (TypeApp o r) | o == tyObject = PrettyPrintObject r
80− convert other = other
81− convertForAlls (ForAll ident ty _) = go [ident] ty
82− where
83− go idents (ForAll ident' ty' _) = go (ident' : idents) ty'
84− go idents other = PrettyPrintForAll idents other
85− convertForAlls other = other
86−
87−matchTypeAtom :: Pattern () Type String
88−matchTypeAtom = typeLiterals <+> fmap parens matchType
89−
90−matchType :: Pattern () Type String
91−matchType = buildPrettyPrinter operators matchTypeAtom
92− where
93− operators :: OperatorTable () Type String
94− operators =
95− OperatorTable [ [ AssocL typeApp $ \f x -> f ++ " " ++ x ]
96− , [ AssocR appliedFunction $ \arg ret -> arg ++ " -> " ++ ret
97− ]
98− , [ Wrap forall_ $ \idents ty -> "forall " ++ unwords idents ++ ". " ++ ty ]
99− ]
100−
101−forall_ :: Pattern () Type ([String], Type)
102−forall_ = mkPattern match
103− where
104− match (PrettyPrintForAll idents ty) = Just (idents, ty)
105− match _ = Nothing
106−
107−-- |
108−-- Generate a pretty-printed string representing a Type, as it should appear inside parentheses
109−--
110−prettyPrintTypeAtom :: Type -> String
111−prettyPrintTypeAtom = fromMaybe (error "Incomplete pattern") . pattern matchTypeAtom () . insertPlaceholders
112−
113−
114−-- |
115−-- Generate a pretty-printed string representing a Type
116−--
117−prettyPrintType :: Type -> String
118−prettyPrintType = fromMaybe (error "Incomplete pattern") . pattern matchType () . insertPlaceholders
119−
src/Language/PureScript/Pretty/Values.hsdeleted−226
@@ -1,226 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Pretty.Values
4−-- Copyright : Kinds.hs(c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Pretty printer for values
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Pretty.Values (
17− prettyPrintValue,
18− prettyPrintBinder
19−) where
20−
21−import Data.Maybe (fromMaybe)
22−import Data.List (intercalate)
23−
24−import Control.Arrow ((<+>), runKleisli)
25−import Control.PatternArrows
26−import Control.Monad.State
27−import Control.Applicative
28−
29−import Language.PureScript.Declarations
30−import Language.PureScript.Pretty.Common
31−import Language.PureScript.Pretty.Types (prettyPrintType)
32−
33−literals :: Pattern PrinterState Value String
34−literals = mkPattern' match
35− where
36− match :: Value -> StateT PrinterState Maybe String
37− match (NumericLiteral n) = return $ either show show n
38− match (StringLiteral s) = return $ show s
39− match (BooleanLiteral True) = return "true"
40− match (BooleanLiteral False) = return "false"
41− match (ArrayLiteral xs) = fmap concat $ sequence
42− [ return "[ "
43− , withIndent $ prettyPrintMany prettyPrintValue' xs
44− , return " ]"
45− ]
46− match (ObjectLiteral []) = return "{}"
47− match (ObjectLiteral ps) = fmap concat $ sequence
48− [ return "{\n"
49− , withIndent $ prettyPrintMany prettyPrintObjectProperty ps
50− , return "\n"
51− , currentIndent
52− , return "}"
53− ]
54− match (Constructor name) = return $ show name
55− match (Case values binders) = fmap concat $ sequence
56− [ return "case "
57− , unwords <$> forM values prettyPrintValue'
58− , return " of\n"
59− , withIndent $ prettyPrintMany prettyPrintCaseAlternative binders
60− , currentIndent
61− ]
62− match (Let ds val) = fmap concat $ sequence
63− [ return "let\n"
64− , withIndent $ prettyPrintMany prettyPrintDeclaration ds
65− , return "\n"
66− , currentIndent
67− , return "in "
68− , prettyPrintValue' val
69− ]
70− match (Var ident) = return $ show ident
71− match (Do els) = fmap concat $ sequence
72− [ return "do "
73− , withIndent $ prettyPrintMany prettyPrintDoNotationElement els
74− , currentIndent
75− ]
76− match (TypeClassDictionary _ _ _) = return "<<dict>>"
77− match (SuperClassDictionary _ _) = return "<<superclass dict>>"
78− match (TypedValue _ val _) = prettyPrintValue' val
79− match (PositionedValue _ val) = prettyPrintValue' val
80− match _ = mzero
81−
82−prettyPrintDeclaration :: Declaration -> StateT PrinterState Maybe String
83−prettyPrintDeclaration (TypeDeclaration ident ty) = return $ show ident ++ " :: " ++ prettyPrintType ty
84−prettyPrintDeclaration (ValueDeclaration ident _ [] Nothing val) = fmap concat $ sequence
85− [ return $ show ident ++ " = "
86− , prettyPrintValue' val
87− ]
88−prettyPrintDeclaration (PositionedDeclaration _ d) = prettyPrintDeclaration d
89−prettyPrintDeclaration _ = error "Invalid argument to prettyPrintDeclaration"
90−
91−prettyPrintCaseAlternative :: CaseAlternative -> StateT PrinterState Maybe String
92−prettyPrintCaseAlternative (CaseAlternative binders grd val) =
93− fmap concat $ sequence
94− [ intercalate ", " <$> forM binders prettyPrintBinder'
95− , maybe (return "") (fmap ("| " ++) . prettyPrintValue') grd
96− , return " -> "
97− , prettyPrintValue' val
98− ]
99−
100−prettyPrintDoNotationElement :: DoNotationElement -> StateT PrinterState Maybe String
101−prettyPrintDoNotationElement (DoNotationValue val) =
102− prettyPrintValue' val
103−prettyPrintDoNotationElement (DoNotationBind binder val) =
104− fmap concat $ sequence
105− [ prettyPrintBinder' binder
106− , return " <- "
107− , prettyPrintValue' val
108− ]
109−prettyPrintDoNotationElement (DoNotationLet ds) =
110− fmap concat $ sequence
111− [ return "let "
112− , withIndent $ prettyPrintMany prettyPrintDeclaration ds
113− ]
114−prettyPrintDoNotationElement (PositionedDoNotationElement _ el) = prettyPrintDoNotationElement el
115−
116−ifThenElse :: Pattern PrinterState Value ((Value, Value), Value)
117−ifThenElse = mkPattern match
118− where
119− match (IfThenElse cond th el) = Just ((th, el), cond)
120− match _ = Nothing
121−
122−accessor :: Pattern PrinterState Value (String, Value)
123−accessor = mkPattern match
124− where
125− match (Accessor prop val) = Just (prop, val)
126− match _ = Nothing
127−
128−objectUpdate :: Pattern PrinterState Value ([String], Value)
129−objectUpdate = mkPattern match
130− where
131− match (ObjectUpdate o ps) = Just (flip map ps $ \(key, val) -> key ++ " = " ++ prettyPrintValue val, o)
132− match _ = Nothing
133−
134−app :: Pattern PrinterState Value (String, Value)
135−app = mkPattern match
136− where
137− match (App val arg) = Just (prettyPrintValue arg, val)
138− match _ = Nothing
139−
140−lam :: Pattern PrinterState Value (String, Value)
141−lam = mkPattern match
142− where
143− match (Abs (Left arg) val) = Just (show arg, val)
144− match _ = Nothing
145−
146−-- |
147−-- Generate a pretty-printed string representing an expression
148−--
149−prettyPrintValue :: Value -> String
150−prettyPrintValue = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyPrintValue'
151−
152−prettyPrintValue' :: Value -> StateT PrinterState Maybe String
153−prettyPrintValue' = runKleisli $ runPattern matchValue
154− where
155− matchValue :: Pattern PrinterState Value String
156− matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
157− operators :: OperatorTable PrinterState Value String
158− operators =
159− OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "." ++ prop ]
160− , [ Wrap objectUpdate $ \ps val -> val ++ "{ " ++ intercalate ", " ps ++ " }" ]
161− , [ Wrap app $ \arg val -> val ++ "(" ++ arg ++ ")" ]
162− , [ Split lam $ \arg val -> "\\" ++ arg ++ " -> " ++ prettyPrintValue val ]
163− , [ Wrap ifThenElse $ \(th, el) cond -> "if " ++ cond ++ " then " ++ prettyPrintValue th ++ " else " ++ prettyPrintValue el ]
164− ]
165−
166−prettyPrintBinderAtom :: Pattern PrinterState Binder String
167−prettyPrintBinderAtom = mkPattern' match
168− where
169− match :: Binder -> StateT PrinterState Maybe String
170− match NullBinder = return "_"
171− match (StringBinder str) = return $ show str
172− match (NumberBinder num) = return $ either show show num
173− match (BooleanBinder True) = return "true"
174− match (BooleanBinder False) = return "false"
175− match (VarBinder ident) = return $ show ident
176− match (ConstructorBinder ctor args) = fmap concat $ sequence
177− [ return $ show ctor ++ " "
178− , unwords <$> forM args match
179− ]
180− match (ObjectBinder bs) = fmap concat $ sequence
181− [ return "{\n"
182− , withIndent $ prettyPrintMany prettyPrintObjectPropertyBinder bs
183− , currentIndent
184− , return "}"
185− ]
186− match (ArrayBinder bs) = fmap concat $ sequence
187− [ return "["
188− , unwords <$> mapM prettyPrintBinder' bs
189− , return "]"
190− ]
191− match (NamedBinder ident binder) = ((show ident ++ "@") ++) <$> prettyPrintBinder' binder
192− match (PositionedBinder _ binder) = prettyPrintBinder' binder
193− match _ = mzero
194−
195−-- |
196−-- Generate a pretty-printed string representing a Binder
197−--
198−prettyPrintBinder :: Binder -> String
199−prettyPrintBinder = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyPrintBinder'
200−
201−prettyPrintBinder' :: Binder -> StateT PrinterState Maybe String
202−prettyPrintBinder' = runKleisli $ runPattern matchBinder
203− where
204− matchBinder :: Pattern PrinterState Binder String
205− matchBinder = buildPrettyPrinter operators (prettyPrintBinderAtom <+> fmap parens matchBinder)
206− operators :: OperatorTable PrinterState Binder String
207− operators =
208− OperatorTable [ [ AssocR matchConsBinder (\b1 b2 -> b1 ++ " : " ++ b2) ] ]
209−
210−matchConsBinder :: Pattern PrinterState Binder (Binder, Binder)
211−matchConsBinder = mkPattern match'
212− where
213− match' (ConsBinder b1 b2) = Just (b1, b2)
214− match' _ = Nothing
215−
216−prettyPrintObjectPropertyBinder :: (String, Binder) -> StateT PrinterState Maybe String
217−prettyPrintObjectPropertyBinder (key, binder) = fmap concat $ sequence
218− [ return $ prettyPrintObjectKey key ++ ": "
219− , prettyPrintBinder' binder
220− ]
221−
222−prettyPrintObjectProperty :: (String, Value) -> StateT PrinterState Maybe String
223−prettyPrintObjectProperty (key, value) = fmap concat $ sequence
224− [ return $ prettyPrintObjectKey key ++ ": "
225− , prettyPrintValue' value
226− ]
src/Language/PureScript/Sugar.hsdeleted−59
@@ -1,59 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Sugar
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Desugaring passes
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Sugar (desugar, module S) where
17−
18−import Control.Monad
19−import Control.Category ((>>>))
20−import Control.Monad.Trans.Class
21−
22−import Language.PureScript.Declarations
23−import Language.PureScript.Errors
24−import Language.PureScript.Supply
25−
26−import Language.PureScript.Sugar.Operators as S
27−import Language.PureScript.Sugar.DoNotation as S
28−import Language.PureScript.Sugar.CaseDeclarations as S
29−import Language.PureScript.Sugar.TypeDeclarations as S
30−import Language.PureScript.Sugar.BindingGroups as S
31−import Language.PureScript.Sugar.TypeClasses as S
32−import Language.PureScript.Sugar.Names as S
33−
34−-- |
35−-- The desugaring pipeline proceeds as follows:
36−--
37−-- * Introduce type synonyms for type class dictionaries
38−--
39−-- * Rebracket user-defined binary operators
40−--
41−-- * Desugar do-notation using the @Prelude.Monad@ type class
42−--
43−-- * Desugar top-level case declarations into explicit case expressions
44−--
45−-- * Desugar type declarations into value declarations with explicit type annotations
46−--
47−-- * Group mutually recursive value and data declarations into binding groups.
48−--
49−-- * Qualify any unqualified names and types
50−--
51−desugar :: [Module] -> SupplyT (Either ErrorStack) [Module]
52−desugar = map removeSignedLiterals
53− >>> mapM desugarDoModule
54− >=> desugarCasesModule
55− >=> lift . (desugarTypeDeclarationsModule
56− >=> desugarImports
57− >=> rebracket)
58− >=> desugarTypeClasses
59− >=> lift . createBindingGroupsModule
src/Language/PureScript/Sugar/BindingGroups.hsdeleted−149
@@ -1,149 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.BindingGroups
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the desugaring pass which creates binding groups from sets of
13−-- mutually-recursive value declarations and mutually-recursive type declarations.
14−--
15−-----------------------------------------------------------------------------
16−
17−module Language.PureScript.Sugar.BindingGroups (
18− createBindingGroups,
19− createBindingGroupsModule,
20− collapseBindingGroups,
21− collapseBindingGroupsModule
22−) where
23−
24−import Data.Graph
25−import Data.List (nub, intersect)
26−import Data.Maybe (isJust, mapMaybe)
27−import Control.Applicative ((<$>), (<*>), pure)
28−
29−import Language.PureScript.Declarations
30−import Language.PureScript.Names
31−import Language.PureScript.Types
32−import Language.PureScript.Environment
33−import Language.PureScript.Errors
34−
35−-- |
36−-- Replace all sets of mutually-recursive declarations in a module with binding groups
37−--
38−createBindingGroupsModule :: [Module] -> Either ErrorStack [Module]
39−createBindingGroupsModule = mapM $ \(Module name ds exps) -> Module name <$> createBindingGroups name ds <*> pure exps
40−
41−-- |
42−-- Collapse all binding groups in a module to individual declarations
43−--
44−collapseBindingGroupsModule :: [Module] -> [Module]
45−collapseBindingGroupsModule = map $ \(Module name ds exps) -> Module name (collapseBindingGroups ds) exps
46−
47−-- |
48−-- Replace all sets of mutually-recursive declarations with binding groups
49−--
50−createBindingGroups :: ModuleName -> [Declaration] -> Either ErrorStack [Declaration]
51−createBindingGroups moduleName ds = do
52− values <- mapM (createBindingGroupsForValue moduleName) $ filter isValueDecl ds
53− let dataDecls = filter isDataDecl ds
54− allProperNames = map getProperName dataDecls
55− dataVerts = map (\d -> (d, getProperName d, usedProperNames moduleName d `intersect` allProperNames)) dataDecls
56− dataBindingGroupDecls <- mapM toDataBindingGroup $ stronglyConnComp dataVerts
57− let allIdents = map getIdent values
58− valueVerts = map (\d -> (d, getIdent d, usedIdents moduleName d `intersect` allIdents)) values
59− bindingGroupDecls = map toBindingGroup $ stronglyConnComp valueVerts
60− return $ filter isImportDecl ds ++
61− filter isExternDataDecl ds ++
62− filter isExternInstanceDecl ds ++
63− dataBindingGroupDecls ++
64− filter isTypeClassDeclaration ds ++
65− filter isFixityDecl ds ++
66− filter isExternDecl ds ++
67− bindingGroupDecls
68−
69−createBindingGroupsForValue :: ModuleName -> Declaration -> Either ErrorStack Declaration
70−createBindingGroupsForValue moduleName =
71− let (f, _, _) = everywhereOnValuesTopDownM return go return
72− in f
73− where
74− go (Let ds val) = Let <$> createBindingGroups moduleName ds <*> pure val
75− go other = return other
76−
77−-- |
78−-- Collapse all binding groups to individual declarations
79−--
80−collapseBindingGroups :: [Declaration] -> [Declaration]
81−collapseBindingGroups = let (f, _, _) = everywhereOnValues id collapseBindingGroupsForValue id in map f . concatMap go
82− where
83− go (DataBindingGroupDeclaration ds) = ds
84− go (BindingGroupDeclaration ds) = map (\(ident, nameKind, val) -> ValueDeclaration ident nameKind [] Nothing val) ds
85− go (PositionedDeclaration pos d) = map (PositionedDeclaration pos) $ go d
86− go other = [other]
87−
88−collapseBindingGroupsForValue :: Value -> Value
89−collapseBindingGroupsForValue (Let ds val) = Let (collapseBindingGroups ds) val
90−collapseBindingGroupsForValue other = other
91−
92−usedIdents :: ModuleName -> Declaration -> [Ident]
93−usedIdents moduleName =
94− let (f, _, _, _, _) = everythingOnValues (++) (const []) usedNames (const []) (const []) (const [])
95− in nub . f
96− where
97− usedNames :: Value -> [Ident]
98− usedNames (Var (Qualified Nothing name)) = [name]
99− usedNames (Var (Qualified (Just moduleName') name)) | moduleName == moduleName' = [name]
100− usedNames _ = []
101−
102−usedProperNames :: ModuleName -> Declaration -> [ProperName]
103−usedProperNames moduleName =
104− let (f, _, _, _, _) = accumTypes (everythingOnTypes (++) usedNames)
105− in nub . f
106− where
107− usedNames :: Type -> [ProperName]
108− usedNames (ConstrainedType constraints _) = flip mapMaybe constraints $ \qual ->
109− case qual of
110− (Qualified (Just moduleName') name, _) | moduleName == moduleName' -> Just name
111− _ -> Nothing
112− usedNames (TypeConstructor (Qualified (Just moduleName') name)) | moduleName == moduleName' = [name]
113− usedNames _ = []
114−
115−getIdent :: Declaration -> Ident
116−getIdent (ValueDeclaration ident _ _ _ _) = ident
117−getIdent (PositionedDeclaration _ d) = getIdent d
118−getIdent _ = error "Expected ValueDeclaration"
119−
120−getProperName :: Declaration -> ProperName
121−getProperName (DataDeclaration pn _ _) = pn
122−getProperName (TypeSynonymDeclaration pn _ _) = pn
123−getProperName (PositionedDeclaration _ d) = getProperName d
124−getProperName _ = error "Expected DataDeclaration"
125−
126−toBindingGroup :: SCC Declaration -> Declaration
127−toBindingGroup (AcyclicSCC d) = d
128−toBindingGroup (CyclicSCC [d]) = d
129−toBindingGroup (CyclicSCC ds') = BindingGroupDeclaration $ map fromValueDecl ds'
130−
131−toDataBindingGroup :: SCC Declaration -> Either ErrorStack Declaration
132−toDataBindingGroup (AcyclicSCC d) = return d
133−toDataBindingGroup (CyclicSCC [d]) = case isTypeSynonym d of
134− Just pn -> Left $ mkErrorStack ("Cycle in type synonym " ++ show pn) Nothing
135− _ -> return d
136−toDataBindingGroup (CyclicSCC ds')
137− | all (isJust . isTypeSynonym) ds' = Left $ mkErrorStack "Cycle in type synonyms" Nothing
138− | otherwise = return $ DataBindingGroupDeclaration ds'
139−
140−isTypeSynonym :: Declaration -> Maybe ProperName
141−isTypeSynonym (TypeSynonymDeclaration pn _ _) = Just pn
142−isTypeSynonym (PositionedDeclaration _ d) = isTypeSynonym d
143−isTypeSynonym _ = Nothing
144−
145−fromValueDecl :: Declaration -> (Ident, NameKind, Value)
146−fromValueDecl (ValueDeclaration ident nameKind [] Nothing val) = (ident, nameKind, val)
147−fromValueDecl ValueDeclaration{} = error "Binders should have been desugared"
148−fromValueDecl (PositionedDeclaration _ d) = fromValueDecl d
149−fromValueDecl _ = error "Expected ValueDeclaration"
src/Language/PureScript/Sugar/CaseDeclarations.hsdeleted−115
@@ -1,115 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.CaseDeclarations
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the desugaring pass which replaces top-level binders with
13−-- case expressions.
14−--
15−-----------------------------------------------------------------------------
16−
17−module Language.PureScript.Sugar.CaseDeclarations (
18− desugarCases,
19− desugarCasesModule
20−) where
21−
22−import Data.Monoid ((<>))
23−import Data.List (groupBy)
24−
25−import Control.Applicative
26−import Control.Monad ((<=<), forM, join, unless, replicateM)
27−import Control.Monad.Error.Class
28−
29−import Language.PureScript.Names
30−import Language.PureScript.Declarations
31−import Language.PureScript.Environment
32−import Language.PureScript.Errors
33−import Language.PureScript.Supply
34−
35−-- |
36−-- Replace all top-level binders in a module with case expressions.
37−--
38−desugarCasesModule :: [Module] -> SupplyT (Either ErrorStack) [Module]
39−desugarCasesModule ms = forM ms $ \(Module name ds exps) ->
40− rethrow (strMsg ("Error in module " ++ show name) <>) $
41− Module name <$> (desugarCases <=< desugarAbs $ ds) <*> pure exps
42−
43−desugarAbs :: [Declaration] -> SupplyT (Either ErrorStack) [Declaration]
44−desugarAbs = mapM f
45− where
46− (f, _, _) = everywhereOnValuesM return replace return
47−
48− replace :: Value -> SupplyT (Either ErrorStack) Value
49− replace (Abs (Right binder) val) = do
50− ident <- Ident <$> freshName
51− return $ Abs (Left ident) $ Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] Nothing val]
52− replace other = return other
53−
54−-- |
55−-- Replace all top-level binders with case expressions.
56−--
57−desugarCases :: [Declaration] -> SupplyT (Either ErrorStack) [Declaration]
58−desugarCases = desugarRest <=< fmap join . mapM toDecls . groupBy inSameGroup
59− where
60− desugarRest :: [Declaration] -> SupplyT (Either ErrorStack) [Declaration]
61− desugarRest (TypeInstanceDeclaration name constraints className tys ds : rest) =
62− (:) <$> (TypeInstanceDeclaration name constraints className tys <$> desugarCases ds) <*> desugarRest rest
63− desugarRest (ValueDeclaration name nameKind bs g val : rest) =
64− let (_, f, _) = everywhereOnValuesTopDownM return go return
65− in (:) <$> (ValueDeclaration name nameKind bs g <$> f val) <*> desugarRest rest
66− where
67− go (Let ds val') = Let <$> desugarCases ds <*> pure val'
68− go other = return other
69− desugarRest (PositionedDeclaration pos d : ds) = do
70− (d' : ds') <- desugarRest (d : ds)
71− return (PositionedDeclaration pos d' : ds')
72− desugarRest (d : ds) = (:) d <$> desugarRest ds
73− desugarRest [] = pure []
74−
75−inSameGroup :: Declaration -> Declaration -> Bool
76−inSameGroup (ValueDeclaration ident1 _ _ _ _) (ValueDeclaration ident2 _ _ _ _) = ident1 == ident2
77−inSameGroup (PositionedDeclaration _ d1) d2 = inSameGroup d1 d2
78−inSameGroup d1 (PositionedDeclaration _ d2) = inSameGroup d1 d2
79−inSameGroup _ _ = False
80−
81−toDecls :: [Declaration] -> SupplyT (Either ErrorStack) [Declaration]
82−toDecls [ValueDeclaration ident nameKind bs Nothing val] | all isVarBinder bs = do
83− let args = map (\(VarBinder arg) -> arg) bs
84− body = foldr (Abs . Left) val args
85− return [ValueDeclaration ident nameKind [] Nothing body]
86−toDecls ds@(ValueDeclaration ident _ bs _ _ : _) = do
87− let tuples = map toTuple ds
88− unless (all ((== length bs) . length . fst) tuples) $
89− throwError $ mkErrorStack ("Argument list lengths differ in declaration " ++ show ident) Nothing
90− caseDecl <- makeCaseDeclaration ident tuples
91− return [caseDecl]
92−toDecls (PositionedDeclaration pos d : ds) = do
93− (d' : ds') <- rethrowWithPosition pos $ toDecls (d : ds)
94− return (PositionedDeclaration pos d' : ds')
95−toDecls ds = return ds
96−
97−isVarBinder :: Binder -> Bool
98−isVarBinder (VarBinder _) = True
99−isVarBinder _ = False
100−
101−toTuple :: Declaration -> ([Binder], (Maybe Guard, Value))
102−toTuple (ValueDeclaration _ _ bs g val) = (bs, (g, val))
103−toTuple (PositionedDeclaration _ d) = toTuple d
104−toTuple _ = error "Not a value declaration"
105−
106−makeCaseDeclaration :: Ident -> [([Binder], (Maybe Guard, Value))] -> SupplyT (Either ErrorStack) Declaration
107−makeCaseDeclaration ident alternatives = do
108− let argPattern = length . fst . head $ alternatives
109− args <- map Ident <$> replicateM argPattern freshName
110− let
111− vars = map (Var . Qualified Nothing) args
112− binders = [ CaseAlternative bs g val | (bs, (g, val)) <- alternatives ]
113− value = foldr (Abs . Left) (Case vars binders) args
114− return $ ValueDeclaration ident Value [] Nothing value
115−
src/Language/PureScript/Sugar/DoNotation.hsdeleted−74
@@ -1,74 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Sugar.DoNotation
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the desugaring pass which replaces do-notation statements with
13−-- appropriate calls to (>>=) from the Prelude.Monad type class.
14−--
15−-----------------------------------------------------------------------------
16−
17−module Language.PureScript.Sugar.DoNotation (
18− desugarDoModule
19−) where
20−
21−import Language.PureScript.Names
22−import Language.PureScript.Declarations
23−import Language.PureScript.Errors
24−import Language.PureScript.Supply
25−
26−import qualified Language.PureScript.Constants as C
27−
28−import Control.Applicative
29−import Control.Monad.Trans.Class
30−
31−-- |
32−-- Replace all @DoNotationBind@ and @DoNotationValue@ constructors with applications of the Prelude.(>>=) function,
33−-- and all @DoNotationLet@ constructors with let expressions.
34−--
35−desugarDoModule :: Module -> SupplyT (Either ErrorStack) Module
36−desugarDoModule (Module mn ds exts) = Module mn <$> mapM desugarDo ds <*> pure exts
37−
38−desugarDo :: Declaration -> SupplyT (Either ErrorStack) Declaration
39−desugarDo (PositionedDeclaration pos d) = (PositionedDeclaration pos) <$> (rethrowWithPosition pos $ desugarDo d)
40−desugarDo d =
41− let (f, _, _) = everywhereOnValuesM return replace return
42− in f d
43− where
44− prelude :: ModuleName
45− prelude = ModuleName [ProperName C.prelude]
46−
47− bind :: Value
48− bind = Var (Qualified (Just prelude) (Op (C.>>=)))
49−
50− replace :: Value -> SupplyT (Either ErrorStack) Value
51− replace (Do els) = go els
52− replace (PositionedValue pos v) = PositionedValue pos <$> rethrowWithPosition pos (replace v)
53− replace other = return other
54−
55− go :: [DoNotationElement] -> SupplyT (Either ErrorStack) Value
56− go [] = error "The impossible happened in desugarDo"
57− go [DoNotationValue val] = return val
58− go (DoNotationValue val : rest) = do
59− rest' <- go rest
60− return $ App (App bind val) (Abs (Left (Ident "_")) rest')
61− go [DoNotationBind _ _] = lift $ Left $ mkErrorStack "Bind statement cannot be the last statement in a do block" Nothing
62− go (DoNotationBind NullBinder val : rest) = go (DoNotationValue val : rest)
63− go (DoNotationBind (VarBinder ident) val : rest) = do
64− rest' <- go rest
65− return $ App (App bind val) (Abs (Left ident) rest')
66− go (DoNotationBind binder val : rest) = do
67− rest' <- go rest
68− ident <- Ident <$> freshName
69− return $ App (App bind val) (Abs (Left ident) (Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] Nothing rest']))
70− go [DoNotationLet _] = lift $ Left $ mkErrorStack "Let statement cannot be the last statement in a do block" Nothing
71− go (DoNotationLet ds : rest) = do
72− rest' <- go rest
73− return $ Let ds rest'
74− go (PositionedDoNotationElement pos el : rest) = rethrowWithPosition pos $ PositionedValue pos <$> go (el : rest)
src/Language/PureScript/Sugar/Names.hsdeleted−468
@@ -1,468 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Sugar.Names
4−-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−module Language.PureScript.Sugar.Names (
16− desugarImports
17−) where
18−
19−import Data.Maybe (fromMaybe, isJust, mapMaybe)
20−import Data.Monoid ((<>))
21−
22−import Control.Applicative (Applicative(..), (<$>), (<*>))
23−import Control.Monad.Error
24−
25−import qualified Data.Map as M
26−
27−import Language.PureScript.Declarations
28−import Language.PureScript.Names
29−import Language.PureScript.Types
30−import Language.PureScript.Environment
31−import Language.PureScript.Errors
32−import Language.PureScript.Traversals
33−
34−import qualified Language.PureScript.Constants as C
35−
36−-- |
37−-- The global export environment - every declaration exported from every module.
38−--
39−type ExportEnvironment = M.Map ModuleName Exports
40−
41−-- |
42−-- The exported declarations from a module.
43−--
44−data Exports = Exports
45− {
46− -- |
47− -- The types exported from each module
48− --
49− exportedTypes :: [(ProperName, [ProperName])]
50− -- |
51− -- The classes exported from each module
52− --
53− , exportedTypeClasses :: [ProperName]
54− -- |
55− -- The values exported from each module
56− , exportedValues :: [Ident]
57− --
58− } deriving (Show)
59−
60−-- |
61−-- An imported environment for a particular module. This also contains the module's own members.
62−--
63−data ImportEnvironment = ImportEnvironment
64− {
65− -- |
66− -- Local names for types within a module mapped to to their qualified names
67− --
68− importedTypes :: M.Map (Qualified ProperName) (Qualified ProperName)
69− -- |
70− -- Local names for data constructors within a module mapped to to their qualified names
71− --
72− , importedDataConstructors :: M.Map (Qualified ProperName) (Qualified ProperName)
73− -- |
74− -- Local names for classes within a module mapped to to their qualified names
75− --
76− , importedTypeClasses :: M.Map (Qualified ProperName) (Qualified ProperName)
77− -- |
78− -- Local names for values within a module mapped to to their qualified names
79− --
80− , importedValues :: M.Map (Qualified Ident) (Qualified Ident)
81− } deriving (Show)
82−
83−-- |
84−-- Updates the exports for a module from the global environment. If the module was not previously
85−-- present in the global environment, it is created.
86−--
87−updateExportedModule :: ExportEnvironment -> ModuleName -> (Exports -> Either ErrorStack Exports) -> Either ErrorStack ExportEnvironment
88−updateExportedModule env mn update = do
89− let exports = fromMaybe (error "Module was undefined in updateExportedModule") $ mn `M.lookup` env
90− exports' <- update exports
91− return $ M.insert mn exports' env
92−
93−-- |
94−-- Adds an empty module to an ExportEnvironment.
95−--
96−addEmptyModule :: ExportEnvironment -> ModuleName -> Either ErrorStack ExportEnvironment
97−addEmptyModule env name =
98− if name `M.member` env
99− then throwError $ mkErrorStack ("Module '" ++ show name ++ "' has been defined more than once") Nothing
100− else return $ M.insert name (Exports [] [] []) env
101−
102−-- |
103−-- Adds a type belonging to a module to the export environment.
104−--
105−addType :: ExportEnvironment -> ModuleName -> ProperName -> [ProperName] -> Either ErrorStack ExportEnvironment
106−addType env mn name dctors = updateExportedModule env mn $ \m -> do
107− types' <- addExport (exportedTypes m) (name, dctors)
108− return $ m { exportedTypes = types' }
109−
110−-- |
111−-- Adds a class to the export environment.
112−--
113−addTypeClass :: ExportEnvironment -> ModuleName -> ProperName -> Either ErrorStack ExportEnvironment
114−addTypeClass env mn name = updateExportedModule env mn $ \m -> do
115− classes <- addExport (exportedTypeClasses m) name
116− return $ m { exportedTypeClasses = classes }
117−
118−-- |
119−-- Adds a class to the export environment.
120−--
121−addValue :: ExportEnvironment -> ModuleName -> Ident -> Either ErrorStack ExportEnvironment
122−addValue env mn name = updateExportedModule env mn $ \m -> do
123− values <- addExport (exportedValues m) name
124− return $ m { exportedValues = values }
125−
126−-- |
127−-- Adds an entry to a list of exports unless it is already present, in which case an error is
128−-- returned.
129−--
130−addExport :: (Eq a, Show a) => [a] -> a -> Either ErrorStack [a]
131−addExport exports name =
132− if name `elem` exports
133− then throwError $ mkErrorStack ("Multiple definitions for '" ++ show name ++ "'") Nothing
134− else return $ name : exports
135−
136−-- |
137−-- Replaces all local names with qualified names within a set of modules.
138−--
139−desugarImports :: [Module] -> Either ErrorStack [Module]
140−desugarImports modules = do
141− unfilteredExports <- findExports modules
142− exports <- foldM filterModuleExports unfilteredExports modules
143− mapM (renameInModule' unfilteredExports exports) modules
144− where
145−
146− -- Filters the exports for a module in the global exports environment so that only explicitly
147− -- exported members remain. If the module does not explicitly export anything, everything is
148− -- exported.
149− filterModuleExports :: ExportEnvironment -> Module -> Either ErrorStack ExportEnvironment
150− filterModuleExports env (Module mn _ (Just exps)) = filterExports mn exps env
151− filterModuleExports env _ = return env
152−
153− -- Rename and check all the names within a module. We tweak the global exports environment so
154− -- the module has access to an unfiltered list of its own members.
155− renameInModule' :: ExportEnvironment -> ExportEnvironment -> Module -> Either ErrorStack Module
156− renameInModule' unfilteredExports exports m@(Module mn _ _) =
157− rethrow (strMsg ("Error in module " ++ show mn) <>) $ do
158− let env = M.update (\_ -> M.lookup mn unfilteredExports) mn exports
159− let exps = fromMaybe (error "Module is missing in renameInModule'") $ M.lookup mn exports
160− imports <- resolveImports env m
161− renameInModule imports env (elaborateExports exps m)
162−
163−-- |
164−-- Make all exports for a module explicit. This may still effect modules that have an exports list,
165−-- as it will also make all data constructor exports explicit.
166−--
167−elaborateExports :: Exports -> Module -> Module
168−elaborateExports exps (Module mn decls _) = Module mn decls (Just $
169− map (\(ctor, dctors) -> TypeRef ctor (Just dctors)) (exportedTypes exps) ++
170− map TypeClassRef (exportedTypeClasses exps) ++
171− map ValueRef (exportedValues exps))
172−
173−-- |
174−-- Replaces all local names with qualified names within a module and checks that all existing
175−-- qualified names are valid.
176−--
177−renameInModule :: ImportEnvironment -> ExportEnvironment -> Module -> Either ErrorStack Module
178−renameInModule imports exports (Module mn decls exps) =
179− Module mn <$> mapM go decls <*> pure exps
180− where
181− (go, _, _, _, _) = everywhereWithContextOnValuesM (Nothing, []) updateDecl updateValue updateBinder updateCase defS
182−
183− updateDecl :: (Maybe SourcePos, [Ident]) -> Declaration -> Either ErrorStack ((Maybe SourcePos, [Ident]), Declaration)
184− updateDecl (_, bound) d@(PositionedDeclaration pos _) = return ((Just pos, bound), d)
185− updateDecl (pos, bound) (DataDeclaration name args dctors) =
186− (,) (pos, bound) <$> (DataDeclaration name args <$> mapM (sndM (mapM (updateTypesEverywhere pos))) dctors)
187− updateDecl (pos, bound) (TypeSynonymDeclaration name ps ty) =
188− (,) (pos, bound) <$> (TypeSynonymDeclaration name ps <$> updateTypesEverywhere pos ty)
189− updateDecl (pos, bound) (TypeClassDeclaration className args implies ds) =
190− (,) (pos, bound) <$> (TypeClassDeclaration className args <$> updateConstraints pos implies <*> pure ds)
191− updateDecl (pos, bound) (TypeInstanceDeclaration name cs cn ts ds) =
192− (,) (pos, bound) <$> (TypeInstanceDeclaration name <$> updateConstraints pos cs <*> updateClassName cn pos <*> mapM (updateTypesEverywhere pos) ts <*> pure ds)
193− updateDecl (pos, bound) (ExternInstanceDeclaration name cs cn ts) =
194− (,) (pos, bound) <$> (ExternInstanceDeclaration name <$> updateConstraints pos cs <*> updateClassName cn Nothing <*> mapM (updateTypesEverywhere pos) ts)
195− updateDecl (pos, bound) (TypeDeclaration name ty) =
196− (,) (pos, bound) <$> (TypeDeclaration name <$> updateTypesEverywhere pos ty)
197− updateDecl (pos, bound) (ExternDeclaration fit name js ty) =
198− (,) (pos, name : bound) <$> (ExternDeclaration fit name js <$> updateTypesEverywhere pos ty)
199− updateDecl s d = return (s, d)
200−
201− updateValue :: (Maybe SourcePos, [Ident]) -> Value -> Either ErrorStack ((Maybe SourcePos, [Ident]), Value)
202− updateValue (_, bound) v@(PositionedValue pos' _) = return ((Just pos', bound), v)
203− updateValue (pos, bound) (Abs (Left arg) val') = return ((pos, arg : bound), Abs (Left arg) val')
204− updateValue (pos, bound) (Let ds val') =
205− let args = mapMaybe letBoundVariable ds
206− in return ((pos, args ++ bound), Let ds val')
207− updateValue (pos, bound) (Var name'@(Qualified Nothing ident)) | ident `notElem` bound =
208− (,) (pos, bound) <$> (Var <$> updateValueName name' pos)
209− updateValue (pos, bound) (Var name'@(Qualified (Just _) _)) =
210− (,) (pos, bound) <$> (Var <$> updateValueName name' pos)
211− updateValue (pos, bound) (BinaryNoParens name'@(Qualified Nothing ident) v1 v2) | ident `notElem` bound =
212− (,) (pos, bound) <$> (BinaryNoParens <$> updateValueName name' pos <*> pure v1 <*> pure v2)
213− updateValue (pos, bound) (BinaryNoParens name'@(Qualified (Just _) _) v1 v2) =
214− (,) (pos, bound) <$> (BinaryNoParens <$> updateValueName name' pos <*> pure v1 <*> pure v2)
215− updateValue s@(pos, _) (Constructor name) = (,) s <$> (Constructor <$> updateDataConstructorName name pos)
216− updateValue s@(pos, _) (TypedValue check val ty) = (,) s <$> (TypedValue check val <$> updateTypesEverywhere pos ty)
217− updateValue s v = return (s, v)
218−
219− updateBinder :: (Maybe SourcePos, [Ident]) -> Binder -> Either ErrorStack ((Maybe SourcePos, [Ident]), Binder)
220− updateBinder (_, bound) v@(PositionedBinder pos _) = return ((Just pos, bound), v)
221− updateBinder s@(pos, _) (ConstructorBinder name b) = (,) s <$> (ConstructorBinder <$> updateDataConstructorName name pos <*> pure b)
222− updateBinder s v = return (s, v)
223−
224− updateCase :: (Maybe SourcePos, [Ident]) -> CaseAlternative -> Either ErrorStack ((Maybe SourcePos, [Ident]), CaseAlternative)
225− updateCase (pos, bound) c@(CaseAlternative bs _ _) = return ((pos, concatMap binderNames bs ++ bound), c)
226−
227− letBoundVariable :: Declaration -> Maybe Ident
228− letBoundVariable (ValueDeclaration ident _ _ _ _) = Just ident
229− letBoundVariable (PositionedDeclaration _ d) = letBoundVariable d
230− letBoundVariable _ = Nothing
231−
232− updateTypesEverywhere :: Maybe SourcePos -> Type -> Either ErrorStack Type
233− updateTypesEverywhere pos0 = everywhereOnTypesM (updateType pos0)
234− where
235− updateType :: Maybe SourcePos -> Type -> Either ErrorStack Type
236− updateType pos (TypeConstructor name) = TypeConstructor <$> updateTypeName name pos
237− updateType pos (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym <$> updateTypeName name pos <*> pure tys
238− updateType pos (ConstrainedType cs t) = ConstrainedType <$> updateConstraints pos cs <*> pure t
239− updateType _ t = return t
240−
241− updateConstraints pos = mapM (\(name, ts) -> (,) <$> updateClassName name pos <*> mapM (updateTypesEverywhere pos) ts)
242−
243− updateTypeName = update "type" importedTypes (\mes -> isJust . (`lookup` exportedTypes mes))
244− updateClassName = update "type class" importedTypeClasses (flip elem . exportedTypeClasses)
245− updateValueName = update "value" importedValues (flip elem . exportedValues)
246− updateDataConstructorName = update "data constructor" importedDataConstructors (\mes -> flip elem (join $ snd `map` exportedTypes mes))
247−
248− -- Update names so unqualified references become qualified, and locally qualified references
249− -- are replaced with their canoncial qualified names (e.g. M.Map -> Data.Map.Map)
250− update :: (Ord a, Show a) => String
251− -> (ImportEnvironment -> M.Map (Qualified a) (Qualified a))
252− -> (Exports -> a -> Bool)
253− -> Qualified a
254− -> Maybe SourcePos
255− -> Either ErrorStack (Qualified a)
256− update t getI checkE qname@(Qualified mn' name) pos = case (M.lookup qname (getI imports), mn') of
257− (Just qname', _) -> return qname'
258− (Nothing, Just mn'') -> do
259− modExports <- getExports mn''
260− if checkE modExports name
261− then return qname
262− else positioned $ throwError $ mkErrorStack ("Unknown " ++ t ++ " '" ++ show qname ++ "'") Nothing
263− _ -> positioned $ throwError $ mkErrorStack ("Unknown " ++ t ++ " '" ++ show name ++ "'") Nothing
264− where
265− positioned err = case pos of
266− Nothing -> err
267− Just pos' -> rethrowWithPosition pos' err
268−
269− -- Gets the exports for a module, or an error message if the module doesn't exist
270− getExports :: ModuleName -> Either ErrorStack Exports
271− getExports mn' = maybe (throwError $ mkErrorStack ("Unknown module '" ++ show mn' ++ "'") Nothing) return $ M.lookup mn' exports
272−
273−-- |
274−-- Finds all exported declarations in a set of modules.
275−--
276−findExports :: [Module] -> Either ErrorStack ExportEnvironment
277−findExports = foldM addModule $ M.singleton (ModuleName [ProperName C.prim]) primExports
278− where
279−
280− -- The exported types from the Prim module
281− primExports = Exports (mkTypeEntry `map` M.keys primTypes) [] []
282− where
283− mkTypeEntry (Qualified _ name) = (name, [])
284−
285− -- Add all of the exported declarations from a module to the global export environment
286− addModule :: ExportEnvironment -> Module -> Either ErrorStack ExportEnvironment
287− addModule env (Module mn ds _) = do
288− env' <- addEmptyModule env mn
289− rethrow (strMsg ("Error in module " ++ show mn) <>) $ foldM (addDecl mn) env' ds
290−
291− -- Add a declaration from a module to the global export environment
292− addDecl :: ModuleName -> ExportEnvironment -> Declaration -> Either ErrorStack ExportEnvironment
293− addDecl mn env (TypeClassDeclaration tcn _ _ ds) = do
294− env' <- addTypeClass env mn tcn
295− foldM go env' ds
296− where
297− go env'' (TypeDeclaration name _) = addValue env'' mn name
298− go env'' (PositionedDeclaration pos d) = rethrowWithPosition pos $ go env'' d
299− go _ _ = error "Invalid declaration in TypeClassDeclaration"
300− addDecl mn env (DataDeclaration tn _ dcs) = addType env mn tn (map fst dcs)
301− addDecl mn env (TypeSynonymDeclaration tn _ _) = addType env mn tn []
302− addDecl mn env (ExternDataDeclaration tn _) = addType env mn tn []
303− addDecl mn env (ValueDeclaration name _ _ _ _) = addValue env mn name
304− addDecl mn env (ExternDeclaration _ name _ _) = addValue env mn name
305− addDecl mn env (PositionedDeclaration _ d) = addDecl mn env d
306− addDecl _ env _ = return env
307−
308−-- |
309−-- Filters the exports for a module to ensure only explicit exports are kept in the global exports
310−-- environment.
311−--
312−filterExports :: ModuleName -> [DeclarationRef] -> ExportEnvironment -> Either ErrorStack ExportEnvironment
313−filterExports mn exps env = do
314− let moduleExports = fromMaybe (error "Module is missing") (mn `M.lookup` env)
315− moduleExports' <- rethrow (strMsg ("Error in module " ++ show mn) <>) $ filterModule moduleExports
316− return $ M.insert mn moduleExports' env
317− where
318−
319− -- Filter the exports for the specific module
320− filterModule :: Exports -> Either ErrorStack Exports
321− filterModule exported = do
322− types' <- foldM (filterTypes $ exportedTypes exported) [] exps
323− values <- foldM (filterValues $ exportedValues exported) [] exps
324− classes <- foldM (filterClasses $ exportedTypeClasses exported) [] exps
325− return exported { exportedTypes = types', exportedTypeClasses = classes, exportedValues = values }
326−
327− -- Ensure the exported types and data constructors exist in the module and add them to the set of
328− -- exports
329− filterTypes :: [(ProperName, [ProperName])] -> [(ProperName, [ProperName])] -> DeclarationRef -> Either ErrorStack [(ProperName, [ProperName])]
330− filterTypes expTys result (PositionedDeclarationRef pos r) = rethrowWithPosition pos $ filterTypes expTys result r
331− filterTypes expTys result (TypeRef name expDcons) = do
332− dcons <- maybe (throwError $ mkErrorStack ("Cannot export undefined type '" ++ show name ++ "'") Nothing) return $ name `lookup` expTys
333− dcons' <- maybe (return dcons) (foldM (filterDcons name dcons) []) expDcons
334− return $ (name, dcons') : result
335− filterTypes _ result _ = return result
336−
337− -- Ensure the exported data constructors exists for a type and add them to the list of exports
338− filterDcons :: ProperName -> [ProperName] -> [ProperName] -> ProperName -> Either ErrorStack [ProperName]
339− filterDcons tcon exps' result name =
340− if name `elem` exps'
341− then return $ name : result
342− else throwError $ mkErrorStack ("Cannot export undefined data constructor '" ++ show name ++ "' for type '" ++ show tcon ++ "'") Nothing
343−
344− -- Ensure the exported classes exist in the module and add them to the set of exports
345− filterClasses :: [ProperName] -> [ProperName] -> DeclarationRef -> Either ErrorStack [ProperName]
346− filterClasses exps' result (PositionedDeclarationRef pos r) = rethrowWithPosition pos $ filterClasses exps' result r
347− filterClasses exps' result (TypeClassRef name) =
348− if name `elem` exps'
349− then return $ name : result
350− else throwError $ mkErrorStack ("Cannot export undefined type class '" ++ show name ++ "'") Nothing
351− filterClasses _ result _ = return result
352−
353− -- Ensure the exported values exist in the module and add them to the set of exports
354− filterValues :: [Ident] -> [Ident] -> DeclarationRef -> Either ErrorStack [Ident]
355− filterValues exps' result (PositionedDeclarationRef pos r) = rethrowWithPosition pos $ filterValues exps' result r
356− filterValues exps' result (ValueRef name) =
357− if name `elem` exps'
358− then return $ name : result
359− else throwError $ mkErrorStack ("Cannot export undefined value '" ++ show name ++ "'") Nothing
360− filterValues _ result _ = return result
361−
362−-- |
363−-- Type representing a set of declarations being explicitly imported from a module
364−--
365−type ExplicitImports = [DeclarationRef]
366−
367−-- |
368−-- Finds the imports within a module, mapping the imported module name to an optional set of
369−-- explicitly imported declarations.
370−--
371−findImports :: [Declaration] -> M.Map ModuleName (Maybe SourcePos, Maybe ExplicitImports, Maybe ModuleName)
372−findImports = foldl (findImports' Nothing) M.empty
373− where
374− findImports' pos result (ImportDeclaration mn expl qual) = M.insert mn (pos, expl, qual) result
375− findImports' _ result (PositionedDeclaration pos d) = findImports' (Just pos) result d
376− findImports' _ result _ = result
377−
378−-- |
379−-- Constructs a local environment for a module.
380−--
381−resolveImports :: ExportEnvironment -> Module -> Either ErrorStack ImportEnvironment
382−resolveImports env (Module currentModule decls _) =
383− foldM resolveImport' (ImportEnvironment M.empty M.empty M.empty M.empty) (M.toList scope)
384− where
385−
386− -- A Map from module name to the source position for the import, the list of imports from that
387− -- module (where Nothing indicates everything is to be imported), and optionally a qualified name
388− -- for the module
389− scope :: M.Map ModuleName (Maybe SourcePos, Maybe ExplicitImports, Maybe ModuleName)
390− scope = M.insert (ModuleName [ProperName C.prim]) (Nothing, Nothing, Nothing) $
391− M.insert currentModule (Nothing, Nothing, Nothing) (findImports decls)
392−
393− resolveImport' :: ImportEnvironment -> (ModuleName, (Maybe SourcePos, Maybe ExplicitImports, Maybe ModuleName)) -> Either ErrorStack ImportEnvironment
394− resolveImport' imp (mn, (pos, explImports, impQual)) = do
395− modExports <- positioned $ maybe (throwError $ mkErrorStack ("Cannot import unknown module '" ++ show mn ++ "'") Nothing) return $ mn `M.lookup` env
396− positioned $ resolveImport currentModule mn modExports imp impQual explImports
397− where
398− positioned err = case pos of
399− Nothing -> err
400− Just pos' -> rethrowWithPosition pos' err
401−
402−-- |
403−-- Extends the local environment for a module by resolving an import of another module.
404−--
405−resolveImport :: ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ModuleName -> Maybe ExplicitImports-> Either ErrorStack ImportEnvironment
406−resolveImport currentModule importModule exps imps impQual = maybe importAll (foldM importExplicit imps)
407− where
408−
409− -- Import everything from a module
410− importAll :: Either ErrorStack ImportEnvironment
411− importAll = do
412− imp' <- foldM (\m (name, dctors) -> importExplicit m (TypeRef name (Just dctors))) imps (exportedTypes exps)
413− imp'' <- foldM (\m name -> importExplicit m (ValueRef name)) imp' (exportedValues exps)
414− foldM (\m name -> importExplicit m (TypeClassRef name)) imp'' (exportedTypeClasses exps)
415−
416− -- Import something explicitly
417− importExplicit :: ImportEnvironment -> DeclarationRef -> Either ErrorStack ImportEnvironment
418− importExplicit imp (PositionedDeclarationRef pos r) = rethrowWithPosition pos $ importExplicit imp r
419− importExplicit imp (ValueRef name) = do
420− _ <- checkImportExists "value" values name
421− values' <- updateImports (importedValues imp) name
422− return $ imp { importedValues = values' }
423− importExplicit imp (TypeRef name dctors) = do
424− _ <- checkImportExists "type" availableTypes name
425− types' <- updateImports (importedTypes imp) name
426− let allDctors = allExportedDataConstructors name
427− dctors' <- maybe (return allDctors) (mapM $ checkDctorExists allDctors) dctors
428− dctors'' <- foldM updateImports (importedDataConstructors imp) dctors'
429− return $ imp { importedTypes = types', importedDataConstructors = dctors'' }
430− importExplicit imp (TypeClassRef name) = do
431− _ <- checkImportExists "type class" classes name
432− typeClasses' <- updateImports (importedTypeClasses imp) name
433− return $ imp { importedTypeClasses = typeClasses' }
434− importExplicit _ _ = error "Invalid argument to importExplicit"
435−
436− -- Find all exported data constructors for a given type
437− allExportedDataConstructors :: ProperName -> [ProperName]
438− allExportedDataConstructors name = fromMaybe [] $ name `lookup` exportedTypes exps
439−
440− -- Add something to the ImportEnvironment if it does not already exist there
441− updateImports :: (Ord a, Show a) => M.Map (Qualified a) (Qualified a) -> a -> Either ErrorStack (M.Map (Qualified a) (Qualified a))
442− updateImports m name = case M.lookup (Qualified impQual name) m of
443− Nothing -> return $ M.insert (Qualified impQual name) (Qualified (Just importModule) name) m
444− Just (Qualified Nothing _) -> error "Invalid state in updateImports"
445− Just x@(Qualified (Just mn) _) -> throwError $ mkErrorStack err Nothing
446− where
447− err = if mn == currentModule || importModule == currentModule
448− then "Definition '" ++ show name ++ "' conflicts with import '" ++ show (Qualified (Just importModule) name) ++ "'"
449− else "Conflicting imports for '" ++ show name ++ "': '" ++ show x ++ "', '" ++ show (Qualified (Just importModule) name) ++ "'"
450−
451− -- The available values, types, and classes in the module being imported
452− values = exportedValues exps
453− availableTypes = fst `map` exportedTypes exps
454− classes = exportedTypeClasses exps
455−
456− -- Ensure that an explicitly imported data constructor exists for the type it is being imported
457− -- from
458− checkDctorExists :: [ProperName] -> ProperName -> Either ErrorStack ProperName
459− checkDctorExists = checkImportExists "data constructor"
460−
461− -- Check that an explicitly imported item exists in the module it is being imported from
462− checkImportExists :: (Eq a, Show a) => String -> [a] -> a -> Either ErrorStack a
463− checkImportExists t exports item =
464− if item `elem` exports
465− then return item
466− else throwError $ mkErrorStack ("Cannot import unknown " ++ t ++ " '" ++ show item ++ "' from '" ++ show importModule ++ "'") Nothing
467−
468−
src/Language/PureScript/Sugar/Operators.hsdeleted−152
@@ -1,152 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Sugar.Operators
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the desugaring pass which reapplies binary operators based
13−-- on their fixity data and removes explicit parentheses.
14−--
15−-- The value parser ignores fixity data when parsing binary operator applications, so
16−-- it is necessary to reorder them here.
17−--
18−-----------------------------------------------------------------------------
19−
20−{-# LANGUAGE Rank2Types, FlexibleContexts #-}
21−
22−module Language.PureScript.Sugar.Operators (
23− rebracket,
24− removeSignedLiterals
25−) where
26−
27−import Language.PureScript.Names
28−import Language.PureScript.Declarations
29−import Language.PureScript.Errors
30−
31−import Control.Applicative
32−import Control.Monad.State
33−import Control.Monad.Error.Class
34−
35−import Data.Monoid ((<>))
36−import Data.Function (on)
37−import Data.Functor.Identity
38−import Data.List (groupBy, sortBy)
39−
40−import qualified Text.Parsec as P
41−import qualified Text.Parsec.Pos as P
42−import qualified Text.Parsec.Expr as P
43−
44−import qualified Language.PureScript.Constants as C
45−
46−-- |
47−-- Remove explicit parentheses and reorder binary operator applications
48−--
49−rebracket :: [Module] -> Either ErrorStack [Module]
50−rebracket ms = do
51− let fixities = concatMap collectFixities ms
52− ensureNoDuplicates $ map (\(i, pos, _) -> (i, pos)) fixities
53− let opTable = customOperatorTable $ map (\(i, _, f) -> (i, f)) fixities
54− mapM (rebracketModule opTable) ms
55−
56−removeSignedLiterals :: Module -> Module
57−removeSignedLiterals (Module mn ds exts) = Module mn (map f' ds) exts
58− where
59− (f', _, _) = everywhereOnValues id go id
60−
61− go (UnaryMinus (NumericLiteral (Left n))) = NumericLiteral (Left $ negate n)
62− go (UnaryMinus (NumericLiteral (Right n))) = NumericLiteral (Right $ negate n)
63− go (UnaryMinus val) = App (Var (Qualified (Just (ModuleName [ProperName C.prelude])) (Ident C.negate))) val
64− go other = other
65−
66−rebracketModule :: [[(Qualified Ident, Value -> Value -> Value, Associativity)]] -> Module -> Either ErrorStack Module
67−rebracketModule opTable (Module mn ds exts) =
68− let (f, _, _) = everywhereOnValuesTopDownM return (matchOperators opTable) return
69− in Module mn <$> (map removeParens <$> mapM f ds) <*> pure exts
70−
71−removeParens :: Declaration -> Declaration
72−removeParens =
73− let (f, _, _) = everywhereOnValues id go id
74− in f
75− where
76− go (Parens val) = val
77− go val = val
78−
79−collectFixities :: Module -> [(Qualified Ident, SourcePos, Fixity)]
80−collectFixities (Module moduleName ds _) = concatMap collect ds
81− where
82− collect :: Declaration -> [(Qualified Ident, SourcePos, Fixity)]
83− collect (PositionedDeclaration pos (FixityDeclaration fixity name)) = [(Qualified (Just moduleName) (Op name), pos, fixity)]
84− collect FixityDeclaration{} = error "Fixity without srcpos info"
85− collect _ = []
86−
87−ensureNoDuplicates :: [(Qualified Ident, SourcePos)] -> Either ErrorStack ()
88−ensureNoDuplicates m = go $ sortBy (compare `on` fst) m
89− where
90− go [] = return ()
91− go [_] = return ()
92− go ((x@(Qualified (Just mn) name), _) : (y, pos) : _) | x == y =
93− rethrow (strMsg ("Error in module " ++ show mn) <>) $
94− rethrowWithPosition pos $
95− throwError $ mkErrorStack ("Redefined fixity for " ++ show name) Nothing
96− go (_ : rest) = go rest
97−
98−customOperatorTable :: [(Qualified Ident, Fixity)] -> [[(Qualified Ident, Value -> Value -> Value, Associativity)]]
99−customOperatorTable fixities =
100− let
101− applyUserOp ident t1 = App (App (Var ident) t1)
102− userOps = map (\(name, Fixity a p) -> (name, applyUserOp name, p, a)) fixities
103− sorted = sortBy (flip compare `on` (\(_, _, p, _) -> p)) userOps
104− groups = groupBy ((==) `on` (\(_, _, p, _) -> p)) sorted
105− in
106− map (map (\(name, f, _, a) -> (name, f, a))) groups
107−
108−type Chain = [Either Value (Qualified Ident)]
109−
110−matchOperators :: [[(Qualified Ident, Value -> Value -> Value, Associativity)]] -> Value -> Either ErrorStack Value
111−matchOperators ops = parseChains
112− where
113− parseChains :: Value -> Either ErrorStack Value
114− parseChains b@BinaryNoParens{} = bracketChain (extendChain b)
115− parseChains other = return other
116− extendChain :: Value -> Chain
117− extendChain (BinaryNoParens name l r) = Left l : Right name : extendChain r
118− extendChain other = [Left other]
119− bracketChain :: Chain -> Either ErrorStack Value
120− bracketChain = either (Left . (`mkErrorStack` Nothing) . show) Right . P.parse (P.buildExpressionParser opTable parseValue <* P.eof) "operator expression"
121− opTable = [P.Infix (P.try (parseTicks >>= \ident -> return (\t1 t2 -> App (App (Var ident) t1) t2))) P.AssocLeft]
122− : map (map (\(name, f, a) -> P.Infix (P.try (matchOp name) >> return f) (toAssoc a))) ops
123− ++ [[ P.Infix (P.try (parseOp >>= \ident -> return (\t1 t2 -> App (App (Var ident) t1) t2))) P.AssocLeft ]]
124−
125−toAssoc :: Associativity -> P.Assoc
126−toAssoc Infixl = P.AssocLeft
127−toAssoc Infixr = P.AssocRight
128−toAssoc Infix = P.AssocNone
129−
130−token :: (P.Stream s Identity t, Show t) => (t -> Maybe a) -> P.Parsec s u a
131−token = P.token show (const (P.initialPos ""))
132−
133−parseValue :: P.Parsec Chain () Value
134−parseValue = token (either Just (const Nothing)) P.<?> "expression"
135−
136−parseOp :: P.Parsec Chain () (Qualified Ident)
137−parseOp = token (either (const Nothing) fromOp) P.<?> "operator"
138− where
139− fromOp q@(Qualified _ (Op _)) = Just q
140− fromOp _ = Nothing
141−
142−parseTicks :: P.Parsec Chain () (Qualified Ident)
143−parseTicks = token (either (const Nothing) fromOp) P.<?> "infix function"
144− where
145− fromOp q@(Qualified _ (Ident _)) = Just q
146− fromOp _ = Nothing
147−
148−matchOp :: Qualified Ident -> P.Parsec Chain () ()
149−matchOp op = do
150− ident <- parseOp
151− guard $ ident == op
152−
src/Language/PureScript/Sugar/TypeClasses.hsdeleted−219
@@ -1,219 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Sugar.TypeClasses
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the desugaring pass which creates type synonyms for type class dictionaries
13−-- and dictionary expressions for type class instances.
14−--
15−-----------------------------------------------------------------------------
16−
17−module Language.PureScript.Sugar.TypeClasses (
18− desugarTypeClasses
19−) where
20−
21−import Language.PureScript.Declarations
22−import Language.PureScript.Names
23−import Language.PureScript.Types
24−import Language.PureScript.Sugar.CaseDeclarations
25−import Language.PureScript.Environment
26−import Language.PureScript.Errors
27−import Language.PureScript.Supply
28−import Language.PureScript.Pretty.Types (prettyPrintTypeAtom)
29−
30−import qualified Language.PureScript.Constants as C
31−
32−import Control.Applicative
33−import Control.Monad.Error
34−import Control.Monad.State
35−import Control.Arrow (first, second)
36−import Data.List ((\\))
37−import Data.Monoid ((<>))
38−import Data.Maybe (catMaybes, mapMaybe)
39−
40−import qualified Data.Map as M
41−
42−type MemberMap = M.Map (ModuleName, ProperName) Declaration
43−
44−type Desugar = StateT MemberMap (SupplyT (Either ErrorStack))
45−
46−-- |
47−-- Add type synonym declarations for type class dictionary types, and value declarations for type class
48−-- instance dictionary expressions.
49−--
50−desugarTypeClasses :: [Module] -> SupplyT (Either ErrorStack) [Module]
51−desugarTypeClasses = flip evalStateT M.empty . mapM desugarModule
52−
53−desugarModule :: Module -> Desugar Module
54−desugarModule (Module name decls (Just exps)) = do
55− (newExpss, declss) <- unzip <$> mapM (desugarDecl name) decls
56− return $ Module name (concat declss) $ Just (exps ++ catMaybes newExpss)
57−desugarModule _ = error "Exports should have been elaborated in name desugaring"
58−
59−{- Desugar type class and type class instance declarations
60−--
61−-- Type classes become type synonyms for their dictionaries, and type instances become dictionary declarations.
62−-- Additional values are generated to access individual members of a dictionary, with the appropriate type.
63−--
64−-- E.g. the following
65−--
66−-- module Test where
67−--
68−-- class Foo a where
69−-- foo :: a -> a
70−--
71−-- instance fooString :: Foo String where
72−-- foo s = s ++ s
73−--
74−-- instance fooArray :: (Foo a) => Foo [a] where
75−-- foo = map foo
76−--
77−-- {- Superclasses -}
78−--
79−-- class (Foo a) <= Sub a where
80−-- sub :: a
81−--
82−-- instance subString :: Sub String where
83−-- sub = ""
84−--
85−-- becomes
86−--
87−-- type Foo a = { foo :: a -> a }
88−--
89−-- foreign import foo "function foo(dict) {\
90−-- \ return dict.foo;\
91−-- \}" :: forall a. (Foo a) => a -> a
92−--
93−-- fooString :: {} -> Foo String
94−-- fooString _ = { foo: \s -> s ++ s }
95−--
96−-- fooArray :: forall a. (Foo a) => Foo [a]
97−-- fooArray = { foo: map foo }
98−--
99−-- {- Superclasses -}
100−--
101−-- ...
102−--
103−-- subString :: {} -> { __superclasses :: { "Foo": {} -> Foo String }, sub :: String }
104−-- subString _ = {
105−-- __superclasses: {
106−-- "Foo": \_ -> <dictionary placeholder to be inserted during type checking\>
107−-- }
108−-- sub: ""
109−-- }
110−-}
111−desugarDecl :: ModuleName -> Declaration -> Desugar (Maybe DeclarationRef, [Declaration])
112−desugarDecl mn d@(TypeClassDeclaration name args implies members) = do
113− modify (M.insert (mn, name) d)
114− return $ (Nothing, d : typeClassDictionaryDeclaration name args implies members : map (typeClassMemberToDictionaryAccessor mn name args) members)
115−desugarDecl mn d@(TypeInstanceDeclaration name deps className ty members) = do
116− desugared <- lift $ desugarCases members
117− dictDecl <- typeInstanceDictionaryDeclaration name mn deps className ty desugared
118− return $ (Just $ TypeInstanceRef name, [d, dictDecl])
119−desugarDecl mn (PositionedDeclaration pos d) = do
120− (dr, ds) <- rethrowWithPosition pos $ desugarDecl mn d
121− return (dr, map (PositionedDeclaration pos) ds)
122−desugarDecl _ other = return (Nothing, [other])
123−
124−memberToNameAndType :: Declaration -> (Ident, Type)
125−memberToNameAndType (TypeDeclaration ident ty) = (ident, ty)
126−memberToNameAndType (PositionedDeclaration _ d) = memberToNameAndType d
127−memberToNameAndType _ = error "Invalid declaration in type class definition"
128−
129−identToProperty :: Ident -> String
130−identToProperty (Ident name) = name
131−identToProperty (Op op) = op
132−
133−typeClassDictionaryDeclaration :: ProperName -> [String] -> [(Qualified ProperName, [Type])] -> [Declaration] -> Declaration
134−typeClassDictionaryDeclaration name args implies members =
135− let superclassesType = TypeApp tyObject (rowFromList ([ (fieldName, function unit tySynApp)
136− | (index, (superclass, tyArgs)) <- zip [0..] implies
137− , let tySynApp = foldl TypeApp (TypeConstructor superclass) tyArgs
138− , let fieldName = mkSuperclassDictionaryName superclass index
139− ], REmpty))
140− members' = map (first identToProperty . memberToNameAndType) members
141− mtys = if null implies then members' else (C.__superclasses, superclassesType) : members'
142− in TypeSynonymDeclaration name args (TypeApp tyObject $ rowFromList (mtys, REmpty))
143−
144−typeClassMemberToDictionaryAccessor :: ModuleName -> ProperName -> [String] -> Declaration -> Declaration
145−typeClassMemberToDictionaryAccessor mn name args (TypeDeclaration ident ty) =
146− ValueDeclaration ident TypeClassAccessorImport [] Nothing $
147− TypedValue False (Abs (Left $ Ident "dict") (Accessor (runIdent ident) (Var $ Qualified Nothing (Ident "dict")))) $
148− moveQuantifiersToFront (quantify (ConstrainedType [(Qualified (Just mn) name, map TypeVar args)] ty))
149−typeClassMemberToDictionaryAccessor mn name args (PositionedDeclaration pos d) =
150− PositionedDeclaration pos $ typeClassMemberToDictionaryAccessor mn name args d
151−typeClassMemberToDictionaryAccessor _ _ _ _ = error "Invalid declaration in type class definition"
152−
153−mkSuperclassDictionaryName :: Qualified ProperName -> Integer -> String
154−mkSuperclassDictionaryName pn index = show pn ++ "_" ++ show index
155−
156−unit :: Type
157−unit = TypeApp tyObject REmpty
158−
159−typeInstanceDictionaryDeclaration :: Ident -> ModuleName -> [(Qualified ProperName, [Type])] -> Qualified ProperName -> [Type] -> [Declaration] -> Desugar Declaration
160−typeInstanceDictionaryDeclaration name mn deps className tys decls =
161− rethrow (strMsg ("Error in type class instance " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys) ++ ":") <>) $ do
162− m <- get
163−
164− -- Lookup the type arguments and member types for the type class
165− (TypeClassDeclaration _ args implies tyDecls) <- lift . lift $
166− maybe (Left $ mkErrorStack ("Type class " ++ show className ++ " is undefined") Nothing) Right $
167− M.lookup (qualify mn className) m
168−
169− case mapMaybe declName tyDecls \\ mapMaybe declName decls of
170− x : _ -> throwError $ mkErrorStack ("Member '" ++ show x ++ "' has not been implemented") Nothing
171− [] -> do
172−
173− let instanceTys = map memberToNameAndType tyDecls
174−
175− -- Replace the type arguments with the appropriate types in the member types
176− let memberTypes = map (second (replaceAllTypeVars (zip args tys))) instanceTys
177− -- Create values for the type instance members
178− memberNames <- map (first identToProperty) <$> mapM (memberToNameAndValue memberTypes) decls
179− -- Create the type of the dictionary
180− -- The type is an object type, but depending on type instance dependencies, may be constrained.
181− -- The dictionary itself is an object literal, but for reasons related to recursion, the dictionary
182− -- must be guarded by at least one function abstraction. For that reason, if the dictionary has no
183− -- dependencies, we introduce an unnamed function parameter.
184− let superclasses = ObjectLiteral
185− [ (fieldName, Abs (Left (Ident "_")) (SuperClassDictionary superclass tyArgs))
186− | (index, (superclass, suTyArgs)) <- zip [0..] implies
187− , let tyArgs = map (replaceAllTypeVars (zip args tys)) suTyArgs
188− , let fieldName = mkSuperclassDictionaryName superclass index
189− ]
190−
191− let memberNames' = if null implies then memberNames else (C.__superclasses, superclasses) : memberNames
192− dictTy = foldl TypeApp (TypeConstructor className) tys
193− constrainedTy = quantify (if null deps then function unit dictTy else ConstrainedType deps dictTy)
194− dict = if null deps then Abs (Left (Ident "_")) (ObjectLiteral memberNames') else ObjectLiteral memberNames'
195−
196− return $ ValueDeclaration name TypeInstanceDictionaryValue [] Nothing (TypedValue True dict constrainedTy)
197−
198− where
199−
200− declName :: Declaration -> Maybe Ident
201− declName (PositionedDeclaration _ d) = declName d
202− declName (ValueDeclaration ident _ _ _ _) = Just ident
203− declName (TypeDeclaration ident _) = Just ident
204− declName _ = Nothing
205−
206− memberToNameAndValue :: [(Ident, Type)] -> Declaration -> Desugar (Ident, Value)
207− memberToNameAndValue tys' d@(ValueDeclaration ident _ _ _ _) = do
208− _ <- lift . lift . maybe (Left $ mkErrorStack ("Type class does not define member '" ++ show ident ++ "'") Nothing) Right $ lookup ident tys'
209− let memberValue = typeInstanceDictionaryEntryValue d
210− return (ident, memberValue)
211− memberToNameAndValue tys' (PositionedDeclaration pos d) = rethrowWithPosition pos $ do
212− (ident, val) <- memberToNameAndValue tys' d
213− return (ident, PositionedValue pos val)
214− memberToNameAndValue _ _ = error "Invalid declaration in type instance definition"
215−
216− typeInstanceDictionaryEntryValue :: Declaration -> Value
217− typeInstanceDictionaryEntryValue (ValueDeclaration _ _ [] _ val) = val
218− typeInstanceDictionaryEntryValue (PositionedDeclaration pos d) = PositionedValue pos (typeInstanceDictionaryEntryValue d)
219− typeInstanceDictionaryEntryValue _ = error "Invalid declaration in type instance definition"
src/Language/PureScript/Sugar/TypeDeclarations.hsdeleted−66
@@ -1,66 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Sugar.TypeDeclarations
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the desugaring pass which replaces top-level type declarations with
13−-- type annotations on the corresponding expression.
14−--
15−-----------------------------------------------------------------------------
16−
17−module Language.PureScript.Sugar.TypeDeclarations (
18− desugarTypeDeclarations,
19− desugarTypeDeclarationsModule
20−) where
21−
22−import Data.Monoid ((<>))
23−
24−import Control.Applicative
25−import Control.Monad.Error.Class
26−import Control.Monad (forM)
27−
28−import Language.PureScript.Declarations
29−import Language.PureScript.Names
30−import Language.PureScript.Environment
31−import Language.PureScript.Errors
32−
33−-- |
34−-- Replace all top level type declarations in a module with type annotations
35−--
36−desugarTypeDeclarationsModule :: [Module] -> Either ErrorStack [Module]
37−desugarTypeDeclarationsModule ms = forM ms $ \(Module name ds exps) ->
38− rethrow (strMsg ("Error in module " ++ show name) <>) $
39− Module name <$> desugarTypeDeclarations ds <*> pure exps
40−
41−-- |
42−-- Replace all top level type declarations with type annotations
43−--
44−desugarTypeDeclarations :: [Declaration] -> Either ErrorStack [Declaration]
45−desugarTypeDeclarations (PositionedDeclaration pos d : ds) = do
46− (d' : ds') <- rethrowWithPosition pos $ desugarTypeDeclarations (d : ds)
47− return (PositionedDeclaration pos d' : ds')
48−desugarTypeDeclarations (TypeDeclaration name ty : d : rest) = do
49− (_, nameKind, val) <- fromValueDeclaration d
50− desugarTypeDeclarations (ValueDeclaration name nameKind [] Nothing (TypedValue True val ty) : rest)
51− where
52− fromValueDeclaration :: Declaration -> Either ErrorStack (Ident, NameKind, Value)
53− fromValueDeclaration (ValueDeclaration name' nameKind [] Nothing val) | name == name' = return (name', nameKind, val)
54− fromValueDeclaration (PositionedDeclaration pos d') = do
55− (ident, nameKind, val) <- rethrowWithPosition pos $ fromValueDeclaration d'
56− return (ident, nameKind, PositionedValue pos val)
57− fromValueDeclaration _ = throwError $ mkErrorStack ("Orphan type declaration for " ++ show name) Nothing
58−desugarTypeDeclarations (TypeDeclaration name _ : []) = throwError $ mkErrorStack ("Orphan type declaration for " ++ show name) Nothing
59−desugarTypeDeclarations (ValueDeclaration name nameKind bs g val : rest) = do
60− let (_, f, _) = everywhereOnValuesTopDownM return go return
61− (:) <$> (ValueDeclaration name nameKind bs g <$> f val) <*> desugarTypeDeclarations rest
62− where
63− go (Let ds val') = Let <$> desugarTypeDeclarations ds <*> pure val'
64− go other = return other
65−desugarTypeDeclarations (d:ds) = (:) d <$> desugarTypeDeclarations ds
66−desugarTypeDeclarations [] = return []
src/Language/PureScript/Supply.hsdeleted−56
@@ -1,56 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Supply
4−-- Copyright : (c) Phil Freeman 2014
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Fresh variable supply
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
17−{-# LANGUAGE FlexibleInstances #-}
18−{-# LANGUAGE MultiParamTypeClasses #-}
19−{-# LANGUAGE UndecidableInstances #-}
20−
21−module Language.PureScript.Supply where
22−
23−import Data.Functor.Identity
24−
25−import Control.Applicative
26−import Control.Monad.State
27−import Control.Monad.Error.Class
28−
29−newtype SupplyT m a = SupplyT { unSupplyT :: StateT Integer m a } deriving (Functor, Applicative, Monad, MonadTrans)
30−
31−runSupplyT :: Integer -> SupplyT m a -> m (a, Integer)
32−runSupplyT n = flip runStateT n . unSupplyT
33−
34−evalSupplyT :: (Functor m) => Integer -> SupplyT m a -> m a
35−evalSupplyT n = fmap fst . runSupplyT n
36−
37−type Supply = SupplyT Identity
38−
39−runSupply :: Integer -> Supply a -> (a, Integer)
40−runSupply n = runIdentity . runSupplyT n
41−
42−evalSupply :: Integer -> Supply a -> a
43−evalSupply n = runIdentity . evalSupplyT n
44−
45−fresh :: (Monad m) => SupplyT m Integer
46−fresh = SupplyT $ do
47− n <- get
48− put (n + 1)
49− return n
50−
51−freshName :: (Functor m, Monad m) => SupplyT m String
52−freshName = ('_' :) . show <$> fresh
53−
54−instance (MonadError e m) => MonadError e (SupplyT m) where
55− throwError = SupplyT . throwError
56− catchError e f = SupplyT $ catchError (unSupplyT e) (unSupplyT . f)
src/Language/PureScript/Traversals.hsdeleted−34
@@ -1,34 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Traversals
4−-- Copyright : (c) 2014 Phil Freeman
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- | Common functions for implementing generic traversals
12−--
13−-----------------------------------------------------------------------------
14−
15−module Language.PureScript.Traversals where
16−
17−import Control.Applicative
18−
19−fstM :: (Functor f) => (a -> f c) -> (a, b) -> f (c, b)
20−fstM f (a, b) = flip (,) b <$> f a
21−
22−sndM :: (Functor f) => (b -> f c) -> (a, b) -> f (a, c)
23−sndM f (a, b) = (,) a <$> f b
24−
25−thirdM :: (Functor f) => (c -> f d) -> (a, b, c) -> f (a, b, d)
26−thirdM f (a, b, c) = (,,) a b <$> f c
27−
28−maybeM :: (Applicative f) => (a -> f b) -> Maybe a -> f (Maybe b)
29−maybeM _ Nothing = pure Nothing
30−maybeM f (Just a) = Just <$> f a
31−
32−defS :: (Monad m) => st -> val -> m (st, val)
33−defS s val = return (s, val)
34−
src/Language/PureScript/TypeChecker.hsdeleted−209
@@ -1,209 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.TypeChecker
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- The top-level type checker, which checks all declarations in a module.
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE FlexibleInstances #-}
17−
18−module Language.PureScript.TypeChecker (
19− module T,
20− typeCheckAll
21−) where
22−
23−import Language.PureScript.TypeChecker.Monad as T
24−import Language.PureScript.TypeChecker.Kinds as T
25−import Language.PureScript.TypeChecker.Types as T
26−import Language.PureScript.TypeChecker.Synonyms as T
27−
28−import Data.Maybe
29−import Data.Monoid ((<>))
30−import qualified Data.Map as M
31−import Control.Monad.State
32−import Control.Monad.Error
33−
34−import Language.PureScript.Types
35−import Language.PureScript.Names
36−import Language.PureScript.Kinds
37−import Language.PureScript.Declarations
38−import Language.PureScript.TypeClassDictionaries
39−import Language.PureScript.Environment
40−import Language.PureScript.Errors
41−
42−addDataType :: ModuleName -> ProperName -> [String] -> [(ProperName, [Type])] -> Kind -> Check ()
43−addDataType moduleName name args dctors ctorKind = do
44− env <- getEnv
45− putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (ctorKind, DataType args dctors) (types env) }
46− forM_ dctors $ \(dctor, tys) ->
47− rethrow (strMsg ("Error in data constructor " ++ show dctor) <>) $
48− addDataConstructor moduleName name args dctor tys
49−
50−addDataConstructor :: ModuleName -> ProperName -> [String] -> ProperName -> [Type] -> Check ()
51−addDataConstructor moduleName name args dctor tys = do
52− env <- getEnv
53− let retTy = foldl TypeApp (TypeConstructor (Qualified (Just moduleName) name)) (map TypeVar args)
54− let dctorTy = foldr function retTy tys
55− let polyType = mkForAll args dctorTy
56− putEnv $ env { dataConstructors = M.insert (Qualified (Just moduleName) dctor) (name, polyType) (dataConstructors env) }
57−
58−addTypeSynonym :: ModuleName -> ProperName -> [String] -> Type -> Kind -> Check ()
59−addTypeSynonym moduleName name args ty kind = do
60− env <- getEnv
61− putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (kind, TypeSynonym) (types env)
62− , typeSynonyms = M.insert (Qualified (Just moduleName) name) (args, ty) (typeSynonyms env) }
63−
64−valueIsNotDefined :: ModuleName -> Ident -> Check ()
65−valueIsNotDefined moduleName name = do
66− env <- getEnv
67− case M.lookup (moduleName, name) (names env) of
68− Just _ -> throwError . strMsg $ show name ++ " is already defined"
69− Nothing -> return ()
70−
71−addValue :: ModuleName -> Ident -> Type -> NameKind -> Check ()
72−addValue moduleName name ty nameKind = do
73− env <- getEnv
74− putEnv (env { names = M.insert (moduleName, name) (ty, nameKind) (names env) })
75−
76−addTypeClass :: ModuleName -> ProperName -> [String] -> [(Qualified ProperName, [Type])] -> [Declaration] -> Check ()
77−addTypeClass moduleName pn args implies ds =
78− let members = map toPair ds in
79− modify $ \st -> st { checkEnv = (checkEnv st) { typeClasses = M.insert (Qualified (Just moduleName) pn) (args, members, implies) (typeClasses . checkEnv $ st) } }
80− where
81− toPair (TypeDeclaration ident ty) = (ident, ty)
82− toPair (PositionedDeclaration _ d) = toPair d
83− toPair _ = error "Invalid declaration in TypeClassDeclaration"
84−
85−addTypeClassDictionaries :: [TypeClassDictionaryInScope] -> Check ()
86−addTypeClassDictionaries entries =
87− let mentries = M.fromList [ ((canonicalizeDictionary entry, mn), entry) | entry@TypeClassDictionaryInScope{ tcdName = Qualified mn _ } <- entries ]
88− in modify $ \st -> st { checkEnv = (checkEnv st) { typeClassDictionaries = (typeClassDictionaries . checkEnv $ st) `M.union` mentries } }
89−
90−checkTypeClassInstance :: ModuleName -> Type -> Check ()
91−checkTypeClassInstance _ (TypeVar _) = return ()
92−checkTypeClassInstance _ (TypeConstructor ctor) = do
93− env <- getEnv
94− when (ctor `M.member` typeSynonyms env) . throwError . strMsg $ "Type synonym instances are disallowed"
95− return ()
96−checkTypeClassInstance m (TypeApp t1 t2) = checkTypeClassInstance m t1 >> checkTypeClassInstance m t2
97−checkTypeClassInstance _ ty = throwError $ mkErrorStack "Type class instance head is invalid." (Just (TypeError ty))
98−
99−-- |
100−-- Type check all declarations in a module
101−--
102−-- At this point, many declarations will have been desugared, but it is still necessary to
103−--
104−-- * Kind-check all types and add them to the @Environment@
105−--
106−-- * Type-check all values and add them to the @Environment@
107−--
108−-- * Bring type class instances into scope
109−--
110−-- * Process module imports
111−--
112−typeCheckAll :: Maybe ModuleName -> ModuleName -> [Declaration] -> Check [Declaration]
113−typeCheckAll _ _ [] = return []
114−typeCheckAll mainModuleName moduleName (d@(DataDeclaration name args dctors) : rest) = do
115− rethrow (strMsg ("Error in type constructor " ++ show name) <>) $ do
116− ctorKind <- kindsOf True moduleName name args (concatMap snd dctors)
117− addDataType moduleName name args dctors ctorKind
118− ds <- typeCheckAll mainModuleName moduleName rest
119− return $ d : ds
120−typeCheckAll mainModuleName moduleName (d@(DataBindingGroupDeclaration tys) : rest) = do
121− rethrow (strMsg "Error in data binding group" <>) $ do
122− let syns = mapMaybe toTypeSynonym tys
123− let dataDecls = mapMaybe toDataDecl tys
124− (syn_ks, data_ks) <- kindsOfAll moduleName syns (map (\(name, args, dctors) -> (name, args, concatMap snd dctors)) dataDecls)
125− forM_ (zip dataDecls data_ks) $ \((name, args, dctors), ctorKind) ->
126− addDataType moduleName name args dctors ctorKind
127− forM_ (zip syns syn_ks) $ \((name, args, ty), kind) ->
128− addTypeSynonym moduleName name args ty kind
129− ds <- typeCheckAll mainModuleName moduleName rest
130− return $ d : ds
131− where
132− toTypeSynonym (TypeSynonymDeclaration nm args ty) = Just (nm, args, ty)
133− toTypeSynonym (PositionedDeclaration _ d') = toTypeSynonym d'
134− toTypeSynonym _ = Nothing
135− toDataDecl (DataDeclaration nm args dctors) = Just (nm, args, dctors)
136− toDataDecl (PositionedDeclaration _ d') = toDataDecl d'
137− toDataDecl _ = Nothing
138−typeCheckAll mainModuleName moduleName (d@(TypeSynonymDeclaration name args ty) : rest) = do
139− rethrow (strMsg ("Error in type synonym " ++ show name) <>) $ do
140− kind <- kindsOf False moduleName name args [ty]
141− addTypeSynonym moduleName name args ty kind
142− ds <- typeCheckAll mainModuleName moduleName rest
143− return $ d : ds
144−typeCheckAll _ _ (TypeDeclaration _ _ : _) = error "Type declarations should have been removed"
145−typeCheckAll mainModuleName moduleName (ValueDeclaration name nameKind [] Nothing val : rest) = do
146− d <- rethrow (strMsg ("Error in declaration " ++ show name) <>) $ do
147− valueIsNotDefined moduleName name
148− [(_, (val', ty))] <- typesOf mainModuleName moduleName [(name, val)]
149− addValue moduleName name ty nameKind
150− return $ ValueDeclaration name nameKind [] Nothing val'
151− ds <- typeCheckAll mainModuleName moduleName rest
152− return $ d : ds
153−typeCheckAll _ _ (ValueDeclaration{} : _) = error "Binders were not desugared"
154−typeCheckAll mainModuleName moduleName (BindingGroupDeclaration vals : rest) = do
155− d <- rethrow (strMsg ("Error in binding group " ++ show (map (\(ident, _, _) -> ident) vals)) <>) $ do
156− forM_ (map (\(ident, _, _) -> ident) vals) $ \name ->
157− valueIsNotDefined moduleName name
158− tys <- typesOf mainModuleName moduleName $ map (\(ident, _, ty) -> (ident, ty)) vals
159− vals' <- forM (zipWith (\(name, nameKind, _) (_, (val, ty)) -> (name, val, nameKind, ty)) vals tys) $ \(name, val, nameKind, ty) -> do
160− addValue moduleName name ty nameKind
161− return (name, nameKind, val)
162− return $ BindingGroupDeclaration vals'
163− ds <- typeCheckAll mainModuleName moduleName rest
164− return $ d : ds
165−typeCheckAll mainModuleName moduleName (d@(ExternDataDeclaration name kind) : rest) = do
166− env <- getEnv
167− putEnv $ env { types = M.insert (Qualified (Just moduleName) name) (kind, ExternData) (types env) }
168− ds <- typeCheckAll mainModuleName moduleName rest
169− return $ d : ds
170−typeCheckAll mainModuleName moduleName (d@(ExternDeclaration importTy name _ ty) : rest) = do
171− rethrow (strMsg ("Error in foreign import declaration " ++ show name) <>) $ do
172− env <- getEnv
173− kind <- kindOf moduleName ty
174− guardWith (strMsg "Expected kind *") $ kind == Star
175− case M.lookup (moduleName, name) (names env) of
176− Just _ -> throwError . strMsg $ show name ++ " is already defined"
177− Nothing -> putEnv (env { names = M.insert (moduleName, name) (ty, Extern importTy) (names env) })
178− ds <- typeCheckAll mainModuleName moduleName rest
179− return $ d : ds
180−typeCheckAll mainModuleName moduleName (d@(FixityDeclaration _ name) : rest) = do
181− ds <- typeCheckAll mainModuleName moduleName rest
182− env <- getEnv
183− guardWith (strMsg ("Fixity declaration with no binding: " ++ name)) $ M.member (moduleName, Op name) $ names env
184− return $ d : ds
185−typeCheckAll mainModuleName currentModule (d@(ImportDeclaration moduleName _ _) : rest) = do
186− tcds <- getTypeClassDictionaries
187− let instances = filter (\tcd -> let Qualified (Just mn) _ = tcdName tcd in moduleName == mn) tcds
188− addTypeClassDictionaries [ tcd { tcdName = Qualified (Just currentModule) ident, tcdType = TCDAlias (canonicalizeDictionary tcd) }
189− | tcd <- instances
190− , let (Qualified _ ident) = tcdName tcd
191− ]
192− ds <- typeCheckAll mainModuleName currentModule rest
193− return $ d : ds
194−typeCheckAll mainModuleName moduleName (d@(TypeClassDeclaration pn args implies tys) : rest) = do
195− addTypeClass moduleName pn args implies tys
196− ds <- typeCheckAll mainModuleName moduleName rest
197− return $ d : ds
198−typeCheckAll mainModuleName moduleName (TypeInstanceDeclaration dictName deps className tys _ : rest) = do
199− typeCheckAll mainModuleName moduleName (ExternInstanceDeclaration dictName deps className tys : rest)
200−typeCheckAll mainModuleName moduleName (d@(ExternInstanceDeclaration dictName deps className tys) : rest) = do
201− mapM_ (checkTypeClassInstance moduleName) tys
202− forM_ deps $ mapM_ (checkTypeClassInstance moduleName) . snd
203− addTypeClassDictionaries [TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) className tys (Just deps) TCDRegular]
204− ds <- typeCheckAll mainModuleName moduleName rest
205− return $ d : ds
206−typeCheckAll mainModuleName moduleName (PositionedDeclaration pos d : rest) =
207− rethrowWithPosition pos $ do
208− (d' : rest') <- typeCheckAll mainModuleName moduleName (d : rest)
209− return (PositionedDeclaration pos d' : rest')
src/Language/PureScript/TypeChecker/Kinds.hsdeleted−185
@@ -1,185 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.TypeChecker.Kinds
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the kind checker
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# OPTIONS_GHC -fno-warn-orphans #-}
17−{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances #-}
18−
19−module Language.PureScript.TypeChecker.Kinds (
20− kindOf,
21− kindsOf,
22− kindsOfAll
23−) where
24−
25−import Language.PureScript.Types
26−import Language.PureScript.Kinds
27−import Language.PureScript.Names
28−import Language.PureScript.TypeChecker.Monad
29−import Language.PureScript.Pretty
30−import Language.PureScript.Environment
31−import Language.PureScript.Errors
32−
33−import Control.Monad.State
34−import Control.Monad.Error
35−import Control.Monad.Unify
36−
37−import Control.Applicative
38−
39−import qualified Data.Map as M
40−import qualified Data.HashMap.Strict as H
41−import Data.Monoid ((<>))
42−
43−instance Partial Kind where
44− unknown = KUnknown
45− isUnknown (KUnknown u) = Just u
46− isUnknown _ = Nothing
47− unknowns = everythingOnKinds (++) go
48− where
49− go (KUnknown u) = [u]
50− go _ = []
51− ($?) sub = everywhereOnKinds go
52− where
53− go t@(KUnknown u) = case H.lookup u (runSubstitution sub) of
54− Nothing -> t
55− Just t' -> t'
56− go other = other
57−
58−instance Unifiable Check Kind where
59− KUnknown u1 =?= KUnknown u2 | u1 == u2 = return ()
60− KUnknown u =?= k = u =:= k
61− k =?= KUnknown u = u =:= k
62− Star =?= Star = return ()
63− Bang =?= Bang = return ()
64− Row k1 =?= Row k2 = k1 =?= k2
65− FunKind k1 k2 =?= FunKind k3 k4 = do
66− k1 =?= k3
67− k2 =?= k4
68− k1 =?= k2 = UnifyT . lift . throwError . strMsg $ "Cannot unify " ++ prettyPrintKind k1 ++ " with " ++ prettyPrintKind k2 ++ "."
69−
70−-- |
71−-- Infer the kind of a single type
72−--
73−kindOf :: ModuleName -> Type -> Check Kind
74−kindOf _ ty =
75− rethrow (mkErrorStack "Error checking kind" (Just (TypeError ty)) <>) $
76− fmap tidyUp . liftUnify $ starIfUnknown <$> infer ty
77− where
78− tidyUp (k, sub) = sub $? k
79−
80−-- |
81−-- Infer the kind of a type constructor with a collection of arguments and a collection of associated data constructors
82−--
83−kindsOf :: Bool -> ModuleName -> ProperName -> [String] -> [Type] -> Check Kind
84−kindsOf isData moduleName name args ts = fmap tidyUp . liftUnify $ do
85− tyCon <- fresh
86− kargs <- replicateM (length args) fresh
87− let dict = (name, tyCon) : zipWith (\arg kind -> (arg, kind)) (map ProperName args) kargs
88− bindLocalTypeVariables moduleName dict $
89− solveTypes isData ts kargs tyCon
90− where
91− tidyUp (k, sub) = starIfUnknown $ sub $? k
92−
93−-- |
94−-- Simultaneously infer the kinds of several mutually recursive type constructors
95−--
96−kindsOfAll :: ModuleName -> [(ProperName, [String], Type)] -> [(ProperName, [String], [Type])] -> Check ([Kind], [Kind])
97−kindsOfAll moduleName syns tys = fmap tidyUp . liftUnify $ do
98− synVars <- replicateM (length syns) fresh
99− let dict = zipWith (\(name, _, _) var -> (name, var)) syns synVars
100− bindLocalTypeVariables moduleName dict $ do
101− tyCons <- replicateM (length tys) fresh
102− let dict' = zipWith (\(name, _, _) tyCon -> (name, tyCon)) tys tyCons
103− bindLocalTypeVariables moduleName dict' $ do
104− data_ks <- zipWithM (\tyCon (_, args, ts) -> do
105− kargs <- replicateM (length args) fresh
106− let argDict = zip (map ProperName args) kargs
107− bindLocalTypeVariables moduleName argDict $
108− solveTypes True ts kargs tyCon) tyCons tys
109− syn_ks <- zipWithM (\synVar (_, args, ty) -> do
110− kargs <- replicateM (length args) fresh
111− let argDict = zip (map ProperName args) kargs
112− bindLocalTypeVariables moduleName argDict $
113− solveTypes False [ty] kargs synVar) synVars syns
114− return (syn_ks, data_ks)
115− where
116− tidyUp ((ks1, ks2), sub) = (map (starIfUnknown . (sub $?)) ks1, map (starIfUnknown . (sub $?)) ks2)
117−
118−-- |
119−-- Solve the set of kind constraints associated with the data constructors for a type constructor
120−--
121−solveTypes :: Bool -> [Type] -> [Kind] -> Kind -> UnifyT Kind (Check) Kind
122−solveTypes isData ts kargs tyCon = do
123− ks <- mapM infer ts
124− when isData $ do
125− tyCon =?= foldr FunKind Star kargs
126− forM_ ks $ \k -> k =?= Star
127− when (not isData) $ do
128− tyCon =?= foldr FunKind (head ks) kargs
129− return tyCon
130−
131−-- |
132−-- Default all unknown kinds to the Star kind of types
133−--
134−starIfUnknown :: Kind -> Kind
135−starIfUnknown (KUnknown _) = Star
136−starIfUnknown (Row k) = Row (starIfUnknown k)
137−starIfUnknown (FunKind k1 k2) = FunKind (starIfUnknown k1) (starIfUnknown k2)
138−starIfUnknown k = k
139−
140−-- |
141−-- Infer a kind for a type
142−--
143−infer :: Type -> UnifyT Kind Check Kind
144−infer ty = rethrow (mkErrorStack "Error inferring type of value" (Just (TypeError ty)) <>) $ infer' ty
145−
146−infer' :: Type -> UnifyT Kind Check Kind
147−infer' (TypeVar v) = do
148− Just moduleName <- checkCurrentModule <$> get
149− UnifyT . lift $ lookupTypeVariable moduleName (Qualified Nothing (ProperName v))
150−infer' c@(TypeConstructor v) = do
151− env <- liftCheck getEnv
152− case M.lookup v (types env) of
153− Nothing -> UnifyT . lift . throwError $ mkErrorStack "Unknown type constructor" (Just (TypeError c))
154− Just (kind, _) -> return kind
155−infer' (TypeApp t1 t2) = do
156− k0 <- fresh
157− k1 <- infer t1
158− k2 <- infer t2
159− k1 =?= FunKind k2 k0
160− return k0
161−infer' (ForAll ident ty _) = do
162− k1 <- fresh
163− Just moduleName <- checkCurrentModule <$> get
164− k2 <- bindLocalTypeVariables moduleName [(ProperName ident, k1)] $ infer ty
165− k2 =?= Star
166− return Star
167−infer' REmpty = do
168− k <- fresh
169− return $ Row k
170−infer' (RCons _ ty row) = do
171− k1 <- infer ty
172− k2 <- infer row
173− k2 =?= Row k1
174− return $ Row k1
175−infer' (ConstrainedType deps ty) = do
176− forM_ deps $ \(className, tys) -> do
177− _ <- infer $ foldl TypeApp (TypeConstructor className) tys
178− return ()
179− k <- infer ty
180− k =?= Star
181− return Star
182−infer' _ = error "Invalid argument to infer"
183−
184−
185−
src/Language/PureScript/TypeChecker/Monad.hsdeleted−204
@@ -1,204 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.TypeChecker.Monad
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Monads for type checking and type inference and associated data types
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE GeneralizedNewtypeDeriving, FlexibleInstances, RankNTypes,
17− MultiParamTypeClasses, FlexibleContexts #-}
18−
19−module Language.PureScript.TypeChecker.Monad where
20−
21−import Language.PureScript.Types
22−import Language.PureScript.Kinds
23−import Language.PureScript.Names
24−import Language.PureScript.Declarations (canonicalizeDictionary)
25−import Language.PureScript.Environment
26−import Language.PureScript.TypeClassDictionaries
27−import Language.PureScript.Options
28−import Language.PureScript.Errors
29−
30−import Data.Maybe
31−
32−import Control.Applicative
33−import Control.Monad.State
34−import Control.Monad.Error
35−import Control.Monad.Unify
36−
37−import qualified Data.Map as M
38−
39−-- |
40−-- Temporarily bind a collection of names to values
41−--
42−bindNames :: (MonadState CheckState m) => M.Map (ModuleName, Ident) (Type, NameKind) -> m a -> m a
43−bindNames newNames action = do
44− orig <- get
45− modify $ \st -> st { checkEnv = (checkEnv st) { names = newNames `M.union` (names . checkEnv $ st) } }
46− a <- action
47− modify $ \st -> st { checkEnv = (checkEnv st) { names = names . checkEnv $ orig } }
48− return a
49−
50−-- |
51−-- Temporarily bind a collection of names to types
52−--
53−bindTypes :: (MonadState CheckState m) => M.Map (Qualified ProperName) (Kind, TypeKind) -> m a -> m a
54−bindTypes newNames action = do
55− orig <- get
56− modify $ \st -> st { checkEnv = (checkEnv st) { types = newNames `M.union` (types . checkEnv $ st) } }
57− a <- action
58− modify $ \st -> st { checkEnv = (checkEnv st) { types = types . checkEnv $ orig } }
59− return a
60−
61−-- |
62−-- Temporarily make a collection of type class dictionaries available
63−--
64−withTypeClassDictionaries :: (MonadState CheckState m) => [TypeClassDictionaryInScope] -> m a -> m a
65−withTypeClassDictionaries entries action = do
66− orig <- get
67− let mentries = M.fromList [ ((canonicalizeDictionary entry, mn), entry) | entry@TypeClassDictionaryInScope{ tcdName = Qualified mn _ } <- entries ]
68− modify $ \st -> st { checkEnv = (checkEnv st) { typeClassDictionaries = (typeClassDictionaries . checkEnv $ st) `M.union` mentries } }
69− a <- action
70− modify $ \st -> st { checkEnv = (checkEnv st) { typeClassDictionaries = typeClassDictionaries . checkEnv $ orig } }
71− return a
72−
73−-- |
74−-- Get the currently available list of type class dictionaries
75−--
76−getTypeClassDictionaries :: (Functor m, MonadState CheckState m) => m [TypeClassDictionaryInScope]
77−getTypeClassDictionaries = M.elems . typeClassDictionaries . checkEnv <$> get
78−
79−-- |
80−-- Temporarily bind a collection of names to local variables
81−--
82−bindLocalVariables :: (Functor m, MonadState CheckState m) => ModuleName -> [(Ident, Type)] -> m a -> m a
83−bindLocalVariables moduleName bindings =
84− bindNames (M.fromList $ flip map bindings $ \(name, ty) -> ((moduleName, name), (ty, LocalVariable)))
85−
86−-- |
87−-- Temporarily bind a collection of names to local type variables
88−--
89−bindLocalTypeVariables :: (Functor m, MonadState CheckState m) => ModuleName -> [(ProperName, Kind)] -> m a -> m a
90−bindLocalTypeVariables moduleName bindings =
91− bindTypes (M.fromList $ flip map bindings $ \(pn, kind) -> (Qualified (Just moduleName) pn, (kind, LocalTypeVariable)))
92−
93−-- |
94−-- Lookup the type of a value by name in the @Environment@
95−--
96−lookupVariable :: (Error e, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified Ident -> m Type
97−lookupVariable currentModule (Qualified moduleName var) = do
98− env <- getEnv
99− case M.lookup (fromMaybe currentModule moduleName, var) (names env) of
100− Nothing -> throwError . strMsg $ show var ++ " is undefined"
101− Just (ty, _) -> return ty
102−
103−-- |
104−-- Lookup the kind of a type by name in the @Environment@
105−--
106−lookupTypeVariable :: (Error e, Functor m, MonadState CheckState m, MonadError e m) => ModuleName -> Qualified ProperName -> m Kind
107−lookupTypeVariable currentModule (Qualified moduleName name) = do
108− env <- getEnv
109− case M.lookup (Qualified (Just $ fromMaybe currentModule moduleName) name) (types env) of
110− Nothing -> throwError . strMsg $ "Type variable " ++ show name ++ " is undefined"
111− Just (k, _) -> return k
112−
113−-- |
114−-- State required for type checking:
115−--
116−data CheckState = CheckState {
117− -- |
118− -- The current @Environment@
119− --
120− checkEnv :: Environment
121− -- |
122− -- The next fresh unification variable name
123− --
124− , checkNextVar :: Int
125− -- |
126− -- The next type class dictionary name
127− --
128− , checkNextDictName :: Int
129− -- |
130− -- The current module
131− --
132− , checkCurrentModule :: Maybe ModuleName
133− }
134−
135−-- |
136−-- The type checking monad, which provides the state of the type checker, and error reporting capabilities
137−--
138−newtype Check a = Check { unCheck :: StateT CheckState (Either ErrorStack) a }
139− deriving (Functor, Monad, Applicative, Alternative, MonadPlus, MonadState CheckState, MonadError ErrorStack)
140−
141−-- |
142−-- Get the current @Environment@
143−--
144−getEnv :: (Functor m, MonadState CheckState m) => m Environment
145−getEnv = checkEnv <$> get
146−
147−-- |
148−-- Update the @Environment@
149−--
150−putEnv :: (MonadState CheckState m) => Environment -> m ()
151−putEnv env = modify (\s -> s { checkEnv = env })
152−
153−-- |
154−-- Modify the @Environment@
155−--
156−modifyEnv :: (MonadState CheckState m) => (Environment -> Environment) -> m ()
157−modifyEnv f = modify (\s -> s { checkEnv = f (checkEnv s) })
158−
159−-- |
160−-- Run a computation in the Check monad, starting with an empty @Environment@
161−--
162−runCheck :: Options -> Check a -> Either String (a, Environment)
163−runCheck opts = runCheck' opts initEnvironment
164−
165−-- |
166−-- Run a computation in the Check monad, failing with an error, or succeeding with a return value and the final @Environment@.
167−--
168−runCheck' :: Options -> Environment -> Check a -> Either String (a, Environment)
169−runCheck' opts env c = stringifyErrorStack (optionsVerboseErrors opts) $ do
170− (a, s) <- flip runStateT (CheckState env 0 0 Nothing) $ unCheck c
171− return (a, checkEnv s)
172−
173−-- |
174−-- Make an assertion, failing with an error message
175−--
176−guardWith :: (MonadError e m) => e -> Bool -> m ()
177−guardWith _ True = return ()
178−guardWith e False = throwError e
179−
180−-- |
181−-- Generate new type class dictionary name
182−--
183−freshDictionaryName :: Check Int
184−freshDictionaryName = do
185− n <- checkNextDictName <$> get
186− modify $ \s -> s { checkNextDictName = succ (checkNextDictName s) }
187− return n
188−
189−-- |
190−-- Lift a computation in the @Check@ monad into the substitution monad.
191−--
192−liftCheck :: Check a -> UnifyT t Check a
193−liftCheck = UnifyT . lift
194−
195−-- |
196−-- Run a computation in the substitution monad, generating a return value and the final substitution.
197−--
198−liftUnify :: (Partial t) => UnifyT t Check a -> Check (a, Substitution t)
199−liftUnify unify = do
200− st <- get
201− (a, ust) <- runUnify (defaultUnifyState { unifyNextVar = checkNextVar st }) unify
202− modify $ \st' -> st' { checkNextVar = unifyNextVar ust }
203− return (a, unifyCurrentSubstitution ust)
204−
src/Language/PureScript/TypeChecker/Synonyms.hsdeleted−55
@@ -1,55 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.TypeChecker.Synonyms
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Functions for replacing fully applied type synonyms with the @SaturatedTypeSynonym@ data constructor
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.TypeChecker.Synonyms (
17− saturateAllTypeSynonyms
18−) where
19−
20−import Language.PureScript.Types
21−import Language.PureScript.Names
22−
23−import Control.Applicative ((<$>))
24−import Data.Maybe (fromMaybe)
25−import Control.Monad.Writer
26−import Control.Monad.Error
27−
28−-- |
29−-- Build a type substitution for a type synonym
30−--
31−buildTypeSubstitution :: Qualified ProperName -> Int -> Type -> Either String (Maybe Type)
32−buildTypeSubstitution name n = go n []
33− where
34− go :: Int -> [Type] -> Type -> Either String (Maybe Type)
35− go 0 args (TypeConstructor ctor) | name == ctor = return (Just $ SaturatedTypeSynonym ctor args)
36− go m _ (TypeConstructor ctor) | m > 0 && name == ctor = throwError $ "Partially applied type synonym " ++ show name
37− go m args (TypeApp f arg) = go (m - 1) (arg:args) f
38− go _ _ _ = return Nothing
39−
40−-- |
41−-- Replace all instances of a specific type synonym with the @SaturatedTypeSynonym@ data constructor
42−--
43−saturateTypeSynonym :: Qualified ProperName -> Int -> Type -> Either String Type
44−saturateTypeSynonym name n = everywhereOnTypesTopDownM replace
45− where
46− replace t = fromMaybe t <$> buildTypeSubstitution name n t
47−
48−-- |
49−-- Replace all type synonyms with the @SaturatedTypeSynonym@ data constructor
50−--
51−saturateAllTypeSynonyms :: [(Qualified ProperName, Int)] -> Type -> Either String Type
52−saturateAllTypeSynonyms syns d = foldM (\result (name, n) -> saturateTypeSynonym name n result) d syns
53−
54−
55−
src/Language/PureScript/TypeChecker/Types.hsdeleted−1121
@@ -1,1121 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.TypeChecker.Types
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- This module implements the type checker
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# OPTIONS_GHC -fno-warn-orphans #-}
17−{-# LANGUAGE FlexibleInstances #-}
18−{-# LANGUAGE FlexibleContexts #-}
19−{-# LANGUAGE MultiParamTypeClasses #-}
20−
21−module Language.PureScript.TypeChecker.Types (
22− typesOf
23−) where
24−
25−{-
26− The following functions represent the corresponding type checking judgements:
27−
28− infer
29− Synthesize a type for a value
30−
31− check
32− Check a value has a given type
33−
34− checkProperties
35− Check an object with a given type contains specified properties
36−
37− checkFunctionApplication
38− Check a function of a given type returns a value of another type when applied to its arguments
39−
40− subsumes
41− Check a type subsumes another type
42−-}
43−
44−import Data.List
45−import Data.Maybe (maybeToList, isNothing, isJust, fromMaybe)
46−import Data.Function (on)
47−import Data.Ord (comparing)
48−import Data.Monoid
49−
50−import Language.PureScript.Declarations
51−import Language.PureScript.Types
52−import Language.PureScript.Kinds
53−import Language.PureScript.Names
54−import Language.PureScript.TypeClassDictionaries
55−import Language.PureScript.TypeChecker.Monad
56−import Language.PureScript.TypeChecker.Kinds
57−import Language.PureScript.TypeChecker.Synonyms
58−import Language.PureScript.Pretty
59−import Language.PureScript.Environment
60−import Language.PureScript.Errors
61−import qualified Language.PureScript.Constants as C
62−
63−import Control.Monad.State
64−import Control.Monad.Error
65−import Control.Monad.Unify
66−
67−import Control.Applicative
68−import Control.Arrow (Arrow(..))
69−
70−import qualified Data.Map as M
71−import qualified Data.HashMap.Strict as H
72−
73−instance Partial Type where
74− unknown = TUnknown
75− isUnknown (TUnknown u) = Just u
76− isUnknown _ = Nothing
77− unknowns = everythingOnTypes (++) go
78− where
79− go (TUnknown u) = [u]
80− go _ = []
81− ($?) sub = everywhereOnTypes go
82− where
83− go t@(TUnknown u) = case H.lookup u (runSubstitution sub) of
84− Nothing -> t
85− Just t' -> t'
86− go other = other
87−
88−instance Unifiable Check Type where
89− (=?=) = unifyTypes
90−
91−-- |
92−-- Unify two types, updating the current substitution
93−--
94−unifyTypes :: Type -> Type -> UnifyT Type Check ()
95−unifyTypes t1 t2 = rethrow (mkErrorStack ("Error unifying type " ++ prettyPrintType t1 ++ " with type " ++ prettyPrintType t2) Nothing <>) $
96− unifyTypes' t1 t2
97− where
98− unifyTypes' (TUnknown u1) (TUnknown u2) | u1 == u2 = return ()
99− unifyTypes' (TUnknown u) t = u =:= t
100− unifyTypes' t (TUnknown u) = u =:= t
101− unifyTypes' (SaturatedTypeSynonym name args) ty = do
102− ty1 <- introduceSkolemScope <=< expandTypeSynonym name $ args
103− ty1 `unifyTypes` ty
104− unifyTypes' ty s@(SaturatedTypeSynonym _ _) = s `unifyTypes` ty
105− unifyTypes' (ForAll ident1 ty1 sc1) (ForAll ident2 ty2 sc2) =
106− case (sc1, sc2) of
107− (Just sc1', Just sc2') -> do
108− sko <- newSkolemConstant
109− let sk1 = skolemize ident1 sko sc1' ty1
110− let sk2 = skolemize ident2 sko sc2' ty2
111− sk1 `unifyTypes` sk2
112− _ -> error "Skolemized type variable was not given a scope"
113− unifyTypes' (ForAll ident ty1 (Just sc)) ty2 = do
114− sko <- newSkolemConstant
115− let sk = skolemize ident sko sc ty1
116− sk `unifyTypes` ty2
117− unifyTypes' ForAll{} _ = throwError . strMsg $ "Skolem variable scope is unspecified"
118− unifyTypes' ty f@ForAll{} = f `unifyTypes` ty
119− unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
120− unifyTypes' (TypeConstructor c1) (TypeConstructor c2) =
121− guardWith (strMsg ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".")) (c1 == c2)
122− unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
123− t3 `unifyTypes` t5
124− t4 `unifyTypes` t6
125− unifyTypes' (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = return ()
126− unifyTypes' r1@RCons{} r2 = unifyRows r1 r2
127− unifyTypes' r1 r2@RCons{} = unifyRows r1 r2
128− unifyTypes' r1@REmpty r2 = unifyRows r1 r2
129− unifyTypes' r1 r2@REmpty = unifyRows r1 r2
130− unifyTypes' t@(ConstrainedType _ _) _ = throwError . strMsg $ "Attempted to unify a constrained type " ++ prettyPrintType t ++ " with another type."
131− unifyTypes' t3 t4@(ConstrainedType _ _) = unifyTypes' t4 t3
132− unifyTypes' t3 t4 = throwError . strMsg $ "Cannot unify " ++ prettyPrintType t3 ++ " with " ++ prettyPrintType t4 ++ "."
133−
134−-- |
135−-- Unify two rows, updating the current substitution
136−--
137−-- Common labels are first identified, and unified. Remaining labels and types are unified with a
138−-- trailing row unification variable, if appropriate, otherwise leftover labels result in a unification
139−-- error.
140−--
141−unifyRows :: Type -> Type -> UnifyT Type Check ()
142−unifyRows r1 r2 =
143− let
144− (s1, r1') = rowToList r1
145− (s2, r2') = rowToList r2
146− int = [ (t1, t2) | (name, t1) <- s1, (name', t2) <- s2, name == name' ]
147− sd1 = [ (name, t1) | (name, t1) <- s1, name `notElem` map fst s2 ]
148− sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ]
149− in do
150− forM_ int (uncurry (=?=))
151− unifyRows' sd1 r1' sd2 r2'
152− where
153− unifyRows' :: [(String, Type)] -> Type -> [(String, Type)] -> Type -> UnifyT Type Check ()
154− unifyRows' [] (TUnknown u) sd r = u =:= rowFromList (sd, r)
155− unifyRows' sd r [] (TUnknown u) = u =:= rowFromList (sd, r)
156− unifyRows' ((name, ty):row) r others u@(TUnknown un) = do
157− occursCheck un ty
158− forM_ row $ \(_, t) -> occursCheck un t
159− u' <- fresh
160− u =?= RCons name ty u'
161− unifyRows' row r others u'
162− unifyRows' [] REmpty [] REmpty = return ()
163− unifyRows' [] (TypeVar v1) [] (TypeVar v2) | v1 == v2 = return ()
164− unifyRows' [] (Skolem _ s1 _) [] (Skolem _ s2 _) | s1 == s2 = return ()
165− unifyRows' sd3 r3 sd4 r4 = throwError . strMsg $ "Cannot unify (" ++ prettyPrintRow (rowFromList (sd3, r3)) ++ ") with (" ++ prettyPrintRow (rowFromList (sd4, r4)) ++ ")"
166−
167−-- |
168−-- Infer the types of multiple mutually-recursive values, and return elaborated values including
169−-- type class dictionaries and type annotations.
170−--
171−typesOf :: Maybe ModuleName -> ModuleName -> [(Ident, Value)] -> Check [(Ident, (Value, Type))]
172−typesOf mainModuleName moduleName vals = do
173− tys <- fmap tidyUp . liftUnify $ do
174− (es, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName vals
175− forM es $ \e -> do
176− triple@(_, (_, ty)) <- typeForBindingGroupElement moduleName e dict untypedDict
177− -- If --main is enabled, need to check that `main` has type Eff eff a for some eff, a
178− when (Just moduleName == mainModuleName && fst e == Ident C.main) $ do
179− [eff, a] <- replicateM 2 fresh
180− ty =?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Control", ProperName "Monad", ProperName "Eff"])) (ProperName "Eff"))) eff) a
181− return triple
182−
183− forM tys $ \(ident, (val, ty)) -> do
184− -- Replace type class dictionary placeholders with actual dictionaries
185− val' <- replaceTypeClassDictionaries moduleName val
186− -- Check skolem variables did not escape their scope
187− skolemEscapeCheck val'
188− -- Remove type synonyms placeholders, remove duplicate row fields, and replace
189− -- top-level unification variables with named type variables.
190− let val'' = overTypes (desaturateAllTypeSynonyms . setifyAll) val'
191− ty' = varIfUnknown . desaturateAllTypeSynonyms . setifyAll $ ty
192− return (ident, (val'', ty'))
193− where
194− -- Apply the substitution that was returned from runUnify to both types and (type-annotated) values
195− tidyUp (ts, sub) = map (\(i, (val, ty)) -> (i, (overTypes (sub $?) val, sub $? ty))) ts
196−
197−typeDictionaryForBindingGroup :: ModuleName -> [(Ident, Value)] -> UnifyT Type Check ([(Ident, (Value, Maybe (Type, Bool)))], M.Map (ModuleName, Ident) (Type, NameKind), [(Ident, Type)])
198−typeDictionaryForBindingGroup moduleName vals = do
199− let
200− -- Map each declaration to a name/value pair, with an optional type, if the declaration is typed
201− es = map isTyped vals
202− -- Filter the typed and untyped declarations
203− typed = filter (isJust . snd . snd) es
204− untyped = filter (isNothing . snd . snd) es
205− -- Make a map of names to typed declarations
206− typedDict = map (\(ident, (_, Just (ty, _))) -> (ident, ty)) typed
207−
208− -- Create fresh unification variables for the types of untyped declarations
209− untypedNames <- replicateM (length untyped) fresh
210−
211− let
212− -- Make a map of names to the unification variables of untyped declarations
213− untypedDict = zip (map fst untyped) untypedNames
214− -- Create the dictionary of all name/type pairs, which will be added to the environment during type checking
215− dict = M.fromList (map (\(ident, ty) -> ((moduleName, ident), (ty, LocalVariable))) $ typedDict ++ untypedDict)
216− return (es, dict, untypedDict)
217−
218−typeForBindingGroupElement :: ModuleName -> (Ident, (Value, Maybe (Type, Bool))) -> M.Map (ModuleName, Ident) (Type, NameKind) -> [(Ident, Type)] -> UnifyT Type Check (Ident, (Value, Type))
219−typeForBindingGroupElement moduleName e@(_, (val, _)) dict untypedDict = do
220− -- If the declaration is a function, it has access to other values in the binding group.
221− -- If not, the generated code might fail at runtime since those values might be undefined.
222− let dict' = if isFunction val then dict else M.empty
223− case e of
224− -- Typed declarations
225− (ident, (val', Just (ty, checkType))) -> do
226− -- Kind check
227− kind <- liftCheck $ kindOf moduleName ty
228− guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
229− -- Check the type with the new names in scope
230− ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
231− val'' <- bindNames dict' $ if checkType
232− then TypedValue True <$> check val' ty' <*> pure ty'
233− else return (TypedValue False val' ty')
234− return (ident, (val'', ty'))
235− -- Untyped declarations
236− (ident, (val', Nothing)) -> do
237− -- Infer the type with the new names in scope
238− TypedValue _ val'' ty <- bindNames dict' $ infer val'
239− ty =?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
240− return (ident, (TypedValue True val'' ty, ty))
241−
242−-- |
243−-- Check if a value introduces a function
244−--
245−isFunction :: Value -> Bool
246−isFunction (Abs _ _) = True
247−isFunction (TypedValue _ val _) = isFunction val
248−isFunction (PositionedValue _ val) = isFunction val
249−isFunction _ = False
250−
251−-- |
252−-- Check if a value contains a type annotation
253−--
254−isTyped :: (Ident, Value) -> (Ident, (Value, Maybe (Type, Bool)))
255−isTyped (name, TypedValue checkType value ty) = (name, (value, Just (ty, checkType)))
256−isTyped (name, value) = (name, (value, Nothing))
257−
258−-- |
259−-- Map a function over type annotations appearing inside a value
260−--
261−overTypes :: (Type -> Type) -> Value -> Value
262−overTypes f = let (_, f', _) = everywhereOnValues id g id in f'
263− where
264− g :: Value -> Value
265− g (TypedValue checkTy val t) = TypedValue checkTy val (f t)
266− g (TypeClassDictionary b (nm, tys) sco) = TypeClassDictionary b (nm, map f tys) sco
267− g other = other
268−
269−-- |
270−-- Replace type class dictionary placeholders with inferred type class dictionaries
271−--
272−replaceTypeClassDictionaries :: ModuleName -> Value -> Check Value
273−replaceTypeClassDictionaries mn =
274− let (_, f, _) = everywhereOnValuesTopDownM return go return
275− in f
276− where
277− go (TypeClassDictionary trySuperclasses constraint dicts) = do
278− env <- getEnv
279− entails env mn dicts constraint trySuperclasses
280− go other = return other
281−
282−-- |
283−-- A simplified representation of expressions which are used to represent type
284−-- class dictionaries at runtime, which can be compared for equality
285−--
286−data DictionaryValue
287− -- |
288− -- A dictionary which is brought into scope by a local constraint
289− --
290− = LocalDictionaryValue (Qualified Ident)
291− -- |
292− -- A dictionary which is brought into scope by an instance declaration
293− --
294− | GlobalDictionaryValue (Qualified Ident)
295− -- |
296− -- A dictionary which depends on other dictionaries
297− --
298− | DependentDictionaryValue (Qualified Ident) [DictionaryValue]
299− -- |
300− -- A subclass dictionary
301− --
302− | SubclassDictionaryValue DictionaryValue (Qualified ProperName) Integer
303− deriving (Show, Ord, Eq)
304−
305−-- |
306−-- Check that the current set of type class dictionaries entail the specified type class goal, and, if so,
307−-- return a type class dictionary reference.
308−--
309−entails :: Environment -> ModuleName -> [TypeClassDictionaryInScope] -> (Qualified ProperName, [Type]) -> Bool -> Check Value
310−entails env moduleName context = solve (sortedNubBy canonicalizeDictionary (filter filterModule context))
311− where
312− sortedNubBy :: (Ord k) => (v -> k) -> [v] -> [v]
313− sortedNubBy f vs = M.elems (M.fromList (map (f &&& id) vs))
314−
315− -- Filter out type dictionaries which are in scope in the current module
316− filterModule :: TypeClassDictionaryInScope -> Bool
317− filterModule (TypeClassDictionaryInScope { tcdName = Qualified (Just mn) _ }) | mn == moduleName = True
318− filterModule (TypeClassDictionaryInScope { tcdName = Qualified Nothing _ }) = True
319− filterModule _ = False
320−
321− solve context' (className, tys) trySuperclasses =
322− let
323− dicts = go trySuperclasses className tys
324− in case sortedNubBy dictTrace (chooseSimplestDictionaries dicts) of
325− [] -> throwError . strMsg $ "No instance found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
326− [_] -> return $ dictionaryValueToValue $ head dicts
327− _ -> throwError . strMsg $ "Overlapping instances found for " ++ show className ++ " " ++ unwords (map prettyPrintTypeAtom tys)
328− where
329− go trySuperclasses' className' tys' =
330− -- Look for regular type instances
331− [ mkDictionary (canonicalizeDictionary tcd) args
332− | tcd <- context'
333− -- Make sure the type class name matches the one we are trying to satisfy
334− , className' == tcdClassName tcd
335− -- Make sure the type unifies with the type in the type instance definition
336− , subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' (tcdInstanceTypes tcd)
337− -- Solve any necessary subgoals
338− , args <- solveSubgoals subst (tcdDependencies tcd) ] ++
339−
340− -- Look for implementations via superclasses
341− [ SubclassDictionaryValue suDict superclass index
342− | trySuperclasses'
343− , (subclassName, (args, _, implies)) <- M.toList (typeClasses env)
344− -- Try each superclass
345− , (index, (superclass, suTyArgs)) <- zip [0..] implies
346− -- Make sure the type class name matches the superclass name
347− , className' == superclass
348− -- Make sure the types unify with the types in the superclass implication
349− , subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' suTyArgs
350− -- Finally, satisfy the subclass constraint
351− , args' <- maybeToList $ mapM (flip lookup subst) args
352− , suDict <- go True subclassName args' ]
353−
354− -- Create dictionaries for subgoals which still need to be solved by calling go recursively
355− -- E.g. the goal (Show a, Show b) => Show (Either a b) can be satisfied if the current type
356− -- unifies with Either a b, and we can satisfy the subgoals Show a and Show b recursively.
357− solveSubgoals :: [(String, Type)] -> Maybe [(Qualified ProperName, [Type])] -> [Maybe [DictionaryValue]]
358− solveSubgoals _ Nothing = return Nothing
359− solveSubgoals subst (Just subgoals) = do
360− dict <- mapM (uncurry (go True) . second (map (replaceAllTypeVars subst))) subgoals
361− return $ Just dict
362− -- Make a dictionary from subgoal dictionaries by applying the correct function
363− mkDictionary :: Qualified Ident -> Maybe [DictionaryValue] -> DictionaryValue
364− mkDictionary fnName Nothing = LocalDictionaryValue fnName
365− mkDictionary fnName (Just []) = GlobalDictionaryValue fnName
366− mkDictionary fnName (Just dicts) = DependentDictionaryValue fnName dicts
367− -- Turn a DictionaryValue into a Value
368− dictionaryValueToValue :: DictionaryValue -> Value
369− dictionaryValueToValue (LocalDictionaryValue fnName) = Var fnName
370− dictionaryValueToValue (GlobalDictionaryValue fnName) = App (Var fnName) (ObjectLiteral [])
371− dictionaryValueToValue (DependentDictionaryValue fnName dicts) = foldl App (Var fnName) (map dictionaryValueToValue dicts)
372− dictionaryValueToValue (SubclassDictionaryValue dict superclassName index) =
373− App (Accessor (show superclassName ++ "_" ++ show index)
374− (Accessor C.__superclasses (dictionaryValueToValue dict)))
375− (ObjectLiteral [])
376− -- Ensure that a substitution is valid
377− verifySubstitution :: [(String, Type)] -> Maybe [(String, Type)]
378− verifySubstitution subst = do
379− let grps = groupBy ((==) `on` fst) subst
380− guard (all (pairwise (unifiesWith env) . map snd) grps)
381− return $ map head grps
382− -- Choose the simplest DictionaryValues from a list of candidates
383− -- The reason for this function is as follows:
384− -- When considering overlapping instances, we don't want to consider the same dictionary
385− -- to be an overlap of itself when obtained as a superclass of another class.
386− -- Observing that we probably don't want to select a superclass instance when an instance
387− -- is available directly, and that there is no way for a superclass instance to actually
388− -- introduce an overlap that wouldn't have been there already, we simply remove dictionaries
389− -- obtained as superclass instances if there are simpler instances available.
390− chooseSimplestDictionaries :: [DictionaryValue] -> [DictionaryValue]
391− chooseSimplestDictionaries ds = case filter isSimpleDictionaryValue ds of
392− [] -> ds
393− simple -> simple
394− isSimpleDictionaryValue SubclassDictionaryValue{} = False
395− isSimpleDictionaryValue (DependentDictionaryValue _ ds) = all isSimpleDictionaryValue ds
396− isSimpleDictionaryValue _ = True
397− -- |
398− -- Get the "trace" of a DictionaryValue - that is, remove all SubclassDictionaryValue
399− -- data constructors
400− --
401− dictTrace :: DictionaryValue -> DictionaryValue
402− dictTrace (DependentDictionaryValue fnName dicts) = DependentDictionaryValue fnName $ map dictTrace dicts
403− dictTrace (SubclassDictionaryValue dict _ _) = dictTrace dict
404− dictTrace other = other
405−
406−-- |
407−-- Check all values in a list pairwise match a predicate
408−--
409−pairwise :: (a -> a -> Bool) -> [a] -> Bool
410−pairwise _ [] = True
411−pairwise _ [_] = True
412−pairwise p (x : xs) = all (p x) xs && pairwise p xs
413−
414−-- |
415−-- Check that two types unify
416−--
417−unifiesWith :: Environment -> Type -> Type -> Bool
418−unifiesWith _ (TUnknown u1) (TUnknown u2) | u1 == u2 = True
419−unifiesWith _ (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = True
420−unifiesWith _ (TypeVar v1) (TypeVar v2) | v1 == v2 = True
421−unifiesWith _ (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = True
422−unifiesWith e (TypeApp h1 t1) (TypeApp h2 t2) = unifiesWith e h1 h2 && unifiesWith e t1 t2
423−unifiesWith e (SaturatedTypeSynonym name args) t2 =
424− case expandTypeSynonym' e name args of
425− Left _ -> False
426− Right t1 -> unifiesWith e t1 t2
427−unifiesWith e t1 t2@(SaturatedTypeSynonym _ _) = unifiesWith e t2 t1
428−unifiesWith _ _ _ = False
429−
430−-- |
431−-- Check whether the type heads of two types are equal (for the purposes of type class dictionary lookup),
432−-- and return a substitution from type variables to types which makes the type heads unify.
433−--
434−typeHeadsAreEqual :: ModuleName -> Environment -> Type -> Type -> Maybe [(String, Type)]
435−typeHeadsAreEqual _ _ (Skolem _ s1 _) (Skolem _ s2 _) | s1 == s2 = Just []
436−typeHeadsAreEqual _ _ t (TypeVar v) = Just [(v, t)]
437−typeHeadsAreEqual _ _ (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = Just []
438−typeHeadsAreEqual m e (TypeApp h1 t1) (TypeApp h2 t2) = (++) <$> typeHeadsAreEqual m e h1 h2 <*> typeHeadsAreEqual m e t1 t2
439−typeHeadsAreEqual m e (SaturatedTypeSynonym name args) t2 = case expandTypeSynonym' e name args of
440− Left _ -> Nothing
441− Right t1 -> typeHeadsAreEqual m e t1 t2
442−typeHeadsAreEqual _ _ _ _ = Nothing
443−
444−-- |
445−-- Ensure skolem variables do not escape their scope
446−--
447−skolemEscapeCheck :: Value -> Check ()
448−skolemEscapeCheck (TypedValue False _ _) = return ()
449−skolemEscapeCheck root@TypedValue{} =
450− -- Every skolem variable is created when a ForAll type is skolemized.
451− -- This determines the scope of that skolem variable, which is copied from the SkolemScope
452− -- field of the ForAll constructor.
453− -- We traverse the tree top-down, and collect any SkolemScopes introduced by ForAlls.
454− -- If a Skolem is encountered whose SkolemScope is not in the current list, we have found
455− -- an escaped skolem variable.
456− let (_, f, _, _, _) = everythingWithContextOnValues [] [] (++) def go def def def
457− in case f root of
458− [] -> return ()
459− ((binding, val) : _) -> throwError $ mkErrorStack ("Rigid/skolem type variable " ++ maybe "" (("bound by " ++) . prettyPrintValue) binding ++ " has escaped.") (Just (ValueError val))
460− where
461− def s _ = (s, [])
462−
463− go :: [(SkolemScope, Value)] -> Value -> ([(SkolemScope, Value)], [(Maybe Value, Value)])
464− go scos val@(TypedValue _ _ (ForAll _ _ (Just sco))) = ((sco, val) : scos, [])
465− go scos val@(TypedValue _ _ ty) = case collectSkolems ty \\ map fst scos of
466− (sco : _) -> (scos, [(findBindingScope sco, val)])
467− _ -> (scos, [])
468− where
469− collectSkolems :: Type -> [SkolemScope]
470− collectSkolems = nub . everythingOnTypes (++) collect
471− where
472− collect (Skolem _ _ scope) = [scope]
473− collect _ = []
474− go scos _ = (scos, [])
475− findBindingScope :: SkolemScope -> Maybe Value
476− findBindingScope sco =
477− let (_, f, _, _, _) = everythingOnValues mappend (const mempty) go' (const mempty) (const mempty) (const mempty)
478− in getFirst $ f root
479− where
480− go' val@(TypedValue _ _ (ForAll _ _ (Just sco'))) | sco == sco' = First (Just val)
481− go' _ = mempty
482−skolemEscapeCheck val = throwError $ mkErrorStack "Untyped value passed to skolemEscapeCheck" (Just (ValueError val))
483−
484−-- |
485−-- Ensure a row contains no duplicate labels
486−--
487−setify :: Type -> Type
488−setify = rowFromList . first (M.toList . M.fromList) . rowToList
489−
490−-- |
491−-- \"Setify\" all rows occuring inside a value
492−--
493−setifyAll :: Type -> Type
494−setifyAll = everywhereOnTypes setify
495−
496−-- |
497−-- Replace outermost unsolved unification variables with named type variables
498−--
499−varIfUnknown :: Type -> Type
500−varIfUnknown ty =
501− let unks = nub $ unknowns ty
502− toName = (:) 't' . show
503− ty' = everywhereOnTypes typeToVar ty
504− typeToVar :: Type -> Type
505− typeToVar (TUnknown u) = TypeVar (toName u)
506− typeToVar t = t
507− in mkForAll (sort . map toName $ unks) ty'
508−
509−-- |
510−-- Remove any ForAlls and ConstrainedType constructors in a type by introducing new unknowns
511−-- or TypeClassDictionary values.
512−--
513−-- This is necessary during type checking to avoid unifying a polymorphic type with a
514−-- unification variable.
515−--
516−instantiatePolyTypeWithUnknowns :: Value -> Type -> UnifyT Type Check (Value, Type)
517−instantiatePolyTypeWithUnknowns val (ForAll ident ty _) = do
518− ty' <- replaceVarWithUnknown ident ty
519− instantiatePolyTypeWithUnknowns val ty'
520−instantiatePolyTypeWithUnknowns val (ConstrainedType constraints ty) = do
521− dicts <- getTypeClassDictionaries
522− (_, ty') <- instantiatePolyTypeWithUnknowns (error "Types under a constraint cannot themselves be constrained") ty
523− return (foldl App val (map (flip (TypeClassDictionary True) dicts) constraints), ty')
524−instantiatePolyTypeWithUnknowns val ty = return (val, ty)
525−
526−-- |
527−-- Replace a single type variable with a new unification variable
528−--
529−replaceVarWithUnknown :: String -> Type -> UnifyT Type Check Type
530−replaceVarWithUnknown ident ty = do
531− tu <- fresh
532− return $ replaceTypeVars ident tu ty
533−
534−-- |
535−-- Replace fully applied type synonyms with the @SaturatedTypeSynonym@ data constructor, which helps generate
536−-- better error messages during unification.
537−--
538−replaceAllTypeSynonyms' :: Environment -> Type -> Either String Type
539−replaceAllTypeSynonyms' env d =
540− let
541− syns = map (\(name, (args, _)) -> (name, length args)) . M.toList $ typeSynonyms env
542− in
543− saturateAllTypeSynonyms syns d
544−
545−replaceAllTypeSynonyms :: (Error e, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
546−replaceAllTypeSynonyms d = do
547− env <- getEnv
548− either (throwError . strMsg) return $ replaceAllTypeSynonyms' env d
549−
550−-- |
551−-- \"Desaturate\" @SaturatedTypeSynonym@s
552−--
553−desaturateAllTypeSynonyms :: Type -> Type
554−desaturateAllTypeSynonyms = everywhereOnTypes replaceSaturatedTypeSynonym
555− where
556− replaceSaturatedTypeSynonym (SaturatedTypeSynonym name args) = foldl TypeApp (TypeConstructor name) args
557− replaceSaturatedTypeSynonym t = t
558−
559−-- |
560−-- Replace a type synonym and its arguments with the aliased type
561−--
562−expandTypeSynonym' :: Environment -> Qualified ProperName -> [Type] -> Either String Type
563−expandTypeSynonym' env name args =
564− case M.lookup name (typeSynonyms env) of
565− Just (synArgs, body) -> do
566− let repl = replaceAllTypeVars (zip synArgs args) body
567− replaceAllTypeSynonyms' env repl
568− Nothing -> error "Type synonym was not defined"
569−
570−expandTypeSynonym :: (Error e, Functor m, Monad m, MonadState CheckState m, MonadError e m) => Qualified ProperName -> [Type] -> m Type
571−expandTypeSynonym name args = do
572− env <- getEnv
573− either (throwError . strMsg) return $ expandTypeSynonym' env name args
574−
575−expandAllTypeSynonyms :: (Error e, Functor m, Applicative m, Monad m, MonadState CheckState m, MonadError e m) => Type -> m Type
576−expandAllTypeSynonyms = everywhereOnTypesTopDownM go
577− where
578− go (SaturatedTypeSynonym name args) = expandTypeSynonym name args
579− go other = return other
580−
581−-- |
582−-- Ensure a set of property names and value does not contain duplicate labels
583−--
584−ensureNoDuplicateProperties :: (Error e, MonadError e m) => [(String, Value)] -> m ()
585−ensureNoDuplicateProperties ps = guardWith (strMsg "Duplicate property names") $ length (nub . map fst $ ps) == length ps
586−
587−-- |
588−-- Infer a type for a value, rethrowing any error to provide a more useful error message
589−--
590−infer :: Value -> UnifyT Type Check Value
591−infer val = rethrow (mkErrorStack "Error inferring type of value" (Just (ValueError val)) <>) $ infer' val
592−
593−-- |
594−-- Infer a type for a value
595−--
596−infer' :: Value -> UnifyT Type Check Value
597−infer' v@(NumericLiteral _) = return $ TypedValue True v tyNumber
598−infer' v@(StringLiteral _) = return $ TypedValue True v tyString
599−infer' v@(BooleanLiteral _) = return $ TypedValue True v tyBoolean
600−infer' (ArrayLiteral vals) = do
601− ts <- mapM infer vals
602− els <- fresh
603− forM_ ts $ \(TypedValue _ _ t) -> els =?= t
604− return $ TypedValue True (ArrayLiteral ts) (TypeApp tyArray els)
605−infer' (ObjectLiteral ps) = do
606− ensureNoDuplicateProperties ps
607− ts <- mapM (infer . snd) ps
608− let fields = zipWith (\name (TypedValue _ _ t) -> (name, t)) (map fst ps) ts
609− ty = TypeApp tyObject $ rowFromList (fields, REmpty)
610− return $ TypedValue True (ObjectLiteral (zip (map fst ps) ts)) ty
611−infer' (ObjectUpdate o ps) = do
612− ensureNoDuplicateProperties ps
613− row <- fresh
614− newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> mapM (infer . snd) ps
615− let newTys = map (\(name, TypedValue _ _ ty) -> (name, ty)) newVals
616− oldTys <- zip (map fst ps) <$> replicateM (length ps) fresh
617− let oldTy = TypeApp tyObject $ rowFromList (oldTys, row)
618− o' <- TypedValue True <$> check o oldTy <*> pure oldTy
619− return $ TypedValue True (ObjectUpdate o' newVals) $ TypeApp tyObject $ rowFromList (newTys, row)
620−infer' (Accessor prop val) = do
621− typed@(TypedValue _ _ objTy) <- infer val
622− propTy <- inferProperty objTy prop
623− case propTy of
624− Nothing -> do
625− field <- fresh
626− rest <- fresh
627− _ <- subsumes Nothing objTy (TypeApp tyObject (RCons prop field rest))
628− return $ TypedValue True (Accessor prop typed) field
629− Just ty -> return $ TypedValue True (Accessor prop typed) ty
630−infer' (Abs (Left arg) ret) = do
631− ty <- fresh
632− Just moduleName <- checkCurrentModule <$> get
633− bindLocalVariables moduleName [(arg, ty)] $ do
634− body@(TypedValue _ _ bodyTy) <- infer' ret
635− return $ TypedValue True (Abs (Left arg) body) $ function ty bodyTy
636−infer' (Abs (Right _) _) = error "Binder was not desugared"
637−infer' (App f arg) = do
638− f'@(TypedValue _ _ ft) <- infer f
639− (ret, app) <- checkFunctionApplication f' ft arg Nothing
640− return $ TypedValue True app ret
641−infer' (Var var) = do
642− Just moduleName <- checkCurrentModule <$> get
643− ty <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< lookupVariable moduleName $ var
644− case ty of
645− ConstrainedType constraints ty' -> do
646− dicts <- getTypeClassDictionaries
647− return $ TypedValue True (foldl App (Var var) (map (flip (TypeClassDictionary True) dicts) constraints)) ty'
648− _ -> return $ TypedValue True (Var var) ty
649−infer' v@(Constructor c) = do
650− env <- getEnv
651− case M.lookup c (dataConstructors env) of
652− Nothing -> throwError . strMsg $ "Constructor " ++ show c ++ " is undefined"
653− Just (_, ty) -> do ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
654− return $ TypedValue True v ty'
655−infer' (Case vals binders) = do
656− ts <- mapM infer vals
657− ret <- fresh
658− binders' <- checkBinders (map (\(TypedValue _ _ t) -> t) ts) ret binders
659− return $ TypedValue True (Case ts binders') ret
660−infer' (IfThenElse cond th el) = do
661− cond' <- check cond tyBoolean
662− v2@(TypedValue _ _ t2) <- infer th
663− v3@(TypedValue _ _ t3) <- infer el
664− t2 =?= t3
665− return $ TypedValue True (IfThenElse cond' v2 v3) t2
666−infer' (Let ds val) = do
667− (ds', val'@(TypedValue _ _ valTy)) <- inferLetBinding [] ds val infer
668− return $ TypedValue True (Let ds' val') valTy
669−infer' (SuperClassDictionary className tys) = do
670− dicts <- getTypeClassDictionaries
671− return $ TypeClassDictionary False (className, tys) dicts
672−infer' (TypedValue checkType val ty) = do
673− Just moduleName <- checkCurrentModule <$> get
674− kind <- liftCheck $ kindOf moduleName ty
675− guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
676− ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
677− val' <- if checkType then check val ty' else return val
678− return $ TypedValue True val' ty'
679−infer' (PositionedValue pos val) = rethrowWithPosition pos $ infer' val
680−infer' _ = error "Invalid argument to infer"
681−
682−inferLetBinding :: [Declaration] -> [Declaration] -> Value -> (Value -> UnifyT Type Check Value) -> UnifyT Type Check ([Declaration], Value)
683−inferLetBinding seen [] ret j = (,) seen <$> j ret
684−inferLetBinding seen (ValueDeclaration ident nameKind [] Nothing tv@(TypedValue checkType val ty) : rest) ret j = do
685− Just moduleName <- checkCurrentModule <$> get
686− kind <- liftCheck $ kindOf moduleName ty
687− guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
688− let dict = if isFunction val then M.singleton (moduleName, ident) (ty, nameKind) else M.empty
689− ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
690− TypedValue _ val' ty'' <- if checkType then bindNames dict (check val ty') else return tv
691− bindNames (M.singleton (moduleName, ident) (ty'', nameKind)) $ inferLetBinding (seen ++ [ValueDeclaration ident nameKind [] Nothing (TypedValue checkType val' ty'')]) rest ret j
692−inferLetBinding seen (ValueDeclaration ident nameKind [] Nothing val : rest) ret j = do
693− valTy <- fresh
694− Just moduleName <- checkCurrentModule <$> get
695− let dict = if isFunction val then M.singleton (moduleName, ident) (valTy, nameKind) else M.empty
696− TypedValue _ val' valTy' <- bindNames dict $ infer val
697− valTy =?= valTy'
698− bindNames (M.singleton (moduleName, ident) (valTy', nameKind)) $ inferLetBinding (seen ++ [ValueDeclaration ident nameKind [] Nothing val']) rest ret j
699−inferLetBinding seen (BindingGroupDeclaration ds : rest) ret j = do
700− Just moduleName <- checkCurrentModule <$> get
701− (es, dict, untypedDict) <- typeDictionaryForBindingGroup moduleName (map (\(i, _, v) -> (i, v)) ds)
702− ds' <- forM es $ \e -> do
703− (ident, (val', _)) <- typeForBindingGroupElement moduleName e dict untypedDict
704− return $ (ident, LocalVariable, val')
705− bindNames dict $ inferLetBinding (seen ++ [BindingGroupDeclaration ds']) rest ret j
706−inferLetBinding seen (PositionedDeclaration pos d : ds) ret j = rethrowWithPosition pos $ do
707− ((d' : ds'), val') <- inferLetBinding seen (d : ds) ret j
708− return (PositionedDeclaration pos d' : ds', val')
709−inferLetBinding _ _ _ _ = error "Invalid argument to inferLetBinding"
710−
711−-- |
712−-- Infer the type of a property inside a record with a given type
713−--
714−inferProperty :: Type -> String -> UnifyT Type Check (Maybe Type)
715−inferProperty (TypeApp obj row) prop | obj == tyObject = do
716− let (props, _) = rowToList row
717− return $ lookup prop props
718−inferProperty (SaturatedTypeSynonym name args) prop = do
719− replaced <- introduceSkolemScope <=< expandTypeSynonym name $ args
720− inferProperty replaced prop
721−inferProperty (ForAll ident ty _) prop = do
722− replaced <- replaceVarWithUnknown ident ty
723− inferProperty replaced prop
724−inferProperty _ _ = return Nothing
725−
726−-- |
727−-- Infer the types of variables brought into scope by a binder
728−--
729−inferBinder :: Type -> Binder -> UnifyT Type Check (M.Map Ident Type)
730−inferBinder _ NullBinder = return M.empty
731−inferBinder val (StringBinder _) = val =?= tyString >> return M.empty
732−inferBinder val (NumberBinder _) = val =?= tyNumber >> return M.empty
733−inferBinder val (BooleanBinder _) = val =?= tyBoolean >> return M.empty
734−inferBinder val (VarBinder name) = return $ M.singleton name val
735−inferBinder val (ConstructorBinder ctor binders) = do
736− env <- getEnv
737− case M.lookup ctor (dataConstructors env) of
738− Just (_, ty) -> do
739− (_, fn) <- instantiatePolyTypeWithUnknowns (error "Data constructor types cannot contain constraints") ty
740− fn' <- replaceAllTypeSynonyms fn
741− go binders fn'
742− where
743− go [] ty' = do
744− _ <- subsumes Nothing val ty'
745− return M.empty
746− go (binder : binders') (TypeApp (TypeApp t obj) ret) | t == tyFunction =
747− M.union <$> inferBinder obj binder <*> go binders' ret
748− go _ _ = throwError . strMsg $ "Wrong number of arguments to constructor " ++ show ctor
749− _ -> throwError . strMsg $ "Constructor " ++ show ctor ++ " is not defined"
750−inferBinder val (ObjectBinder props) = do
751− row <- fresh
752− rest <- fresh
753− m1 <- inferRowProperties row rest props
754− val =?= TypeApp tyObject row
755− return m1
756− where
757− inferRowProperties :: Type -> Type -> [(String, Binder)] -> UnifyT Type Check (M.Map Ident Type)
758− inferRowProperties nrow row [] = nrow =?= row >> return M.empty
759− inferRowProperties nrow row ((name, binder):binders) = do
760− propTy <- fresh
761− m1 <- inferBinder propTy binder
762− m2 <- inferRowProperties nrow (RCons name propTy row) binders
763− return $ m1 `M.union` m2
764−inferBinder val (ArrayBinder binders) = do
765− el <- fresh
766− m1 <- M.unions <$> mapM (inferBinder el) binders
767− val =?= TypeApp tyArray el
768− return m1
769−inferBinder val (ConsBinder headBinder tailBinder) = do
770− el <- fresh
771− m1 <- inferBinder el headBinder
772− m2 <- inferBinder val tailBinder
773− val =?= TypeApp tyArray el
774− return $ m1 `M.union` m2
775−inferBinder val (NamedBinder name binder) = do
776− m <- inferBinder val binder
777− return $ M.insert name val m
778−inferBinder val (PositionedBinder pos binder) =
779− rethrowWithPosition pos $ inferBinder val binder
780−
781−-- |
782−-- Check the types of the return values in a set of binders in a case statement
783−--
784−checkBinders :: [Type] -> Type -> [CaseAlternative] -> UnifyT Type Check [CaseAlternative]
785−checkBinders _ _ [] = return []
786−checkBinders nvals ret (CaseAlternative binders grd val : bs) = do
787− Just moduleName <- checkCurrentModule <$> get
788− m1 <- M.unions <$> zipWithM inferBinder nvals binders
789− r <- bindLocalVariables moduleName (M.toList m1) $ do
790− val' <- TypedValue True <$> check val ret <*> pure ret
791− case grd of
792− Nothing -> return $ CaseAlternative binders Nothing val'
793− Just g -> do
794− g' <- check g tyBoolean
795− return $ CaseAlternative binders (Just g') val'
796− rs <- checkBinders nvals ret bs
797− return $ r : rs
798−
799−-- |
800−-- Generate a new skolem constant
801−--
802−newSkolemConstant :: UnifyT Type Check Int
803−newSkolemConstant = fresh'
804−
805−-- |
806−-- Generate a new skolem scope
807−--
808−newSkolemScope :: UnifyT Type Check SkolemScope
809−newSkolemScope = SkolemScope <$> fresh'
810−
811−-- |
812−-- Skolemize a type variable by replacing its instances with fresh skolem constants
813−--
814−skolemize :: String -> Int -> SkolemScope -> Type -> Type
815−skolemize ident sko scope = replaceTypeVars ident (Skolem ident sko scope)
816−
817−-- |
818−-- This function has one purpose - to skolemize type variables appearing in a
819−-- SuperClassDictionary placeholder. These type variables are somewhat unique since they are the
820−-- only example of scoped type variables.
821−--
822−skolemizeTypesInValue :: String -> Int -> SkolemScope -> Value -> Value
823−skolemizeTypesInValue ident sko scope = let (_, f, _) = everywhereOnValues id go id in f
824− where
825− go (SuperClassDictionary c ts) = SuperClassDictionary c (map (skolemize ident sko scope) ts)
826− go other = other
827−
828−-- |
829−-- Introduce skolem scope at every occurence of a ForAll
830−--
831−introduceSkolemScope :: Type -> UnifyT Type Check Type
832−introduceSkolemScope = everywhereOnTypesM go
833− where
834− go (ForAll ident ty Nothing) = ForAll ident ty <$> (Just <$> newSkolemScope)
835− go other = return other
836−
837−-- |
838−-- Check the type of a value, rethrowing errors to provide a better error message
839−--
840−check :: Value -> Type -> UnifyT Type Check Value
841−check val ty = rethrow (mkErrorStack errorMessage (Just (ValueError val)) <>) $ check' val ty
842− where
843− errorMessage =
844− "Error checking type of term " ++
845− prettyPrintValue val ++
846− " against type " ++
847− prettyPrintType ty
848−
849−-- |
850−-- Check the type of a value
851−--
852−check' :: Value -> Type -> UnifyT Type Check Value
853−check' val (ForAll ident ty _) = do
854− scope <- newSkolemScope
855− sko <- newSkolemConstant
856− let sk = skolemize ident sko scope ty
857− let skVal = skolemizeTypesInValue ident sko scope val
858− val' <- check skVal sk
859− return $ TypedValue True val' (ForAll ident ty (Just scope))
860−check' val t@(ConstrainedType constraints ty) = do
861− dictNames <- forM constraints $ \(Qualified _ (ProperName className), _) -> do
862− n <- liftCheck freshDictionaryName
863− return $ Ident $ "__dict_" ++ className ++ "_" ++ show n
864− val' <- withTypeClassDictionaries (zipWith (\name (className, instanceTy) ->
865− TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular) (map (Qualified Nothing) dictNames)
866− constraints) $ check val ty
867− return $ TypedValue True (foldr (Abs . Left) val' dictNames) t
868−check' val (SaturatedTypeSynonym name args) = do
869− ty <- introduceSkolemScope <=< expandTypeSynonym name $ args
870− check val ty
871−check' val u@(TUnknown _) = do
872− val'@(TypedValue _ _ ty) <- infer val
873− -- Don't unify an unknown with an inferred polytype
874− (val'', ty') <- instantiatePolyTypeWithUnknowns val' ty
875− ty' =?= u
876− return $ TypedValue True val'' ty'
877−check' v@(NumericLiteral _) t | t == tyNumber =
878− return $ TypedValue True v t
879−check' v@(StringLiteral _) t | t == tyString =
880− return $ TypedValue True v t
881−check' v@(BooleanLiteral _) t | t == tyBoolean =
882− return $ TypedValue True v t
883−check' (ArrayLiteral vals) t@(TypeApp a ty) = do
884− a =?= tyArray
885− array <- ArrayLiteral <$> forM vals (`check` ty)
886− return $ TypedValue True array t
887−check' (Abs (Left arg) ret) ty@(TypeApp (TypeApp t argTy) retTy) | t == tyFunction = do
888− Just moduleName <- checkCurrentModule <$> get
889− ret' <- bindLocalVariables moduleName [(arg, argTy)] $ check ret retTy
890− return $ TypedValue True (Abs (Left arg) ret') ty
891−check' (Abs (Right _) _) _ = error "Binder was not desugared"
892−check' (App f arg) ret = do
893− f'@(TypedValue _ _ ft) <- infer f
894− (_, app) <- checkFunctionApplication f' ft arg (Just ret)
895− return $ TypedValue True app ret
896−check' v@(Var var) ty = do
897− Just moduleName <- checkCurrentModule <$> get
898− repl <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< lookupVariable moduleName $ var
899− ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty
900− v' <- subsumes (Just v) repl ty'
901− case v' of
902− Nothing -> throwError . strMsg $ "Unable to check type subsumption"
903− Just v'' -> return $ TypedValue True v'' ty'
904−check' (SuperClassDictionary className tys) _ = do
905− {-
906− -- Here, we replace a placeholder for a superclass dictionary with a regular
907− -- TypeClassDictionary placeholder. The reason we do this is that it is necessary to have the
908− -- correct super instance dictionaries in scope, and these are not available when the type class
909− -- declaration gets desugared.
910− --
911− -- Note also that the first argument to TypeClassDictionary is False, meaning we _do not_ want
912− -- to consider superclass instances when searching for this dictionary - doing so might lead
913− -- to traversing a cycle in the instance graph.
914− -}
915− dicts <- getTypeClassDictionaries
916− return $ TypeClassDictionary False (className, tys) dicts
917−check' (TypedValue checkType val ty1) ty2 = do
918− Just moduleName <- checkCurrentModule <$> get
919− kind <- liftCheck $ kindOf moduleName ty1
920− guardWith (strMsg $ "Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
921− ty1' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
922− val' <- subsumes (Just val) ty1' ty2
923− case val' of
924− Nothing -> throwError . strMsg $ "Unable to check type subsumption"
925− Just val'' -> do
926− val''' <- if checkType then check val'' ty1' else return val''
927− return $ TypedValue checkType (TypedValue True val''' ty1) ty2
928−check' (Case vals binders) ret = do
929− vals' <- mapM infer vals
930− let ts = map (\(TypedValue _ _ t) -> t) vals'
931− binders' <- checkBinders ts ret binders
932− return $ TypedValue True (Case vals' binders') ret
933−check' (IfThenElse cond th el) ty = do
934− cond' <- check cond tyBoolean
935− th' <- check th ty
936− el' <- check el ty
937− return $ TypedValue True (IfThenElse cond' th' el') ty
938−check' (ObjectLiteral ps) t@(TypeApp obj row) | obj == tyObject = do
939− ensureNoDuplicateProperties ps
940− ps' <- checkProperties ps row False
941− return $ TypedValue True (ObjectLiteral ps') t
942−check' (ObjectUpdate obj ps) t@(TypeApp o row) | o == tyObject = do
943− ensureNoDuplicateProperties ps
944− us <- zip (map fst ps) <$> replicateM (length ps) fresh
945− let (propsToCheck, rest) = rowToList row
946− propsToRemove = map fst ps
947− remainingProps = filter (\(p, _) -> p `notElem` propsToRemove) propsToCheck
948− obj' <- check obj (TypeApp tyObject (rowFromList (us ++ remainingProps, rest)))
949− ps' <- checkProperties ps row True
950− return $ TypedValue True (ObjectUpdate obj' ps') t
951−check' (Accessor prop val) ty = do
952− rest <- fresh
953− val' <- check val (TypeApp tyObject (RCons prop ty rest))
954− return $ TypedValue True (Accessor prop val') ty
955−check' (Constructor c) ty = do
956− env <- getEnv
957− case M.lookup c (dataConstructors env) of
958− Nothing -> throwError . strMsg $ "Constructor " ++ show c ++ " is undefined"
959− Just (_, ty1) -> do
960− repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1
961− _ <- subsumes Nothing repl ty
962− return $ TypedValue True (Constructor c) ty
963−check' (Let ds val) ty = do
964− (ds', val') <- inferLetBinding [] ds val (flip check ty)
965− return $ TypedValue True (Let ds' val') ty
966−check' val ty | containsTypeSynonyms ty = do
967− ty' <- introduceSkolemScope <=< expandAllTypeSynonyms $ ty
968− check val ty'
969−check' (PositionedValue pos val) ty =
970− rethrowWithPosition pos $ check val ty
971−check' val ty = throwError $ mkErrorStack ("Value does not have type " ++ prettyPrintType ty) (Just (ValueError val))
972−
973−containsTypeSynonyms :: Type -> Bool
974−containsTypeSynonyms = everythingOnTypes (||) go where
975− go (SaturatedTypeSynonym _ _) = True
976− go _ = False
977−
978−-- |
979−-- Check the type of a collection of named record fields
980−--
981−-- The @lax@ parameter controls whether or not every record member has to be provided. For object updates, this is not the case.
982−--
983−checkProperties :: [(String, Value)] -> Type -> Bool -> UnifyT Type Check [(String, Value)]
984−checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
985− go [] [] REmpty = return []
986− go [] [] u@(TUnknown _) = do u =?= REmpty
987− return []
988− go [] [] (Skolem _ _ _) | lax = return []
989− go [] ((p, _): _) _ | lax = return []
990− | otherwise = throwError $ mkErrorStack ("Object does not have property " ++ p) (Just (ValueError (ObjectLiteral ps)))
991− go ((p,_):_) [] REmpty = throwError $ mkErrorStack ("Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row) (Just (ValueError (ObjectLiteral ps)))
992− go ((p,v):ps') [] u@(TUnknown _) = do
993− v'@(TypedValue _ _ ty) <- infer v
994− rest <- fresh
995− u =?= RCons p ty rest
996− ps'' <- go ps' [] rest
997− return $ (p, v') : ps''
998− go ((p,v):ps') ts r =
999− case lookup p ts of
1000− Nothing -> do
1001− v'@(TypedValue _ _ ty) <- infer v
1002− rest <- fresh
1003− r =?= RCons p ty rest
1004− ps'' <- go ps' ts rest
1005− return $ (p, v') : ps''
1006− Just ty -> do
1007− v' <- check v ty
1008− ps'' <- go ps' (delete (p, ty) ts) r
1009− return $ (p, v') : ps''
1010− go _ _ _ = throwError $ mkErrorStack ("Object does not have type " ++ prettyPrintType (TypeApp tyObject row)) (Just (ValueError (ObjectLiteral ps)))
1011−
1012−-- |
1013−-- Check the type of a function application, rethrowing errors to provide a better error message
1014−--
1015−checkFunctionApplication :: Value -> Type -> Value -> Maybe Type -> UnifyT Type Check (Type, Value)
1016−checkFunctionApplication fn fnTy arg ret = rethrow (mkErrorStack errorMessage (Just (ValueError fn)) <>) $ checkFunctionApplication' fn fnTy arg ret
1017− where
1018− errorMessage = "Error applying function of type "
1019− ++ prettyPrintType fnTy
1020− ++ " to argument " ++ prettyPrintValue arg
1021−
1022−-- |
1023−-- Check the type of a function application
1024−--
1025−checkFunctionApplication' :: Value -> Type -> Value -> Maybe Type -> UnifyT Type Check (Type, Value)
1026−checkFunctionApplication' fn (TypeApp (TypeApp tyFunction' argTy) retTy) arg ret = do
1027− tyFunction' =?= tyFunction
1028− _ <- maybe (return Nothing) (subsumes Nothing retTy) ret
1029− subst <- unifyCurrentSubstitution <$> UnifyT get
1030− arg' <- check arg (subst $? argTy)
1031− return (retTy, App fn arg')
1032−checkFunctionApplication' fn (ForAll ident ty _) arg ret = do
1033− replaced <- replaceVarWithUnknown ident ty
1034− checkFunctionApplication fn replaced arg ret
1035−checkFunctionApplication' fn u@(TUnknown _) arg ret = do
1036− arg' <- do
1037− TypedValue _ arg' t <- infer arg
1038− (arg'', t') <- instantiatePolyTypeWithUnknowns arg' t
1039− return $ TypedValue True arg'' t'
1040− let ty = (\(TypedValue _ _ t) -> t) arg'
1041− ret' <- maybe fresh return ret
1042− u =?= function ty ret'
1043− return (ret', App fn arg')
1044−checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do
1045− ty <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
1046− checkFunctionApplication fn ty arg ret
1047−checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
1048− dicts <- getTypeClassDictionaries
1049− checkFunctionApplication' (foldl App fn (map (flip (TypeClassDictionary True) dicts) constraints)) fnTy arg ret
1050−checkFunctionApplication' _ fnTy arg _ = throwError . strMsg $ "Cannot apply a function of type "
1051− ++ prettyPrintType fnTy
1052− ++ " to argument " ++ prettyPrintValue arg
1053−
1054−-- |
1055−-- Check whether one type subsumes another, rethrowing errors to provide a better error message
1056−--
1057−subsumes :: Maybe Value -> Type -> Type -> UnifyT Type Check (Maybe Value)
1058−subsumes val ty1 ty2 = rethrow (mkErrorStack errorMessage (ValueError <$> val) <>) $ subsumes' val ty1 ty2
1059− where
1060− errorMessage = "Error checking that type "
1061− ++ prettyPrintType ty1
1062− ++ " subsumes type "
1063− ++ prettyPrintType ty2
1064−
1065−-- |
1066−-- Check whether one type subsumes another
1067−--
1068−subsumes' :: Maybe Value -> Type -> Type -> UnifyT Type Check (Maybe Value)
1069−subsumes' val (ForAll ident ty1 _) ty2 = do
1070− replaced <- replaceVarWithUnknown ident ty1
1071− subsumes val replaced ty2
1072−subsumes' val ty1 (ForAll ident ty2 sco) =
1073− case sco of
1074− Just sco' -> do
1075− sko <- newSkolemConstant
1076− let sk = skolemize ident sko sco' ty2
1077− subsumes val ty1 sk
1078− Nothing -> throwError . strMsg $ "Skolem variable scope is unspecified"
1079−subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do
1080− _ <- subsumes Nothing arg2 arg1
1081− _ <- subsumes Nothing ret1 ret2
1082− return val
1083−subsumes' val (SaturatedTypeSynonym name tyArgs) ty2 = do
1084− ty1 <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
1085− subsumes val ty1 ty2
1086−subsumes' val ty1 (SaturatedTypeSynonym name tyArgs) = do
1087− ty2 <- introduceSkolemScope <=< expandTypeSynonym name $ tyArgs
1088− subsumes val ty1 ty2
1089−subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
1090− dicts <- getTypeClassDictionaries
1091− _ <- subsumes' Nothing ty1 ty2
1092− return . Just $ foldl App val (map (flip (TypeClassDictionary True) dicts) constraints)
1093−subsumes' val (TypeApp f1 r1) (TypeApp f2 r2) | f1 == tyObject && f2 == tyObject = do
1094− let
1095− (ts1, r1') = rowToList r1
1096− (ts2, r2') = rowToList r2
1097− ts1' = sortBy (comparing fst) ts1
1098− ts2' = sortBy (comparing fst) ts2
1099− go ts1' ts2' r1' r2'
1100− return val
1101− where
1102− go [] ts2 r1' r2' = r1' =?= rowFromList (ts2, r2')
1103− go ts1 [] r1' r2' = r2' =?= rowFromList (ts1, r1')
1104− go ((p1, ty1) : ts1) ((p2, ty2) : ts2) r1' r2'
1105− | p1 == p2 = do _ <- subsumes Nothing ty1 ty2
1106− go ts1 ts2 r1' r2'
1107− | p1 < p2 = do rest <- fresh
1108− r2' =?= RCons p1 ty1 rest
1109− go ts1 ((p2, ty2) : ts2) r1' rest
1110− | otherwise = do rest <- fresh
1111− r1' =?= RCons p2 ty2 rest
1112− go ((p1, ty1) : ts1) ts2 rest r2'
1113−subsumes' val ty1 ty2@(TypeApp obj _) | obj == tyObject = subsumes val ty2 ty1
1114−subsumes' val ty1 ty2 = do
1115− ty1 =?= ty2
1116− return val
1117−
1118−
1119−
1120−
1121−
src/Language/PureScript/TypeClassDictionaries.hsdeleted−62
@@ -1,62 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.TypeClassDictionaries
4−-- Copyright : (c) 2014 Phil Freeman
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−{-# LANGUAGE DeriveDataTypeable #-}
16−
17−module Language.PureScript.TypeClassDictionaries where
18−
19−import Data.Data
20−
21−import Language.PureScript.Names
22−import Language.PureScript.Types
23−
24−-- |
25−-- Data representing a type class dictionary which is in scope
26−--
27−data TypeClassDictionaryInScope
28− = TypeClassDictionaryInScope {
29− -- |
30− -- The identifier with which the dictionary can be accessed at runtime
31− --
32− tcdName :: Qualified Ident
33− -- |
34− -- The name of the type class to which this type class instance applies
35− --
36− , tcdClassName :: Qualified ProperName
37− -- |
38− -- The types to which this type class instance applies
39− --
40− , tcdInstanceTypes :: [Type]
41− -- |
42− -- Type class dependencies which must be satisfied to construct this dictionary
43− --
44− , tcdDependencies :: Maybe [(Qualified ProperName, [Type])]
45− -- |
46− -- The type of this dictionary
47− --
48− , tcdType :: TypeClassDictionaryType
49− } deriving (Show, Data, Typeable)
50−
51−-- |
52−-- The type of a type class dictionary
53−--
54−data TypeClassDictionaryType
55− -- |
56− -- A regular type class dictionary
57− --
58− = TCDRegular
59− -- |
60− -- A type class dictionary which is an alias for an imported dictionary from another module
61− --
62− | TCDAlias (Qualified Ident) deriving (Show, Eq, Data, Typeable)
src/Language/PureScript/Types.hsdeleted−276
@@ -1,276 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Types
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−-- Data types for types
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE DeriveDataTypeable #-}
17−
18−module Language.PureScript.Types where
19−
20−import Data.Data
21−import Data.List (nub)
22−
23−import Control.Monad.Unify
24−import Control.Arrow (second)
25−import Control.Applicative
26−import Control.Monad ((<=<))
27−
28−import Language.PureScript.Names
29−import Language.PureScript.Traversals
30−
31−-- |
32−-- An identifier for the scope of a skolem variable
33−--
34−newtype SkolemScope = SkolemScope { runSkolemScope :: Int } deriving (Show, Eq, Ord, Data, Typeable)
35−
36−-- |
37−-- The type of types
38−--
39−data Type
40− -- |
41− -- A unification variable of type Type
42− --
43− = TUnknown Unknown
44− -- |
45− -- A named type variable
46− --
47− | TypeVar String
48− -- |
49− -- A type constructor
50− --
51− | TypeConstructor (Qualified ProperName)
52− -- |
53− -- A type application
54− --
55− | TypeApp Type Type
56− -- |
57− -- A type synonym which is \"saturated\", i.e. fully applied
58− --
59− | SaturatedTypeSynonym (Qualified ProperName) [Type]
60− -- |
61− -- Forall quantifier
62− --
63− | ForAll String Type (Maybe SkolemScope)
64− -- |
65− -- A type with a set of type class constraints
66− --
67− | ConstrainedType [(Qualified ProperName, [Type])] Type
68− -- |
69− -- A skolem constant
70− --
71− | Skolem String Int SkolemScope
72− -- |
73− -- An empty row
74− --
75− | REmpty
76− -- |
77− -- A non-empty row
78− --
79− | RCons String Type Type
80− -- |
81− -- A placeholder used in pretty printing
82− --
83− | PrettyPrintFunction Type Type
84− -- |
85− -- A placeholder used in pretty printing
86− --
87− | PrettyPrintArray Type
88− -- |
89− -- A placeholder used in pretty printing
90− --
91− | PrettyPrintObject Type
92− -- |
93− -- A placeholder used in pretty printing
94− --
95− | PrettyPrintForAll [String] Type deriving (Show, Eq, Data, Typeable)
96−
97−-- |
98−-- Convert a row to a list of pairs of labels and types
99−--
100−rowToList :: Type -> ([(String, Type)], Type)
101−rowToList (RCons name ty row) = let (tys, rest) = rowToList row
102− in ((name, ty):tys, rest)
103−rowToList r = ([], r)
104−
105−-- |
106−-- Convert a list of labels and types to a row
107−--
108−rowFromList :: ([(String, Type)], Type) -> Type
109−rowFromList ([], r) = r
110−rowFromList ((name, t):ts, r) = RCons name t (rowFromList (ts, r))
111−
112−-- |
113−-- Check whether a type is a monotype
114−--
115−isMonoType :: Type -> Bool
116−isMonoType ForAll{} = False
117−isMonoType _ = True
118−
119−-- |
120−-- Universally quantify a type
121−--
122−mkForAll :: [String] -> Type -> Type
123−mkForAll args ty = foldl (\t arg -> ForAll arg t Nothing) ty args
124−
125−-- |
126−-- Replace a type variable, taking into account variable shadowing
127−--
128−replaceTypeVars :: String -> Type -> Type -> Type
129−replaceTypeVars = replaceTypeVars' []
130− where
131− replaceTypeVars' bound name replacement = go bound
132− where
133− go :: [String] -> Type -> Type
134− go _ (TypeVar v) | v == name = replacement
135− go bs (TypeApp t1 t2) = TypeApp (go bs t1) (go bs t2)
136− go bs (SaturatedTypeSynonym name' ts) = SaturatedTypeSynonym name' $ map (go bs) ts
137− go bs f@(ForAll v t sco) | v == name = f
138− | v `elem` usedTypeVariables replacement =
139− let v' = genName v (name : bs ++ usedTypeVariables replacement)
140− t' = replaceTypeVars' bs v (TypeVar v') t
141− in ForAll v' (go (v' : bs) t') sco
142− | otherwise = ForAll v (go (v : bs) t) sco
143− go bs (ConstrainedType cs t) = ConstrainedType (map (second $ map (go bs)) cs) (go bs t)
144− go bs (RCons name' t r) = RCons name' (go bs t) (go bs r)
145− go _ ty = ty
146− genName orig inUse = try 0
147− where
148− try :: Integer -> String
149− try n | (orig ++ show n) `elem` inUse = try (n + 1)
150− | otherwise = orig ++ show n
151−
152−-- |
153−-- Replace named type variables with types
154−--
155−replaceAllTypeVars :: [(String, Type)] -> Type -> Type
156−replaceAllTypeVars = foldl (\f (name, ty) -> replaceTypeVars name ty . f) id
157−
158−-- |
159−-- Collect all type variables appearing in a type
160−--
161−usedTypeVariables :: Type -> [String]
162−usedTypeVariables = nub . everythingOnTypes (++) go
163− where
164− go (TypeVar v) = [v]
165− go _ = []
166−
167−-- |
168−-- Collect all free type variables appearing in a type
169−--
170−freeTypeVariables :: Type -> [String]
171−freeTypeVariables = nub . go []
172− where
173− go :: [String] -> Type -> [String]
174− go bound (TypeVar v) | v `notElem` bound = [v]
175− go bound (TypeApp t1 t2) = go bound t1 ++ go bound t2
176− go bound (SaturatedTypeSynonym _ ts) = concatMap (go bound) ts
177− go bound (ForAll v t _) = go (v : bound) t
178− go bound (ConstrainedType cs t) = concatMap (concatMap (go bound) . snd) cs ++ go bound t
179− go bound (RCons _ t r) = go bound t ++ go bound r
180− go _ _ = []
181−
182−-- |
183−-- Universally quantify over all type variables appearing free in a type
184−--
185−quantify :: Type -> Type
186−quantify ty = foldr (\arg t -> ForAll arg t Nothing) ty $ freeTypeVariables ty
187−
188−-- |
189−-- Move all universal quantifiers to the front of a type
190−--
191−moveQuantifiersToFront :: Type -> Type
192−moveQuantifiersToFront = go [] []
193− where
194− go qs cs (ForAll q ty sco) = go ((q, sco) : qs) cs ty
195− go qs cs (ConstrainedType cs' ty) = go qs (cs ++ cs') ty
196− go qs cs ty =
197− let constrained = case cs of
198− [] -> ty
199− cs' -> ConstrainedType cs' ty
200− in case qs of
201− [] -> constrained
202− qs' -> foldl (\ty' (q, sco) -> ForAll q ty' sco) constrained qs'
203−
204−--
205−-- Traversals
206−--
207−
208−everywhereOnTypes :: (Type -> Type) -> Type -> Type
209−everywhereOnTypes f = go
210− where
211− go (TypeApp t1 t2) = f (TypeApp (go t1) (go t2))
212− go (SaturatedTypeSynonym name tys) = f (SaturatedTypeSynonym name (map go tys))
213− go (ForAll arg ty sco) = f (ForAll arg (go ty) sco)
214− go (ConstrainedType cs ty) = f (ConstrainedType (map (fmap (map go)) cs) (go ty))
215− go (RCons name ty rest) = f (RCons name (go ty) (go rest))
216− go (PrettyPrintFunction t1 t2) = f (PrettyPrintFunction (go t1) (go t2))
217− go (PrettyPrintArray t) = f (PrettyPrintArray (go t))
218− go (PrettyPrintObject t) = f (PrettyPrintObject (go t))
219− go (PrettyPrintForAll args t) = f (PrettyPrintForAll args (go t))
220− go other = f other
221−
222−everywhereOnTypesTopDown :: (Type -> Type) -> Type -> Type
223−everywhereOnTypesTopDown f = go . f
224− where
225− go (TypeApp t1 t2) = TypeApp (go (f t1)) (go (f t2))
226− go (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym name (map (go . f) tys)
227− go (ForAll arg ty sco) = ForAll arg (go (f ty)) sco
228− go (ConstrainedType cs ty) = ConstrainedType (map (fmap (map (go . f))) cs) (go (f ty))
229− go (RCons name ty rest) = RCons name (go (f ty)) (go (f rest))
230− go (PrettyPrintFunction t1 t2) = PrettyPrintFunction (go (f t1)) (go (f t2))
231− go (PrettyPrintArray t) = PrettyPrintArray (go (f t))
232− go (PrettyPrintObject t) = PrettyPrintObject (go (f t))
233− go (PrettyPrintForAll args t) = PrettyPrintForAll args (go (f t))
234− go other = f other
235−
236−everywhereOnTypesM :: (Functor m, Applicative m, Monad m) => (Type -> m Type) -> Type -> m Type
237−everywhereOnTypesM f = go
238− where
239− go (TypeApp t1 t2) = (TypeApp <$> go t1 <*> go t2) >>= f
240− go (SaturatedTypeSynonym name tys) = (SaturatedTypeSynonym name <$> mapM go tys) >>= f
241− go (ForAll arg ty sco) = (ForAll arg <$> go ty <*> pure sco) >>= f
242− go (ConstrainedType cs ty) = (ConstrainedType <$> mapM (sndM (mapM go)) cs <*> go ty) >>= f
243− go (RCons name ty rest) = (RCons name <$> go ty <*> go rest) >>= f
244− go (PrettyPrintFunction t1 t2) = (PrettyPrintFunction <$> go t1 <*> go t2) >>= f
245− go (PrettyPrintArray t) = (PrettyPrintArray <$> go t) >>= f
246− go (PrettyPrintObject t) = (PrettyPrintObject <$> go t) >>= f
247− go (PrettyPrintForAll args t) = (PrettyPrintForAll args <$> go t) >>= f
248− go other = f other
249−
250−everywhereOnTypesTopDownM :: (Functor m, Applicative m, Monad m) => (Type -> m Type) -> Type -> m Type
251−everywhereOnTypesTopDownM f = go <=< f
252− where
253− go (TypeApp t1 t2) = TypeApp <$> (f t1 >>= go) <*> (f t2 >>= go)
254− go (SaturatedTypeSynonym name tys) = SaturatedTypeSynonym name <$> mapM (go <=< f) tys
255− go (ForAll arg ty sco) = ForAll arg <$> (f ty >>= go) <*> pure sco
256− go (ConstrainedType cs ty) = ConstrainedType <$> mapM (sndM (mapM (go <=< f))) cs <*> (f ty >>= go)
257− go (RCons name ty rest) = RCons name <$> (f ty >>= go) <*> (f rest >>= go)
258− go (PrettyPrintFunction t1 t2) = PrettyPrintFunction <$> (f t1 >>= go) <*> (f t2 >>= go)
259− go (PrettyPrintArray t) = PrettyPrintArray <$> (f t >>= go)
260− go (PrettyPrintObject t) = PrettyPrintObject <$> (f t >>= go)
261− go (PrettyPrintForAll args t) = PrettyPrintForAll args <$> (f t >>= go)
262− go other = f other
263−
264−everythingOnTypes :: (r -> r -> r) -> (Type -> r) -> Type -> r
265−everythingOnTypes (<>) f = go
266− where
267− go t@(TypeApp t1 t2) = f t <> go t1 <> go t2
268− go t@(SaturatedTypeSynonym _ tys) = foldl (<>) (f t) (map go tys)
269− go t@(ForAll _ ty _) = f t <> go ty
270− go t@(ConstrainedType cs ty) = foldl (<>) (f t) (map go $ concatMap snd cs) <> go ty
271− go t@(RCons _ ty rest) = f t <> go ty <> go rest
272− go t@(PrettyPrintFunction t1 t2) = f t <> go t1 <> go t2
273− go t@(PrettyPrintArray t1) = f t <> go t1
274− go t@(PrettyPrintObject t1) = f t <> go t1
275− go t@(PrettyPrintForAll _ t1) = f t <> go t1
276− go other = f other
src/Tests.hsnew file+141
@@ -0,0 +1,141 @@
1+module Tests (runTests) where
2+
3+import Prelude.Compat
4+import Data.List
5+import Control.Applicative
6+import Control.Monad
7+
8+import System.Process
9+import System.FilePath
10+import System.IO
11+import System.Directory
12+
13+-------------------------------------------------------------------------------
14+testsDir :: IO (FilePath, FilePath)
15+-------------------------------------------------------------------------------
16+testsDir = do
17+ baseDir <- getCurrentDirectory
18+ return (baseDir </> "purescript-tests", baseDir)
19+
20+-------------------------------------------------------------------------------
21+runTests :: IO ()
22+-------------------------------------------------------------------------------
23+runTests = do
24+
25+ (outputDir, baseDir) <- testsDir
26+
27+ outputDirExists <- doesDirectoryExist outputDir
28+ when outputDirExists $ removeDirectoryRecursive outputDir
29+ createDirectory outputDir
30+
31+ let srcDir = outputDir </> "src"
32+ createDirectory srcDir
33+
34+ callProcess "git" ["clone", "--branch", "v0.13.8", "--depth", "1", "https://github.com/purescript/purescript.git"]
35+ let passingDir = baseDir </> "purescript" </> "tests" </> "purs" </> "passing"
36+ passingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents passingDir
37+
38+ setCurrentDirectory outputDir
39+
40+ fetchPackages
41+
42+ let tests = filter (`notElem` skipped) passingTestCases
43+
44+ tmp <- getTemporaryDirectory
45+ createDirectoryIfMissing False (tmp </> logpath)
46+ outputFile <- openFile (tmp </> logpath </> logfile) WriteMode
47+ hClose outputFile
48+
49+ -- Run the tests
50+ --
51+ forM_ tests $ \inputFile -> do
52+ --
53+ -- Compile/build
54+ --
55+ putStrLn $ "Compiling test " ++ inputFile ++ " ..."
56+ setCurrentDirectory outputDir
57+ copyFile (passingDir </> inputFile) (srcDir </> inputFile)
58+
59+ let testCaseDir = passingDir </> (takeWhile (/='.') inputFile)
60+ testCaseDirExists <- doesDirectoryExist testCaseDir
61+ when testCaseDirExists $ callProcess "cp" ["-R", testCaseDir, srcDir]
62+
63+ callProcess "rm" ["-rf", "output"]
64+ callProcess "rm" ["-rf", "Main"]
65+ callProcess "spago" ["build"]
66+ --
67+ -- Run executable file
68+ --
69+ outputFile <- openFile (tmp </> logpath </> logfile) AppendMode
70+ hPutStrLn outputFile ("\n" ++ inputFile ++ ":")
71+ proc <- runProcess ("./" </> "Main") [] Nothing Nothing Nothing (Just outputFile) Nothing
72+
73+ removeFile (srcDir </> inputFile)
74+ when testCaseDirExists $ callProcess "rm" ["-rf", srcDir </> (takeWhile (/='.') inputFile)]
75+
76+ -- TODO: support failing test cases
77+ --
78+ -- let failing = baseDir </> "examples" </> "failing"
79+ -- failingTestCases <- sort . filter (".purs" `isSuffixOf`) <$> getDirectoryContents failing
80+ --
81+
82+ setCurrentDirectory baseDir
83+ putStrLn "PureScript tests finished"
84+ putStrLn $ "Total tests available: " ++ show (length passingTestCases)
85+ putStrLn $ "Tests run: " ++ show (length tests)
86+ putStrLn $ "Tests skipped: " ++ show (length skipped)
87+
88+-------------------------------------------------------------------------------
89+packages :: [String]
90+-------------------------------------------------------------------------------
91+packages =
92+ [ "arrays"
93+ , "assert"
94+ , "console"
95+ , "control"
96+ , "effect"
97+ , "foldable-traversable"
98+ , "functions"
99+ , "generics-rep"
100+ , "invariant"
101+ , "newtype"
102+ , "partial"
103+ , "prelude"
104+ , "proxy"
105+ , "refs"
106+ , "st"
107+ , "type-equality"
108+ , "typelevel-prelude"
109+ ]
110+
111+-------------------------------------------------------------------------------
112+fetchPackages :: IO ()
113+-------------------------------------------------------------------------------
114+fetchPackages = do
115+ callProcess "spago" ["init"]
116+ callCommand "sed '$s/\\(}\\)/, backend = \"psgo\"\\1/' < spago.dhall | dhall format > spago.tmp"
117+ callCommand "mv spago.tmp spago.dhall"
118+
119+ mapM (callProcess "spago" . (\p -> ["install", p])) packages
120+ return ()
121+
122+-------------------------------------------------------------------------------
123+skipped :: [String]
124+-------------------------------------------------------------------------------
125+skipped =
126+ [ "2172.purs" -- foreign in Main needed (test manually)
127+ , "EffFn.purs" -- foreign in Main needed (test manually)
128+ , "FunWithFunDeps.purs" -- foreign in Main needed (test manually)
129+ , "NumberLiterals.purs" -- unreliable float string comparison (test manually)
130+ , "PolyLabels.purs" -- foreign in Main needed (test manually)
131+ , "RowUnion.purs" -- foreign in Main needed (test manually)
132+ , "ShadowedModuleName.purs" -- ?
133+ , "StringEdgeCases.purs" -- javascript char encoding specific
134+ , "StringEscapes.purs" -- Partially javascript-char-encoding-specific (test manually)
135+ ]
136+
137+logpath :: FilePath
138+logpath = "purescript-output"
139+
140+logfile :: FilePath
141+logfile = "purescript-tests.out"
stack.nixnew file+23
@@ -0,0 +1,23 @@
1+#
2+# You may need to manually run `unset STACK_IN_NIX_SHELL`
3+# (doesn't work from a `shellHook`; see: https://github.com/commercialhaskell/stack/issues/5000
4+#
5+#
6+# You may need to set LC_ALL when building, e.g.
7+# LC_ALL=en_US.iso88591 stack --nix build; see e.g. https://github.com/koalaman/shellcheck/issues/324
8+#
9+#
10+{ pkgs ?
11+ import (builtins.fetchTarball {
12+ name = "nixos-release-19.03";
13+ url = https://github.com/nixos/nixpkgs/archive/34c7eb7545d155cc5b6f499b23a7cb1c96ab4d59.tar.gz;
14+ sha256 = "11z6ajj108fy2q5g8y4higlcaqncrbjm3dnv17pvif6avagw4mcb";
15+ }) {}
16+}:
17+
18+pkgs.haskell.lib.buildStackProject {
19+ name = "default-stack-shell";
20+ ghc = pkgs.haskell.compiler.ghc865;
21+ buildInputs = with pkgs; [git git-lfs gmp ncurses zlib];
22+ LANG = "en_US.UTF-8";
23+}
stack.yamlnew file+24
@@ -0,0 +1,24 @@
1+resolver: lts-13.26
2+
3+packages:
4+- .
5+
6+extra-deps:
7+- git: https://github.com/purescript/purescript
8+ commit: 9cad73ed8ea7df3011032ddbd2f3de5a0c08629c
9+- happy-1.19.9
10+- language-javascript-0.7.0.0
11+- network-3.0.1.1
12+- these-1.0.1
13+- semialign-1
14+
15+nix:
16+ enable: false
17+ shell-file: stack.nix
18+
19+flags:
20+ aeson-pretty:
21+ lib-only: true
22+ these:
23+ assoc: false
24+ quickcheck: false
support/ffi-loader.gonew file+30
@@ -0,0 +1,30 @@
1+package ffi_loader
2+
3+// Load PureScript standard library FFI packages. Comment out the ones you don't need for
4+// faster/smaller builds.
5+
6+import (
7+ _ "github.com/purescript-native/go-ffi/purescript-arrays"
8+ _ "github.com/purescript-native/go-ffi/purescript-assert"
9+ _ "github.com/purescript-native/go-ffi/purescript-console"
10+ _ "github.com/purescript-native/go-ffi/purescript-effect"
11+ _ "github.com/purescript-native/go-ffi/purescript-enums"
12+ _ "github.com/purescript-native/go-ffi/purescript-exceptions"
13+ _ "github.com/purescript-native/go-ffi/purescript-foldable-traversable"
14+ _ "github.com/purescript-native/go-ffi/purescript-functions"
15+ _ "github.com/purescript-native/go-ffi/purescript-globals"
16+ _ "github.com/purescript-native/go-ffi/purescript-integers"
17+ _ "github.com/purescript-native/go-ffi/purescript-lazy"
18+ _ "github.com/purescript-native/go-ffi/purescript-math"
19+ _ "github.com/purescript-native/go-ffi/purescript-partial"
20+ _ "github.com/purescript-native/go-ffi/purescript-prelude"
21+ _ "github.com/purescript-native/go-ffi/purescript-random"
22+ _ "github.com/purescript-native/go-ffi/purescript-refs"
23+ _ "github.com/purescript-native/go-ffi/purescript-st"
24+ _ "github.com/purescript-native/go-ffi/purescript-strings"
25+ _ "github.com/purescript-native/go-ffi/purescript-unfoldable"
26+)
27+
28+// Add your own FFI packages here.
29+
30+import ()
support/go.mod.ffi-loadernew file+2
@@ -0,0 +1,2 @@
1+module $PROJECT/purescript-native/ffi-loader
2+
support/go.mod.outputnew file+2
@@ -0,0 +1,2 @@
1+module $PROJECT/purescript-native/output
2+
support/go.mod.workingnew file+1
@@ -0,0 +1 @@
1+module $PROJECT/example
test/Spec.hsnew file+2
@@ -0,0 +1,2 @@
1+main :: IO ()
2+main = putStrLn "Test suite not yet implemented"
tests/Main.hsdeleted−103
@@ -1,103 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Main
4−-- Copyright : (c) Phil Freeman 2013
5−-- License : MIT
6−--
7−-- Maintainer : Phil Freeman <paf31@cantab.net>
8−-- Stability : experimental
9−-- Portability :
10−--
11−-- |
12−--
13−-----------------------------------------------------------------------------
14−
15−{-# LANGUAGE DoAndIfThenElse #-}
16−
17−module Main (main) where
18−
19−import qualified Language.PureScript as P
20−
21−import Data.List (isSuffixOf)
22−import Data.Traversable (traverse)
23−import Control.Monad
24−import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
25−import System.Exit
26−import System.Process
27−import System.FilePath (pathSeparator)
28−import System.Directory (getCurrentDirectory, getTemporaryDirectory, getDirectoryContents, findExecutable)
29−import Text.Parsec (ParseError)
30−import qualified Paths_purescript as Paths
31−import qualified System.IO.UTF8 as U
32−
33−preludeFilename :: IO FilePath
34−preludeFilename = Paths.getDataFileName "prelude/prelude.purs"
35−
36−readInput :: [FilePath] -> IO (Either ParseError [P.Module])
37−readInput inputFiles = fmap (fmap concat . sequence) $ forM inputFiles $ \inputFile -> do
38− text <- U.readFile inputFile
39− return $ P.runIndentParser inputFile P.parseModules text
40−
41−compile :: P.Options -> [FilePath] -> IO (Either String (String, String, P.Environment))
42−compile opts inputFiles = do
43− modules <- readInput inputFiles
44− case modules of
45− Left parseError ->
46− return (Left $ show parseError)
47− Right ms -> return $ P.compile opts ms
48−
49−assert :: FilePath -> P.Options -> FilePath -> (Either String (String, String, P.Environment) -> IO (Maybe String)) -> IO ()
50−assert preludeExterns opts inputFile f = do
51− e <- compile opts [preludeExterns, inputFile]
52− maybeErr <- f e
53− case maybeErr of
54− Just err -> putStrLn err >> exitFailure
55− Nothing -> return ()
56−
57−assertCompiles :: String -> FilePath -> FilePath -> IO ()
58−assertCompiles preludeJs preludeExterns inputFile = do
59− putStrLn $ "Assert " ++ inputFile ++ " compiles successfully"
60− let options = P.defaultOptions { P.optionsMain = Just "Main", P.optionsModules = ["Main"], P.optionsCodeGenModules = ["Main"], P.optionsBrowserNamespace = Just "Tests" }
61− assert preludeExterns options inputFile $ either (return . Just) $ \(js, _, _) -> do
62− process <- findNodeProcess
63− result <- traverse (\node -> readProcessWithExitCode node [] (preludeJs ++ js)) process
64− case result of
65− Just (ExitSuccess, out, _) -> putStrLn out >> return Nothing
66− Just (ExitFailure _, _, err) -> return $ Just err
67− Nothing -> return $ Just "Couldn't find node.js executable"
68−
69−assertDoesNotCompile :: FilePath -> FilePath -> IO ()
70−assertDoesNotCompile preludeExterns inputFile = do
71− putStrLn $ "Assert " ++ inputFile ++ " does not compile"
72− assert preludeExterns (P.defaultOptions { P.optionsBrowserNamespace = Just "Tests" }) inputFile $ \e ->
73− case e of
74− Left _ -> return Nothing
75− Right _ -> return $ Just "Should not have compiled"
76−
77−findNodeProcess :: IO (Maybe String)
78−findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names
79− where names = ["nodejs", "node"]
80−
81−main :: IO ()
82−main = do
83− prelude <- preludeFilename
84− putStrLn "Compiling Prelude"
85− preludeResult <- compile (P.defaultOptions { P.optionsBrowserNamespace = Just "Tests" }) [prelude]
86− case preludeResult of
87− Left err -> putStrLn err >> exitFailure
88− Right (preludeJs, exts, _) -> do
89− tmp <- getTemporaryDirectory
90− let preludeExterns = tmp ++ pathSeparator : "prelude.externs"
91− writeFile preludeExterns exts
92− putStrLn $ "Wrote " ++ preludeExterns
93− cd <- getCurrentDirectory
94− let examples = cd ++ pathSeparator : "examples"
95− let passing = examples ++ pathSeparator : "passing"
96− passingTestCases <- getDirectoryContents passing
97− forM_ passingTestCases $ \inputFile -> when (".purs" `isSuffixOf` inputFile) $
98− assertCompiles preludeJs preludeExterns (passing ++ pathSeparator : inputFile)
99− let failing = examples ++ pathSeparator : "failing"
100− failingTestCases <- getDirectoryContents failing
101− forM_ failingTestCases $ \inputFile -> when (".purs" `isSuffixOf` inputFile) $
102− assertDoesNotCompile preludeExterns (failing ++ pathSeparator : inputFile)
103− exitSuccess