packages feed

purescript 0.6.9.4 → 0.6.9.5

raw patch · 43 files changed

+1502/−2340 lines, 43 filesdep −HUnitdep ~basedep ~directorydep ~mtlPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies removed: HUnit

Dependency ranges changed: base, directory, mtl, transformers

API changes (from Hackage documentation)

- Language.PureScript.AST.SourcePos: displaySourcePos :: SourcePos -> String
- Language.PureScript.AST.SourcePos: displaySourceSpan :: SourceSpan -> String
- Language.PureScript.Constants: bottom :: String
- Language.PureScript.Constants: boundedBoolean :: String
- Language.PureScript.Constants: complementedLatticeBoolean :: String
- Language.PureScript.Constants: dataInt :: String
- Language.PureScript.Constants: dataIntBits :: String
- Language.PureScript.Constants: eqInt :: String
- Language.PureScript.Constants: fromNumber :: String
- Language.PureScript.Constants: inf :: String
- Language.PureScript.Constants: latticeBoolean :: String
- Language.PureScript.Constants: mod :: String
- Language.PureScript.Constants: moduloSemiringInt :: String
- Language.PureScript.Constants: ordInt :: String
- Language.PureScript.Constants: ringInt :: String
- Language.PureScript.Constants: semiringInt :: String
- Language.PureScript.Constants: sup :: String
- Language.PureScript.Constants: top :: String
- Language.PureScript.Errors: CannotGetFileInfo :: FilePath -> ErrorMessage
- Language.PureScript.Errors: CannotReadFile :: FilePath -> ErrorMessage
- Language.PureScript.Errors: CannotWriteFile :: FilePath -> ErrorMessage
- Language.PureScript.Errors: CycleInModules :: [ModuleName] -> ErrorMessage
- Language.PureScript.Errors: ErrorParsingExterns :: ParseError -> ErrorMessage
- Language.PureScript.Errors: ErrorParsingPrelude :: ParseError -> ErrorMessage
- Language.PureScript.Errors: InvalidExternsFile :: FilePath -> ErrorMessage
- Language.PureScript.TypeChecker.Monad: preservingNames :: (Functor m, MonadState CheckState m) => m a -> m a
- Language.PureScript.TypeChecker.Monad: withBindingGroupVisible :: (Functor m, MonadState CheckState m) => m a -> m a
+ Language.PureScript.Constants: bitsNumber :: String
+ Language.PureScript.Constants: boolLikeBoolean :: String
+ Language.PureScript.Constants: numNumber :: String
- Language.PureScript: class (MonadReader (Options Make) m, MonadError MultipleErrors m) => MonadMake m
+ Language.PureScript: class (MonadReader (Options Make) m, MonadError String m) => MonadMake m
- Language.PureScript: compile :: (Functor m, Applicative m, MonadError MultipleErrors m, MonadReader (Options Compile) m) => [Module] -> [String] -> m (String, String, Environment)
+ Language.PureScript: compile :: (Functor m, Applicative m, MonadError String m, MonadReader (Options Compile) m) => [Module] -> [String] -> m (String, String, Environment)
- Language.PureScript: compile' :: (Functor m, Applicative m, MonadError MultipleErrors m, MonadReader (Options Compile) m) => Environment -> [Module] -> [String] -> m (String, String, Environment)
+ Language.PureScript: compile' :: (Functor m, Applicative m, MonadError String m, MonadReader (Options Compile) m) => Environment -> [Module] -> [String] -> m (String, String, Environment)
- Language.PureScript.AST.Declarations: exportedDctors :: Module -> ProperName -> [(ProperName, [Type])]
+ Language.PureScript.AST.Declarations: exportedDctors :: Module -> ProperName -> [ProperName]
- Language.PureScript.Errors: interpretMultipleErrors :: MonadError MultipleErrors m => Either MultipleErrors a -> m a
+ Language.PureScript.Errors: interpretMultipleErrors :: MonadError String m => Bool -> Either MultipleErrors a -> m a
- Language.PureScript.ModuleDependencies: sortModules :: MonadError MultipleErrors m => [Module] -> m ([Module], ModuleGraph)
+ Language.PureScript.ModuleDependencies: sortModules :: MonadError String m => [Module] -> m ([Module], ModuleGraph)
- Language.PureScript.TypeChecker.Monad: makeBindingGroupVisible :: (Functor m, MonadState CheckState m) => m ()
+ Language.PureScript.TypeChecker.Monad: makeBindingGroupVisible :: (Functor m, MonadState CheckState m) => m a -> m a
- Language.PureScript.TypeChecker.Monad: runCheck :: MonadError MultipleErrors m => Check a -> m (a, Environment)
+ Language.PureScript.TypeChecker.Monad: runCheck :: (MonadReader (Options mode) m, MonadError String m) => Check a -> m (a, Environment)
- Language.PureScript.TypeChecker.Monad: runCheck' :: MonadError MultipleErrors m => Environment -> Check a -> m (a, Environment)
+ Language.PureScript.TypeChecker.Monad: runCheck' :: (MonadReader (Options mode) m, MonadError String m) => Environment -> Check a -> m (a, Environment)

Files

− examples/failing/365.purs
@@ -1,11 +0,0 @@-module Main where--class C a where-  f :: a -> a-  g :: a -> a--instance cS :: C String where-  f s = s-  g = f--main = g "Done"
− examples/failing/RowConstructors1.purs
@@ -1,6 +0,0 @@-module Main where--data Foo = Bar-type Baz = { | Foo }--main = Debug.Trace.trace "Done"
− examples/failing/RowConstructors2.purs
@@ -1,6 +0,0 @@-module Main where--type Foo r = (x :: Number | r)-type Bar = { | Foo }--main = Debug.Trace.trace "Done"
− examples/failing/RowConstructors3.purs
@@ -1,6 +0,0 @@-module Main where--type Foo = { x :: Number }-type Bar = { | Foo }--main = Debug.Trace.trace "Done"
− examples/failing/TypeSynonyms5.purs
@@ -1,3 +0,0 @@-module Main where--type T = T
examples/passing/Collatz.purs view
@@ -1,19 +1,8 @@ module Main where +import Prelude import Control.Monad.Eff import Control.Monad.ST--foreign import jsMod-  """-  function jsMod(x) {-    return function (y) {-      return x % y;-    };-  }-  """ :: Number -> Number -> Number--infixl 7 %-(%) = jsMod  collatz :: Number -> Number collatz n = runPure (runST (do
examples/passing/Guards.purs view
@@ -1,39 +1,29 @@ module Main where -foreign import jsMod-  """-  function jsMod(x) {-    return function (y) {-      return x % y;-    };-  }-  """ :: Number -> Number -> Number--infixl 7 %-(%) = jsMod+  import Prelude -collatz = \x -> case x of-  y | y % 2 == 0 -> y / 2-  y -> y * 3 + 1+  collatz = \x -> case x of+    y | y % 2 == 0 -> y / 2+    y -> y * 3 + 1 --- Guards have access to current scope-collatz2 = \x y -> case x of-  z | y > 0 -> z / 2-  z -> z * 3 + 1+  -- Guards have access to current scope+  collatz2 = \x y -> case x of+    z | y > 0 -> z / 2+    z -> z * 3 + 1 -min :: forall a. (Ord a) => a -> a -> a-min n m | n < m     = n-        | otherwise = m+  min :: forall a. (Ord a) => a -> a -> a+  min n m | n < m     = n+          | otherwise = m -max :: forall a. (Ord a) => a -> a -> a-max n m = case unit of-  _ | m < n     -> n-    | otherwise -> m+  max :: forall a. (Ord a) => a -> a -> a+  max n m = case unit of+    _ | m < n     -> n+      | otherwise -> m -testIndentation :: Number -> Number -> Number-testIndentation x y | x > 0-  = x + y-                    | otherwise-  = y - x+  testIndentation :: Number -> Number -> Number+  testIndentation x y | x > 0+    = x + y+                      | otherwise+    = y - x -main = Debug.Trace.trace $ min "Done" "ZZZZ"+  main = Debug.Trace.trace $ min "Done" "ZZZZ"
− examples/passing/Let2.purs
@@ -1,15 +0,0 @@-module Main where--test = -  let f :: Number -> Boolean-      f 0 = false-      f n = g (n - 1)--      g :: Number -> Boolean-      g 0 = true-      g n = f (n - 1)--      x = f 1-  in not x--main = Debug.Trace.print test
examples/passing/OperatorAssociativity.purs view
@@ -35,13 +35,21 @@     assert (6 / (3 * 2) == 1)   "6 / (3 * 2) == 1"     assert ((6 / 3) * 2 == 4)   "(6 / 3) * 2 == 4" +    assert (6 % (2 * 2) == 2)   "6 % (2 * 2) == 2"+    assert ((6 % 2) * 2 == 0)   "(6 % 2) * 2 == 0"++    assert (4 % (9 / 3) == 1)   "4 % (9 / 3) == 1"+    assert ((4 % 9) / 2 == 2)   "(4 % 9) / 2 == 2"+     assert (not (1 < 0) == true) "not (1 < 0) == true"+    assert (not (complement (1 + 10) == 8) == true) "not (complement (1 + 10) == 8) == true"     assert (not ((negate 1) < 0) == false) "not ((negate 1) < 0) == false"      assert (negate (1 + 10) == -11) "negate (1 + 10) == -11"      assert (2 * 3 / 4 == 1.5) "2 * 3 / 4 == 1.5"     assert (1 * 2 * 3 * 4 * 5 / 6 == 20) "1 * 2 * 3 * 4 * 5 / 6 == 20"+    assert (complement (2 / 3 * 4) == -3) "complement (2 / 3 * 4) == -3"      assert (1 + 10 - 5 == 6) "1 + 10 - 5 == 6"     assert (1 + 10 * 5 == 51) "1 + 10 * 5 == 51"
− examples/passing/OperatorInlining.purs
@@ -1,46 +0,0 @@-module Main where--import Debug.Trace--main = do--  -- semiringNumber-  print (1 + 2)-  print (1 * 2)--  -- ringNumber-  print (1 - 2)-  print (negate 1)--  -- moduleSemiringNumber-  print (1 / 2)--  -- ordNumber-  print (1 > 2)-  print (1 < 2)-  print (1 <= 2)-  print (1 >= 2)-  print (1 == 2)--  -- eqNumber-  print (1 == 2)-  print (1 /= 2)--  -- eqString-  print ("foo" == "bar")-  print ("foo" /= "bar")--  -- eqBoolean-  print (true == false)-  print (true /= false)--  -- semigroupString-  print ("foo" ++ "bar")-  print ("foo" <> "bar")--  -- latticeBoolean-  print (top && true)-  print (bottom || false)--  -- complementedLatticeBoolean-  print (not true)
examples/passing/Operators.purs view
@@ -61,6 +61,9 @@   test15 :: Number -> Number -> Boolean   test15 a b = const false $ a `test14` b +  test16 :: Number -> Number -> Number+  test16 x y = x .|. y .&. y+   test17 :: Number   test17 = negate (-1) @@ -91,6 +94,7 @@     let t13 = test13 k 1 2     let t14 = test14 1 2     let t15 = test15 1 2+    let t16 = test16 1 2     let t17 = test17     let t18 = test18     let t19 = test19
− examples/passing/RebindableSyntax.purs
@@ -1,37 +0,0 @@-module Main where--example1 :: String-example1 = do-  "Do"-  " notation"-  " for"-  " Semigroup"-  where-  (>>=) x f = x <> f unit--(*>) :: forall f a b. (Apply f) => f a -> f b -> f b-(*>) fa fb = const id <$> fa <*> fb--newtype Const a b = Const a--runConst :: forall a b. Const a b -> a-runConst (Const a) = a--instance functorConst :: Functor (Const a) where-  (<$>) _ (Const a) = Const a--instance applyConst :: (Semigroup a) => Apply (Const a) where-  (<*>) (Const a1) (Const a2) = Const (a1 <> a2)--example2 :: Const String Unit-example2 = do-  Const "Do"-  Const " notation"-  Const " for"-  Const " Apply"-  where-  (>>=) x f = x *> f unit--main = do-  Debug.Trace.trace example1-  Debug.Trace.trace $ runConst example2
− examples/passing/RowConstructors.purs
@@ -1,40 +0,0 @@-module Main where--type Foo = (x :: Number | (y :: Number | (z :: Number)))-type Bar = (x :: Number, y :: Number, z :: Number)-type Baz = { w :: Number | Bar }--foo :: { | Foo }-foo = { x: 0, y: 0, z: 0 }--bar :: { | Bar }-bar = { x: 0, y: 0, z: 0 }--id' :: Object Foo -> Object Bar-id' = id--foo' :: { | Foo }-foo' = id' foo--bar' :: { | Bar }-bar' = id' bar--baz :: Baz-baz = { x: 0, y: 0, z: 0, w: 0 }--type Quux r = (q :: Number | r)-type Norf r = (q' :: Number | Quux r)--quux :: { f :: { | Foo } | Quux Bar }-quux = { f: foo', x: 0, y: 0, z: 0, q: 0 }--quux' :: { | Norf Bar }-quux' = { x: 0, y: 0, z: 0, q: 0, q': 0 }--wildcard :: { w :: Number | _ } -> Baz-wildcard { w: w } = { x: w, y: w, z: w, w: w }--wildcard' :: { | Quux _ } -> Number-wildcard' { q: q } = q--main = Debug.Trace.trace "Done"
examples/passing/TopLevelCase.purs view
@@ -1,28 +1,18 @@ module Main where -foreign import jsMod-  """-  function jsMod(x) {-    return function (y) {-      return x % y;-    };-  }-  """ :: Number -> Number -> Number--infixl 7 %-(%) = jsMod+  import Prelude -gcd :: Number -> Number -> Number-gcd 0 x = x-gcd x 0 = x-gcd x y | x > y = gcd (x % y) y-gcd x y = gcd (y % x) x+  gcd :: Number -> Number -> Number+  gcd 0 x = x+  gcd x 0 = x+  gcd x y | x > y = gcd (x % y) y+  gcd x y = gcd (y % x) x -guardsTest (x:xs) | x > 0 = guardsTest xs-guardsTest xs = xs+  guardsTest (x:xs) | x > 0 = guardsTest xs+  guardsTest xs = xs -data A = A+  data A = A -parseTest A 0 = 0+  parseTest A 0 = 0 -main = Debug.Trace.trace "Done"+  main = Debug.Trace.trace "Done"
prelude/prelude.purs view
@@ -1,89 +1,50 @@ module Prelude-  ( Unit(..), unit-  , ($), (#)+  ( otherwise   , flip   , const   , asTypeOf-  , otherwise-  , (:), cons   , Semigroupoid, (<<<), (>>>)   , Category, id+  , ($), (#)+  , (:), cons+  , Show, show   , Functor, (<$>), (<#>), void   , Apply, (<*>)   , Applicative, pure, liftA1   , Bind, (>>=)   , Monad, return, liftM1, ap-  , Semigroup, (<>), (++)   , Semiring, (+), zero, (*), one   , ModuloSemiring, (/), mod-  , Ring, (-), negate-  , Num+  , Ring, (-)+  , (%)+  , negate   , DivisionRing+  , Num   , Eq, (==), (/=)-  , Ordering(..), Ord, compare, (<), (>), (<=), (>=)-  , Bounded, top, bottom-  , Lattice, sup, inf, (||), (&&)-  , BoundedLattice-  , ComplementedLattice, not-  , DistributiveLattice-  , BooleanAlgebra-  , Show, show+  , Ord, Ordering(..), compare, (<), (>), (<=), (>=)+  , Bits, (.&.), (.|.), (.^.), shl, shr, zshr, complement+  , BoolLike, (&&), (||)+  , not+  , Semigroup, (<>), (++)+  , Unit(..), unit   ) where -  -- | The `Unit` type has a single inhabitant, called `unit`. It represents-  -- | values with no computational content.-  -- |-  -- | `Unit` is often used, wrapped in a monadic type constructor, as the-  -- | return type of a computation where only-  -- | the _effects_ are important.-  newtype Unit = Unit {}--  -- | `unit` is the sole inhabitant of the `Unit` type.-  unit :: Unit-  unit = Unit {}--  infixr 0 $-  infixl 0 #--  -- | Applies a function to its argument.-  -- |-  -- | ```purescript-  -- | length $ groupBy productCategory $ filter isInStock $ products-  -- | ```-  -- |-  -- | is equivalent to:-  -- |-  -- | ```purescript-  -- | length (groupBy productCategory (filter isInStock products))-  -- | ```-  -- |-  -- | `($)` is different from [`(#)`](#-2) because it is right-infix instead of-  -- | left: `a $ b $ c $ d x = a $ (b $ (c $ (d $ x))) = a (b (c (d x)))`-  ($) :: forall a b. (a -> b) -> a -> b-  ($) f x = f x--  -- | Applies an argument to a function.-  -- |-  -- | ```purescript-  -- | products # filter isInStock # groupBy productCategory # length-  -- | ```-  -- |-  -- | is equivalent to:+  -- | An alias for `true`, which can be useful in guard clauses:   -- |   -- | ```purescript-  -- | length (groupBy productCategory (filter isInStock products))+  -- | max x y | x >= y = x+  -- |         | otherwise = y   -- | ```   -- |-  -- | `(#)` is different from [`($)`](#-1) because it is left-infix instead of-  -- | right: `x # a # b # c # d = (((x # a) # b) # c) # d = d (c (b (a x)))`-  (#) :: forall a b. a -> (a -> b) -> b-  (#) x f = f x+  otherwise :: Boolean+  otherwise = true    -- | Flips the order of the arguments to a function of two arguments.   -- |   -- | ```purescript   -- | flip const 1 2 = const 2 1 = 2   -- | ```+  -- |   flip :: forall a b c. (a -> b -> c) -> b -> a -> c   flip f b a = f a b @@ -92,30 +53,105 @@   -- | ```purescript   -- | const 1 "hello" = 1   -- | ```+  -- |   const :: forall a b. a -> b -> a   const a _ = a -  -- | This function returns its first argument, and can be used to assert type-  -- | equalities. This can be useful when types are otherwise ambiguous.+  -- | This function returns its first argument, and can be used to assert type equalities.+  -- | This can be useful when types are otherwise ambiguous.   -- |   -- | ```purescript   -- | main = print $ [] `asTypeOf` [0]   -- | ```   -- |-  -- | If instead, we had written `main = print []`, the type of the argument-  -- | `[]` would have been ambiguous, resulting in a compile-time error.+  -- | If instead, we had written `main = print []`, the type of the argument `[]` would have+  -- | been ambiguous, resulting in a compile-time error.   asTypeOf :: forall a. a -> a -> a   asTypeOf x _ = x -  -- | An alias for `true`, which can be useful in guard clauses:+  infixr 9 >>>+  infixr 9 <<<++  -- | A `Semigroupoid` is similar to a [`Category`](#category) but does not require an identity+  -- | element `id`, just composable morphisms.   -- |+  -- | `Semigroupoid`s should obey the following rule:+  -- |+  -- | - Associativity: `p <<< (q <<< r) = (p <<< q) <<< r`+  -- |+  -- | One example of a `Semigroupoid` is the function type constructor `(->)`, with `(<<<)` defined+  -- | as function composition.+  class Semigroupoid a where+    (<<<) :: forall b c d. a c d -> a b c -> a b d++  instance semigroupoidArr :: Semigroupoid (->) where+    (<<<) f g x = f (g x)++  -- | Forwards composition, or `(<<<)` with its arguments reversed.+  (>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d+  (>>>) f g = g <<< f++  -- | `Category`s consist of objects and composable morphisms between them, and as such are+  -- | [`Semigroupoids`](#semigroupoid), but unlike `semigroupoids` must have an identity element.+  -- |+  -- | `Category`s should obey the following rules.+  -- |+  -- | - Left Identity: `id <<< p = p`+  -- | - Right Identity: `p <<< id = p`+  -- |+  class (Semigroupoid a) <= Category a where+    id :: forall t. a t t++  instance categoryArr :: Category (->) where+    id x = x++  infixr 0 $+  infixl 0 #++  -- | Applies a function to its argument+  -- |   -- | ```purescript-  -- | max x y | x >= y    = x-  -- |         | otherwise = y+  -- | length $ groupBy productCategory $ filter isInStock products   -- | ```-  otherwise :: Boolean-  otherwise = true+  -- |+  -- | is equivalent to+  -- |+  -- | ```purescript+  -- | length (groupBy productCategory (filter isInStock (products)))+  -- | ```+  -- |+  -- | `($)` is different from [`(#)`](#-2) because it is right-infix instead of left, so+  -- | `a $ b $ c $ d x` = `a $ (b $ (c $ (d $ x)))` = `a (b (c (d x)))`+  -- |+  ($) :: forall a b. (a -> b) -> a -> b+  ($) f x = f x +  -- | Applies a function to its argument+  -- |+  -- | ```purescript+  -- | products # groupBy productCategory # filter isInStock # length+  -- | ```+  -- |+  -- | is equivalent to+  -- |+  -- | ```purescript+  -- | length (groupBy productCategory (filter isInStock (products)))+  -- | ```+  -- |+  -- | `(#)` is different from [`($)`](#-1) because it is left-infix instead of right, so+  -- | `x # a # b # c # d` = `(((x # a) # b) # c) # d` = `d (c (b (a x)))`+  -- |+  (#) :: forall a b. a -> (a -> b) -> b+  (#) x f = f x++  infixr 6 :++  -- | An infix alias for `cons`.+  -- |+  -- | Note, the running time of this function is `O(n)`.+  (:) :: forall a. a -> [a] -> [a]+  (:) = cons+   -- | Attaches an element to the front of an array, creating a new array.   -- |   -- | ```purescript@@ -132,70 +168,72 @@     }     """ :: forall a. a -> [a] -> [a] -  infixr 6 :--  -- | An infix alias for `cons`.+  -- | The `Show` type class represents those types which can be converted into a human-readable `String` representation.   -- |-  -- | Note, the running time of this function is `O(n)`.-  (:) :: forall a. a -> [a] -> [a]-  (:) = cons+  -- | While not required, it is recommended that for any expression `x`, the string `show x` be executable PureScript code+  -- | which evaluates to the same value as the expression `x`.+  class Show a where+    show :: a -> String -  infixr 9 >>>-  infixr 9 <<<+  foreign import showStringImpl+    """+    function showStringImpl(s) {+      return JSON.stringify(s);+    }+    """ :: String -> String -  -- | A `Semigroupoid` is similar to a [`Category`](#category) but does not-  -- | require an identity element `id`, just composable morphisms.-  -- |-  -- | `Semigroupoid`s must satisfy the following law:-  -- |-  -- | - Associativity: `p <<< (q <<< r) = (p <<< q) <<< r`-  -- |-  -- | One example of a `Semigroupoid` is the function type constructor `(->)`,-  -- | with `(<<<)` defined as function composition.-  class Semigroupoid a where-    (<<<) :: forall b c d. a c d -> a b c -> a b d+  instance showUnit :: Show Unit where+    show (Unit {}) = "Unit {}" -  instance semigroupoidArr :: Semigroupoid (->) where-    (<<<) f g x = f (g x)+  instance showString :: Show String where+    show = showStringImpl -  -- | Forwards composition, or `(<<<)` with its arguments reversed.-  (>>>) :: forall a b c d. (Semigroupoid a) => a b c -> a c d -> a b d-  (>>>) f g = g <<< f+  instance showBoolean :: Show Boolean where+    show true = "true"+    show false = "false" -  -- | `Category`s consist of objects and composable morphisms between them, and-  -- | as such are [`Semigroupoids`](#semigroupoid), but unlike `semigroupoids`-  -- | must have an identity element.-  -- |-  -- | Instances must satisfy the following law in addition to the-  -- | `Semigroupoid` law:-  -- |-  -- | - Identity: `id <<< p = p <<< id = p`-  class (Semigroupoid a) <= Category a where-    id :: forall t. a t t+  foreign import showNumberImpl+    """+    function showNumberImpl(n) {+      return n.toString();+    }+    """ :: Number -> String -  instance categoryArr :: Category (->) where-    id x = x+  instance showNumber :: Show Number where+    show = showNumberImpl +  foreign import showArrayImpl+    """+    function showArrayImpl(f) {+      return function(xs) {+        var ss = [];+        for (var i = 0, l = xs.length; i < l; i++) {+          ss[i] = f(xs[i]);+        }+        return '[' + ss.join(',') + ']';+      };+    }+    """ :: forall a. (a -> String) -> [a] -> String++  instance showArray :: (Show a) => Show [a] where+    show = showArrayImpl show+   infixl 4 <$>   infixl 1 <#> -  -- | A `Functor` is a type constructor which supports a mapping operation-  -- | `(<$>)`.+  -- | A `Functor` is a type constructor which supports a mapping operation `(<$>)`.   -- |-  -- | `(<$>)` can be used to turn functions `a -> b` into functions-  -- | `f a -> f b` whose argument and return types use the type constructor `f`-  -- | to represent some computational context.+  -- | `(<$>)` can be used to turn functions `a -> b` into functions `f a -> f b` whose argument and return+  -- | types use the type constructor `f` to represent some computational context.   -- |-  -- | Instances must satisfy the following laws:+  -- | `Functor` instances should satisfy the following laws:   -- |   -- | - Identity: `(<$>) id = id`   -- | - Composition: `(<$>) (f <<< g) = (f <$>) <<< (g <$>)`+  -- |   class Functor f where     (<$>) :: forall a b. (a -> b) -> f a -> f b -  instance functorArr :: Functor ((->) r) where-    (<$>) = (<<<)-   -- | `(<#>)` is `(<$>)` with its arguments reversed. For example:   -- |   -- | ```purescript@@ -204,12 +242,10 @@   (<#>) :: forall f a b. (Functor f) => f a -> (a -> b) -> f b   (<#>) fa f = f <$> fa -  -- | The `void` function is used to ignore the type wrapped by a-  -- | [`Functor`](#functor), replacing it with `Unit` and keeping only the type-  -- | information provided by the type constructor itself.+  -- | The `void` function is used to ignore the type wrapped by a [`Functor`](#functor), replacing it with `Unit` and+  -- | keeping only the type information provided by the type constructor itself.   -- |-  -- | `void` is often useful when using `do` notation to change the return type-  -- | of a monadic computation:+  -- | `void` is often useful when using `do` notation to change the return type of a monadic computation:   -- |   -- | ```purescript   -- | main = forE 1 10 \n -> void do@@ -221,69 +257,48 @@    infixl 4 <*> -  -- | The `Apply` class provides the `(<*>)` which is used to apply a function-  -- | to an argument under a type constructor.+  -- | The `Apply` class provides the `(<*>)` which is used to apply a function to an argument under a type constructor.   -- |-  -- | `Apply` can be used to lift functions of two or more arguments to work on-  -- | values wrapped with the type constructor `f`. It might also be understood-  -- | in terms of the `lift2` function:+  -- | `Apply` can be used to lift functions of two or more arguments to work on values wrapped with the type constructor `f`.+  -- | It might also be understood in terms of the `lift2` function:   -- |   -- | ```purescript   -- | lift2 :: forall f a b c. (Apply f) => (a -> b -> c) -> f a -> f b -> f c   -- | lift2 f a b = f <$> a <*> b   -- | ```   -- |-  -- | `(<*>)` is recovered from `lift2` as `lift2 ($)`. That is, `(<*>)` lifts-  -- | the function application operator `($)` to arguments wrapped with the-  -- | type constructor `f`.+  -- | `(<*>)` is recovered from `lift2` as `lift2 ($)`. That is, `(<*>)` lifts the function application operator `($)` to arguments+  -- | wrapped with the type constructor `f`.   -- |-  -- | Instances must satisfy the following law in addition to the `Functor`-  -- | laws:+  -- | `Apply` instances should satisfy the following law:   -- |-  -- | - Associative composition: `(<<<) <$> f <*> g <*> h = f <*> (g <*> h)`+  -- | - Associative Composition: `(<<<) <$> f <*> g <*> h = f <*> (g <*> h)`   -- |   -- | Formally, `Apply` represents a strong lax semi-monoidal endofunctor.   class (Functor f) <= Apply f where     (<*>) :: forall a b. f (a -> b) -> f a -> f b -  instance applyArr :: Apply ((->) r) where-    (<*>) f g x = f x (g x)--  -- | The `Applicative` type class extends the [`Apply`](#apply) type class-  -- | with a `pure` function, which can be used to create values of type `f a`-  -- | from values of type `a`.+  -- | The `Applicative` type class extends the [`Apply`](#apply) type class with a `pure` function, which can be used to+  -- | create values of type `f a` from values of type `a`.   -- |-  -- | Where [`Apply`](#apply) provides the ability to lift functions of two or-  -- | more arguments to functions whose arguments are wrapped using `f`, and-  -- | [`Functor`](#functor) provides the ability to lift functions of one-  -- | argument, `pure` can be seen as the function which lifts functions of-  -- | _zero_ arguments. That is, `Applicative` functors support a lifting-  -- | operation for any number of function arguments.+  -- | Where [`Apply`](#apply) provides the ability to lift functions of two or more arguments to functions whose arguments are wrapped using `f`,+  -- | and [`Functor`](#functor) provides the ability to lift functions of one argument, `pure` can be seen as the function which lifts functions of+  -- | _zero_ arguments. That is, `Applicative` functors support a lifting operation for any number of function arguments.   -- |-  -- | Instances must satisfy the following laws in addition to the `Apply`-  -- | laws:+  -- | `Applicative` instances should satisfy the following laws:   -- |   -- | - Identity: `(pure id) <*> v = v`   -- | - Composition: `(pure <<<) <*> f <*> g <*> h = f <*> (g <*> h)`   -- | - Homomorphism: `(pure f) <*> (pure x) = pure (f x)`   -- | - Interchange: `u <*> (pure y) = (pure ($ y)) <*> u`+  -- |   class (Apply f) <= Applicative f where     pure :: forall a. a -> f a -  instance applicativeArr :: Applicative ((->) r) where-    pure = const--  -- | `return` is an alias for `pure`.-  return :: forall m a. (Applicative m) => a -> m a-  return = pure--  -- | `liftA1` provides a default implementation of `(<$>)` for any-  -- | [`Applicative`](#applicative) functor, without using `(<$>)` as provided-  -- | by the [`Functor`](#functor)-[`Applicative`](#applicative) superclass-  -- | relationship.+  -- | `liftA1` provides a default implementation of `(<$>)` for any [`Applicative`](#applicative) functor,+  -- | without using `(<$>)` as provided by the [`Functor`](#functor)-[`Applicative`](#applicative) superclass relationship.   -- |-  -- | `liftA1` can therefore be used to write [`Functor`](#functor) instances-  -- | as follows:+  -- | `liftA1` can therefore be used to write [`Functor`](#functor) instances as follows:   -- |   -- | ```purescript   -- | instance functorF :: Functor F where@@ -294,9 +309,8 @@    infixl 1 >>= -  -- | The `Bind` type class extends the [`Apply`](#apply) type class with a-  -- | "bind" operation `(>>=)` which composes computations in sequence, using-  -- | the return value of one computation to determine the next computation.+  -- | The `Bind` type class extends the [`Apply`](#apply) type class with a "bind" operation `(>>=)` which composes computations+  -- | in sequence, using the return value of one computation to determine the next computation.   -- |   -- | The `>>=` operator can also be expressed using `do` notation, as follows:   -- |@@ -307,14 +321,16 @@   -- |   -- | where the function argument of `f` is given the name `y`.   -- |-  -- | Instances must satisfy the following law in addition to the `Apply`-  -- | laws:+  -- | `Bind` instances should satisfy the following law:   -- |   -- | - Associativity: `(x >>= f) >>= g = x >>= (\k => f k >>= g)`   -- |-  -- | Associativity tells us that we can regroup operations which use `do`-  -- | notation so that we can unambiguously write, for example:+  -- | Or, expressed using `do` notation:   -- |+  -- | - Associativity: `do { z <- do { y <- x ; f y } ; g z } = do { k <- x ; do { y <- f k ; g y } }`+  -- |+  -- | Associativity tells us that we can regroup operations which use do-notation, so that we can unambiguously write, for example:+  -- |   -- | ```purescript   -- | do x <- m1   -- |    y <- m2 x@@ -323,29 +339,29 @@   class (Apply m) <= Bind m where     (>>=) :: forall a b. m a -> (a -> m b) -> m b -  instance bindArr :: Bind ((->) r) where-    (>>=) m f x = f (m x) x--  -- | The `Monad` type class combines the operations of the `Bind` and-  -- | `Applicative` type classes. Therefore, `Monad` instances represent type-  -- | constructors which support sequential composition, and also lifting of-  -- | functions of arbitrary arity.+  -- | The `Monad` type class combines the operations of the `Bind` and `Applicative` type classes. Therefore, `Monad` instances+  -- | represent type constructors which support sequential composition, and also lifting of functions of arbitrary arity.   -- |-  -- | Instances must satisfy the following laws in addition to the-  -- | `Applicative` and `Bind` laws:+  -- | `Monad` instances should satisfy the following laws:   -- |   -- | - Left Identity: `pure x >>= f = f x`   -- | - Right Identity: `x >>= pure = x`+  -- |+  -- | Or, expressed using `do` notation:+  -- |+  -- | - Left Identity: `do { y <- pure x ; f y } = f x`+  -- | - Right Identity: `do { y <- x ; pure y } = x`+  -- |   class (Applicative m, Bind m) <= Monad m -  instance monadArr :: Monad ((->) r)+  -- | `return` is an alias for `pure`.+  return :: forall m a. (Monad m) => a -> m a+  return = pure -  -- | `liftM1` provides a default implementation of `(<$>)` for any-  -- | [`Monad`](#monad), without using `(<$>)` as provided by the-  -- | [`Functor`](#functor)-[`Monad`](#monad) superclass relationship.+  -- | `liftM1` provides a default implementation of `(<$>)` for any [`Monad`](#monad),+  -- | without using `(<$>)` as provided by the [`Functor`](#functor)-[`Monad`](#monad) superclass relationship.   -- |-  -- | `liftM1` can therefore be used to write [`Functor`](#functor) instances-  -- | as follows:+  -- | `liftM1` can therefore be used to write [`Functor`](#functor) instances as follows:   -- |   -- | ```purescript   -- | instance functorF :: Functor F where@@ -356,12 +372,10 @@     a' <- a     return (f a') -  -- | `ap` provides a default implementation of `(<*>)` for any-  -- | [`Monad`](#monad), without using `(<*>)` as provided by the-  -- | [`Apply`](#apply)-[`Monad`](#monad) superclass relationship.+  -- | `ap` provides a default implementation of `(<*>)` for any [`Monad`](#monad),+  -- | without using `(<*>)` as provided by the [`Apply`](#apply)-[`Monad`](#monad) superclass relationship.   -- |-  -- | `ap` can therefore be used to write [`Apply`](#apply) instances as-  -- | follows:+  -- | `ap` can therefore be used to write [`Apply`](#apply) instances as follows:   -- |   -- | ```purescript   -- | instance applyF :: Apply F where@@ -373,152 +387,68 @@     a' <- a     return (f' a') -  infixr 5 <>-  infixr 5 ++--  -- | The `Semigroup` type class identifies an associative operation on a type.-  -- |-  -- | Instances are required to satisfy the following law:-  -- |-  -- | - Associativity: `(x <> y) <> z = x <> (y <> z)`-  -- |-  -- | One example of a `Semigroup` is `String`, with `(<>)` defined as string-  -- | concatenation.-  class Semigroup a where-    (<>) :: a -> a -> a--  -- | `(++)` is an alias for `(<>)`.-  (++) :: forall s. (Semigroup s) => s -> s -> s-  (++) = (<>)+  instance functorArr :: Functor ((->) r) where+    (<$>) = (<<<) -  instance semigroupString :: Semigroup String where-    (<>) = concatString+  instance applyArr :: Apply ((->) r) where+    (<*>) f g x = f x (g x) -  instance semigroupUnit :: Semigroup Unit where-    (<>) _ _ = unit+  instance applicativeArr :: Applicative ((->) r) where+    pure = const -  instance semigroupArr :: (Semigroup s') => Semigroup (s -> s') where-    (<>) f g = \x -> f x <> g x+  instance bindArr :: Bind ((->) r) where+    (>>=) m f x = f (m x) x -  instance semigroupOrdering :: Semigroup Ordering where-    (<>) LT _ = LT-    (<>) GT _ = GT-    (<>) EQ y = y+  instance monadArr :: Monad ((->) r) -  foreign import concatString-    """-    function concatString(s1) {-      return function(s2) {-        return s1 + s2;-      };-    }-    """ :: String -> String -> String+  infixl 7 *+  infixl 7 /+  infixl 7 % +  infixl 6 -   infixl 6 +-  infixl 7 * -  -- | The `Semiring` class is for types that support an addition and-  -- | multiplication operation.+  -- | Addition and multiplication, satisfying the following laws:   -- |-  -- | Instances must satisfy the following laws:+  -- | - `a` is a commutative monoid under addition+  -- | - `a` is a monoid under multiplication+  -- | - multiplication distributes over addition+  -- | - multiplication by `zero` annihilates `a`   -- |-  -- | - Commutative monoid under addition:-  -- |   - Associativity: `(a + b) + c = a + (b + c)`-  -- |   - Identity: `zero + a = a + zero = a`-  -- |   - Commutative: `a + b = b + a`-  -- | - Monoid under multiplication:-  -- |   - Associativity: `(a * b) * c = a * (b * c)`-  -- |   - Identity: `one * a = a * one = a`-  -- | - Multiplication distributes over addition:-  -- |   - Left distributivity: `a * (b + c) = (a * b) + (a * c)`-  -- |   - Right distributivity: `(a + b) * c = (a * c) + (b * c)`-  -- | - Annihiliation: `zero * a = a * zero = zero`   class Semiring a where     (+)  :: a -> a -> a     zero :: a     (*)  :: a -> a -> a     one  :: a -  instance semiringNumber :: Semiring Number where-    (+) = numAdd-    zero = 0-    (*) = numMul-    one = 1--  instance semiringUnit :: Semiring Unit where-    (+) _ _ = unit-    zero = unit-    (*) _ _ = unit-    one = unit--  infixl 6 ---  -- | The `Ring` class is for types that support addition, multiplication,-  -- | and subtraction operations.-  -- |-  -- | Instances must satisfy the following law in addition to the `Semiring`-  -- | laws:-  -- |-  -- | - Additive inverse: `a + (-a) = (-a) + a = zero`-  class (Semiring a) <= Ring a where-    (-) :: a -> a -> a--  instance ringNumber :: Ring Number where-    (-) = numSub--  instance ringUnit :: Ring Unit where-    (-) _ _ = unit--  negate :: forall a. (Ring a) => a -> a-  negate a = zero - a--  infixl 7 /--  -- | The `ModuloSemiring` class is for types that support addition,-  -- | multiplication, division, and modulo (division remainder) operations.+  -- | Addition, multiplication, modulo operation and division, satisfying:   -- |-  -- | Instances must satisfy the following law in addition to the `Semiring`-  -- | laws:+  -- | - ```a / b * b + (a `mod` b) = a```   -- |-  -- | - Remainder: `a / b * b + (a `mod` b) = a`   class (Semiring a) <= ModuloSemiring a where     (/) :: a -> a -> a     mod :: a -> a -> a -  instance moduloSemiringNumber :: ModuloSemiring Number where-    (/) = numDiv-    mod _ _ = 0--  instance moduloSemiringUnit :: ModuloSemiring Unit where-    (/) _ _ = unit-    mod _ _ = unit--  -- | A `Ring` where every nonzero element has a multiplicative inverse.+  -- | Addition, multiplication, and subtraction.   -- |-  -- | Instances must satisfy the following law in addition to the `Ring` and-  -- | `ModuloSemiring` laws:+  -- | Has the same laws as `Semiring` but additionally satisfying:   -- |-  -- | - Multiplicative inverse: `(one / x) * x = one`+  -- | - `a` is an abelian group under addition   -- |-  -- | As a consequence of this ```a `mod` b = zero``` as no divide operation-  -- | will have a remainder.-  class (Ring a, ModuloSemiring a) <= DivisionRing a--  instance divisionRingNumber :: DivisionRing Number+  class (Semiring a) <= Ring a where+    (-) :: a -> a -> a -  instance divisionRingUnit :: DivisionRing Unit+  negate :: forall a. (Ring a) => a -> a+  negate a = zero - a -  -- | The `Num` class is for types that are commutative fields.+  -- | Ring where every nonzero element has a multiplicative inverse so that:   -- |-  -- | Instances must satisfy the following law in addition to the-  -- | `DivisionRing` laws:+  -- | - ```a `mod` b = zero```   -- |-  -- | - Commutative multiplication: `a * b = b * a`-  class (DivisionRing a) <= Num a--  instance numNumber :: Num Number+  class (Ring a, ModuloSemiring a) <= DivisionRing a -  instance numUnit :: Num Unit+  -- | A commutative field+  class (DivisionRing a) <= Num a    foreign import numAdd     """@@ -529,6 +459,15 @@     }     """ :: Number -> Number -> Number +  foreign import numSub+    """+    function numSub(n1) {+      return function(n2) {+        return n1 - n2;+      };+    }+    """ :: Number -> Number -> Number+   foreign import numMul     """     function numMul(n1) {@@ -547,15 +486,44 @@     }     """ :: Number -> Number -> Number -  foreign import numSub+  foreign import numMod     """-    function numSub(n1) {+    function numMod(n1) {       return function(n2) {-        return n1 - n2;+        return n1 % n2;       };     }     """ :: Number -> Number -> Number +  (%) = numMod++  instance semiringNumber :: Semiring Number where+    (+) = numAdd+    zero = 0+    (*) = numMul+    one = 1++  instance ringNumber :: Ring Number where+    (-) = numSub++  instance moduloSemiringNumber :: ModuloSemiring Number where+    (/) = numDiv+    mod _ _ = 0++  instance divisionRingNumber :: DivisionRing Number++  instance numNumber :: Num Number++  -- | The `Unit` type has a single inhabitant, called `unit`. It represents values with no computational content.+  -- |+  -- | `Unit` is often used, wrapped in a monadic type constructor, as the return type of a computation where only+  -- | the _effects_ are important.+  newtype Unit = Unit {}++  -- | `unit` is the sole inhabitant of the `Unit` type.+  unit :: Unit+  unit = Unit {}+   infix 4 ==   infix 4 /= @@ -573,33 +541,6 @@     (==) :: a -> a -> Boolean     (/=) :: a -> a -> Boolean -  instance eqBoolean :: Eq Boolean where-    (==) = refEq-    (/=) = refIneq--  instance eqNumber :: Eq Number where-    (==) = refEq-    (/=) = refIneq--  instance eqString :: Eq String where-    (==) = refEq-    (/=) = refIneq--  instance eqUnit :: Eq Unit where-    (==) _ _ = true-    (/=) _ _ = false--  instance eqArray :: (Eq a) => Eq [a] where-    (==) = eqArrayImpl (==)-    (/=) xs ys = not (xs == ys)--  instance eqOrdering :: Eq Ordering where-    (==) LT LT = true-    (==) GT GT = true-    (==) EQ EQ = true-    (==) _  _  = false-    (/=) x y = not (x == y)-   foreign import refEq     """     function refEq(r1) {@@ -618,6 +559,22 @@     }     """ :: forall a. a -> a -> Boolean +  instance eqUnit :: Eq Unit where+    (==) (Unit {}) (Unit {}) = true+    (/=) (Unit {}) (Unit {}) = false++  instance eqString :: Eq String where+    (==) = refEq+    (/=) = refIneq++  instance eqNumber :: Eq Number where+    (==) = refEq+    (/=) = refIneq++  instance eqBoolean :: Eq Boolean where+    (==) = refEq+    (/=) = refIneq+   foreign import eqArrayImpl     """     function eqArrayImpl(f) {@@ -633,14 +590,34 @@     }     """ :: forall a. (a -> a -> Boolean) -> [a] -> [a] -> Boolean -  -- | The `Ordering` data type represents the three possible outcomes of-  -- | comparing two values:+  instance eqArray :: (Eq a) => Eq [a] where+    (==) xs ys = eqArrayImpl (==) xs ys+    (/=) xs ys = not (xs == ys)++  -- | The `Ordering` data type represents the three possible outcomes of comparing two values:   -- |   -- | `LT` - The first value is _less than_ the second.   -- | `GT` - The first value is _greater than_ the second.   -- | `EQ` - The first value is _equal to_ or _incomparable to_ the second.   data Ordering = LT | GT | EQ +  instance eqOrdering :: Eq Ordering where+    (==) LT LT = true+    (==) GT GT = true+    (==) EQ EQ = true+    (==) _  _  = false+    (/=) x y = not (x == y)++  instance showOrdering :: Show Ordering where+    show LT = "LT"+    show GT = "GT"+    show EQ = "EQ"++  instance semigroupOrdering :: Semigroup Ordering where+    (<>) LT _ = LT+    (<>) GT _ = GT+    (<>) EQ y = y+   -- | The `Ord` type class represents types which support comparisons.   -- |   -- | `Ord` instances should satisfy the laws of _partially orderings_:@@ -648,45 +625,11 @@   -- | - Reflexivity: `a <= a`   -- | - Antisymmetry: if `a <= b` and `b <= a` then `a = b`   -- | - Transitivity: if `a <= b` and `b <= c` then `a <= c`+  -- |   class (Eq a) <= Ord a where     compare :: a -> a -> Ordering -  instance ordBoolean :: Ord Boolean where-    compare false false = EQ-    compare false true  = LT-    compare true  true  = EQ-    compare true  false = GT--  instance ordNumber :: Ord Number where-    compare = unsafeCompare--  instance ordString :: Ord String where-    compare = unsafeCompare--  instance ordUnit :: Ord Unit where-    compare _ _ = EQ--  instance ordArray :: (Ord a) => Ord [a] where-    compare [] [] = EQ-    compare [] _ = LT-    compare _ [] = GT-    compare (x:xs) (y:ys) = case compare x y of-      EQ -> compare xs ys-      other -> other--  instance ordOrdering :: Ord Ordering where-    compare LT LT = EQ-    compare EQ EQ = EQ-    compare GT GT = EQ-    compare LT _  = LT-    compare EQ LT = GT-    compare EQ GT = LT-    compare GT _  = GT-   infixl 4 <-  infixl 4 >-  infixl 4 <=-  infixl 4 >=    -- | Test whether one value is _strictly less than_ another.   (<) :: forall a. (Ord a) => a -> a -> Boolean@@ -694,27 +637,30 @@     LT -> true     _ -> false +  infixl 4 >+   -- | Test whether one value is _strictly greater than_ another.   (>) :: forall a. (Ord a) => a -> a -> Boolean   (>) a1 a2 = case a1 `compare` a2 of     GT -> true     _ -> false +  infixl 4 <=+   -- | Test whether one value is _non-strictly less than_ another.   (<=) :: forall a. (Ord a) => a -> a -> Boolean   (<=) a1 a2 = case a1 `compare` a2 of     GT -> false     _ -> true +  infixl 4 >=+   -- | Test whether one value is _non-strictly greater than_ another.   (>=) :: forall a. (Ord a) => a -> a -> Boolean   (>=) a1 a2 = case a1 `compare` a2 of     LT -> false     _ -> true -  unsafeCompare :: forall a. a -> a -> Ordering-  unsafeCompare = unsafeCompareImpl LT EQ GT-   foreign import unsafeCompareImpl     """     function unsafeCompareImpl(lt) {@@ -730,148 +676,145 @@     }     """ :: forall a. Ordering -> Ordering -> Ordering -> a -> a -> Ordering -  -- | The `Bounded` type class represents types that are finite partially-  -- | ordered sets.-  -- |-  -- | Instances should satisfy the following law in addition to the `Ord` laws:-  -- |-  -- | - Ordering: `bottom <= a <= top`-  class (Ord a) <= Bounded a where-    top :: a-    bottom :: a--  instance boundedBoolean :: Bounded Boolean where-    top = true-    bottom = false--  instance boundedUnit :: Bounded Unit where-    top = unit-    bottom = unit+  unsafeCompare :: forall a. a -> a -> Ordering+  unsafeCompare = unsafeCompareImpl LT EQ GT -  instance boundedOrdering :: Bounded Ordering where-    top = GT-    bottom = LT+  instance ordUnit :: Ord Unit where+    compare (Unit {}) (Unit {}) = EQ -  -- | The `Lattice` type class represents types that are partially ordered-  -- | sets with a supremum (`sup` or `||`) and infimum (`inf` or `&&`).-  -- |-  -- | Instances should satisfy the following laws in addition to the `Ord`-  -- | laws:-  -- |-  -- | - Associativity:-  -- |   - `a || (b || c) = (a || b) || c`-  -- |   - `a && (b && c) = (a && b) && c`-  -- | - Commutativity:-  -- |   - `a || b = b || a`-  -- |   - `a && b = b && a`-  -- | - Absorption:-  -- |   - `a || (a && b) = a`-  -- |   - `a && (a || b) = a`-  -- | - Idempotent:-  -- |   - `a || a = a`-  -- |   - `a && a = a`-  class (Ord a) <= Lattice a where-    sup :: a -> a -> a-    inf :: a -> a -> a+  instance ordBoolean :: Ord Boolean where+    compare false false = EQ+    compare false true  = LT+    compare true  true  = EQ+    compare true  false = GT -  instance latticeBoolean :: Lattice Boolean where-    sup = boolOr-    inf = boolAnd+  instance ordNumber :: Ord Number where+    compare = unsafeCompare -  instance latticeUnit :: Lattice Unit where-    sup _ _ = unit-    inf _ _ = unit+  instance ordString :: Ord String where+    compare = unsafeCompare -  infixr 2 ||-  infixr 3 &&+  instance ordArray :: (Ord a) => Ord [a] where+    compare [] [] = EQ+    compare [] _ = LT+    compare _ [] = GT+    compare (x:xs) (y:ys) = case compare x y of+      EQ -> compare xs ys+      other -> other -  -- | The `sup` operator.-  (||) :: forall a. (Lattice a) => a -> a -> a-  (||) = sup+  infixl 10 .&.+  infixl 10 .|.+  infixl 10 .^. -  -- | The `inf` operator.-  (&&) :: forall a. (Lattice a) => a -> a -> a-  (&&) = inf+  -- | The `Bits` type class identifies types which support bitwise operations.+  class Bits b where+    (.&.) :: b -> b -> b+    (.|.) :: b -> b -> b+    (.^.) :: b -> b -> b+    shl :: b -> Number -> b+    shr :: b -> Number -> b+    zshr :: b -> Number -> b+    complement :: b -> b -  -- | The `BoundedLattice` type class represents types that are finite-  -- | lattices.-  -- |-  -- | Instances should satisfy the following law in addition to the `Lattice`-  -- | and `Bounded` laws:-  -- |-  -- | - Identity:-  -- |   - `a || bottom = a`-  -- |   - `a && top = a`-  -- | - Annihiliation:-  -- |   - `a || top = top`-  -- |   - `a && bottom = bottom`-  class (Bounded a, Lattice a) <= BoundedLattice a+  foreign import numShl+    """+    function numShl(n1) {+      return function(n2) {+        return n1 << n2;+      };+    }+    """ :: Number -> Number -> Number -  instance boundedLatticeBoolean :: BoundedLattice Boolean+  foreign import numShr+    """+    function numShr(n1) {+      return function(n2) {+        return n1 >> n2;+      };+    }+    """ :: Number -> Number -> Number -  instance boundedLatticeUnit :: BoundedLattice Unit+  foreign import numZshr+    """+    function numZshr(n1) {+      return function(n2) {+        return n1 >>> n2;+      };+    }+    """ :: Number -> Number -> Number -  -- | The `ComplementedLattice` type class represents types that are lattices-  -- | where every member is also uniquely complemented.-  -- |-  -- | Instances should satisfy the following law in addition to the-  -- | `BoundedLattice` laws:-  -- |-  -- | - Complemented:-  -- |   - `not a || a == top`-  -- |   - `not a && a == bottom`-  -- | - Double negation:-  -- |   - `not <<< not == id`-  class (BoundedLattice a) <= ComplementedLattice a where-    not :: a -> a+  foreign import numAnd+    """+    function numAnd(n1) {+      return function(n2) {+        return n1 & n2;+      };+    }+    """ :: Number -> Number -> Number -  instance complementedLatticeBoolean :: ComplementedLattice Boolean where-    not = boolNot+  foreign import numOr+    """+    function numOr(n1) {+      return function(n2) {+        return n1 | n2;+      };+    }+    """ :: Number -> Number -> Number -  instance complementedLatticeUnit :: ComplementedLattice Unit where-    not _ = unit+  foreign import numXor+    """+    function numXor(n1) {+      return function(n2) {+        return n1 ^ n2;+      };+    }+    """ :: Number -> Number -> Number -  -- | The `DistributiveLattice` type class represents types that are lattices-  -- | where the `&&` and `||` distribute over each other.-  -- |-  -- | Instances should satisfy the following law in addition to the `Lattice`-  -- | laws:-  -- |-  -- | - Distributivity: `x && (y || z) = (x && y) || (x && z)`-  class (Lattice a) <= DistributiveLattice a+  foreign import numComplement+    """+    function numComplement(n) {+      return ~n;+    }+    """ :: Number -> Number -  instance distributiveLatticeBoolean :: DistributiveLattice Boolean+  instance bitsNumber :: Bits Number where+    (.&.) = numAnd+    (.|.) = numOr+    (.^.) = numXor+    shl = numShl+    shr = numShr+    zshr = numZshr+    complement = numComplement -  instance distributiveLatticeUnit :: DistributiveLattice Unit+  infixr 2 ||+  infixr 3 && -  -- | The `BooleanAlgebra` type class represents types that are Boolean-  -- | algebras, also known as Boolean lattices.+  -- | The `BoolLike` type class identifies types which support Boolean operations.   -- |-  -- | Instances should satisfy the `ComplementedLattice` and-  -- | `DistributiveLattice` laws.-  class (ComplementedLattice a, DistributiveLattice a) <= BooleanAlgebra a--  instance booleanAlgebraBoolean :: BooleanAlgebra Boolean--  instance booleanAlgebraUnit :: BooleanAlgebra Unit+  -- | `BoolLike` instances are required to satisfy the laws of a _Boolean algebra_.+  -- |+  class BoolLike b where+    (&&) :: b -> b -> b+    (||) :: b -> b -> b+    not :: b -> b -  foreign import boolOr+  foreign import boolAnd     """-    function boolOr(b1) {+    function boolAnd(b1) {       return function(b2) {-        return b1 || b2;+        return b1 && b2;       };     }-    """ :: Boolean -> Boolean -> Boolean+    """  :: Boolean -> Boolean -> Boolean -  foreign import boolAnd+  foreign import boolOr     """-    function boolAnd(b1) {+    function boolOr(b1) {       return function(b2) {-        return b1 && b2;+        return b1 || b2;       };     }-    """  :: Boolean -> Boolean -> Boolean+    """ :: Boolean -> Boolean -> Boolean    foreign import boolNot     """@@ -880,62 +823,46 @@     }     """ :: Boolean -> Boolean -  -- | The `Show` type class represents those types which can be converted into-  -- | a human-readable `String` representation.-  -- |-  -- | While not required, it is recommended that for any expression `x`, the-  -- | string `show x` be executable PureScript code which evaluates to the same-  -- | value as the expression `x`.-  class Show a where-    show :: a -> String--  instance showBoolean :: Show Boolean where-    show true = "true"-    show false = "false"+  instance boolLikeBoolean :: BoolLike Boolean where+    (&&) = boolAnd+    (||) = boolOr+    not = boolNot -  instance showNumber :: Show Number where-    show = showNumberImpl+  infixr 5 <> -  instance showString :: Show String where-    show = showStringImpl+  -- | The `Semigroup` type class identifies an associative operation on a type.+  -- |+  -- | `Semigroup` instances are required to satisfy the following law:+  -- |+  -- | - Associativity: `(x <> y) <> z = x <> (y <> z)`+  -- |+  -- | For example, the `String` type is an instance of `Semigroup`, where `(<>)` is defined to be string concatenation.+  class Semigroup a where+    (<>) :: a -> a -> a -  instance showUnit :: Show Unit where-    show _ = "unit"+  foreign import concatString+    """+    function concatString(s1) {+      return function(s2) {+        return s1 + s2;+      };+    }+    """ :: String -> String -> String -  instance showArray :: (Show a) => Show [a] where-    show = showArrayImpl show+  instance semigroupUnit :: Semigroup Unit where+    (<>) (Unit {}) (Unit {}) = Unit {} -  instance showOrdering :: Show Ordering where-    show LT = "LT"-    show GT = "GT"-    show EQ = "EQ"+  instance semigroupString :: Semigroup String where+    (<>) = concatString -  foreign import showNumberImpl-    """-    function showNumberImpl(n) {-      return n.toString();-    }-    """ :: Number -> String+  instance semigroupArr :: (Semigroup s') => Semigroup (s -> s') where+    (<>) f g = \x -> f x <> g x -  foreign import showStringImpl-    """-    function showStringImpl(s) {-      return JSON.stringify(s);-    }-    """ :: String -> String+  infixr 5 ++ -  foreign import showArrayImpl-    """-    function showArrayImpl(f) {-      return function(xs) {-        var ss = [];-        for (var i = 0, l = xs.length; i < l; i++) {-          ss[i] = f(xs[i]);-        }-        return '[' + ss.join(',') + ']';-      };-    }-    """ :: forall a. (a -> String) -> [a] -> String+  -- | `(++)` is an alias for `(<>)`.+  (++) :: forall s. (Semigroup s) => s -> s -> s+  (++) = (<>)  module Data.Function where 
psc-make/Main.hs view
@@ -52,29 +52,27 @@   content <- forM ioInputFiles $ \inFile -> (Right inFile, ) <$> readFile inFile   return (if ioNoPrelude then content else (Left P.RebuildNever, P.prelude) : content) -newtype Make a = Make { unMake :: ReaderT (P.Options P.Make) (ExceptT P.MultipleErrors IO) a }-  deriving (Functor, Applicative, Monad, MonadIO, MonadError P.MultipleErrors, MonadReader (P.Options P.Make))+newtype Make a = Make { unMake :: ReaderT (P.Options P.Make) (ExceptT String IO) a }+  deriving (Functor, Applicative, Monad, MonadIO, MonadError String, MonadReader (P.Options P.Make)) -runMake :: P.Options P.Make -> Make a -> IO (Either P.MultipleErrors a)+runMake :: P.Options P.Make -> Make a -> IO (Either String a) runMake opts = runExceptT . flip runReaderT opts . unMake -makeIO :: (IOError -> P.ErrorMessage) -> IO a -> Make a-makeIO f io = do-  e <- liftIO $ tryIOError io-  either (throwError . P.errorMessage . f) return e+makeIO :: IO a -> Make a+makeIO = Make . lift . ExceptT . fmap (either (Left . show) Right) . tryIOError  instance P.MonadMake Make where-  getTimestamp path = makeIO (const (P.CannotGetFileInfo path)) $ do+  getTimestamp path = makeIO $ do     exists <- doesFileExist path     traverse (const $ getModificationTime path) $ guard exists-  readTextFile path = makeIO (const (P.CannotReadFile path))$ do+  readTextFile path = makeIO $ do     putStrLn $ "Reading " ++ path     readFile path-  writeTextFile path text = makeIO (const (P.CannotWriteFile path)) $ do+  writeTextFile path text = makeIO $ do     mkdirp path     putStrLn $ "Writing " ++ path     writeFile path text-  progress = liftIO . putStrLn+  progress = makeIO . putStrLn  compile :: PSCMakeOptions -> IO () compile (PSCMakeOptions input outputDir opts usePrefix) = do@@ -86,8 +84,8 @@     Right ms -> do       e <- runMake opts $ P.make outputDir ms prefix       case e of-        Left errs -> do-          putStrLn (P.prettyPrintMultipleErrors (P.optionsVerboseErrors opts) errs)+        Left err -> do+          putStrLn err           exitFailure         Right _ -> do           exitSuccess
psc/Main.hs view
@@ -63,8 +63,8 @@       exitFailure     Right ms -> do       case P.compile (map snd ms) prefix `runReaderT` opts of-        Left errs -> do-          hPutStrLn stderr (P.prettyPrintMultipleErrors (P.optionsVerboseErrors opts) errs)+        Left err -> do+          hPutStrLn stderr err           exitFailure         Right (js, exts, _) -> do           case output of
+ psci/Commands.hs view
@@ -0,0 +1,78 @@+-----------------------------------------------------------------------------+--+-- Module      :  Commands+-- Copyright   :  (c) Phil Freeman 2014+-- License     :  MIT+--+-- Maintainer  :  Phil Freeman <paf31@cantab.net>+-- Stability   :  experimental+-- Portability :+--+-- |+-- Commands for PSCI.+--+-----------------------------------------------------------------------------++module Commands where++import Language.PureScript++-- |+-- Valid Meta-commands for PSCI+--+data Command+  -- |+  -- A purescript expression+  --+  = Expression Expr+  -- |+  -- Show the help command+  --+  | Help+  -- |+  -- Import a module from a loaded file+  --+  | Import ImportedModule+  -- |+  -- Browse a module+  --+  | Browse ModuleName+  -- |+  -- Load a file for use with importing+  --+  | LoadFile FilePath+  -- |+  -- Exit PSCI+  --+  | Quit+  -- |+  -- Reset the state of the REPL+  --+  | Reset+  -- |+  -- Add some declarations to the current evaluation context.+  --+  | Decls [Declaration]+  -- |+  -- Find the type of an expression+  --+  | TypeOf Expr+  -- |+  -- Find the kind of an expression+  --+  | KindOf Type+  -- |+  -- Show command+  --+  | Show String++-- | All of the data that is contained by an ImportDeclaration in the AST.+-- That is:+--+-- * A module name, the name of the module which is being imported+-- * An ImportDeclarationType which specifies whether there is an explicit+--   import list, a hiding list, or neither.+-- * If the module is imported qualified, its qualified name in the importing+--   module. Otherwise, Nothing.+--+type ImportedModule = (ModuleName, ImportDeclarationType, Maybe ModuleName)
− psci/Completion.hs
@@ -1,232 +0,0 @@-module Completion where--import Data.Maybe (mapMaybe)-import Data.List (nub, nubBy, sortBy, isPrefixOf, stripPrefix)-import Data.Char (isUpper)-import Data.Function (on)-import Data.Traversable (traverse)--import Control.Applicative ((<$>), (<*>))-import Control.Monad.Trans.Reader (asks, runReaderT, ReaderT)-import Control.Monad.Trans.State.Strict--import System.Console.Haskeline--import qualified Language.PureScript as P-import qualified Language.PureScript.Names as N--import qualified Directive as D-import Types---- Completions may read the state, but not modify it.-type CompletionM = ReaderT PSCiState IO---- Lift a `CompletionM` action to a `StateT PSCiState IO` one.-liftCompletionM :: CompletionM a -> StateT PSCiState IO a-liftCompletionM act = StateT (\s -> (\a -> (a, s)) <$> runReaderT act s)---- Haskeline completions--data CompletionContext-  = CtxDirective String-  | CtxFilePath String-  | CtxModule-  | CtxIdentifier-  | CtxType-  | CtxFixed String-  deriving (Show)---- |--- Loads module, function, and file completions.----completion :: CompletionFunc (StateT PSCiState IO)-completion = liftCompletionM . completion'--completion' :: CompletionFunc CompletionM-completion' = completeWordWithPrev Nothing " \t\n\r" findCompletions---- |--- Decide what kind of completion we need based on input. This function expects--- a list of complete words (to the left of the cursor) as the first argument,--- and the current word as the second argument.-completionContext :: [String] -> String -> [CompletionContext]-completionContext [] _ = [CtxDirective "", CtxIdentifier, CtxFixed "import"]-completionContext ws w | headSatisfies (":" `isPrefixOf`) ws = completeDirective ws w-completionContext ws w | headSatisfies (== "import") ws = completeImport ws w-completionContext _ _ = [CtxIdentifier]--completeDirective :: [String] -> String -> [CompletionContext]-completeDirective ws w =-  case ws of-    []    -> [CtxDirective w]-    [dir] -> case D.directivesFor <$> stripPrefix ":" dir of-                -- only offer completions if the directive is unambiguous-                Just [dir'] -> directiveArg w dir'-                _           -> []--    -- All directives take exactly one argument. If we haven't yet matched,-    -- that means one argument has already been supplied. So don't complete-    -- any others.-    _     -> []--directiveArg :: String -> Directive -> [CompletionContext]-directiveArg _ Browse = [CtxModule]-directiveArg w Load   = [CtxFilePath w]-directiveArg _ Quit   = []-directiveArg _ Reset  = []-directiveArg _ Help   = []-directiveArg _ Show   = map CtxFixed replQueryStrings-directiveArg _ Type   = [CtxIdentifier]-directiveArg _ Kind   = [CtxType]--completeImport :: [String] -> String -> [CompletionContext]-completeImport ws w' =-  case (ws, w') of-    (["import"], w) | headSatisfies isUpper w -> [CtxModule]-    (["import"], _)                           -> [CtxModule, CtxFixed "qualified"]-    (["import", "qualified"], _)              -> [CtxModule]-    _                                         -> []--headSatisfies :: (a -> Bool) -> [a] -> Bool-headSatisfies p str =-  case str of-    (c:_)  -> p c-    _     -> False---- | Callback for Haskeline's `completeWordWithPrev`.--- Expects:---   * Line contents to the left of the word, reversed---   * Word to be completed-findCompletions :: String -> String -> CompletionM [Completion]-findCompletions prev word = do-  let ctx = completionContext (words (reverse prev)) word-  completions <- concat <$> traverse getCompletions ctx-  return $ sortBy directivesFirst completions-  where-  getCompletions :: CompletionContext -> CompletionM [Completion]-  getCompletions = fmap (mapMaybe (either (prefixedBy word) Just)) . getCompletion--  prefixedBy :: String -> String -> Maybe Completion-  prefixedBy w cand = if w `isPrefixOf` cand-                        then Just (simpleCompletion cand)-                        else Nothing--getCompletion :: CompletionContext -> CompletionM [Either String Completion]-getCompletion ctx =-  case ctx of-    CtxFilePath f        -> map Right <$> listFiles f-    CtxModule            -> map Left <$> getModuleNames-    CtxIdentifier        -> map Left <$> ((++) <$> getIdentNames <*> getDctorNames)-    CtxType              -> map Left <$> getTypeNames-    CtxFixed str         -> return [Left str]-    CtxDirective d       -> return (map Left (completeDirectives d))--  where-  completeDirectives :: String -> [String]-  completeDirectives = map (':' :) . D.directiveStringsFor---getLoadedModules :: CompletionM [P.Module]-getLoadedModules = asks (map snd . psciLoadedModules)--getImportedModules :: CompletionM [ImportedModule]-getImportedModules = asks psciImportedModules--getModuleNames :: CompletionM [String]-getModuleNames = moduleNames <$> getLoadedModules--mapLoadedModulesAndQualify :: (Show a) => (P.Module -> [(a, P.Declaration)]) -> CompletionM [String]-mapLoadedModulesAndQualify f = do-  ms <- getLoadedModules-  let argPairs = do m <- ms-                    fm <- f m-                    return (m, fm)-  concat <$> traverse (uncurry getAllQualifications) argPairs--getIdentNames :: CompletionM [String]-getIdentNames = mapLoadedModulesAndQualify identNames--getDctorNames :: CompletionM [String]-getDctorNames = mapLoadedModulesAndQualify dctorNames--getTypeNames :: CompletionM [String]-getTypeNames = mapLoadedModulesAndQualify typeDecls---- | Given a module and a declaration in that module, return all possible ways--- it could have been referenced given the current PSCiState - including fully--- qualified, qualified using an alias, and unqualified.-getAllQualifications :: (Show a) => P.Module -> (a, P.Declaration) -> CompletionM [String]-getAllQualifications m (declName, decl) = do-  imports <- getAllImportsOf m-  let fullyQualified = qualifyWith (Just (P.getModuleName m))-  let otherQuals = nub (concatMap qualificationsUsing imports)-  return $ fullyQualified : otherQuals-  where-  qualifyWith mMod = show (P.Qualified mMod declName)-  referencedBy refs = P.isExported (Just refs) decl--  qualificationsUsing (_, importType, asQ') =-    let q = qualifyWith asQ'-    in case importType of-          P.Implicit      -> [q]-          P.Explicit refs -> if referencedBy refs-                               then [q]-                               else []-          P.Hiding refs   -> if referencedBy refs-                               then []-                               else [q]----- | Returns all the ImportedModule values referring to imports of a particular--- module.-getAllImportsOf :: P.Module -> CompletionM [ImportedModule]-getAllImportsOf = asks . allImportsOf--nubOnFst :: Eq a => [(a, b)] -> [(a, b)]-nubOnFst = nubBy ((==) `on` fst)--typeDecls :: P.Module -> [(N.ProperName, P.Declaration)]-typeDecls = mapMaybe getTypeName . filter P.isDataDecl . P.exportedDeclarations-  where-  getTypeName :: P.Declaration -> Maybe (N.ProperName, P.Declaration)-  getTypeName d@(P.TypeSynonymDeclaration name _ _) = Just (name, d)-  getTypeName d@(P.DataDeclaration _ name _ _) = Just (name, d)-  getTypeName (P.PositionedDeclaration _ _ d) = getTypeName d-  getTypeName _ = Nothing--identNames :: P.Module -> [(N.Ident, P.Declaration)]-identNames = nubOnFst . mapMaybe getDeclName . P.exportedDeclarations-  where-  getDeclName :: P.Declaration -> Maybe (P.Ident, P.Declaration)-  getDeclName d@(P.ValueDeclaration ident _ _ _)  = Just (ident, d)-  getDeclName d@(P.ExternDeclaration _ ident _ _) = Just (ident, d)-  getDeclName (P.PositionedDeclaration _ _ d) = getDeclName d-  getDeclName _ = Nothing--dctorNames :: P.Module -> [(N.ProperName, P.Declaration)]-dctorNames m = nubOnFst $ concatMap dctors dnames-  where-  getDataDeclName :: P.Declaration -> Maybe (N.ProperName, P.Declaration)-  getDataDeclName d@(P.DataDeclaration _ name _ _) = Just (name, d)-  getDataDeclName (P.PositionedDeclaration _ _ d) = getDataDeclName d-  getDataDeclName _ = Nothing--  dnames :: [(N.ProperName, P.Declaration)]-  dnames = (mapMaybe getDataDeclName onlyDataDecls)--  onlyDataDecls :: [P.Declaration]-  onlyDataDecls = (filter P.isDataDecl (P.exportedDeclarations m))--  dctors :: (N.ProperName, P.Declaration) -> [(N.ProperName, P.Declaration)]-  dctors (name, decl) = map (\n -> (n, decl)) (map fst (P.exportedDctors m name))--moduleNames :: [P.Module] -> [String]-moduleNames ms = nub [show moduleName | P.Module _ moduleName _ _ <- ms]--directivesFirst :: Completion -> Completion -> Ordering-directivesFirst (Completion _ d1 _) (Completion _ d2 _) = go d1 d2-  where-  go (':' : xs) (':' : ys) = compare xs ys-  go (':' : _) _ = LT-  go _ (':' : _) = GT-  go xs ys = compare xs ys
psci/Directive.hs view
@@ -15,85 +15,46 @@  module Directive where -import Data.Maybe (fromJust, listToMaybe)-import Data.List (isPrefixOf)-import Data.Tuple (swap)--import Types---- |--- List of all avaliable directives.----directives :: [Directive]-directives = map fst directiveStrings---- |--- A mapping of directives to the different strings that can be used to invoke--- them.----directiveStrings :: [(Directive, [String])]-directiveStrings =-    [ (Help   , ["?", "help"])-    , (Quit   , ["quit"])-    , (Reset  , ["reset"])-    , (Browse , ["browse"])-    , (Load   , ["load", "module"])-    , (Type   , ["type"])-    , (Kind   , ["kind"])-    , (Show   , ["show"])-    ]---- |--- Like directiveStrings, but the other way around.----directiveStrings' :: [(String, Directive)]-directiveStrings' = concatMap go directiveStrings-  where-  go (dir, strs) = map (\s -> (s, dir)) strs---- |--- List of all directive strings.----strings :: [String]-strings = concatMap snd directiveStrings+import Data.List (nub, isPrefixOf) --- |--- Returns all possible string representations of a directive.----stringsFor :: Directive -> [String]-stringsFor d = fromJust (lookup d directiveStrings)+data Directive+  = Help+  | Quit+  | Reset+  | Browse+  | Load+  | Type+  | Kind+  | Show+  deriving Eq  -- |--- Returns the default string representation of a directive.+-- Maps given directive to relating command strings. ---stringFor :: Directive -> String-stringFor = head . stringsFor+commands :: Directive -> [String]+commands Help = ["?", "help"]+commands Quit = ["quit"]+commands Reset = ["reset"]+commands Browse = ["browse"]+commands Load = ["load", "module"]+commands Type = ["type"]+commands Kind = ["kind"]+commands Show = ["show"]  -- |--- Returns the list of directives which could be expanded from the string--- argument, together with the string alias that matched.+-- Tries to parse given string into a directive. ---directivesFor' :: String -> [(Directive, String)]-directivesFor' str = go directiveStrings'-  where-  go = map swap . filter ((str `isPrefixOf`) . fst)--directivesFor :: String -> [Directive]-directivesFor = map fst . directivesFor'--directiveStringsFor :: String -> [String]-directiveStringsFor = map snd . directivesFor'- parseDirective :: String -> Maybe Directive-parseDirective = listToMaybe . directivesFor+parseDirective cmd =+  case filter (matches . snd) mapping of+    [directive] -> Just $ fst directive+    _ -> Nothing+  where+  mapping :: [(Directive, [String])]+  mapping = zip directives (map commands directives) --- |--- True if the given directive takes an argument, false otherwise.-hasArgument :: Directive -> Bool-hasArgument Help = False-hasArgument Quit = False-hasArgument Reset = False-hasArgument _ = True+  matches :: [String] -> Bool+  matches = any (cmd `isPrefixOf`)  -- | -- The help menu.@@ -102,12 +63,17 @@ help =   [ (Help,   "",         "Show this help menu")   , (Quit,   "",         "Quit PSCi")-  , (Reset,  "",         "Discard all imported modules and declared bindings")-  , (Browse, "<module>", "See all functions in <module>")+  , (Reset,  "",         "Reset")+  , (Browse, "<module>", "Browse <module>")   , (Load,   "<file>",   "Load <file> for importing")   , (Type,   "<expr>",   "Show the type of <expr>")   , (Kind,   "<type>",   "Show the kind of <type>")-  , (Show,   "import",   "Show all imported modules")-  , (Show,   "loaded",   "Show all loaded modules")+  , (Show,   "import",   "Show imported modules")+  , (Show,   "loaded",   "Show loaded modules")   ] +-- |+-- List of all avaliable directives.+--+directives :: [Directive]+directives = nub . map (\(dir, _, _) -> dir) $ help
+ psci/Main.hs view
@@ -0,0 +1,702 @@+-----------------------------------------------------------------------------+--+-- Module      :  Main+-- Copyright   :  (c) Phil Freeman 2013+-- License     :  MIT+--+-- Maintainer  :  Phil Freeman <paf31@cantab.net>+-- Stability   :  experimental+-- Portability :+--+-- |+-- PureScript Compiler Interactive.+--+-----------------------------------------------------------------------------++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE DoAndIfThenElse #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RecordWildCards #-}++module Main where++import Data.Foldable (traverse_)+import Data.List (intercalate, isPrefixOf, nub, sortBy, sort)+import Data.Maybe (mapMaybe)+import Data.Traversable (traverse)+import Data.Version (showVersion)+import Data.Char (isSpace)+import qualified Data.Map as M++import Control.Applicative+import Control.Monad+import Control.Monad.Except (ExceptT(..), MonadError, runExceptT)+import Control.Monad.Reader (MonadReader, ReaderT, runReaderT)+import Control.Monad.Trans.Class+import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)+import Control.Monad.Trans.State.Strict+import qualified Control.Monad.Trans.State.Lazy as L++import Options.Applicative as Opts++import System.Console.Haskeline+import System.Directory (createDirectoryIfMissing, getModificationTime, doesFileExist, findExecutable, getHomeDirectory, getCurrentDirectory)+import System.Exit+import System.FilePath (pathSeparator, takeDirectory, (</>), isPathSeparator)+import System.IO.Error (tryIOError)+import System.Process (readProcessWithExitCode)++import qualified Text.Parsec as Par (ParseError)++import qualified Language.PureScript as P+import qualified Language.PureScript.AST as D+import qualified Language.PureScript.Names as N+import qualified Paths_purescript as Paths++import qualified Commands as C+import qualified Directive as D+import Parser++data PSCiOptions = PSCiOptions+  { psciMultiLineMode  :: Bool+  , psciInputFile      :: [FilePath]+  , psciInputNodeFlags :: [String]+  }++-- |+-- The PSCI state.+-- Holds a list of imported modules, loaded files, and partial let bindings.+-- The let bindings are partial,+-- because it makes more sense to apply the binding to the final evaluated expression.+--+data PSCiState = PSCiState+  { psciImportedFilenames   :: [FilePath]+  , psciImportedModules     :: [C.ImportedModule]+  , psciLoadedModules       :: [(Either P.RebuildPolicy FilePath, P.Module)]+  , psciLetBindings         :: [P.Declaration]+  , psciNodeFlags           :: [String]+  }++psciImportedModuleNames :: PSCiState -> [P.ModuleName]+psciImportedModuleNames (PSCiState{psciImportedModules = is}) =+  map (\(mn, _, _) -> mn) is++-- State helpers++-- |+-- Updates the state to have more imported modules.+--+updateImportedFiles :: FilePath -> PSCiState -> PSCiState+updateImportedFiles filename st = st { psciImportedFilenames = filename : psciImportedFilenames st }++-- |+-- Updates the state to have more imported modules.+--+updateImportedModules :: C.ImportedModule -> PSCiState -> PSCiState+updateImportedModules im st = st { psciImportedModules = im : psciImportedModules st }++-- |+-- Updates the state to have more loaded files.+--+updateModules :: [(Either P.RebuildPolicy FilePath, P.Module)] -> PSCiState -> PSCiState+updateModules modules st = st { psciLoadedModules = psciLoadedModules st ++ modules }++-- |+-- Updates the state to have more let bindings.+--+updateLets :: [P.Declaration] -> PSCiState -> PSCiState+updateLets ds st = st { psciLetBindings = psciLetBindings st ++ ds }++-- File helpers+-- |+-- Load the necessary modules.+--+defaultImports :: [C.ImportedModule]+defaultImports = [(P.ModuleName [P.ProperName "Prelude"], D.Implicit, Nothing)]++-- |+-- Locates the node executable.+-- Checks for either @nodejs@ or @node@.+--+findNodeProcess :: IO (Maybe String)+findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names+  where names = ["nodejs", "node"]++-- |+-- Grabs the filename where the history is stored.+--+getHistoryFilename :: IO FilePath+getHistoryFilename = do+  home <- getHomeDirectory+  let filename = home </> ".purescript" </> "psci_history"+  mkdirp filename+  return filename++-- |+-- Loads a file for use with imports.+--+loadModule :: FilePath -> IO (Either String [P.Module])+loadModule filename = do+  content <- readFile filename+  return $ either (Left . show) (Right . map snd) $ P.parseModulesFromFiles id [(filename, content)]++-- |+-- Load all modules, including the Prelude+--+loadAllModules :: [FilePath] -> IO (Either Par.ParseError [(Either P.RebuildPolicy FilePath, P.Module)])+loadAllModules files = do+  filesAndContent <- forM files $ \filename -> do+    content <- readFile filename+    return (Right filename, content)+  return $ P.parseModulesFromFiles (either (const "") id) $ (Left P.RebuildNever, P.prelude) : filesAndContent++-- |+-- Load all modules, updating the application state+--+loadAllImportedModules :: PSCI ()+loadAllImportedModules = do+  files <- PSCI . lift $ fmap psciImportedFilenames get+  modulesOrFirstError <- psciIO $ loadAllModules files+  case modulesOrFirstError of+    Left err -> psciIO $ print err+    Right modules -> PSCI . lift . modify $ \st -> st { psciLoadedModules = modules }++-- |+-- Expands tilde in path.+--+expandTilde :: FilePath -> IO FilePath+expandTilde ('~':p:rest) | isPathSeparator p = (</> rest) <$> getHomeDirectory+expandTilde p = return p+-- Messages++-- |+-- The help message.+--+helpMessage :: String+helpMessage = "The following commands are available:\n\n    " +++  intercalate "\n    " (map line D.help)+  where+    line :: (D.Directive, String, String) -> String+    line (dir, arg, desc) = intercalate " "+          [ cmd+          , replicate (11 - length cmd) ' '+          , arg+          , replicate (11 - length arg) ' '+          , desc+          ]+      where cmd = ":" ++ head (D.commands dir)++-- |+-- The welcome prologue.+--+prologueMessage :: String+prologueMessage = intercalate "\n"+  [ " ____                 ____            _       _   "+  , "|  _ \\ _   _ _ __ ___/ ___|  ___ _ __(_)_ __ | |_ "+  , "| |_) | | | | '__/ _ \\___ \\ / __| '__| | '_ \\| __|"+  , "|  __/| |_| | | |  __/___) | (__| |  | | |_) | |_ "+  , "|_|    \\__,_|_|  \\___|____/ \\___|_|  |_| .__/ \\__|"+  , "                                       |_|        "+  , ""+  , ":? shows help"+  ]++-- |+-- The quit message.+--+quitMessage :: String+quitMessage = "See ya!"++-- Haskeline completions++data CompletionContext = Command String | FilePath String | Module | Identifier+                       | Type | Fixed [String] | Multiple [CompletionContext]+                         deriving (Show)++-- |+-- Decide what kind of completion we need based on input.+completionContext :: String -> String -> Maybe CompletionContext+completionContext cmd@"" _ = Just $ Multiple [Command cmd, Identifier]+completionContext (':' : cmd) word =+  case D.parseDirective dstr of+    Just directive | dstr `elem` D.commands directive -> context directive+    _ -> Just $ Command cmd+  where+  dstr :: String+  dstr = takeWhile (not . isSpace) cmd++  context :: D.Directive -> Maybe CompletionContext+  context D.Browse = Just Module+  context D.Load = Just $ FilePath word+  context D.Quit = Nothing+  context D.Reset = Nothing+  context D.Help = Nothing+  context D.Show = Just $ Fixed ["import", "loaded"]+  context D.Type = Just Identifier+  context D.Kind = Just Type+completionContext _ _ = Just Identifier++-- |+-- Loads module, function, and file completions.+--+completion :: CompletionFunc (StateT PSCiState IO)+completion = completeWordWithPrev Nothing " \t\n\r" findCompletions+  where+  findCompletions :: String -> String -> StateT PSCiState IO [Completion]+  findCompletions prev word = do+    let ctx = completionContext ((dropWhile isSpace (reverse prev)) ++ word) word+    completions <- case ctx of+      Nothing -> return []+      (Just c) -> (mapMaybe $ either (\cand -> if word `isPrefixOf` cand+                                               then Just $ simpleCompletion cand+                                               else Nothing) Just)+                  <$> getCompletion c+    return $ sortBy sorter completions++  getCompletion :: CompletionContext -> StateT PSCiState IO [Either String Completion]+  getCompletion (FilePath f) = (map Right) <$> listFiles f+  getCompletion Module = (map Left) <$> getModuleNames+  getCompletion Identifier = (map Left) <$> ((++) <$> getIdentNames <*> getDctorNames)+  getCompletion Type = (map Left) <$> getTypeNames+  getCompletion (Fixed list) = return $ (map Left) list+  getCompletion (Multiple contexts) = concat <$> mapM getCompletion contexts+  getCompletion (Command cmd) = return . map (Left . (":" ++)) . nub $ matching+    where+    matching :: [String]+    matching = filter (isPrefixOf cmd) . concatMap (D.commands) $ D.directives++  getLoadedModules :: StateT PSCiState IO [P.Module]+  getLoadedModules = map snd . psciLoadedModules <$> get++  getModuleNames :: StateT PSCiState IO [String]+  getModuleNames = moduleNames <$> getLoadedModules++  mapLoadedModulesAndQualify :: (Show a) => (P.Module -> [a]) -> StateT PSCiState IO [String]+  mapLoadedModulesAndQualify f = do+    ms <- getLoadedModules+    q <- sequence [qualifyIfNeeded m (f m) | m <- ms]+    return $ concat q++  getIdentNames :: StateT PSCiState IO [String]+  getIdentNames = mapLoadedModulesAndQualify identNames++  getDctorNames :: StateT PSCiState IO [String]+  getDctorNames = mapLoadedModulesAndQualify dctorNames++  getTypeNames :: StateT PSCiState IO [String]+  getTypeNames = mapLoadedModulesAndQualify typeDecls++  qualifyIfNeeded :: (Show a) => P.Module -> [a] -> StateT PSCiState IO [String]+  qualifyIfNeeded m decls = do+    let name = P.getModuleName m+    imported <- psciImportedModuleNames <$> get+    let qualified = map (P.Qualified $ Just name) decls+    if name `elem` imported then+        return $ map show $ qualified ++ (map (P.Qualified Nothing) decls)+    else+        return $ map show qualified++  typeDecls :: P.Module -> [N.ProperName]+  typeDecls m = mapMaybe getTypeName $ filter P.isDataDecl (P.exportedDeclarations m)+      where getTypeName :: P.Declaration -> Maybe N.ProperName+            getTypeName (P.TypeSynonymDeclaration name _ _) = Just name+            getTypeName (P.DataDeclaration _ name _ _) = Just name+            getTypeName (P.PositionedDeclaration _ _ d) = getTypeName d+            getTypeName _ = Nothing++  identNames :: P.Module -> [N.Ident]+  identNames (P.Module _ _ ds exports) = nub [ ident | ident <- mapMaybe (getDeclName exports) (D.flattenDecls ds) ]+    where getDeclName :: Maybe [P.DeclarationRef] -> P.Declaration -> Maybe P.Ident+          getDeclName exts decl@(P.ValueDeclaration ident _ _ _)  | P.isExported exts decl = Just ident+          getDeclName exts decl@(P.ExternDeclaration _ ident _ _) | P.isExported exts decl = Just ident+          getDeclName exts (P.PositionedDeclaration _ _ d) = getDeclName exts d+          getDeclName _ _ = Nothing++  dctorNames :: P.Module -> [N.ProperName]+  dctorNames m = nub $ concat $ map (P.exportedDctors m) dnames+    where getDataDeclName :: P.Declaration -> Maybe N.ProperName+          getDataDeclName (P.DataDeclaration _ name _ _) = Just name+          getDataDeclName (P.PositionedDeclaration _ _ d) = getDataDeclName d+          getDataDeclName _ = Nothing++          dnames :: [N.ProperName]+          dnames = (mapMaybe getDataDeclName onlyDataDecls)++          onlyDataDecls :: [P.Declaration]+          onlyDataDecls = (filter P.isDataDecl (P.exportedDeclarations m))++  moduleNames :: [P.Module] -> [String]+  moduleNames ms = nub [show moduleName | P.Module _ moduleName _ _ <- ms]++  sorter :: Completion -> Completion -> Ordering+  sorter (Completion _ d1 _) (Completion _ d2 _) = if ":" `isPrefixOf` d1 then LT else compare d1 d2++-- Compilation++-- | Compilation options.+--+options :: P.Options P.Make+options = P.Options False False False Nothing False False False P.MakeOptions++-- |+-- PSCI monad+--+newtype PSCI a = PSCI { runPSCI :: InputT (StateT PSCiState IO) a } deriving (Functor, Applicative, Monad)++psciIO :: IO a -> PSCI a+psciIO io = PSCI . lift $ lift io++newtype Make a = Make { unMake :: ReaderT (P.Options P.Make) (ExceptT String IO) a }+  deriving (Functor, Applicative, Monad, MonadError String, MonadReader (P.Options P.Make))++runMake :: Make a -> IO (Either String a)+runMake = runExceptT . flip runReaderT options . unMake++makeIO :: IO a -> Make a+makeIO = Make . lift . ExceptT . fmap (either (Left . show) Right) . tryIOError++instance P.MonadMake Make where+  getTimestamp path = makeIO $ do+    exists <- doesFileExist path+    traverse (const $ getModificationTime path) $ guard exists+  readTextFile path = makeIO $ readFile path+  writeTextFile path text = makeIO $ do+    mkdirp path+    writeFile path text+  progress s = unless (s == "Compiling $PSCI") $ makeIO . putStrLn $ s++mkdirp :: FilePath -> IO ()+mkdirp = createDirectoryIfMissing True . takeDirectory++-- |+-- Makes a volatile module to execute the current expression.+--+createTemporaryModule :: Bool -> PSCiState -> P.Expr -> P.Module+createTemporaryModule exec PSCiState{psciImportedModules = imports, psciLetBindings = lets} val =+  let+    moduleName = P.ModuleName [P.ProperName "$PSCI"]+    traceModule = P.ModuleName [P.ProperName "Debug", P.ProperName "Trace"]+    trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))+    mainValue = P.App trace (P.Var (P.Qualified Nothing (P.Ident "it")))+    itDecl = P.ValueDeclaration (P.Ident "it") P.Value [] $ Right val+    mainDecl = P.ValueDeclaration (P.Ident "main") P.Value [] $ Right mainValue+    decls = if exec then [itDecl, mainDecl] else [itDecl]+  in+    P.Module [] moduleName ((importDecl `map` imports) ++ lets ++ decls) Nothing+++-- |+-- Makes a volatile module to hold a non-qualified type synonym for a fully-qualified data type declaration.+--+createTemporaryModuleForKind :: PSCiState -> P.Type -> P.Module+createTemporaryModuleForKind PSCiState{psciImportedModules = imports} typ =+  let+    moduleName = P.ModuleName [P.ProperName "$PSCI"]+    itDecl = P.TypeSynonymDeclaration (P.ProperName "IT") [] typ+  in+    P.Module [] moduleName ((importDecl `map` imports) ++ [itDecl]) Nothing++-- |+-- Makes a volatile module to execute the current imports.+--+createTemporaryModuleForImports :: PSCiState -> P.Module+createTemporaryModuleForImports PSCiState{psciImportedModules = imports} =+  let+    moduleName = P.ModuleName [P.ProperName "$PSCI"]+  in+    P.Module [] moduleName (importDecl `map` imports) Nothing++importDecl :: C.ImportedModule -> P.Declaration+importDecl (mn, declType, asQ) = P.ImportDeclaration mn declType asQ++modulesDir :: FilePath+modulesDir = ".psci_modules" ++ pathSeparator : "node_modules"++indexFile :: FilePath+indexFile = ".psci_modules" ++ pathSeparator : "index.js"++-- |+-- Takes a value declaration and evaluates it with the current state.+--+handleDeclaration :: P.Expr -> PSCI ()+handleDeclaration val = do+  st <- PSCI $ lift get+  let m = createTemporaryModule True st val+  let nodeArgs = psciNodeFlags st ++ [indexFile]+  e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []+  case e of+    Left err -> PSCI $ outputStrLn err+    Right _ -> do+      psciIO $ writeFile indexFile "require('$PSCI').main();"+      process <- psciIO findNodeProcess+      result  <- psciIO $ traverse (\node -> readProcessWithExitCode node nodeArgs "") process+      case result of+        Just (ExitSuccess,   out, _)   -> PSCI $ outputStrLn out+        Just (ExitFailure _, _,   err) -> PSCI $ outputStrLn err+        Nothing                        -> PSCI $ outputStrLn "Couldn't find node.js"++-- |+-- Takes a list of declarations and updates the environment, then run a make. If the declaration fails,+-- restore the original environment.+--+handleDecls :: [P.Declaration] -> PSCI ()+handleDecls ds = do+  st <- PSCI $ lift get+  let st' = updateLets ds st+  let m = createTemporaryModule False st' (P.ObjectLiteral [])+  e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st' ++ [(Left P.RebuildAlways, m)]) []+  case e of+    Left err -> PSCI $ outputStrLn err+    Right _ -> PSCI $ lift (put st')++-- |+-- Show actual loaded modules in psci.+--+handleShowLoadedModules :: PSCI ()+handleShowLoadedModules = do+  PSCiState { psciLoadedModules = loadedModules } <- PSCI $ lift get+  psciIO $ readModules loadedModules >>= putStrLn+  return ()+  where readModules = return . unlines . sort . nub . map toModuleName+        toModuleName =  N.runModuleName . (\ (D.Module _ mdName _ _) -> mdName) . snd++-- |+-- Show the imported modules in psci.+--+handleShowImportedModules :: PSCI ()+handleShowImportedModules = do+  PSCiState { psciImportedModules = importedModules } <- PSCI $ lift get+  psciIO $ showModules importedModules >>= putStrLn+  return ()+  where+  showModules = return . unlines . sort . map showModule+  showModule (mn, declType, asQ) =+    "import " ++ case asQ of+      Just mn' -> "qualified " ++ N.runModuleName mn ++ " as " ++ N.runModuleName mn'+      Nothing  -> N.runModuleName mn ++ " " ++ showDeclType declType++  showDeclType D.Implicit = ""+  showDeclType (D.Explicit refs) = refsList refs+  showDeclType (D.Hiding refs) = "hiding " ++ refsList refs+  refsList refs = "(" ++ commaList (map showRef refs) ++ ")"++  showRef :: P.DeclarationRef -> String+  showRef (D.TypeRef pn dctors) = show pn ++ "(" ++ maybe ".." (commaList . map N.runProperName) dctors ++ ")"+  showRef (D.ValueRef ident) = show ident+  showRef (D.TypeClassRef pn) = show pn+  showRef (D.TypeInstanceRef ident) = show ident+  showRef (D.PositionedDeclarationRef _ _ ref) = showRef ref++  commaList :: [String] -> String+  commaList = intercalate ", "++-- |+-- Imports a module, preserving the initial state on failure.+--+handleImport :: C.ImportedModule -> PSCI ()+handleImport im = do+   st <- updateImportedModules im <$> PSCI (lift get)+   let m = createTemporaryModuleForImports st+   e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []+   case e of+     Left err -> PSCI $ outputStrLn err+     Right _  -> do+       PSCI $ lift $ put st+       return ()++-- |+-- Takes a value and prints its type+--+handleTypeOf :: P.Expr -> PSCI ()+handleTypeOf val = do+  st <- PSCI $ lift get+  let m = createTemporaryModule False st val+  e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []+  case e of+    Left err -> PSCI $ outputStrLn err+    Right env' ->+      case M.lookup (P.ModuleName [P.ProperName "$PSCI"], P.Ident "it") (P.names env') of+        Just (ty, _, _) -> PSCI . outputStrLn . P.prettyPrintType $ ty+        Nothing -> PSCI $ outputStrLn "Could not find type"++-- |+-- Pretty print a module's signatures+--+printModuleSignatures :: P.ModuleName -> P.Environment -> PSCI ()+printModuleSignatures moduleName env =+  PSCI $ let namesEnv = P.names env+             moduleNamesIdent = (filter ((== moduleName) . fst) . M.keys) namesEnv+             in case moduleNamesIdent of+                  [] -> outputStrLn $ "This module '"++ P.runModuleName moduleName ++"' does not export functions."+                  _ -> ( outputStrLn+                       . unlines+                       . sort+                       . map (showType . findType namesEnv)) moduleNamesIdent+  where findType :: M.Map (P.ModuleName, P.Ident) (P.Type, P.NameKind, P.NameVisibility) -> (P.ModuleName, P.Ident) -> (P.Ident, Maybe (P.Type, P.NameKind, P.NameVisibility))+        findType envNames m@(_, mIdent) = (mIdent, M.lookup m envNames)+        showType :: (P.Ident, Maybe (P.Type, P.NameKind, P.NameVisibility)) -> String+        showType (mIdent, Just (mType, _, _)) = show mIdent ++ " :: " ++ P.prettyPrintType mType+        showType _ = error "The impossible happened in printModuleSignatures."++-- |+-- Browse a module and displays its signature (if module exists).+--+handleBrowse :: P.ModuleName -> PSCI ()+handleBrowse moduleName = do+  st <- PSCI $ lift get+  let loadedModules = psciLoadedModules st+  env <- psciIO . runMake $ P.make modulesDir loadedModules []+  case env of+    Left err -> PSCI $ outputStrLn err+    Right env' ->+      if moduleName `notElem` (nub . map ((\ (P.Module _ modName _ _ ) -> modName) . snd)) loadedModules+        then PSCI $ outputStrLn $ "Module '" ++ N.runModuleName moduleName ++ "' is not valid."+        else printModuleSignatures moduleName env'++-- |+-- Takes a value and prints its kind+--+handleKindOf :: P.Type -> PSCI ()+handleKindOf typ = do+  st <- PSCI $ lift get+  let m = createTemporaryModuleForKind st typ+      mName = P.ModuleName [P.ProperName "$PSCI"]+  e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []+  case e of+    Left err -> PSCI $ outputStrLn err+    Right env' ->+      case M.lookup (P.Qualified (Just mName) $ P.ProperName "IT") (P.typeSynonyms env') of+        Just (_, typ') -> do+          let chk = P.CheckState env' 0 0 (Just mName)+              k   = L.runStateT (P.unCheck (P.kindOf mName typ')) chk+          case k of+            Left errStack   -> PSCI . outputStrLn . P.prettyPrintMultipleErrors False $ errStack+            Right (kind, _) -> PSCI . outputStrLn . P.prettyPrintKind $ kind+        Nothing -> PSCI $ outputStrLn "Could not find kind"++-- Commands++-- |+-- Parses the input and returns either a Metacommand or an expression.+--+getCommand :: Bool -> InputT (StateT PSCiState IO) (Either String (Maybe C.Command))+getCommand singleLineMode = do+  firstLine <- getInputLine "> "+  case firstLine of+    Nothing -> return (Right Nothing)+    Just "" -> return (Right Nothing)+    Just s | singleLineMode || head s == ':' -> return . either Left (Right . Just) $ parseCommand s+    Just s -> either Left (Right . Just) . parseCommand <$> go [s]+  where+    go :: [String] -> InputT (StateT PSCiState IO) String+    go ls = maybe (return . unlines $ reverse ls) (go . (:ls)) =<< getInputLine "  "++-- |+-- Performs an action for each meta-command given, and also for expressions..+--+handleCommand :: C.Command -> PSCI ()+handleCommand (C.Expression val) = handleDeclaration val+handleCommand C.Help = PSCI $ outputStrLn helpMessage+handleCommand (C.Import im) = handleImport im+handleCommand (C.Decls l) = handleDecls l+handleCommand (C.LoadFile filePath) = do+  absPath <- psciIO $ expandTilde filePath+  exists <- psciIO $ doesFileExist absPath+  if exists then do+    PSCI . lift $ modify (updateImportedFiles absPath)+    m <- psciIO $ loadModule absPath+    case m of+      Left err -> PSCI $ outputStrLn err+      Right mods -> PSCI . lift $ modify (updateModules (map ((,) (Right absPath)) mods))+  else+    PSCI . outputStrLn $ "Couldn't locate: " ++ filePath+handleCommand C.Reset = do+  files <- psciImportedFilenames <$> PSCI (lift get)+  PSCI . lift . modify $ \st -> st+    { psciImportedFilenames   = files+    , psciImportedModules     = defaultImports+    , psciLetBindings         = []+    }+  loadAllImportedModules+handleCommand (C.TypeOf val) = handleTypeOf val+handleCommand (C.KindOf typ) = handleKindOf typ+handleCommand (C.Browse moduleName) = handleBrowse moduleName+handleCommand (C.Show "loaded") = handleShowLoadedModules+handleCommand (C.Show "import") = handleShowImportedModules+handleCommand _ = PSCI $ outputStrLn "Unknown command"++loadUserConfig :: IO (Maybe [C.Command])+loadUserConfig = do+  configFile <- (</> ".psci") <$> getCurrentDirectory+  exists <- doesFileExist configFile+  if exists+  then do+    ls <- lines <$> readFile configFile+    case mapM parseCommand ls of+      Left err -> print err >> exitFailure+      Right cs -> return $ Just cs+  else+    return Nothing++-- |+-- The PSCI main loop.+--+loop :: PSCiOptions -> IO ()+loop PSCiOptions{..} = do+  config <- loadUserConfig+  modulesOrFirstError <- loadAllModules psciInputFile+  case modulesOrFirstError of+    Left err -> print err >> exitFailure+    Right modules -> do+      historyFilename <- getHistoryFilename+      let settings = defaultSettings { historyFile = Just historyFilename }+      flip evalStateT (PSCiState psciInputFile defaultImports modules [] psciInputNodeFlags) . runInputT (setComplete completion settings) $ do+        outputStrLn prologueMessage+        traverse_ (mapM_ (runPSCI . handleCommand)) config+        go+      where+        go :: InputT (StateT PSCiState IO) ()+        go = do+          c <- getCommand (not psciMultiLineMode)+          case c of+            Left err -> outputStrLn err >> go+            Right Nothing -> go+            Right (Just C.Quit) -> outputStrLn quitMessage+            Right (Just c') -> runPSCI (loadAllImportedModules >> handleCommand c') >> go++multiLineMode :: Parser Bool+multiLineMode = switch $+     long "multi-line-mode"+  <> short 'm'+  <> Opts.help "Run in multi-line mode (use ^D to terminate commands)"++inputFile :: Parser FilePath+inputFile = strArgument $+     metavar "FILE"+  <> Opts.help "Optional .purs files to load on start"++nodeFlagsFlag :: Parser [String]+nodeFlagsFlag = option parser $+     long "node-opts"+  <> metavar "NODE_OPTS"+  <> value []+  <> Opts.help "Flags to pass to node, separated by spaces"+  where+    parser = words <$> str++psciOptions :: Parser PSCiOptions+psciOptions = PSCiOptions <$> multiLineMode+                          <*> many inputFile+                          <*> nodeFlagsFlag++main :: IO ()+main = execParser opts >>= loop+  where+  opts        = info (version <*> helper <*> psciOptions) infoModList+  infoModList = fullDesc <> headerInfo <> footerInfo+  headerInfo  = header   "psci - Interactive mode for PureScript"+  footerInfo  = footer $ "psci " ++ showVersion Paths.version++  version :: Parser (a -> a)+  version = abortOption (InfoMsg (showVersion Paths.version)) $ long "version" <> Opts.help "Show the version number" <> hidden
− psci/PSCi.hs
@@ -1,543 +0,0 @@------------------------------------------------------------------------------------ Module      :  PSCi--- Copyright   :  (c) Phil Freeman 2013--- License     :  MIT------ Maintainer  :  Phil Freeman <paf31@cantab.net>--- Stability   :  experimental--- Portability :------ |--- PureScript Compiler Interactive.-----------------------------------------------------------------------------------{-# LANGUAGE DataKinds #-}-{-# LANGUAGE DoAndIfThenElse #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE RecordWildCards #-}--module PSCi where--import Data.Foldable (traverse_)-import Data.List (intercalate, nub, sort)-import Data.Traversable (traverse)-import Data.Version (showVersion)-import qualified Data.Map as M--import Control.Applicative-import Control.Monad-import Control.Monad.IO.Class (MonadIO, liftIO)-import Control.Monad.Error.Class (throwError)-import Control.Monad.Except (ExceptT(..), MonadError, runExceptT)-import Control.Monad.Reader (MonadReader, ReaderT, runReaderT)-import Control.Monad.Trans.Class-import Control.Monad.Trans.Maybe (MaybeT(..), runMaybeT)-import Control.Monad.Trans.State.Strict-import qualified Control.Monad.Trans.State.Lazy as L--import Options.Applicative as Opts--import System.Console.Haskeline-import System.Directory (createDirectoryIfMissing, getModificationTime, doesFileExist, findExecutable, getHomeDirectory, getCurrentDirectory)-import System.Exit-import System.FilePath (pathSeparator, takeDirectory, (</>), isPathSeparator)-import System.IO.Error (tryIOError)-import System.Process (readProcessWithExitCode)--import qualified Text.Parsec as Par (ParseError)--import qualified Language.PureScript as P-import qualified Language.PureScript.Names as N-import qualified Paths_purescript as Paths--import qualified Directive as D-import Parser (parseCommand)-import Completion (completion)-import Types----- File helpers--- |--- Load the necessary modules.----defaultImports :: [ImportedModule]-defaultImports = [(P.ModuleName [P.ProperName "Prelude"], P.Implicit, Nothing)]---- |--- Locates the node executable.--- Checks for either @nodejs@ or @node@.----findNodeProcess :: IO (Maybe String)-findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names-  where names = ["nodejs", "node"]---- |--- Grabs the filename where the history is stored.----getHistoryFilename :: IO FilePath-getHistoryFilename = do-  home <- getHomeDirectory-  let filename = home </> ".purescript" </> "psci_history"-  mkdirp filename-  return filename---- |--- Loads a file for use with imports.----loadModule :: FilePath -> IO (Either String [P.Module])-loadModule filename = do-  content <- readFile filename-  return $ either (Left . show) (Right . map snd) $ P.parseModulesFromFiles id [(filename, content)]---- |--- Load all modules, including the Prelude----loadAllModules :: [FilePath] -> IO (Either Par.ParseError [(Either P.RebuildPolicy FilePath, P.Module)])-loadAllModules files = do-  filesAndContent <- forM files $ \filename -> do-    content <- readFile filename-    return (Right filename, content)-  return $ P.parseModulesFromFiles (either (const "") id) $ (Left P.RebuildNever, P.prelude) : filesAndContent---- |--- Load all modules, updating the application state----loadAllImportedModules :: PSCI ()-loadAllImportedModules = do-  files <- PSCI . lift $ fmap psciImportedFilenames get-  modulesOrFirstError <- psciIO $ loadAllModules files-  case modulesOrFirstError of-    Left err -> psciIO $ print err-    Right modules -> PSCI . lift . modify $ \st -> st { psciLoadedModules = modules }---- |--- Expands tilde in path.----expandTilde :: FilePath -> IO FilePath-expandTilde ('~':p:rest) | isPathSeparator p = (</> rest) <$> getHomeDirectory-expandTilde p = return p--- Messages---- |--- The help message.----helpMessage :: String-helpMessage = "The following commands are available:\n\n    " ++-  intercalate "\n    " (map line D.help) ++-  "\n\n" ++ extraHelp-  where-  line :: (Directive, String, String) -> String-  line (dir, arg, desc) =-    let cmd = ':' : D.stringFor dir-    in intercalate " "-        [ cmd-        , replicate (11 - length cmd) ' '-        , arg-        , replicate (11 - length arg) ' '-        , desc-        ]--  extraHelp =-    "Further information is available on the PureScript wiki:\n" ++-    " --> https://github.com/purescript/purescript/wiki/psci"----- |--- The welcome prologue.----prologueMessage :: String-prologueMessage = intercalate "\n"-  [ " ____                 ____            _       _   "-  , "|  _ \\ _   _ _ __ ___/ ___|  ___ _ __(_)_ __ | |_ "-  , "| |_) | | | | '__/ _ \\___ \\ / __| '__| | '_ \\| __|"-  , "|  __/| |_| | | |  __/___) | (__| |  | | |_) | |_ "-  , "|_|    \\__,_|_|  \\___|____/ \\___|_|  |_| .__/ \\__|"-  , "                                       |_|        "-  , ""-  , ":? shows help"-  ]---- |--- The quit message.----quitMessage :: String-quitMessage = "See ya!"----- Compilation---- | Compilation options.----options :: P.Options P.Make-options = P.Options False False False Nothing False False False P.MakeOptions---- |--- PSCI monad----newtype PSCI a = PSCI { runPSCI :: InputT (StateT PSCiState IO) a } deriving (Functor, Applicative, Monad)--psciIO :: IO a -> PSCI a-psciIO io = PSCI . lift $ lift io--newtype Make a = Make { unMake :: ReaderT (P.Options P.Make) (ExceptT P.MultipleErrors IO) a }-  deriving (Functor, Applicative, Monad, MonadIO, MonadError P.MultipleErrors, MonadReader (P.Options P.Make))--runMake :: Make a -> IO (Either P.MultipleErrors a)-runMake = runExceptT . flip runReaderT options . unMake--makeIO :: (IOError -> P.ErrorMessage) -> IO a -> Make a-makeIO f io = do-  e <- liftIO $ tryIOError io-  either (throwError . P.errorMessage . f) return e--instance P.MonadMake Make where-  getTimestamp path = makeIO (const (P.CannotGetFileInfo path)) $ do-    exists <- doesFileExist path-    traverse (const $ getModificationTime path) $ guard exists-  readTextFile path = makeIO (const (P.CannotReadFile path)) $ readFile path-  writeTextFile path text = makeIO (const (P.CannotWriteFile path)) $ do-    mkdirp path-    writeFile path text-  progress s = unless (s == "Compiling $PSCI") $ liftIO . putStrLn $ s--mkdirp :: FilePath -> IO ()-mkdirp = createDirectoryIfMissing True . takeDirectory---- |--- Makes a volatile module to execute the current expression.----createTemporaryModule :: Bool -> PSCiState -> P.Expr -> P.Module-createTemporaryModule exec PSCiState{psciImportedModules = imports, psciLetBindings = lets} val =-  let-    moduleName = P.ModuleName [P.ProperName "$PSCI"]-    traceModule = P.ModuleName [P.ProperName "Debug", P.ProperName "Trace"]-    trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))-    mainValue = P.App trace (P.Var (P.Qualified Nothing (P.Ident "it")))-    itDecl = P.ValueDeclaration (P.Ident "it") P.Value [] $ Right val-    mainDecl = P.ValueDeclaration (P.Ident "main") P.Value [] $ Right mainValue-    decls = if exec then [itDecl, mainDecl] else [itDecl]-  in-    P.Module [] moduleName ((importDecl `map` imports) ++ lets ++ decls) Nothing----- |--- Makes a volatile module to hold a non-qualified type synonym for a fully-qualified data type declaration.----createTemporaryModuleForKind :: PSCiState -> P.Type -> P.Module-createTemporaryModuleForKind PSCiState{psciImportedModules = imports} typ =-  let-    moduleName = P.ModuleName [P.ProperName "$PSCI"]-    itDecl = P.TypeSynonymDeclaration (P.ProperName "IT") [] typ-  in-    P.Module [] moduleName ((importDecl `map` imports) ++ [itDecl]) Nothing---- |--- Makes a volatile module to execute the current imports.----createTemporaryModuleForImports :: PSCiState -> P.Module-createTemporaryModuleForImports PSCiState{psciImportedModules = imports} =-  let-    moduleName = P.ModuleName [P.ProperName "$PSCI"]-  in-    P.Module [] moduleName (importDecl `map` imports) Nothing--importDecl :: ImportedModule -> P.Declaration-importDecl (mn, declType, asQ) = P.ImportDeclaration mn declType asQ--modulesDir :: FilePath-modulesDir = ".psci_modules" ++ pathSeparator : "node_modules"--indexFile :: FilePath-indexFile = ".psci_modules" ++ pathSeparator : "index.js"---- |--- Takes a value declaration and evaluates it with the current state.----handleDeclaration :: P.Expr -> PSCI ()-handleDeclaration val = do-  st <- PSCI $ lift get-  let m = createTemporaryModule True st val-  let nodeArgs = psciNodeFlags st ++ [indexFile]-  e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []-  case e of-    Left errs -> printErrors errs-    Right _ -> do-      psciIO $ writeFile indexFile "require('$PSCI').main();"-      process <- psciIO findNodeProcess-      result  <- psciIO $ traverse (\node -> readProcessWithExitCode node nodeArgs "") process-      case result of-        Just (ExitSuccess,   out, _)   -> PSCI $ outputStrLn out-        Just (ExitFailure _, _,   err) -> PSCI $ outputStrLn err-        Nothing                        -> PSCI $ outputStrLn "Couldn't find node.js"---- |--- Takes a list of declarations and updates the environment, then run a make. If the declaration fails,--- restore the original environment.----handleDecls :: [P.Declaration] -> PSCI ()-handleDecls ds = do-  st <- PSCI $ lift get-  let st' = updateLets ds st-  let m = createTemporaryModule False st' (P.ObjectLiteral [])-  e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st' ++ [(Left P.RebuildAlways, m)]) []-  case e of-    Left err -> printErrors err-    Right _ -> PSCI $ lift (put st')---- |--- Show actual loaded modules in psci.----handleShowLoadedModules :: PSCI ()-handleShowLoadedModules = do-  PSCiState { psciLoadedModules = loadedModules } <- PSCI $ lift get-  psciIO $ readModules loadedModules >>= putStrLn-  return ()-  where readModules = return . unlines . sort . nub . map toModuleName-        toModuleName =  N.runModuleName . (\ (P.Module _ mdName _ _) -> mdName) . snd---- |--- Show the imported modules in psci.----handleShowImportedModules :: PSCI ()-handleShowImportedModules = do-  PSCiState { psciImportedModules = importedModules } <- PSCI $ lift get-  psciIO $ showModules importedModules >>= putStrLn-  return ()-  where-  showModules = return . unlines . sort . map showModule-  showModule (mn, declType, asQ) =-    "import " ++ case asQ of-      Just mn' -> "qualified " ++ N.runModuleName mn ++ " as " ++ N.runModuleName mn'-      Nothing  -> N.runModuleName mn ++ " " ++ showDeclType declType--  showDeclType P.Implicit = ""-  showDeclType (P.Explicit refs) = refsList refs-  showDeclType (P.Hiding refs) = "hiding " ++ refsList refs-  refsList refs = "(" ++ commaList (map showRef refs) ++ ")"--  showRef :: P.DeclarationRef -> String-  showRef (P.TypeRef pn dctors) = show pn ++ "(" ++ maybe ".." (commaList . map N.runProperName) dctors ++ ")"-  showRef (P.ValueRef ident) = show ident-  showRef (P.TypeClassRef pn) = show pn-  showRef (P.TypeInstanceRef ident) = show ident-  showRef (P.PositionedDeclarationRef _ _ ref) = showRef ref--  commaList :: [String] -> String-  commaList = intercalate ", "---- |--- Imports a module, preserving the initial state on failure.----handleImport :: ImportedModule -> PSCI ()-handleImport im = do-   st <- updateImportedModules im <$> PSCI (lift get)-   let m = createTemporaryModuleForImports st-   e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []-   case e of-     Left errs -> printErrors errs-     Right _  -> do-       PSCI $ lift $ put st-       return ()---- |--- Takes a value and prints its type----handleTypeOf :: P.Expr -> PSCI ()-handleTypeOf val = do-  st <- PSCI $ lift get-  let m = createTemporaryModule False st val-  e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []-  case e of-    Left errs -> printErrors errs-    Right env' ->-      case M.lookup (P.ModuleName [P.ProperName "$PSCI"], P.Ident "it") (P.names env') of-        Just (ty, _, _) -> PSCI . outputStrLn . P.prettyPrintType $ ty-        Nothing -> PSCI $ outputStrLn "Could not find type"---- |--- Pretty print a module's signatures----printModuleSignatures :: P.ModuleName -> P.Environment -> PSCI ()-printModuleSignatures moduleName env =-  PSCI $ let namesEnv = P.names env-             moduleNamesIdent = (filter ((== moduleName) . fst) . M.keys) namesEnv-             in case moduleNamesIdent of-                  [] -> outputStrLn $ "This module '"++ P.runModuleName moduleName ++"' does not export functions."-                  _ -> ( outputStrLn-                       . unlines-                       . sort-                       . map (showType . findType namesEnv)) moduleNamesIdent-  where findType :: M.Map (P.ModuleName, P.Ident) (P.Type, P.NameKind, P.NameVisibility) -> (P.ModuleName, P.Ident) -> (P.Ident, Maybe (P.Type, P.NameKind, P.NameVisibility))-        findType envNames m@(_, mIdent) = (mIdent, M.lookup m envNames)-        showType :: (P.Ident, Maybe (P.Type, P.NameKind, P.NameVisibility)) -> String-        showType (mIdent, Just (mType, _, _)) = show mIdent ++ " :: " ++ P.prettyPrintType mType-        showType _ = error "The impossible happened in printModuleSignatures."---- |--- Browse a module and displays its signature (if module exists).----handleBrowse :: P.ModuleName -> PSCI ()-handleBrowse moduleName = do-  st <- PSCI $ lift get-  let loadedModules = psciLoadedModules st-  env <- psciIO . runMake $ P.make modulesDir loadedModules []-  case env of-    Left errs -> printErrors errs-    Right env' ->-      if moduleName `notElem` (nub . map ((\ (P.Module _ modName _ _ ) -> modName) . snd)) loadedModules-        then PSCI $ outputStrLn $ "Module '" ++ N.runModuleName moduleName ++ "' is not valid."-        else printModuleSignatures moduleName env'---- | Pretty-print errors-printErrors :: P.MultipleErrors -> PSCI ()-printErrors = PSCI . outputStrLn . P.prettyPrintMultipleErrors False---- |--- Takes a value and prints its kind----handleKindOf :: P.Type -> PSCI ()-handleKindOf typ = do-  st <- PSCI $ lift get-  let m = createTemporaryModuleForKind st typ-      mName = P.ModuleName [P.ProperName "$PSCI"]-  e <- psciIO . runMake $ P.make modulesDir (psciLoadedModules st ++ [(Left P.RebuildAlways, m)]) []-  case e of-    Left errs -> printErrors errs-    Right env' ->-      case M.lookup (P.Qualified (Just mName) $ P.ProperName "IT") (P.typeSynonyms env') of-        Just (_, typ') -> do-          let chk = P.CheckState env' 0 0 (Just mName)-              k   = L.runStateT (P.unCheck (P.kindOf mName typ')) chk-          case k of-            Left errStack   -> PSCI . outputStrLn . P.prettyPrintMultipleErrors False $ errStack-            Right (kind, _) -> PSCI . outputStrLn . P.prettyPrintKind $ kind-        Nothing -> PSCI $ outputStrLn "Could not find kind"---- Commands---- |--- Parses the input and returns either a Metacommand, or an error as a string.----getCommand :: Bool -> InputT (StateT PSCiState IO) (Either String (Maybe Command))-getCommand singleLineMode = do-  firstLine <- getInputLine "> "-  case firstLine of-    Nothing -> return (Right Nothing)-    Just "" -> return (Right Nothing)-    Just s | singleLineMode || head s == ':' -> return . either Left (Right . Just) $ parseCommand s-    Just s -> either Left (Right . Just) . parseCommand <$> go [s]-  where-    go :: [String] -> InputT (StateT PSCiState IO) String-    go ls = maybe (return . unlines $ reverse ls) (go . (:ls)) =<< getInputLine "  "---- |--- Performs an action for each meta-command given, and also for expressions.----handleCommand :: Command -> PSCI ()-handleCommand (Expression val) = handleDeclaration val-handleCommand ShowHelp = PSCI $ outputStrLn helpMessage-handleCommand (Import im) = handleImport im-handleCommand (Decls l) = handleDecls l-handleCommand (LoadFile filePath) = do-  absPath <- psciIO $ expandTilde filePath-  exists <- psciIO $ doesFileExist absPath-  if exists then do-    PSCI . lift $ modify (updateImportedFiles absPath)-    m <- psciIO $ loadModule absPath-    case m of-      Left err -> PSCI $ outputStrLn err-      Right mods -> PSCI . lift $ modify (updateModules (map ((,) (Right absPath)) mods))-  else-    PSCI . outputStrLn $ "Couldn't locate: " ++ filePath-handleCommand ResetState = do-  files <- psciImportedFilenames <$> PSCI (lift get)-  PSCI . lift . modify $ \st -> st-    { psciImportedFilenames   = files-    , psciImportedModules     = defaultImports-    , psciLetBindings         = []-    }-  loadAllImportedModules-handleCommand (TypeOf val) = handleTypeOf val-handleCommand (KindOf typ) = handleKindOf typ-handleCommand (BrowseModule moduleName) = handleBrowse moduleName-handleCommand (ShowInfo QueryLoaded) = handleShowLoadedModules-handleCommand (ShowInfo QueryImport) = handleShowImportedModules-handleCommand QuitPSCi = error "`handleCommand QuitPSCi` was called. This is a bug."--loadUserConfig :: IO (Maybe [Command])-loadUserConfig = do-  configFile <- (</> ".psci") <$> getCurrentDirectory-  exists <- doesFileExist configFile-  if exists-  then do-    ls <- lines <$> readFile configFile-    case mapM parseCommand ls of-      Left err -> print err >> exitFailure-      Right cs -> return $ Just cs-  else-    return Nothing---- |--- The PSCI main loop.----loop :: PSCiOptions -> IO ()-loop PSCiOptions{..} = do-  config <- loadUserConfig-  modulesOrFirstError <- loadAllModules psciInputFile-  case modulesOrFirstError of-    Left err -> print err >> exitFailure-    Right modules -> do-      historyFilename <- getHistoryFilename-      let settings = defaultSettings { historyFile = Just historyFilename }-      flip evalStateT (PSCiState psciInputFile defaultImports modules [] psciInputNodeFlags) . runInputT (setComplete completion settings) $ do-        outputStrLn prologueMessage-        traverse_ (mapM_ (runPSCI . handleCommand)) config-        go-      where-        go :: InputT (StateT PSCiState IO) ()-        go = do-          c <- getCommand (not psciMultiLineMode)-          case c of-            Left err -> outputStrLn err >> go-            Right Nothing -> go-            Right (Just QuitPSCi) -> outputStrLn quitMessage-            Right (Just c') -> runPSCI (loadAllImportedModules >> handleCommand c') >> go--multiLineMode :: Parser Bool-multiLineMode = switch $-     long "multi-line-mode"-  <> short 'm'-  <> Opts.help "Run in multi-line mode (use ^D to terminate commands)"--inputFile :: Parser FilePath-inputFile = strArgument $-     metavar "FILE"-  <> Opts.help "Optional .purs files to load on start"--nodeFlagsFlag :: Parser [String]-nodeFlagsFlag = option parser $-     long "node-opts"-  <> metavar "NODE_OPTS"-  <> value []-  <> Opts.help "Flags to pass to node, separated by spaces"-  where-    parser = words <$> str--psciOptions :: Parser PSCiOptions-psciOptions = PSCiOptions <$> multiLineMode-                          <*> many inputFile-                          <*> nodeFlagsFlag--runPSCi :: IO ()-runPSCi = execParser opts >>= loop-  where-  opts        = info (version <*> helper <*> psciOptions) infoModList-  infoModList = fullDesc <> headerInfo <> footerInfo-  headerInfo  = header   "psci - Interactive mode for PureScript"-  footerInfo  = footer $ "psci " ++ showVersion Paths.version--  version :: Parser (a -> a)-  version = abortOption (InfoMsg (showVersion Paths.version)) $ long "version" <> Opts.help "Show the version number" <> hidden
psci/Parser.hs view
@@ -19,23 +19,22 @@  import Prelude hiding (lex) +import qualified Commands as C+import qualified Directive as D+ import Data.Char (isSpace)-import Data.List (intercalate)  import Control.Applicative hiding (many)  import Text.Parsec hiding ((<|>))  import qualified Language.PureScript as P-import Language.PureScript.Parser.Common (mark, same)--import qualified Directive as D-import Types+import qualified Language.PureScript.Parser.Common as C (mark, same)  -- | -- Parses PSCI metacommands or expressions input from the user. ---parseCommand :: String -> Either String Command+parseCommand :: String -> Either String C.Command parseCommand cmdString =   case cmdString of     (':' : cmd) -> parseDirective cmd@@ -46,7 +45,7 @@   ts <- P.lex "" s   P.runTokenParser "" (p <* eof) ts -psciCommand :: P.TokenParser Command+psciCommand :: P.TokenParser C.Command psciCommand = choice (map try parsers)   where   parsers =@@ -65,31 +64,25 @@ trimEnd :: String -> String trimEnd = reverse . trimStart . reverse -parseDirective :: String -> Either String Command+parseDirective :: String -> Either String C.Command parseDirective cmd =-  case D.directivesFor' dstr of-    [(d, _)] -> commandFor d-    []       -> Left "Unrecognized directive. Type :? for help."-    ds       -> Left ("Ambiguous directive. Possible matches: " ++-                  intercalate ", " (map snd ds) ++ ". Type :? for help.")-  where-  (dstr, arg) = break isSpace cmd--  commandFor d = case d of-    Help   -> return ShowHelp-    Quit   -> return QuitPSCi-    Reset  -> return ResetState-    Browse -> BrowseModule <$> parseRest P.moduleName arg-    Load   -> return $ LoadFile (trim arg)-    Show   -> ShowInfo <$> parseReplQuery' (trim arg)-    Type   -> TypeOf <$> parseRest P.parseValue arg-    Kind   -> KindOf <$> parseRest P.parseType arg+  case D.parseDirective dstr of+    Just D.Help -> return C.Help+    Just D.Quit -> return C.Quit+    Just D.Reset -> return C.Reset+    Just D.Browse -> C.Browse <$> parseRest P.moduleName arg+    Just D.Load -> return $ C.LoadFile (trim arg)+    Just D.Show -> return $ C.Show (trim arg)+    Just D.Type -> C.TypeOf <$> parseRest P.parseValue arg+    Just D.Kind -> C.KindOf <$> parseRest P.parseType arg+    Nothing -> Left $ "Unrecognized command. Type :? for help."+  where (dstr, arg) = break isSpace cmd  -- | -- Parses expressions entered at the PSCI repl. ---psciExpression :: P.TokenParser Command-psciExpression = Expression <$> P.parseValue+psciExpression :: P.TokenParser C.Command+psciExpression = C.Expression <$> P.parseValue  -- | -- PSCI version of @let@.@@ -97,21 +90,21 @@ -- However, since we don't support the @Eff@ monad, -- we actually want the normal @let@. ---psciLet :: P.TokenParser Command-psciLet = Decls <$> (P.reserved "let" *> P.indented *> manyDecls)+psciLet :: P.TokenParser C.Command+psciLet = C.Decls <$> (P.reserved "let" *> P.indented *> manyDecls)   where   manyDecls :: P.TokenParser [P.Declaration]-  manyDecls = mark (many1 (same *> P.parseLocalDeclaration))+  manyDecls = C.mark (many1 (C.same *> P.parseLocalDeclaration))  -- | Imports must be handled separately from other declarations, so that -- :show import works, for example.-psciImport :: P.TokenParser Command-psciImport = Import <$> P.parseImportDeclaration'+psciImport :: P.TokenParser C.Command+psciImport = C.Import <$> P.parseImportDeclaration'  -- | Any other declaration that we don't need a 'special case' parser for -- (like let or import declarations).-psciOtherDeclaration :: P.TokenParser Command-psciOtherDeclaration = Decls . (:[]) <$> do+psciOtherDeclaration :: P.TokenParser C.Command+psciOtherDeclaration = C.Decls . (:[]) <$> do   decl <- discardPositionInfo <$> P.parseDeclaration   if acceptable decl     then return decl@@ -130,10 +123,3 @@ acceptable (P.TypeClassDeclaration _ _ _ _) = True acceptable (P.TypeInstanceDeclaration _ _ _ _ _) = True acceptable _ = False--parseReplQuery' :: String -> Either String ReplQuery-parseReplQuery' str =-  case parseReplQuery str of-    Nothing -> Left ("Don't know how to show " ++ str ++ ". Try one of: " ++-                      intercalate ", " replQueryStrings ++ ".")-    Just query -> Right query
− psci/Types.hs
@@ -1,167 +0,0 @@------------------------------------------------------------------------------------ Module      :  Types--- Copyright   :  (c) Phil Freeman 2014--- License     :  MIT------ Maintainer  :  Phil Freeman <paf31@cantab.net>--- Stability   :  experimental--- Portability :------ |--- Type declarations and associated basic functions for PSCI.-----------------------------------------------------------------------------------module Types where--import qualified Language.PureScript as P--data PSCiOptions = PSCiOptions-  { psciMultiLineMode  :: Bool-  , psciInputFile      :: [FilePath]-  , psciInputNodeFlags :: [String]-  }---- |--- The PSCI state.--- Holds a list of imported modules, loaded files, and partial let bindings.--- The let bindings are partial,--- because it makes more sense to apply the binding to the final evaluated expression.----data PSCiState = PSCiState-  { psciImportedFilenames   :: [FilePath]-  , psciImportedModules     :: [ImportedModule]-  , psciLoadedModules       :: [(Either P.RebuildPolicy FilePath, P.Module)]-  , psciLetBindings         :: [P.Declaration]-  , psciNodeFlags           :: [String]-  }---- | All of the data that is contained by an ImportDeclaration in the AST.--- That is:------ * A module name, the name of the module which is being imported--- * An ImportDeclarationType which specifies whether there is an explicit---   import list, a hiding list, or neither.--- * If the module is imported qualified, its qualified name in the importing---   module. Otherwise, Nothing.----type ImportedModule = (P.ModuleName, P.ImportDeclarationType, Maybe P.ModuleName)--psciImportedModuleNames :: PSCiState -> [P.ModuleName]-psciImportedModuleNames (PSCiState{psciImportedModules = is}) =-  map (\(mn, _, _) -> mn) is--allImportsOf :: P.Module -> PSCiState -> [ImportedModule]-allImportsOf m (PSCiState{psciImportedModules = is}) =-  filter isImportOfThis is-  where-  name = P.getModuleName m-  isImportOfThis (name', _, _) = name == name'---- State helpers---- |--- Updates the state to have more imported modules.----updateImportedFiles :: FilePath -> PSCiState -> PSCiState-updateImportedFiles filename st = st { psciImportedFilenames = filename : psciImportedFilenames st }---- |--- Updates the state to have more imported modules.----updateImportedModules :: ImportedModule -> PSCiState -> PSCiState-updateImportedModules im st = st { psciImportedModules = im : psciImportedModules st }---- |--- Updates the state to have more loaded files.----updateModules :: [(Either P.RebuildPolicy FilePath, P.Module)] -> PSCiState -> PSCiState-updateModules modules st = st { psciLoadedModules = psciLoadedModules st ++ modules }---- |--- Updates the state to have more let bindings.----updateLets :: [P.Declaration] -> PSCiState -> PSCiState-updateLets ds st = st { psciLetBindings = psciLetBindings st ++ ds }---- |--- Valid Meta-commands for PSCI----data Command-  -- |-  -- A purescript expression-  ---  = Expression P.Expr-  -- |-  -- Show the help (ie, list of directives)-  ---  | ShowHelp-  -- |-  -- Import a module from a loaded file-  ---  | Import ImportedModule-  -- |-  -- Browse a module-  ---  | BrowseModule P.ModuleName-  -- |-  -- Load a file for use with importing-  ---  | LoadFile FilePath-  -- |-  -- Exit PSCI-  ---  | QuitPSCi-  -- |-  -- Reset the state of the REPL-  ---  | ResetState-  -- |-  -- Add some declarations to the current evaluation context.-  ---  | Decls [P.Declaration]-  -- |-  -- Find the type of an expression-  ---  | TypeOf P.Expr-  -- |-  -- Find the kind of an expression-  ---  | KindOf P.Type-  -- |-  -- Shows information about the current state of the REPL-  ---  | ShowInfo ReplQuery--data ReplQuery-  = QueryLoaded-  | QueryImport-  deriving (Eq, Show)---- | A list of all ReplQuery values.-replQueries :: [ReplQuery]-replQueries = [QueryLoaded, QueryImport]--replQueryStrings :: [String]-replQueryStrings = map showReplQuery replQueries--showReplQuery :: ReplQuery -> String-showReplQuery QueryLoaded = "loaded"-showReplQuery QueryImport = "import"--parseReplQuery :: String -> Maybe ReplQuery-parseReplQuery "loaded" = Just QueryLoaded-parseReplQuery "import" = Just QueryImport-parseReplQuery _ = Nothing--data Directive-  = Help-  | Quit-  | Reset-  | Browse-  | Load-  | Type-  | Kind-  | Show-  deriving (Eq, Show)
− psci/main/Main.hs
@@ -1,6 +0,0 @@-module Main where--import PSCi--main :: IO ()-main = runPSCi
− psci/tests/Main.hs
@@ -1,137 +0,0 @@-{-# LANGUAGE RecordWildCards #-}--module Main where--import Control.Monad.Trans.State.Strict (runStateT)-import Control.Monad (when)--import System.Exit (exitFailure)-import System.Console.Haskeline--import Test.HUnit--import qualified Language.PureScript as P--import PSCi-import Completion-import Types--main :: IO ()-main = do-  Counts{..} <- runTestTT allTests-  when (errors + failures > 0) exitFailure--allTests :: Test-allTests = completionTests--completionTests :: Test-completionTests =-  TestLabel "completionTests"-    (TestList (map (TestCase . assertCompletedOk) completionTestData))---- If the cursor is at the right end of the line, with the 1st element of the--- pair as the text in the line, then pressing tab should offer all the--- elements of the list (which is the 2nd element) as completions.-completionTestData :: [(String, [String])]-completionTestData =-  -- basic directives-  [ (":h", [":help"])-  , (":re", [":reset"])-  , (":q", [":quit"])-  , (":mo", [":module"])-  , (":b", [":browse"])--  -- :browse should complete modules-  , (":b Prel", [":b Prelude", ":b Prelude.Unsafe"])-  , (":b Prelude.", [":b Prelude.Unsafe"])--  -- :load, :module should complete file paths-  , (":l psci/tests/data/", [":l psci/tests/data/Sample.purs"])-  , (":module psci/tests/data/", [":module psci/tests/data/Sample.purs"])--  -- :quit, :help, :reset should not complete-  , (":help ", [])-  , (":quit ", [])-  , (":reset ", [])--  -- :show should complete to "loaded" and "import"-  , (":show ", [":show import", ":show loaded"])-  , (":show a", [])--  -- :type should complete values and data constructors in scope-  , (":type Prelude.Unsafe.un", [":type Prelude.Unsafe.unsafeIndex"])-  , (":type un", [":type unit"])-  , (":type E", [":type EQ"])--  -- :kind should complete types in scope-  , (":kind C", [":kind Control.Monad.Eff.Pure"])-  , (":kind O", [":kind Ordering"])--  -- Only one argument for directives should be completed-  , (":show import ", [])-  , (":type EQ ", [])-  , (":kind Ordering ", [])--  -- import should complete module names-  , ("import Control.Monad.S", ["import Control.Monad.ST"])-  , ("import qualified Control.Monad.S", ["import qualified Control.Monad.ST"])-  , ("import Control.Monad.", map ("import Control.Monad." ++)-                                  ["Eff", "Eff.Unsafe", "ST"])--  -- a few other import tests-  , ("impor", ["import"])-  , ("import q", ["import qualified"])-  , ("import ", map ("import " ++) allModuleNames ++ ["import qualified"])-  , ("import Prelude.Unsafe ", [])--  -- String and number literals should not be completed-  , ("\"hi", [])-  , ("34", [])--  -- Identifiers and data constructors should be completed-  , ("un", ["unit"])-  , ("Debug.Trace.", map ("Debug.Trace." ++) ["print", "trace"])-  , ("G", ["GT"])-  , ("Prelude.L", ["Prelude.LT"])--  -- if a module is imported qualified, values should complete under the-  -- qualified name, as well as the original name.-  , ("ST.new", ["ST.newSTRef"])-  , ("Control.Monad.ST.new", ["Control.Monad.ST.newSTRef"])-  ]-  where-  allModuleNames = [ "Control.Monad.Eff"-                   , "Control.Monad.Eff.Unsafe"-                   , "Control.Monad.ST"-                   , "Data.Function"-                   , "Debug.Trace"-                   , "Prelude"-                   , "Prelude.Unsafe"-                   ]--assertCompletedOk :: (String, [String]) -> Assertion-assertCompletedOk (line, expecteds) = do-  (unusedR, completions) <- runCM (completion' (reverse line, ""))-  let unused = reverse unusedR-  let actuals = map ((unused ++) . replacement) completions-  expecteds @=? actuals--runCM :: CompletionM a -> IO a-runCM act = do-  psciState <- getPSCiState-  fmap fst (runStateT (liftCompletionM act) psciState)--getPSCiState :: IO PSCiState-getPSCiState = do-  modulesOrFirstError <- loadAllModules []-  case modulesOrFirstError of-    Left err ->-      print err >> exitFailure-    Right modules ->-      let imports = controlMonadSTasST : defaultImports-      in  return (PSCiState [] imports modules [] [])--controlMonadSTasST :: ImportedModule-controlMonadSTasST = (s "Control.Monad.ST", P.Implicit, Just (s "ST"))-  where-  s = P.moduleNameFromString
purescript.cabal view
@@ -1,5 +1,5 @@ name: purescript-version: 0.6.9.4+version: 0.6.9.5 cabal-version: >=1.8 build-type: Simple license: MIT@@ -148,12 +148,10 @@      main-is: Main.hs     buildable: True-    hs-source-dirs: psci psci/main-    other-modules: Types+    hs-source-dirs: psci+    other-modules: Commands                    Parser                    Directive-                   Completion-                   PSCi     ghc-options: -Wall -O2  executable psc-docs@@ -184,14 +182,3 @@     main-is: Main.hs     buildable: True     hs-source-dirs: tests--test-suite psci-tests-    build-depends: base >=4 && <5, containers -any, directory -any, filepath -any,-                   mtl -any, optparse-applicative >= 0.10.0, parsec -any,-                   haskeline >= 0.7.0.0, purescript -any, transformers -any,-                   process -any, HUnit -any-    type: exitcode-stdio-1.0-    main-is: Main.hs-    buildable: True-    hs-source-dirs: psci psci/tests-    ghc-options: -Wall
src/Language/PureScript.hs view
@@ -89,20 +89,20 @@ -- --  * Pretty-print the generated Javascript ---compile :: (Functor m, Applicative m, MonadError MultipleErrors m, MonadReader (Options Compile) m)+compile :: (Functor m, Applicative m, MonadError String m, MonadReader (Options Compile) m)         => [Module] -> [String] -> m (String, String, Environment) compile = compile' initEnvironment -compile' :: (Functor m, Applicative m, MonadError MultipleErrors m, MonadReader (Options Compile) m)+compile' :: (Functor m, Applicative m, MonadError String m, MonadReader (Options Compile) m)          => Environment -> [Module] -> [String] -> m (String, String, Environment) compile' env ms prefix = do   noPrelude <- asks optionsNoPrelude   additional <- asks optionsAdditional   mainModuleIdent <- asks (fmap moduleNameFromString . optionsMain)   (sorted, _) <- sortModules $ map importPrim $ if noPrelude then ms else map importPrelude ms-  (desugared, nextVar) <- runSupplyT 0 $ desugar sorted+  (desugared, nextVar) <- interpretMultipleErrors True $ runSupplyT 0 $ desugar sorted   (elaborated, env') <- runCheck' env $ forM desugared $ typeCheckModule mainModuleIdent-  regrouped <- createBindingGroupsModule . collapseBindingGroupsModule $ elaborated+  regrouped <- interpretMultipleErrors True $ createBindingGroupsModule . collapseBindingGroupsModule $ elaborated   let corefn = map (CoreFn.moduleToCoreFn env') regrouped   let entryPoints = moduleNameFromString `map` entryPointModules additional   let elim = if null entryPoints then corefn else eliminateDeadCode entryPoints corefn@@ -115,21 +115,21 @@   let pjs = unlines $ map ("// " ++) prefix ++ [prettyPrintJS js']   return (pjs, exts, env') -generateMain :: (MonadError MultipleErrors m, MonadReader (Options Compile) m) => Environment -> [JS] -> m [JS]+generateMain :: (MonadError String m, MonadReader (Options Compile) m) => Environment -> [JS] -> m [JS] generateMain env js = do   main <- asks optionsMain   additional <- asks optionsAdditional   case moduleNameFromString <$> main of     Just mmi -> do       when ((mmi, Ident C.main) `M.notMember` names env) $-        throwError . errorMessage $ NameIsUndefined (Ident C.main)+        throwError $ show mmi ++ "." ++ C.main ++ " is undefined"       return $ js ++ [JSApp (JSAccessor C.main (JSAccessor (moduleNameToJs mmi) (JSVar (browserNamespace additional)))) []]     _ -> return js  -- | -- A type class which collects the IO actions we need to be able to run in "make" mode ---class (MonadReader (P.Options P.Make) m, MonadError MultipleErrors m) => MonadMake m where+class (MonadReader (P.Options P.Make) m, MonadError String m) => MonadMake m where   -- |   -- Get a file timestamp   --@@ -196,7 +196,7 @@    marked <- rebuildIfNecessary (reverseDependencies graph) toRebuild sorted -  (desugared, nextVar) <- runSupplyT 0 $ zip (map fst marked) <$> desugar (map snd marked)+  (desugared, nextVar) <- interpretMultipleErrors True $ runSupplyT 0 $ zip (map fst marked) <$> desugar (map snd marked)    evalSupplyT nextVar $ go initEnvironment desugared @@ -216,7 +216,7 @@      (Module _ _ elaborated _, env') <- lift . runCheck' env $ typeCheckModule Nothing m -    regrouped <- createBindingGroups moduleName' . collapseBindingGroups $ elaborated+    regrouped <- interpretMultipleErrors True . createBindingGroups moduleName' . collapseBindingGroups $ elaborated      let mod' = Module coms moduleName' regrouped exps     let corefn = CoreFn.moduleToCoreFn env' mod'@@ -240,10 +240,10 @@   rebuildIfNecessary graph toRebuild (Module _ moduleName' _ _ : ms') = do     let externsFile = outputDir </> runModuleName moduleName' </> "externs.purs"     externs <- readTextFile externsFile-    externsModules <- fmap (map snd) . either (throwError . errorMessage . ErrorParsingExterns) return $ P.parseModulesFromFiles id [(externsFile, externs)]+    externsModules <- fmap (map snd) . either (throwError . show) return $ P.parseModulesFromFiles id [(externsFile, externs)]     case externsModules of       [m'@(Module _ moduleName'' _ _)] | moduleName'' == moduleName' -> (:) (False, m') <$> rebuildIfNecessary graph toRebuild ms'-      _ -> throwError . errorMessage . InvalidExternsFile $ externsFile+      _ -> throwError $ "Externs file " ++ externsFile ++ " was invalid"  reverseDependencies :: ModuleGraph -> M.Map ModuleName [ModuleName] reverseDependencies g = combine [ (dep, mn) | (mn, deps) <- g, dep <- deps ]
src/Language/PureScript/AST/Declarations.hs view
@@ -78,12 +78,12 @@ -- | -- Return the exported data constructors for a given type. ---exportedDctors :: Module -> ProperName -> [(ProperName, [Type])]+exportedDctors :: Module -> ProperName -> [ProperName] exportedDctors (Module _ _ decls exps) ident =-  filter (isDctorExported ident exps . fst) dctors+  filter (isDctorExported ident exps) dctors   where   dctors = concatMap getDctors (flattenDecls decls)-  getDctors (DataDeclaration _ _ _ ctors) = ctors+  getDctors (DataDeclaration _ _ _ ctors) = map fst ctors   getDctors (PositionedDeclaration _ _ d) = getDctors d   getDctors _ = [] 
src/Language/PureScript/AST/SourcePos.hs view
@@ -30,12 +30,10 @@     -- Column number     --   , sourcePosColumn :: Int-  } deriving (Eq, Show, D.Data, D.Typeable)+  } deriving (Eq, D.Data, D.Typeable) -displaySourcePos :: SourcePos -> String-displaySourcePos sp =-  "line " ++ show (sourcePosLine sp) ++-    ", column " ++ show (sourcePosColumn sp)+instance Show SourcePos where+  show sp = "line " ++ show (sourcePosLine sp) ++ ", column " ++ show (sourcePosColumn sp)  data SourceSpan = SourceSpan   { -- |@@ -49,10 +47,7 @@     -- End of the span     --   , spanEnd :: SourcePos-  } deriving (Eq, Show, D.Data, D.Typeable)+  } deriving (Eq, D.Data, D.Typeable) -displaySourceSpan :: SourceSpan -> String-displaySourceSpan sp =-  spanName sp ++ " " ++-    displaySourcePos (spanStart sp) ++ " - " ++-    displaySourcePos (spanEnd sp)+instance Show SourceSpan where+  show sp = spanName sp ++ " " ++ show (spanStart sp) ++ " - " ++ show (spanEnd sp)
src/Language/PureScript/CodeGen/JS/Optimizer/Inliner.hs view
@@ -84,28 +84,10 @@ inlineValues = everywhereOnJS convert   where   convert :: JS -> JS-  convert (JSApp fn [dict]) | isDict semiringNumber dict && isFn fnZero fn = JSNumericLiteral (Left 0)-                            | isDict semiringNumber dict && isFn fnOne fn = JSNumericLiteral (Left 1)-                            | isDict semiringInt dict && isFn fnZero fn = JSNumericLiteral (Left 0)-                            | isDict semiringInt dict && isFn fnOne fn = JSNumericLiteral (Left 1)-                            | isDict boundedBoolean dict && isFn fnBottom fn = JSBooleanLiteral False-                            | isDict boundedBoolean dict && isFn fnTop fn = JSBooleanLiteral True-  convert (JSApp fn [value]) | isFn fromNumber fn = JSBinary BitwiseOr value (JSNumericLiteral (Left 0))-  convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y])-    | isDict semiringInt dict && isFn fnAdd fn = JSBinary BitwiseOr (JSBinary Add x y) (JSNumericLiteral (Left 0))-    | isDict semiringInt dict && isFn fnMultiply fn = JSBinary BitwiseOr (JSBinary Multiply x y) (JSNumericLiteral (Left 0))-    | isDict moduloSemiringInt dict && isFn fnDivide fn = JSBinary BitwiseOr (JSBinary Divide x y) (JSNumericLiteral (Left 0))-    | isDict ringInt dict && isFn fnSubtract fn = JSBinary BitwiseOr (JSBinary Subtract x y) (JSNumericLiteral (Left 0))+  convert (JSApp fn [dict]) | isPreludeDict C.semiringNumber dict && isPreludeFn C.zero fn = JSNumericLiteral (Left 0)+  convert (JSApp fn [dict]) | isPreludeDict C.semiringNumber dict && isPreludeFn C.one fn = JSNumericLiteral (Left 1)+  convert (JSApp (JSApp fn [x]) [y]) | isPreludeFn (C.%) fn = JSBinary Modulus x y   convert other = other-  fnZero = (C.prelude, C.zero)-  fnOne = (C.prelude, C.one)-  fnBottom = (C.prelude, C.bottom)-  fnTop = (C.prelude, C.top)-  fromNumber = (C.dataInt, C.fromNumber)-  fnAdd = (C.prelude, (C.+))-  fnDivide = (C.prelude, (C./))-  fnMultiply = (C.prelude, (C.*))-  fnSubtract = (C.prelude, (C.-))  inlineOperator :: (String, String) -> (JS -> JS -> JS) -> JS -> JS inlineOperator (m, op) f = everywhereOnJS convert@@ -119,83 +101,58 @@  inlineCommonOperators :: JS -> JS inlineCommonOperators = applyAll $-  [ binary semiringNumber (C.+) Add-  , binary semiringNumber (C.*) Multiply--  , binary ringNumber (C.-) Subtract-  , unary  ringNumber C.negate Negate-  , binary ringInt (C.-) Subtract-  , unary  ringInt C.negate Negate--  , binary moduloSemiringNumber (C./) Divide-  , binary moduloSemiringInt C.mod Modulus+  [ binary C.semiringNumber (C.+) Add+  , binary C.semiringNumber (C.*) Multiply+  , binary C.ringNumber (C.-) Subtract+  , unary  C.ringNumber C.negate Negate+  , binary C.moduloSemiringNumber (C./) Divide -  , binary eqNumber (C.==) EqualTo-  , binary eqNumber (C./=) NotEqualTo-  , binary eqInt (C.==) EqualTo-  , binary eqInt (C./=) NotEqualTo-  , binary eqString (C.==) EqualTo-  , binary eqString (C./=) NotEqualTo-  , binary eqBoolean (C.==) EqualTo-  , binary eqBoolean (C./=) NotEqualTo+  , binary C.ordNumber (C.<) LessThan+  , binary C.ordNumber (C.>) GreaterThan+  , binary C.ordNumber (C.<=) LessThanOrEqualTo+  , binary C.ordNumber (C.>=) GreaterThanOrEqualTo -  , binary ordNumber (C.<) LessThan-  , binary ordNumber (C.>) GreaterThan-  , binary ordNumber (C.<=) LessThanOrEqualTo-  , binary ordNumber (C.>=) GreaterThanOrEqualTo-  , binary ordInt (C.<) LessThan-  , binary ordInt (C.>) GreaterThan-  , binary ordInt (C.<=) LessThanOrEqualTo-  , binary ordInt (C.>=) GreaterThanOrEqualTo+  , binary C.eqNumber (C.==) EqualTo+  , binary C.eqNumber (C./=) NotEqualTo+  , binary C.eqString (C.==) EqualTo+  , binary C.eqString (C./=) NotEqualTo+  , binary C.eqBoolean (C.==) EqualTo+  , binary C.eqBoolean (C./=) NotEqualTo -  , binary semigroupString (C.<>) Add-  , binary semigroupString (C.++) Add+  , binary C.semigroupString (C.<>) Add+  , binary C.semigroupString (C.++) Add -  , binary latticeBoolean (C.&&) And-  , binary latticeBoolean (C.||) Or-  , binaryFunction latticeBoolean C.inf And-  , binaryFunction latticeBoolean C.sup Or-  , unary complementedLatticeBoolean C.not Not+  , binaryFunction C.bitsNumber C.shl ShiftLeft+  , binaryFunction C.bitsNumber C.shr ShiftRight+  , binaryFunction C.bitsNumber C.zshr ZeroFillShiftRight+  , binary         C.bitsNumber (C..&.) BitwiseAnd+  , binary         C.bitsNumber (C..|.) BitwiseOr+  , binary         C.bitsNumber (C..^.) BitwiseXor+  , unary          C.bitsNumber C.complement BitwiseNot -  , binary' C.dataIntBits (C..|.) BitwiseOr-  , binary' C.dataIntBits (C..&.) BitwiseAnd-  , binary' C.dataIntBits (C..^.) BitwiseXor-  , binary' C.dataIntBits C.shl ShiftLeft-  , binary' C.dataIntBits C.shr ShiftRight-  , binary' C.dataIntBits C.zshr ZeroFillShiftRight-  , unary'  C.dataIntBits C.complement BitwiseNot+  , binary C.boolLikeBoolean (C.&&) And+  , binary C.boolLikeBoolean (C.||) Or+  , unary  C.boolLikeBoolean C.not Not   ] ++   [ fn | i <- [0..10], fn <- [ mkFn i, runFn i ] ]   where-  binary :: (String, String) -> String -> BinaryOperator -> JS -> JS-  binary dict opString op = everywhereOnJS convert-    where-    convert :: JS -> JS-    convert (JSApp (JSApp (JSApp fn [dict']) [x]) [y]) | isDict dict dict' && isPreludeFn opString fn = JSBinary op x y-    convert other = other-  binary' :: String -> String -> BinaryOperator -> JS -> JS-  binary' moduleName opString op = everywhereOnJS convert-    where-    convert :: JS -> JS-    convert (JSApp (JSApp fn [x]) [y]) | isFn (moduleName, opString) fn = JSBinary op x y-    convert other = other-  binaryFunction :: (String, String) -> String -> BinaryOperator -> JS -> JS-  binaryFunction dict fnName op = everywhereOnJS convert+  binary :: String -> String -> BinaryOperator -> JS -> JS+  binary dictName opString op = everywhereOnJS convert     where     convert :: JS -> JS-    convert (JSApp (JSApp (JSApp fn [dict']) [x]) [y]) | isPreludeFn fnName fn && isDict dict dict' = JSBinary op x y+    convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isPreludeDict dictName dict && isPreludeFn opString fn = JSBinary op x y     convert other = other-  unary :: (String, String) -> String -> UnaryOperator -> JS -> JS-  unary dict fnName op = everywhereOnJS convert+  binaryFunction :: String -> String -> BinaryOperator -> JS -> JS+  binaryFunction dictName fnName op = everywhereOnJS convert     where     convert :: JS -> JS-    convert (JSApp (JSApp fn [dict']) [x]) | isPreludeFn fnName fn && isDict dict dict' = JSUnary op x+    convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isPreludeFn fnName fn && isPreludeDict dictName dict = JSBinary op x y     convert other = other-  unary' :: String -> String -> UnaryOperator -> JS -> JS-  unary' moduleName fnName op = everywhereOnJS convert+  unary :: String -> String -> UnaryOperator -> JS -> JS+  unary dictName fnName op = everywhereOnJS convert     where     convert :: JS -> JS-    convert (JSApp fn [x]) | isFn (moduleName, fnName) fn = JSUnary op x+    convert (JSApp (JSApp fn [dict]) [x]) | isPreludeFn fnName fn && isPreludeDict dictName dict = JSUnary op x     convert other = other   mkFn :: Int -> JS -> JS   mkFn 0 = everywhereOnJS convert@@ -233,62 +190,12 @@     go m acc (JSApp lhs [arg]) = go (m - 1) (arg : acc) lhs     go _ _   _ = Nothing -isDict :: (String, String) -> JS -> Bool-isDict (moduleName, dictName) (JSAccessor x (JSVar y)) = x == dictName && y == moduleName-isDict _ _ = False--isFn :: (String, String) -> JS -> Bool-isFn (moduleName, fnName) (JSAccessor x (JSVar y)) = x == fnName && y == moduleName-isFn (moduleName, fnName) (JSIndexer (JSStringLiteral x) (JSVar y)) = x == fnName && y == moduleName-isFn _ _ = False+isPreludeDict :: String -> JS -> Bool+isPreludeDict dictName (JSAccessor prop (JSVar prelude)) = prelude == C.prelude && prop == dictName+isPreludeDict _ _ = False  isPreludeFn :: String -> JS -> Bool-isPreludeFn fnName = isFn (C.prelude, fnName)--semiringNumber :: (String, String)-semiringNumber = (C.prelude, C.semiringNumber)--semiringInt :: (String, String)-semiringInt = (C.dataInt, C.semiringInt)--ringNumber :: (String, String)-ringNumber = (C.prelude, C.ringNumber)--ringInt :: (String, String)-ringInt = (C.dataInt, C.ringInt)--moduloSemiringNumber :: (String, String)-moduloSemiringNumber = (C.prelude, C.moduloSemiringNumber)--moduloSemiringInt :: (String, String)-moduloSemiringInt = (C.dataInt, C.moduloSemiringInt)--eqNumber :: (String, String)-eqNumber = (C.prelude, C.eqNumber)--eqInt :: (String, String)-eqInt = (C.dataInt, C.eqInt)--eqString :: (String, String)-eqString = (C.prelude, C.eqNumber)--eqBoolean :: (String, String)-eqBoolean = (C.prelude, C.eqNumber)--ordNumber :: (String, String)-ordNumber = (C.prelude, C.ordNumber)--ordInt :: (String, String)-ordInt = (C.dataInt, C.ordInt)--semigroupString :: (String, String)-semigroupString = (C.prelude, C.semigroupString)--boundedBoolean :: (String, String)-boundedBoolean = (C.prelude, C.boundedBoolean)--latticeBoolean :: (String, String)-latticeBoolean = (C.prelude, C.latticeBoolean)--complementedLatticeBoolean :: (String, String)-complementedLatticeBoolean = (C.prelude, C.complementedLatticeBoolean)+isPreludeFn fnName (JSAccessor fnName' (JSVar prelude)) = prelude == C.prelude && fnName' == fnName+isPreludeFn fnName (JSIndexer (JSStringLiteral fnName') (JSVar prelude)) = prelude == C.prelude && fnName' == fnName+isPreludeFn fnName (JSAccessor longForm (JSAccessor prelude (JSVar _))) = prelude == C.prelude && longForm == identToJs (Op fnName)+isPreludeFn _ _ = False
src/Language/PureScript/CodeGen/JS/Optimizer/TCO.hs view
@@ -15,8 +15,6 @@  module Language.PureScript.CodeGen.JS.Optimizer.TCO (tco) where -import Data.Monoid- import Language.PureScript.Options import Language.PureScript.CodeGen.JS.AST @@ -32,13 +30,10 @@   where   tcoLabel :: String   tcoLabel = "tco"-   tcoVar :: String -> String   tcoVar arg = "__tco_" ++ arg-   copyVar :: String -> String   copyVar arg = "__copy_" ++ arg-   convert :: JS -> JS   convert js@(JSVariableIntroduction name (Just fn@JSFunction {})) =     let@@ -51,7 +46,6 @@               JSVariableIntroduction name (Just (replace (toLoop name allArgs body')))         | otherwise -> js   convert js = js-   collectAllFunctionArgs :: [[String]] -> (JS -> JS) -> JS -> ([[String]], JS, JS -> JS)   collectAllFunctionArgs allArgs f (JSFunction ident args (JSBlock (body@(JSReturn _):_))) =     collectAllFunctionArgs (args : allArgs) (\b -> f (JSFunction ident (map copyVar args) (JSBlock [b]))) body@@ -62,35 +56,25 @@   collectAllFunctionArgs allArgs f (JSReturn (JSFunction ident args body@(JSBlock _))) =     (args : allArgs, body, f . JSReturn . JSFunction ident (map copyVar args))   collectAllFunctionArgs allArgs f body = (allArgs, body, f)-   isTailCall :: String -> JS -> Bool   isTailCall ident js =     let       numSelfCalls = everythingOnJS (+) countSelfCalls js       numSelfCallsInTailPosition = everythingOnJS (+) countSelfCallsInTailPosition js       numSelfCallsUnderFunctions = everythingOnJS (+) countSelfCallsUnderFunctions js-      numSelfCallWithFnArgs = everythingOnJS (+) countSelfCallsWithFnArgs js     in       numSelfCalls > 0       && numSelfCalls == numSelfCallsInTailPosition       && numSelfCallsUnderFunctions == 0-      && numSelfCallWithFnArgs == 0     where     countSelfCalls :: JS -> Int     countSelfCalls (JSApp (JSVar ident') _) | ident == ident' = 1     countSelfCalls _ = 0-         countSelfCallsInTailPosition :: JS -> Int     countSelfCallsInTailPosition (JSReturn ret) | isSelfCall ident ret = 1     countSelfCallsInTailPosition _ = 0-    -    countSelfCallsUnderFunctions :: JS -> Int     countSelfCallsUnderFunctions (JSFunction _ _ js') = everythingOnJS (+) countSelfCalls js'     countSelfCallsUnderFunctions _ = 0-    -    countSelfCallsWithFnArgs :: JS -> Int-    countSelfCallsWithFnArgs ret = if isSelfCallWithFnArgs ident ret [] then 1 else 0-   toLoop :: String -> [String] -> JS -> JS   toLoop ident allArgs js = JSBlock $         map (\arg -> JSVariableIntroduction arg (Just (JSVar (copyVar arg)))) allArgs ++@@ -110,19 +94,10 @@     collectSelfCallArgs :: [[JS]] -> JS -> [[JS]]     collectSelfCallArgs allArgumentValues (JSApp fn args') = collectSelfCallArgs (args' : allArgumentValues) fn     collectSelfCallArgs allArgumentValues _ = allArgumentValues-   isSelfCall :: String -> JS -> Bool-  isSelfCall ident (JSApp (JSVar ident') _) = ident == ident'-  isSelfCall ident (JSApp fn _) = isSelfCall ident fn+  isSelfCall ident (JSApp (JSVar ident') args) | ident == ident' && not (any isFunction args) = True+  isSelfCall ident (JSApp fn args) | not (any isFunction args) = isSelfCall ident fn   isSelfCall _ _ = False--  isSelfCallWithFnArgs :: String -> JS -> [JS] -> Bool-  isSelfCallWithFnArgs ident (JSVar ident') args | ident == ident' && any hasFunction args = True-  isSelfCallWithFnArgs ident (JSApp fn args) acc = isSelfCallWithFnArgs ident fn (args ++ acc)-  isSelfCallWithFnArgs _ _ _ = False-    -  hasFunction :: JS -> Bool -  hasFunction = getAny . everythingOnJS mappend (Any . isFunction)-    where-    isFunction (JSFunction _ _ _) = True-    isFunction _ = False+  isFunction :: JS -> Bool+  isFunction (JSFunction _ _ _) = True+  isFunction _ = False
src/Language/PureScript/Constants.hs view
@@ -15,7 +15,7 @@  module Language.PureScript.Constants where --- Operators+-- Prelude Operators  ($) :: String ($) = "$"@@ -65,6 +65,15 @@ (/=) :: String (/=) = "/=" +(.&.) :: String+(.&.) = ".&."++(.|.) :: String+(.|.) = ".|."++(.^.) :: String+(.^.) = ".^."+ (&&) :: String (&&) = "&&" @@ -74,32 +83,11 @@ unsafeIndex :: String unsafeIndex = "unsafeIndex" -(.|.) :: String-(.|.) = ".|."--(.&.) :: String-(.&.) = ".&."--(.^.) :: String-(.^.) = ".^."---- Functions+-- Prelude Operator Functions  negate :: String negate = "negate" -not :: String-not = "not"--sup :: String-sup = "sup"--inf :: String-inf = "inf"--mod :: String-mod = "mod"- shl :: String shl = "shl" @@ -112,8 +100,8 @@ complement :: String complement = "complement" -fromNumber :: String-fromNumber = "fromNumber"+not :: String+not = "not"  -- Prelude Values @@ -123,12 +111,6 @@ one :: String one = "one" -bottom :: String-bottom = "bottom"--top :: String-top = "top"- return :: String return = "return" @@ -190,47 +172,32 @@ semiringNumber :: String semiringNumber = "semiringNumber" -semiringInt :: String-semiringInt = "semiringInt"- ringNumber :: String ringNumber = "ringNumber" -ringInt :: String-ringInt = "ringInt"- moduloSemiringNumber :: String moduloSemiringNumber = "moduloSemiringNumber" -moduloSemiringInt :: String-moduloSemiringInt = "moduloSemiringInt"+numNumber :: String+numNumber = "numNumber"  ordNumber :: String ordNumber = "ordNumber" -ordInt :: String-ordInt = "ordInt"- eqNumber :: String eqNumber = "eqNumber" -eqInt :: String-eqInt = "eqInt"- eqString :: String eqString = "eqString"  eqBoolean :: String eqBoolean = "eqBoolean" -boundedBoolean :: String-boundedBoolean = "boundedBoolean"--latticeBoolean :: String-latticeBoolean = "latticeBoolean"+bitsNumber :: String+bitsNumber = "bitsNumber" -complementedLatticeBoolean :: String-complementedLatticeBoolean = "complementedLatticeBoolean"+boolLikeBoolean :: String+boolLikeBoolean = "boolLikeBoolean"  semigroupString :: String semigroupString = "semigroupString"@@ -270,9 +237,3 @@  dataFunction :: String dataFunction = "Data_Function"--dataInt :: String-dataInt = "Data_Int"--dataIntBits :: String-dataIntBits = "Data_Int_Bits"
src/Language/PureScript/Errors.hs view
@@ -36,19 +36,11 @@  import qualified Text.PrettyPrint.Boxes as Box -import qualified Text.Parsec as P- -- | -- A type of error messages -- data ErrorMessage -  = ErrorParsingExterns P.ParseError-  | ErrorParsingPrelude P.ParseError-  | InvalidExternsFile FilePath-  | CannotGetFileInfo FilePath-  | CannotReadFile FilePath-  | CannotWriteFile FilePath-  | InfiniteType Type+  = InfiniteType Type   | InfiniteKind Kind   | CannotReorderOperators   | MultipleFixities Ident@@ -78,7 +70,6 @@   | InvalidDoLet   | CycleInDeclaration Ident   | CycleInTypeSynonym (Maybe ProperName)-  | CycleInModules [ModuleName]   | NameIsUndefined Ident   | NameNotInScope Ident   | UndefinedTypeVariable ProperName@@ -135,12 +126,6 @@ -- Get the error code for a particular error type -- errorCode :: ErrorMessage -> String-errorCode (ErrorParsingExterns _)       = "ErrorParsingExterns"-errorCode (ErrorParsingPrelude _)       = "ErrorParsingPrelude"-errorCode (InvalidExternsFile _)        = "InvalidExternsFile"-errorCode (CannotGetFileInfo _)         = "CannotGetFileInfo"-errorCode (CannotReadFile _)            = "CannotReadFile"-errorCode (CannotWriteFile _)           = "CannotWriteFile" errorCode (InfiniteType _)              = "InfiniteType" errorCode (InfiniteKind _)              = "InfiniteKind" errorCode CannotReorderOperators        = "CannotReorderOperators"@@ -171,7 +156,6 @@ errorCode InvalidDoLet                  = "InvalidDoLet" errorCode (CycleInDeclaration _)        = "CycleInDeclaration" errorCode (CycleInTypeSynonym _)        = "CycleInTypeSynonym"-errorCode (CycleInModules _)            = "CycleInModules" errorCode (NameIsUndefined _)           = "NameIsUndefined" errorCode (NameNotInScope _)            = "NameNotInScope" errorCode (UndefinedTypeVariable _)     = "UndefinedTypeVariable"@@ -193,13 +177,13 @@ errorCode SubsumptionCheckFailed        = "SubsumptionCheckFailed" errorCode (ExprDoesNotHaveType _ _)     = "ExprDoesNotHaveType" errorCode (PropertyIsMissing _ _)       = "PropertyIsMissing"+errorCode (ErrorUnifyingTypes _ _ _)    = "ErrorUnifyingTypes" errorCode (CannotApplyFunction _ _)     = "CannotApplyFunction" errorCode TypeSynonymInstance           = "TypeSynonymInstance" errorCode InvalidNewtype                = "InvalidNewtype" errorCode (InvalidInstanceHead _)       = "InvalidInstanceHead" errorCode (TransitiveExportError _ _)   = "TransitiveExportError" errorCode (NotYetDefined _ e)           = errorCode e-errorCode (ErrorUnifyingTypes _ _ e)    = errorCode e errorCode (ErrorInExpression _ e)       = errorCode e errorCode (ErrorInModule _ e)           = errorCode e errorCode (ErrorInInstance _ _ e)       = errorCode e@@ -261,24 +245,6 @@     wikiUri = "https://github.com/purescript/purescript/wiki/Error-Code-" ++ errorCode e            go :: ErrorMessage -> Box.Box-    go (CannotGetFileInfo path)        = paras [ line "Unable to read file info: "-                                               , indent . line $ path-                                               ]-    go (CannotReadFile path)           = paras [ line "Unable to read file: "-                                               , indent . line $ path-                                               ]-    go (CannotWriteFile path)          = paras [ line "Unable to write file: "-                                               , indent . line $ path-                                               ]-    go (ErrorParsingExterns err)       = paras [ line "Error parsing externs files: "-                                               , indent . line . show $ err-                                               ]-    go (ErrorParsingPrelude err)       = paras [ line "Error parsing prelude: "-                                               , indent . line . show $ err-                                               ]-    go (InvalidExternsFile path)       = paras [ line "Externs file is invalid: "-                                               , indent . line $ path-                                               ]     go InvalidDoBind                   = line "Bind statement cannot be the last statement in a do block"     go InvalidDoLet                    = line "Let statement cannot be the last statement in a do block"     go CannotReorderOperators          = line "Unable to reorder operators"@@ -312,7 +278,6 @@     go (DuplicateClassExport nm)       = line $ "Duplicate export declaration for type class " ++ show nm     go (DuplicateValueExport nm)       = line $ "Duplicate export declaration for value " ++ show nm     go (CycleInDeclaration nm)         = line $ "Cycle in declaration of " ++ show nm-    go (CycleInModules mns)            = line $ "Cycle in module dependencies: " ++ intercalate ", " (map show mns)     go (NotYetDefined names err)       = paras [ line $ "The following are not yet defined here: " ++ intercalate ", " (map show names) ++ ":"                                                , indent $ go err                                                ]@@ -439,7 +404,7 @@     go (ErrorInForeignImport nm err)   = paras [ line $ "Error in foreign import " ++ show nm ++ ":"                                                , go err                                                ]-    go (PositionedError srcSpan err)   = paras [ line $ "Error at " ++ displaySourceSpan srcSpan ++ ":"+    go (PositionedError pos err)       = paras [ line $ "Error at " ++ show pos ++ ":"                                                , indent $ go err                                                ] @@ -525,8 +490,8 @@ -- | -- Interpret multiple errors in a monad supporting errors ---interpretMultipleErrors :: (MonadError MultipleErrors m) => Either MultipleErrors a -> m a-interpretMultipleErrors = either throwError return+interpretMultipleErrors :: (MonadError String m) => Bool -> Either MultipleErrors a -> m a+interpretMultipleErrors printFullStack = either (throwError . prettyPrintMultipleErrors printFullStack) return  -- | -- Rethrow an error with a more detailed error message in the case of failure
src/Language/PureScript/ModuleDependencies.hs view
@@ -28,7 +28,6 @@ import Language.PureScript.AST import Language.PureScript.Names import Language.PureScript.Types-import Language.PureScript.Errors  -- | -- A list of modules with their dependencies@@ -40,7 +39,7 @@ -- -- Reports an error if the module graph contains a cycle. ---sortModules :: (MonadError MultipleErrors m) => [Module] -> m ([Module], ModuleGraph)+sortModules :: (MonadError String m) => [Module] -> m ([Module], ModuleGraph) sortModules ms = do   let verts = map (\m@(Module _ _ ds _) -> (m, getModuleName m, nub (concatMap usedModules ds))) ms   ms' <- mapM toModule $ stronglyConnComp verts@@ -71,7 +70,7 @@ -- | -- Convert a strongly connected component of the module graph to a module ---toModule :: (MonadError MultipleErrors m) => SCC Module -> m Module+toModule :: (MonadError String m) => SCC Module -> m Module toModule (AcyclicSCC m) = return m toModule (CyclicSCC [m]) = return m-toModule (CyclicSCC ms) = throwError . errorMessage $ CycleInModules (map getModuleName ms)+toModule (CyclicSCC ms) = throwError $ "Cycle in module dependencies: " ++ show (map getModuleName ms)
src/Language/PureScript/Parser/Types.hs view
@@ -126,7 +126,9 @@ parseNameAndType p = (,) <$> (indented *> (lname <|> stringLiteral) <* indented <* doubleColon) <*> p  parseRowEnding :: TokenParser Type-parseRowEnding = P.option REmpty $ indented *> pipe *> indented *> parseType+parseRowEnding = P.option REmpty $ indented *> pipe *> indented *> P.choice  (map P.try+            [ parseTypeWildcard+            , TypeVar <$> identifier ])  parseRow :: TokenParser Type parseRow = (curry rowFromList <$> commaSep (parseNameAndType parsePolyType) <*> parseRowEnding) P.<?> "row"
src/Language/PureScript/Sugar/BindingGroups.hs view
@@ -157,6 +157,7 @@ -- toBindingGroup :: (Functor m, MonadError MultipleErrors m) => ModuleName -> SCC Declaration -> m Declaration toBindingGroup _ (AcyclicSCC d) = return d+toBindingGroup _ (CyclicSCC [d]) = return d toBindingGroup moduleName (CyclicSCC ds') =   -- Once we have a mutually-recursive group of declarations, we need to sort   -- them further by their immediate dependencies (those outside function
src/Language/PureScript/Sugar/CaseDeclarations.hs view
@@ -25,7 +25,7 @@ import Data.List (nub, groupBy)  import Control.Applicative-import Control.Monad ((<=<), forM, replicateM, join, unless)+import Control.Monad ((<=<), forM, join, unless, replicateM) import Control.Monad.Except (throwError) import Control.Monad.Error.Class (MonadError) import Control.Monad.Supply.Class@@ -130,20 +130,12 @@       value = foldr (Abs . Left) (Case vars binders) args   return $ ValueDeclaration ident Value [] (Right value)   where-  -- We will construct a table of potential names.-  -- VarBinders will become Just (Just _) which is a potential name.-  -- NullBinder will become Just Nothing, which indicates that we may -  -- have to generate a name.-  -- Everything else becomes Nothing, which indicates that we definitely-  --have to generate a name.   findName :: Binder -> Maybe (Maybe Ident)   findName NullBinder = Just Nothing   findName (VarBinder name) = Just (Just name)   findName (PositionedBinder _ _ binder) = findName binder   findName _ = Nothing -  -- We still have to make sure the generated names are unique, or else-  -- we will end up constructing an invalid function.   allUnique :: (Eq a) => [a] -> Bool   allUnique xs = length xs == length (nub xs) @@ -153,15 +145,11 @@     name <- freshName     return (Ident name) -  -- Combine two lists of potential names from two case alternatives-  -- by zipping correspoding columns.   resolveNames :: [Maybe (Maybe Ident)] ->                    [Maybe (Maybe Ident)] ->                    [Maybe (Maybe Ident)]   resolveNames = zipWith resolveName -  -- Resolve a pair of names. VarBinder beats NullBinder, and everything-  -- else results in Nothing.   resolveName :: Maybe (Maybe Ident) ->                   Maybe (Maybe Ident) ->                   Maybe (Maybe Ident)
src/Language/PureScript/Sugar/DoNotation.hs view
@@ -44,8 +44,11 @@   let (f, _, _) = everywhereOnValuesM return replace return   in f d   where+  prelude :: ModuleName+  prelude = ModuleName [ProperName C.prelude]+   bind :: Expr-  bind = Var (Qualified Nothing (Op (C.>>=)))+  bind = Var (Qualified (Just prelude) (Op (C.>>=)))    replace :: Expr -> m Expr   replace (Do els) = go els
src/Language/PureScript/TypeChecker/Entailment.hs view
@@ -116,7 +116,7 @@       checkOverlaps :: [DictionaryValue] -> Check Expr       checkOverlaps dicts =         case [ (d1, d2) | d1 <- dicts, d2 <- dicts, d1 `overlapping` d2 ] of-          ds@(_ : _) -> throwError . errorMessage $ OverlappingInstances className tys $ nub (map fst ds)+          ds@(_ : _) -> throwError . errorMessage $ OverlappingInstances className tys (map fst ds)           _ -> case chooseSimplestDictionaries dicts of                  [] -> throwError . errorMessage $ NoInstanceFound className tys                  d : _ -> return $ dictionaryValueToValue d
src/Language/PureScript/TypeChecker/Monad.hs view
@@ -23,6 +23,7 @@  import Control.Applicative import Control.Monad.Except+import Control.Monad.Reader.Class import Control.Monad.State import Control.Monad.Unify @@ -30,6 +31,7 @@ import Language.PureScript.Errors import Language.PureScript.Kinds import Language.PureScript.Names+import Language.PureScript.Options import Language.PureScript.TypeClassDictionaries import Language.PureScript.Types @@ -96,19 +98,12 @@ -- | -- Update the visibility of all names to Defined ---makeBindingGroupVisible :: (Functor m, MonadState CheckState m) => m () -makeBindingGroupVisible = modifyEnv $ \e -> e { names = M.map (\(ty, nk, _) -> (ty, nk, Defined)) (names e) }---- | Update the visibility of all names to Defined in the scope of the provided action-withBindingGroupVisible :: (Functor m, MonadState CheckState m) => m a -> m a-withBindingGroupVisible action = preservingNames $ makeBindingGroupVisible >> action---- | Perform an action while preserving the names from the @Environment@.-preservingNames :: (Functor m, MonadState CheckState m) => m a -> m a-preservingNames action = do-  orig <- gets (names . checkEnv)+makeBindingGroupVisible :: (Functor m, MonadState CheckState m) => m a -> m a+makeBindingGroupVisible action = do+  orig <- get+  modify $ \st -> st { checkEnv = (checkEnv st) { names = M.map (\(ty, nk, _) -> (ty, nk, Defined)) (names . checkEnv $ st) } }   a <- action-  modifyEnv $ \e -> e { names = orig }+  modify $ \st -> st { checkEnv = (checkEnv st) { names = names . checkEnv $ orig } }   return a  -- |@@ -200,16 +195,18 @@ -- | -- Run a computation in the Check monad, starting with an empty @Environment@ ---runCheck :: (MonadError MultipleErrors m) => Check a -> m (a, Environment)+runCheck :: (MonadReader (Options mode) m, MonadError String m) => Check a -> m (a, Environment) runCheck = runCheck' initEnvironment  -- | -- Run a computation in the Check monad, failing with an error, or succeeding with a return value and the final @Environment@. ---runCheck' :: (MonadError MultipleErrors m) => Environment -> Check a -> m (a, Environment)-runCheck' env c = interpretMultipleErrors $ do-  (a, s) <- flip runStateT (CheckState env 0 0 Nothing) $ unCheck c-  return (a, checkEnv s)+runCheck' :: (MonadReader (Options mode) m, MonadError String m) => Environment -> Check a -> m (a, Environment)+runCheck' env c = do+  verbose <- asks optionsVerboseErrors+  interpretMultipleErrors verbose $ do+    (a, s) <- flip runStateT (CheckState env 0 0 Nothing) $ unCheck c+    return (a, checkEnv s)  -- | -- Make an assertion, failing with an error message
src/Language/PureScript/TypeChecker/Types.hs view
@@ -247,7 +247,7 @@ infer' (Abs (Left arg) ret) = do   ty <- fresh   Just moduleName <- checkCurrentModule <$> get-  withBindingGroupVisible $ bindLocalVariables moduleName [(arg, ty, Defined)] $ do+  makeBindingGroupVisible $ bindLocalVariables moduleName [(arg, ty, Defined)] $ do     body@(TypedValue _ _ bodyTy) <- infer' ret     return $ TypedValue True (Abs (Left arg) body) $ function ty bodyTy infer' (Abs (Right _) _) = error "Binder was not desugared"@@ -298,7 +298,7 @@ infer' _ = error "Invalid argument to infer"  inferLetBinding :: [Declaration] -> [Declaration] -> Expr -> (Expr -> UnifyT Type Check Expr) -> UnifyT Type Check ([Declaration], Expr)-inferLetBinding seen [] ret j = (,) seen <$> withBindingGroupVisible (j ret)+inferLetBinding seen [] ret j = (,) seen <$> makeBindingGroupVisible (j ret) inferLetBinding seen (ValueDeclaration ident nameKind [] (Right (tv@(TypedValue checkType val ty))) : rest) ret j = do   Just moduleName <- checkCurrentModule <$> get   (kind, args) <- liftCheck $ kindOfWithScopedVars ty@@ -320,9 +320,7 @@   ds1' <- parU typed $ \e -> checkTypedBindingGroupElement moduleName e dict   ds2' <- forM untyped $ \e -> typeForBindingGroupElement e dict untypedDict   let ds' = [(ident, LocalVariable, val') | (ident, (val', _)) <- ds1' ++ ds2']-  bindNames dict $ do-    makeBindingGroupVisible-    inferLetBinding (seen ++ [BindingGroupDeclaration ds']) rest ret j+  makeBindingGroupVisible $ bindNames dict $ inferLetBinding (seen ++ [BindingGroupDeclaration ds']) rest ret j inferLetBinding seen (PositionedDeclaration pos com d : ds) ret j = rethrowWithPosition pos $ do   (d' : ds', val') <- inferLetBinding seen (d : ds) ret j   return (PositionedDeclaration pos com d' : ds', val')@@ -444,7 +442,7 @@   dictNames <- forM constraints $ \(Qualified _ (ProperName className), _) -> do     n <- liftCheck freshDictionaryName     return $ Ident $ "__dict_" ++ className ++ "_" ++ show n-  val' <- withBindingGroupVisible $ withTypeClassDictionaries (zipWith (\name (className, instanceTy) ->+  val' <- makeBindingGroupVisible $ withTypeClassDictionaries (zipWith (\name (className, instanceTy) ->     TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular False) (map (Qualified Nothing) dictNames)       constraints) $ check val ty   return $ TypedValue True (foldr (Abs . Left) val' dictNames) t@@ -470,7 +468,7 @@ check' (Abs (Left arg) ret) ty@(TypeApp (TypeApp t argTy) retTy) = do   t =?= tyFunction   Just moduleName <- checkCurrentModule <$> get-  ret' <- withBindingGroupVisible $ bindLocalVariables moduleName [(arg, argTy, Defined)] $ check ret retTy+  ret' <- makeBindingGroupVisible $ bindLocalVariables moduleName [(arg, argTy, Defined)] $ check ret retTy   return $ TypedValue True (Abs (Left arg) ret') ty check' (Abs (Right _) _) _ = error "Binder was not desugared" check' (App f arg) ret = do
tests/Main.hs view
@@ -35,21 +35,21 @@   text <- readFile inputFile   return (inputFile, text) -loadPrelude :: Either P.MultipleErrors (String, String, P.Environment)+loadPrelude :: Either String (String, String, P.Environment) loadPrelude =   case P.parseModulesFromFiles id [("", P.prelude)] of-    Left parseError -> Left . P.errorMessage . P.ErrorParsingPrelude $ parseError+    Left parseError -> Left (show parseError)     Right ms -> runReaderT (P.compile (map snd ms) []) $ P.defaultCompileOptions { P.optionsAdditional = P.CompileOptions "Tests" [] [] } -compile :: P.Options P.Compile -> [FilePath] -> IO (Either P.MultipleErrors (String, String, P.Environment))+compile :: P.Options P.Compile -> [FilePath] -> IO (Either String (String, String, P.Environment)) compile opts inputFiles = do   modules <- P.parseModulesFromFiles id <$> readInput inputFiles   case modules of     Left parseError ->-      return . Left . P.errorMessage . P.ErrorParsingPrelude $ parseError+      return (Left $ show parseError)     Right ms -> return $ runReaderT (P.compile (map snd ms) []) opts -assert :: FilePath -> P.Options P.Compile -> FilePath -> (Either P.MultipleErrors (String, String, P.Environment) -> IO (Maybe String)) -> IO ()+assert :: FilePath -> P.Options P.Compile -> FilePath -> (Either String (String, String, P.Environment) -> IO (Maybe String)) -> IO () assert preludeExterns opts inputFile f = do   e <- compile opts [preludeExterns, inputFile]   maybeErr <- f e@@ -64,7 +64,7 @@                               { P.optionsMain = Just "Main"                               , P.optionsAdditional = P.CompileOptions "Tests" ["Main"] ["Main"]                               }-  assert preludeExterns options inputFile $ either (return . Just . P.prettyPrintMultipleErrors False) $ \(js, _, _) -> do+  assert preludeExterns options inputFile $ either (return . Just) $ \(js, _, _) -> do     process <- findNodeProcess     result <- traverse (\node -> readProcessWithExitCode node [] (preludeJs ++ js)) process     case result of@@ -77,7 +77,7 @@   putStrLn $ "Assert " ++ inputFile ++ " does not compile"   assert preludeExterns (P.defaultCompileOptions { P.optionsAdditional = P.CompileOptions "Tests" [] [] }) inputFile $ \e ->     case e of-      Left errs -> putStrLn  (P.prettyPrintMultipleErrors False errs) >> return Nothing+      Left err -> putStrLn err >> return Nothing       Right _ -> return $ Just "Should not have compiled"  findNodeProcess :: IO (Maybe String)@@ -88,7 +88,7 @@ main = do   putStrLn "Compiling Prelude"   case loadPrelude of-    Left errs -> putStrLn (P.prettyPrintMultipleErrors False errs) >> exitFailure+    Left err -> putStrLn err >> exitFailure     Right (preludeJs, exts, _) -> do       tmp <- getTemporaryDirectory       let preludeExterns = tmp ++ pathSeparator : "prelude.externs"@@ -105,3 +105,4 @@       forM_ failingTestCases $ \inputFile -> when (".purs" `isSuffixOf` inputFile) $         assertDoesNotCompile preludeExterns (failing ++ pathSeparator : inputFile)       exitSuccess+