git.iko.soy/rowtype-yoga/purescript-native
on golang help sign in
172 files changed+2724−10540
since splitsnapshots
unifiedsplit
.gitignore+13 .travis.yml−3 CONTRIBUTING.md−13 ChangeLog.md+3 LICENSE+26−16 README-go.md+48 README.md+38−10 RELEASE.md−171 Setup.hs+2 Setup.lhs−6 app/Main.hs+250 default.nix+23 docs/.gitignore−1 docs/Makefile−177 docs/source/blocks.rst−90 docs/source/conf.py−258 docs/source/ffi.rst−31 docs/source/index.rst−31 docs/source/intro.rst−132 docs/source/kinds.rst−21 docs/source/modules.rst−29 docs/source/patterns.rst−127 docs/source/prelude.rst−88 docs/source/syntax.rst−222 docs/source/typeclasses.rst−26 docs/source/types.rst−159 examples/.gitignore−1 examples/failing/Arrays.purs−5 examples/failing/Do.purs−8 examples/failing/Import.purs−3 examples/failing/KindError.purs−3 examples/failing/LocalVars.purs−8 examples/failing/ModuleDeps.purs−7 examples/failing/NullaryAbs.purs−3 examples/failing/PatternScope.purs−12 examples/failing/Rank2Types.purs−7 examples/failing/ReadShow.purs−7 examples/failing/Reserved.purs−4 examples/failing/Shadowed.purs−14 examples/failing/SkolemEscape.purs−5 examples/failing/TypeClassInstances.purs−8 examples/failing/TypeClasses.purs−7 examples/failing/TypeClasses2.purs−15 examples/failing/TypeError.purs−5 examples/failing/TypeSynonyms.purs−5 examples/passing/Applicative.purs−16 examples/passing/ArrayType.purs−17 examples/passing/Arrays.purs−27 examples/passing/Assign.purs−38 examples/passing/Auto.purs−15 examples/passing/Category.purs−15 examples/passing/Church.purs−18 examples/passing/Conditional.purs−9 examples/passing/Cons.purs−12 examples/passing/Console.purs−13 examples/passing/DataAndType.purs−9 examples/passing/DataImport.purs−13 examples/passing/Do.purs−65 examples/passing/Dollar.purs−16 examples/passing/Eff.purs−27 examples/passing/ExternData.purs−19 examples/passing/ExternRaw.purs−15 examples/passing/FFI.purs−16 examples/passing/Functions.purs−17 examples/passing/Guards.purs−16 examples/passing/IfThenElse.purs−42 examples/passing/Import.purs−16 examples/passing/List.purs−10 examples/passing/Match.purs−9 examples/passing/Maybe.purs−12 examples/passing/Module.purs−28 examples/passing/ModuleDeps.purs−17 examples/passing/Monad.purs−32 examples/passing/MutRec.purs−21 examples/passing/NamedPatterns.purs−9 examples/passing/Nested.purs−9 examples/passing/ObjectSynonym.purs−15 examples/passing/ObjectUpdate.purs−20 examples/passing/Objects.purs−20 examples/passing/OneConstructor.purs−9 examples/passing/Operators.purs−78 examples/passing/OptimizerBug.purs−11 examples/passing/Patterns.purs−30 examples/passing/Person.purs−15 examples/passing/Rank2Data.purs−31 examples/passing/Rank2Types.purs−25 examples/passing/Recursion.purs−12 examples/passing/RedefinedFixity.purs−18 examples/passing/TailCall.purs−17 examples/passing/Tick.purs−7 examples/passing/TopLevelCase.purs−20 examples/passing/TypeClasses.purs−69 examples/passing/TypeDecl.purs−20 examples/passing/TypeSynonyms.purs−44 examples/passing/iota.purs−11 examples/passing/s.purs−7 execTests.sh−1 libraries/.gitignore−1 libraries/jquery/jquery.purs−45 libraries/jquery/tests/.gitignore−1 libraries/jquery/tests/build.sh−2 libraries/jquery/tests/index.html−10 libraries/jquery/tests/jquery.purs−28 libraries/prelude/prelude.purs−910 libraries/prelude/tests/.gitignore−1 libraries/prelude/tests/Eff.purs−51 libraries/prelude/tests/build.sh−2 package.yaml+86 psc/Main.hs−120 psci/Main.hs−146 psgo.cabal+145 purescript.cabal−96 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/Data/Generics/Extras.hs−28 src/Language/PureScript.hs−70 src/Language/PureScript/CodeGen.hs−26 src/Language/PureScript/CodeGen/Common.hs−56 src/Language/PureScript/CodeGen/Externs.hs−51 src/Language/PureScript/CodeGen/JS.hs−273 src/Language/PureScript/CodeGen/JS/AST.hs−233 src/Language/PureScript/CodeGen/Monad.hs−44 src/Language/PureScript/CodeGen/Optimize.hs−369 src/Language/PureScript/Declarations.hs−171 src/Language/PureScript/Kinds.hs−46 src/Language/PureScript/ModuleDependencies.hs−65 src/Language/PureScript/Names.hs−74 src/Language/PureScript/Options.hs−48 src/Language/PureScript/Parser.hs−35 src/Language/PureScript/Parser/Common.hs−403 src/Language/PureScript/Parser/Declarations.hs−153 src/Language/PureScript/Parser/JS.hs−167 src/Language/PureScript/Parser/Kinds.hs−45 src/Language/PureScript/Parser/State.hs−30 src/Language/PureScript/Parser/Types.hs−120 src/Language/PureScript/Parser/Values.hs−299 src/Language/PureScript/Pretty.hs−32 src/Language/PureScript/Pretty/Common.hs−22 src/Language/PureScript/Pretty/JS.hs−254 src/Language/PureScript/Pretty/Kinds.hs−60 src/Language/PureScript/Pretty/Types.hs−90 src/Language/PureScript/Pretty/Values.hs−173 src/Language/PureScript/Scope.hs−63 src/Language/PureScript/Sugar.hs−50 src/Language/PureScript/Sugar/BindingGroups.hs−120 src/Language/PureScript/Sugar/CaseDeclarations.hs−70 src/Language/PureScript/Sugar/DoNotation.hs−62 src/Language/PureScript/Sugar/Operators.hs−113 src/Language/PureScript/Sugar/TypeClasses.hs−150 src/Language/PureScript/Sugar/TypeDeclarations.hs−43 src/Language/PureScript/TypeChecker.hs−247 src/Language/PureScript/TypeChecker/Kinds.hs−156 src/Language/PureScript/TypeChecker/Monad.hs−330 src/Language/PureScript/TypeChecker/Synonyms.hs−59 src/Language/PureScript/TypeChecker/Types.hs−878 src/Language/PureScript/Types.hs−155 src/Language/PureScript/Values.hs−272 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−106
.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: false
CONTRIBUTING.mddeleted−13
@@ -1,13 +0,0 @@
1−Pull requests are encouraged.
2−
3−Please follow the following guidelines:
4−
5−- Add at least a test to `examples/passing/` and possibly to `examples/failing`
6−- Run `cabal test`
7−- Please run `hlint`.
8−
9−If you would like to contribute, please consider the issues in the current milestone first.
10−
11−Send me (`paf31`) a message if you have any implementation questions, I'm more than happy to talk about the design, and I'm more than willing to redesign parts if necessary.
12−
13−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.
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.mddeleted−171
@@ -1,171 +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−
86−## 0.2.0 Changes
87−
88−Many thanks to the [contributors](https://github.com/purescript/purescript/graphs/contributors) who helped with this release.
89−
90−- Full language guide can be found [here](http://functorial.com/purescript).
91−- Try out the latest features [here](http://tryps.functorial.com).
92−
93−### New Features
94−
95−- RankNTypes
96−
97− 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:
98−
99− rank2 :: (forall a. a -> a) -> Number
100− rank2 = \f -> if f true then f 1 else f 2
101−
102−- Modules
103−- Polymorphic Object Update
104−
105− Records now support member update in which the type of the field changes during the update. For example:
106−
107− data Wrap a = Wrap a
108−
109− update = \o -> o { prop = Wrap o.prop }
110−
111−### Enhancements
112−
113−- Naked expressions as statements
114−
115− Naked expressions of type `{}` can now be used as statements.
116−
117−- Split code generation into `AST -> JS` and `JS -> String`
118−
119− 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.
120−
121−- Syntactic sugar for introducing curried functions
122−
123− Single-argument functions and multiple-argument functions can now be introduced in the same way:
124−
125− test = \a (b, c) d -> a + b + c + d
126−
127−- JavaScript optimizations
128−
129− Some basic dead-variable elimination, inlining and eta-conversion are now performed on the generated JavaScript.
130−
131−- Generate formatted Javascript
132−
133− The generated JavaScript is now formatted to be more readable. In particular, newlines get generated, and the correct indentation is used.
134−
135−- More valid infix operators
136−
137− The colon and period characters are now valid in infix operator names.
138−
139−### Syntax Changes
140−
141−- Avoid 'do' keyword for blocks
142−
143− `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.
144−
145−- Member foreign import syntax
146−
147− A small syntactic addition to the FFI, to support a common use case.
148−
149−- Make FFI syntax match Haskell
150−
151− Use `foreign import` instead of `extern`.
152−
153−- Make record declaration syntax match Haskell
154−- Simplify array binders
155−
156− 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]`.
157−
158−- Array indexing syntax is ambiguous
159−
160− Array elements are now accessed using the `!!` operator: `arr !! 0` etc.
161−
162−### Bug Fixes
163−
164−- Allow guards access to current scope
165−
166−### Libraries
167−
168−- Prelude
169−
170− There is now a basic prelude in the `libraries/prelude` folder.
171−
Setup.hsnew file+2
@@ -0,0 +1,2 @@
1+import Distribution.Simple
2+main = defaultMain
Setup.lhsdeleted−6
@@ -1,6 +0,0 @@
1−#!/usr/bin/runhaskell
2−> module Main where
3−> import Distribution.Simple
4−> main :: IO ()
5−> main = defaultMain
6−
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+}
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/blocks.rstdeleted−90
@@ -1,90 +0,0 @@
1−Blocks
2−======
3−
4−Blocks are collections of statements wrapped in braces ``{ ... }``. Blocks must return a value of the same type on every branch of execution.
5−
6−The following types of statement are supported:
7−
8−- Variable introduction
9−- Variable assignment
10−- For loops
11−- While loops
12−- If-Then-Else statements
13−
14−Here is an example of a power function defined using a block::
15−
16− pow n p = {
17− var m = n;
18− for (i <- 0 until p) {
19− m = m * n;
20− }
21− return m;
22− }
23−
24−Blocks enable local mutation of their variables, but mutation is not allowed in general. The type system prevents mutable variables from escaping their scope.
25−
26−That is, while the example above is valid, the following does not compile::
27−
28− incr n = {
29− n = n + 1;
30− return n;
31− }
32−
33−The variable ``n`` is not mutable, and so the assignment in the first line of the block is not allowed.
34−
35−This function can be rewritten as follows::
36−
37− incr n = {
38− var m = n;
39− m = m + 1;
40− return m;
41− }
42−
43−For Loops
44−---------
45−
46−For loops iterate over a range of numbers::
47−
48− total = {
49− var n = 0;
50− for (i <- 0 until 10) {
51− n = n + i;
52− }
53− return n;
54− }
55−
56−The bounds `0` and `10` are inclusive and exclusive respectively.
57−
58−While Loops
59−------------
60−
61−While loops repeat a set of statements while a boolean expression evaluates to ``true``::
62−
63− log2 n = {
64− var count = 0;
65− var m = n;
66− while (m > 1) {
67− m = m / 2;
68− count = count + 1;
69− }
70− return count;
71− }
72−
73−If-Then-Else Statements
74−-----------------------
75−
76−Else branches are optional, and may contain further ``if`` statements, just as in Javascript:
77−
78− collatz n = {
79− var count = 0;
80− var m = n;
81− while (m > 1) {
82− if (m % 2 == 0) {
83− m = m / 2;
84− } else {
85− m = m * 3 + 1;
86− }
87− count = count + 1;
88− }
89− return count;
90− }
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.3.1'
55−# The full version, including alpha/beta/rc tags.
56−release = '0.3.1'
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−31
@@ -1,31 +0,0 @@
1−Foreign Function Interface
2−==========================
3−
4−Importing Values
5−----------------
6−
7−The `foreign import` keyword declares 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 "function pow(n) {\
17− \ return function(p) {\
18− \ return Math.pow(n, p);\
19− \ };\
20− \}" :: Number -> Number -> Number
21−
22−Importing Types
23−---------------
24−
25−To declare a new type with no constructors, use `foreign import data` and provide the kind::
26−
27− foreign import data DOM :: *
28−
29− foreign import document :: {
30− createElement :: String -> DOM
31− }
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− types
16− kinds
17− syntax
18− blocks
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−132
@@ -1,132 +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−- Type-safe blocks with for/while/assignment etc.
12−- Pattern matching
13−- Simple FFI
14−- Modules
15−- Rank N Types
16−- Do Notation
17−- Optional tail-call elimination
18−- Type Classes
19−
20−Installation
21−------------
22−
23−If you have the Haskell Plaform installed, then you can install the latest released version from Hackage::
24−
25− cabal update
26− cabal install purescript
27−
28−If you would like to build the latest version of the code, clone this repository and build::
29−
30− git clone git://github.com:paf31/purescript.git
31− cabal configure --enable-tests
32− cabal build
33− cabal test
34− cabal install
35−
36−Usage
37−-----
38−
39−The `psc` executable takes a list of PureScript source files as arguments and by default writes out its errors or output to the console.
40−
41−The following options are supported:
42−
43−--stdin Read input from standard input instead of from files
44−--output Write the generated Javascript to the specified file
45−--externs Write a list of foreign imports declarations to the specified file in addition to generating Javascript output
46−--runtime-type-checks Generate simple runtime type checks for function arguments with simple types.
47−--tco Perform tail-call elimination on the generated Javascript.
48−--no-prelude Do not include the Prelude in the generated Javascript.
49−--magic-do Overload the `do` keyword to inline calls to `bind` for the `Eff` monad, to generate more efficient code.
50−--run-main Generate a call to `Main.main` after all other generated Javascript.
51−
52−Motivation
53−----------
54−
55−I was looking for a simple functional language which would compile to JavaScript and have the following characteristics:
56−
57−- Generate simple readable Javascript
58−- Provide the ability to compile to tight loops if necessary
59−- Reasonable type system
60−- Ideally, written in a programming language I would enjoy working in
61−- Provides a simple interface to existing Javascript code
62−
63−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.
64−
65−PureScript is *not* designed to be a general-purpose programming language. The primary use case is as a generator for purely-functional core libraries, with the main application code written in another language.
66−
67−PureScript can also be seen as a trade-off between a theoretically ideal language and one which generates reasonably high performance code.
68−
69−Hello, PureScript!
70−------------------
71−
72−As an introductory example, here is the usual "Hello World" written in PureScript::
73−
74− module Main where
75−
76− import Trace
77−
78− main = trace "Hello, World!"
79−
80−which compiles to the following Javascript, ignoring the Prelude::
81−
82− var Main;
83− (function (Main) {
84− var main = trace("Hello, World!");
85− Main.main = main;
86− })(Main = Main || {});
87−
88−The following command will compile and execute the PureScript code above::
89−
90− psc input.purs --run-main | nodejs
91−
92−Another Example
93−---------------
94−
95−The following code defines a `Person` data type and a function to generate a string representation for a `Person`::
96−
97− data Person = Person { name :: String, age :: Number }
98−
99− foreign import numberToString :: Number -> String
100−
101− showPerson :: Person -> String
102− showPerson (Person o) = o.name ++ ", aged " ++ numberToString(o.age)
103−
104−Line by line, this reads as follows:
105−
106−- `Person` is a data type with one constructor, also called `Person`
107−- The `Person` constructor takes an object with two properties, `name` which is a `String`, and `age` which is a `Number`
108−- The `numberToString` function is written in Javascript, and converts a `Number` to its `String` representation
109−- The `showPerson` function takes a `Person` and returns a `String`
110−- `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.
111−
112−The generated Javascript looks like this::
113−
114− var Person = function (value) {
115− return { ctor: 'Person', value: value };
116− };
117−
118− function showPerson(_1) {
119− return _1.value.name + ", aged " + numberToString(_1.value.age);
120− };
121−
122−Related Projects
123−----------------
124−
125−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.
126−
127−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)
128−
129−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.
130−
131−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.
132−
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−29
@@ -1,29 +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 (id)
docs/source/patterns.rstdeleted−127
@@ -1,127 +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−- Record patterns
29−- Named patterns
30−- Guards
31−
32−Patterns need not be exhaustive. A pattern match failed exception will be thrown at runtime if no pattern matches the input.
33−
34−Wildcard Patterns
35−-----------------
36−
37−The wilcard `_` matches any input and brings nothing into scope::
38−
39− f _ = 0
40−
41−Literal Patterns
42−----------------
43−
44−Literal patterns are provided to match on primitives::
45−
46− f true = 0
47− f false = 1
48−
49− g "Foo" = 0
50− g _ = 1
51−
52− h 0 = 0
53− h _ = 1
54−
55−Variable Patterns
56−-----------------
57−
58−A variable pattern matches any input and binds that input to its name::
59−
60− double x = x * 2
61−
62−Array Patterns
63−--------------
64−
65−Array patterns match an input which is an array, and bring its elements into scope. For example::
66−
67− f [x] = x
68− f [x, y] = x * y + f xs
69− f _ = 0
70−
71−Here, the first pattern only matches arrays of length one, and brings the first element of the array into scope.
72−
73−The second pattern matches arrays with two elements, and brings the first and second elements into scope.
74−
75−Cons Patterns
76−-------------
77−
78−The head and tail of a non-empty array can be matched by using a cons pattern::
79−
80− sum [] = 0
81− sum (x : xs) = x + sum xs
82−
83−`:` associates to the right::
84−
85− addPairs (x : y : xs) = x * y + addPairs xs
86− addPairs _ = 0
87−
88−Record Patterns
89−---------------
90−
91−Record patterns match an input which is a record, and bring its properties into scope::
92−
93− f { foo = "Foo" } = o.bar
94− f _ = 0
95−
96−Nested Patterns
97−---------------
98−
99−The patterns above can be combined to create larger patterns. For example::
100−
101− f { arr = x : _, take = "car" } = x
102− f { arr = _ : x : _, take = "cadr" } = x
103− f _ = 0
104−
105−Named Patterns
106−--------------
107−
108−Named patterns bring additional names into scope when using nested patterns. Any pattern can be named by using the ``@`` symbol::
109−
110− f a@(_ : _ : _) = true
111− f _ = false
112−
113−Here, in the first pattern, any array with two or more elements will be matched and bound to the variable ``a``.
114−
115−Guards
116−------
117−
118−Guards are used to impose additional constraints inside a pattern using boolean-valued expressions, and are introduced with a pipe after the pattern::
119−
120− evens [] = 0
121− evens (x : xs) | x % 2 == 0 = 1 + evens xs
122− evens (_ : xs) = evens xs
123−
124−When using patterns to define a function at the top level, guards appear after all patterns::
125−
126− greater x y | x > y = true
127− greater _ _ = false
docs/source/prelude.rstdeleted−88
@@ -1,88 +0,0 @@
1−Prelude
2−=======
3−
4−The Prelude is a collection of standard modules which define types for standard Javascript functions, as well as some common functions that will be familiar to users of Haskell or similar functional languages.
5−
6−Prelude Module
7−--------------
8−
9−=========== ============================================================ ===========================================
10−Name Type Description
11−=========== ============================================================ ===========================================
12−``id`` ``forall a. a -> a`` Identity function
13−``flip`` ``forall a b c. (a -> b -> c) -> b -> a -> c`` Flips the order of a function's arguments
14−``konst`` ``forall a b. a -> b -> a`` Defines a constant function
15−``(<|)`` ``forall a b c. (a -> b) -> (b -> c) -> a -> c`` Function composition
16−``(|>)`` ``forall a b c. (b -> c) -> (a -> b) -> a -> c`` Function composition
17−``($)`` ``forall a b. (a -> b) -> a -> b`` Function application
18−=========== ============================================================ ===========================================
19−
20−======= ===========================================
21−Name Description
22−======= ===========================================
23−Show Type class for types whose values can be
24− converted to strings
25−Monad Type class for type constructors which
26− support ``do`` notation
27−======= ===========================================
28−
29−String Module
30−-------------
31−
32−`TODO`
33−
34−Regex Module
35−------------
36−
37−`TODO`
38−
39−Maybe Module
40−------------
41−
42−`TODO`
43−
44−Either Module
45−-------------
46−
47−`TODO`
48−
49−Arrays Module
50−-------------
51−
52−`TODO`
53−
54−Tuple Module
55−------------
56−
57−`TODO`
58−
59−Eff Module
60−----------
61−
62−`TODO`
63−
64−Errors Module
65−-------------
66−
67−`TODO`
68−
69−IORef Module
70−------------
71−
72−`TODO`
73−
74−Random Module
75−-------------
76−
77−`TODO`
78−
79−ST Module
80−---------
81−
82−`TODO`
83−
84−Trace Module
85−------------
86−
87−`TODO`
88−
docs/source/syntax.rstdeleted−222
@@ -1,222 +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−PureScript supports the following unary operators (in precedence order):
23−
24−== =======================
25− Meaning
26−== =======================
27−\- Numeric negation
28−! Boolean negation
29−~ Binary negation
30−\+ Unary plus (numeric)
31−== =======================
32−
33−and the following binary operators (in precedence order):
34−
35−==== =====================
36− Meaning
37−==== =====================
38−\+ Numeric addition
39−\- Numeric subtraction
40−\* Numeric multiplication
41−/ Numeric division
42−% Numeric modulus
43−== Equality check
44−!= Inequality check
45−< Less than
46−<= Less than or equal
47−> Greater than
48−>= Greater than or equal
49−&& Boolean AND
50−|| Boolean OR
51−& Binary AND
52−\| Binary OR
53−^ Binary XOR
54−<< Shift Left
55−>> Shift Right
56−\>>> Zero-Fill Shift Right
57−++ String concatenation
58−==== =====================
59−
60−Literal Values
61−--------------
62−
63−Numeric literals can be integers or floating point numbers. Numbers in hexadecimal notation should be preceded by the characters ``0x``::
64−
65− 16
66− 16.0
67− 0xF0
68−
69−String literals are enclosed in double-quotes and may extend over multiple lines. Line breaks should be surrounded by slashes as follows::
70−
71− "Hello World"
72−
73− "Hello \
74− \World"
75−
76−The two boolean literals are ``true`` and ``false``.
77−
78−Array Literals
79−--------------
80−
81−Array literals are surrounded by square brackets, as in Javascript::
82−
83− []
84− [1, 2, 3]
85−
86−Record Literals
87−---------------
88−
89−Record literals are surrounded by braces, as in Javascript::
90−
91− {}
92− { foo: "Foo", bar: 1 }
93−
94−Array Indexing
95−--------------
96−
97−To retrieve the element of an array at an index, use the ``!!`` operator::
98−
99− arr !! 0
100−
101−This example corresponds to the Javascript ``arr[0]``.
102−
103−Property Accessors
104−------------------
105−
106−To access a property of a record, use a dot, followed by the property name, as in Javascript::
107−
108− rec.propertyName
109−
110−Functions
111−---------
112−
113−Functions are introduced by using a backslash followed by a list of argument names::
114−
115− example1 = \a b -> a + b
116−
117−which would correspond to the following Javascript::
118−
119− function example1(a) {
120− return function (b) {
121− return a + b;
122− }
123− }
124−
125−Function application is indicated by just the juxtaposition of a function with its arugments::
126−
127− example1 10 20
128−
129−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::
130−
131− f [] [] = []
132− f (x:xs) (y:ys) = x + y : f xs ys
133−
134−If-Then-Else Expressions
135−------------------------
136−
137−The ``if``, ``then`` and ``else`` keywords can be used to create conditional expressions. In this case, the ``else`` block is always required.
138−
139−For example::
140−
141− conditional = if 2 > 1 then "ok" else "oops"
142−
143−Do Notation
144−-----------
145−
146−The `do` keyword introduces simple syntactic sugar for monadic expressions.
147−
148−Here is an example, using the maybe monad::
149−
150− data Maybe a = Nothing | Just a
151−
152− instance Monad Maybe where
153− ret = Just
154− (>>=) Nothing _ = Nothing
155− (>>=) (Just a) f = f a
156−
157− isEven n | n % 2 == 0 = Just {}
158− isEven _ = Nothing
159−
160− evenSum a b = do
161− n <- a
162− m <- b
163− let sum = n + m
164− isEven sum
165− ret sum
166−
167−``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``.
168−
169−When using `do` notation, the corresponding type constructor must be an instance of the `Prelude.Monad` type class, which defines the ``ret`` and ``>>=`` functions.
170−
171−Statements can have the following form:
172−
173−- ``a <- x`` which desugars to ``m.bind x (\a -> ...)` `
174−- ``let a = x`` which desugars to ``(\a -> ...)(x)``
175−- ``x`` which desugars to ``m.bind x (\_ -> ...)`` or just ``x`` if this is the last statement.
176−
177−Binders can be used on the left hand side of ``<-`` or ``=``. For example::
178−
179− test arr = do
180− (x:y:_) <- arr
181− ret (x + y)
182−
183−A pattern match failure will generate a runtime exception, just as in the case of a regular ``case`` statement.
184−
185−Operators
186−---------
187−
188−In addition to the standard operators, user-defined infix operators can be created by enclosing names in parentheses.
189−
190−E.g. to create a synonym for string concatenation::
191−
192− (<>) = \s1 s2 -> s1 ++ s2
193−
194− greeting = "Hello" <> "World!"
195−
196−Regular functions can be used as operators by enclosing their names in backticks::
197−
198− foo = \x y -> x * y + y
199−
200− test = 10 `foo` 20
201−
202−Fixity declarations can associate a precedence level, which is a natural number, to a user-defined operator, and specify which way it associates::
203−
204− infixl 5 <>
205− infixr 7 %%
206−
207−Record Updates
208−--------------
209−
210−Properties on records can be updated using the following syntax::
211−
212− o { key = value, ..., key = value }
213−
214−For example, the following function increments the ``foo`` property on its argument::
215−
216− incr o = o { foo = o.foo + 1 }
217−
218−The generated Javascript assumes the existence of a method called ``Object.extend`` such that ``Object.extend(o, p)`` takes an object ``o`` and generates a shallow copy of ``o`` including the properties of ``p``. A simple JQuery implementation of this specification is::
219−
220− Object.prototype.extend = function(o, p) {
221− return $.extend({}, o, p);
222− };
docs/source/typeclasses.rstdeleted−26
@@ -1,26 +0,0 @@
1−Type Classes
2−============
3−
4−PureScript has basic support for type classes via the `class` and `instance` keywords.
5−
6−Type class instances must be of the form `String`, `Number`, `Boolean`, `[t]` or `C t1 ... tn`, and only a single type class parameter is supported.
7−
8−Type class instances are resolved based on the order in which they appeared in the source files. In particular, overlapping instances are permitted.
9−
10−Here is an example of the `Show` typeclass, with instances for Strings, Booleans and arrays::
11−
12− class Show a where
13− show :: a -> String
14−
15− instance Show String where
16− show s = s
17−
18− instance Show Boolean where
19− show true = "true"
20− show false = "false"
21−
22− instance (Show a) => Show [a] where
23− show [] = "[]"
24− show (x:xs) = show x ++ " : " ++ showArray xs
25−
26− example = show [true, false]
docs/source/types.rstdeleted−159
@@ -1,159 +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 one 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 ``Foo``s are constructed.
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−::
84− forall r. { foo :: Number, bar :: Number | r } -> Number
85−
86−Here, the type variable ``r`` has kind ``# *`` - it represents a `row` of `types`. It can be instantiated with any row of named types.
87−
88−In other words, ``addProps`` accepts any record which has properties ``Foo`` and ``Bar``, and *any other record properties*.
89−
90−Therefore, the following application compiles::
91−
92− addProps { foo: 1, bar: 2, baz: 3 }
93−
94−even though the type of ``addProps`` does not mention the property ``baz``. However, the following does not compile::
95−
96− addProps { foo: 1 }
97−
98−since the `bar` property is missing.
99−
100−Rank N Types
101−------------
102−
103−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.
104−
105−In most cases, a type annotation is necessary when using this feature.
106−
107−As an example, we can pass a polymorphic function as an argument to another function::
108−
109− poly :: (forall a. a -> a) -> Boolean
110− poly f = (f 0 < 1) == f true
111−
112−Notice that the polymorphic function's type argument is instantiated to both `Number` and `Boolean`.
113−
114−An argument to ``poly`` must indeed be polymorphic. For example, the following fails::
115−
116− test = poly (\n -> n + 1)
117−
118−since the skolemized type variable ``a`` does not unify with ``Number``.
119−
120−Rows
121−----
122−
123−A row of types represents an unordered collection of named types without duplicates.
124−
125−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.
126−
127−To denote a closed row, separate the fields with commas, with each label separated from its type with a double colon::
128−
129− (name :: String, age :: Number)
130−
131−It may be necessary, depending on the context, to surround a row in parentheses.
132−
133−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::
134−
135− (name :: String, age :: Number | r)
136−
137−Type Synonyms
138−-------------
139−
140−For convenience, it is possible to declare a synonym for a type using the ``type`` keyword. Type synonyms can include type arguments.
141−
142−For example::
143−
144− type Foo = { foo :: Number, bar Number }
145−
146− addFoo :: Foo -> Number
147− addFoo = \o -> o.foo + o.bar
148−
149−Constrained Types
150−-----------------
151−
152−Polymorphic types may be predicated on one or more ``constraints``. See the chapter on type classes for more information.
153−
154−Type Annotations
155−----------------
156−
157−Most types can be inferred (not including Rank N Types and constrained types), but annotations can optionally be provided using a double-colon::
158−
159− one = 1 :: Number
examples/.gitignoredeleted−1
@@ -1 +0,0 @@
1−shelltest/tests
examples/failing/Arrays.pursdeleted−5
@@ -1,5 +0,0 @@
1−module Arrays where
2−
3− import Prelude
4−
5− test = \arr -> arr !! (0 !! 0)
examples/failing/Do.pursdeleted−8
@@ -1,8 +0,0 @@
1−module Do where
2−
3−test1 = do let x = 1
4−
5−test2 y = do x <- y
6−
7−test3 = do ret 1
8− ret 2
examples/failing/Import.pursdeleted−3
@@ -1,3 +0,0 @@
1−module Module where
2−
3− import UndefinedModule
examples/failing/KindError.pursdeleted−3
@@ -1,3 +0,0 @@
1−module KindError where
2−
3− data KindError f a = One f | Two f a
examples/failing/LocalVars.pursdeleted−8
@@ -1,8 +0,0 @@
1−module LocalVars where
2−
3− import Prelude
4−
5− bad = \x -> {
6− x = x + 1;
7− return x;
8− }
examples/failing/ModuleDeps.pursdeleted−7
@@ -1,7 +0,0 @@
1−module M1 where
2−
3−import M2
4−
5−module M2 where
6−
7−import M1
examples/failing/NullaryAbs.pursdeleted−3
@@ -1,3 +0,0 @@
1−module NullaryAbs where
2−
3− func = \ -> "no"
examples/failing/PatternScope.pursdeleted−12
@@ -1,12 +0,0 @@
1−module PatternScope where
2−
3− import Prelude
4−
5− -- Pattern scope doesn't leak
6− foobar = \x -> {
7− var y = case x of
8− z | z % 2 == 0 -> 1
9− _ -> 2;
10− return z;
11− }
12−
examples/failing/Rank2Types.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Rank2Types where
2−
3− import Prelude
4−
5− foreign import test :: (forall a. a -> a) -> Number
6−
7− test1 = test (\n -> n + 1)
examples/failing/ReadShow.pursdeleted−7
@@ -1,7 +0,0 @@
1−module ReadShow where
2−
3− foreign import read :: forall a. String -> a
4−
5− foreign import show :: forall a. a -> String
6−
7− test = \x -> show (read x)
examples/failing/Reserved.pursdeleted−4
@@ -1,4 +0,0 @@
1−module Reserved where
2−
3−(<) :: Number -> Number -> Number
4−(<) a b = !(a >= b)
examples/failing/Shadowed.pursdeleted−14
@@ -1,14 +0,0 @@
1−module Shadowed where
2−
3−import Prelude
4−
5−a = [1, 2]
6−
7−foo = {
8− var x = a !! 0;
9− var a = 0;
10−
11− a = a + 1;
12−
13− return x + a;
14− }
examples/failing/SkolemEscape.pursdeleted−5
@@ -1,5 +0,0 @@
1−module SkolemEscape where
2−
3− foreign import foo :: (forall a. a -> a) -> Number
4−
5− test = \x -> foo x
examples/failing/TypeClassInstances.pursdeleted−8
@@ -1,8 +0,0 @@
1−module TypeClassInstances 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/TypeClasses.pursdeleted−7
@@ -1,7 +0,0 @@
1−module TypeClasses where
2−
3−class Show a where
4− show :: a -> String
5−
6−instance TypeClasses.Show ([[String]]) where
7− show _ = "array"
examples/failing/TypeClasses2.pursdeleted−15
@@ -1,15 +0,0 @@
1−module TC1 where
2−
3−class Show a where
4− show :: a -> String
5−
6−module TC2 where
7−
8−instance TC1.Show String where
9− show s = s
10−
11−module TC3 where
12−
13−import TC1
14−
15−test = show "testing"
examples/failing/TypeError.pursdeleted−5
@@ -1,5 +0,0 @@
1−module TypeError where
2−
3− import Prelude
4−
5− test = 1 ++ "A"
examples/failing/TypeSynonyms.pursdeleted−5
@@ -1,5 +0,0 @@
1−module TypeSynonyms where
2−
3−type T1 = [T2]
4−
5−type T2 = T1
examples/passing/Applicative.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Applicative where
2−
3−class Applicative f where
4− pure :: forall a. a -> f a
5− (<*>) :: forall a b. f (a -> b) -> f a -> f b
6−
7−data Maybe a = Nothing | Just a
8−
9−instance Applicative Maybe where
10− pure = Just
11− (<*>) (Just f) (Just a) = Just (f a)
12− (<*>) _ _ = Nothing
13−
14−module Main where
15−
16−main = Trace.trace "Done"
examples/passing/ArrayType.pursdeleted−17
@@ -1,17 +0,0 @@
1−module ArrayType where
2−
3−test :: [] Number
4−test = [1, 2, 3]
5−
6−class Functor f where
7− fmap :: forall a b. (a -> b) -> f a -> f b
8−
9−foreign import (:) :: forall a. a -> [a] -> [a]
10−
11−instance Functor [] where
12− fmap _ [] = []
13− fmap f (x:xs) = f x : fmap f xs
14−
15−module Main where
16−
17−main = Trace.trace "Done"
examples/passing/Arrays.pursdeleted−27
@@ -1,27 +0,0 @@
1−module ArraysTests where
2−
3−import Prelude
4−
5−test1 arr = arr !! 0 + arr !! 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−module Main where
25−
26−main = Trace.trace "Done"
27−
examples/passing/Assign.pursdeleted−38
@@ -1,38 +0,0 @@
1−module Assign where
2−
3− import Prelude
4−
5− sum = \n -> {
6− var x = 0;
7− for (i <- 0 until n) {
8− x = x + i;
9− }
10− return x;
11− }
12−
13− arr = [1, 2]
14−
15− foo = {
16− var x = 0; -- mutable
17− var y = 1; -- immutable
18−
19− -- x should not be inlined since x is mutable
20− while (x < 10) {
21− x = x + 1;
22− }
23−
24− var z1 = arr !! x; -- immutable
25− var b = (\x -> z1) 2; -- z1 should not be inlined since x is bound
26−
27− var z2 = arr !! x; -- immutable
28− var z3 = arr !! x; -- immutable
29− var a = (\z2 -> z2) 2; -- z3 should not be inlined since z2 is bound
30−
31− -- y should be inlined
32− -- z3 should be inlined
33− return x + y + z1 + z2 + z3 + a + b;
34− }
35−
36−module Main where
37−
38−main = Trace.trace "Done"
examples/passing/Auto.pursdeleted−15
@@ -1,15 +0,0 @@
1−module Auto 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−module Main where
14−
15−main = Trace.trace "Done"
examples/passing/Category.pursdeleted−15
@@ -1,15 +0,0 @@
1−module Category where
2−
3−class Category c where
4− id :: forall x. c x x
5− (<|) :: forall x y z. c y z -> c x y -> c x z
6−
7−instance Category (->) where
8− id = Prelude.id
9− (<|) = Prelude.(<|)
10−
11−module Main where
12−
13−import Category
14−
15−main = Trace.trace (id "Done")
examples/passing/Church.pursdeleted−18
@@ -1,18 +0,0 @@
1−module Church where
2−
3− type List a = forall r. r -> (a -> r -> r) -> r
4−
5− empty :: forall a. List a
6− empty = \r f -> r
7−
8− cons :: forall a. a -> List a -> List a
9− cons = \a l r f -> f a (l r f)
10−
11− append :: forall a. List a -> List a -> List a
12− append = \l1 l2 r f -> l2 (l1 r f) f
13−
14− test = append (cons 1 empty) (cons 2 empty)
15−
16−module Main where
17−
18−main = Trace.trace "Done"
examples/passing/Conditional.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Conditional where
2−
3− fns = \f -> if f true then f else \x -> x
4−
5− not = \x -> if x then false else true
6−
7−module Main where
8−
9−main = Trace.trace "Done"
examples/passing/Cons.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Cons where
2−
3− import Prelude
4− import Arrays
5−
6− test1 = \xs -> 1 : xs
7−
8− test2 = 1 : 2 : 3 : []
9−
10−module Main where
11−
12−main = Trace.trace "Done"
examples/passing/Console.pursdeleted−13
@@ -1,13 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Eff
5−import Trace
6−
7−replicateM_ :: forall m a. (Monad m) => Number -> m a -> m {}
8−replicateM_ 0 _ = ret {}
9−replicateM_ n act = do
10− act
11− replicateM_ (n - 1) act
12−
13−main = replicateM_ 10 (trace "Hello World!")
examples/passing/DataAndType.pursdeleted−9
@@ -1,9 +0,0 @@
1−module DataAndType where
2−
3−data A = A B
4−
5−type B = A
6−
7−module Main where
8−
9−main = Trace.trace "Done"
examples/passing/DataImport.pursdeleted−13
@@ -1,13 +0,0 @@
1−module M1 where
2−
3−data Test = MkTest String
4−
5−module Main where
6−
7−import M1
8−
9−unTest (MkTest s) = s
10−
11−main = do
12− let x = unTest (MkTest "Done")
13− Trace.trace x
examples/passing/Do.pursdeleted−65
@@ -1,65 +0,0 @@
1−module Do where
2−
3−import Prelude
4−
5−data Maybe a = Nothing | Just a
6−
7−instance Prelude.Monad Maybe where
8− ret = Just
9− (>>=) Nothing _ = Nothing
10− (>>=) (Just a) f = f a
11−
12−test1 = \_ -> do
13− Just "abc"
14−
15−test2 = \_ -> do
16− (x : _) <- Just [1, 2, 3]
17− (y : _) <- Just [4, 5, 6]
18− Just (x + y)
19−
20−test3 = \_ -> do
21− Just 1
22− Nothing :: Maybe Number
23− Just 2
24−
25−test4 mx my = do
26− x <- mx
27− y <- my
28− Just (x + y + 1)
29−
30−test5 mx my mz = do
31− x <- mx
32− y <- my
33− let sum = x + y
34− z <- mz
35− Just (z + sum + 1)
36−
37−test6 mx = \_ -> do
38− let Just x = mx
39− Just x
40−
41−test8 = \_ -> do
42− Just (do
43− Just 1)
44−
45−(<$>) :: forall a b. (a -> b) -> Maybe a -> Maybe b
46−(<$>) f m = do
47− a <- m
48− ret (f a)
49−
50−(<*>) :: forall a b. (Maybe (a -> b)) -> Maybe a -> Maybe b
51−(<*>) f m = do
52− g <- f
53− a <- m
54− ret (g a)
55−
56−forever :: forall m a b. (Monad m) => m a -> m b
57−forever a = do
58− a
59− forever a
60−
61−test9 = \_ -> (+) <$> Just 1 <*> Just 2
62−
63−module Main where
64−
65−main = Trace.trace "Done"
examples/passing/Dollar.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Dollar where
2−
3−($) :: forall a b. (a -> b) -> a -> b
4−($) f x = f x
5−
6−infixr 1000 $
7−
8−id x = x
9−
10−test1 x = id $ id $ id $ id $ x
11−
12−test2 x = id id $ id x
13−
14−module Main where
15−
16−main = Trace.trace "Done"
examples/passing/Eff.pursdeleted−27
@@ -1,27 +0,0 @@
1−module TestEff where
2−
3−import Prelude
4−import Eff
5−import ST
6−import Errors
7−import Trace
8−
9−test1 = catchError (\s -> ret 0) $ do
10− trace "Testing"
11− throwError "Error!"
12−
13−test2 = runPure $ runST $ do
14− ref <- newSTRef 0
15− modifySTRef ref $ \n -> n + 1
16− readSTRef ref
17−
18−module Main where
19−
20−import Prelude
21−import Eff
22−import TestEff
23−
24−main = do
25− n <- test1
26− Trace.print n
27− Trace.print test2
examples/passing/ExternData.pursdeleted−19
@@ -1,19 +0,0 @@
1−module ExternData where
2−
3− foreign import data IO :: * -> *
4−
5− foreign import fmap :: forall a b. IO a -> (a -> b) -> IO b
6−
7− foreign import ret :: forall a. a -> IO a
8−
9− foreign import bind :: forall a b. IO a -> (a -> IO b) -> IO b
10−
11− foreign import showMessage :: String -> IO { }
12−
13− foreign import prompt :: IO String
14−
15− main = \_ -> prompt `bind` \s -> showMessage s
16−
17−module Main where
18−
19−main = Trace.trace "Done"
examples/passing/ExternRaw.pursdeleted−15
@@ -1,15 +0,0 @@
1−module ExternRaw 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−module Main where
14−
15−main = Trace.trace "Done"
examples/passing/FFI.pursdeleted−16
@@ -1,16 +0,0 @@
1−module FFI where
2−
3−foreign import foo :: String -> String
4−
5−bar :: String -> String
6−bar _ = foo "test"
7−
8−module FFIModuleTest where
9−
10−import FFI
11−
12−baz _ = foo "test"
13−
14−module Main where
15−
16−main = Trace.trace "Done"
examples/passing/Functions.pursdeleted−17
@@ -1,17 +0,0 @@
1−module Functions 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−module Main where
16−
17−main = Trace.trace "Done"
examples/passing/Guards.pursdeleted−16
@@ -1,16 +0,0 @@
1−module Guards 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−module Main where
15−
16−main = Trace.trace "Done"
examples/passing/IfThenElse.pursdeleted−42
@@ -1,42 +0,0 @@
1−module IfThenElse where
2−
3− import Prelude
4−
5− testIf =
6− {
7− var x = 0;
8− if (x == 0) {
9− x = x + 1;
10− }
11− return x;
12− }
13−
14− testIfElse =
15− {
16− var x = 0;
17− if (x == 0) {
18− x = x + 1;
19− } else {
20− x = x - 1;
21− }
22− return x;
23− }
24−
25− testIfElseIf = \x ->
26− {
27− var y = x;
28− while (y > 1) {
29− if (y % 3 == 0) {
30− y = y / 3;
31− } else if (y % 3 == 1) {
32− y = (y - 1) % 3;
33− } else {
34− y = y * 4 + 1;
35− }
36− }
37− return y;
38− }
39−
40−module Main where
41−
42−main = Trace.trace "Done"
examples/passing/Import.pursdeleted−16
@@ -1,16 +0,0 @@
1−module M1 where
2−
3− id :: forall a. a -> a
4− id = \x -> x
5−
6− foo = id
7−
8−module M2 where
9−
10− import M1
11−
12− main = \_ -> foo 42
13−
14−module Main where
15−
16−main = Trace.trace "Done"
examples/passing/List.pursdeleted−10
@@ -1,10 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Eff
5−import Arrays
6−import Global
7−
8−main = do
9− let test1 = concat [1, 2, 3] [4, 5, 6]
10− Trace.print test1
examples/passing/Match.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Match where
2−
3− data Foo a = Foo
4−
5− foo = \f -> case f of Foo -> "foo"
6−
7−module Main where
8−
9−main = Trace.trace "Done"
examples/passing/Maybe.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Maybe
5−import Global
6−
7−main = do
8− let test1 = fromMaybe 0 $ do
9− a <- Just 1
10− b <- Just 2
11− ret (a + b)
12− Trace.print test1
examples/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 = Trace.trace "Done"
examples/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 = Trace.trace "Done"
examples/passing/Monad.pursdeleted−32
@@ -1,32 +0,0 @@
1−module Monad where
2−
3− type Monad m = { ret :: forall a. a -> m a
4− , bind :: forall a b. m a -> (a -> m b) -> m b }
5−
6− data Id a = Id a
7−
8− id :: Monad Id
9− id = { ret : Id
10− , bind : \ma f -> case ma of Id a -> f a }
11−
12− data Maybe a = Nothing | Just a
13−
14− maybe :: Monad Maybe
15− maybe = { ret : Just
16− , bind : \ma f -> case ma of
17− Nothing -> Nothing
18− Just a -> f a
19− }
20−
21− test :: forall m. Monad m -> m Number
22− test = \m -> m.bind (m.ret 1) (\n1 ->
23− m.bind (m.ret "Test") (\n2 ->
24− m.ret n1))
25−
26− test1 = test id
27−
28− test2 = test maybe
29−
30−module Main where
31−
32−main = Trace.trace "Done"
examples/passing/MutRec.pursdeleted−21
@@ -1,21 +0,0 @@
1−module MutRec 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−module Main where
20−
21−main = Trace.trace "Done"
examples/passing/NamedPatterns.pursdeleted−9
@@ -1,9 +0,0 @@
1−module NamedPatterns where
2−
3− foo = \x -> case x of
4− y@{ foo = "Foo" } -> y
5− y -> y
6−
7−module Main where
8−
9−main = Trace.trace "Done"
examples/passing/Nested.pursdeleted−9
@@ -1,9 +0,0 @@
1−module Nested 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−module Main where
8−
9−main = Trace.trace "Done"
examples/passing/ObjectSynonym.pursdeleted−15
@@ -1,15 +0,0 @@
1−module ObjectSynonym 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−module Main where
14−
15−main = Trace.trace "Done"
examples/passing/ObjectUpdate.pursdeleted−20
@@ -1,20 +0,0 @@
1−module ObjectUpdate 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−module Main where
19−
20−main = Trace.trace "Done"
examples/passing/Objects.pursdeleted−20
@@ -1,20 +0,0 @@
1−module Objects 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−module Main where
19−
20−main = Trace.trace "Done"
examples/passing/OneConstructor.pursdeleted−9
@@ -1,9 +0,0 @@
1−module OneConstructor where
2−
3−data One a = One a
4−
5−one (One a) = a
6−
7−module Main where
8−
9−main = Trace.trace "Done"
examples/passing/Operators.pursdeleted−78
@@ -1,78 +0,0 @@
1−module Operators1 where
2−
3− import Prelude ((++))
4−
5− (@@) :: forall a b. (a -> b) -> a -> b
6− (@@) = \f x -> f x
7−
8− foo :: String -> String
9− foo = \s -> s
10−
11− test8 = foo @@ "Hello World"
12−
13− bar = \s1 s2 -> s1 ++ s2
14−
15−module Operators2 where
16−
17− import Prelude
18−
19− test1 :: forall n. (Num n) => n -> n -> (n -> n -> n) -> n
20− test1 x y z = x * y + z x y
21−
22− test2 = (\x -> x.foo false) { foo : \_ -> 1 }
23−
24− test3 = (\x y -> x)(1 + 2 * (1 + 2)) (true && (false || false))
25−
26− k = \x -> \y -> x
27−
28− test4 = 1 `k` 2
29−
30− infixl 5 %%
31−
32− (%%) :: Number -> Number -> Number
33− (%%) x y = x * y + y
34−
35− test5 = 1 %% 2 %% 3
36−
37− test6 = ((\x -> x) `k` 2) 3
38−
39− (<>) = \s1 s2 -> s1 ++ s2
40−
41− test7 = "Hello" <> "World!"
42−
43− test9 = Operators1.foo Operators1.@@ "Hello World"
44−
45− test10 = "Hello" `Operators1.bar` "World"
46−
47− (...) :: forall a. [a] -> [a] -> [a]
48− (...) = \as -> \bs -> as
49−
50− test11 = [1, 2, 3] ... [4, 5, 6]
51−
52− test12 (<%>) a b = a <%> b
53−
54−module Main where
55−
56−import Operators1
57−import Operators2
58−
59−import Prelude
60−import Eff
61−import Trace
62−import Global
63−import Arrays
64−
65−main = do
66− print $ test1 1 2 $ \x y -> x + y
67− print test2
68− print test3
69− print test4
70− print test5
71− print test6
72− print test7
73− print test8
74− print test9
75− print test10
76− print test11
77− print (test12 k 1 2)
78−
examples/passing/OptimizerBug.pursdeleted−11
@@ -1,11 +0,0 @@
1−module OptimizerBug where
2−
3−import Prelude
4−
5−x = 1 + y
6−
7−y = x
8−
9−module Main where
10−
11−main = Trace.trace "Done"
examples/passing/Patterns.pursdeleted−30
@@ -1,30 +0,0 @@
1−module Patterns 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−module Main where
29−
30−main = Trace.trace "Done"
examples/passing/Person.pursdeleted−15
@@ -1,15 +0,0 @@
1−module Person where
2−
3− import Prelude ((++))
4−
5− data Person = Person { name :: String, age :: Number }
6−
7− foreign import itoa :: Number -> String
8−
9− showPerson :: Person -> String
10− showPerson = \p -> case p of
11− Person o -> o.name ++ ", aged " ++ itoa(o.age)
12−
13−module Main where
14−
15−main = Trace.trace "Done"
examples/passing/Rank2Data.pursdeleted−31
@@ -1,31 +0,0 @@
1−module Rank2Data 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−module Main where
30−
31−main = Trace.trace "Done"
examples/passing/Rank2Types.pursdeleted−25
@@ -1,25 +0,0 @@
1−module Rank2Types where
2−
3− import Prelude
4−
5− test1 :: (forall a. (a -> a)) -> Number
6− test1 = \f -> f 0
7−
8− foreign import data ST :: * -> * -> *
9−
10− foreign import runST :: forall a. (forall s. ST s a) -> a
11−
12− foreign import exampleST :: forall s. ST s Number
13−
14− testST = \_ -> runST exampleST
15−
16− foreign import push :: forall el. el -> [el] -> [el]
17−
18− replicateM :: forall m a. (forall a. a -> m a) -> (forall a b. m a -> (a -> m b) -> m b) -> Number -> m a -> m [a]
19− replicateM = \ret bind n m -> case n of
20− 0 -> ret []
21− n -> bind m (\x -> bind (replicateM ret bind (n - 1) m) (\xs -> ret (push x xs)))
22−
23−module Main where
24−
25−main = Trace.trace "Done"
examples/passing/Recursion.pursdeleted−12
@@ -1,12 +0,0 @@
1−module Recursion 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−module Main where
11−
12−main = Trace.trace "Done"
examples/passing/RedefinedFixity.pursdeleted−18
@@ -1,18 +0,0 @@
1−module M1 where
2−
3−($) f a = f a
4−
5−infixr 1000 $
6−
7−module M2 where
8−
9−import M1
10−
11−module M3 where
12−
13−import M1
14−import M2
15−
16−module Main where
17−
18−main = Trace.trace "Done"
examples/passing/TailCall.pursdeleted−17
@@ -1,17 +0,0 @@
1−module TailCall 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−module Main where
16−
17−main = Trace.trace "Done"
examples/passing/Tick.pursdeleted−7
@@ -1,7 +0,0 @@
1−module Tick where
2−
3−test' x = x
4−
5−module Main where
6−
7−main = Trace.trace "Done"
examples/passing/TopLevelCase.pursdeleted−20
@@ -1,20 +0,0 @@
1−module TopLevelCase 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−module Main where
19−
20−main = Trace.trace "Done"
examples/passing/TypeClasses.pursdeleted−69
@@ -1,69 +0,0 @@
1−module TypeClasses 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 (Prelude.Show a) => Prelude.Show (Data a) where
20− show (Data a) = "Data (" ++ show a ++ ")"
21−
22−test3 = \_ -> show (Data "testing")
23−
24−instance Prelude.Monad Data where
25− ret = Data
26− (>>=) (Data a) f = f a
27−
28−data Maybe a = Nothing | Just a
29−
30−instance Prelude.Monad Maybe where
31− ret = Just
32− (>>=) Nothing _ = Nothing
33− (>>=) (Just a) f = f a
34−
35−test4 :: forall a m. (Monad m) => a -> m Number
36−test4 = \_ -> ret 1
37−
38−test5 = \_ -> Just 1 >>= \n -> ret (n + 1)
39−
40−module TypeClasses2 where
41−
42−import Prelude
43−import TypeClasses
44−
45−instance (Prelude.Show a) => Prelude.Show [a] where
46− show [] = "[]"
47− show (x:xs) = show x ++ ", " ++ show xs
48−
49−test6 = \_ -> show ["testing"]
50−
51−instance Prelude.Monad (->) r where
52− ret a r = a
53− (>>=) f g r = g (f r) r
54−
55−ask r = r
56−
57−runReader r f = f r
58−
59−test9 _ = runReader 0 $ do
60− n <- ask
61− ret $ n + 1
62−
63−module Main where
64−
65−import Prelude
66−import TypeClasses
67−
68−main = Trace.trace (test7 "Done")
69−
examples/passing/TypeDecl.pursdeleted−20
@@ -1,20 +0,0 @@
1−module TypeDecl where
2−
3− id :: forall a. (a) -> a
4− id = \x -> x
5−
6− k :: String -> Number -> String
7− k = \x -> \y -> x
8−
9− iterate :: forall a. Number -> (a -> a) -> a -> a
10− iterate = \n -> \f -> \a -> {
11− var result = a;
12− for (i <- 0 until n) {
13− result = f result;
14− }
15− return result;
16− }
17−
18−module Main where
19−
20−main = Trace.trace "Done"
examples/passing/TypeSynonyms.pursdeleted−44
@@ -1,44 +0,0 @@
1−module TypeSynonyms 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 ->
12− {
13− var b = l1.get a;
14− var b1 = l2.set b c;
15− return l1.set a b1;
16− }
17− }
18−
19− type Pair a b = { fst :: a, snd :: b }
20−
21− fst :: forall a b. Lens (Pair a b) a
22− fst =
23− { get: \p -> p.fst
24− , set: \p -> \a -> { fst: a, snd: p.snd }
25− }
26−
27− test1 :: forall a b c. Lens (Pair (Pair a b) c) a
28− test1 = composeLenses fst fst
29−
30− import Arrays
31−
32− headLens :: forall a. Lens [a] a
33− headLens =
34− { get: \l -> head l
35− , set: \l a -> case l of
36− _:xs -> a : xs
37− }
38−
39− test2 :: forall a b c. Lens (Pair [Pair a b] c) a
40− test2 = composeLenses fst (composeLenses headLens fst)
41−
42−module Main where
43−
44−main = Trace.trace "Done"
examples/passing/iota.pursdeleted−11
@@ -1,11 +0,0 @@
1−module Iota 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−module Main where
10−
11−main = Trace.trace "Done"
examples/passing/s.pursdeleted−7
@@ -1,7 +0,0 @@
1−module S where
2−
3− s = \x y z -> x z (y z)
4−
5−module Main where
6−
7−main = Trace.trace "Done"
execTests.shdeleted−1
@@ -1 +0,0 @@
1−dist/build/tests/tests --run-js
libraries/.gitignoredeleted−1
@@ -1 +0,0 @@
1−*/all.js
libraries/jquery/jquery.pursdeleted−45
@@ -1,45 +0,0 @@
1−module JQuery where
2−
3− import Eff
4−
5− -- An effect type which indicates DOM manipulation
6− foreign import data DOM :: !
7−
8− -- The jQuery wrapper type
9− foreign import data JQuery :: *
10−
11− -- Wrapper function for jQuery selection $('..')
12− foreign import select "function select(selector) { return function () { return jQuery(selector); }; }" :: forall eff. String -> Eff (dom :: DOM | eff) JQuery
13−
14− -- Wrapper function for jQuery creation e.g. $('<div>')
15− foreign import create "function create(html) { return function () { return jQuery(html); }; }" :: forall eff. String -> Eff (dom :: DOM | eff) JQuery
16−
17− -- .attr({ ... })
18− foreign import attr "function attr(attrs) { return function(ob) { return function () { return ob.attr(attrs); }; }; }" :: forall eff attr. { | attr } -> JQuery -> Eff (dom :: DOM | eff) JQuery
19−
20− -- .css({ ... })
21− foreign import css "function css(props) { return function(ob) { return function () { return ob.css(props); }; }; }" :: forall eff css. { | css } -> JQuery -> Eff (dom :: DOM | eff) JQuery
22−
23− -- .append(...)
24− foreign import append "function append(ob1) { return function(ob) { return function () { return ob.append(ob1); }; }; }" :: forall eff. JQuery -> JQuery -> Eff (dom :: DOM | eff) JQuery
25−
26− -- .append(...)
27− foreign import appendText "function appendText(s) { return function(ob) { return function () { return ob.append(s); }; }; }" :: forall eff. String -> JQuery -> Eff (dom :: DOM | eff) JQuery
28−
29− -- Get the document body
30− foreign import body "function body() { return jQuery(document.body); }" :: forall eff. Eff (dom :: DOM | eff) JQuery
31−
32− -- Get the text content of an element
33− foreign import getText "function getText(ob) { return function() { return ob.text(); }; }" :: forall eff. JQuery -> Eff (dom :: DOM | eff) String
34−
35− -- Set the text content of an element
36− foreign import setText "function setText(text) { return function(ob) { return function() { ob.text(text); }; }; }" :: forall eff. String -> JQuery -> Eff (dom :: DOM | eff) JQuery
37−
38− -- Get the value of a text field
39− foreign import getValue "function getValue(ob) { return function() { return ob.val(); }; }" :: forall eff. JQuery -> Eff (dom :: DOM | eff) String
40−
41− -- Set the value of a text field
42− foreign import setValue "function setValue(val) { return function(ob) { return function() { return ob.val(val); }; }; }" :: forall eff. String -> JQuery -> Eff (dom :: DOM | eff) JQuery
43−
44− -- Register an event handler
45− foreign import on "function on(evt) { return function(act) { return function(ob) { return function() { return ob.on(evt, function() { act(); } ); }; }; }; }" :: forall eff a. String -> Eff eff a -> JQuery -> Eff (dom :: DOM | eff) JQuery
libraries/jquery/tests/.gitignoredeleted−1
@@ -1 +0,0 @@
1−jquery.js
libraries/jquery/tests/build.shdeleted−2
@@ -1,2 +0,0 @@
1−psc ../jquery.purs jquery.purs --magic-do --run-main -o jquery.js
2−
libraries/jquery/tests/index.htmldeleted−10
@@ -1,10 +0,0 @@
1−<!DOCTYPE html>
2−<html>
3−<head>
4−<title>JQuery Example</title>
5−<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.10.2/jquery.js"></script>
6−</head>
7−<body>
8−<script src="jquery.js"></script>
9−</body>
10−</html>
libraries/jquery/tests/jquery.pursdeleted−28
@@ -1,28 +0,0 @@
1−module Main where
2−
3−import Prelude
4−import Eff
5−import Trace
6−import JQuery
7−
8−main = do
9− -- Get the document body
10− b <- body
11−
12− -- Create a text box
13− div <- create "<div>"
14− input <- create "<input>"
15− "Your Name: " `appendText` div
16− input `append` div
17− div `append` b
18−
19− -- Create a paragraph to display a greeting
20− greeting <- create "<p>"
21− { color: "red" } `css` greeting
22− greeting `append` b
23−
24− -- Listen for change events on the text box
25− flip (on "change") input $ do
26− name <- getValue input
27− trace $ "Name changed to " ++ name
28− setText ("Hello, " ++ name) greeting
libraries/prelude/prelude.pursdeleted−910
@@ -1,910 +0,0 @@
1−module Prelude where
2−
3− foreign import data String :: *
4− foreign import data Number :: *
5− foreign import data Boolean :: *
6− foreign import data Array :: * -> *
7− foreign import data Function :: * -> * -> *
8−
9− id :: forall a. a -> a
10− id = \x -> x
11−
12− flip :: forall a b c. (a -> b -> c) -> b -> a -> c
13− flip = \f -> \b -> \a -> f a b
14−
15− konst :: forall a b. a -> b -> a
16− konst = \a -> \b -> a
17−
18− (|>) :: forall a b c. (a -> b) -> (b -> c) -> a -> c
19− (|>) = \f -> \g -> \a -> g (f a)
20−
21− infixr 5 |>
22−
23− (<|) :: forall a b c. (b -> c) -> (a -> b) -> a -> c
24− (<|) = flip (|>)
25−
26− infixr 5 <|
27−
28− ($) :: forall a b. (a -> b) -> a -> b
29− ($) f x = f x
30−
31− infixr 1000 $
32−
33− class Show a where
34− show :: a -> String
35−
36− instance Show String where
37− show s = s
38−
39− instance Show Boolean where
40− show true = "true"
41− show false = "false"
42−
43− foreign import showNumber "function showNumber(n) {\
44− \ return n.toString();\
45− \}" :: Number -> String
46−
47− instance Prelude.Show Number where
48− show = showNumber
49−
50− class Read a where
51− read :: String -> a
52−
53− instance Read String where
54− read s = s
55−
56− instance Read Boolean where
57− read "true" = true
58− read _ = false
59−
60− class Monad m where
61− ret :: forall a. a -> m a
62− (>>=) :: forall a b. m a -> (a -> m b) -> m b
63−
64− infixl 5 *
65− infixl 5 /
66− infixl 5 %
67−
68− infixl 7 -
69− infixl 7 +
70−
71− class Num a where
72− (+) :: a -> a -> a
73− (-) :: a -> a -> a
74− (*) :: a -> a -> a
75− (/) :: a -> a -> a
76− (%) :: a -> a -> a
77− negate :: a -> a
78−
79− foreign import numAdd "function numAdd(n1) {\
80− \ return function(n2) {\
81− \ return n1 + n2;\
82− \ };\
83− \}" :: Number -> Number -> Number
84−
85− foreign import numSub "function numSub(n1) {\
86− \ return function(n2) {\
87− \ return n1 - n2;\
88− \ };\
89− \}" :: Number -> Number -> Number
90−
91− foreign import numMul "function numMul(n1) {\
92− \ return function(n2) {\
93− \ return n1 * n2;\
94− \ };\
95− \}" :: Number -> Number -> Number
96−
97− foreign import numDiv "function numDiv(n1) {\
98− \ return function(n2) {\
99− \ return n1 / n2;\
100− \ };\
101− \}" :: Number -> Number -> Number
102−
103− foreign import numMod "function numMod(n1) {\
104− \ return function(n2) {\
105− \ return n1 % n2;\
106− \ };\
107− \}" :: Number -> Number -> Number
108−
109− foreign import numNegate "function numNegate(n) {\
110− \ return -n;\
111− \}" :: Number -> Number
112−
113− instance Num Number where
114− (+) = numAdd
115− (-) = numSub
116− (*) = numMul
117− (/) = numDiv
118− (%) = numMod
119− negate = numNegate
120−
121− infixl 9 ==
122− infixl 9 /=
123−
124− class Eq a where
125− (==) :: a -> a -> Boolean
126− (/=) :: a -> a -> Boolean
127−
128− -- Referential equality
129− data Ref a = Ref a
130−
131− foreign import refEq "function refEq(r1) {\
132− \ return function(r2) {\
133− \ return r1.value === r2.value;\
134− \ };\
135− \}" :: forall a. Ref a -> Ref a -> Boolean
136−
137− foreign import refIneq "function refIneq(r1) {\
138− \ return function(r2) {\
139− \ return r1.value !== r2.value;\
140− \ };\
141− \}" :: forall a. Ref a -> Ref a -> Boolean
142−
143− foreign import unsafeRefEq "function unsafeRefEq(r1) {\
144− \ return function(r2) {\
145− \ return r1 === r2;\
146− \ };\
147− \}" :: forall a. a -> a -> Boolean
148−
149− foreign import unsafeRefIneq "function unsafeRefIneq(r1) {\
150− \ return function(r2) {\
151− \ return r1 !== r2;\
152− \ };\
153− \}" :: forall a. a -> a -> Boolean
154−
155− instance Eq (Ref a) where
156− (==) = refEq
157− (/=) = refIneq
158−
159− instance Eq String where
160− (==) = unsafeRefEq
161− (/=) = unsafeRefIneq
162−
163− instance Eq Number where
164− (==) = unsafeRefEq
165− (/=) = unsafeRefIneq
166−
167− instance Eq Boolean where
168− (==) = unsafeRefEq
169− (/=) = unsafeRefIneq
170−
171− instance (Eq a) => Eq [a] where
172− (==) = unsafeRefEq
173− (/=) = unsafeRefIneq
174−
175− infixl 3 <
176− infixl 3 >
177− infixl 3 <=
178− infixl 3 >=
179−
180− class Ord a where
181− (<) :: a -> a -> Boolean
182− (>) :: a -> a -> Boolean
183− (<=) :: a -> a -> Boolean
184− (>=) :: a -> a -> Boolean
185−
186− foreign import numLess "function numLess(n1) {\
187− \ return function(n2) {\
188− \ return n1 < n2;\
189− \ };\
190− \}" :: Number -> Number -> Boolean
191−
192− foreign import numLessEq "function numLessEq(n1) {\
193− \ return function(n2) {\
194− \ return n1 <= n2;\
195− \ };\
196− \}" :: Number -> Number -> Boolean
197−
198− foreign import numGreater "function numGreater(n1) {\
199− \ return function(n2) {\
200− \ return n1 > n2;\
201− \ };\
202− \}" :: Number -> Number -> Boolean
203−
204− foreign import numGreaterEq "function numGreaterEq(n1) {\
205− \ return function(n2) {\
206− \ return n1 >= n2;\
207− \ };\
208− \}" :: Number -> Number -> Boolean
209−
210− instance Ord Number where
211− (<) = numLess
212− (>) = numGreater
213− (<=) = numLessEq
214− (>=) = numGreaterEq
215−
216− infixl 8 <<
217− infixl 8 >>
218− infixl 8 >>>
219−
220− infixl 10 &
221− infixl 10 |
222− infixl 10 ^
223−
224− class Bits b where
225− (<<) :: b -> Number -> b
226− (>>) :: b -> Number -> b
227− (>>>) :: b -> Number -> b
228− (&) :: b -> b -> b
229− (|) :: b -> b -> b
230− (^) :: b -> b -> b
231− complement :: b -> b
232−
233− foreign import numShl "function numShl(n1) {\
234− \ return function(n2) {\
235− \ return n1 << n2;\
236− \ };\
237− \}" :: Number -> Number -> Number
238−
239− foreign import numShr "function numShr(n1) {\
240− \ return function(n2) {\
241− \ return n1 >> n2;\
242− \ };\
243− \}" :: Number -> Number -> Number
244−
245− foreign import numZfShr "function numZfShr(n1) {\
246− \ return function(n2) {\
247− \ return n1 >>> n2;\
248− \ };\
249− \}" :: Number -> Number -> Number
250−
251− foreign import numAnd "function numAnd(n1) {\
252− \ return function(n2) {\
253− \ return n1 & n2;\
254− \ };\
255− \}" :: Number -> Number -> Number
256−
257− foreign import numOr "function numOr(n1) {\
258− \ return function(n2) {\
259− \ return n1 | n2;\
260− \ };\
261− \}" :: Number -> Number -> Number
262−
263− foreign import numXor "function numXor(n1) {\
264− \ return function(n2) {\
265− \ return n1 ^ n2;\
266− \ };\
267− \}" :: Number -> Number -> Number
268−
269− foreign import numComplement "function numComplement(n) {\
270− \ return ~n;\
271− \}" :: Number -> Number
272−
273− instance Bits Number where
274− (<<) = numShl
275− (>>) = numShr
276− (>>>) = numZfShr
277− (&) = numAnd
278− (|) = numOr
279− (^) = numXor
280− complement = numComplement
281−
282− infixl 4 !!
283−
284− foreign import (!!) "function $bang$bang(xs) {\
285− \ return function(n) {\
286− \ return xs[n];\
287− \ };\
288− \}" :: forall a. [a] -> Number -> a
289−
290− infixr 11 ||
291− infixr 11 &&
292−
293− class BoolLike b where
294− (&&) :: b -> b -> b
295− (||) :: b -> b -> b
296− not :: b -> b
297−
298− foreign import boolAnd "function boolAnd(b1) {\
299− \ return function(b2) {\
300− \ return b1 && b2;\
301− \ };\
302− \}" :: Boolean -> Boolean -> Boolean
303−
304− foreign import boolOr "function boolOr(b1) {\
305− \ return function(b2) {\
306− \ return b1 || b2;\
307− \ };\
308− \}" :: Boolean -> Boolean -> Boolean
309−
310− foreign import boolNot "function boolNot(b) {\
311− \ return !b;\
312− \}" :: Boolean -> Boolean
313−
314− instance BoolLike Boolean where
315− (&&) = boolAnd
316− (||) = boolOr
317− not = boolNot
318−
319− infixr 6 ++
320−
321− foreign import (++) "function $plus$plus(s1) {\
322− \ return function(s2) {\
323− \ return s1 + s2;\
324− \ };\
325− \}" :: String -> String -> String
326−
327−module Maybe where
328−
329− data Maybe a = Nothing | Just a
330−
331− maybe :: forall a b. b -> (a -> b) -> Maybe a -> b
332− maybe b _ Nothing = b
333− maybe _ f (Just a) = f a
334−
335− fromMaybe :: forall a. a -> Maybe a -> a
336− fromMaybe a = maybe a Prelude.id
337−
338− instance Prelude.Monad Maybe where
339− ret = Just
340− (>>=) m f = maybe Nothing f m
341−
342−module Either where
343−
344− data Either a b = Left a | Right b
345−
346− either :: forall a b c. (a -> c) -> (b -> c) -> Either a b -> c
347− either f _ (Left a) = f a
348− either _ g (Right b) = g b
349−
350− instance Prelude.Monad (Either e) where
351− ret = Right
352− (>>=) = either (\e _ -> Left e) (\a f -> f a)
353−
354−module Arrays where
355−
356− import Prelude
357− import Maybe
358−
359− head :: forall a. [a] -> a
360− head (x : _) = x
361−
362− headSafe :: forall a. [a] -> Maybe a
363− headSafe (x : _) = Just x
364− headSafe _ = Nothing
365−
366− tail :: forall a. [a] -> [a]
367− tail (_ : xs) = xs
368−
369− tailSafe :: forall a. [a] -> Maybe [a]
370− tailSafe (_ : xs) = Just xs
371− tailSafe _ = Nothing
372−
373− map :: forall a b. (a -> b) -> [a] -> [b]
374− map _ [] = []
375− map f (x:xs) = f x : map f xs
376−
377− foldr :: forall a b. (a -> b -> a) -> a -> [b] -> a
378− foldr f a (b : bs) = f (foldr f a bs) b
379− foldr _ a [] = a
380−
381− foldl :: forall a b. (a -> b -> b) -> b -> [a] -> b
382− foldl _ b [] = b
383− foldl f b (a:as) = foldl f (f a b) as
384−
385− foreign import length "function length(xs) { \
386− \ return xs.length; \
387− \}" :: forall a. [a] -> Number
388−
389− foreign import indexOf "function indexOf(l) {\
390− \ return function (e) {\
391− \ return l.indexOf(e);\
392− \ };\
393− \}" :: forall a. [a] -> a -> Number
394−
395− foreign import lastIndexOf "function lastIndexOf(l) {\
396− \ return function (e) {\
397− \ return l.lastIndexOf(e);\
398− \ };\
399− \}" :: forall a. [a] -> a -> Number
400−
401− foreign import concat "function concat(l1) {\
402− \ return function (l2) {\
403− \ return l1.concat(l2);\
404− \ };\
405− \}" :: forall a. [a] -> [a] -> [a]
406−
407− foreign import join "function join(l) {\
408− \ return l.join();\
409− \}" :: [String] -> String
410−
411− foreign import joinWith "function joinWith(l) {\
412− \ return function (s) {\
413− \ return l.join(s);\
414− \ };\
415− \}" :: [String] -> String -> String
416−
417− foreign import push "function push(l) {\
418− \ return function (e) {\
419− \ var l1 = l.slice();\
420− \ l1.push(e); \
421− \ return l1;\
422− \ };\
423− \}" :: forall a. [a] -> a -> [a]
424−
425− foreign import reverse "function reverse(l) {\
426− \ var l1 = l.slice();\
427− \ l1.reverse(); \
428− \ return l1;\
429− \}" :: forall a. [a] -> [a]
430−
431− foreign import shift "function shift(l) {\
432− \ var l1 = l.slice();\
433− \ l1.shift();\
434− \ return l1;\
435− \}" :: forall a. [a] -> [a]
436−
437− foreign import slice "function slice(s) {\
438− \ return function(e) {\
439− \ return function (l) {\
440− \ return l.slice(s, e);\
441− \ };\
442− \ };\
443− \}" :: forall a. Number -> Number -> [a] -> [a]
444−
445− foreign import sort "function sort(l) {\
446− \ var l1 = l.slice();\
447− \ l.sort();\
448− \ return l1;\
449− \}" :: forall a. [a] -> [a]
450−
451− foreign import splice "function splice(s) {\
452− \ return function(e) {\
453− \ return function(l1) { \
454− \ return function(l2) {\
455− \ return l2.splice(s, e, l1);\
456− \ }; \
457− \ }; \
458− \ };\
459− \}":: forall a. Number -> Number -> [a] -> [a] -> [a]
460−
461− infixr 6 :
462−
463− (:) :: forall a. a -> [a] -> [a]
464− (:) a = concat [a]
465−
466− concatMap :: forall a b. [a] -> (a -> [b]) -> [b]
467− concatMap [] f = []
468− concatMap (a:as) f = f a `concat` concatMap as f
469−
470− filter :: forall a. (a -> Boolean) -> [a] -> [a]
471− filter _ [] = []
472− filter p (x:xs) | p x = x : filter p xs
473− filter p (_:xs) = filter p xs
474−
475− empty :: forall a. [a] -> Boolean
476− empty [] = true
477− empty _ = false
478−
479− range :: Number -> Number -> [Number]
480− range lo hi = {
481− var ns = [];
482− for (n <- lo until hi) {
483− ns = push ns n;
484− }
485− return ns;
486− }
487−
488− zipWith :: forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
489− zipWith f (a:as) (b:bs) = f a b : zipWith f as bs
490− zipWith _ _ _ = []
491−
492− any :: forall a. (a -> Boolean) -> [a] -> Boolean
493− any _ [] = false
494− any p (a:as) = p a || any p as
495−
496− all :: forall a. (a -> Boolean) -> [a] -> Boolean
497− all _ [] = true
498− all p (a:as) = p a && all p as
499−
500− instance (Prelude.Show a) => Prelude.Show [a] where
501− show [] = "[]"
502− show (x:xs) = show x ++ " : " ++ show xs
503−
504−module Tuple where
505−
506− import Arrays
507−
508− type Tuple a b = { fst :: a, snd :: b }
509−
510− curry :: forall a b c. (Tuple a b -> c) -> a -> b -> c
511− curry f a b = f { fst: a, snd: b }
512−
513− uncurry :: forall a b c. (a -> b -> c) -> Tuple a b -> c
514− uncurry f t = f t.fst t.snd
515−
516− tuple :: forall a b. a -> b -> Tuple a b
517− tuple = curry Prelude.id
518−
519− zip :: forall a b. [a] -> [b] -> [Tuple a b]
520− zip = zipWith tuple
521−
522− unzip :: forall a b. [Tuple a b] -> Tuple [a] [b]
523− unzip (t:ts) = case unzip ts of
524− { fst = as, snd = bs } -> tuple (t.fst : as) (t.snd : bs)
525− unzip [] = tuple [] []
526−
527−module String where
528−
529− foreign import lengthS "function lengthS(s) {\
530− \ return s.length;\
531− \}" :: String -> Number
532−
533− foreign import charAt "function charAt(i) {\
534− \ return function(s) {\
535− \ return s.charAt(i); \
536− \ };\
537− \}" :: Number -> String -> String
538−
539− foreign import indexOfS "function indexOfS(s1) {\
540− \ return function(s2) {\
541− \ return s2.indexOf(s2);\
542− \ }; \
543− \}" :: String -> String -> Number
544−
545− foreign import lastIndexOfS "function lastIndexOfS(s1) {\
546− \ return function(s2) {\
547− \ return s2.lastIndexOf(s2);\
548− \ };\
549− \}" :: String -> String -> Number
550−
551− foreign import localeCompare "function localeCompare(s1) {\
552− \ return function(s2) { \
553− \ return s1.localeCompare(s2);\
554− \ };\
555− \}" :: String -> String -> Number
556−
557− foreign import replace "function replace(s1) {\
558− \ return function(s2) {\
559− \ return function(s3) {\
560− \ return s3.replace(s1, s2);\
561− \ };\
562− \ };\
563− \}" :: String -> String -> String -> String
564−
565− foreign import sliceS "function sliceS(st) {\
566− \ return function(e) {\
567− \ return function(s) {\
568− \ return s.slice(st, e);\
569− \ };\
570− \ };\
571− \}" :: Number -> Number -> String -> String
572−
573− foreign import split "function split(sep) {\
574− \ return function(s) {\
575− \ return s.split(s);\
576− \ };\
577− \}" :: String -> String -> [String]
578−
579− foreign import substr "function substr(n1) {\
580− \ return function(n2) {\
581− \ return function(s) {\
582− \ return s.substr(n1, n2);\
583− \ };\
584− \ };\
585− \}" :: Number -> Number -> String -> String
586−
587− foreign import substring "function substring(n1) {\
588− \ return function(n2) {\
589− \ return function(s) {\
590− \ return s.substring(n1, n2);\
591− \ };\
592− \ };\
593− \}" :: Number -> Number -> String -> String
594−
595− foreign import toLower "function toLower(s) {\
596− \ return s.toLower();\
597− \}" :: String -> String
598−
599− foreign import toUpper "function toUpper(s) {\
600− \ return s.toUpper();\
601− \}" :: String -> String
602−
603− foreign import trim "function trim(s) {\
604− \ return s.trim();\
605− \}" :: String -> String
606−
607−module Regex where
608−
609− foreign import data Regex :: *
610−
611− foreign import regex "function regex(s1) {\
612− \ return function(s2) {\
613− \ return new Regex(s1, s2);\
614− \ };\
615− \}" :: String -> String -> Regex
616−
617− foreign import test "function test(r) {\
618− \ return function (s) { \
619− \ return r.test(s);\
620− \ };\
621− \}" :: Regex -> String -> Boolean
622−
623− foreign import match "function match(r) {\
624− \ return function (s) {\
625− \ return s.match(r); \
626− \ };\
627− \}" :: Regex -> String -> [String]
628−
629− foreign import replaceR "function replaceR(r) {\
630− \ return function(s1) {\
631− \ return function(s2) { \
632− \ return s2.replace(r, s1);\
633− \ };\
634− \ };\
635− \}" :: Regex -> String -> String -> String
636−
637− foreign import search "function search(r) {\
638− \ return function (s) {\
639− \ return s.search(r);\
640− \ };\
641− \}" :: Regex -> String -> Number
642−
643−module Global where
644−
645− foreign import nan "var nan = NaN;" :: Number
646−
647− foreign import infinity "var infinity = Infinity;" :: Number
648−
649− foreign import toExponential "function toExponential(n) {\
650− \ return n.toExponential();\
651− \}" :: Number -> String
652−
653− foreign import toFixed "function toFixed(d) {\
654− \ return function(n) {\
655− \ return n.toFixed(d);\
656− \ };\
657− \}" :: Number -> Number -> String
658−
659− foreign import toPrecision "function toPrecision(d) {\
660− \ return function(n) {\
661− \ return n.toPrecision(d);\
662− \ };\
663− \}" :: Number -> Number -> String
664−
665− foreign import isFinite :: Number -> Boolean
666−
667− foreign import parseFloat :: String -> Number
668−
669− foreign import parseInt :: String -> Number
670−
671− foreign import encodeURIComponent :: String -> String
672−
673− foreign import decodeURIComponent :: String -> String
674−
675− foreign import encodeURI :: String -> String
676−
677− foreign import decodeURI :: String -> String
678−
679− foreign import isNaN :: Number -> Boolean
680−
681−module Math where
682−
683− foreign import abs "function abs(n){\
684− \ return Math.abs(n);\
685− \}" :: Number -> Number
686−
687− foreign import acos "function acos(n){\
688− \ return Math.acos(n);\
689− \}" :: Number -> Number
690−
691− foreign import asin "function asin(n){\
692− \ return Math.asin(n);\
693− \}" :: Number -> Number
694−
695− foreign import atan "function atan(n){\
696− \ return Math.atan(n);\
697− \}" :: Number -> Number
698−
699− foreign import atan2 "function atan2(y){\
700− \ return function (x) {\
701− \ return Math.atan2(y, x);\
702− \ };\
703− \}" :: Number -> Number -> Number
704−
705− foreign import aceil "function aceil(n){\
706− \ return Math.aceil(n);\
707− \}" :: Number -> Number
708−
709− foreign import cos "function cos(n){\
710− \ return Math.cos(n);\
711− \}" :: Number -> Number
712−
713− foreign import exp "function exp(n){\
714− \ return Math.exp(n);\
715− \}" :: Number -> Number
716−
717− foreign import floor "function floor(n){\
718− \ return Math.floor(n);\
719− \}" :: Number -> Number
720−
721− foreign import log "function log(n){\
722− \ return Math.log(n);\
723− \}" :: Number -> Number
724−
725− foreign import max "function max(n){\
726− \ return Math.max(n);\
727− \}" :: Number -> Number
728−
729− foreign import min "function min(n){\
730− \ return Math.min(n);\
731− \}" :: Number -> Number
732−
733− foreign import pow "function pow(n){\
734− \ return Math.pow(n);\
735− \}" :: Number -> Number
736−
737− foreign import round "function round(n){\
738− \ return Math.round(n);\
739− \}" :: Number -> Number
740−
741− foreign import sin "function sin(n){\
742− \ return Math.sin(n);\
743− \}" :: Number -> Number
744−
745− foreign import sqrt "function sqrt(n){\
746− \ return Math.sqrt(n);\
747− \}" :: Number -> Number
748−
749− foreign import tan "function tan(n){\
750− \ return Math.tan(n);\
751− \}" :: Number -> Number
752−
753−module Eff where
754−
755− foreign import data Eff :: # ! -> * -> *
756−
757− foreign import retEff "function retEff(a) { \
758− \ return function() { \
759− \ return a; \
760− \ }; \
761− \}" :: forall e a. a -> Eff e a
762−
763− foreign import bindEff "function bindEff(a) { \
764− \ return function(f) { \
765− \ return function() { \
766− \ return f(a())(); \
767− \ }; \
768− \ }; \
769− \}" :: forall e a b. Eff e a -> (a -> Eff e b) -> Eff e b
770−
771− type Pure a = forall e. Eff e a
772−
773− foreign import runPure "function runPure(f) { \
774− \ return f(); \
775− \}" :: forall a. Pure a -> a
776−
777− instance Prelude.Monad (Eff e) where
778− ret = retEff
779− (>>=) = bindEff
780−
781−module Random where
782−
783− import Eff
784−
785− foreign import data Random :: !
786−
787− foreign import random "function random() {\
788− \ return function() {\
789− \ return Math.random();\
790− \ };\
791− \}" :: forall e. Eff (random :: Random | e) Number
792−
793−module Errors where
794−
795− import Eff
796−
797− foreign import data Error :: * -> !
798−
799− foreign import throwError "function throwError(e) { \
800− \ return function() { \
801− \ throw e; \
802− \ }; \
803− \}" :: forall a e r. e -> Eff (err :: Error e | r) a
804−
805− foreign import catchError "function catchError(c) { \
806− \ return function(t) { \
807− \ return function() { \
808− \ try { \
809− \ return t(); \
810− \ } catch(e) { \
811− \ return c(e)(); \
812− \ }\
813− \ }; \
814− \ }; \
815− \}" :: forall e r a. (e -> Eff r a) -> Eff (err :: Error e | r) a -> Eff r a
816−
817−module IORef where
818−
819− import Eff
820−
821− foreign import data Ref :: !
822−
823− foreign import data IORef :: * -> *
824−
825− foreign import newIORef "function newIORef(val) {\
826− \ return function () {\
827− \ return { value: val };\
828− \ };\
829− \}" :: forall s r. s -> Eff (ref :: Ref | r) (IORef s)
830−
831− foreign import readIORef "function readIORef(ref) {\
832− \ return function() {\
833− \ return ref.value;\
834− \ };\
835− \}" :: forall s r. IORef s -> Eff (ref :: Ref | r) s
836−
837−
838− foreign import modifyIORef "function modifyIORef(ref) {\
839− \ return function(f) {\
840− \ return function() {\
841− \ ref.value = f(ref.value);\
842− \ };\
843− \ };\
844− \}" :: forall s r. IORef s -> (s -> s) -> Eff (ref :: Ref | r) {}
845−
846− foreign import writeIORef "function writeIORef(ref) {\
847− \ return function(val) {\
848− \ return function() {\
849− \ ref.value = val;\
850− \ };\
851− \ };\
852− \}" :: forall s r. IORef s -> s -> Eff (ref :: Ref | r) {}
853−
854−module Trace where
855−
856− import Prelude
857− import Eff
858−
859− foreign import data Trace :: !
860−
861− foreign import trace "function trace(s) { \
862− \ return function() { \
863− \ console.log(s); \
864− \ return {}; \
865− \ }; \
866− \}" :: forall r. String -> Eff (trace :: Trace | r) {}
867−
868− print :: forall a r. (Prelude.Show a) => a -> Eff (trace :: Trace | r) {}
869− print o = trace (show o)
870−
871−module ST where
872−
873− import Eff
874−
875− foreign import data ST :: * -> !
876−
877− foreign import data STRef :: * -> * -> *
878−
879− foreign import newSTRef "function newSTRef(val) {\
880− \ return function () {\
881− \ return { value: val };\
882− \ };\
883− \}" :: forall a h r. a -> Eff (st :: ST h | r) (STRef h a)
884−
885− foreign import readSTRef "function readSTRef(ref) {\
886− \ return function() {\
887− \ return ref.value;\
888− \ };\
889− \}" :: forall a h r. STRef h a -> Eff (st :: ST h | r) a
890−
891− foreign import modifySTRef "function modifySTRef(ref) {\
892− \ return function(f) {\
893− \ return function() {\
894− \ ref.value = f(ref.value);\
895− \ };\
896− \ };\
897− \}" :: forall a h r. STRef h a -> (a -> a) -> Eff (st :: ST h | r) {}
898−
899− foreign import writeSTRef "function writeSTRef(ref) {\
900− \ return function(a) {\
901− \ return function() {\
902− \ ref.value = a;\
903− \ };\
904− \ };\
905− \}" :: forall a h r. STRef h a -> a -> Eff (st :: ST h | r) {}
906−
907− foreign import runST "function runST(f) {\
908− \ return f;\
909− \}" :: forall a r. (forall h. Eff (st :: ST h | r) a) -> Eff r a
910−
libraries/prelude/tests/.gitignoredeleted−1
@@ -1 +0,0 @@
1−Eff.js
libraries/prelude/tests/Eff.pursdeleted−51
@@ -1,51 +0,0 @@
1−module Tests where
2−
3−import Prelude
4−import Eff
5−import Errors
6−import Trace
7−import Global
8−
9−test1 n = runPure $ catchError (\s -> ret 0) $ do
10− case {} of
11− _ | n > 10 -> do
12− throwError "Error!"
13− _ -> ret n
14−
15−test2 = do
16− trace "Hello World"
17− throwError "Error!"
18−
19−test3 n = catchError (\s -> ret 0) $ do
20− case {} of
21− _ | n > 10 -> do
22− trace "n > 10"
23− throwError "Error!"
24− _ -> ret n
25−
26−test4 = do
27− trace "Hello World!"
28− ret 0
29−
30−test5 = do
31− trace "Hello World!"
32− test5
33−
34−test6 s = do
35− trace s
36− test6 (s ++ " test")
37−
38−import ST
39−
40−test7 _ = do
41− n <- runST $ do
42− r <- newSTRef 0
43− modifySTRef r $ \n -> n + 1
44− readSTRef r
45− print $ n
46−
47−module Main where
48−
49−import Tests
50−
51−main = test7 {}
libraries/prelude/tests/build.shdeleted−2
@@ -1,2 +0,0 @@
1−psc ../prelude.purs Eff.purs --magic-do --run-main --no-prelude -o Eff.js
2−
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
psc/Main.hsdeleted−120
@@ -1,120 +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 qualified Language.PureScript as P
18−import System.Console.CmdTheLine
19−import Control.Applicative
20−import Control.Monad (forM)
21−import System.Exit (exitSuccess, exitFailure)
22−import qualified System.IO.UTF8 as U
23−import Text.Parsec (ParseError)
24−import qualified Paths_purescript as Paths
25−import Data.Version (showVersion)
26−
27−preludeFilename :: IO FilePath
28−preludeFilename = Paths.getDataFileName "libraries/prelude/prelude.purs"
29−
30−readInput :: Maybe [FilePath] -> IO (Either ParseError [P.Module])
31−readInput Nothing = getContents >>= return . P.runIndentParser P.parseModules
32−readInput (Just input) = fmap (fmap concat . sequence) $ forM input $ \inputFile -> do
33− text <- U.readFile inputFile
34− return $ P.runIndentParser P.parseModules text
35−
36−compile :: P.Options -> Maybe [FilePath] -> Maybe FilePath -> Maybe FilePath -> IO ()
37−compile opts input output externs = do
38− modules <- readInput input
39− case modules of
40− Left err -> do
41− U.print err
42− exitFailure
43− Right ms ->
44− case P.compile opts ms of
45− Left err -> do
46− U.putStrLn err
47− exitFailure
48− Right (js, exts, _) -> do
49− case output of
50− Just path -> U.writeFile path js
51− Nothing -> U.putStrLn js
52− case externs of
53− Nothing -> return ()
54− Just filePath -> U.writeFile filePath exts
55− exitSuccess
56−
57−useStdIn :: Term Bool
58−useStdIn = value . flag $ (optInfo [ "s", "stdin" ])
59− { optDoc = "Read from standard input" }
60−
61−inputFiles :: Term [FilePath]
62−inputFiles = value $ posAny [] $ posInfo
63− { posDoc = "The input .ps files" }
64−
65−outputFile :: Term (Maybe FilePath)
66−outputFile = value $ opt Nothing $ (optInfo [ "o", "output" ])
67− { optDoc = "The output .js file" }
68−
69−externsFile :: Term (Maybe FilePath)
70−externsFile = value $ opt Nothing $ (optInfo [ "e", "externs" ])
71− { optDoc = "The output .e.ps file" }
72−
73−tco :: Term Bool
74−tco = value $ flag $ (optInfo [ "tco" ])
75− { optDoc = "Perform tail call optimizations" }
76−
77−performRuntimeTypeChecks :: Term Bool
78−performRuntimeTypeChecks = value $ flag $ (optInfo [ "runtime-type-checks" ])
79− { optDoc = "Generate runtime type checks" }
80−
81−noPrelude :: Term Bool
82−noPrelude = value $ flag $ (optInfo [ "no-prelude" ])
83− { optDoc = "Omit the Prelude" }
84−
85−magicDo :: Term Bool
86−magicDo = value $ flag $ (optInfo [ "magic-do" ])
87− { optDoc = "Overload the do keyword to generate efficient code specifically for the Eff monad." }
88−
89−runMain :: Term Bool
90−runMain = value $ flag $ (optInfo [ "run-main" ])
91− { optDoc = "Generate code to run the main method in the Main module." }
92−
93−noOpts :: Term Bool
94−noOpts = value $ flag $ (optInfo [ "no-opts" ])
95− { optDoc = "Skip the optimization phase." }
96−
97−options :: Term P.Options
98−options = P.Options <$> tco <*> performRuntimeTypeChecks <*> magicDo <*> runMain <*> noOpts
99−
100−stdInOrInputFiles :: FilePath -> Term (Maybe [FilePath])
101−stdInOrInputFiles prelude = combine <$> useStdIn <*> (not <$> noPrelude) <*> inputFiles
102− where
103− combine False True input = Just (prelude : input)
104− combine False False input = Just input
105− combine True _ _ = Nothing
106−
107−term :: FilePath -> Term (IO ())
108−term prelude = compile <$> options <*> stdInOrInputFiles prelude <*> outputFile <*> externsFile
109−
110−termInfo :: TermInfo
111−termInfo = defTI
112− { termName = "psc"
113− , version = showVersion $ Paths.version
114− , termDoc = "Compiles PureScript to Javascript"
115− }
116−
117−main :: IO ()
118−main = do
119− prelude <- preludeFilename
120− run (term prelude, termInfo)
psci/Main.hsdeleted−146
@@ -1,146 +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 FlexibleContexts #-}
16−
17−module Main where
18−
19−import Control.Monad.IO.Class
20−import Control.Applicative
21−import Control.Monad.Trans.Class
22−
23−import Data.List (nub, isPrefixOf)
24−import Data.Maybe (mapMaybe)
25−
26−import System.Process
27−import System.Console.Haskeline
28−
29−import qualified Language.PureScript as P
30−import qualified Paths_purescript as Paths
31−import qualified System.IO.UTF8 as U (readFile)
32−import qualified Text.Parsec as Parsec (eof)
33−
34−getPreludeFilename :: IO FilePath
35−getPreludeFilename = Paths.getDataFileName "libraries/prelude/prelude.purs"
36−
37−options :: P.Options
38−options = P.Options True False True True True
39−
40−completion :: [P.Module] -> CompletionFunc IO
41−completion ms = completeWord Nothing " \t\n\r" findCompletions
42− where
43− findCompletions :: String -> IO [Completion]
44− findCompletions str = do
45− files <- listFiles str
46− let names = nub $ [ show qual
47− | P.Module moduleName ds <- ms
48− , ident <- mapMaybe getDeclName ds
49− , qual <- [ P.Qualified Nothing ident
50− , P.Qualified (Just (P.ModuleName moduleName)) ident]
51− ]
52− let matches = filter (isPrefixOf str) names
53− return $ map simpleCompletion matches ++ files
54− getDeclName :: P.Declaration -> Maybe P.Ident
55− getDeclName (P.ValueDeclaration ident _ _ _) = Just ident
56− getDeclName _ = Nothing
57−
58−createTemporaryModule :: [P.ProperName] -> P.Value -> P.Module
59−createTemporaryModule imports value =
60− let
61− moduleName = P.ProperName "Main"
62− importDecl m = P.ImportDeclaration m Nothing
63− traceModule = P.ModuleName (P.ProperName "Trace")
64− trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))
65− mainDecl = P.ValueDeclaration (P.Ident "main") [] Nothing
66− (P.Do [ P.DoNotationBind (P.VarBinder (P.Ident "it")) value
67− , P.DoNotationValue (P.App trace (P.Var (P.Qualified Nothing (P.Ident "it"))) )
68− ])
69− in
70− P.Module moduleName $ map (importDecl . P.ModuleName) imports ++ [mainDecl]
71−
72−handleDeclaration :: [P.Module] -> [P.ProperName] -> P.Value -> InputT IO ()
73−handleDeclaration loadedModules imports value = do
74− let m = createTemporaryModule imports value
75− case P.compile options (loadedModules ++ [m]) of
76− Left err -> outputStrLn err
77− Right (js, _, _) -> do
78− output <- liftIO $ readProcess "nodejs" [] js
79− outputStrLn output
80−
81−data Command
82− = Empty
83− | Expression [String]
84− | Import String
85− | LoadModule FilePath
86− | Reload deriving (Show, Eq)
87−
88−getCommand :: InputT IO Command
89−getCommand = do
90− firstLine <- getInputLine "> "
91− case firstLine of
92− Nothing -> return Empty
93− Just (':':'i':' ':moduleName) -> return $ Import moduleName
94− Just (':':'m':' ':modulePath) -> return $ LoadModule modulePath
95− Just ":r" -> return Reload
96− Just (':':_) -> outputStrLn "Unknown command" >> getCommand
97− Just other -> Expression <$> go [other]
98− where
99− go ls = do
100− l <- getInputLine " "
101− case l of
102− Nothing -> return $ reverse ls
103− Just l' -> go (l' : ls)
104−
105−loadModule :: FilePath -> IO (Either String [P.Module])
106−loadModule moduleFile = do
107− print moduleFile
108− moduleText <- U.readFile moduleFile
109− return . either (Left . show) Right $ P.runIndentParser P.parseModules moduleText
110−
111−main :: IO ()
112−main = do
113− preludeFilename <- getPreludeFilename
114− (Right prelude) <- loadModule preludeFilename
115− runInputT (setComplete (completion prelude) defaultSettings) $ do
116− outputStrLn " ____ ____ _ _ "
117− outputStrLn "| _ \\ _ _ _ __ ___/ ___| ___ _ __(_)_ __ | |_ "
118− outputStrLn "| |_) | | | | '__/ _ \\___ \\ / __| '__| | '_ \\| __|"
119− outputStrLn "| __/| |_| | | | __/___) | (__| | | | |_) | |_ "
120− outputStrLn "|_| \\__,_|_| \\___|____/ \\___|_| |_| .__/ \\__|"
121− outputStrLn " |_| "
122− outputStrLn ""
123− outputStrLn "Expressions are terminated using Ctrl+D"
124− go [P.ProperName "Prelude"] prelude
125− where
126− go imports loadedModules = do
127− cmd <- getCommand
128− case cmd of
129− Empty -> go imports loadedModules
130− Expression ls -> do
131− case P.runIndentParser (P.whiteSpace *> P.parseValue <* Parsec.eof) (unlines ls) of
132− Left err -> outputStrLn (show err)
133− Right decl -> handleDeclaration loadedModules imports decl
134− go imports loadedModules
135− Import moduleName -> go (imports ++ [P.ProperName moduleName]) loadedModules
136− LoadModule moduleFile -> do
137− ms <- lift $ loadModule moduleFile
138− case ms of
139− Left err -> outputStrLn err
140− Right ms' -> go imports (loadedModules ++ ms')
141− Reload -> do
142− preludeFilename <- lift getPreludeFilename
143− (Right prelude) <- lift $ loadModule preludeFilename
144− go [P.ProperName "Prelude"] prelude
145−
146−
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−96
@@ -1,96 +0,0 @@
1−name: purescript
2−version: 0.3.7
3−cabal-version: >=1.8
4−build-type: Simple
5−license: MIT
6−license-file: LICENSE
7−copyright: (c) Phil Freeman 2013
8−maintainer: Phil Freeman <paf31@cantab.net>
9−stability: experimental
10−synopsis: PureScript Programming Language Compiler
11−description: A small compile-to-JS language with extensible records and type-safe blocks
12−category: Language
13−author: Phil Freeman <paf31@cantab.net>
14−data-files: libraries/prelude/prelude.purs
15−data-dir: ""
16−
17−library
18− build-depends: base >=4 && <5, cmdtheline -any, containers -any,
19− directory -any, filepath -any, mtl -any, parsec -any, syb -any,
20− transformers -any, utf8-string -any, pattern-arrows -any, monad-unify -any
21− exposed-modules: Data.Generics.Extras
22− Language.PureScript
23− Language.PureScript.Options
24− Language.PureScript.Declarations
25− Language.PureScript.Kinds
26− Language.PureScript.Names
27− Language.PureScript.Types
28− Language.PureScript.Values
29− Language.PureScript.Scope
30− Language.PureScript.Sugar
31− Language.PureScript.ModuleDependencies
32− Language.PureScript.Sugar.CaseDeclarations
33− Language.PureScript.Sugar.DoNotation
34− Language.PureScript.Sugar.TypeDeclarations
35− Language.PureScript.Sugar.BindingGroups
36− Language.PureScript.Sugar.Operators
37− Language.PureScript.Sugar.TypeClasses
38− Language.PureScript.CodeGen
39− Language.PureScript.CodeGen.Common
40− Language.PureScript.CodeGen.Externs
41− Language.PureScript.CodeGen.JS
42− Language.PureScript.CodeGen.JS.AST
43− Language.PureScript.CodeGen.Monad
44− Language.PureScript.CodeGen.Optimize
45− Language.PureScript.Parser
46− Language.PureScript.Parser.Common
47− Language.PureScript.Parser.Declarations
48− Language.PureScript.Parser.Kinds
49− Language.PureScript.Parser.State
50− Language.PureScript.Parser.Types
51− Language.PureScript.Parser.Values
52− Language.PureScript.Parser.JS
53− Language.PureScript.Pretty
54− Language.PureScript.Pretty.Common
55− Language.PureScript.Pretty.JS
56− Language.PureScript.Pretty.Kinds
57− Language.PureScript.Pretty.Types
58− Language.PureScript.Pretty.Values
59− Language.PureScript.TypeChecker
60− Language.PureScript.TypeChecker.Kinds
61− Language.PureScript.TypeChecker.Monad
62− Language.PureScript.TypeChecker.Synonyms
63− Language.PureScript.TypeChecker.Types
64− exposed: True
65− buildable: True
66− hs-source-dirs: src
67− other-modules:
68−
69−executable psc
70− build-depends: base >=4 && <5, cmdtheline -any, containers -any,
71− directory -any, filepath -any, mtl -any, parsec -any,
72− purescript -any, syb -any, transformers -any, utf8-string -any
73− main-is: Main.hs
74− buildable: True
75− hs-source-dirs: psc
76− other-modules:
77− ghc-options: -Wall -O2 -fno-warn-unused-do-bind
78−
79−executable psci
80− build-depends: base >=4 && <5, containers -any, mtl -any,
81− parsec -any, haskeline <=0.7.1.1, purescript -any, syb -any,
82− transformers -any, utf8-string -any, process -any
83− main-is: Main.hs
84− buildable: True
85− hs-source-dirs: psci
86− other-modules:
87− ghc-options: -Wall -O2
88−
89−test-suite tests
90− build-depends: base >=4 && <5, containers -any, directory -any,
91− filepath -any, mtl -any, parsec -any, purescript -any, syb -any,
92− transformers -any, utf8-string -any, process -any
93− type: exitcode-stdio-1.0
94− main-is: Main.hs
95− buildable: True
96− 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/Data/Generics/Extras.hsdeleted−28
@@ -1,28 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Data.Generics.Extras
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−-- Additional SYB combinators
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE Rank2Types #-}
17−
18−module Data.Generics.Extras where
19−
20−import Data.Data
21−
22−-- |
23−-- Apply a top-down monadic transformation everywhere
24−--
25−everywhereM' :: (Monad m, Data d) => (forall d1. (Data d1) => d1 -> m d1) -> d -> m d
26−everywhereM' f x = do
27− y <- f x
28− gmapM (everywhereM' f) y
src/Language/PureScript.hsdeleted−70
@@ -1,70 +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) where
17−
18−import Language.PureScript.Values as P
19−import Language.PureScript.Types as P
20−import Language.PureScript.Kinds as P
21−import Language.PureScript.Declarations as P
22−import Language.PureScript.Names as P
23−import Language.PureScript.Parser as P
24−import Language.PureScript.CodeGen 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−
31−import Data.List (intercalate)
32−import Control.Monad (when, forM)
33−import Control.Monad.State.Lazy
34−import Control.Applicative ((<$>))
35−import qualified Data.Map as M
36−
37−-- |
38−-- Compile a collection of modules
39−--
40−-- The compilation pipeline proceeds as follows:
41−--
42−-- * Sort the modules based on module dependencies, checking for cyclic dependencies.
43−--
44−-- * Perform a set of desugaring passes.
45−--
46−-- * Type check, and elaborate values to include type annotations and type class dictionaries.
47−--
48−-- * Regroup values to take into account new value dependencies introduced by elaboration
49−--
50−-- * Generate Javascript, and perform optimization passes.
51−--
52−-- * Pretty-print the generated Javascript
53−--
54−compile :: Options -> [Module] -> Either String (String, String, Environment)
55−compile opts ms = do
56− sorted <- sortModules ms
57− desugared <- desugar sorted
58− (elaborated, env) <- runCheck $ forM desugared $ \(Module moduleName decls) -> do
59− modify (\s -> s { checkCurrentModule = Just (ModuleName moduleName) })
60− Module moduleName <$> typeCheckAll (ModuleName moduleName) decls
61− regrouped <- createBindingGroupsModule . collapseBindingGroupsModule $ elaborated
62− let js = concatMap (flip (moduleToJs opts) env) $ regrouped
63− let exts = intercalate "\n" . map (flip moduleToPs env) $ regrouped
64− js' <- case () of
65− _ | optionsRunMain opts -> do
66− when ((ModuleName (ProperName "Main"), Ident "main") `M.notMember` (names env)) $
67− Left "Main.main is undefined"
68− return $ js ++ [JSApp (JSAccessor "main" (JSVar "Main")) []]
69− | otherwise -> return js
70− return (prettyPrintJS js', exts, env)
src/Language/PureScript/CodeGen.hsdeleted−26
@@ -1,26 +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
26−import Language.PureScript.CodeGen.Optimize as C
src/Language/PureScript/CodeGen/Common.hsdeleted−56
@@ -1,56 +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 Language.PureScript.Names
20−
21−-- |
22−-- Convert an Ident into a valid Javascript identifier:
23−--
24−-- * Alphanumeric characters are kept unmodified
25−--
26−-- * Symbols are encoded as a dollar symbol ($) followed by their ordinal value
27−--
28−identToJs :: Ident -> String
29−identToJs (Ident name) = concatMap identCharToString name
30−identToJs (Op op) = concatMap identCharToString op
31−identToJs (Escaped name) = name
32−
33−identCharToString :: Char -> String
34−identCharToString c | isAlphaNum c = [c]
35−identCharToString '_' = "_"
36−identCharToString '.' = "$dot"
37−identCharToString '$' = "$dollar"
38−identCharToString '~' = "$tilde"
39−identCharToString '=' = "$eq"
40−identCharToString '<' = "$less"
41−identCharToString '>' = "$greater"
42−identCharToString '!' = "$bang"
43−identCharToString '#' = "$hash"
44−identCharToString '%' = "$percent"
45−identCharToString '^' = "$up"
46−identCharToString '&' = "$amp"
47−identCharToString '|' = "$bar"
48−identCharToString '*' = "$times"
49−identCharToString '/' = "$div"
50−identCharToString '+' = "$plus"
51−identCharToString '-' = "$minus"
52−identCharToString ':' = "$colon"
53−identCharToString '\\' = "$bslash"
54−identCharToString '?' = "$qmark"
55−identCharToString '@' = "$at"
56−identCharToString c = '$' : show (ord c)
src/Language/PureScript/CodeGen/Externs.hsdeleted−51
@@ -1,51 +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 (maybeToList, mapMaybe)
21−import qualified Data.Map as M
22−import Language.PureScript.Declarations
23−import Language.PureScript.TypeChecker.Monad
24−import Language.PureScript.Pretty
25−import Language.PureScript.Names
26−import Data.List (intercalate)
27−
28−-- |
29−-- Generate foreign imports for all declarations in a module
30−--
31−moduleToPs :: Module -> Environment -> String
32−moduleToPs (Module pname@(ProperName moduleName) decls) env =
33− "module " ++ moduleName ++ " where\n" ++
34− (intercalate "\n" . map (" " ++) . concatMap (declToPs (ModuleName pname) env) $ decls)
35−
36−declToPs :: ModuleName -> Environment -> Declaration -> [String]
37−declToPs path env (ValueDeclaration name _ _ _) = maybeToList $ do
38− (ty, _) <- M.lookup (path, name) $ names env
39− return $ "foreign import " ++ show name ++ " :: " ++ prettyPrintType ty
40−declToPs path env (BindingGroupDeclaration vals) = do
41− flip mapMaybe vals $ \(name, _) -> do
42− (ty, _) <- M.lookup (path, name) $ names env
43− return $ "foreign import " ++ show name ++ " :: " ++ prettyPrintType ty
44−declToPs path env (DataDeclaration name _ _) = maybeToList $ do
45− (kind, _) <- M.lookup (path, name) $ types env
46− return $ "foreign import data " ++ show name ++ " :: " ++ prettyPrintKind kind
47−declToPs _ _ (ExternDataDeclaration name kind) =
48− return $ "foreign import data " ++ show name ++ " :: " ++ prettyPrintKind kind
49−declToPs _ _ (TypeSynonymDeclaration name args ty) =
50− return $ "type " ++ show name ++ " " ++ unwords args ++ " = " ++ prettyPrintType ty
51−declToPs _ _ _ = []
src/Language/PureScript/CodeGen/JS.hsdeleted−273
@@ -1,273 +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− declToJs,
21− moduleToJs
22−) where
23−
24−import Data.Maybe (fromMaybe, mapMaybe)
25−import Data.List (sortBy)
26−import Data.Function (on)
27−
28−import Control.Arrow (second)
29−import Control.Monad (replicateM, forM)
30−
31−import qualified Data.Map as M
32−
33−import Language.PureScript.TypeChecker (Environment(..), NameKind(..))
34−import Language.PureScript.Values
35−import Language.PureScript.Names
36−import Language.PureScript.Scope
37−import Language.PureScript.Declarations
38−import Language.PureScript.Pretty.Common
39−import Language.PureScript.CodeGen.Monad
40−import Language.PureScript.Options
41−import Language.PureScript.CodeGen.JS.AST as AST
42−import Language.PureScript.Types
43−import Language.PureScript.CodeGen.Optimize
44−import Language.PureScript.CodeGen.Common (identToJs)
45−import Language.PureScript.TypeChecker.Monad (canonicalizeDataConstructor)
46−
47−-- |
48−-- Generate code in the simplified Javascript intermediate representation for all declarations in a module
49−--
50−moduleToJs :: Options -> Module -> Environment -> [JS]
51−moduleToJs opts (Module pname@(ProperName name) decls) env =
52− [ JSVariableIntroduction name Nothing
53− , JSApp (JSFunction Nothing [name]
54− (JSBlock (concat $ mapMaybe (\decl -> fmap (map $ optimize opts) $ declToJs opts (ModuleName pname) decl env) (decls))))
55− [JSAssignment (JSVar name)
56− (JSBinary Or (JSVar name) (JSObjectLiteral []))]
57− ]
58−
59−-- |
60−-- Generate code in the simplified Javascript intermediate representation for a declaration
61−--
62−declToJs :: Options -> ModuleName -> Declaration -> Environment -> Maybe [JS]
63−declToJs opts mp (ValueDeclaration ident _ _ val) e =
64− Just $ JSVariableIntroduction (identToJs ident) (Just (valueToJs opts mp e val))
65− : setProperty ident (var ident) mp
66−declToJs opts mp (BindingGroupDeclaration vals) e =
67− Just $ concatMap (\(ident, val) ->
68− JSVariableIntroduction (identToJs ident) (Just (valueToJs opts mp e val))
69− : setProperty ident (var ident) mp
70− ) vals
71−declToJs _ mp (DataDeclaration _ _ ctors) _ =
72− Just $ flip concatMap ctors $ \(pn@(ProperName ctor), maybeTy) ->
73− let
74− ctorJs =
75− case maybeTy of
76− Nothing -> JSVariableIntroduction ctor (Just (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn))) ]))
77− Just _ -> JSFunction (Just ctor) ["value"]
78− (JSBlock [JSReturn
79− (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn)))
80− , ("value", JSVar "value") ])])
81− in ctorJs : setProperty (Escaped ctor) (JSVar ctor) mp
82−declToJs opts mp (DataBindingGroupDeclaration ds) e =
83− Just $ concat $ mapMaybe (flip (declToJs opts mp) e) ds
84−declToJs _ mp (ExternDeclaration importTy ident (Just js) _) _ =
85− Just $ js : setProperty ident (var ident) mp
86−declToJs _ _ _ _ = Nothing
87−
88−setProperty :: Ident -> JS -> ModuleName -> [JS]
89−setProperty ident@(Op op) val (ModuleName (ProperName moduleName)) =
90− [ JSAssignment (JSAccessor (identToJs ident) (JSVar moduleName)) val
91− , JSAssignment (JSIndexer (JSStringLiteral op) (JSVar moduleName)) (JSAccessor (identToJs ident) (JSVar moduleName)) ]
92−setProperty ident val (ModuleName (ProperName moduleName)) =
93− [ JSAssignment (JSAccessor (identToJs ident) (JSVar moduleName)) val ]
94−
95−var :: Ident -> JS
96−var = JSVar . identToJs
97−
98−valueToJs :: Options -> ModuleName -> Environment -> Value -> JS
99−valueToJs _ _ _ (NumericLiteral n) = JSNumericLiteral n
100−valueToJs _ _ _ (StringLiteral s) = JSStringLiteral s
101−valueToJs _ _ _ (BooleanLiteral b) = JSBooleanLiteral b
102−valueToJs opts m e (ArrayLiteral xs) = JSArrayLiteral (map (valueToJs opts m e) xs)
103−valueToJs opts m e (ObjectLiteral ps) = JSObjectLiteral (map (second (valueToJs opts m e)) ps)
104−valueToJs opts m e (ObjectUpdate o ps) = JSApp (JSAccessor "extend" (JSVar "Object")) [ valueToJs opts m e o, JSObjectLiteral (map (second (valueToJs opts m e)) ps)]
105−valueToJs _ m e (Constructor (Qualified Nothing name)) =
106− case M.lookup (m, name) (dataConstructors e) of
107− Just (_, Alias aliasModule aliasIdent) -> qualifiedToJS identToJs (Qualified (Just aliasModule) aliasIdent)
108− _ -> JSVar . runProperName $ name
109−valueToJs _ _ _ (Constructor name) = qualifiedToJS runProperName name
110−valueToJs opts m e (Block sts) = JSApp (JSFunction Nothing [] (JSBlock (map (statementToJs opts m e) sts))) []
111−valueToJs opts m e (Case values binders) = bindersToJs opts m e binders (map (valueToJs opts m e) values)
112−valueToJs opts m e (IfThenElse cond th el) = JSConditional (valueToJs opts m e cond) (valueToJs opts m e th) (valueToJs opts m e el)
113−valueToJs opts m e (Accessor prop val) = JSAccessor prop (valueToJs opts m e val)
114−valueToJs opts m e (App val arg) = JSApp (valueToJs opts m e val) [valueToJs opts m e arg]
115−valueToJs opts m e (Abs arg val) = JSFunction Nothing [identToJs arg] (JSBlock [JSReturn (valueToJs opts m e val)])
116−valueToJs opts m e (TypedValue _ (Abs arg val) ty) | optionsPerformRuntimeTypeChecks opts = let arg' = identToJs arg in JSFunction Nothing [arg'] (JSBlock $ runtimeTypeChecks arg' ty ++ [JSReturn (valueToJs opts m e val)])
117−valueToJs _ m e (Var ident) = varToJs m e ident
118−valueToJs opts m e (TypedValue _ val _) = valueToJs opts m e val
119−valueToJs _ _ _ (TypeClassDictionary _ _) = error "Type class dictionary was not replaced"
120−valueToJs _ _ _ _ = error "Invalid argument to valueToJs"
121−
122−runtimeTypeChecks :: String -> Type -> [JS]
123−runtimeTypeChecks arg ty =
124− let
125− argTy = getFunctionArgumentType ty
126− in
127− maybe [] (argumentCheck (JSVar arg)) argTy
128− where
129− getFunctionArgumentType :: Type -> Maybe Type
130− getFunctionArgumentType (TypeApp (TypeApp t funArg) _) | t == tyFunction = Just funArg
131− getFunctionArgumentType (ForAll _ ty') = getFunctionArgumentType ty'
132− getFunctionArgumentType _ = Nothing
133− argumentCheck :: JS -> Type -> [JS]
134− argumentCheck val t | t == tyNumber = [typeCheck val "number"]
135− argumentCheck val t | t == tyString = [typeCheck val "string"]
136− argumentCheck val t | t == tyBoolean = [typeCheck val "boolean"]
137− argumentCheck val (TypeApp t _) | t == tyArray = [arrayCheck val]
138− argumentCheck val (Object row) =
139− let
140− (pairs, _) = rowToList row
141− in
142− typeCheck val "object" : concatMap (\(prop, ty') -> argumentCheck (JSAccessor prop val) ty') pairs
143− argumentCheck val (TypeApp (TypeApp t _) _) | t == tyFunction = [typeCheck val "function"]
144− argumentCheck val (ForAll _ ty') = argumentCheck val ty'
145− argumentCheck _ _ = []
146− typeCheck :: JS -> String -> JS
147− typeCheck js ty' = JSIfElse (JSBinary NotEqualTo (JSTypeOf js) (JSStringLiteral ty')) (JSBlock [JSThrow (JSStringLiteral $ ty' ++ " expected")]) Nothing
148− arrayCheck :: JS -> JS
149− arrayCheck js = JSIfElse (JSUnary Not (JSApp (JSAccessor "isArray" (JSVar "Array")) [js])) (JSBlock [JSThrow (JSStringLiteral "Array expected")]) Nothing
150−
151−varToJs :: ModuleName -> Environment -> Qualified Ident -> JS
152−varToJs m e qual@(Qualified _ ident) = go qual
153− where
154− go qual = case M.lookup (qualify m qual) (names e) of
155− Just (_, ty) | isExtern ty -> var ident
156− Just (_, Alias aliasModule aliasIdent) -> go (Qualified (Just aliasModule) aliasIdent)
157− _ -> case qual of
158− Qualified Nothing _ -> var ident
159− Qualified (Just (ModuleName (ProperName mn))) (Op op) -> JSIndexer (JSStringLiteral op) (JSVar mn)
160− _ -> qualifiedToJS identToJs qual
161− isExtern (Extern ForeignImport) = True
162− isExtern (Alias m' ident') = case M.lookup (m', ident') (names e) of
163− Just (_, ty') -> isExtern ty'
164− Nothing -> error "Undefined alias in varToJs"
165− isExtern _ = False
166−
167−qualifiedToJS :: (a -> String) -> Qualified a -> JS
168−qualifiedToJS f (Qualified (Just (ModuleName (ProperName m))) a) = JSAccessor (f a) (JSVar m)
169−qualifiedToJS f (Qualified Nothing a) = JSVar (f a)
170−
171−bindersToJs :: Options -> ModuleName -> Environment -> [([Binder], Maybe Guard, Value)] -> [JS] -> JS
172−bindersToJs opts m e binders vals = runGen (map identToJs (unusedNames (binders, vals))) $ do
173− valNames <- replicateM (length vals) fresh
174− jss <- forM binders $ \(bs, grd, result) -> go valNames [JSReturn (valueToJs opts m e result)] bs grd
175− return $ JSApp (JSFunction Nothing valNames (JSBlock (concat jss ++ [JSThrow (JSStringLiteral "Failed pattern match")])))
176− vals
177− where
178− go :: [String] -> [JS] -> [Binder] -> Maybe Guard -> Gen [JS]
179− go _ done [] Nothing = return done
180− go _ done [] (Just cond) = return [JSIfElse (valueToJs opts m e cond) (JSBlock done) Nothing]
181− go (v:vs) done' (b:bs) grd = do
182− done'' <- go vs done' bs grd
183− binderToJs m e v done'' b
184− go _ _ _ _ = error "Invalid arguments to bindersToJs"
185−
186−binderToJs :: ModuleName -> Environment -> String -> [JS] -> Binder -> Gen [JS]
187−binderToJs _ _ _ done NullBinder = return done
188−binderToJs _ _ varName done (StringBinder str) =
189− return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSStringLiteral str)) (JSBlock done) Nothing]
190−binderToJs _ _ varName done (NumberBinder num) =
191− return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSNumericLiteral num)) (JSBlock done) Nothing]
192−binderToJs _ _ varName done (BooleanBinder True) =
193− return [JSIfElse (JSVar varName) (JSBlock done) Nothing]
194−binderToJs _ _ varName done (BooleanBinder False) =
195− return [JSIfElse (JSUnary Not (JSVar varName)) (JSBlock done) Nothing]
196−binderToJs _ _ varName done (VarBinder ident) =
197− return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : done)
198−binderToJs m e varName done (NullaryBinder ctor) =
199− if isOnlyConstructor m e ctor
200− then
201− return done
202− else
203− return [JSIfElse (JSBinary EqualTo (JSAccessor "ctor" (JSVar varName)) (JSStringLiteral (show ((\(mp, nm) -> Qualified (Just mp) nm) $ canonicalizeDataConstructor m e ctor)))) (JSBlock done) Nothing]
204−binderToJs m e varName done (UnaryBinder ctor b) = do
205− value <- fresh
206− js <- binderToJs m e value done b
207− let success = JSBlock (JSVariableIntroduction value (Just (JSAccessor "value" (JSVar varName))) : js)
208− if isOnlyConstructor m e ctor
209− then
210− return [success]
211− else
212− return [JSIfElse (JSBinary EqualTo (JSAccessor "ctor" (JSVar varName)) (JSStringLiteral (show ((\(mp, nm) -> Qualified (Just mp) nm) $ canonicalizeDataConstructor m e ctor))))
213− success
214− Nothing]
215−binderToJs m e varName done (ObjectBinder bs) = go done bs
216− where
217− go :: [JS] -> [(String, Binder)] -> Gen [JS]
218− go done' [] = return done'
219− go done' ((prop, binder):bs') = do
220− propVar <- fresh
221− done'' <- go done' bs'
222− js <- binderToJs m e propVar done'' binder
223− return (JSVariableIntroduction propVar (Just (JSAccessor prop (JSVar varName))) : js)
224−binderToJs m e varName done (ArrayBinder bs) = do
225− js <- go done 0 bs
226− return [JSIfElse (JSBinary EqualTo (JSAccessor "length" (JSVar varName)) (JSNumericLiteral (Left (fromIntegral $ length bs)))) (JSBlock js) Nothing]
227− where
228− go :: [JS] -> Integer -> [Binder] -> Gen [JS]
229− go done' _ [] = return done'
230− go done' index (binder:bs') = do
231− elVar <- fresh
232− done'' <- go done' (index + 1) bs'
233− js <- binderToJs m e elVar done'' binder
234− return (JSVariableIntroduction elVar (Just (JSIndexer (JSNumericLiteral (Left index)) (JSVar varName))) : js)
235−binderToJs m e varName done (ConsBinder headBinder tailBinder) = do
236− headVar <- fresh
237− tailVar <- fresh
238− js1 <- binderToJs m e headVar done headBinder
239− js2 <- binderToJs m e tailVar js1 tailBinder
240− return [JSIfElse (JSBinary GreaterThan (JSAccessor "length" (JSVar varName)) (JSNumericLiteral (Left 0))) (JSBlock
241− ( JSVariableIntroduction headVar (Just (JSIndexer (JSNumericLiteral (Left 0)) (JSVar varName))) :
242− JSVariableIntroduction tailVar (Just (JSApp (JSAccessor "slice" (JSVar varName)) [JSNumericLiteral (Left 1)])) :
243− js2
244− )) Nothing]
245−binderToJs m e varName done (NamedBinder ident binder) = do
246− js <- binderToJs m e varName done binder
247− return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : js)
248−
249−isOnlyConstructor :: ModuleName -> Environment -> Qualified ProperName -> Bool
250−isOnlyConstructor m e ctor =
251− let (ty, _) = fromMaybe (error "Data constructor not found") $ qualify m ctor `M.lookup` dataConstructors e
252− in numConstructors ty == 1
253− where
254− numConstructors ty = length $ filter (\(ty1, _) -> ((==) `on` typeConstructor) ty ty1) $ M.elems $ dataConstructors e
255− typeConstructor (TypeConstructor qual) = qualify m qual
256− typeConstructor (ForAll _ ty) = typeConstructor ty
257− typeConstructor (TypeApp (TypeApp t _) ty) | t == tyFunction = typeConstructor ty
258− typeConstructor (TypeApp ty _) = typeConstructor ty
259− typeConstructor fn = error $ "Invalid arguments to typeConstructor: " ++ show fn
260−
261−statementToJs :: Options -> ModuleName -> Environment -> Statement -> JS
262−statementToJs opts m e (VariableIntroduction ident value) = JSVariableIntroduction (identToJs ident) (Just (valueToJs opts m e value))
263−statementToJs opts m e (Assignment target value) = JSAssignment (JSVar (identToJs target)) (valueToJs opts m e value)
264−statementToJs opts m e (While cond sts) = JSWhile (valueToJs opts m e cond) (JSBlock (map (statementToJs opts m e) sts))
265−statementToJs opts m e (For ident start end sts) = JSFor (identToJs ident) (valueToJs opts m e start) (valueToJs opts m e end) (JSBlock (map (statementToJs opts m e) sts))
266−statementToJs opts m e (If ifst) = ifToJs ifst
267− where
268− ifToJs :: IfStatement -> JS
269− ifToJs (IfStatement cond thens elses) = JSIfElse (valueToJs opts m e cond) (JSBlock (map (statementToJs opts m e) thens)) (fmap elseToJs elses)
270− elseToJs :: ElseStatement -> JS
271− elseToJs (Else sts) = JSBlock (map (statementToJs opts m e) sts)
272− elseToJs (ElseIf elif) = ifToJs elif
273−statementToJs opts m e (Return value) = JSReturn (valueToJs opts m e value)
src/Language/PureScript/CodeGen/JS/AST.hsdeleted−233
@@ -1,233 +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−
24−-- |
25−-- Built-in unary operators
26−--
27−data UnaryOperator
28− -- |
29− -- Numeric negation
30− --
31− = Negate
32− -- |
33− -- Boolean negation
34− --
35− | Not
36− -- |
37− -- Bitwise negation
38− --
39− | BitwiseNot
40− -- |
41− -- Numeric unary \'plus\'
42− --
43− | Positive deriving (Show, Eq, Data, Typeable)
44−
45−-- |
46−-- Built-in binary operators
47−--
48−data BinaryOperator
49− -- |
50− -- Numeric addition
51− --
52− = Add
53− -- |
54− -- Numeric subtraction
55− --
56− | Subtract
57− -- |
58− -- Numeric multiplication
59− --
60− | Multiply
61− -- |
62− -- Numeric division
63− --
64− | Divide
65− -- |
66− -- Remainder
67− --
68− | Modulus
69− -- |
70− -- Generic equality test
71− --
72− | EqualTo
73− -- |
74− -- Generic inequality test
75− --
76− | NotEqualTo
77− -- |
78− -- Numeric less-than
79− --
80− | LessThan
81− -- |
82− -- Numeric less-than-or-equal
83− --
84− | LessThanOrEqualTo
85− -- |
86− -- Numeric greater-than
87− --
88− | GreaterThan
89− -- |
90− -- Numeric greater-than-or-equal
91− --
92− | GreaterThanOrEqualTo
93− -- |
94− -- Boolean and
95− --
96− | And
97− -- |
98− -- Boolean or
99− --
100− | Or
101− -- |
102− -- Bitwise and
103− --
104− | BitwiseAnd
105− -- |
106− -- Bitwise or
107− --
108− | BitwiseOr
109− -- |
110− -- Bitwise xor
111− --
112− | BitwiseXor
113− -- |
114− -- Bitwise left shift
115− --
116− | ShiftLeft
117− -- |
118− -- Bitwise right shift
119− --
120− | ShiftRight
121− -- |
122− -- Bitwise right shift with zero-fill
123− --
124− | ZeroFillShiftRight deriving (Show, Eq, Data, Typeable)
125−
126−-- |
127−-- Data type for simplified Javascript expressions
128−--
129−data JS
130− -- |
131− -- A numeric literal
132− --
133− = JSNumericLiteral (Either Integer Double)
134− -- |
135− -- A string literal
136− --
137− | JSStringLiteral String
138− -- |
139− -- A boolean literal
140− --
141− | JSBooleanLiteral Bool
142− -- |
143− -- A unary operator application
144− --
145− | JSUnary UnaryOperator JS
146− -- |
147− -- A binary operator application
148− --
149− | JSBinary BinaryOperator JS JS
150− -- |
151− -- An array literal
152− --
153− | JSArrayLiteral [JS]
154− -- |
155− -- An array indexer expression
156− --
157− | JSIndexer JS JS
158− -- |
159− -- An object literal
160− --
161− | JSObjectLiteral [(String, JS)]
162− -- |
163− -- An object property accessor expression
164− --
165− | JSAccessor String JS
166− -- |
167− -- A function introduction (optional name, arguments, body)
168− --
169− | JSFunction (Maybe String) [String] JS
170− -- |
171− -- Function application
172− --
173− | JSApp JS [JS]
174− -- |
175− -- Variable
176− --
177− | JSVar String
178− -- |
179− -- Conditional expression
180− --
181− | JSConditional JS JS JS
182− -- |
183− -- A block of expressions in braces
184− --
185− | JSBlock [JS]
186− -- |
187− -- A variable introduction and optional initialization
188− --
189− | JSVariableIntroduction String (Maybe JS)
190− -- |
191− -- A variable assignment
192− --
193− | JSAssignment JS JS
194− -- |
195− -- While loop
196− --
197− | JSWhile JS JS
198− -- |
199− -- For loop
200− --
201− | JSFor String JS JS JS
202− -- |
203− -- If-then-else statement
204− --
205− | JSIfElse JS JS (Maybe JS)
206− -- |
207− -- Return statement
208− --
209− | JSReturn JS
210− -- |
211− -- Throw statement
212− --
213− | JSThrow JS
214− -- |
215− -- Type-Of operator
216− --
217− | JSTypeOf JS
218− -- |
219− -- Labelled statement
220− --
221− | JSLabel String JS
222− -- |
223− -- Break statement
224− --
225− | JSBreak String
226− -- |
227− -- Continue statement
228− --
229− | JSContinue String
230− -- |
231− -- Raw Javascript (generated when parsing fails for an inline foreign import declaration)
232− --
233− | JSRaw String deriving (Show, Eq, Data, Typeable)
src/Language/PureScript/CodeGen/Monad.hsdeleted−44
@@ -1,44 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.CodeGen.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−-- Code generation monad
13−--
14−-- This monad provides a supply of fresh names which can be used to create variables.
15−--
16−-----------------------------------------------------------------------------
17−
18−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
19−
20−module Language.PureScript.CodeGen.Monad where
21−
22−import Control.Monad.State
23−import Control.Applicative
24−import Language.PureScript.Names
25−
26−-- |
27−-- Code generation monad data type
28−--
29−newtype Gen a = Gen { unGen :: State [String] a } deriving (Functor, Applicative, Monad, MonadState [String])
30−
31−-- |
32−-- Run a computation in the code generation monad
33−--
34−runGen :: [String] -> Gen a -> a
35−runGen names = flip evalState names . unGen
36−
37−-- |
38−-- Generate a fresh name
39−--
40−fresh :: Gen String
41−fresh = do
42− (s:ss) <- get
43− put ss
44− return s
src/Language/PureScript/CodeGen/Optimize.hsdeleted−369
@@ -1,369 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Optimize
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 unused variables
23−--
24−-- * Removal of unnecessary thunks
25−--
26−-- * Eta conversion
27−--
28−-- * Inlining variables
29−--
30−-- * Inline Prelude.($), Prelude.(++), Prelude.(!!)
31−--
32−-- * Inlining primitive Javascript operators
33−--
34−-----------------------------------------------------------------------------
35−
36−module Language.PureScript.CodeGen.Optimize (
37− optimize
38−) where
39−
40−import Data.Data
41−import Data.Maybe (fromMaybe)
42−import Data.Generics
43−
44−import Language.PureScript.Names
45−import Language.PureScript.CodeGen.JS.AST
46−import Language.PureScript.Options
47−import Language.PureScript.CodeGen.Common (identToJs)
48−import Language.PureScript.Sugar.TypeClasses
49− (mkDictionaryValueName)
50−import Language.PureScript.Types
51−
52−-- |
53−-- Apply a series of optimizer passes to simplified Javascript code
54−--
55−optimize :: Options -> JS -> JS
56−optimize opts | optionsNoOptimizations opts = id
57− | otherwise = untilFixedPoint $ applyAll
58− [ collapseNestedBlocks
59− , tco opts
60− , magicDo opts
61− , removeUnusedVariables
62− , unThunk
63− , etaConvert
64− , inlineVariables
65− , inlineOperator "$" $ \f x -> JSApp f [x]
66− , inlineOperator "!!" $ flip JSIndexer
67− , inlineOperator "++" $ JSBinary Add
68− , inlineCommonOperators ]
69−
70−applyAll :: [a -> a] -> a -> a
71−applyAll = foldl1 (.)
72−
73−untilFixedPoint :: (Eq a) => (a -> a) -> a -> a
74−untilFixedPoint f a = go a
75− where
76− go a' = let a'' = f a' in
77− if a'' == a' then a'' else go a''
78−
79−replaceIdent :: (Data d) => String -> JS -> d -> d
80−replaceIdent var1 js = everywhere (mkT replace)
81− where
82− replace (JSVar var2) | var1 == var2 = js
83− replace other = other
84−
85−replaceIdents :: (Data d) => [(String, JS)] -> d -> d
86−replaceIdents vars = everywhere (mkT replace)
87− where
88− replace v@(JSVar var) = fromMaybe v $ lookup var vars
89− replace other = other
90−
91−isReassigned :: (Data d) => String -> d -> Bool
92−isReassigned var1 = everything (||) (mkQ False check)
93− where
94− check :: JS -> Bool
95− check (JSFunction _ args _) | var1 `elem` args = True
96− check _ = False
97−
98−isRebound :: (Data d) => JS -> d -> Bool
99−isRebound js d = any (\var -> isReassigned var d) (variablesOf js)
100− where
101− variablesOf (JSVar var) = [var]
102− variablesOf (JSAccessor _ val) = variablesOf val
103− variablesOf (JSIndexer index val) = variablesOf index ++ variablesOf val
104− variablesOf _ = []
105−
106−isUsed :: (Data d) => String -> d -> Bool
107−isUsed var1 = everything (||) (mkQ False check)
108− where
109− check :: JS -> Bool
110− check (JSVar var2) | var1 == var2 = True
111− check (JSAssignment target _) | var1 == targetVariable target = True
112− check _ = False
113−
114−targetVariable :: JS -> String
115−targetVariable (JSVar var) = var
116−targetVariable (JSAccessor _ tgt) = targetVariable tgt
117−targetVariable (JSIndexer _ tgt) = targetVariable tgt
118−targetVariable _ = error "Invalid argument to targetVariable"
119−
120−isUpdated :: (Data d) => String -> d -> Bool
121−isUpdated var1 = everything (||) (mkQ False check)
122− where
123− check :: JS -> Bool
124− check (JSAssignment target _) | var1 == targetVariable target = True
125− check _ = False
126−
127−shouldInline :: JS -> Bool
128−shouldInline (JSVar _) = True
129−shouldInline (JSNumericLiteral _) = True
130−shouldInline (JSStringLiteral _) = True
131−shouldInline (JSBooleanLiteral _) = True
132−shouldInline (JSAccessor _ val) = shouldInline val
133−shouldInline (JSIndexer index val) = shouldInline index && shouldInline val
134−shouldInline _ = False
135−
136−inlineVariables :: JS -> JS
137−inlineVariables = everywhere (mkT removeFromBlock)
138− where
139− removeFromBlock :: JS -> JS
140− removeFromBlock (JSBlock sts) = JSBlock (go sts)
141− removeFromBlock js = js
142− go :: [JS] -> [JS]
143− go [] = []
144− go (s@(JSVariableIntroduction var (Just js)) : sts)
145− | shouldInline js && not (isReassigned var sts) && not (isRebound js sts) && not (isUpdated var sts) =
146− go (replaceIdent var js sts)
147− go (s:sts) = s : go sts
148−
149−removeUnusedVariables :: JS -> JS
150−removeUnusedVariables = everywhere (mkT removeFromBlock)
151− where
152− removeFromBlock :: JS -> JS
153− removeFromBlock (JSBlock sts) = JSBlock (go sts)
154− removeFromBlock js = js
155− go :: [JS] -> [JS]
156− go [] = []
157− go (JSVariableIntroduction var _ : sts) | not (isUsed var sts) = go sts
158− go (s:sts) = s : go sts
159−
160−etaConvert :: JS -> JS
161−etaConvert = everywhere (mkT convert)
162− where
163− convert :: JS -> JS
164− convert (JSBlock [JSReturn (JSApp (JSFunction Nothing idents block@(JSBlock body)) args)])
165− | all shouldInline args && not (or (map (flip isRebound block) args)) = JSBlock (replaceIdents (zip idents args) body)
166− convert js = js
167−
168−unThunk :: JS -> JS
169−unThunk = everywhere (mkT convert)
170− where
171− convert :: JS -> JS
172− convert (JSBlock [JSReturn (JSApp (JSFunction Nothing [] (JSBlock body)) [])]) = JSBlock body
173− convert js = js
174−
175−tco :: Options -> JS -> JS
176−tco opts | optionsTco opts = tco'
177− | otherwise = id
178−
179−tco' :: JS -> JS
180−tco' = everywhere (mkT convert)
181− where
182− tcoLabel :: String
183− tcoLabel = "tco"
184− tcoVar :: String -> String
185− tcoVar arg = "__tco_" ++ arg
186− copyVar :: String -> String
187− copyVar arg = "__copy_" ++ arg
188− convert :: JS -> JS
189− convert js@(JSVariableIntroduction name (Just fn@(JSFunction _ _ _))) =
190− let
191− (argss, body', replace) = collectAllFunctionArgs [] id fn
192− in case () of
193− _ | isTailCall name body' ->
194− let
195− allArgs = reverse $ concat argss
196− in
197− JSVariableIntroduction name (Just (replace (toLoop name allArgs body')))
198− | otherwise -> js
199− convert js = js
200− collectAllFunctionArgs :: [[String]] -> (JS -> JS) -> JS -> ([[String]], JS, JS -> JS)
201− collectAllFunctionArgs allArgs f (JSFunction ident args (JSBlock (body@(JSReturn _):_))) =
202− collectAllFunctionArgs (args : allArgs) (\b -> f (JSFunction ident (map copyVar args) (JSBlock [b]))) body
203− collectAllFunctionArgs allArgs f (JSFunction ident args body@(JSBlock _)) =
204− (args : allArgs, body, \b -> f (JSFunction ident (map copyVar args) b))
205− collectAllFunctionArgs allArgs f (JSReturn (JSFunction ident args (JSBlock [body]))) =
206− collectAllFunctionArgs (args : allArgs) (\b -> f (JSReturn (JSFunction ident (map copyVar args) (JSBlock [b])))) body
207− collectAllFunctionArgs allArgs f (JSReturn (JSFunction ident args body@(JSBlock _))) =
208− (args : allArgs, body, \b -> f (JSReturn (JSFunction ident (map copyVar args) b)))
209− collectAllFunctionArgs allArgs f body = (allArgs, body, f)
210− isTailCall :: String -> JS -> Bool
211− isTailCall ident js =
212− let
213− numSelfCalls = everything (+) (mkQ 0 countSelfCalls) js
214− numSelfCallsInTailPosition = everything (+) (mkQ 0 countSelfCallsInTailPosition) js
215− numSelfCallsUnderFunctions = everything (+) (mkQ 0 countSelfCallsUnderFunctions) js
216− in
217− numSelfCalls > 0
218− && numSelfCalls == numSelfCallsInTailPosition
219− && numSelfCallsUnderFunctions == 0
220− where
221− countSelfCalls :: JS -> Int
222− countSelfCalls (JSApp (JSVar ident') _) | ident == ident' = 1
223− countSelfCalls _ = 0
224− countSelfCallsInTailPosition :: JS -> Int
225− countSelfCallsInTailPosition (JSReturn ret) | isSelfCall ident ret = 1
226− countSelfCallsInTailPosition _ = 0
227− countSelfCallsUnderFunctions (JSFunction _ _ js') = everything (+) (mkQ 0 countSelfCalls) js'
228− countSelfCallsUnderFunctions _ = 0
229− toLoop :: String -> [String] -> JS -> JS
230− toLoop ident allArgs js = JSBlock $
231− map (\arg -> JSVariableIntroduction arg (Just (JSVar (copyVar arg)))) allArgs ++
232− [ JSLabel tcoLabel $ JSWhile (JSBooleanLiteral True) (JSBlock [ everywhere (mkT loopify) js ]) ]
233− where
234− loopify :: JS -> JS
235− loopify (JSReturn ret) | isSelfCall ident ret =
236− let
237− allArgumentValues = concat $ collectSelfCallArgs [] ret
238− in
239− JSBlock $ zipWith (\val arg ->
240− JSVariableIntroduction (tcoVar arg) (Just val)) allArgumentValues allArgs
241− ++ map (\arg ->
242− JSAssignment (JSVar arg) (JSVar (tcoVar arg))) allArgs
243− ++ [ JSContinue tcoLabel ]
244− loopify other = other
245− collectSelfCallArgs :: [[JS]] -> JS -> [[JS]]
246− collectSelfCallArgs allArgumentValues (JSApp fn args') = collectSelfCallArgs (args' : allArgumentValues) fn
247− collectSelfCallArgs allArgumentValues _ = allArgumentValues
248− isSelfCall :: String -> JS -> Bool
249− isSelfCall ident (JSApp (JSVar ident') _) | ident == ident' = True
250− isSelfCall ident (JSApp fn _) = isSelfCall ident fn
251− isSelfCall _ _ = False
252−
253−magicDo :: Options -> JS -> JS
254−magicDo opts | optionsMagicDo opts = magicDo'
255− | otherwise = id
256−
257−magicDo' :: JS -> JS
258−magicDo' = everywhere (mkT undo) . everywhere' (mkT convert)
259− where
260− fnName = "__do"
261− convert :: JS -> JS
262− convert (JSApp (JSApp ret [val]) []) | isReturn ret = val
263− convert (JSApp (JSApp bind [m]) [JSFunction Nothing ["_"] (JSBlock [JSReturn ret])]) | isBind bind =
264− JSFunction (Just fnName) [] $ JSBlock [ JSApp m [], JSReturn (JSApp ret []) ]
265− convert (JSApp (JSApp bind [m]) [JSFunction Nothing [arg] (JSBlock [JSReturn ret])]) | isBind bind =
266− JSFunction (Just fnName) [] $ JSBlock [ JSVariableIntroduction arg (Just (JSApp m [])), JSReturn (JSApp ret []) ]
267− convert other = other
268− isBind (JSApp bindPoly [effDict]) | isBindPoly bindPoly && isEffDict effDict = True
269− isBind _ = False
270− isReturn (JSApp retPoly [effDict]) | isRetPoly retPoly && isEffDict effDict = True
271− isReturn _ = False
272− isBindPoly (JSVar op) | op == identToJs (Op ">>=") = True
273− isBindPoly (JSAccessor prop (JSVar "Prelude")) | prop == identToJs (Op ">>=") = True
274− isBindPoly (JSIndexer (JSStringLiteral ">>=") (JSVar "Prelude")) = True
275− isBindPoly _ = False
276− isRetPoly (JSVar "ret") = True
277− isRetPoly (JSAccessor "ret" (JSVar "Prelude")) = True
278− isRetPoly _ = False
279− prelude = ModuleName (ProperName "Prelude")
280− effModule = ModuleName (ProperName "Eff")
281− Right (Ident effDictName) = mkDictionaryValueName
282− effModule
283− (Qualified (Just prelude) (ProperName "Monad"))
284− (TypeConstructor (Qualified (Just effModule) (ProperName "Eff")))
285− isEffDict (JSVar ident) | ident == effDictName = True
286− isEffDict (JSAccessor prop (JSVar "Eff")) | prop == effDictName = True
287− isEffDict _ = False
288− undo :: JS -> JS
289− undo (JSReturn (JSApp (JSFunction (Just ident) [] body) [])) | ident == fnName = body
290− undo other = other
291−
292−collapseNestedBlocks :: JS -> JS
293−collapseNestedBlocks = everywhere (mkT collapse)
294− where
295− collapse :: JS -> JS
296− collapse (JSBlock sts) = JSBlock (concatMap go sts)
297− collapse js = js
298− go :: JS -> [JS]
299− go (JSBlock sts) = sts
300− go s = [s]
301−
302−inlineOperator :: String -> (JS -> JS -> JS) -> JS -> JS
303−inlineOperator op f = everywhere (mkT convert)
304− where
305− convert :: JS -> JS
306− convert (JSApp (JSApp op [x]) [y]) | isOp op = f x y
307− convert other = other
308− isOp (JSAccessor longForm (JSVar "Prelude")) | longForm == identToJs (Op op) = True
309− isOp (JSIndexer (JSStringLiteral op') (JSVar "Prelude")) | op == op' = True
310− isOp _ = False
311−
312−inlineCommonOperators :: JS -> JS
313−inlineCommonOperators = applyAll
314− [ binary "+" "Num" tyNumber Add
315− , binary "-" "Num" tyNumber Subtract
316− , binary "*" "Num" tyNumber Multiply
317− , binary "/" "Num" tyNumber Divide
318− , binary "%" "Num" tyNumber Modulus
319− , unary "negate" "Num" tyNumber Negate
320−
321− , binary "<" "Ord" tyNumber LessThan
322− , binary ">" "Ord" tyNumber GreaterThan
323− , binary "<=" "Ord" tyNumber LessThanOrEqualTo
324− , binary ">=" "Ord" tyNumber GreaterThanOrEqualTo
325−
326− , binary "==" "Eq" tyNumber EqualTo
327− , binary "/=" "Eq" tyNumber NotEqualTo
328− , binary "==" "Eq" tyString EqualTo
329− , binary "/=" "Eq" tyString NotEqualTo
330− , binary "==" "Eq" tyBoolean EqualTo
331− , binary "/=" "Eq" tyBoolean NotEqualTo
332−
333− , binary "<<" "Bits" tyNumber ShiftLeft
334− , binary ">>" "Bits" tyNumber ShiftRight
335− , binary ">>>" "Bits" tyNumber ZeroFillShiftRight
336− , binary "&" "Bits" tyNumber BitwiseAnd
337− , binary "|" "Bits" tyNumber BitwiseOr
338− , binary "^" "Bits" tyNumber BitwiseXor
339− , unary "complement" "Bits" tyNumber BitwiseNot
340−
341− , binary "&&" "BoolLike" tyBoolean And
342− , binary "||" "BoolLike" tyBoolean Or
343− , unary "not" "BoolLike" tyBoolean Not
344− ]
345− where
346− binary :: String -> String -> Type -> BinaryOperator -> JS -> JS
347− binary opString className classTy op = everywhere (mkT convert)
348− where
349− convert :: JS -> JS
350− convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isOp fn && isOpDict className classTy dict = JSBinary op x y
351− convert other = other
352− isOp (JSAccessor longForm (JSVar "Prelude")) | longForm == identToJs (Op opString) = True
353− isOp (JSIndexer (JSStringLiteral op') (JSVar "Prelude")) | opString == op' = True
354− isOp _ = False
355− unary :: String -> String -> Type -> UnaryOperator -> JS -> JS
356− unary fnName className classTy op = everywhere (mkT convert)
357− where
358− convert :: JS -> JS
359− convert (JSApp (JSApp fn [dict]) [x]) | isOp fn && isOpDict className classTy dict = JSUnary op x
360− convert other = other
361− isOp (JSAccessor fnName' (JSVar "Prelude")) | fnName' == fnName = True
362− isOp _ = False
363− isOpDict className ty (JSAccessor prop (JSVar "Prelude")) | prop == dictName = True
364− where
365− Right (Ident dictName) = mkDictionaryValueName
366− (ModuleName (ProperName "Prelude"))
367− (Qualified (Just (ModuleName (ProperName "Prelude"))) (ProperName className))
368− ty
369− isOpDict _ _ _ = False
src/Language/PureScript/Declarations.hsdeleted−171
@@ -1,171 +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 #-}
16−
17−module Language.PureScript.Declarations where
18−
19−import Language.PureScript.Values
20−import Language.PureScript.Types
21−import Language.PureScript.Names
22−import Language.PureScript.Kinds
23−import Language.PureScript.CodeGen.JS.AST
24−
25−import qualified Data.Data as D
26−
27−-- |
28−-- A precedence level for an infix operator
29−--
30−type Precedence = Integer
31−
32−-- |
33−-- Associativity for infix operators
34−--
35−data Associativity = Infixl | Infixr deriving (Show, D.Data, D.Typeable)
36−
37−-- |
38−-- Fixity data for infix operators
39−--
40−data Fixity = Fixity Associativity Precedence deriving (Show, D.Data, D.Typeable)
41−
42−-- |
43−-- A module declaration, consisting of a module name and a list of declarations
44−--
45−data Module = Module ProperName [Declaration] deriving (Show, D.Data, D.Typeable)
46−
47−-- |
48−-- The type of a foreign import
49−--
50−data ForeignImportType
51− -- |
52− -- A regular foreign import
53− --
54− = ForeignImport
55− -- |
56− -- A foreign import which contains inline Javascript as a string literal
57− --
58− | InlineJavascript
59− -- |
60− -- A type class dictionary import, generated during desugaring of type class declarations
61− --
62− | TypeClassDictionaryImport
63− -- |
64− -- A type class dictionary member accessor import, generated during desugaring of type class declarations
65− --
66− | TypeClassAccessorImport deriving (Show, Eq, D.Data, D.Typeable)
67−
68−-- |
69−-- The data type of declarations
70−--
71−data Declaration
72− -- |
73− -- A data type declaration (name, arguments, data constructors)
74− --
75− = DataDeclaration ProperName [String] [(ProperName, Maybe Type)]
76− -- |
77− -- A minimal mutually recursive set of data type declarations
78− --
79− | DataBindingGroupDeclaration [Declaration]
80− -- |
81− -- A type synonym declaration (name, arguments, type)
82− --
83− | TypeSynonymDeclaration ProperName [String] Type
84− -- |
85− -- A type declaration for a value (name, ty)
86− --
87− | TypeDeclaration Ident Type
88− -- |
89− -- A value declaration (name, top-level binders, optional guard, value)
90− --
91− | ValueDeclaration Ident [Binder] (Maybe Guard) Value
92− -- |
93− -- A minimal mutually recursive set of value declarations
94− --
95− | BindingGroupDeclaration [(Ident, Value)]
96− -- |
97− -- A foreign import declaration (type, name, optional inline Javascript, type)
98− --
99− | ExternDeclaration ForeignImportType Ident (Maybe JS) Type
100− -- |
101− -- A data type foreign import (name, kind)
102− --
103− | ExternDataDeclaration ProperName Kind
104− -- |
105− -- A fixity declaration (fixity data, operator name)
106− --
107− | FixityDeclaration Fixity String
108− -- |
109− -- A module import (module name, optional set of identifiers to import)
110− --
111− | ImportDeclaration ModuleName (Maybe [Either Ident ProperName])
112− -- |
113− -- A type class declaration (name, argument, member declarations)
114− --
115− | TypeClassDeclaration ProperName String [Declaration]
116− -- |
117− -- A type instance declaration (dependencies, class name, instance type, member declarations)
118− --
119− | TypeInstanceDeclaration [(Qualified ProperName, Type)] (Qualified ProperName) Type [Declaration]
120− deriving (Show, D.Data, D.Typeable)
121−
122−-- |
123−-- Test if a declaration is a value declaration
124−--
125−isValueDecl :: Declaration -> Bool
126−isValueDecl (ValueDeclaration _ _ _ _) = True
127−isValueDecl _ = False
128−
129−-- |
130−-- Test if a declaration is a data type or type synonym declaration
131−--
132−isDataDecl :: Declaration -> Bool
133−isDataDecl (DataDeclaration _ _ _) = True
134−isDataDecl (TypeSynonymDeclaration _ _ _) = True
135−isDataDecl _ = False
136−
137−-- |
138−-- Test if a declaration is a module import
139−--
140−isImportDecl :: Declaration -> Bool
141−isImportDecl (ImportDeclaration _ _) = True
142−isImportDecl _ = False
143−
144−-- |
145−-- Test if a declaration is a data type foreign import
146−--
147−isExternDataDecl :: Declaration -> Bool
148−isExternDataDecl (ExternDataDeclaration _ _) = True
149−isExternDataDecl _ = False
150−
151−-- |
152−-- Test if a declaration is a fixity declaration
153−--
154−isFixityDecl :: Declaration -> Bool
155−isFixityDecl (FixityDeclaration _ _) = True
156−isFixityDecl _ = False
157−
158−-- |
159−-- Test if a declaration is a foreign import
160−--
161−isExternDecl :: Declaration -> Bool
162−isExternDecl (ExternDeclaration _ _ _ _) = True
163−isExternDecl _ = False
164−
165−-- |
166−-- Test if a declaration is a type class or instance declaration
167−--
168−isTypeClassDeclaration :: Declaration -> Bool
169−isTypeClassDeclaration (TypeClassDeclaration _ _ _) = True
170−isTypeClassDeclaration (TypeInstanceDeclaration _ _ _ _) = True
171−isTypeClassDeclaration _ = False
src/Language/PureScript/Kinds.hsdeleted−46
@@ -1,46 +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 (TypedUnknown(..))
22−
23−-- |
24−-- The data type of kinds
25−--
26−data Kind
27− -- |
28− -- Unification variable of type Kind
29− --
30− = KUnknown (TypedUnknown Kind)
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)
src/Language/PureScript/ModuleDependencies.hsdeleted−65
@@ -1,65 +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−) where
18−
19−import Data.Data
20−import Data.Graph
21−import Data.Generics
22−import Data.List (nub, intersect)
23−import Control.Applicative ((<$>))
24−
25−import Language.PureScript.Declarations
26−import Language.PureScript.Names
27−import Language.PureScript.Values
28−import Language.PureScript.Types
29−
30−-- |
31−-- Sort a collection of modules based on module dependencies.
32−--
33−-- Reports an error if the module graph contains a cycle.
34−--
35−sortModules :: [Module] -> Either String [Module]
36−sortModules ms = do
37− let verts = map (\m -> (m, getModuleName m, usedModules m)) ms
38− mapM toModule $ stronglyConnComp verts
39−
40−-- |
41−-- Calculate a list of used modules based on explicit imports and qualified names
42−--
43−usedModules :: (Data d) => d -> [ProperName]
44−usedModules = nub . everything (++) (mkQ [] qualifiedIdents `extQ` qualifiedProperNames `extQ` imports)
45− where
46− qualifiedIdents :: Qualified Ident -> [ProperName]
47− qualifiedIdents (Qualified (Just (ModuleName pn)) _) = [pn]
48− qualifiedIdents _ = []
49− qualifiedProperNames :: Qualified ProperName -> [ProperName]
50− qualifiedProperNames (Qualified (Just (ModuleName pn)) _) = [pn]
51− qualifiedProperNames _ = []
52− imports :: Declaration -> [ProperName]
53− imports (ImportDeclaration (ModuleName pn) _) = [pn]
54− imports _ = []
55−
56−getModuleName :: Module -> ProperName
57−getModuleName (Module pn _) = pn
58−
59−-- |
60−-- Convert a strongly connected component of the module graph to a module
61−--
62−toModule :: SCC Module -> Either String Module
63−toModule (AcyclicSCC m) = return m
64−toModule (CyclicSCC [m]) = return m
65−toModule (CyclicSCC _) = Left "Cycle in module dependencies"
src/Language/PureScript/Names.hsdeleted−74
@@ -1,74 +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.Data
21−
22−-- |
23−-- Names for value identifiers
24−--
25−data Ident
26− -- |
27− -- An alphanumeric identifier
28− --
29− = Ident String
30− -- |
31− -- A symbolic name for an infix operator
32− --
33− | Op String
34− -- |
35− -- An escaped name
36− --
37− | Escaped String deriving (Eq, Ord, Data, Typeable)
38−
39−instance Show Ident where
40− show (Ident s) = s
41− show (Op op) = '(':op ++ ")"
42− show (Escaped s) = s
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−instance Show ModuleName where
58− show (ModuleName name) = show name
59−
60−-- |
61−-- A qualified name, i.e. a name with an optional module name
62−--
63−data Qualified a = Qualified (Maybe ModuleName) a deriving (Eq, Ord, Data, Typeable)
64−
65−instance (Show a) => Show (Qualified a) where
66− show (Qualified Nothing a) = show a
67− show (Qualified (Just (ModuleName name)) a) = show name ++ "." ++ show a
68−
69−-- |
70−-- Provide a default module name, if a name is unqualified
71−--
72−qualify :: ModuleName -> Qualified a -> (ModuleName, a)
73−qualify m (Qualified Nothing a) = (m, a)
74−qualify _ (Qualified (Just m) a) = (m, a)
src/Language/PureScript/Options.hsdeleted−48
@@ -1,48 +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− -- Perform tail-call elimination
24− --
25− optionsTco :: Bool
26− -- |
27− -- Perform type checks at runtime
28− --
29− , optionsPerformRuntimeTypeChecks :: Bool
30− -- |
31− -- Inline calls to ret and bind for the Eff monad
32− --
33− , optionsMagicDo :: Bool
34− -- |
35− -- Check the type of Main.main and generate its code
36− --
37− , optionsRunMain :: Bool
38− -- |
39− -- Skip all optimizations
40− --
41− , optionsNoOptimizations :: Bool
42− } deriving Show
43−
44−-- |
45−-- Default compiler options
46−--
47−defaultOptions :: Options
48−defaultOptions = Options False False False False False
src/Language/PureScript/Parser.hsdeleted−35
@@ -1,35 +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.Values as P
33−import Language.PureScript.Parser.State as P
34−import Language.PureScript.Parser.Kinds as P
35−import Language.PureScript.Parser.Declarations as P
src/Language/PureScript/Parser/Common.hsdeleted−403
@@ -1,403 +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 reserved identifiers
31−--
32−reservedNames :: [String]
33−reservedNames = [ "case"
34− , "of"
35− , "data"
36− , "type"
37− , "var"
38− , "val"
39− , "while"
40− , "for"
41− , "foreach"
42− , "if"
43− , "then"
44− , "else"
45− , "return"
46− , "true"
47− , "false"
48− , "foreign"
49− , "import"
50− , "member"
51− , "forall"
52− , "do"
53− , "until"
54− , "in"
55− , "break"
56− , "catch"
57− , "continue"
58− , "debugger"
59− , "default"
60− , "delete"
61− , "finally"
62− , "function"
63− , "instanceof"
64− , "new"
65− , "switch"
66− , "this"
67− , "throw"
68− , "try"
69− , "typeof"
70− , "void"
71− , "with"
72− , "Number"
73− , "String"
74− , "Boolean"
75− , "infixl"
76− , "infixr"
77− , "module"
78− , "let"
79− , "class"
80− , "instance"
81− , "where"
82− , "null"
83− , "undefined" ]
84−
85−-- |
86−-- A list of reserved operators
87−--
88−reservedOpNames :: [String]
89−reservedOpNames = [ "=>", "->", "=", ".", "\\" ]
90−
91−-- |
92−-- Valid first characters for an identifier
93−--
94−identStart :: P.Parsec String u Char
95−identStart = P.lower <|> P.oneOf "_"
96−
97−-- |
98−-- Valid first characters for a proper name
99−--
100−properNameStart :: P.Parsec String u Char
101−properNameStart = P.upper
102−
103−-- |
104−-- Valid identifier characters
105−--
106−identLetter :: P.Parsec String u Char
107−identLetter = P.alphaNum <|> P.oneOf "_'"
108−
109−-- |
110−-- Valid first characters for an operator
111−--
112−opStart :: P.Parsec String u Char
113−opStart = P.oneOf ":!#$%&*+./<=>?@\\^|-~"
114−
115−-- |
116−-- Valid operators characters
117−--
118−opLetter :: P.Parsec String u Char
119−opLetter = P.oneOf ":!#$%&*+./<=>?@\\^|-~"
120−
121−-- |
122−-- The PureScript language definition
123−--
124−langDef :: PT.GenLanguageDef String u Identity
125−langDef = PT.LanguageDef
126− { PT.reservedNames = reservedNames
127− , PT.reservedOpNames = reservedOpNames
128− , PT.commentStart = "{-"
129− , PT.commentEnd = "-}"
130− , PT.commentLine = "--"
131− , PT.nestedComments = True
132− , PT.identStart = identStart
133− , PT.identLetter = identLetter
134− , PT.opStart = opStart
135− , PT.opLetter = opLetter
136− , PT.caseSensitive = True
137− }
138−
139−-- |
140−-- A token parser based on the language definition
141−--
142−tokenParser :: PT.GenTokenParser String u Identity
143−tokenParser = PT.makeTokenParser langDef
144−
145−-- |
146−-- Parse a token
147−--
148−lexeme :: P.Parsec String u a -> P.Parsec String u a
149−lexeme = PT.lexeme tokenParser
150−
151−-- |
152−-- Parse an identifier
153−--
154−identifier :: P.Parsec String u String
155−identifier = PT.identifier tokenParser
156−
157−-- |
158−-- Parse a reserved word
159−--
160−reserved :: String -> P.Parsec String u ()
161−reserved = PT.reserved tokenParser
162−
163−-- |
164−-- Parse a reserved operator
165−--
166−reservedOp :: String -> P.Parsec String u ()
167−reservedOp = PT.reservedOp tokenParser
168−
169−-- |
170−-- Parse an operator
171−--
172−operator :: P.Parsec String u String
173−operator = PT.operator tokenParser
174−
175−-- |
176−-- Parse a string literal
177−--
178−stringLiteral :: P.Parsec String u String
179−stringLiteral = PT.stringLiteral tokenParser
180−
181−-- |
182−-- Parse whitespace
183−--
184−whiteSpace :: P.Parsec String u ()
185−whiteSpace = PT.whiteSpace tokenParser
186−
187−-- |
188−-- Semicolon
189−--
190−semi :: P.Parsec String u String
191−semi = PT.semi tokenParser
192−
193−-- |
194−-- Colon
195−--
196−colon :: P.Parsec String u String
197−colon = PT.colon tokenParser
198−
199−-- |
200−-- Period
201−--
202−dot :: P.Parsec String u String
203−dot = PT.dot tokenParser
204−
205−-- |
206−-- Comma
207−--
208−comma :: P.Parsec String u String
209−comma = PT.comma tokenParser
210−
211−-- |
212−-- Backtick
213−--
214−tick :: P.Parsec String u Char
215−tick = lexeme $ P.char '`'
216−
217−-- |
218−-- Pipe character
219−--
220−pipe :: P.Parsec String u Char
221−pipe = lexeme $ P.char '|'
222−
223−-- |
224−-- Natural number
225−--
226−natural :: P.Parsec String u Integer
227−natural = PT.natural tokenParser
228−
229−-- |
230−-- Parse a proper name
231−--
232−properName :: P.Parsec String u ProperName
233−properName = lexeme $ ProperName <$> P.try ((:) <$> P.upper <*> many (PT.identLetter langDef) P.<?> "name")
234−
235−-- |
236−-- Parse a qualified name, i.e. M.name or just name
237−--
238−parseQualified :: P.Parsec String ParseState a -> P.Parsec String ParseState (Qualified a)
239−parseQualified parser = qual
240− where
241− qual = (Qualified <$> (Just . ModuleName <$> P.try (properName <* delimiter)) <*> parser)
242− <|> (Qualified Nothing <$> P.try parser)
243− delimiter = indented *> dot
244−
245−-- |
246−-- Parse an integer or floating point value
247−--
248−integerOrFloat :: P.Parsec String u (Either Integer Double)
249−integerOrFloat = (Left <$> P.try (PT.natural tokenParser) <|>
250− Right <$> P.try (PT.float tokenParser)) P.<?> "number"
251−
252−-- |
253−-- Parse an identifier or parenthesized operator
254−--
255−parseIdent :: P.Parsec String ParseState Ident
256−parseIdent = (Ident <$> identifier) <|> (Op <$> parens operator)
257−
258−
259−-- |
260−-- Parse an identifier or parenthesized operator that is not a reserved keyword or operator
261−--
262−parseNonReservedIdent :: P.Parsec String ParseState Ident
263−parseNonReservedIdent = do
264− ident <- parseIdent
265− when (isReserved ident) $ P.unexpected $ "reserved identifier " ++ show ident
266− return ident
267− where
268− isReserved (Ident ident) = ident `elem` reservedNames
269− isReserved (Op op) = op `elem` reservedOpNames
270−
271−-- |
272−-- Parse a token inside square brackets
273−--
274−squares :: P.Parsec String ParseState a -> P.Parsec String ParseState a
275−squares = P.between (lexeme $ P.char '[') (lexeme $ indented *> P.char ']') . (indented *>)
276−
277−-- |
278−-- Parse a token inside parentheses
279−--
280−parens :: P.Parsec String ParseState a -> P.Parsec String ParseState a
281−parens = P.between (lexeme $ P.char '(') (lexeme $ indented *> P.char ')') . (indented *>)
282−
283−-- |
284−-- Parse a token inside braces
285−--
286−braces :: P.Parsec String ParseState a -> P.Parsec String ParseState a
287−braces = P.between (lexeme $ P.char '{') (lexeme $ indented *> P.char '}') . (indented *>)
288−
289−-- |
290−-- Parse a token inside angle brackets
291−--
292−angles :: P.Parsec String ParseState a -> P.Parsec String ParseState a
293−angles = P.between (lexeme $ P.char '<') (lexeme $ indented *> P.char '>') . (indented *>)
294−
295−-- |
296−-- Parse zero or more values separated by a separator token
297−--
298−sepBy :: P.Parsec String ParseState a -> P.Parsec String ParseState sep -> P.Parsec String ParseState [a]
299−sepBy p s = P.sepBy (indented *> p) (indented *> s)
300−
301−-- |
302−-- Parse one or more values separated by a separator token
303−--
304−sepBy1 :: P.Parsec String ParseState a -> P.Parsec String ParseState sep -> P.Parsec String ParseState [a]
305−sepBy1 p s = P.sepBy1 (indented *> p) (indented *> s)
306−
307−-- |
308−-- Parse zero or more values separated by semicolons
309−--
310−semiSep :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
311−semiSep = flip sepBy semi
312−
313−-- |
314−-- Parse one or more values separated by semicolons
315−--
316−semiSep1 :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
317−semiSep1 = flip sepBy1 semi
318−
319−-- |
320−-- Parse zero or more values separated by commas
321−--
322−commaSep :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
323−commaSep = flip sepBy comma
324−
325−-- |
326−-- Parse one or more values separated by commas
327−--
328−commaSep1 :: P.Parsec String ParseState a -> P.Parsec String ParseState [a]
329−commaSep1 = flip sepBy1 comma
330−
331−-- |
332−-- Run the first parser, then match the second if possible, applying the specified function on a successful match
333−--
334−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
335−augment p q f = flip (maybe id $ flip f) <$> p <*> P.optionMaybe q
336−
337−-- |
338−-- Run the first parser, then match the second zero or more times, applying the specified function for each match
339−--
340−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
341−fold first more combine = do
342− a <- first
343− bs <- P.many more
344− return $ foldl combine a bs
345−
346−-- |
347−-- Build a parser from a smaller parser and a list of parsers for postfix operators
348−--
349−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
350−buildPostfixParser fs first = do
351− a <- first
352− go a
353− where
354− go a = do
355− maybeA <- P.optionMaybe $ P.choice (map ($ a) fs)
356− case maybeA of
357− Nothing -> return a
358− Just a' -> go a'
359−
360−-- |
361−-- Parse an identifier in backticks or an operator
362−--
363−parseIdentInfix :: P.Parsec String ParseState (Qualified Ident)
364−parseIdentInfix = (P.between tick tick (parseQualified (Ident <$> identifier))) <|> parseQualified (Op <$> operator)
365−
366−-- |
367−-- Mark the current indentation level
368−--
369−mark :: P.Parsec String ParseState a -> P.Parsec String ParseState a
370−mark p = do
371− current <- indentationLevel <$> P.getState
372− pos <- P.sourceColumn <$> P.getPosition
373− P.modifyState $ \st -> st { indentationLevel = pos }
374− a <- p
375− P.modifyState $ \st -> st { indentationLevel = current }
376− return a
377−
378−-- |
379−-- Check that the current identation level matches a predicate
380−--
381−checkIndentation :: (P.Column -> P.Column -> Bool) -> P.Parsec String ParseState ()
382−checkIndentation rel = do
383− col <- P.sourceColumn <$> P.getPosition
384− current <- indentationLevel <$> P.getState
385− guard (col `rel` current)
386−
387−-- |
388−-- Check that the current indentation level is past the current mark
389−--
390−indented :: P.Parsec String ParseState ()
391−indented = checkIndentation (>) P.<?> "indentation"
392−
393−-- |
394−-- Check that the current indentation level is at the same indentation as the current mark
395−--
396−same :: P.Parsec String ParseState ()
397−same = checkIndentation (==) P.<?> "no indentation"
398−
399−-- |
400−-- Run a parser which supports indentation
401−--
402−runIndentParser :: P.Parsec String ParseState a -> String -> Either P.ParseError a
403−runIndentParser p = P.runParser p (ParseState 0) ""
src/Language/PureScript/Parser/Declarations.hsdeleted−153
@@ -1,153 +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−) where
21−
22−import Data.Maybe (isJust, fromMaybe)
23−import Control.Monad (when)
24−import Control.Applicative
25−import qualified Text.Parsec as P
26−
27−import Language.PureScript.Names
28−import Language.PureScript.Parser.State
29−import Language.PureScript.Parser.Common
30−import Language.PureScript.Declarations
31−import Language.PureScript.Parser.Values
32−import Language.PureScript.Parser.Types
33−import Language.PureScript.Parser.Kinds
34−import Language.PureScript.Parser.JS
35−import Language.PureScript.CodeGen.JS.AST
36−import Language.PureScript.Values
37−
38−parseDataDeclaration :: P.Parsec String ParseState Declaration
39−parseDataDeclaration = do
40− reserved "data"
41− name <- indented *> properName
42− tyArgs <- many (indented *> identifier)
43− _ <- lexeme $ indented *> P.char '='
44− ctors <- sepBy1 ((,) <$> properName <*> P.optionMaybe (indented *> parsePolyType)) pipe
45− return $ DataDeclaration name tyArgs ctors
46−
47−parseTypeDeclaration :: P.Parsec String ParseState Declaration
48−parseTypeDeclaration =
49− TypeDeclaration <$> P.try (parseNonReservedIdent <* lexeme (indented *> P.string "::"))
50− <*> parsePolyType
51−
52−parseTypeSynonymDeclaration :: P.Parsec String ParseState Declaration
53−parseTypeSynonymDeclaration =
54− TypeSynonymDeclaration <$> (P.try (reserved "type") *> indented *> properName)
55− <*> many (indented *> identifier)
56− <*> (lexeme (indented *> P.char '=') *> parsePolyType)
57−
58−parseValueDeclaration :: P.Parsec String ParseState Declaration
59−parseValueDeclaration =
60− ValueDeclaration <$> parseNonReservedIdent
61− <*> P.many parseBinderNoParens
62− <*> P.optionMaybe parseGuard
63− <*> ((lexeme (indented *> P.char '=')) *> parseValue)
64−
65−parseExternDeclaration :: P.Parsec String ParseState Declaration
66−parseExternDeclaration = P.try (reserved "foreign") *> indented *> (reserved "import") *> indented *>
67− (ExternDataDeclaration <$> (P.try (reserved "data") *> indented *> properName)
68− <*> (lexeme (indented *> P.string "::") *> parseKind)
69− <|> do ident <- parseNonReservedIdent
70− js <- P.optionMaybe (parseJSLiteral <$> stringLiteral)
71− ty <- (lexeme (indented *> P.string "::") *> parsePolyType)
72− return $ ExternDeclaration (if isJust js then InlineJavascript else ForeignImport) ident js ty)
73−parseJSLiteral :: String -> JS
74−parseJSLiteral s = either (const $ JSRaw s) id $ P.runParser parseJS () "Javascript" s
75−
76−parseAssociativity :: P.Parsec String ParseState Associativity
77−parseAssociativity =
78− (P.try (reserved "infixl") >> return Infixl) <|>
79− (P.try (reserved "infixr") >> return Infixr)
80−
81−parseFixity :: P.Parsec String ParseState Fixity
82−parseFixity = Fixity <$> parseAssociativity <*> (indented *> natural)
83−
84−parseFixityDeclaration :: P.Parsec String ParseState Declaration
85−parseFixityDeclaration = do
86− fixity <- parseFixity
87− indented
88− name <- operator
89− return $ FixityDeclaration fixity name
90−
91−parseImportDeclaration :: P.Parsec String ParseState Declaration
92−parseImportDeclaration = do
93− reserved "import"
94− indented
95− moduleName <- ModuleName <$> properName
96− idents <- P.optionMaybe $ parens $ commaSep1 (Left <$> parseIdent <|> Right <$> properName)
97− return $ ImportDeclaration moduleName idents
98−
99−parseTypeClassDeclaration :: P.Parsec String ParseState Declaration
100−parseTypeClassDeclaration = do
101− reserved "class"
102− className <- indented *> properName
103− ident <- indented *> identifier
104− indented *> reserved "where"
105− members <- mark (P.many (same *> parseTypeDeclaration))
106− return $ TypeClassDeclaration className ident members
107−
108−parseTypeInstanceDeclaration :: P.Parsec String ParseState Declaration
109−parseTypeInstanceDeclaration = do
110− reserved "instance"
111− deps <- P.optionMaybe $ do
112− deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> parseType))
113− indented
114− reservedOp "=>"
115− return deps
116− className <- indented *> parseQualified properName
117− ty <- indented *> parseType
118− indented *> reserved "where"
119− members <- mark (P.many (same *> parseValueDeclaration))
120− return $ TypeInstanceDeclaration (fromMaybe [] deps) className ty members
121−
122−-- |
123−-- Parse a single declaration
124−--
125−parseDeclaration :: P.Parsec String ParseState Declaration
126−parseDeclaration = P.choice
127− [ parseDataDeclaration
128− , parseTypeDeclaration
129− , parseTypeSynonymDeclaration
130− , parseValueDeclaration
131− , parseExternDeclaration
132− , parseFixityDeclaration
133− , parseImportDeclaration
134− , parseTypeClassDeclaration
135− , parseTypeInstanceDeclaration ] P.<?> "declaration"
136−
137−-- |
138−-- Parse a module header and a collection of declarations
139−--
140−parseModule :: P.Parsec String ParseState Module
141−parseModule = do
142− reserved "module"
143− indented
144− name <- properName
145− _ <- lexeme $ P.string "where"
146− decls <- mark (P.many (same *> parseDeclaration))
147− return $ Module name decls
148−
149−-- |
150−-- Parse a collection of modules
151−--
152−parseModules :: P.Parsec String ParseState [Module]
153−parseModules = whiteSpace *> mark (P.many (same *> parseModule)) <* P.eof
src/Language/PureScript/Parser/JS.hsdeleted−167
@@ -1,167 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser.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−-- A parser for a small fragment of Javascript
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Parser.JS (
17− parseJS
18−) where
19−
20−import Language.PureScript.Values
21−import Language.PureScript.Names
22−import Language.PureScript.CodeGen.JS.AST
23−import qualified Language.PureScript.Parser.Common as C
24−import Control.Applicative
25−import Data.Functor.Identity
26−import qualified Text.Parsec as P
27−import qualified Text.Parsec.Token as P
28−import qualified Text.Parsec.Expr as P
29−
30−booleanLiteral :: P.Parsec String u Bool
31−booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
32−
33−parseNumericLiteral :: P.Parsec String u JS
34−parseNumericLiteral = JSNumericLiteral <$> C.integerOrFloat
35−
36−parseStringLiteral :: P.Parsec String u JS
37−parseStringLiteral = JSStringLiteral <$> C.stringLiteral
38−
39−parseBooleanLiteral :: P.Parsec String u JS
40−parseBooleanLiteral = JSBooleanLiteral <$> booleanLiteral
41−
42−parseArrayLiteral :: P.Parsec String u JS
43−parseArrayLiteral = JSArrayLiteral <$> P.squares C.tokenParser (P.commaSep C.tokenParser parseJS)
44−
45−parseObjectLiteral :: P.Parsec String u JS
46−parseObjectLiteral = JSObjectLiteral <$> P.braces C.tokenParser (P.commaSep C.tokenParser parseIdentifierAndValue)
47−
48−parseIdentifierAndValue :: P.Parsec String u (String, JS)
49−parseIdentifierAndValue = (,) <$> (C.identifier <* C.colon)
50− <*> parseJS
51−
52−parseFunction :: P.Parsec String u JS
53−parseFunction = do
54− C.reserved "function"
55− name <- P.optionMaybe C.identifier
56− args <- P.parens C.tokenParser $ P.commaSep C.tokenParser C.identifier
57− body <- parseJS
58− return $ JSFunction name args body
59−
60−parseBlock :: P.Parsec String u JS
61−parseBlock = JSBlock <$> P.braces C.tokenParser (P.many parseJS)
62−
63−parseVar :: P.Parsec String u JS
64−parseVar = JSVar <$> C.identifier
65−
66−parseJSAtom :: P.Parsec String u JS
67−parseJSAtom = P.choice
68− [ P.try parseNumericLiteral
69− , P.try parseStringLiteral
70− , P.try parseBooleanLiteral
71− , parseArrayLiteral
72− , P.try parseObjectLiteral
73− , parseFunction
74− , parseBlock
75− , P.try parseVar
76− , parseVariableIntroduction
77− , parseWhile
78− , parseIf
79− , parseReturn
80− , P.parens C.tokenParser parseJS ]
81−
82−parseAccessor :: JS -> P.Parsec String u JS
83−parseAccessor js = P.try $ flip JSAccessor js <$> (C.dot *> P.notFollowedBy C.opLetter *> C.identifier)
84−
85−parseIndexer :: JS -> P.Parsec String u JS
86−parseIndexer js = P.try $ flip JSIndexer js <$> (P.squares C.tokenParser parseJS)
87−
88−parseConditional :: JS -> P.Parsec String u JS
89−parseConditional js = P.try $ do
90− _ <- C.lexeme $ P.char '?'
91− tr <- parseJS
92− _ <- C.lexeme $ P.char ':'
93− fa <- parseJS
94− return $ JSConditional js tr fa
95−
96−binary :: BinaryOperator -> String -> P.Assoc -> P.Operator String u Identity JS
97−binary op s f = P.Infix (P.try $ C.reservedOp s >> return (JSBinary op)) f
98−
99−unary :: UnaryOperator -> String -> P.Operator String u Identity JS
100−unary op s = P.Prefix (P.try $ C.reservedOp s >> return (JSUnary op))
101−
102−-- |
103−-- Parse a simplified Javascript expression
104−--
105−parseJS :: P.Parsec String u JS
106−parseJS =
107− (P.buildExpressionParser operators
108− . C.buildPostfixParser postfixTable2
109− $ indexersAndAccessors) P.<?> "javascript"
110− where
111− indexersAndAccessors = C.buildPostfixParser postfixTable1 parseJSAtom
112− postfixTable1 = [ parseAccessor, parseIndexer, parseConditional, parseAssignment ]
113− postfixTable2 = [ \v -> P.try $ JSApp v <$> (P.parens C.tokenParser (P.commaSep C.tokenParser parseJS)) ]
114− operators = [ [ binary LessThan "<" P.AssocLeft]
115− , [ binary LessThanOrEqualTo "<=" P.AssocLeft]
116− , [ binary GreaterThan ">" P.AssocLeft]
117− , [ binary GreaterThanOrEqualTo ">=" P.AssocLeft]
118− , [ unary Not "!" ]
119− , [ unary BitwiseNot "~" ]
120− , [ unary Negate "-" ]
121− , [ unary Positive "+" ]
122− , [ binary Multiply "*" P.AssocLeft]
123− , [ binary Divide "/" P.AssocLeft]
124− , [ binary Modulus "%" P.AssocLeft]
125− , [ binary Add "+" P.AssocLeft]
126− , [ binary Subtract "-" P.AssocLeft]
127− , [ binary ShiftLeft "<<" P.AssocLeft]
128− , [ binary ShiftRight ">>" P.AssocLeft]
129− , [ binary ZeroFillShiftRight ">>>" P.AssocLeft]
130− , [ binary EqualTo "===" P.AssocLeft]
131− , [ binary NotEqualTo "!==" P.AssocLeft]
132− , [ binary BitwiseAnd "&" P.AssocLeft]
133− , [ binary BitwiseXor "^" P.AssocLeft]
134− , [ binary BitwiseOr "|" P.AssocLeft]
135− , [ binary And "&&" P.AssocRight]
136− , [ binary Or "||" P.AssocRight]
137− ]
138−
139−parseVariableIntroduction :: P.Parsec String u JS
140−parseVariableIntroduction = do
141− C.reserved "var"
142− name <- P.identifier C.tokenParser
143− value <- P.optionMaybe $ do
144− _ <- C.lexeme $ P.char '='
145− value <- parseJS
146− _ <- C.semi
147− return value
148− return $ JSVariableIntroduction name value
149−
150−parseAssignment :: JS -> P.Parsec String u JS
151−parseAssignment tgt = do
152− _ <- C.lexeme $ P.char '='
153− value <- parseJS
154− _ <- C.semi
155− return $ JSAssignment tgt value
156−
157−parseWhile :: P.Parsec String u JS
158−parseWhile = JSWhile <$> (C.reserved "while" *> P.parens C.tokenParser parseJS)
159− <*> parseJS
160−
161−parseIf :: P.Parsec String u JS
162−parseIf = JSIfElse <$> (C.reserved "if" *> P.parens C.tokenParser parseJS)
163− <*> parseJS
164− <*> P.optionMaybe (C.reserved "else" >> parseJS)
165−
166−parseReturn :: P.Parsec String u JS
167−parseReturn = JSReturn <$> (C.reserved "return" *> parseJS <* C.semi)
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−120
@@ -1,120 +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−) where
20−
21−import Language.PureScript.Types
22−import Language.PureScript.Parser.State
23−import Language.PureScript.Parser.Common
24−import Control.Applicative
25−import qualified Text.Parsec as P
26−import qualified Text.Parsec.Expr as P
27−import Control.Monad (when, unless)
28−
29−parseNumber :: P.Parsec String ParseState Type
30−parseNumber = const tyNumber <$> reserved "Number"
31−
32−parseString :: P.Parsec String ParseState Type
33−parseString = const tyString <$> reserved "String"
34−
35−parseBoolean :: P.Parsec String ParseState Type
36−parseBoolean = const tyBoolean <$> reserved "Boolean"
37−
38−parseArray :: P.Parsec String ParseState Type
39−parseArray = squares $ return tyArray
40−
41−parseArrayOf :: P.Parsec String ParseState Type
42−parseArrayOf = squares $ TypeApp tyArray <$> parseType
43−
44−parseFunction :: P.Parsec String ParseState Type
45−parseFunction = parens $ P.try (lexeme (P.string "->")) >> return tyFunction
46−
47−parseObject :: P.Parsec String ParseState Type
48−parseObject = braces $ Object <$> parseRow False
49−
50−parseTypeVariable :: P.Parsec String ParseState Type
51−parseTypeVariable = TypeVar <$> identifier
52−
53−parseTypeConstructor :: P.Parsec String ParseState Type
54−parseTypeConstructor = TypeConstructor <$> parseQualified properName
55−
56−parseForAll :: P.Parsec String ParseState Type
57−parseForAll = (mkForAll <$> (P.try (reserved "forall") *> P.many1 (indented *> identifier) <* indented <* dot)
58− <*> parseConstrainedType)
59−
60−parseTypeAtom :: P.Parsec String ParseState Type
61−parseTypeAtom = indented *> P.choice (map P.try
62− [ parseNumber
63− , parseString
64− , parseBoolean
65− , parseArray
66− , parseArrayOf
67− , parseFunction
68− , parseObject
69− , parseTypeVariable
70− , parseTypeConstructor
71− , parseForAll
72− , parens (parseRow True)
73− , parens parsePolyType ])
74−
75−parseConstrainedType :: P.Parsec String ParseState Type
76−parseConstrainedType = do
77− constraints <- P.optionMaybe . P.try $ do
78− constraints <- parens . commaSep1 $ do
79− className <- parseQualified properName
80− indented
81− ty <- parseType
82− return (className, ty)
83− _ <- lexeme $ P.string "=>"
84− return constraints
85− indented
86− ty <- parseType
87− return $ maybe ty (flip ConstrainedType ty) constraints
88−
89−parseAnyType :: P.Parsec String ParseState Type
90−parseAnyType = (P.buildExpressionParser operators $ parseTypeAtom) P.<?> "type"
91− where
92− operators = [ [ P.Infix (return TypeApp) P.AssocLeft ]
93− , [ P.Infix (P.try (lexeme (P.string "->")) >> return function) P.AssocRight ] ]
94−
95−-- |
96−-- Parse a monotype
97−--
98−parseType :: P.Parsec String ParseState Type
99−parseType = do
100− ty <- parseAnyType
101− unless (isMonoType ty) $ P.unexpected "polymorphic type"
102− return ty
103−
104−-- |
105−-- Parse a polytype
106−--
107−parsePolyType :: P.Parsec String ParseState Type
108−parsePolyType = do
109− ty <- parseAnyType
110− return ty
111−
112−parseNameAndType :: P.Parsec String ParseState t -> P.Parsec String ParseState (String, t)
113−parseNameAndType p = (,) <$> (indented *> identifier <* indented <* lexeme (P.string "::")) <*> p
114−
115−parseRowEnding :: P.Parsec String ParseState Type
116−parseRowEnding = P.option REmpty (TypeVar <$> (lexeme (indented *> P.char '|') *> indented *> identifier))
117−
118−parseRow :: Bool -> P.Parsec String ParseState Type
119−parseRow nonEmpty = (curry rowFromList <$> (many $ parseNameAndType parsePolyType) <*> parseRowEnding) P.<?> "row"
120− where many = if nonEmpty then commaSep1 else commaSep
src/Language/PureScript/Parser/Values.hsdeleted−299
@@ -1,299 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Parser.Values
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 values, statements, binders and guards
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Parser.Values (
17− parseValue,
18− parseStatement,
19− parseGuard,
20− parseBinder,
21− parseBinderNoParens,
22−) where
23−
24−import Language.PureScript.Values
25−import Language.PureScript.Parser.State
26−import qualified Language.PureScript.Parser.Common as C
27−import Control.Applicative
28−import qualified Text.Parsec as P
29−import Text.Parsec.Expr
30−import Language.PureScript.Parser.Types
31−
32−booleanLiteral :: P.Parsec String ParseState Bool
33−booleanLiteral = (C.reserved "true" >> return True) P.<|> (C.reserved "false" >> return False)
34−
35−parseNumericLiteral :: P.Parsec String ParseState Value
36−parseNumericLiteral = NumericLiteral <$> C.integerOrFloat
37−
38−parseStringLiteral :: P.Parsec String ParseState Value
39−parseStringLiteral = StringLiteral <$> C.stringLiteral
40−
41−parseBooleanLiteral :: P.Parsec String ParseState Value
42−parseBooleanLiteral = BooleanLiteral <$> booleanLiteral
43−
44−parseArrayLiteral :: P.Parsec String ParseState Value
45−parseArrayLiteral = ArrayLiteral <$> C.squares (C.commaSep parseValue)
46−
47−parseObjectLiteral :: P.Parsec String ParseState Value
48−parseObjectLiteral = ObjectLiteral <$> C.braces (C.commaSep parseIdentifierAndValue)
49−
50−parseIdentifierAndValue :: P.Parsec String ParseState (String, Value)
51−parseIdentifierAndValue = (,) <$> (C.indented *> C.identifier <* C.indented <* C.colon)
52− <*> (C.indented *> parseValue)
53−
54−parseAbs :: P.Parsec String ParseState Value
55−parseAbs = do
56− C.reservedOp "\\"
57− args <- P.many1 (C.indented *> (Abs <$> C.parseIdent))
58− C.indented *> C.reservedOp "->"
59− value <- parseValue
60− return $ toFunction args value
61− where
62− toFunction :: [Value -> Value] -> Value -> Value
63− toFunction args value = foldr (($)) value args
64−
65−parseVar :: P.Parsec String ParseState Value
66−parseVar = Var <$> C.parseQualified C.parseIdent
67−
68−parseConstructor :: P.Parsec String ParseState Value
69−parseConstructor = Constructor <$> C.parseQualified C.properName
70−
71−parseCase :: P.Parsec String ParseState Value
72−parseCase = Case <$> P.between (P.try (C.reserved "case")) (C.indented *> C.reserved "of") (return <$> parseValue)
73− <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative)))
74−
75−parseCaseAlternative :: P.Parsec String ParseState ([Binder], Maybe Guard, Value)
76−parseCaseAlternative = (,,) <$> (return <$> parseBinder)
77− <*> P.optionMaybe parseGuard
78− <*> (C.indented *> C.reservedOp "->" *> parseValue)
79− P.<?> "case alternative"
80−
81−parseIfThenElse :: P.Parsec String ParseState Value
82−parseIfThenElse = IfThenElse <$> (P.try (C.reserved "if") *> C.indented *> parseValue)
83− <*> (C.indented *> C.reserved "then" *> C.indented *> parseValue)
84− <*> (C.indented *> C.reserved "else" *> C.indented *> parseValue)
85−
86−parseBlock :: P.Parsec String ParseState Value
87−parseBlock = Block <$> parseManyStatements
88−
89−parseManyStatements :: P.Parsec String ParseState [Statement]
90−parseManyStatements = (do
91− _ <- C.lexeme $ P.char '{'
92− C.indented
93− sts <- C.mark (P.many (C.same *> C.mark parseStatement))
94− _ <- C.lexeme (P.char '}')
95− return sts) P.<?> "block"
96−
97−parseValueAtom :: P.Parsec String ParseState Value
98−parseValueAtom = P.choice
99− [ P.try parseNumericLiteral
100− , P.try parseStringLiteral
101− , P.try parseBooleanLiteral
102− , parseArrayLiteral
103− , P.try parseObjectLiteral
104− , parseAbs
105− , P.try parseConstructor
106− , P.try parseVar
107− , parseBlock
108− , parseCase
109− , parseIfThenElse
110− , parseDo
111− , Parens <$> C.parens parseValue ]
112−
113−parsePropertyUpdate :: P.Parsec String ParseState (String, Value)
114−parsePropertyUpdate = do
115− name <- C.lexeme C.identifier
116− _ <- C.lexeme $ C.indented *> P.char '='
117− value <- C.indented *> parseValue
118− return (name, value)
119−
120−parseAccessor :: Value -> P.Parsec String ParseState Value
121−parseAccessor (Constructor _) = P.unexpected "constructor"
122−parseAccessor obj = P.try $ Accessor <$> (C.indented *> C.dot *> P.notFollowedBy C.opLetter *> C.indented *> C.identifier) <*> pure obj
123−
124−parseDo :: P.Parsec String ParseState Value
125−parseDo = do
126− C.reserved "do"
127− C.indented
128− Do <$> C.mark (P.many (C.same *> C.mark parseDoNotationElement))
129−
130−parseDoNotationLet :: P.Parsec String ParseState DoNotationElement
131−parseDoNotationLet = DoNotationLet <$> (C.reserved "let" *> C.indented *> parseBinder)
132− <*> (C.indented *> C.reservedOp "=" *> parseValue)
133−
134−parseDoNotationBind :: P.Parsec String ParseState DoNotationElement
135−parseDoNotationBind = DoNotationBind <$> parseBinder <*> (C.indented *> C.reservedOp "<-" *> parseValue)
136−
137−parseDoNotationElement :: P.Parsec String ParseState DoNotationElement
138−parseDoNotationElement = P.choice
139− [ P.try parseDoNotationBind
140− , parseDoNotationLet
141− , P.try (DoNotationValue <$> parseValue) ]
142−
143−-- |
144−-- Parse a value
145−--
146−parseValue :: P.Parsec String ParseState Value
147−parseValue =
148− (buildExpressionParser operators
149− . C.buildPostfixParser postfixTable2
150− $ indexersAndAccessors) P.<?> "expression"
151− where
152− indexersAndAccessors = C.buildPostfixParser postfixTable1 parseValueAtom
153− postfixTable1 = [ parseAccessor
154− , \v -> P.try $ flip ObjectUpdate <$> (C.indented *> C.braces (C.commaSep1 (C.indented *> parsePropertyUpdate))) <*> pure v ]
155− postfixTable2 = [ \v -> P.try (C.indented *> indexersAndAccessors >>= return . flip App) <*> pure v
156− , \v -> flip (TypedValue True) <$> (P.try (C.lexeme (C.indented *> P.string "::")) *> parsePolyType) <*> pure v
157− ]
158− operators = [ [ Infix (C.lexeme (P.try (C.indented *> C.parseIdentInfix P.<?> "operator") >>= \ident ->
159− return (BinaryNoParens ident))) AssocRight ]
160− ]
161−
162−parseVariableIntroduction :: P.Parsec String ParseState Statement
163−parseVariableIntroduction = do
164− C.reserved "var"
165− name <- C.indented *> C.parseIdent
166− _ <- C.lexeme $ C.indented *> P.char '='
167− value <- parseValue
168− _ <- C.indented *> C.semi
169− return $ VariableIntroduction name value
170−
171−parseAssignment :: P.Parsec String ParseState Statement
172−parseAssignment = do
173− tgt <- P.try $ do
174− tgt <- C.parseIdent
175− _ <- C.lexeme $ C.indented *> P.char '='
176− return tgt
177− value <- parseValue
178− _ <- C.indented *> C.semi
179− return $ Assignment tgt value
180−
181−parseWhile :: P.Parsec String ParseState Statement
182−parseWhile = While <$> (C.reserved "while" *> C.indented *> C.parens parseValue)
183− <*> (C.indented *> parseManyStatements)
184−
185−parseFor :: P.Parsec String ParseState Statement
186−parseFor = For <$> (C.reserved "for" *> C.indented *> C.lexeme (P.char '(') *> C.indented *> C.parseIdent)
187− <*> (C.indented *> C.lexeme (P.string "<-") *> parseValue)
188− <*> (C.indented *> C.reserved "until" *> parseValue <* C.indented <* C.lexeme (P.char ')'))
189− <*> parseManyStatements
190−
191−parseIf :: P.Parsec String ParseState Statement
192−parseIf = If <$> parseIfStatement
193−
194−parseIfStatement :: P.Parsec String ParseState IfStatement
195−parseIfStatement =
196− IfStatement <$> (C.reserved "if" *> C.indented *> C.parens parseValue)
197− <*> parseManyStatements
198− <*> P.optionMaybe parseElseStatement
199−
200−parseElseStatement :: P.Parsec String ParseState ElseStatement
201−parseElseStatement = C.reserved "else" >> (ElseIf <$> parseIfStatement
202− <|> Else <$> parseManyStatements)
203−
204−parseReturn :: P.Parsec String ParseState Statement
205−parseReturn = Return <$> (C.reserved "return" *> parseValue <* C.indented <* C.semi)
206−
207−-- |
208−-- Parse a statement
209−--
210−parseStatement :: P.Parsec String ParseState Statement
211−parseStatement = P.choice
212− [ parseVariableIntroduction
213− , parseAssignment
214− , parseWhile
215− , parseFor
216− , parseIf
217− , parseReturn ] P.<?> "statement"
218−
219−parseStringBinder :: P.Parsec String ParseState Binder
220−parseStringBinder = StringBinder <$> C.stringLiteral
221−
222−parseBooleanBinder :: P.Parsec String ParseState Binder
223−parseBooleanBinder = BooleanBinder <$> booleanLiteral
224−
225−parseNumberBinder :: P.Parsec String ParseState Binder
226−parseNumberBinder = NumberBinder <$> C.integerOrFloat
227−
228−parseVarBinder :: P.Parsec String ParseState Binder
229−parseVarBinder = VarBinder <$> C.parseIdent
230−
231−parseNullaryBinder :: P.Parsec String ParseState Binder
232−parseNullaryBinder = NullaryBinder <$> C.lexeme (C.parseQualified C.properName)
233−
234−parseUnaryBinder :: P.Parsec String ParseState Binder
235−parseUnaryBinder = UnaryBinder <$> C.lexeme (C.parseQualified C.properName) <*> (C.indented *> parseBinder)
236−
237−parseObjectBinder :: P.Parsec String ParseState Binder
238−parseObjectBinder = ObjectBinder <$> C.braces (C.commaSep (C.indented *> parseIdentifierAndBinder))
239−
240−parseArrayBinder :: P.Parsec String ParseState Binder
241−parseArrayBinder = C.squares $ ArrayBinder <$> (C.commaSep (C.indented *> parseBinder))
242−
243−parseNamedBinder :: P.Parsec String ParseState Binder
244−parseNamedBinder = NamedBinder <$> (C.parseIdent <* C.indented <* C.lexeme (P.char '@'))
245− <*> (C.indented *> parseBinder)
246−
247−parseNullBinder :: P.Parsec String ParseState Binder
248−parseNullBinder = C.lexeme (P.char '_') *> P.notFollowedBy C.identLetter *> return NullBinder
249−
250−parseIdentifierAndBinder :: P.Parsec String ParseState (String, Binder)
251−parseIdentifierAndBinder = do
252− name <- C.lexeme C.identifier
253− _ <- C.lexeme $ C.indented *> P.char '='
254− binder <- C.indented *> parseBinder
255− return (name, binder)
256−
257−parseBinderAtom :: P.Parsec String ParseState Binder
258−parseBinderAtom = P.choice (map P.try
259− [ parseNullBinder
260− , parseStringBinder
261− , parseBooleanBinder
262− , parseNumberBinder
263− , parseNamedBinder
264− , parseVarBinder
265− , parseUnaryBinder
266− , parseNullaryBinder
267− , parseObjectBinder
268− , parseArrayBinder
269− , C.parens parseBinder ]) P.<?> "binder"
270−
271−-- |
272−-- Parse a binder
273−--
274−parseBinder :: P.Parsec String ParseState Binder
275−parseBinder = (buildExpressionParser operators parseBinderAtom) P.<?> "expression"
276− where
277− operators = [ [ Infix ( C.lexeme (P.try $ C.indented *> C.reservedOp ":") >> return ConsBinder) AssocRight ] ]
278−
279−-- |
280−-- Parse a binder as it would appear in a top level declaration
281−--
282−parseBinderNoParens :: P.Parsec String ParseState Binder
283−parseBinderNoParens = P.choice (map P.try
284− [ parseNullBinder
285− , parseStringBinder
286− , parseBooleanBinder
287− , parseNumberBinder
288− , parseNamedBinder
289− , parseVarBinder
290− , parseNullaryBinder
291− , parseObjectBinder
292− , parseArrayBinder
293− , C.parens parseBinder ]) P.<?> "binder"
294−-- |
295−-- Parse a guard
296−--
297−parseGuard :: P.Parsec String ParseState Guard
298−parseGuard = C.indented *> C.pipe *> C.indented *> parseValue
299−
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−22
@@ -1,22 +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−-- |
19−-- Wrap a string in parentheses
20−--
21−parens :: String -> String
22−parens s = ('(':s) ++ ")"
src/Language/PureScript/Pretty/JS.hsdeleted−254
@@ -1,254 +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.Names
21−import Language.PureScript.Values
22−import Language.PureScript.Pretty.Common
23−import Language.PureScript.CodeGen.JS.AST
24−
25−import Data.List
26−import Data.Maybe (fromMaybe)
27−import qualified Control.Arrow as A
28−import Control.Arrow ((<+>))
29−import Control.PatternArrows
30−import Control.Applicative
31−import Control.Monad.State
32−
33−newtype PrinterState = PrinterState { indent :: Int } deriving (Show, Eq, Ord)
34−
35−-- |
36−-- Number of characters per identation level
37−--
38−blockIndent :: Int
39−blockIndent = 4
40−
41−-- |
42−-- Pretty print with a new indentation level
43−--
44−withIndent :: StateT PrinterState Maybe String -> StateT PrinterState Maybe String
45−withIndent action = do
46− modify $ \st -> st { indent = indent st + blockIndent }
47− result <- action
48− modify $ \st -> st { indent = indent st - blockIndent }
49− return result
50−
51−-- |
52−-- Get the current indentation level
53−--
54−currentIndent :: StateT PrinterState Maybe String
55−currentIndent = do
56− current <- get
57− return $ replicate (indent current) ' '
58−
59−literals :: Pattern PrinterState JS String
60−literals = mkPattern' match
61− where
62− match :: JS -> StateT PrinterState Maybe String
63− match (JSNumericLiteral n) = return $ either show show n
64− match (JSStringLiteral s) = return $ show s
65− match (JSBooleanLiteral True) = return "true"
66− match (JSBooleanLiteral False) = return "false"
67− match (JSArrayLiteral xs) = fmap concat $ sequence
68− [ return "[ "
69− , fmap (intercalate ", ") $ forM xs prettyPrintJS'
70− , return " ]"
71− ]
72− match (JSObjectLiteral ps) = fmap concat $ sequence
73− [ return "{\n"
74− , withIndent $ do
75− jss <- forM ps $ \(key, value) -> fmap ((key ++ ": ") ++) . prettyPrintJS' $ value
76− indentString <- currentIndent
77− return $ intercalate ", \n" $ map (indentString ++) jss
78− , return "\n"
79− , currentIndent
80− , return "}"
81− ]
82− match (JSBlock sts) = fmap concat $ sequence
83− [ return "{\n"
84− , withIndent $ do
85− jss <- forM sts prettyPrintJS'
86− indentString <- currentIndent
87− return $ intercalate "\n" $ map (++ ";") $ map (indentString ++) jss
88− , return "\n"
89− , currentIndent
90− , return "}"
91− ]
92− match (JSVar ident) = return ident
93− match (JSVariableIntroduction ident value) = fmap concat $ sequence
94− [ return "var "
95− , return ident
96− , maybe (return "") (fmap (" = " ++) . prettyPrintJS') value
97− ]
98− match (JSAssignment target value) = fmap concat $ sequence
99− [ prettyPrintJS' target
100− , return " = "
101− , prettyPrintJS' value
102− ]
103− match (JSWhile cond sts) = fmap concat $ sequence
104− [ return "while ("
105− , prettyPrintJS' cond
106− , return ") "
107− , prettyPrintJS' sts
108− ]
109− match (JSFor ident start end sts) = fmap concat $ sequence
110− [ return $ "for (" ++ ident ++ " = "
111− , prettyPrintJS' start
112− , return $ "; " ++ ident ++ " < "
113− , prettyPrintJS' end
114− , return $ "; " ++ ident ++ "++) "
115− , prettyPrintJS' sts
116− ]
117− match (JSIfElse cond thens elses) = fmap concat $ sequence
118− [ return "if ("
119− , prettyPrintJS' cond
120− , return ") "
121− , prettyPrintJS' thens
122− , maybe (return "") (fmap (" else " ++) . prettyPrintJS') elses
123− ]
124− match (JSReturn value) = fmap concat $ sequence
125− [ return "return "
126− , prettyPrintJS' value
127− ]
128− match (JSThrow value) = fmap concat $ sequence
129− [ return "throw "
130− , prettyPrintJS' value
131− ]
132− match (JSBreak lbl) = return $ "break " ++ lbl
133− match (JSContinue lbl) = return $ "continue " ++ lbl
134− match (JSLabel lbl js) = fmap concat $ sequence
135− [ return $ lbl ++ ": "
136− , prettyPrintJS' js
137− ]
138− match (JSRaw js) = return js
139− match _ = mzero
140−
141−conditional :: Pattern PrinterState JS ((JS, JS), JS)
142−conditional = mkPattern match
143− where
144− match (JSConditional cond th el) = Just ((th, el), cond)
145− match _ = Nothing
146−
147−accessor :: Pattern PrinterState JS (String, JS)
148−accessor = mkPattern match
149− where
150− match (JSAccessor prop val) = Just (prop, val)
151− match _ = Nothing
152−
153−indexer :: Pattern PrinterState JS (String, JS)
154−indexer = mkPattern' match
155− where
156− match (JSIndexer index val) = (,) <$> prettyPrintJS' index <*> pure val
157− match _ = mzero
158−
159−lam :: Pattern PrinterState JS ((Maybe String, [String]), JS)
160−lam = mkPattern match
161− where
162− match (JSFunction name args ret) = Just ((name, args), ret)
163− match _ = Nothing
164−
165−app :: Pattern PrinterState JS (String, JS)
166−app = mkPattern' match
167− where
168− match (JSApp val args) = do
169− jss <- mapM prettyPrintJS' args
170− return (intercalate ", " jss, val)
171− match _ = mzero
172−
173−typeOf :: Pattern PrinterState JS ((), JS)
174−typeOf = mkPattern match
175− where
176− match (JSTypeOf val) = Just ((), val)
177− match _ = Nothing
178−
179−unary :: UnaryOperator -> String -> Operator PrinterState JS String
180−unary op str = Wrap match (++)
181− where
182− match :: Pattern PrinterState JS (String, JS)
183− match = mkPattern match'
184− where
185− match' (JSUnary op' val) | op' == op = Just (str, val)
186− match' _ = Nothing
187−
188−binary :: BinaryOperator -> String -> Operator PrinterState JS String
189−binary op str = AssocR match (\v1 v2 -> v1 ++ " " ++ str ++ " " ++ v2)
190− where
191− match :: Pattern PrinterState JS (JS, JS)
192− match = mkPattern match'
193− where
194− match' (JSBinary op' v1 v2) | op' == op = Just (v1, v2)
195− match' _ = Nothing
196−
197−-- |
198−-- Generate a pretty-printed string representing a Javascript expression
199−--
200−prettyPrintJS1 :: JS -> String
201−prettyPrintJS1 = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) . prettyPrintJS'
202−
203−-- |
204−-- Generate a pretty-printed string representing a collection of Javascript expressions at the same indentation level
205−--
206−prettyPrintJS :: [JS] -> String
207−prettyPrintJS sts = fromMaybe (error "Incomplete pattern") . flip evalStateT (PrinterState 0) $ do
208− jss <- forM sts prettyPrintJS'
209− indentString <- currentIndent
210− return $ intercalate "\n" $ map (++ ";") $ map (indentString ++) jss
211−
212−-- |
213−-- Generate an indented, pretty-printed string representing a Javascript expression
214−--
215−prettyPrintJS' :: JS -> StateT PrinterState Maybe String
216−prettyPrintJS' = A.runKleisli $ runPattern matchValue
217− where
218− matchValue :: Pattern PrinterState JS String
219− matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
220− operators :: OperatorTable PrinterState JS String
221− operators =
222− OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "." ++ prop ]
223− , [ Wrap indexer $ \index val -> val ++ "[" ++ index ++ "]" ]
224− , [ Wrap app $ \args val -> val ++ "(" ++ args ++ ")" ]
225− , [ Wrap lam $ \(name, args) ret -> "function "
226− ++ maybe "" id name
227− ++ "(" ++ (intercalate ", " args) ++ ") "
228− ++ ret ]
229− , [ Wrap conditional $ \(th, el) cond -> cond ++ " ? " ++ prettyPrintJS1 th ++ " : " ++ prettyPrintJS1 el ]
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− ]
src/Language/PureScript/Pretty/Kinds.hsdeleted−60
@@ -1,60 +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−import Control.Monad.Unify
25−
26−import Language.PureScript.Kinds
27−import Language.PureScript.Pretty.Common
28−
29−typeLiterals :: Pattern () Kind String
30−typeLiterals = mkPattern match
31− where
32− match Star = Just "*"
33− match Bang = Just "!"
34− match (KUnknown (TypedUnknown (Unknown u))) = Just $ 'u' : show u
35− match _ = Nothing
36−
37−matchRow :: Pattern () Kind ((), Kind)
38−matchRow = mkPattern match
39− where
40− match (Row k) = Just ((), k)
41− match _ = Nothing
42−
43−funKind :: Pattern () Kind (Kind, Kind)
44−funKind = mkPattern match
45− where
46− match (FunKind arg ret) = Just (arg, ret)
47− match _ = Nothing
48−
49−-- |
50−-- Generate a pretty-printed string representing a Kind
51−--
52−prettyPrintKind :: Kind -> String
53−prettyPrintKind = fromMaybe (error "Incomplete pattern") . pattern matchKind ()
54− where
55− matchKind :: Pattern () Kind String
56− matchKind = buildPrettyPrinter operators (typeLiterals <+> fmap parens matchKind)
57− operators :: OperatorTable () Kind String
58− operators =
59− OperatorTable [ [ Wrap matchRow $ \_ k -> "# " ++ k]
60− , [ AssocR funKind $ \arg ret -> arg ++ " -> " ++ ret ] ]
src/Language/PureScript/Pretty/Types.hsdeleted−90
@@ -1,90 +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− prettyPrintRow
19−) where
20−
21−import Data.Maybe (fromMaybe)
22−import Data.List (intercalate)
23−
24−import Control.Arrow ((<+>))
25−import Control.PatternArrows
26−import Control.Monad.Unify
27−
28−import Language.PureScript.Types
29−import Language.PureScript.Pretty.Common
30−
31−typeLiterals :: Pattern () Type String
32−typeLiterals = mkPattern match
33− where
34− match (Object row) = Just $ "{ " ++ prettyPrintType row ++ " }"
35− match (TypeVar var) = Just var
36− match (TypeApp arr ty) | arr == tyArray = Just $ "[" ++ prettyPrintType ty ++ "]"
37− match (TypeConstructor ctor) = Just $ show ctor
38− match (TUnknown (TypedUnknown (Unknown u))) = Just $ 'u' : show u
39− match (Skolem s) = Just $ 's' : show s
40− match (ConstrainedType deps ty) = Just $ "(" ++ intercalate "," (map (\(pn, ty') -> show pn ++ " (" ++ prettyPrintType ty' ++ ")") deps) ++ ") => " ++ prettyPrintType ty
41− match (SaturatedTypeSynonym name args) = Just $ show name ++ "<" ++ intercalate "," (map prettyPrintType args) ++ ">"
42− match (ForAll ident ty) = Just $ "forall " ++ ident ++ ". " ++ prettyPrintType ty
43− match REmpty = Just $ prettyPrintRow REmpty
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 = name ++ " :: " ++ prettyPrintType ty
55− tailToPs :: Type -> String
56− tailToPs REmpty = ""
57− tailToPs (TUnknown (TypedUnknown (Unknown u))) = " | u" ++ show u
58− tailToPs (TypeVar var) = " | " ++ var
59− tailToPs (Skolem s) = " | s" ++ show s
60− tailToPs _ = error "Invalid row tail"
61− toList :: [(String, Type)] -> Type -> ([(String, Type)], Type)
62− toList tys (RCons name ty row) = toList ((name, ty):tys) row
63− toList tys r = (tys, r)
64−
65−typeApp :: Pattern () Type (Type, Type)
66−typeApp = mkPattern match
67− where
68− match (TypeApp f x) = Just (f, x)
69− match _ = Nothing
70−
71−singleArgumentFunction :: Pattern () Type (Type, Type)
72−singleArgumentFunction = mkPattern match
73− where
74− match (TypeApp (TypeApp t arg) ret) | t == tyFunction = Just (arg, ret)
75− match _ = Nothing
76−
77−-- |
78−-- Generate a pretty-printed string representing a Type
79−--
80−prettyPrintType :: Type -> String
81−prettyPrintType = fromMaybe (error "Incomplete pattern") . pattern matchType ()
82− where
83− matchType :: Pattern () Type String
84− matchType = buildPrettyPrinter operators (typeLiterals <+> fmap parens matchType)
85− operators :: OperatorTable () Type String
86− operators =
87− OperatorTable [ [ AssocL typeApp $ \f x -> f ++ " " ++ x ]
88− , [ AssocR singleArgumentFunction $ \arg ret -> arg ++ " -> " ++ ret
89− ]
90− ]
src/Language/PureScript/Pretty/Values.hsdeleted−173
@@ -1,173 +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−import Control.Arrow ((<+>))
24−import Control.PatternArrows
25−
26−import Language.PureScript.Types
27−import Language.PureScript.Values
28−import Language.PureScript.Pretty.Common
29−import Language.PureScript.Pretty.Types
30−
31−literals :: Pattern () Value String
32−literals = mkPattern match
33− where
34− match (NumericLiteral n) = Just $ either show show n
35− match (StringLiteral s) = Just $ show s
36− match (BooleanLiteral True) = Just "true"
37− match (BooleanLiteral False) = Just "false"
38− match (ArrayLiteral xs) = Just $ "[" ++ intercalate ", " (map prettyPrintValue xs) ++ "]"
39− match (ObjectLiteral ps) = Just $ "{" ++ intercalate ", " (map (uncurry prettyPrintObjectProperty) ps) ++ "}"
40− match (Constructor name) = Just $ show name
41− match (Block sts) = Just $ "do { " ++ intercalate " ; " (map prettyPrintStatement sts) ++ " }"
42− match (Case values binders) = Just $ "case " ++ intercalate " " (map prettyPrintValue values) ++
43− " of { " ++ intercalate " ; " (map prettyPrintCaseAlternative binders) ++ " }"
44− match (Var ident) = Just $ show ident
45− match (Do els) = Just $ " do { " ++ intercalate "; " (map prettyPrintDoNotationElement els) ++ " }"
46− match (TypeClassDictionary _ _) = error "Type class dictionary was not replaced"
47− match _ = Nothing
48−
49−prettyPrintCaseAlternative :: ([Binder], Maybe Guard, Value) -> String
50−prettyPrintCaseAlternative (binders, grd, val) = "(" ++ intercalate ", " (map prettyPrintBinder binders) ++ ") " ++
51− (maybe "" (("| " ++) . prettyPrintValue) grd) ++ " -> " ++ prettyPrintValue val
52−
53−ifThenElse :: Pattern () Value ((Value, Value), Value)
54−ifThenElse = mkPattern match
55− where
56− match (IfThenElse cond th el) = Just ((th, el), cond)
57− match _ = Nothing
58−
59−accessor :: Pattern () Value (String, Value)
60−accessor = mkPattern match
61− where
62− match (Accessor prop val) = Just (prop, val)
63− match _ = Nothing
64−
65−objectUpdate :: Pattern () Value ([String], Value)
66−objectUpdate = mkPattern match
67− where
68− match (ObjectUpdate o ps) = Just (flip map ps $ \(key, val) -> key ++ " = " ++ prettyPrintValue val, o)
69− match _ = Nothing
70−
71−app :: Pattern () Value (String, Value)
72−app = mkPattern match
73− where
74− match (App val arg) = Just (prettyPrintValue arg, val)
75− match _ = Nothing
76−
77−lam :: Pattern () Value (String, Value)
78−lam = mkPattern match
79− where
80− match (Abs arg val) = Just (show arg, val)
81− match _ = Nothing
82−
83−typed :: Pattern () Value (Type, Value)
84−typed = mkPattern match
85− where
86− match (TypedValue _ val ty) = Just (ty, val)
87− match _ = Nothing
88−
89−prettyPrintDoNotationElement :: DoNotationElement -> String
90−prettyPrintDoNotationElement (DoNotationValue val) = prettyPrintValue val
91−prettyPrintDoNotationElement (DoNotationBind binder val) = prettyPrintBinder binder ++ " <- " ++ prettyPrintValue val
92−prettyPrintDoNotationElement (DoNotationLet binder val) = "let " ++ prettyPrintBinder binder ++ " = " ++ prettyPrintValue val
93−
94−-- |
95−-- Generate a pretty-printed string representing a Value
96−--
97−prettyPrintValue :: Value -> String
98−prettyPrintValue = fromMaybe (error "Incomplete pattern") . pattern matchValue ()
99− where
100− matchValue :: Pattern () Value String
101− matchValue = buildPrettyPrinter operators (literals <+> fmap parens matchValue)
102− operators :: OperatorTable () Value String
103− operators =
104− OperatorTable [ [ Wrap accessor $ \prop val -> val ++ "." ++ prop ]
105− , [ Wrap objectUpdate $ \ps val -> val ++ "{ " ++ intercalate ", " ps ++ " }" ]
106− , [ Wrap app $ \arg val -> val ++ "(" ++ arg ++ ")" ]
107− , [ Split lam $ \arg val -> "\\" ++ arg ++ " -> " ++ prettyPrintValue val ]
108− , [ Wrap ifThenElse $ \(th, el) cond -> cond ++ " ? " ++ prettyPrintValue th ++ " : " ++ prettyPrintValue el ]
109− , [ Wrap typed $ \ty val -> val ++ " :: " ++ prettyPrintType ty ]
110− ]
111−
112−prettyPrintBinderAtom :: Pattern () Binder String
113−prettyPrintBinderAtom = mkPattern match
114− where
115− match :: Binder -> Maybe String
116− match NullBinder = Just "_"
117− match (StringBinder str) = Just $ show str
118− match (NumberBinder num) = Just $ either show show num
119− match (BooleanBinder True) = Just "true"
120− match (BooleanBinder False) = Just "false"
121− match (VarBinder ident) = Just $ show ident
122− match (NullaryBinder ctor) = Just $ show ctor
123− match (UnaryBinder ctor b) = Just $ show ctor ++ " " ++ prettyPrintBinder b
124− match (ObjectBinder bs) = Just $ "{ " ++ intercalate ", " (map (uncurry prettyPrintObjectPropertyBinder) bs) ++ " }"
125− match (ArrayBinder bs) = Just $ "[ " ++ intercalate ", " (map prettyPrintBinder bs) ++ " ]"
126− match (NamedBinder ident binder) = Just $ show ident ++ "@" ++ prettyPrintBinder binder
127− match _ = Nothing
128−
129−-- |
130−-- Generate a pretty-printed string representing a Binder
131−--
132−prettyPrintBinder :: Binder -> String
133−prettyPrintBinder = fromMaybe (error "Incomplete pattern") . pattern matchBinder ()
134− where
135− matchBinder :: Pattern () Binder String
136− matchBinder = buildPrettyPrinter operators (prettyPrintBinderAtom <+> fmap parens matchBinder)
137− operators :: OperatorTable () Binder String
138− operators =
139− OperatorTable [ [ AssocR matchConsBinder (\b1 b2 -> b1 ++ " : " ++ b2) ] ]
140−
141−matchConsBinder :: Pattern () Binder (Binder, Binder)
142−matchConsBinder = mkPattern match'
143− where
144− match' (ConsBinder b1 b2) = Just (b1, b2)
145− match' _ = Nothing
146−
147−prettyPrintObjectPropertyBinder :: String -> Binder -> String
148−prettyPrintObjectPropertyBinder key binder = key ++ ": " ++ prettyPrintBinder binder
149−
150−prettyPrintObjectProperty :: String -> Value -> String
151−prettyPrintObjectProperty key value = key ++ ": " ++ prettyPrintValue value
152−
153−prettyPrintStatement :: Statement -> String
154−prettyPrintStatement (VariableIntroduction ident value) = "var " ++ show ident ++ " = " ++ prettyPrintValue value
155−prettyPrintStatement (Assignment target value) = show target ++ " = " ++ prettyPrintValue value
156−prettyPrintStatement (While cond sts) = "while " ++ prettyPrintValue cond ++ ": {" ++ intercalate ";" (map prettyPrintStatement sts) ++ " }"
157−prettyPrintStatement (For ident start end sts) = "for " ++ show ident
158− ++ " <- " ++ prettyPrintValue start
159− ++ " until " ++ prettyPrintValue end ++ ": {"
160− ++ intercalate "; " (map prettyPrintStatement sts) ++ " }"
161−prettyPrintStatement (If ifst) = prettyPrintIfStatement ifst
162−prettyPrintStatement (Return value) = "return " ++ prettyPrintValue value
163−
164−prettyPrintIfStatement :: IfStatement -> String
165−prettyPrintIfStatement (IfStatement cond thens elst) =
166− "if "
167− ++ prettyPrintValue cond ++ ": {"
168− ++ intercalate "; " (map prettyPrintStatement thens) ++ " }"
169− ++ maybe "" prettyPrintElseStatement elst
170−
171−prettyPrintElseStatement :: ElseStatement -> String
172−prettyPrintElseStatement (Else sts) = "else: {" ++ intercalate "; " (map prettyPrintStatement sts) ++ " }"
173−prettyPrintElseStatement (ElseIf ifst) = "else " ++ prettyPrintIfStatement ifst
src/Language/PureScript/Scope.hsdeleted−63
@@ -1,63 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Scope
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−-- Utility functions for working with names in scope
13−--
14−-----------------------------------------------------------------------------
15−
16−module Language.PureScript.Scope (
17− usedNames,
18− unusedNames
19−) where
20−
21−import Data.Data
22−import Data.List ((\\), nub)
23−import Data.Generics (extQ, mkQ, everything)
24−
25−import Language.PureScript.Values
26−import Language.PureScript.Names
27−import Language.PureScript.CodeGen.JS.AST
28−
29−-- |
30−-- Gather all used names appearing inside a value
31−--
32−usedNames :: (Data d) => d -> [Ident]
33−usedNames val = nub $ everything (++) (mkQ [] namesV `extQ` namesS `extQ` namesB `extQ` namesJS) val
34− where
35− namesV :: Value -> [Ident]
36− namesV (Abs arg _) = [arg]
37− namesV (Var (Qualified Nothing name)) = [name]
38− namesV _ = []
39− namesS :: Statement -> [Ident]
40− namesS (VariableIntroduction name _) = [name]
41− namesS (For name _ _ _) = [name]
42− namesS _ = []
43− namesB :: Binder -> [Ident]
44− namesB (VarBinder name) = [name]
45− namesB _ = []
46− namesJS :: JS -> [Ident]
47− namesJS (JSVar name) = [Ident name]
48− namesJS (JSFunction (Just name) args _) = (Ident name) : (Ident `map` args)
49− namesJS (JSFunction Nothing args _) = (Ident `map` args)
50− namesJS (JSVariableIntroduction name _) = [Ident name]
51− namesJS (JSFor name _ _ _) = [Ident name]
52− namesJS _ = []
53−
54−-- |
55−-- Generate a set of names which are unused inside a value, of the form @_{n}@ for an integer @n@
56−--
57−unusedNames :: (Data d) => d -> [Ident]
58−unusedNames val =
59− let
60− allNames = usedNames val
61− varNames = map (Ident . ('_' :) . show) ([1..] :: [Int])
62− in
63− varNames \\ allNames
src/Language/PureScript/Sugar.hsdeleted−50
@@ -1,50 +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−
20−import Language.PureScript.Declarations
21−
22−import Language.PureScript.Sugar.Operators as S
23−import Language.PureScript.Sugar.DoNotation as S
24−import Language.PureScript.Sugar.CaseDeclarations as S
25−import Language.PureScript.Sugar.TypeDeclarations as S
26−import Language.PureScript.Sugar.BindingGroups as S
27−import Language.PureScript.Sugar.TypeClasses as S
28−
29−-- |
30−-- The desugaring pipeline proceeds as follows:
31−--
32−-- * Introduce type synonyms for type class dictionaries
33−--
34−-- * Rebracket user-defined binary operators
35−--
36−-- * Desugar do-notation using the @Prelude.Monad@ type class
37−--
38−-- * Desugar top-level case declarations into explicit case expressions
39−--
40−-- * Desugar type declarations into value declarations with explicit type annotations
41−--
42−-- * Group mutually recursive value and data declarations into binding groups.
43−--
44−desugar :: [Module] -> Either String [Module]
45−desugar = desugarTypeClasses
46− >=> rebracket
47− >=> desugarDo
48− >=> desugarCasesModule
49− >=> desugarTypeDeclarationsModule
50− >=> createBindingGroupsModule
src/Language/PureScript/Sugar/BindingGroups.hsdeleted−120
@@ -1,120 +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.Data
25−import Data.Graph
26−import Data.Generics
27−import Data.List (nub, intersect)
28−import Control.Applicative ((<$>))
29−
30−import Language.PureScript.Declarations
31−import Language.PureScript.Names
32−import Language.PureScript.Values
33−import Language.PureScript.Types
34−
35−-- |
36−-- Replace all sets of mutually-recursive declarations in a module with binding groups
37−--
38−createBindingGroupsModule :: [Module] -> Either String [Module]
39−createBindingGroupsModule = mapM $ \(Module name ds) -> Module name <$> createBindingGroups ds
40−
41−-- |
42−-- Collapse all binding groups in a module to individual declarations
43−--
44−collapseBindingGroupsModule :: [Module] -> [Module]
45−collapseBindingGroupsModule = map $ \(Module name ds) -> Module name (collapseBindingGroups ds)
46−
47−-- |
48−-- Replace all sets of mutually-recursive declarations with binding groups
49−--
50−createBindingGroups :: [Declaration] -> Either String [Declaration]
51−createBindingGroups ds = do
52− let values = filter isValueDecl ds
53− dataDecls = filter isDataDecl ds
54− allProperNames = map getProperName dataDecls
55− dataVerts = map (\d -> (d, getProperName d, usedProperNames d `intersect` allProperNames)) dataDecls
56− dataBindingGroupDecls <- mapM toDataBindingGroup $ stronglyConnComp dataVerts
57− let allIdents = map getIdent values
58− valueVerts = map (\d -> (d, getIdent d, usedIdents d `intersect` allIdents)) values
59− bindingGroupDecls = map toBindingGroup $ stronglyConnComp valueVerts
60− return $ filter isImportDecl ds ++
61− filter isExternDataDecl ds ++
62− dataBindingGroupDecls ++
63− filter isTypeClassDeclaration ds ++
64− filter isFixityDecl ds ++
65− filter isExternDecl ds ++
66− bindingGroupDecls
67−
68−-- |
69−-- Collapse all binding groups to individual declarations
70−--
71−collapseBindingGroups :: [Declaration] -> [Declaration]
72−collapseBindingGroups ds = concatMap go ds
73− where
74− go (DataBindingGroupDeclaration ds) = ds
75− go (BindingGroupDeclaration ds) = map (\(ident, val) -> ValueDeclaration ident [] Nothing val) ds
76− go other = [other]
77−
78−usedIdents :: (Data d) => d -> [Ident]
79−usedIdents = nub . everything (++) (mkQ [] names)
80− where
81− names :: Value -> [Ident]
82− names (Var (Qualified Nothing name)) = [name]
83− names _ = []
84−
85−usedProperNames :: (Data d) => d -> [ProperName]
86−usedProperNames = nub . everything (++) (mkQ [] names)
87− where
88− names :: Type -> [ProperName]
89− names (TypeConstructor (Qualified Nothing name)) = [name]
90− names _ = []
91−
92−getIdent :: Declaration -> Ident
93−getIdent (ValueDeclaration ident _ _ _) = ident
94−getIdent _ = error "Expected ValueDeclaration"
95−
96−getProperName :: Declaration -> ProperName
97−getProperName (DataDeclaration pn _ _) = pn
98−getProperName (TypeSynonymDeclaration pn _ _) = pn
99−getProperName _ = error "Expected DataDeclaration"
100−
101−toBindingGroup :: SCC Declaration -> Declaration
102−toBindingGroup (AcyclicSCC d) = d
103−toBindingGroup (CyclicSCC [d]) = d
104−toBindingGroup (CyclicSCC ds') = BindingGroupDeclaration $ map fromValueDecl ds'
105−
106−toDataBindingGroup :: SCC Declaration -> Either String Declaration
107−toDataBindingGroup (AcyclicSCC d) = return d
108−toDataBindingGroup (CyclicSCC [TypeSynonymDeclaration pn _ _]) = Left $ "Cycle in type synonym " ++ show pn
109−toDataBindingGroup (CyclicSCC [d]) = return d
110−toDataBindingGroup (CyclicSCC ds')
111− | all isTypeSynonym ds' = Left "Cycle in type synonyms"
112− | otherwise = return $ DataBindingGroupDeclaration ds'
113− where
114− isTypeSynonym (TypeSynonymDeclaration _ _ _) = True
115− isTypeSynonym _ = False
116−
117−fromValueDecl :: Declaration -> (Ident, Value)
118−fromValueDecl (ValueDeclaration ident [] Nothing val) = (ident, val)
119−fromValueDecl (ValueDeclaration _ _ _ _) = error "Binders should have been desugared"
120−fromValueDecl _ = error "Expected ValueDeclaration"
src/Language/PureScript/Sugar/CaseDeclarations.hsdeleted−70
@@ -1,70 +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.List (groupBy)
23−import Control.Applicative ((<$>))
24−import Control.Monad (forM, join, unless)
25−import Control.Monad.Error.Class
26−
27−import Language.PureScript.Names
28−import Language.PureScript.Values
29−import Language.PureScript.Declarations
30−import Language.PureScript.Scope
31−
32−-- |
33−-- Replace all top-level binders in a module with case expressions.
34−--
35−desugarCasesModule :: [Module] -> Either String [Module]
36−desugarCasesModule ms = forM ms $ \(Module name ds) -> Module name <$> desugarCases ds
37−-- |
38−-- Replace all top-level binders with case expressions.
39−--
40−desugarCases :: [Declaration] -> Either String [Declaration]
41−desugarCases = fmap join . mapM toDecls . groupBy inSameGroup
42−
43−inSameGroup :: Declaration -> Declaration -> Bool
44−inSameGroup (ValueDeclaration ident1 _ _ _) (ValueDeclaration ident2 _ _ _) = ident1 == ident2
45−inSameGroup _ _ = False
46−
47−toDecls :: [Declaration] -> Either String [Declaration]
48−toDecls d@[ValueDeclaration _ [] Nothing _] = return d
49−toDecls ds@(ValueDeclaration ident bs _ _ : _) = do
50− let tuples = map toTuple ds
51− unless (all ((== length bs) . length . fst) tuples) $
52− throwError $ "Argument list lengths differ in declaration " ++ show ident
53− return [makeCaseDeclaration ident tuples]
54−toDecls ds = return ds
55−
56−toTuple :: Declaration -> ([Binder], (Maybe Guard, Value))
57−toTuple (ValueDeclaration _ bs g val) = (bs, (g, val))
58−toTuple _ = error "Not a value declaration"
59−
60−makeCaseDeclaration :: Ident -> [([Binder], (Maybe Guard, Value))] -> Declaration
61−makeCaseDeclaration ident alternatives =
62− let
63− argPattern = length . fst . head $ alternatives
64− args = take argPattern $ unusedNames (ident, alternatives)
65− vars = map (\arg -> Var (Qualified Nothing arg)) args
66− binders = [ (bs, g, val) | (bs, (g, val)) <- alternatives ]
67− value = foldr (\args' ret -> Abs args' ret) (Case vars binders) args
68− in
69− ValueDeclaration ident [] Nothing value
70−
src/Language/PureScript/Sugar/DoNotation.hsdeleted−62
@@ -1,62 +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− desugarDo
19−) where
20−
21−import Data.Data
22−import Data.Generics
23−
24−import Language.PureScript.Values
25−import Language.PureScript.Names
26−import Language.PureScript.Scope
27−
28−-- |
29−-- Replace all @DoNotationBind@ and @DoNotationValue@ constructors with applications of the Prelude.(>>=) function,
30−-- and all @DoNotationLet@ constructors with let expressions.
31−--
32−desugarDo :: (Data d) => d -> Either String d
33−desugarDo = everywhereM (mkM replace)
34− where
35− prelude :: ModuleName
36− prelude = ModuleName (ProperName "Prelude")
37− ret :: Value
38− ret = Var (Qualified (Just prelude) (Ident "ret"))
39− bind :: Value
40− bind = Var (Qualified (Just prelude) (Op ">>="))
41− replace :: Value -> Either String Value
42− replace (Do els) = go els
43− replace other = return other
44− go :: [DoNotationElement] -> Either String Value
45− go [] = error "The impossible happened in desugarDo"
46− go [DoNotationValue val] = return val
47− go (DoNotationValue val : rest) = do
48− rest' <- go rest
49− return $ App (App bind val) (Abs (Ident "_") rest')
50− go [DoNotationBind _ _] = Left "Bind statement cannot be the last statement in a do block"
51− go (DoNotationBind NullBinder val : rest) = go (DoNotationValue val : rest)
52− go (DoNotationBind (VarBinder ident) val : rest) = do
53− rest' <- go rest
54− return $ App (App bind val) (Abs ident rest')
55− go (DoNotationBind binder val : rest) = do
56− rest' <- go rest
57− let ident = head $ unusedNames rest'
58− return $ App (App bind val) (Abs ident (Case [Var (Qualified Nothing ident)] [([binder], Nothing, rest')]))
59− go [DoNotationLet _ _] = Left "Let statement cannot be the last statement in a do block"
60− go (DoNotationLet binder val : rest) = do
61− rest' <- go rest
62− return $ Case [val] [([binder], Nothing, rest')]
src/Language/PureScript/Sugar/Operators.hsdeleted−113
@@ -1,113 +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 #-}
21−
22−module Language.PureScript.Sugar.Operators (
23− rebracket
24−) where
25−
26−import Language.PureScript.Names
27−import Language.PureScript.Declarations
28−import Language.PureScript.Values
29−
30−import Data.Function (on)
31−import Data.List (groupBy, sortBy)
32−import qualified Data.Map as M
33−import qualified Data.Generics as G
34−import qualified Data.Generics.Extras as G
35−import Control.Monad.State
36−import Control.Applicative
37−import qualified Text.Parsec as P
38−import qualified Text.Parsec.Pos as P
39−import qualified Text.Parsec.Expr as P
40−
41−-- |
42−-- Remove explicit parentheses and reorder binary operator applications
43−--
44−rebracket :: [Module] -> Either String [Module]
45−rebracket = go M.empty []
46− where
47− go _ rb [] = return . reverse $ rb
48− go m rb (Module name ds : ms) = do
49− m' <- M.union m <$> collectFixities m (ModuleName name) ds
50− let opTable = customOperatorTable m'
51− ds' <- G.everywhereM' (G.mkM (matchOperators (ModuleName name) opTable)) ds
52− go m' (Module name (G.everywhere (G.mkT removeParens) ds') : rb) ms
53−
54−removeParens :: Value -> Value
55−removeParens (Parens val) = val
56−removeParens val = val
57−
58−customOperatorTable :: M.Map (Qualified Ident) Fixity -> [[(Qualified Ident, Value -> Value -> Value, Associativity)]]
59−customOperatorTable fixities =
60− let
61− applyUserOp name t1 t2 = App (App (Var name) t1) t2
62− userOps = map (\(name, Fixity a p) -> (name, applyUserOp name, p, a)) . M.toList $ fixities
63− sorted = sortBy (compare `on` (\(_, _, p, _) -> p)) userOps
64− groups = groupBy ((==) `on` (\(_, _, p, _) -> p)) sorted
65− in
66− map (map (\(name, f, _, a) -> (name, f, a))) groups
67−
68−type Chain = [Either Value (Qualified Ident)]
69−
70−matchOperators :: ModuleName -> [[(Qualified Ident, Value -> Value -> Value, Associativity)]] -> Value -> Either String Value
71−matchOperators moduleName ops val = G.everywhereM' (G.mkM parseChains) val
72− where
73− parseChains :: Value -> Either String Value
74− parseChains b@(BinaryNoParens _ _ _) = bracketChain (extendChain b)
75− parseChains other = return other
76− extendChain :: Value -> Chain
77− extendChain (BinaryNoParens name l r) = Left l : Right name : extendChain r
78− extendChain other = [Left other]
79− bracketChain :: Chain -> Either String Value
80− bracketChain = either (Left . show) Right . P.parse (P.buildExpressionParser opTable parseValue <* P.eof) "operator expression"
81− opTable = map (map (\(name, f, a) -> P.Infix (P.try (matchOp moduleName name) >> return f) (toAssoc a))) ops
82− ++ [[P.Infix (P.try (parseOp >>= \ident -> return (\t1 t2 -> App (App (Var ident) t1) t2))) P.AssocLeft]]
83−
84−toAssoc :: Associativity -> P.Assoc
85−toAssoc Infixl = P.AssocLeft
86−toAssoc Infixr = P.AssocRight
87−
88−parseValue :: P.Parsec Chain () Value
89−parseValue = P.token show (const (P.initialPos "")) (either Just (const Nothing)) P.<?> "expression"
90−
91−parseOp :: P.Parsec Chain () (Qualified Ident)
92−parseOp = P.token show (const (P.initialPos "")) (either (const Nothing) Just) P.<?> "operator"
93−
94−matchOp :: ModuleName -> Qualified Ident -> P.Parsec Chain () ()
95−matchOp moduleName op = do
96− ident <- parseOp
97− guard (qualify moduleName ident == qualify moduleName op)
98−
99−collectFixities :: M.Map (Qualified Ident) Fixity -> ModuleName -> [Declaration] -> Either String (M.Map (Qualified Ident) Fixity)
100−collectFixities m _ [] = return m
101−collectFixities m moduleName (FixityDeclaration fixity name : rest) = do
102− let qual = Qualified (Just moduleName) (Op name)
103− when (qual `M.member` m) (Left $ "redefined fixity for " ++ show name)
104− collectFixities (M.insert qual fixity m) moduleName rest
105−collectFixities m moduleName (ImportDeclaration importedModule _ : rest) = do
106− let fs = [ (i, fixity) | (Qualified mn i, fixity) <- M.toList m, mn == Just importedModule ]
107− let m' = M.fromList (map (\(i, fixity) -> (Qualified (Just moduleName) i, fixity)) fs)
108− collectFixities (M.union m' m) moduleName rest
109−collectFixities m moduleName (_:ds) = collectFixities m moduleName ds
110−
111−globalOp :: String -> Qualified Ident
112−globalOp = Qualified Nothing . Op
113−
src/Language/PureScript/Sugar/TypeClasses.hsdeleted−150
@@ -1,150 +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− mkDictionaryValueName,
20− mkDictionaryEntryName
21−) where
22−
23−import Language.PureScript.Declarations
24−import Language.PureScript.Names
25−import Language.PureScript.Types
26−import Language.PureScript.Values
27−import Language.PureScript.CodeGen.JS.AST
28−import Language.PureScript.Sugar.CaseDeclarations
29−
30−import qualified Data.Map as M
31−
32−import Control.Applicative
33−import Control.Monad.State
34−import Data.Maybe (fromMaybe)
35−import Data.List (nub)
36−import Data.Generics (mkQ, everything)
37−import Language.PureScript.CodeGen.Common (identToJs)
38−
39−type MemberMap = M.Map (ModuleName, ProperName) (String, [(String, Type)])
40−
41−type Desugar = StateT MemberMap (Either String)
42−
43−-- |
44−-- Add type synonym declarations for type class dictionary types, and value declarations for type class
45−-- instance dictionary expressions.
46−--
47−desugarTypeClasses :: [Module] -> Either String [Module]
48−desugarTypeClasses = flip evalStateT M.empty . mapM desugarModule
49−
50−desugarModule :: Module -> Desugar Module
51−desugarModule (Module name decls) = Module name <$> concat <$> mapM (desugarDecl (ModuleName name)) decls
52−
53−desugarDecl :: ModuleName -> Declaration -> Desugar [Declaration]
54−desugarDecl mn d@(TypeClassDeclaration name arg members) = do
55− let tys = map memberToNameAndType members
56− modify (M.insert (mn, name) (arg, tys))
57− return $ d : typeClassDictionaryDeclaration name arg members : map (typeClassMemberToDictionaryAccessor name arg) members
58−desugarDecl mn d@(TypeInstanceDeclaration deps name ty members) = do
59− desugared <- lift $ desugarCases members
60− entries <- mapM (typeInstanceDictionaryEntryDeclaration mn deps name ty) desugared
61− dictDecl <- typeInstanceDictionaryDeclaration mn deps name ty desugared
62− return $ d : entries ++ [dictDecl]
63−desugarDecl _ other = return [other]
64−
65−memberToNameAndType :: Declaration -> (String, Type)
66−memberToNameAndType (TypeDeclaration ident ty) = (identToJs ident, ty)
67−memberToNameAndType _ = error "Invalid declaration in type class definition"
68−
69−typeClassDictionaryDeclaration :: ProperName -> String -> [Declaration] -> Declaration
70−typeClassDictionaryDeclaration name arg members =
71− TypeSynonymDeclaration name [arg] (Object $ rowFromList (map memberToNameAndType members, REmpty))
72−
73−typeClassMemberToDictionaryAccessor :: ProperName -> String -> Declaration -> Declaration
74−typeClassMemberToDictionaryAccessor name arg (TypeDeclaration ident ty) =
75− ExternDeclaration TypeClassAccessorImport ident
76− (Just (JSFunction (Just $ identToJs ident) ["dict"] (JSBlock [JSReturn (JSAccessor (identToJs ident) (JSVar "dict"))])))
77− (ForAll arg (ConstrainedType [(Qualified Nothing name, TypeVar arg)] ty))
78−typeClassMemberToDictionaryAccessor _ _ _ = error "Invalid declaration in type class definition"
79−
80−typeInstanceDictionaryDeclaration :: ModuleName -> [(Qualified ProperName, Type)] -> Qualified ProperName -> Type -> [Declaration] -> Desugar Declaration
81−typeInstanceDictionaryDeclaration mn deps name ty decls = do
82− m <- get
83− (arg, instanceTys) <- lift $ maybe (Left $ "Type class " ++ show name ++ " is undefined. Type class names must be qualified.") Right
84− $ M.lookup (qualify mn name) m
85− let memberTypes = map (replaceTypeVars arg ty) instanceTys
86− entryName <- lift $ mkDictionaryValueName mn name ty
87− memberNames <- mapM (memberToNameAndValue memberTypes) decls
88− return $ ValueDeclaration entryName [] Nothing
89− (TypedValue True
90− (foldr Abs (ObjectLiteral memberNames) (map (\n -> Ident ('_' : show n)) [1..length deps]))
91− (quantify (foldr function (TypeApp (TypeConstructor name) ty) (map (\(pn, ty') -> TypeApp (TypeConstructor pn) ty') deps)))
92− )
93− where
94− memberToNameAndValue :: [(String, Type)] -> Declaration -> Desugar (String, Value)
95− memberToNameAndValue tys (ValueDeclaration ident _ _ _) = do
96− memberType <- lift . maybe (Left "Type class member type not found") Right $ lookup (identToJs ident) tys
97− memberName <- mkDictionaryEntryName mn name ty ident
98− return (identToJs ident, TypedValue False
99− (if null deps then Var (Qualified Nothing memberName)
100− else foldl App (Var (Qualified Nothing memberName)) (map (\n -> Var (Qualified Nothing (Ident ('_' : show n)))) [1..length deps]))
101− (quantify memberType))
102− memberToNameAndValue _ _ = error "Invalid declaration in type instance definition"
103−
104−typeInstanceDictionaryEntryDeclaration :: ModuleName -> [(Qualified ProperName, Type)] -> Qualified ProperName -> Type -> Declaration -> Desugar Declaration
105−typeInstanceDictionaryEntryDeclaration mn deps name ty (ValueDeclaration ident [] _ val) = do
106− m <- get
107− valTy <- lift $ do (arg, members) <- lookupTypeClass m
108− ty' <- lookupIdent members
109− return $ replaceTypeVars arg ty ty'
110− entryName <- mkDictionaryEntryName mn name ty ident
111− return $ ValueDeclaration entryName [] Nothing
112− (TypedValue True val (quantify (if null deps then valTy else ConstrainedType deps valTy)))
113− where
114− lookupTypeClass m = maybe (Left $ "Type class " ++ show name ++ " is undefined. Type class names must be qualified.") Right $ M.lookup (qualify mn name) m
115− lookupIdent members = maybe (Left $ "Type class " ++ show name ++ " does not have method " ++ show ident) Right $ lookup (identToJs ident) members
116−typeInstanceDictionaryEntryDeclaration _ _ _ _ _ = error "Invalid declaration in type instance definition"
117−
118−qualifiedToString :: ModuleName -> Qualified ProperName -> String
119−qualifiedToString mn (Qualified Nothing pn) = qualifiedToString mn (Qualified (Just mn) pn)
120−qualifiedToString _ (Qualified (Just (ModuleName mn)) pn) = runProperName mn ++ "_" ++ runProperName pn
121−
122−quantify :: Type -> Type
123−quantify ty' = foldr ForAll ty' tyVars
124− where
125− tyVars = nub $ everything (++) (mkQ [] collect) ty'
126− collect (TypeVar v) = [v]
127− collect _ = []
128−
129−-- |
130−-- Generate a name for a type class dictionary, based on the module name, class name and type name
131−--
132−mkDictionaryValueName :: ModuleName -> Qualified ProperName -> Type -> Either String Ident
133−mkDictionaryValueName mn cl ty = do
134− tyStr <- typeToString mn ty
135− return $ Ident $ "__" ++ qualifiedToString mn cl ++ "_" ++ tyStr
136−
137−typeToString :: ModuleName -> Type -> Either String String
138−typeToString _ (TypeVar _) = return "var"
139−typeToString mn (TypeConstructor ty') = return $ qualifiedToString mn ty'
140−typeToString mn (TypeApp ty' (TypeVar _)) = typeToString mn ty'
141−typeToString _ _ = Left "Type class instance must be of the form T a1 ... an"
142−
143−-- |
144−-- Generate a name for a type class dictionary member, based on the module name, class name, type name and
145−-- member name
146−--
147−mkDictionaryEntryName :: ModuleName -> Qualified ProperName -> Type -> Ident -> Desugar Ident
148−mkDictionaryEntryName mn name ty ident = do
149− Ident dictName <- lift $ mkDictionaryValueName mn name ty
150− return $ Escaped $ dictName ++ "_" ++ identToJs ident
src/Language/PureScript/Sugar/TypeDeclarations.hsdeleted−43
@@ -1,43 +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 Control.Applicative
23−import Control.Monad.Error.Class
24−import Control.Monad (forM)
25−
26−import Language.PureScript.Declarations
27−import Language.PureScript.Values
28−
29−-- |
30−-- Replace all top level type declarations in a module with type annotations
31−--
32−desugarTypeDeclarationsModule :: [Module] -> Either String [Module]
33−desugarTypeDeclarationsModule ms = forM ms $ \(Module name ds) -> Module name <$> desugarTypeDeclarations ds
34−
35−-- |
36−-- Replace all top level type declarations with type annotations
37−--
38−desugarTypeDeclarations :: [Declaration] -> Either String [Declaration]
39−desugarTypeDeclarations (TypeDeclaration name ty : ValueDeclaration name' [] Nothing val : rest) | name == name' =
40− desugarTypeDeclarations (ValueDeclaration name [] Nothing (TypedValue True val ty) : rest)
41−desugarTypeDeclarations (TypeDeclaration name _ : _) = throwError $ "Orphan type declaration for " ++ show name
42−desugarTypeDeclarations (d:ds) = (:) d <$> desugarTypeDeclarations ds
43−desugarTypeDeclarations [] = return []
src/Language/PureScript/TypeChecker.hsdeleted−247
@@ -1,247 +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 qualified Data.Map as M
30−import Control.Monad.State
31−import Control.Monad.Error
32−import Data.Either (rights, lefts)
33−
34−import Language.PureScript.Types
35−import Language.PureScript.Names
36−import Language.PureScript.Values
37−import Language.PureScript.Kinds
38−import Language.PureScript.Declarations
39−import Language.PureScript.Sugar.TypeClasses
40−
41−addDataType :: ModuleName -> ProperName -> [String] -> [(ProperName, Maybe Type)] -> Kind -> Check ()
42−addDataType moduleName name args dctors ctorKind = do
43− env <- getEnv
44− putEnv $ env { types = M.insert (moduleName, name) (ctorKind, Data) (types env) }
45− forM_ dctors $ \(dctor, maybeTy) ->
46− rethrow (("Error in data constructor " ++ show name ++ ":\n") ++) $
47− addDataConstructor moduleName name args dctor maybeTy
48−
49−addDataConstructor :: ModuleName -> ProperName -> [String] -> ProperName -> Maybe Type -> Check ()
50−addDataConstructor moduleName name args dctor maybeTy = do
51− env <- getEnv
52− dataConstructorIsNotDefined moduleName dctor
53− let retTy = foldl TypeApp (TypeConstructor (Qualified (Just moduleName) name)) (map TypeVar args)
54− let dctorTy = maybe retTy (flip function retTy) maybeTy
55− let polyType = mkForAll args dctorTy
56− putEnv $ env { dataConstructors = M.insert (moduleName, dctor) (qualifyAllUnqualifiedNames moduleName env polyType, DataConstructor) (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 (moduleName, name) (kind, TypeSynonym) (types env)
62− , typeSynonyms = M.insert (moduleName, name) (args, qualifyAllUnqualifiedNames moduleName env ty) (typeSynonyms env) }
63−
64−typeIsNotDefined :: ModuleName -> ProperName -> Check ()
65−typeIsNotDefined moduleName name = do
66− env <- getEnv
67− guardWith (show name ++ " is already defined") $
68− not $ M.member (moduleName, name) (types env)
69−
70−dataConstructorIsNotDefined :: ModuleName -> ProperName -> Check ()
71−dataConstructorIsNotDefined moduleName dctor = do
72− env <- getEnv
73− guardWith (show dctor ++ " is already defined") $
74− not $ M.member (moduleName, dctor) (dataConstructors env)
75−
76−valueIsNotDefined :: ModuleName -> Ident -> Check ()
77−valueIsNotDefined moduleName name = do
78− env <- getEnv
79− case M.lookup (moduleName, name) (names env) of
80− Just _ -> throwError $ show name ++ " is already defined"
81− Nothing -> return ()
82−
83−addValue :: ModuleName -> Ident -> Type -> Check ()
84−addValue moduleName name ty = do
85− env <- getEnv
86− putEnv (env { names = M.insert (moduleName, name) (qualifyAllUnqualifiedNames moduleName env ty, Value) (names env) })
87−
88−addTypeClassDictionaries :: [TypeClassDictionaryInScope] -> Check ()
89−addTypeClassDictionaries entries = do
90− modify $ \st -> st { checkEnv = (checkEnv st) { typeClassDictionaries = entries ++ (typeClassDictionaries . checkEnv $ st) } }
91−
92−-- |
93−-- Type check all declarations in a module
94−--
95−-- At this point, many declarations will have been desugared, but it is still necessary to
96−--
97−-- * Kind-check all types and add them to the @Environment@
98−--
99−-- * Type-check all values and add them to the @Environment@
100−--
101−-- * Bring type class instances into scope
102−--
103−-- * Process module imports
104−--
105−typeCheckAll :: ModuleName -> [Declaration] -> Check [Declaration]
106−typeCheckAll _ [] = return []
107−typeCheckAll moduleName (d@(DataDeclaration name args dctors) : rest) = do
108− rethrow (("Error in type constructor " ++ show name ++ ":\n") ++) $ do
109− typeIsNotDefined moduleName name
110− ctorKind <- kindsOf moduleName name args (mapMaybe snd dctors)
111− addDataType moduleName name args dctors ctorKind
112− ds <- typeCheckAll moduleName rest
113− return $ d : ds
114−typeCheckAll moduleName (d@(DataBindingGroupDeclaration tys) : rest) = do
115− rethrow ("Error in data binding group:\n" ++) $ do
116− let syns = mapMaybe toTypeSynonym tys
117− let dataDecls = mapMaybe toDataDecl tys
118− (syn_ks, data_ks) <- kindsOfAll moduleName syns (map (\(name, args, dctors) -> (name, args, mapMaybe snd dctors)) dataDecls)
119− forM_ (zip dataDecls data_ks) $ \((name, args, dctors), ctorKind) -> do
120− typeIsNotDefined moduleName name
121− addDataType moduleName name args dctors ctorKind
122− forM_ (zip syns syn_ks) $ \((name, args, ty), kind) -> do
123− typeIsNotDefined moduleName name
124− addTypeSynonym moduleName name args ty kind
125− ds <- typeCheckAll moduleName rest
126− return $ d : ds
127− where
128− toTypeSynonym (TypeSynonymDeclaration nm args ty) = Just (nm, args, ty)
129− toTypeSynonym _ = Nothing
130− toDataDecl (DataDeclaration nm args dctors) = Just (nm, args, dctors)
131− toDataDecl _ = Nothing
132−typeCheckAll moduleName (d@(TypeSynonymDeclaration name args ty) : rest) = do
133− rethrow (("Error in type synonym " ++ show name ++ ":\n") ++) $ do
134− typeIsNotDefined moduleName name
135− kind <- kindsOf moduleName name args [ty]
136− addTypeSynonym moduleName name args ty kind
137− ds <- typeCheckAll moduleName rest
138− return $ d : ds
139−typeCheckAll _ (TypeDeclaration _ _ : _) = error "Type declarations should have been removed"
140−typeCheckAll moduleName (ValueDeclaration name [] Nothing val : rest) = do
141− d <- rethrow (("Error in declaration " ++ show name ++ ":\n") ++) $ do
142− valueIsNotDefined moduleName name
143− [(_, (val', ty))] <- typesOf moduleName [(name, val)]
144− addValue moduleName name ty
145− return $ ValueDeclaration name [] Nothing val'
146− ds <- typeCheckAll moduleName rest
147− return $ d : ds
148−typeCheckAll _ (ValueDeclaration _ _ _ _ : _) = error "Binders were not desugared"
149−typeCheckAll moduleName (BindingGroupDeclaration vals : rest) = do
150− d <- rethrow (("Error in binding group " ++ show (map fst vals) ++ ":\n") ++) $ do
151− forM_ (map fst vals) $ \name ->
152− valueIsNotDefined moduleName name
153− tys <- typesOf moduleName vals
154− vals' <- forM (zip (map fst vals) (map snd tys)) $ \(name, (val, ty)) -> do
155− addValue moduleName name ty
156− return (name, val)
157− return $ BindingGroupDeclaration vals'
158− ds <- typeCheckAll moduleName rest
159− return $ d : ds
160−typeCheckAll moduleName (d@(ExternDataDeclaration name kind) : rest) = do
161− env <- getEnv
162− guardWith (show name ++ " is already defined") $ not $ M.member (moduleName, name) (types env)
163− putEnv $ env { types = M.insert (moduleName, name) (kind, TypeSynonym) (types env) }
164− ds <- typeCheckAll moduleName rest
165− return $ d : ds
166−typeCheckAll moduleName (d@(ExternDeclaration importTy name _ ty) : rest) = do
167− rethrow (("Error in foreign import declaration " ++ show name ++ ":\n") ++) $ do
168− env <- getEnv
169− kind <- kindOf moduleName ty
170− guardWith "Expected kind *" $ kind == Star
171− case M.lookup (moduleName, name) (names env) of
172− Just _ -> throwError $ show name ++ " is already defined"
173− Nothing -> putEnv (env { names = M.insert (moduleName, name) (qualifyAllUnqualifiedNames moduleName env ty, Extern importTy) (names env) })
174− ds <- typeCheckAll moduleName rest
175− return $ d : ds
176−typeCheckAll moduleName (d@(FixityDeclaration _ name) : rest) = do
177− ds <- typeCheckAll moduleName rest
178− env <- getEnv
179− guardWith ("Fixity declaration with no binding: " ++ name) $ M.member (moduleName, Op name) $ names env
180− return $ d : ds
181−typeCheckAll currentModule (d@(ImportDeclaration moduleName idents) : rest) = do
182− env <- getEnv
183− rethrow errorMessage $ do
184− guardWith ("Module " ++ show moduleName ++ " does not exist") $ moduleExists env
185− case idents of
186− Nothing -> do
187− shadowIdents (map snd $ filterModule (names env)) env
188− shadowTypes (map snd $ filterModule (types env)) env
189− Just idents' -> do
190− shadowIdents (lefts idents') env
191− shadowTypes (rights idents') env
192− shadowTypeClassInstances env
193− ds <- typeCheckAll currentModule rest
194− return $ d : ds
195− where
196− errorMessage = (("Error in import declaration " ++ show moduleName ++ ":\n") ++)
197− filterModule = filter ((== moduleName) . fst) . M.keys
198− moduleExists env = not (null (filterModule (names env))) || not (null (filterModule (types env)))
199− shadowIdents idents' env =
200− forM_ idents' $ \ident -> do
201− case (moduleName, ident) `M.lookup` names env of
202− Just (_, Alias _ _) -> return ()
203− Just (pt, _) -> do
204− guardWith (show currentModule ++ "." ++ show ident ++ " is already defined") $ (currentModule, ident) `M.notMember` names env
205− modifyEnv (\e -> e { names = M.insert (currentModule, ident) (pt, Alias moduleName ident) (names e) })
206− Nothing -> throwError (show moduleName ++ "." ++ show ident ++ " is undefined")
207− shadowTypes pns env =
208− forM_ pns $ \pn -> do
209− case (moduleName, pn) `M.lookup` types env of
210− Nothing -> throwError (show moduleName ++ "." ++ show pn ++ " is undefined")
211− Just (_, DataAlias _ _) -> return ()
212− Just (k, _) -> do
213− guardWith (show currentModule ++ "." ++ show pn ++ " is already defined") $ (currentModule, pn) `M.notMember` types env
214− modifyEnv (\e -> e { types = M.insert (currentModule, pn) (k, DataAlias moduleName pn) (types e) })
215− let keys = map (snd . fst) . filter (\(_, (fn, _)) -> fn `constructs` pn) . M.toList . dataConstructors $ env
216− forM_ keys $ \dctor -> do
217− case (moduleName, dctor) `M.lookup` dataConstructors env of
218− Just (_, Alias _ _) -> return ()
219− Just (ctorTy, _) -> do
220− guardWith (show currentModule ++ "." ++ show dctor ++ " is already defined") $ (currentModule, dctor) `M.notMember` dataConstructors env
221− modifyEnv (\e -> e { dataConstructors = M.insert (currentModule, dctor) (ctorTy, Alias moduleName (Ident (runProperName dctor))) (dataConstructors e) })
222− Nothing -> throwError (show moduleName ++ "." ++ show dctor ++ " is undefined")
223− shadowTypeClassInstances env = do
224− let instances = filter (\tcd ->
225− let Qualified (Just mn) _ = tcdName tcd in
226− moduleName == mn && tcdType tcd == TCDRegular
227− ) (typeClassDictionaries env)
228− forM_ instances $ \tcd -> do
229− let (Qualified _ ident) = tcdName tcd
230− addTypeClassDictionaries [tcd { tcdName = (Qualified (Just currentModule) ident), tcdType = TCDAlias (tcdName tcd) }]
231− constructs (TypeConstructor (Qualified (Just mn) pn')) pn
232− = mn == moduleName && pn' == pn
233− constructs (ForAll _ ty) pn = ty `constructs` pn
234− constructs (TypeApp (TypeApp t _) ty) pn | t == tyFunction = ty `constructs` pn
235− constructs (TypeApp ty _) pn = ty `constructs` pn
236− constructs fn _ = error $ "Invalid arguments to constructs: " ++ show fn
237−typeCheckAll moduleName (d@(TypeClassDeclaration _ _ _) : rest) = do
238− env <- getEnv
239− ds <- typeCheckAll moduleName rest
240− return $ qualifyAllUnqualifiedNames moduleName env d : ds
241−typeCheckAll moduleName (d@(TypeInstanceDeclaration deps className ty _) : rest) = do
242− env <- getEnv
243− dictName <- Check . lift $ mkDictionaryValueName moduleName className ty
244− addTypeClassDictionaries (qualifyAllUnqualifiedNames moduleName env
245− [TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) className ty (Just deps) TCDRegular])
246− ds <- typeCheckAll moduleName rest
247− return $ qualifyAllUnqualifiedNames moduleName env d : ds
src/Language/PureScript/TypeChecker/Kinds.hsdeleted−156
@@ -1,156 +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 DeriveDataTypeable #-}
18−{-# LANGUAGE MultiParamTypeClasses #-}
19−
20−module Language.PureScript.TypeChecker.Kinds (
21− kindOf,
22− kindsOf,
23− kindsOfAll
24−) where
25−
26−import Language.PureScript.Types
27−import Language.PureScript.Kinds
28−import Language.PureScript.Names
29−import Language.PureScript.TypeChecker.Monad
30−import Language.PureScript.Pretty
31−
32−import Control.Monad.State
33−import Control.Monad.Error
34−import Control.Monad.Reader
35−import Control.Monad.Unify
36−
37−import Control.Applicative
38−
39−import qualified Data.Map as M
40−
41−instance Unifiable Check Kind where
42− unknown = KUnknown
43− isUnknown (KUnknown u) = Just u
44− isUnknown _ = Nothing
45− KUnknown u1 ?= KUnknown u2 | u1 == u2 = return ()
46− KUnknown u ?= k = replace u k
47− k ?= KUnknown u = replace u k
48− Star ?= Star = return ()
49− Bang ?= Bang = return ()
50− Row k1 ?= Row k2 = k1 ?= k2
51− FunKind k1 k2 ?= FunKind k3 k4 = do
52− k1 ?= k3
53− k2 ?= k4
54− k1 ?= k2 = UnifyT . lift . throwError $ "Cannot unify " ++ prettyPrintKind k1 ++ " with " ++ prettyPrintKind k2 ++ "."
55−
56−-- |
57−-- Infer the kind of a single type
58−--
59−kindOf :: ModuleName -> Type -> Check Kind
60−kindOf moduleName ty = liftUnify $ starIfUnknown <$> infer ty
61−
62−-- |
63−-- Infer the kind of a type constructor with a collection of arguments and a collection of associated data constructors
64−--
65−kindsOf :: ModuleName -> ProperName -> [String] -> [Type] -> Check Kind
66−kindsOf moduleName name args ts = fmap starIfUnknown . liftUnify $ do
67− tyCon <- fresh
68− kargs <- replicateM (length args) fresh
69− let dict = (name, tyCon) : zip (map ProperName args) kargs
70− bindLocalTypeVariables moduleName dict $
71− solveTypes ts kargs tyCon
72−
73−-- |
74−-- Simultaneously infer the kinds of several mutually recursive type constructors
75−--
76−kindsOfAll :: ModuleName -> [(ProperName, [String], Type)] -> [(ProperName, [String], [Type])] -> Check ([Kind], [Kind])
77−kindsOfAll moduleName syns tys = fmap tidyUp . liftUnify $ do
78− synVars <- replicateM (length syns) fresh
79− let dict = zipWith (\(name, _, _) var -> (name, var)) syns synVars
80− bindLocalTypeVariables moduleName dict $ do
81− tyCons <- replicateM (length tys) fresh
82− let dict = zipWith (\(name, _, _) tyCon -> (name, tyCon)) tys tyCons
83− bindLocalTypeVariables moduleName dict $ do
84− data_ks <- zipWithM (\tyCon (_, args, ts) -> do
85− kargs <- replicateM (length args) fresh
86− let argDict = zip (map ProperName args) kargs
87− bindLocalTypeVariables moduleName argDict $
88− solveTypes ts kargs tyCon) tyCons tys
89− syn_ks <- zipWithM (\synVar (_, args, ty) -> do
90− kargs <- replicateM (length args) fresh
91− let argDict = zip (map ProperName args) kargs
92− bindLocalTypeVariables moduleName argDict $
93− solveTypes [ty] kargs synVar) synVars syns
94− return (syn_ks, data_ks)
95− where
96− tidyUp (ks1, ks2) = (map starIfUnknown ks1, map starIfUnknown ks2)
97−
98−-- |
99−-- Solve the set of kind constraints associated with the data constructors for a type constructor
100−--
101−solveTypes :: [Type] -> [Kind] -> Kind -> UnifyT Check Kind
102−solveTypes ts kargs tyCon = do
103− ks <- mapM infer ts
104− tyCon ?= foldr FunKind Star kargs
105− forM_ ks $ \k -> k ?= Star
106− return tyCon
107−
108−-- |
109−-- Default all unknown kinds to the Star kind of types
110−--
111−starIfUnknown :: Kind -> Kind
112−starIfUnknown (KUnknown _) = Star
113−starIfUnknown (FunKind k1 k2) = FunKind (starIfUnknown k1) (starIfUnknown k2)
114−starIfUnknown k = k
115−
116−-- |
117−-- Infer a kind for a type
118−--
119−infer :: Type -> UnifyT Check Kind
120−infer (Object row) = do
121− k <- infer row
122− k ?= Row Star
123− return Star
124−infer (TypeVar v) = do
125− Just moduleName <- checkCurrentModule <$> get
126− UnifyT . lift $ lookupTypeVariable moduleName (Qualified Nothing (ProperName v))
127−infer (TypeConstructor v) = do
128− env <- liftCheck getEnv
129− Just moduleName <- checkCurrentModule <$> get
130− case M.lookup (qualify moduleName v) (types env) of
131− Nothing -> UnifyT . lift . throwError $ "Unknown type constructor '" ++ show v ++ "'"
132− Just (kind, _) -> return kind
133−infer (TypeApp t1 t2) = do
134− k0 <- fresh
135− k1 <- infer t1
136− k2 <- infer t2
137− k1 ?= FunKind k2 k0
138− return k0
139−infer (ForAll ident ty) = do
140− k <- fresh
141− Just moduleName <- checkCurrentModule <$> get
142− bindLocalTypeVariables moduleName [(ProperName ident, k)] $ infer ty
143−infer REmpty = do
144− k <- fresh
145− return $ Row k
146−infer (RCons _ ty row) = do
147− k1 <- infer ty
148− k2 <- infer row
149− k2 ?= Row k1
150− return $ Row k1
151−infer (ConstrainedType deps ty) = do
152− mapM_ (infer . snd) deps
153− k <- infer ty
154− k ?= Star
155− return Star
156−infer _ = error "Invalid argument to infer"
src/Language/PureScript/TypeChecker/Monad.hsdeleted−330
@@ -1,330 +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, DeriveDataTypeable,
17− GADTs, StandaloneDeriving, 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.Values
24−import Language.PureScript.Names
25−import Language.PureScript.Declarations
26−
27−import Data.Data
28−import Data.Maybe
29−import Data.Monoid
30−import Data.Generics (mkT, everywhere)
31−
32−import Control.Applicative
33−import Control.Monad.State
34−import Control.Monad.Error
35−import Control.Monad.Reader
36−import Control.Monad.Unify
37−import Control.Arrow ((***))
38−
39−import qualified Data.Map as M
40−
41−-- |
42−-- The type of a name in the @Environment@
43−--
44−data NameKind
45− -- |
46− -- A value introduced as a binding in a module
47− --
48− = Value
49− -- |
50− -- A foreign import
51− --
52− | Extern ForeignImportType
53− -- |
54− -- An alias for a value in another module, introduced using an import declaration
55− --
56− | Alias ModuleName Ident
57− -- |
58− -- A local name introduced using a lambda abstraction, variable introduction or binder
59− --
60− | LocalVariable
61− -- |
62− -- A data constructor
63− --
64− | DataConstructor deriving Show
65−
66−-- |
67−-- The type of a type declaration
68−--
69−data TypeDeclarationKind
70− -- |
71− -- A data constructor
72− --
73− = Data
74− -- |
75− -- A data type foreign import
76− --
77− | ExternData
78− -- |
79− -- A type synonym
80− --
81− | TypeSynonym
82− -- |
83− -- An alias for a type in another module, introduced using an import declaration
84− --
85− | DataAlias ModuleName ProperName
86− -- |
87− -- A local type name introduced using a forall quantifier
88− --
89− | LocalTypeVariable deriving Show
90−
91−-- |
92−-- The @Environment@ defines all values and types which are currently in scope:
93−--
94−data Environment = Environment {
95− -- |
96− -- Value names currently in scope
97− --
98− names :: M.Map (ModuleName, Ident) (Type, NameKind)
99− -- |
100− -- Type names currently in scope
101− --
102− , types :: M.Map (ModuleName, ProperName) (Kind, TypeDeclarationKind)
103− -- |
104− -- Data constructors currently in scope, along with their associated data type constructors
105− --
106− , dataConstructors :: M.Map (ModuleName, ProperName) (Type, NameKind)
107− -- |
108− -- Type synonyms currently in scope
109− --
110− , typeSynonyms :: M.Map (ModuleName, ProperName) ([String], Type)
111− -- |
112− -- Available type class dictionaries
113− --
114− , typeClassDictionaries :: [TypeClassDictionaryInScope]
115− } deriving (Show)
116−
117−-- |
118−-- An empty environment with no values and no types defined
119−--
120−emptyEnvironment :: Environment
121−emptyEnvironment = Environment M.empty M.empty M.empty M.empty []
122−
123−-- |
124−-- Temporarily bind a collection of names to values
125−--
126−bindNames :: (MonadState CheckState m) => M.Map (ModuleName, Ident) (Type, NameKind) -> m a -> m a
127−bindNames newNames action = do
128− orig <- get
129− modify $ \st -> st { checkEnv = (checkEnv st) { names = newNames `M.union` (names . checkEnv $ st) } }
130− a <- action
131− modify $ \st -> st { checkEnv = (checkEnv st) { names = names . checkEnv $ orig } }
132− return a
133−
134−-- |
135−-- Temporarily bind a collection of names to types
136−--
137−bindTypes :: (MonadState CheckState m) => M.Map (ModuleName, ProperName) (Kind, TypeDeclarationKind) -> m a -> m a
138−bindTypes newNames action = do
139− orig <- get
140− modify $ \st -> st { checkEnv = (checkEnv st) { types = newNames `M.union` (types . checkEnv $ st) } }
141− a <- action
142− modify $ \st -> st { checkEnv = (checkEnv st) { types = types . checkEnv $ orig } }
143− return a
144−
145−-- |
146−-- Temporarily make a collection of type class dictionaries available
147−--
148−withTypeClassDictionaries :: (MonadState CheckState m) => [TypeClassDictionaryInScope] -> m a -> m a
149−withTypeClassDictionaries entries action = do
150− orig <- get
151− modify $ \st -> st { checkEnv = (checkEnv st) { typeClassDictionaries = entries ++ (typeClassDictionaries . checkEnv $ st) } }
152− a <- action
153− modify $ \st -> st { checkEnv = (checkEnv st) { typeClassDictionaries = typeClassDictionaries . checkEnv $ orig } }
154− return a
155−
156−-- |
157−-- Get the currently available list of type class dictionaries
158−--
159−getTypeClassDictionaries :: (Functor m, MonadState CheckState m) => m [TypeClassDictionaryInScope]
160−getTypeClassDictionaries = typeClassDictionaries . checkEnv <$> get
161−
162−-- |
163−-- Temporarily bind a collection of names to local variables
164−--
165−bindLocalVariables :: (Functor m, MonadState CheckState m) => ModuleName -> [(Ident, Type)] -> m a -> m a
166−bindLocalVariables moduleName bindings action =
167− bindNames (M.fromList $ flip map bindings $ \(name, ty) -> ((moduleName, name), (ty, LocalVariable))) action
168−
169−-- |
170−-- Temporarily bind a collection of names to local type variables
171−--
172−bindLocalTypeVariables :: (Functor m, MonadState CheckState m) => ModuleName -> [(ProperName, Kind)] -> m a -> m a
173−bindLocalTypeVariables moduleName bindings action =
174− bindTypes (M.fromList $ flip map bindings $ \(name, k) -> ((moduleName, name), (k, LocalTypeVariable))) action
175−
176−-- |
177−-- Lookup the type of a value by name in the @Environment@
178−--
179−lookupVariable :: (Functor m, MonadState CheckState m, MonadError String m) => ModuleName -> Qualified Ident -> m Type
180−lookupVariable currentModule (Qualified moduleName var) = do
181− env <- getEnv
182− case M.lookup (fromMaybe currentModule moduleName, var) (names env) of
183− Nothing -> throwError $ show var ++ " is undefined"
184− Just (ty, _) -> return ty
185−
186−-- |
187−-- Lookup the kind of a type by name in the @Environment@
188−--
189−lookupTypeVariable :: (Functor m, MonadState CheckState m, MonadError String m) => ModuleName -> Qualified ProperName -> m Kind
190−lookupTypeVariable currentModule (Qualified moduleName name) = do
191− env <- getEnv
192− case M.lookup (fromMaybe currentModule moduleName, name) (types env) of
193− Nothing -> throwError $ "Type variable " ++ show name ++ " is undefined"
194− Just (k, _) -> return k
195−
196−-- |
197−-- Canonicalize an identifier by resolving any aliases introduced by module imports
198−--
199−canonicalize :: ModuleName -> Environment -> Qualified Ident -> (ModuleName, Ident)
200−canonicalize _ _ (Qualified (Just mn) i) = (mn, i)
201−canonicalize mn env (Qualified Nothing i) = case (mn, i) `M.lookup` names env of
202− Just (_, Alias mn' i') -> (mn', i')
203− _ -> (mn, i)
204−
205−-- |
206−-- Canonicalize a type variable by resolving any aliases introduced by module imports
207−--
208−canonicalizeType :: ModuleName -> Environment -> Qualified ProperName -> (ModuleName, ProperName)
209−canonicalizeType _ _ (Qualified (Just mn) nm) = (mn, nm)
210−canonicalizeType mn env (Qualified Nothing nm) = case (mn, nm) `M.lookup` types env of
211− Just (_, DataAlias mn' pn') -> (mn', pn')
212− _ -> (mn, nm)
213−
214−-- |
215−-- Canonicalize a data constructor by resolving any aliases introduced by module imports
216−--
217−canonicalizeDataConstructor :: ModuleName -> Environment -> Qualified ProperName -> (ModuleName, Ident)
218−canonicalizeDataConstructor _ _ (Qualified (Just mn) i) = (mn, Ident $ show i)
219−canonicalizeDataConstructor mn env (Qualified Nothing i) = case (mn, i) `M.lookup` dataConstructors env of
220− Just (_, Alias mn' i') -> (mn', i')
221− _ -> (mn, Ident $ show i)
222−
223−-- |
224−-- State required for type checking:
225−--
226−data CheckState = CheckState {
227− -- |
228− -- The current @Environment@
229− --
230− checkEnv :: Environment
231− -- |
232− -- The next fresh unification variable name
233− --
234− , checkNextVar :: Int
235− -- |
236− -- The next type class dictionary name
237− --
238− , checkNextDictName :: Int
239− -- |
240− -- The current module
241− --
242− , checkCurrentModule :: Maybe ModuleName
243− }
244−
245−-- |
246−-- The type checking monad, which provides the state of the type checker, and error reporting capabilities
247−--
248−newtype Check a = Check { unCheck :: StateT CheckState (Either String) a }
249− deriving (Functor, Monad, Applicative, MonadPlus, MonadState CheckState, MonadError String)
250−
251−-- |
252−-- Get the current @Environment@
253−--
254−getEnv :: (Functor m, MonadState CheckState m) => m Environment
255−getEnv = checkEnv <$> get
256−
257−-- |
258−-- Update the @Environment#
259−--
260−putEnv :: (MonadState CheckState m) => Environment -> m ()
261−putEnv env = modify (\s -> s { checkEnv = env })
262−
263−-- |
264−-- Modify the @Environment@
265−--
266−modifyEnv :: (MonadState CheckState m) => (Environment -> Environment) -> m ()
267−modifyEnv f = modify (\s -> s { checkEnv = f (checkEnv s) })
268−
269−-- |
270−-- Run a computation in the Check monad, failing with an error, or succeeding with a return value and the final @Environment@.
271−--
272−runCheck :: Check a -> Either String (a, Environment)
273−runCheck c = do
274− (a, s) <- flip runStateT (CheckState emptyEnvironment 0 0 Nothing) $ unCheck c
275− return (a, checkEnv s)
276−
277−-- |
278−-- Make an assertion, failing with an error message
279−--
280−guardWith :: (MonadError e m) => e -> Bool -> m ()
281−guardWith _ True = return ()
282−guardWith e False = throwError e
283−
284−-- |
285−-- Rethrow an error with a more detailed error message in the case of failure
286−--
287−rethrow :: (MonadError e m) => (e -> e) -> m a -> m a
288−rethrow f = flip catchError $ \e -> throwError (f e)
289−
290−-- |
291−-- Generate new type class dictionary name
292−--
293−freshDictionaryName :: Check Int
294−freshDictionaryName = do
295− n <- checkNextDictName <$> get
296− modify $ \s -> s { checkNextDictName = succ (checkNextDictName s) }
297− return n
298−
299−-- |
300−-- Lift a computation in the @Check@ monad into the substitution monad.
301−--
302−liftCheck :: Check a -> UnifyT Check a
303−liftCheck = UnifyT . lift . lift
304−
305−-- |
306−-- Run a computation in the substitution monad, generating a return value and the final substitution.
307−--
308−liftUnify :: (Data a) => UnifyT Check a -> Check a
309−liftUnify unify = do
310− st <- get
311− e <- runUnify (defaultUnifyState { unifyNextVar = checkNextVar st }) unify
312− case e of
313− Left err -> throwError err
314− Right (a, ust) -> do
315− modify $ \st -> st { checkNextVar = unifyNextVar ust }
316− return $ runSubstitution (unifyCurrentSubstitution ust) a
317−
318−-- |
319−-- Replace any unqualified names in a type wit their qualified versionss
320−--
321−qualifyAllUnqualifiedNames :: (Data d) => ModuleName -> Environment -> d -> d
322−qualifyAllUnqualifiedNames mn env = everywhere (mkT go)
323− where
324− go :: Type -> Type
325− go (TypeConstructor nm) = TypeConstructor $ qualify' nm
326− go (SaturatedTypeSynonym nm args) = SaturatedTypeSynonym (qualify' nm) args
327− go (ConstrainedType constraints ty) = ConstrainedType (map (qualify' *** id) constraints) ty
328− go other = other
329− qualify' qual = let (mn', pn') = canonicalizeType mn env qual
330− in Qualified (Just mn') pn'
src/Language/PureScript/TypeChecker/Synonyms.hsdeleted−59
@@ -1,59 +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− saturateTypeSynonym,
18− saturateAllTypeSynonyms
19−) where
20−
21−import Language.PureScript.Types
22−import Language.PureScript.Names
23−import Language.PureScript.TypeChecker.Monad (Environment(..), canonicalizeType)
24−
25−import Data.Maybe (fromMaybe)
26−import Data.Data
27−import Data.Generics
28−import Data.Generics.Extras
29−import Control.Monad.Writer
30−import Control.Monad.Error
31−
32−-- |
33−-- Build a type substitution for a type synonym
34−--
35−buildTypeSubstitution :: Environment -> ModuleName -> (ModuleName, ProperName) -> Int -> Type -> Either String (Maybe Type)
36−buildTypeSubstitution env moduleName name n = go n []
37− where
38− go :: Int -> [Type] -> Type -> Either String (Maybe Type)
39− go 0 args (TypeConstructor ctor) | name == canonicalizeType moduleName env ctor = return (Just $ SaturatedTypeSynonym ctor args)
40− go m _ (TypeConstructor ctor) | m > 0 && name == qualify moduleName ctor = throwError $ "Partially applied type synonym " ++ show name
41− go m args (TypeApp f arg) = go (m - 1) (arg:args) f
42− go _ _ _ = return Nothing
43−
44−-- |
45−-- Replace all instances of a specific type synonym with the @SaturatedTypeSynonym@ data constructor
46−--
47−saturateTypeSynonym :: (Data d) => Environment -> ModuleName -> (ModuleName, ProperName) -> Int -> d -> Either String d
48−saturateTypeSynonym env moduleName name n = everywhereM' (mkM replace)
49− where
50− replace t = fmap (fromMaybe t) $ buildTypeSubstitution env moduleName name n t
51−
52−-- |
53−-- Replace all type synonyms with the @SaturatedTypeSynonym@ data constructor
54−--
55−saturateAllTypeSynonyms :: (Data d) => Environment -> ModuleName -> [((ModuleName, ProperName), Int)] -> d -> Either String d
56−saturateAllTypeSynonyms env moduleName syns d = foldM (\result (name, n) -> saturateTypeSynonym env moduleName name n result) d syns
57−
58−
59−
src/Language/PureScript/TypeChecker/Types.hsdeleted−878
@@ -1,878 +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 DeriveDataTypeable #-}
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 qualified Data.Data as D
47−import Data.Generics
48− (mkM, everywhereM, everything, mkT, something, everywhere, mkQ)
49−
50−import Language.PureScript.Values
51−import Language.PureScript.Types
52−import Language.PureScript.Kinds
53−import Language.PureScript.Names
54−import Language.PureScript.TypeChecker.Monad
55−import Language.PureScript.TypeChecker.Kinds
56−import Language.PureScript.TypeChecker.Synonyms
57−import Language.PureScript.Pretty
58−
59−import Control.Monad.State
60−import Control.Monad.Error
61−import Control.Monad.Reader
62−import Control.Monad.Unify
63−
64−import Control.Applicative
65−import Control.Arrow (Arrow(..))
66−
67−import qualified Data.Map as M
68−import Data.Function (on)
69−
70−instance Unifiable Check Type where
71− unknown = TUnknown
72− isUnknown (TUnknown u) = Just u
73− isUnknown _ = Nothing
74− (?=) = unifyTypes
75−
76−-- |
77−-- Unify two types, updating the current substitution
78−--
79−unifyTypes :: Type -> Type -> UnifyT Check ()
80−unifyTypes t1 t2 = rethrow (\e -> "Error unifying type " ++ prettyPrintType t1 ++ " with type " ++ prettyPrintType t2 ++ ":\n" ++ e) $ do
81− unifyTypes' t1 t2
82− where
83− unifyTypes' (TUnknown u1) (TUnknown u2) | u1 == u2 = return ()
84− unifyTypes' (TUnknown u) t = replace u t
85− unifyTypes' t (TUnknown u) = replace u t
86− unifyTypes' (SaturatedTypeSynonym name args) ty = do
87− ty1 <- expandTypeSynonym name args
88− ty1 `unifyTypes` ty
89− unifyTypes' ty s@(SaturatedTypeSynonym _ _) = s `unifyTypes` ty
90− unifyTypes' (ForAll ident1 ty1) (ForAll ident2 ty2) = do
91− sk <- skolemize ident1 ty1
92− replaced <- replaceVarWithUnknown ident2 ty2
93− sk `unifyTypes` replaced
94− unifyTypes' (ForAll ident ty1) ty2 = do
95− sk <- skolemize ident ty1
96− sk `unifyTypes` ty2
97− unifyTypes' ty f@(ForAll _ _) = f `unifyTypes` ty
98− unifyTypes' (Object row1) (Object row2) = row1 ?= row2
99− unifyTypes' (TypeVar v1) (TypeVar v2) | v1 == v2 = return ()
100− unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do
101− env <- getEnv
102− Just moduleName <- checkCurrentModule <$> get
103− guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (typeConstructorsAreEqual env moduleName c1 c2)
104− unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do
105− t3 `unifyTypes` t5
106− t4 `unifyTypes` t6
107− unifyTypes' (Skolem s1) (Skolem s2) | s1 == s2 = return ()
108− unifyTypes' r1@(RCons _ _ _) r2 = unifyRows r1 r2
109− unifyTypes' r1 r2@(RCons _ _ _) = unifyRows r1 r2
110− unifyTypes' r1@REmpty r2 = unifyRows r1 r2
111− unifyTypes' r1 r2@REmpty = unifyRows r1 r2
112− unifyTypes' t3 t4 = throwError $ "Cannot unify " ++ prettyPrintType t3 ++ " with " ++ prettyPrintType t4 ++ "."
113−
114−-- |
115−-- Unify two rows, updating the current substitution
116−--
117−-- Common labels are first identified, and unified. Remaining labels and types are unified with a
118−-- trailing row unification variable, if appropriate, otherwise leftover labels result in a unification
119−-- error.
120−--
121−unifyRows :: Type -> Type -> UnifyT Check ()
122−unifyRows r1 r2 =
123− let
124− (s1, r1') = rowToList r1
125− (s2, r2') = rowToList r2
126− int = [ (t1, t2) | (name, t1) <- s1, (name', t2) <- s2, name == name' ]
127− sd1 = [ (name, t1) | (name, t1) <- s1, name `notElem` map fst s2 ]
128− sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ]
129− in do
130− forM_ int (uncurry (?=))
131− unifyRows' sd1 r1' sd2 r2'
132− where
133− unifyRows' :: [(String, Type)] -> Type -> [(String, Type)] -> Type -> UnifyT Check ()
134− unifyRows' [] (TUnknown u) sd r = replace u (rowFromList (sd, r))
135− unifyRows' sd r [] (TUnknown u) = replace u (rowFromList (sd, r))
136− unifyRows' ((name, ty):row) r others u@(TUnknown un) = do
137− occursCheck un ty
138− forM_ row $ \(_, t) -> occursCheck un t
139− u' <- fresh
140− u ?= RCons name ty u'
141− unifyRows' row r others u'
142− unifyRows' [] REmpty [] REmpty = return ()
143− unifyRows' [] (TypeVar v1) [] (TypeVar v2) | v1 == v2 = return ()
144− unifyRows' [] (Skolem s1) [] (Skolem s2) | s1 == s2 = return ()
145− unifyRows' sd3 r3 sd4 r4 = throwError $ "Cannot unify " ++ prettyPrintRow (rowFromList (sd3, r3)) ++ " with " ++ prettyPrintRow (rowFromList (sd4, r4)) ++ "."
146−
147−-- |
148−-- Ensure type constructors are equal after canonicalization
149−--
150−typeConstructorsAreEqual :: Environment -> ModuleName -> Qualified ProperName -> Qualified ProperName -> Bool
151−typeConstructorsAreEqual env moduleName = (==) `on` canonicalizeType moduleName env
152−
153−-- |
154−-- Infer the types of multiple mutually-recursive values, and return elaborated values including
155−-- type class dictionaries and type annotations.
156−--
157−typesOf :: ModuleName -> [(Ident, Value)] -> Check [(Ident, (Value, Type))]
158−typesOf moduleName vals = do
159− tys <- liftUnify $ do
160− let es = map isTyped vals
161− typed = filter (isJust . snd . snd) es
162− untyped = filter (isNothing . snd . snd) es
163− typedDict = map (\(ident, (_, Just ty)) -> (ident, ty)) typed
164− untypedNames <- replicateM (length untyped) fresh
165− let untypedDict = zip (map fst untyped) untypedNames
166− dict = M.fromList (map (\(ident, ty) -> ((moduleName, ident), (ty, LocalVariable))) $ (map (id *** fst) typedDict) ++ untypedDict)
167− forM es $ \e -> do
168− triple@(_, (val, ty)) <- case e of
169− (ident, (val, Just (ty, checkType))) -> do
170− kind <- liftCheck $ kindOf moduleName ty
171− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
172− ty' <- replaceAllTypeSynonyms ty
173− val' <- bindNames dict $ if checkType then check val ty' else return val
174− return (ident, (val', ty'))
175− (ident, (val, Nothing)) -> do
176− TypedValue _ val' ty <- bindNames dict $ infer val
177− ty ?= fromMaybe (error "name not found in dictionary") (lookup ident untypedDict)
178− return (ident, (val', ty))
179− when (moduleName == ModuleName (ProperName "Main") && fst e == Ident "main") $ do
180− [eff, a] <- replicateM 2 fresh
181− ty ?= TypeApp (TypeApp (TypeConstructor (Qualified (Just (ModuleName (ProperName "Eff"))) (ProperName "Eff"))) eff) a
182− escapeCheck val ty
183− return triple
184− forM_ tys $ skolemEscapeCheck . snd . snd
185− forM tys $ \(ident, (val, ty)) -> do
186− val' <- replaceTypeClassDictionaries moduleName val
187− return (ident, (overTypes (desaturateAllTypeSynonyms . setifyAll) $ val'
188− , varIfUnknown . desaturateAllTypeSynonyms . setifyAll $ ty))
189−
190−-- |
191−-- Check if a value contains a type annotation
192−--
193−isTyped :: (Ident, Value) -> (Ident, (Value, Maybe (Type, Bool)))
194−isTyped (name, TypedValue checkType value ty) = (name, (value, Just (ty, checkType)))
195−isTyped (name, value) = (name, (value, Nothing))
196−
197−-- |
198−-- Map a function over type annotations appearing inside a value
199−--
200−overTypes :: (Type -> Type) -> Value -> Value
201−overTypes f = everywhere (mkT f)
202−
203−-- |
204−-- Replace type class dictionary placeholders with inferred type class dictionaries
205−--
206−replaceTypeClassDictionaries :: ModuleName -> Value -> Check Value
207−replaceTypeClassDictionaries mn = everywhereM (mkM go)
208− where
209− go (TypeClassDictionary constraint dicts) = entails mn dicts constraint
210− go other = return other
211−
212−-- |
213−-- Check that the current set of type class dictionaries entail the specified type class goal, and, if so,
214−-- return a type class dictionary reference.
215−--
216−entails :: ModuleName -> [TypeClassDictionaryInScope] -> (Qualified ProperName, Type) -> Check Value
217−entails moduleName context goal@(className, ty) = do
218− env <- getEnv
219− case go env goal of
220− [] -> throwError $ "No " ++ show className ++ " instance found for " ++ prettyPrintType ty
221− (dict : _) -> return dict
222− where
223− go env (className', ty') =
224− [ mkDictionary (canonicalizeDictionary tcd) args
225− | tcd <- context
226− , filterModule tcd
227− , typeConstructorsAreEqual env moduleName className' (tcdClassName tcd)
228− , subst <- maybeToList $ typeHeadsAreEqual moduleName env ty' (tcdInstanceType tcd)
229− , args <- solveSubgoals env subst (tcdDependencies tcd) ]
230− solveSubgoals :: Environment -> [(String, Type)] -> Maybe [(Qualified ProperName, Type)] -> [Maybe [Value]]
231− solveSubgoals _ _ Nothing = return Nothing
232− solveSubgoals env subst (Just subgoals) = do
233− dict <- mapM (go env) (replaceAllTypeVars subst subgoals)
234− return $ Just dict
235− mkDictionary :: Qualified Ident -> Maybe [Value] -> Value
236− mkDictionary fnName Nothing = Var fnName
237− mkDictionary fnName (Just dicts) = foldr (flip App) (Var fnName) dicts
238− filterModule :: TypeClassDictionaryInScope -> Bool
239− filterModule (TypeClassDictionaryInScope { tcdName = Qualified (Just mn) _ }) | mn == moduleName = True
240− filterModule (TypeClassDictionaryInScope { tcdName = Qualified Nothing _ }) = True
241− filterModule _ = False
242− canonicalizeDictionary :: TypeClassDictionaryInScope -> Qualified Ident
243− canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDRegular, tcdName = nm }) = nm
244− canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDAlias nm }) = nm
245−
246−-- |
247−-- Check whether the type heads of two types are equal (for the purposes of type class dictionary lookup),
248−-- and return a substitution from type variables to types which makes the type heads unify.
249−--
250−typeHeadsAreEqual :: ModuleName -> Environment -> Type -> Type -> Maybe [(String, Type)]
251−typeHeadsAreEqual _ _ (Skolem s1) (Skolem s2) | s1 == s2 = Just []
252−typeHeadsAreEqual m e (TypeConstructor c1) (TypeConstructor c2) | typeConstructorsAreEqual e m c1 c2 = Just []
253−typeHeadsAreEqual m e (TypeApp h1 (TypeVar v)) (TypeApp h2 arg) = (:) (v, arg) <$> typeHeadsAreEqual m e h1 h2
254−typeHeadsAreEqual m e t1@(TypeApp _ _) t2@(TypeApp _ (TypeVar _)) = typeHeadsAreEqual m e t2 t1
255−typeHeadsAreEqual _ _ _ _ = Nothing
256−
257−-- |
258−-- Ensure unsolved unification variables do not escape
259−--
260−escapeCheck :: Value -> Type -> UnifyT Check ()
261−escapeCheck value ty = do
262− subst <- unifyCurrentSubstitution <$> UnifyT get
263− let visibleUnknowns = nub $ unknowns $ runSubstitution subst ty
264− let allUnknowns = findAllTypes value
265− forM_ allUnknowns $ \t -> do
266− let unsolvedUnknowns = nub . unknowns $ runSubstitution subst t
267− guardWith ("Escape check fails" ++ show ( runSubstitution subst ty, runSubstitution subst t)) $ null $ unsolvedUnknowns \\ visibleUnknowns
268−
269−-- |
270−-- Find all type annotations occuring inside a value
271−--
272−findAllTypes :: Value -> [Type]
273−findAllTypes = everything (++) (mkQ [] go)
274− where
275− go (TypedValue _ _ ty) = [ty]
276− go _ = []
277−
278−-- |
279−-- Ensure skolem variables do not escape their scope
280−--
281−skolemEscapeCheck :: Type -> Check ()
282−skolemEscapeCheck ty =
283− case something (mkQ Nothing findSkolems) ty of
284− Nothing -> return ()
285− Just _ -> throwError $ "Skolem variables cannot escape. Consider adding a type signature."
286− where
287− findSkolems (Skolem _) = return ()
288− findSkolems _ = mzero
289−
290−-- |
291−-- Ensure a row contains no duplicate labels
292−--
293−setify :: Type -> Type
294−setify = rowFromList . first (M.toList . M.fromList) . rowToList
295−
296−-- |
297−-- \"Setify\" all rows occuring inside a value
298−--
299−setifyAll :: (D.Data d) => d -> d
300−setifyAll = everywhere (mkT setify)
301−
302−-- |
303−-- Replace outermost unsolved unification variables with named type variables
304−--
305−varIfUnknown :: Type -> Type
306−varIfUnknown ty =
307− let unks = nub $ unknowns ty
308− toName = (:) 't' . show
309− ty' = everywhere (mkT typeToVar) $ ty
310− typeToVar :: Type -> Type
311− typeToVar (TUnknown (TypedUnknown (Unknown u))) = TypeVar (toName u)
312− typeToVar t = t
313− in mkForAll (sort . map (toName . runUnknown) $ unks) ty'
314−
315−-- |
316−-- Replace named type variables with types
317−--
318−replaceAllTypeVars :: (D.Data d) => [(String, Type)] -> d -> d
319−replaceAllTypeVars = foldl' (\f (name, ty) -> replaceTypeVars name ty . f) id
320−
321−-- |
322−-- Replace named type variables with new unification variables
323−--
324−replaceAllVarsWithUnknowns :: Type -> UnifyT Check Type
325−replaceAllVarsWithUnknowns (ForAll ident ty) = replaceVarWithUnknown ident ty >>= replaceAllVarsWithUnknowns
326−replaceAllVarsWithUnknowns ty = return ty
327−
328−-- |
329−-- Replace a single type variable with a new unification variable
330−--
331−replaceVarWithUnknown :: String -> Type -> UnifyT Check Type
332−replaceVarWithUnknown ident ty = do
333− tu <- fresh
334− return $ replaceTypeVars ident tu $ ty
335−
336−-- |
337−-- Replace fully applied type synonyms with the @SaturatedTypeSynonym@ data constructor, which helps generate
338−-- better error messages during unification.
339−--
340−replaceAllTypeSynonyms :: (Functor m, MonadState CheckState m, MonadError String m) => (D.Data d) => d -> m d
341−replaceAllTypeSynonyms d = do
342− env <- getEnv
343− Just moduleName <- checkCurrentModule <$> get
344− let syns = map (\((path, name), (args, _)) -> ((path, name), length args)) . M.toList $ typeSynonyms env
345− either throwError return $ saturateAllTypeSynonyms env moduleName syns d
346−
347−-- |
348−-- \"Desaturate\" @SaturatedTypeSynonym@s
349−--
350−desaturateAllTypeSynonyms :: (D.Data d) => d -> d
351−desaturateAllTypeSynonyms = everywhere (mkT replaceSaturatedTypeSynonym)
352− where
353− replaceSaturatedTypeSynonym (SaturatedTypeSynonym name args) = foldl TypeApp (TypeConstructor name) args
354− replaceSaturatedTypeSynonym t = t
355−
356−-- |
357−-- Replace a type synonym and its arguments with the aliased type
358−--
359−expandTypeSynonym :: Qualified ProperName -> [Type] -> UnifyT Check Type
360−expandTypeSynonym name args = do
361− env <- getEnv
362− Just moduleName <- checkCurrentModule <$> get
363− case M.lookup (canonicalizeType moduleName env name) (typeSynonyms env) of
364− Just (synArgs, body) -> return $ replaceAllTypeVars (zip synArgs args) body
365− Nothing -> error "Type synonym was not defined"
366−
367−-- |
368−-- Ensure a set of property names and value does not contain duplicate labels
369−--
370−ensureNoDuplicateProperties :: (MonadError String m) => [(String, Value)] -> m ()
371−ensureNoDuplicateProperties ps = guardWith "Duplicate property names" $ length (nub . map fst $ ps) == length ps
372−
373−-- |
374−-- Infer a type for a value, rethrowing any error to provide a more useful error message
375−--
376−infer :: Value -> UnifyT Check Value
377−infer val = rethrow (\e -> "Error inferring type of term " ++ prettyPrintValue val ++ ":\n" ++ e) $ infer' val
378−
379−-- |
380−-- Infer a type for a value
381−--
382−infer' :: Value -> UnifyT Check Value
383−infer' v@(NumericLiteral _) = return $ TypedValue True v tyNumber
384−infer' v@(StringLiteral _) = return $ TypedValue True v tyString
385−infer' v@(BooleanLiteral _) = return $ TypedValue True v tyBoolean
386−infer' (ArrayLiteral vals) = do
387− ts <- mapM infer vals
388− els <- fresh
389− forM_ ts $ \(TypedValue _ _ t) -> els ?= TypeApp tyArray t
390− return $ TypedValue True (ArrayLiteral ts) els
391−infer' (ObjectLiteral ps) = do
392− ensureNoDuplicateProperties ps
393− ts <- mapM (infer . snd) ps
394− let fields = zipWith (\name (TypedValue _ _ t) -> (name, t)) (map fst ps) ts
395− ty = Object $ rowFromList (fields, REmpty)
396− return $ TypedValue True (ObjectLiteral (zip (map fst ps) ts)) ty
397−infer' (ObjectUpdate o ps) = do
398− ensureNoDuplicateProperties ps
399− row <- fresh
400− newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> mapM (infer . snd) ps
401− let newTys = map (\(name, TypedValue _ _ ty) -> (name, ty)) newVals
402− oldTys <- zip (map fst ps) <$> replicateM (length ps) fresh
403− o' <- check o $ Object $ rowFromList (oldTys, row)
404− return $ TypedValue True (ObjectUpdate o' newVals) $ Object $ rowFromList (newTys, row)
405−infer' (Accessor prop val) = do
406− typed@(TypedValue _ _ objTy) <- infer val
407− propTy <- inferProperty objTy prop
408− case propTy of
409− Nothing -> do
410− field <- fresh
411− rest <- fresh
412− _ <- subsumes Nothing objTy (Object (RCons prop field rest))
413− return $ TypedValue True (Accessor prop typed) field
414− Just ty -> return $ TypedValue True (Accessor prop typed) ty
415−infer' (Abs arg ret) = do
416− ty <- fresh
417− Just moduleName <- checkCurrentModule <$> get
418− bindLocalVariables moduleName [(arg, ty)] $ do
419− body@(TypedValue _ _ bodyTy) <- infer' ret
420− return $ TypedValue True (Abs arg body) $ function ty bodyTy
421−infer' (App f arg) = do
422− f'@(TypedValue _ _ ft) <- infer f
423− ret <- fresh
424− app <- checkFunctionApplication f' ft arg ret
425− return $ TypedValue True app ret
426−infer' (Var var) = do
427− Just moduleName <- checkCurrentModule <$> get
428− ty <- lookupVariable moduleName var
429− ty' <- replaceAllTypeSynonyms ty
430− case ty' of
431− ConstrainedType constraints _ -> do
432− env <- getEnv
433− dicts <- getTypeClassDictionaries
434− return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty'
435− _ -> return $ TypedValue True (Var var) ty'
436−infer' (Block ss) = do
437− ret <- fresh
438− (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
439− guardWith "Block is missing a return statement" allCodePathsReturn
440− return $ TypedValue True (Block ss') ret
441−infer' v@(Constructor c) = do
442− env <- getEnv
443− Just moduleName <- checkCurrentModule <$> get
444− case M.lookup (qualify moduleName c) (dataConstructors env) of
445− Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
446− Just (ty, _) -> do ty' <- replaceAllTypeSynonyms ty
447− return $ TypedValue True v ty'
448−infer' (Case vals binders) = do
449− ts <- mapM infer vals
450− ret <- fresh
451− binders' <- checkBinders (map (\(TypedValue _ _ t) -> t) ts) ret binders
452− return $ TypedValue True (Case ts binders') ret
453−infer' (IfThenElse cond th el) = do
454− cond' <- check cond tyBoolean
455− v2@(TypedValue _ _ t2) <- infer th
456− v3@(TypedValue _ _ t3) <- infer el
457− t2 ?= t3
458− return $ TypedValue True (IfThenElse cond' v2 v3) t2
459−infer' (TypedValue checkType val ty) = do
460− Just moduleName <- checkCurrentModule <$> get
461− kind <- liftCheck $ kindOf moduleName ty
462− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
463− ty' <- replaceAllTypeSynonyms ty
464− val' <- if checkType then check val ty' else return val
465− return $ TypedValue True val' ty
466−infer' _ = error "Invalid argument to infer"
467−
468−-- |
469−-- Infer the type of a property inside a record with a given type
470−--
471−inferProperty :: Type -> String -> UnifyT Check (Maybe Type)
472−inferProperty (Object row) prop = do
473− let (props, _) = rowToList row
474− return $ lookup prop props
475−inferProperty (SaturatedTypeSynonym name args) prop = do
476− replaced <- expandTypeSynonym name args
477− inferProperty replaced prop
478−inferProperty (ForAll ident ty) prop = do
479− replaced <- replaceVarWithUnknown ident ty
480− inferProperty replaced prop
481−inferProperty _ _ = return Nothing
482−
483−-- |
484−-- Infer the types of variables brought into scope by a binder
485−--
486−inferBinder :: Type -> Binder -> UnifyT Check (M.Map Ident Type)
487−inferBinder _ NullBinder = return M.empty
488−inferBinder val (StringBinder _) = val ?= tyString >> return M.empty
489−inferBinder val (NumberBinder _) = val ?= tyNumber >> return M.empty
490−inferBinder val (BooleanBinder _) = val ?= tyBoolean >> return M.empty
491−inferBinder val (VarBinder name) = return $ M.singleton name val
492−inferBinder val (NullaryBinder ctor) = do
493− env <- getEnv
494− Just moduleName <- checkCurrentModule <$> get
495− case M.lookup (qualify moduleName ctor) (dataConstructors env) of
496− Just (ty, _) -> do
497− _ <- subsumes Nothing ty val
498− return M.empty
499− _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
500−inferBinder val (UnaryBinder ctor binder) = do
501− env <- getEnv
502− Just moduleName <- checkCurrentModule <$> get
503− case M.lookup (qualify moduleName ctor) (dataConstructors env) of
504− Just (ty, _) -> do
505− fn <- replaceAllVarsWithUnknowns ty
506− case fn of
507− TypeApp (TypeApp t obj) ret | t == tyFunction -> do
508− _ <- subsumes Nothing val ret
509− inferBinder obj binder
510− _ -> throwError $ "Constructor " ++ show ctor ++ " is not a unary constructor"
511− _ -> throwError $ "Constructor " ++ show ctor ++ " is not defined"
512−inferBinder val (ObjectBinder props) = do
513− row <- fresh
514− rest <- fresh
515− m1 <- inferRowProperties row rest props
516− val ?= Object row
517− return m1
518− where
519− inferRowProperties :: Type -> Type -> [(String, Binder)] -> UnifyT Check (M.Map Ident Type)
520− inferRowProperties nrow row [] = nrow ?= row >> return M.empty
521− inferRowProperties nrow row ((name, binder):binders) = do
522− propTy <- fresh
523− m1 <- inferBinder propTy binder
524− m2 <- inferRowProperties nrow (RCons name propTy row) binders
525− return $ m1 `M.union` m2
526−inferBinder val (ArrayBinder binders) = do
527− el <- fresh
528− m1 <- M.unions <$> mapM (inferBinder el) binders
529− val ?= TypeApp tyArray el
530− return m1
531−inferBinder val (ConsBinder headBinder tailBinder) = do
532− el <- fresh
533− m1 <- inferBinder el headBinder
534− m2 <- inferBinder val tailBinder
535− val ?= TypeApp tyArray el
536− return $ m1 `M.union` m2
537−inferBinder val (NamedBinder name binder) = do
538− m <- inferBinder val binder
539− return $ M.insert name val m
540−
541−-- |
542−-- Check the types of the return values in a set of binders in a case statement
543−--
544−checkBinders :: [Type] -> Type -> [([Binder], Maybe Guard, Value)] -> UnifyT Check [([Binder], Maybe Guard, Value)]
545−checkBinders _ _ [] = return []
546−checkBinders nvals ret ((binders, grd, val):bs) = do
547− Just moduleName <- checkCurrentModule <$> get
548− m1 <- M.unions <$> zipWithM inferBinder nvals binders
549− r <- bindLocalVariables moduleName (M.toList m1) $ do
550− val' <- check val ret
551− case grd of
552− Nothing -> return (binders, Nothing, val')
553− Just g -> do
554− g' <- check g tyBoolean
555− return (binders, Just g', val')
556− rs <- checkBinders nvals ret bs
557− return $ r : rs
558−
559−-- |
560−-- Check that a local variable name is not already used
561−--
562−assignVariable :: Ident -> UnifyT Check ()
563−assignVariable name = do
564− env <- checkEnv <$> get
565− Just moduleName <- checkCurrentModule <$> get
566− case M.lookup (moduleName, name) (names env) of
567− Just _ -> UnifyT . lift . throwError $ "Variable with name " ++ show name ++ " already exists."
568− _ -> return ()
569−
570−-- |
571−-- Check the type of the return values of a statement, returning whether or not the statement returns on
572−-- all code paths
573−--
574−checkStatement :: M.Map Ident Type -> Type -> Statement -> UnifyT Check (Bool, M.Map Ident Type, Statement)
575−checkStatement mass _ (VariableIntroduction name val) = do
576− assignVariable name
577− val'@(TypedValue _ _ t) <- infer val
578− return (False, M.insert name t mass, VariableIntroduction name val')
579−checkStatement mass _ (Assignment ident val) = do
580− val'@(TypedValue _ _ t) <- infer val
581− case M.lookup ident mass of
582− Nothing -> throwError $ "No local variable with name " ++ show ident
583− Just ty -> do t ?= ty
584− return (False, mass, Assignment ident val')
585−checkStatement mass ret (While val inner) = do
586− val' <- check val tyBoolean
587− (allCodePathsReturn, _, inner') <- checkBlock mass ret inner
588− return (allCodePathsReturn, mass, While val' inner')
589−checkStatement mass ret (If ifst) = do
590− (allCodePathsReturn, ifst') <- checkIfStatement mass ret ifst
591− return (allCodePathsReturn, mass, If ifst')
592−checkStatement mass ret (For ident start end inner) = do
593− Just moduleName <- checkCurrentModule <$> get
594− assignVariable ident
595− start' <- check start tyNumber
596− end' <- check end tyNumber
597− (allCodePathsReturn, _, inner') <- bindLocalVariables moduleName [(ident, tyNumber)] $ checkBlock mass ret inner
598− return (allCodePathsReturn, mass, For ident start' end' inner')
599−checkStatement mass ret (Return val) = do
600− val' <- check val ret
601− return (True, mass, Return val')
602−
603−-- |
604−-- Check the type of an if-then-else statement
605−--
606−checkIfStatement :: M.Map Ident Type -> Type -> IfStatement -> UnifyT Check (Bool, IfStatement)
607−checkIfStatement mass ret (IfStatement val thens Nothing) = do
608− val' <- check val tyBoolean
609− (_, _, thens') <- checkBlock mass ret thens
610− return (False, IfStatement val' thens' Nothing)
611−checkIfStatement mass ret (IfStatement val thens (Just elses)) = do
612− val' <- check val tyBoolean
613− (allCodePathsReturn1, _, thens') <- checkBlock mass ret thens
614− (allCodePathsReturn2, elses') <- checkElseStatement mass ret elses
615− return (allCodePathsReturn1 && allCodePathsReturn2, IfStatement val' thens' (Just elses'))
616−
617−-- |
618−-- Check the type of an else statement
619−--
620−checkElseStatement :: M.Map Ident Type -> Type -> ElseStatement -> UnifyT Check (Bool, ElseStatement)
621−checkElseStatement mass ret (Else elses) = do
622− (allCodePathsReturn, _, elses') <- checkBlock mass ret elses
623− return (allCodePathsReturn, Else elses')
624−checkElseStatement mass ret (ElseIf ifst) = (id *** ElseIf) <$> checkIfStatement mass ret ifst
625−
626−-- |
627−-- Check the type of the return value of a block of statements
628−--
629−checkBlock :: M.Map Ident Type -> Type -> [Statement] -> UnifyT Check (Bool, M.Map Ident Type, [Statement])
630−checkBlock mass _ [] = return (False, mass, [])
631−checkBlock mass ret (s:ss) = do
632− Just moduleName <- checkCurrentModule <$> get
633− (b1, mass1, s') <- checkStatement mass ret s
634− bindLocalVariables moduleName (M.toList mass1) $ case (b1, ss) of
635− (True, []) -> return (True, mass1, [s'])
636− (True, _) -> throwError "Unreachable code"
637− (False, ss') -> do
638− (b, m, ss'') <- checkBlock mass1 ret ss'
639− return (b, m, s':ss'')
640−
641−-- |
642−-- Skolemize a type variable by replacing its instances with fresh skolem constants
643−--
644−skolemize :: String -> Type -> UnifyT Check Type
645−skolemize ident ty = do
646− tsk <- Skolem . runUnknown <$> fresh'
647− return $ replaceTypeVars ident tsk ty
648−
649−-- |
650−-- Check the type of a value, rethrowing errors to provide a better error message
651−--
652−check :: Value -> Type -> UnifyT Check Value
653−check val ty = rethrow errorMessage $ check' val ty
654− where
655− errorMessage msg =
656− "Error checking type of term " ++
657− prettyPrintValue val ++
658− " against type " ++
659− prettyPrintType ty ++
660− ":\n" ++
661− msg
662−
663−-- |
664−-- Check the type of a value
665−--
666−check' :: Value -> Type -> UnifyT Check Value
667−check' val (ForAll idents ty) = do
668− sk <- skolemize idents ty
669− check val sk
670−check' val (ConstrainedType constraints ty) = do
671− env <- getEnv
672− Just moduleName <- checkCurrentModule <$> get
673− dictNames <- flip mapM constraints $ \(Qualified _ (ProperName className), _) -> do
674− n <- liftCheck freshDictionaryName
675− return $ Ident $ "__dict_" ++ className ++ "_" ++ show n
676− val' <- withTypeClassDictionaries (zipWith (\name (className, instanceTy) ->
677− TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular) (map (Qualified Nothing) dictNames)
678− (qualifyAllUnqualifiedNames moduleName env constraints)) $
679− check val ty
680− return $ foldr Abs val' dictNames
681−check' val u@(TUnknown _) = do
682− val'@(TypedValue _ _ ty) <- infer val
683− -- Don't unify an unknown with an inferred polytype
684− ty' <- replaceAllVarsWithUnknowns ty
685− ty' ?= u
686− return val'
687−check' v@(NumericLiteral _) t | t == tyNumber = return v
688−check' v@(StringLiteral _) t | t == tyString = return v
689−check' v@(BooleanLiteral _) t | t == tyBoolean = return v
690−check' (ArrayLiteral vals) (TypeApp a ty) | a == tyArray = ArrayLiteral <$> forM vals (\val -> check val ty)
691−check' (Abs arg ret) (TypeApp (TypeApp t argTy) retTy) | t == tyFunction = do
692− Just moduleName <- checkCurrentModule <$> get
693− ret' <- bindLocalVariables moduleName [(arg, argTy)] $ check ret retTy
694− return $ Abs arg ret'
695−check' (App f arg) ret = do
696− f'@(TypedValue _ _ ft) <- infer f
697− app <- checkFunctionApplication f' ft arg ret
698− return $ app
699−check' v@(Var var) ty = do
700− Just moduleName <- checkCurrentModule <$> get
701− ty1 <- lookupVariable moduleName var
702− repl <- replaceAllTypeSynonyms ty1
703− ty' <- replaceAllTypeSynonyms ty
704− v' <- subsumes (Just v) repl ty'
705− case v' of
706− Nothing -> throwError "Unable to check type subsumption"
707− Just v'' -> return v''
708−check' (TypedValue checkType val ty1) ty2 = do
709− Just moduleName <- checkCurrentModule <$> get
710− kind <- liftCheck $ kindOf moduleName ty1
711− guardWith ("Expected type of kind *, was " ++ prettyPrintKind kind) $ kind == Star
712− val' <- subsumes (Just val) ty1 ty2
713− case val' of
714− Nothing -> throwError "Unable to check type subsumption"
715− Just val'' -> do
716− val''' <- if checkType then check val'' ty1 else return val''
717− return $ TypedValue True val''' ty1
718−check' (Case vals binders) ret = do
719− vals' <- mapM infer vals
720− let ts = map (\(TypedValue _ _ t) -> t) vals'
721− binders' <- checkBinders ts ret binders
722− return $ Case vals' binders'
723−check' (IfThenElse cond th el) ty = do
724− cond' <- check cond tyBoolean
725− th' <- check th ty
726− el' <- check el ty
727− return $ IfThenElse cond' th' el'
728−check' (ObjectLiteral ps) (Object row) = do
729− ensureNoDuplicateProperties ps
730− ps' <- checkProperties ps row False
731− return $ ObjectLiteral ps'
732−check' (ObjectUpdate obj ps) (Object row) = do
733− ensureNoDuplicateProperties ps
734− us <- zip (map fst ps) <$> replicateM (length ps) fresh
735− let (propsToCheck, rest) = rowToList row
736− propsToRemove = map fst ps
737− remainingProps = filter (\(p, _) -> p `notElem` propsToRemove) propsToCheck
738− obj' <- check obj (Object (rowFromList (us ++ remainingProps, rest)))
739− ps' <- checkProperties ps row True
740− return $ ObjectUpdate obj' ps'
741−check' (Accessor prop val) ty = do
742− rest <- fresh
743− val' <- check val (Object (RCons prop ty rest))
744− return $ Accessor prop val'
745−check' (Block ss) ret = do
746− (allCodePathsReturn, _, ss') <- checkBlock M.empty ret ss
747− guardWith "Block is missing a return statement" allCodePathsReturn
748− return $ Block ss'
749−check' (Constructor c) ty = do
750− env <- getEnv
751− Just moduleName <- checkCurrentModule <$> get
752− case M.lookup (qualify moduleName c) (dataConstructors env) of
753− Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"
754− Just (ty1, _) -> do
755− repl <- replaceAllTypeSynonyms ty1
756− _ <- subsumes Nothing repl ty
757− return $ Constructor c
758−check' val (SaturatedTypeSynonym name args) = do
759− ty <- expandTypeSynonym name args
760− check val ty
761−check' val ty = throwError $ prettyPrintValue val ++ " does not have type " ++ prettyPrintType ty
762−
763−-- |
764−-- Check the type of a collection of named record fields
765−--
766−-- The @lax@ parameter controls whether or not every record member has to be provided. For object updates, this is not the case.
767−--
768−checkProperties :: [(String, Value)] -> Type -> Bool -> UnifyT Check [(String, Value)]
769−checkProperties ps row lax = let (ts, r') = rowToList row in go ps ts r' where
770− go [] [] REmpty = return []
771− go [] [] u@(TUnknown _) = do u ?= REmpty
772− return []
773− go [] [] (Skolem _) | lax = return []
774− go [] ((p, _): _) _ | lax = return []
775− | otherwise = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have property " ++ p
776− go ((p,_):_) [] REmpty = throwError $ "Property " ++ p ++ " is not present in closed object type " ++ prettyPrintRow row
777− go ((p,v):ps') [] u@(TUnknown _) = do
778− v'@(TypedValue _ _ ty) <- infer v
779− rest <- fresh
780− u ?= RCons p ty rest
781− ps'' <- go ps' [] rest
782− return $ (p, v') : ps''
783− go ((p,v):ps') ts r =
784− case lookup p ts of
785− Nothing -> do
786− v'@(TypedValue _ _ ty) <- infer v
787− rest <- fresh
788− r ?= RCons p ty rest
789− ps'' <- go ps' ts rest
790− return $ (p, v') : ps''
791− Just ty -> do
792− v' <- check v ty
793− ps'' <- go ps' (delete (p, ty) ts) r
794− return $ (p, v') : ps''
795− go _ _ _ = throwError $ prettyPrintValue (ObjectLiteral ps) ++ " does not have type " ++ prettyPrintType (Object row)
796−
797−-- |
798−-- Check the type of a function application, rethrowing errors to provide a better error message
799−--
800−checkFunctionApplication :: Value -> Type -> Value -> Type -> UnifyT Check Value
801−checkFunctionApplication fn fnTy arg ret = rethrow errorMessage $ checkFunctionApplication' fn fnTy arg ret
802− where
803− errorMessage msg = "Error applying function of type "
804− ++ prettyPrintType fnTy
805− ++ " to argument " ++ prettyPrintValue arg
806− ++ ":\n" ++ msg
807−
808−-- |
809−-- Check the type of a function application
810−--
811−checkFunctionApplication' :: Value -> Type -> Value -> Type -> UnifyT Check Value
812−checkFunctionApplication' fn (TypeApp (TypeApp tyFunction' argTy) retTy) arg ret = do
813− tyFunction' ?= tyFunction
814− arg' <- check arg argTy
815− _ <- subsumes Nothing retTy ret
816− return $ App fn arg'
817−checkFunctionApplication' fn (ForAll ident ty) arg ret = do
818− replaced <- replaceVarWithUnknown ident ty
819− checkFunctionApplication fn replaced arg ret
820−checkFunctionApplication' fn u@(TUnknown _) arg ret = do
821− arg' <- do
822− TypedValue _ v t <- infer arg
823− TypedValue True v <$> replaceAllVarsWithUnknowns t
824− let ty = (\(TypedValue _ _ t) -> t) arg'
825− u ?= function ty ret
826− return $ App fn arg'
827−checkFunctionApplication' fn (SaturatedTypeSynonym name tyArgs) arg ret = do
828− ty <- expandTypeSynonym name tyArgs
829− checkFunctionApplication fn ty arg ret
830−checkFunctionApplication' fn (ConstrainedType constraints fnTy) arg ret = do
831− env <- getEnv
832− dicts <- getTypeClassDictionaries
833− Just moduleName <- checkCurrentModule <$> get
834− checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) fnTy arg ret
835−checkFunctionApplication' _ fnTy arg ret = throwError $ "Applying a function of type "
836− ++ prettyPrintType fnTy
837− ++ " to argument(s) " ++ prettyPrintValue arg
838− ++ " does not yield a value of type " ++ prettyPrintType ret ++ "."
839−
840−-- |
841−-- Check whether one type subsumes another, rethrowing errors to provide a better error message
842−--
843−subsumes :: Maybe Value -> Type -> Type -> UnifyT Check (Maybe Value)
844−subsumes val ty1 ty2 = rethrow errorMessage $ subsumes' val ty1 ty2
845− where
846− errorMessage msg = "Error checking that type "
847− ++ prettyPrintType ty1
848− ++ " subsumes type "
849− ++ prettyPrintType ty2
850− ++ ":\n" ++ msg
851−
852−-- |
853−-- Check whether one type subsumes another
854−--
855−subsumes' :: Maybe Value -> Type -> Type -> UnifyT Check (Maybe Value)
856−subsumes' val (ForAll ident ty1) ty2 = do
857− replaced <- replaceVarWithUnknown ident ty1
858− subsumes val replaced ty2
859−subsumes' val (TypeApp (TypeApp f1 arg1) ret1) (TypeApp (TypeApp f2 arg2) ret2) | f1 == tyFunction && f2 == tyFunction = do
860− subsumes Nothing arg2 arg1
861− subsumes Nothing ret1 ret2
862− return val
863−subsumes' val (SaturatedTypeSynonym name tyArgs) ty2 = do
864− ty1 <- expandTypeSynonym name tyArgs
865− subsumes val ty1 ty2
866−subsumes' val ty1 (SaturatedTypeSynonym name tyArgs) = do
867− ty2 <- expandTypeSynonym name tyArgs
868− subsumes val ty1 ty2
869−subsumes' (Just val) (ConstrainedType constraints ty1) ty2 = do
870− env <- getEnv
871− dicts <- getTypeClassDictionaries
872− Just moduleName <- checkCurrentModule <$> get
873− _ <- subsumes' Nothing ty1 ty2
874− return . Just $ foldl App val (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))
875−subsumes' val ty1 ty2 = do
876− ty1 ?= ty2
877− return val
878−
src/Language/PureScript/Types.hsdeleted−155
@@ -1,155 +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.Generics (mkT, mkQ, everywhereBut)
22−
23−import Control.Monad.Unify
24−
25−import Language.PureScript.Names
26−
27−-- |
28−-- The type of types
29−--
30−data Type
31− -- |
32− -- A unification variable of type Type
33− --
34− = TUnknown (TypedUnknown Type)
35− -- |
36− -- Javascript numbers
37− --
38− | Object Type
39− -- |
40− -- A named type variable
41− --
42− | TypeVar String
43− -- |
44− -- A type constructor
45− --
46− | TypeConstructor (Qualified ProperName)
47− -- |
48− -- A type application
49− --
50− | TypeApp Type Type
51− -- |
52− -- A type synonym which is \"saturated\", i.e. fully applied
53− --
54− | SaturatedTypeSynonym (Qualified ProperName) [Type]
55− -- |
56− -- Forall quantifier
57− --
58− | ForAll String Type
59− -- |
60− -- A type with a set of type class constraints
61− --
62− | ConstrainedType [(Qualified ProperName, Type)] Type
63− -- |
64− -- A skolem constant
65− --
66− | Skolem Int
67− -- |
68− -- An empty row
69− --
70− | REmpty
71− -- |
72− -- A non-empty row
73− --
74− | RCons String Type Type deriving (Show, Eq, Data, Typeable)
75−
76−-- |
77−-- Type constructor for functions
78−--
79−tyFunction :: Type
80−tyFunction = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Function")
81−
82−-- |
83−-- Type constructor for strings
84−--
85−tyString :: Type
86−tyString = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "String")
87−
88−-- |
89−-- Type constructor for numbers
90−--
91−tyNumber :: Type
92−tyNumber = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Number")
93−
94−-- |
95−-- Type constructor for booleans
96−--
97−tyBoolean :: Type
98−tyBoolean = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Boolean")
99−
100−-- |
101−-- Type constructor for arrays
102−--
103−tyArray :: Type
104−tyArray = TypeConstructor $ (Qualified $ Just $ ModuleName $ ProperName "Prelude") (ProperName "Array")
105−
106−-- |
107−-- Smart constructor for function types
108−--
109−function :: Type -> Type -> Type
110−function t1 t2 = TypeApp (TypeApp tyFunction t1) t2
111−
112−-- |
113−-- Convert a row to a list of pairs of labels and types
114−--
115−rowToList :: Type -> ([(String, Type)], Type)
116−rowToList (RCons name ty row) = let (tys, rest) = rowToList row
117− in ((name, ty):tys, rest)
118−rowToList r = ([], r)
119−
120−-- |
121−-- Convert a list of labels and types to a row
122−--
123−rowFromList :: ([(String, Type)], Type) -> Type
124−rowFromList ([], r) = r
125−rowFromList ((name, t):ts, r) = RCons name t (rowFromList (ts, r))
126−
127−-- |
128−-- Check whether a type is a monotype
129−--
130−isMonoType :: Type -> Bool
131−isMonoType (ForAll _ _) = False
132−isMonoType ty = True
133−
134−-- |
135−-- Universally quantify a type
136−--
137−mkForAll :: [String] -> Type -> Type
138−mkForAll = flip . foldl . flip $ ForAll
139−
140−-- |
141−-- The empty record type
142−--
143−unit :: Type
144−unit = Object REmpty
145−
146−-- |
147−-- Replace a type variable, taking into account variable shadowing
148−--
149−replaceTypeVars :: (Data d) => String -> Type -> d -> d
150−replaceTypeVars name t = everywhereBut (mkQ False isShadowed) (mkT replaceTypeVar)
151− where
152− replaceTypeVar (TypeVar v) | v == name = t
153− replaceTypeVar other = other
154− isShadowed (ForAll v _) | v == name = True
155− isShadowed _ = False
src/Language/PureScript/Values.hsdeleted−272
@@ -1,272 +0,0 @@
1−-----------------------------------------------------------------------------
2−--
3−-- Module : Language.PureScript.Values
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 values, statements, binders and do notation
13−--
14−-----------------------------------------------------------------------------
15−
16−{-# LANGUAGE DeriveDataTypeable #-}
17−
18−module Language.PureScript.Values where
19−
20−import Language.PureScript.Types
21−import Language.PureScript.Names
22−
23−import Data.Data
24−
25−-- |
26−-- A guard is just a boolean-valued expression that appears alongside a set of binders
27−--
28−type Guard = Value
29−
30−-- |
31−-- Data type for values
32−--
33−data Value
34− -- |
35− -- A numeric literal
36− --
37− = NumericLiteral (Either Integer Double)
38− -- |
39− -- A string literal
40− --
41− | StringLiteral String
42− -- |
43− -- A boolean literal
44− --
45− | BooleanLiteral Bool
46− -- |
47− -- Binary operator application. During the rebracketing phase of desugaring, this data constructor
48− -- will be removed.
49− --
50− | BinaryNoParens (Qualified Ident) Value Value
51− -- |
52− -- Explicit parentheses. During the rebracketing phase of desugaring, this data constructor
53− -- will be removed.
54− --
55− | Parens Value
56− -- |
57− -- An array literal
58− --
59− | ArrayLiteral [Value]
60− -- |
61− -- An object literal
62− --
63− | ObjectLiteral [(String, Value)]
64− -- |
65− -- An record property accessor expression
66− --
67− | Accessor String Value
68− -- |
69− -- Partial record update
70− --
71− | ObjectUpdate Value [(String, Value)]
72− -- |
73− -- Function introduction
74− --
75− | Abs Ident Value
76− -- |
77− -- Function application
78− --
79− | App Value Value
80− -- |
81− -- Variable
82− --
83− | Var (Qualified Ident)
84− -- |
85− -- Conditional (if-then-else expression)
86− --
87− | IfThenElse Value Value Value
88− -- |
89− -- A \"Block\" i.e. a collection of statements which evaluate to a value
90− --
91− | Block [Statement]
92− -- |
93− -- A data constructor
94− --
95− | Constructor (Qualified ProperName)
96− -- |
97− -- A case expression. During the case expansion phase of desugaring, top-level binders will get
98− -- desugared into case expressions, hence the need for guards and multiple binders per branch here.
99− --
100− | Case [Value] [([Binder], Maybe Guard, Value)]
101− -- |
102− -- A value with a type annotation
103− --
104− | TypedValue Bool Value Type
105− -- |
106− -- A do-notation block
107− --
108− | Do [DoNotationElement]
109− -- |
110− -- A placeholder for a type class dictionary to be inserted later. At the end of type checking, these
111− -- placeholders will be replaced with actual expressions representing type classes dictionaries which
112− -- can be evaluated at runtime. The constructor arguments represent (in order): the type class name and
113− -- instance type, and the type class dictionaries in scope.
114− --
115− | TypeClassDictionary (Qualified ProperName, Type) [TypeClassDictionaryInScope] deriving (Show, Data, Typeable)
116−
117−-- |
118−-- The type of a type class dictionary
119−--
120−data TypeClassDictionaryType
121− -- |
122− -- A regular type class dictionary
123− --
124− = TCDRegular
125− -- |
126− -- A type class dictionary which is an alias for an imported dictionary from another module
127− --
128− | TCDAlias (Qualified Ident) deriving (Show, Eq, Data, Typeable)
129−
130−-- |
131−-- Data representing a type class dictionary which is in scope
132−--
133−data TypeClassDictionaryInScope
134− = TypeClassDictionaryInScope {
135− -- |
136− -- The identifier with which the dictionary can be accessed at runtime
137− --
138− tcdName :: Qualified Ident
139− -- |
140− -- The name of the type class to which this type class instance applies
141− --
142− , tcdClassName :: Qualified ProperName
143− -- |
144− -- The type to which this type class instance applies
145− --
146− , tcdInstanceType :: Type
147− -- |
148− -- Type class dependencies which must be satisfied to construct this dictionary
149− --
150− , tcdDependencies :: Maybe [(Qualified ProperName, Type)]
151− -- |
152− -- The type of this dictionary
153− --
154− , tcdType :: TypeClassDictionaryType
155− } deriving (Show, Data, Typeable)
156−
157−-- |
158−-- A statement in a do-notation block
159−--
160−data DoNotationElement
161− -- |
162− -- A monadic value without a binder
163− --
164− = DoNotationValue Value
165− -- |
166− -- A monadic value with a binder
167− --
168− | DoNotationBind Binder Value
169− -- |
170− -- A let statement, i.e. a pure value with a binder
171− --
172− | DoNotationLet Binder Value deriving (Show, Data, Typeable)
173−
174−-- |
175−-- Data type for statements which can appear inside a @Block@ expression
176−--
177−data Statement
178− -- |
179− -- A variable introduction and initial assignment
180− --
181− = VariableIntroduction Ident Value
182− -- |
183− -- A variable reassignment
184− --
185− | Assignment Ident Value
186− -- |
187− -- A while loop
188− --
189− | While Value [Statement]
190− -- |
191− -- A for loop
192− --
193− | For Ident Value Value [Statement]
194− -- |
195− -- An if-then-else statement
196− --
197− | If IfStatement
198− -- |
199− -- A return statement
200− --
201− | Return Value deriving (Show, Data, Typeable)
202−
203−-- |
204−-- Data type for if-statements
205−--
206−data IfStatement
207− -- |
208− -- An if statement. Arguments are (in order): boolean condition, true branch, optional else branch.
209− --
210− = IfStatement Value [Statement] (Maybe ElseStatement) deriving (Show, Data, Typeable)
211−
212−-- |
213−-- Data type for the else branch in an if-statement
214−--
215−data ElseStatement
216− -- |
217− -- An else branch
218− --
219− = Else [Statement]
220− -- |
221− -- An else-if branch
222− --
223− | ElseIf IfStatement deriving (Show, Data, Typeable)
224−
225−-- |
226−-- Data type for binders
227−--
228−data Binder
229− -- |
230− -- Wildcard binder
231− --
232− = NullBinder
233− -- |
234− -- A binder which matches a boolean literal
235− --
236− | BooleanBinder Bool
237− -- |
238− -- A binder which matches a string literal
239− --
240− | StringBinder String
241− -- |
242− -- A binder which matches a numeric literal
243− --
244− | NumberBinder (Either Integer Double)
245− -- |
246− -- A binder which binds an identifier
247− --
248− | VarBinder Ident
249− -- |
250− -- A binder which matches a data constructor with no argument
251− --
252− | NullaryBinder (Qualified ProperName)
253− -- |
254− -- A binder which matches a data constructor with one argument
255− --
256− | UnaryBinder (Qualified ProperName) Binder
257− -- |
258− -- A binder which matches a record and binds its properties
259− --
260− | ObjectBinder [(String, Binder)]
261− -- |
262− -- A binder which matches an array and binds its elements
263− --
264− | ArrayBinder [Binder]
265− -- |
266− -- A binder which matches an array and binds its head and tail
267− --
268− | ConsBinder Binder Binder
269− -- |
270− -- A binder which binds its input to an identifier
271− --
272− | NamedBinder Ident Binder deriving (Show, Data, Typeable)
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−106
@@ -1,106 +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.Applicative
24−import Control.Monad
25−import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)
26−import System.Exit
27−import System.Process
28−import System.FilePath (pathSeparator)
29−import System.Directory (getCurrentDirectory, getDirectoryContents, findExecutable)
30−import System.Environment (getArgs)
31−import Text.Parsec (ParseError)
32−import qualified Paths_purescript as Paths
33−import qualified System.IO.UTF8 as U
34−import qualified Data.Map as M
35−
36−preludeFilename :: IO FilePath
37−preludeFilename = Paths.getDataFileName "libraries/prelude/prelude.purs"
38−
39−readInput :: [FilePath] -> IO (Either ParseError [P.Module])
40−readInput inputFiles = fmap (fmap concat . sequence) $ forM inputFiles $ \inputFile -> do
41− text <- U.readFile inputFile
42− return $ P.runIndentParser P.parseModules text
43−
44−compile :: P.Options -> [FilePath] -> IO (Either String String)
45−compile opts inputFiles = do
46− modules <- readInput inputFiles
47− case modules of
48− Left parseError -> do
49− return (Left $ show parseError)
50− Right ms -> do
51− case P.compile opts ms of
52− Left typeError -> do
53− return (Left typeError)
54− Right (js, _, _) -> do
55− return (Right js)
56−
57−assert :: P.Options -> [FilePath] -> (Either String String -> IO (Maybe String)) -> IO ()
58−assert opts inputFiles f = do
59− e <- compile opts inputFiles
60− maybeErr <- f e
61− case maybeErr of
62− Just err -> putStrLn err >> exitFailure
63− Nothing -> return ()
64−
65−assertCompiles :: FilePath -> IO ()
66−assertCompiles inputFile = do
67− putStrLn $ "assert " ++ inputFile ++ " compiles successfully"
68− prelude <- preludeFilename
69− assert (P.defaultOptions { P.optionsRunMain = True, P.optionsNoOptimizations = True }) [prelude, inputFile] $ either (return . Just) $ \js -> do
70− args <- getArgs
71− if "--run-js" `elem` args
72− then do
73− process <- findNodeProcess
74− result <- traverse (\node -> readProcessWithExitCode node [] js) process
75− case result of
76− Just (ExitSuccess, out, _) -> putStrLn out >> return Nothing
77− Just (ExitFailure _, _, err) -> return $ Just err
78− Nothing -> return $ Just "Couldn't find node.js executable"
79− else return Nothing
80−
81−findNodeProcess :: IO (Maybe String)
82−findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names
83− where names = ["nodejs", "node"]
84−
85−assertDoesNotCompile :: FilePath -> IO ()
86−assertDoesNotCompile inputFile = do
87− putStrLn $ "assert " ++ inputFile ++ " does not compile"
88− assert P.defaultOptions [inputFile] $ \e ->
89− case e of
90− Left _ -> return Nothing
91− Right _ -> return $ Just "Should not have compiled"
92−
93−main :: IO ()
94−main = do
95− cd <- getCurrentDirectory
96− putStrLn $ cd
97− let examples = cd ++ pathSeparator : "examples"
98− let passing = examples ++ pathSeparator : "passing"
99− passingTestCases <- getDirectoryContents passing
100− forM_ passingTestCases $ \inputFile -> when (".purs" `isSuffixOf` inputFile) $
101− assertCompiles (passing ++ pathSeparator : inputFile)
102− let failing = examples ++ pathSeparator : "failing"
103− failingTestCases <- getDirectoryContents failing
104− forM_ failingTestCases $ \inputFile -> when (".purs" `isSuffixOf` inputFile) $
105− assertDoesNotCompile (failing ++ pathSeparator : inputFile)
106− exitSuccess