packages feed

purescript 0.10.4 → 0.10.5

raw patch · 49 files changed

+817/−333 lines, 49 filesdep +scientificdep ~bower-jsonPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: scientific

Dependency ranges changed: bower-json

API changes (from Hackage documentation)

- Language.PureScript.Pretty.Common: prettyPrintObjectKey :: Text -> Text
+ Language.PureScript.Kinds: kindFromJSON :: Parse Text Kind
+ Language.PureScript.Label: Label :: PSString -> Label
+ Language.PureScript.Label: [runLabel] :: Label -> PSString
+ Language.PureScript.Label: instance Data.Aeson.Types.Class.FromJSON Language.PureScript.Label.Label
+ Language.PureScript.Label: instance Data.Aeson.Types.Class.ToJSON Language.PureScript.Label.Label
+ Language.PureScript.Label: instance Data.String.IsString Language.PureScript.Label.Label
+ Language.PureScript.Label: instance GHC.Base.Monoid Language.PureScript.Label.Label
+ Language.PureScript.Label: instance GHC.Classes.Eq Language.PureScript.Label.Label
+ Language.PureScript.Label: instance GHC.Classes.Ord Language.PureScript.Label.Label
+ Language.PureScript.Label: instance GHC.Show.Show Language.PureScript.Label.Label
+ Language.PureScript.Label: newtype Label
+ Language.PureScript.PSString: data PSString
+ Language.PureScript.PSString: decodeString :: PSString -> Maybe Text
+ Language.PureScript.PSString: decodeStringEither :: PSString -> [Either Word16 Char]
+ Language.PureScript.PSString: instance Data.Aeson.Types.Class.FromJSON Language.PureScript.PSString.PSString
+ Language.PureScript.PSString: instance Data.Aeson.Types.Class.ToJSON Language.PureScript.PSString.PSString
+ Language.PureScript.PSString: instance Data.String.IsString Language.PureScript.PSString.PSString
+ Language.PureScript.PSString: instance GHC.Base.Monoid Language.PureScript.PSString.PSString
+ Language.PureScript.PSString: instance GHC.Classes.Eq Language.PureScript.PSString.PSString
+ Language.PureScript.PSString: instance GHC.Classes.Ord Language.PureScript.PSString.PSString
+ Language.PureScript.PSString: instance GHC.Show.Show Language.PureScript.PSString.PSString
+ Language.PureScript.PSString: mkString :: Text -> PSString
+ Language.PureScript.PSString: prettyPrintString :: PSString -> Text
+ Language.PureScript.PSString: prettyPrintStringJS :: PSString -> Text
+ Language.PureScript.PSString: toUTF16CodeUnits :: PSString -> [Word16]
+ Language.PureScript.Parser.Common: parseLabel :: TokenParser PSString
+ Language.PureScript.Pretty.Common: objectKeyRequiresQuoting :: Text -> Bool
+ Language.PureScript.Pretty.Types: prettyPrintLabel :: Label -> Text
+ Language.PureScript.Pretty.Types: prettyPrintObjectKey :: PSString -> Text
+ Language.PureScript.Publish.BoxesHelpers: bulletedListT :: (a -> Text) -> [a] -> [Box]
- Language.PureScript.AST.Declarations: Accessor :: Text -> Expr -> Expr
+ Language.PureScript.AST.Declarations: Accessor :: PSString -> Expr -> Expr
- Language.PureScript.AST.Declarations: AdditionalProperty :: Text -> SimpleErrorMessage
+ Language.PureScript.AST.Declarations: AdditionalProperty :: Label -> SimpleErrorMessage
- Language.PureScript.AST.Declarations: DuplicateLabel :: Text -> (Maybe Expr) -> SimpleErrorMessage
+ Language.PureScript.AST.Declarations: DuplicateLabel :: Label -> (Maybe Expr) -> SimpleErrorMessage
- Language.PureScript.AST.Declarations: ErrorCheckingAccessor :: Expr -> Text -> ErrorMessageHint
+ Language.PureScript.AST.Declarations: ErrorCheckingAccessor :: Expr -> PSString -> ErrorMessageHint
- Language.PureScript.AST.Declarations: ObjectUpdate :: Expr -> [(Text, Expr)] -> Expr
+ Language.PureScript.AST.Declarations: ObjectUpdate :: Expr -> [(PSString, Expr)] -> Expr
- Language.PureScript.AST.Declarations: PropertyIsMissing :: Text -> SimpleErrorMessage
+ Language.PureScript.AST.Declarations: PropertyIsMissing :: Label -> SimpleErrorMessage
- Language.PureScript.AST.Literals: ObjectLiteral :: [(Text, a)] -> Literal a
+ Language.PureScript.AST.Literals: ObjectLiteral :: [(PSString, a)] -> Literal a
- Language.PureScript.AST.Literals: StringLiteral :: Text -> Literal a
+ Language.PureScript.AST.Literals: StringLiteral :: PSString -> Literal a
- Language.PureScript.CodeGen.JS.AST: JSObjectLiteral :: (Maybe SourceSpan) -> [(Text, JS)] -> JS
+ Language.PureScript.CodeGen.JS.AST: JSObjectLiteral :: (Maybe SourceSpan) -> [(PSString, JS)] -> JS
- Language.PureScript.CodeGen.JS.AST: JSStringLiteral :: (Maybe SourceSpan) -> Text -> JS
+ Language.PureScript.CodeGen.JS.AST: JSStringLiteral :: (Maybe SourceSpan) -> PSString -> JS
- Language.PureScript.CoreFn.Expr: Accessor :: a -> Text -> (Expr a) -> Expr a
+ Language.PureScript.CoreFn.Expr: Accessor :: a -> PSString -> (Expr a) -> Expr a
- Language.PureScript.CoreFn.Expr: ObjectUpdate :: a -> (Expr a) -> [(Text, Expr a)] -> Expr a
+ Language.PureScript.CoreFn.Expr: ObjectUpdate :: a -> (Expr a) -> [(PSString, Expr a)] -> Expr a
- Language.PureScript.Docs.Types: asKind :: Parse e Kind
+ Language.PureScript.Docs.Types: asKind :: Parse PackageError Kind
- Language.PureScript.Parser.Lexer: stringLiteral :: TokenParser Text
+ Language.PureScript.Parser.Lexer: stringLiteral :: TokenParser PSString
- Language.PureScript.Publish.ErrorsWarnings: BadRepositoryType :: String -> RepositoryFieldError
+ Language.PureScript.Publish.ErrorsWarnings: BadRepositoryType :: Text -> RepositoryFieldError
- Language.PureScript.Types: RCons :: Text -> Type -> Type -> Type
+ Language.PureScript.Types: RCons :: Label -> Type -> Type -> Type
- Language.PureScript.Types: TypeLevelString :: Text -> Type
+ Language.PureScript.Types: TypeLevelString :: PSString -> Type
- Language.PureScript.Types: rowFromList :: ([(Text, Type)], Type) -> Type
+ Language.PureScript.Types: rowFromList :: ([(Label, Type)], Type) -> Type
- Language.PureScript.Types: rowToList :: Type -> ([(Text, Type)], Type)
+ Language.PureScript.Types: rowToList :: Type -> ([(Label, Type)], Type)

Files

+ examples/failing/2534.purs view
@@ -0,0 +1,8 @@+-- @shouldFailWith InfiniteType+module Main where++foo :: Array Int -> Int+foo xs = go xs where+  go :: Array _ -> Int+  go [] = 0+  go xs = go [xs]
+ examples/failing/DeclConflictDuplicateCtor.purs view
@@ -0,0 +1,5 @@+-- @shouldFailWith DeclConflict+module Main where++data T = Fail | Fail+
+ examples/passing/StringEdgeCases.purs view
@@ -0,0 +1,9 @@+module Main where++import Prelude+import Records as Records+import Symbols as Symbols++main = do+  Records.main+  Symbols.main
+ examples/passing/StringEdgeCases/Records.purs view
@@ -0,0 +1,66 @@+module Records where++import Prelude+import Data.Generic (class Generic, toSpine, GenericSpine(..))+import Control.Monad.Eff.Console (log)+import Test.Assert (assert')++newtype AstralKeys = AstralKeys { "💡" :: Int, "💢" :: Int }+newtype LoneSurrogateKeys = LoneSurrogateKeys { "\xdf06" :: Int, "\xd834" :: Int }++derive instance genericAstralKeys :: Generic AstralKeys+derive instance genericLoneSurrogateKeys :: Generic LoneSurrogateKeys++spineOf :: forall a. Generic a => a -> Unit -> GenericSpine+spineOf x _ = toSpine x++testLoneSurrogateKeys =+  let+    expected = 5+    actual = (_."\xd801" <<< helper) { "\xd800": 5 }+  in+    assert' ("lone surrogate keys: " <> show actual) (expected == actual)++  where+  helper :: { "\xd800" :: Int } -> { "\xd801" :: Int }+  helper o =+    case o."\xd800" of+      x -> { "\xd801": x }++testAstralKeys =+  let+    expected = 5+    actual = (_."💢" <<< helper) { "💡": 5 }+  in+    assert' ("astral keys: " <> show actual) (expected == actual)++  where+  helper :: { "💡" :: Int } -> { "💢" :: Int }+  helper o =+    case o."💡" of+      x -> { "💢": x }++testGenericLoneSurrogateKeys = do+  let expected = SProd "Records.LoneSurrogateKeys"+                  [ \_ -> SRecord [ {recLabel: "\xd834", recValue: spineOf 1}+                                  , {recLabel: "\xdf06", recValue: spineOf 0}+                                  ]+                  ]+      actual = toSpine (LoneSurrogateKeys { "\xdf06": 0, "\xd834": 1 })+  assert' ("generic lone surrogate keys: " <> show actual) (expected == actual)++testGenericAstralKeys = do+  let expected = SProd "Records.AstralKeys"+                  [ \_ -> SRecord [ {recLabel: "💡", recValue: spineOf 0}+                                  , {recLabel: "💢", recValue: spineOf 1}+                                  ]+                  ]+      actual = toSpine (AstralKeys { "💡": 0, "💢": 1 })+  assert' ("generic astral keys: " <> show actual) (expected == actual)++main = do+  testLoneSurrogateKeys+  testAstralKeys+  testGenericLoneSurrogateKeys+  testGenericAstralKeys+  log "Done"
+ examples/passing/StringEdgeCases/Symbols.purs view
@@ -0,0 +1,30 @@+-- This is similar to StringEscapes except we are performing the same tests+-- with Symbols (at the type level).++module Symbols where++import Prelude+import Control.Monad.Eff.Console (log)+import Type.Data.Symbol (SProxy(..), class AppendSymbol, appendSymbol, reflectSymbol)+import Test.Assert (assert')++highS :: SProxy "\xd834"+highS = SProxy++lowS :: SProxy "\xdf06"+lowS = SProxy++loneSurrogates :: Boolean+loneSurrogates = reflectSymbol (appendSymbol highS lowS) == "\x1d306"++outOfOrderSurrogates :: Boolean+outOfOrderSurrogates = reflectSymbol (appendSymbol lowS highS) == "\xdf06\xd834"++notReplacing :: Boolean+notReplacing = reflectSymbol lowS /= "\xfffd"++main = do+  assert' "lone surrogates may be combined into a surrogate pair" loneSurrogates+  assert' "lone surrogates may be combined out of order to remain lone surrogates" outOfOrderSurrogates+  assert' "lone surrogates are not replaced with the Unicode replacement character U+FFFD" notReplacing+  log "Done"
examples/passing/StringEscapes.purs view
@@ -22,5 +22,5 @@   assert' "astral code points are represented as a UTF-16 surrogate pair" surrogatePair
   assert' "lone surrogates may be combined into a surrogate pair" loneSurrogates
   assert' "lone surrogates may be combined out of order to remain lone surrogates" outOfOrderSurrogates
-  -- assert' "lone surrogates are not replaced with the Unicode replacement character U+FFFD" notReplacing
+  assert' "lone surrogates are not replaced with the Unicode replacement character U+FFFD" notReplacing
   log "Done"
purescript.cabal view
@@ -1,5 +1,5 @@ name: purescript-version: 0.10.4+version: 0.10.5 cabal-version: >=1.8 build-type: Simple license: BSD3@@ -54,6 +54,7 @@                   , examples/passing/ResolvableScopeConflict3/*.purs                   , examples/passing/ShadowedModuleName/*.purs                   , examples/passing/SolvingIsSymbol/*.purs+                  , examples/passing/StringEdgeCases/*.purs                   , examples/passing/TransitiveImport/*.purs                   , examples/passing/TypeOperators/*.purs                   , examples/passing/TypeWithoutParens/*.purs@@ -116,7 +117,7 @@                    aeson-better-errors >= 0.8,                    ansi-terminal >= 0.6.2 && < 0.7,                    base-compat >=0.6.0,-                   bower-json >= 0.8,+                   bower-json >= 1.0.0.1 && < 1.1,                    boxes >= 0.1.4 && < 0.2.0,                    bytestring -any,                    containers -any,@@ -146,6 +147,7 @@                    protolude >= 0.1.6,                    regex-tdfa -any,                    safe >= 0.3.9 && < 0.4,+                   scientific >= 0.3.4.9 && < 0.4,                    semigroups >= 0.16.2 && < 0.19,                    sourcemap >= 0.1.6,                    spdx == 0.2.*,@@ -199,6 +201,7 @@                      Language.PureScript.Errors                      Language.PureScript.Errors.JSON                      Language.PureScript.Kinds+                     Language.PureScript.Label                      Language.PureScript.Linter                      Language.PureScript.Linter.Exhaustive                      Language.PureScript.Linter.Imports@@ -219,6 +222,7 @@                      Language.PureScript.Pretty.Kinds                      Language.PureScript.Pretty.Types                      Language.PureScript.Pretty.Values+                     Language.PureScript.PSString                      Language.PureScript.Renamer                      Language.PureScript.Sugar                      Language.PureScript.Sugar.BindingGroups
src/Language/PureScript/AST/Declarations.hs view
@@ -18,6 +18,8 @@ import Language.PureScript.AST.Operators import Language.PureScript.AST.SourcePos import Language.PureScript.Types+import Language.PureScript.PSString (PSString)+import Language.PureScript.Label (Label) import Language.PureScript.Names import Language.PureScript.Kinds import Language.PureScript.TypeClassDictionaries@@ -90,7 +92,7 @@   | CannotDerive (Qualified (ProperName 'ClassName)) [Type]   | InvalidNewtypeInstance (Qualified (ProperName 'ClassName)) [Type]   | CannotFindDerivingType (ProperName 'TypeName)-  | DuplicateLabel Text (Maybe Expr)+  | DuplicateLabel Label (Maybe Expr)   | DuplicateValueDeclaration Ident   | ArgListLengthsDiffer Ident   | OverlappingArgNames (Maybe Ident)@@ -99,8 +101,8 @@   | ExpectedType Type Kind   | IncorrectConstructorArity (Qualified (ProperName 'ConstructorName))   | ExprDoesNotHaveType Expr Type-  | PropertyIsMissing Text-  | AdditionalProperty Text+  | PropertyIsMissing Label+  | AdditionalProperty Label   | TypeSynonymInstance   | OrphanInstance Ident (Qualified (ProperName 'ClassName)) [Type]   | InvalidNewtype (ProperName 'TypeName)@@ -145,7 +147,7 @@   | ErrorInModule ModuleName   | ErrorInInstance (Qualified (ProperName 'ClassName)) [Type]   | ErrorInSubsumption Type Type-  | ErrorCheckingAccessor Expr Text+  | ErrorCheckingAccessor Expr PSString   | ErrorCheckingType Expr Type   | ErrorCheckingKind Type   | ErrorCheckingGuard@@ -573,11 +575,11 @@   -- Anonymous arguments will be removed during desugaring and expanded   -- into a lambda that reads a property from a record.   ---  | Accessor Text Expr+  | Accessor PSString Expr   -- |   -- Partial record update   ---  | ObjectUpdate Expr [(Text, Expr)]+  | ObjectUpdate Expr [(PSString, Expr)]   -- |   -- Function introduction   --
src/Language/PureScript/AST/Literals.hs view
@@ -4,7 +4,7 @@ module Language.PureScript.AST.Literals where  import Prelude.Compat-import Data.Text (Text)+import Language.PureScript.PSString (PSString)  -- | -- Data type for literal values. Parameterised so it can be used for Exprs and@@ -18,7 +18,7 @@   -- |   -- A string literal   ---  | StringLiteral Text+  | StringLiteral PSString   -- |   -- A character literal   --@@ -34,5 +34,5 @@   -- |   -- An object literal   ---  | ObjectLiteral [(Text, a)]+  | ObjectLiteral [(PSString, a)]   deriving (Eq, Ord, Show, Functor)
src/Language/PureScript/CodeGen/JS.hs view
@@ -20,6 +20,7 @@ import qualified Data.Map as M import Data.Maybe (fromMaybe, isNothing) import Data.Monoid ((<>))+import Data.String (fromString) import Data.Text (Text) import qualified Data.Text as T @@ -34,6 +35,7 @@                                    errorMessage, rethrowWithPosition, addHint) import Language.PureScript.Names import Language.PureScript.Options+import Language.PureScript.PSString (PSString, mkString, decodeString) import Language.PureScript.Traversals (sndM) import qualified Language.PureScript.Constants as C @@ -65,8 +67,8 @@     let moduleBody = header : foreign' ++ jsImports ++ concat optimized     let foreignExps = exps `intersect` (fst `map` foreigns)     let standardExps = exps \\ foreignExps-    let exps' = JSObjectLiteral Nothing $ map (runIdent &&& JSVar Nothing . identToJs) standardExps-                               ++ map (runIdent &&& foreignIdent) foreignExps+    let exps' = JSObjectLiteral Nothing $ map (mkString . runIdent &&& JSVar Nothing . identToJs) standardExps+                               ++ map (mkString . runIdent &&& foreignIdent) foreignExps     return $ moduleBody ++ [JSAssignment Nothing (JSAccessor Nothing "exports" (JSVar Nothing "module")) exps']    where@@ -108,7 +110,7 @@   importToJs :: M.Map ModuleName (Ann, ModuleName) -> ModuleName -> m JS   importToJs mnLookup mn' = do     let ((ss, _, _, _), mnSafe) = fromMaybe (internalError "Missing value in mnLookup") $ M.lookup mn' mnLookup-    let moduleBody = JSApp Nothing (JSVar Nothing "require") [JSStringLiteral Nothing (T.pack (".." </> T.unpack (runModuleName mn')))]+    let moduleBody = JSApp Nothing (JSVar Nothing "require") [JSStringLiteral Nothing (fromString (".." </> T.unpack (runModuleName mn')))]     withPos ss $ JSVariableIntroduction Nothing (moduleNameToJs mnSafe) (Just moduleBody)    -- |@@ -176,12 +178,16 @@   -- indexer is returned.   --   accessor :: Ident -> JS -> JS-  accessor (Ident prop) = accessorString prop+  accessor (Ident prop) = accessorString $ mkString prop   accessor (GenIdent _ _) = internalError "GenIdent in accessor" -  accessorString :: Text -> JS -> JS-  accessorString prop | identNeedsEscaping prop = JSIndexer Nothing (JSStringLiteral Nothing prop)-                      | otherwise = JSAccessor Nothing prop+  accessorString :: PSString -> JS -> JS+  accessorString prop =+    case decodeString prop of+      Just s | not (identNeedsEscaping s) ->+        JSAccessor Nothing s+      _ ->+        JSIndexer Nothing (JSStringLiteral Nothing prop)    -- |   -- Generate code in the simplified Javascript intermediate representation for a value or expression.@@ -212,7 +218,7 @@     unAbs (Abs _ arg val) = arg : unAbs val     unAbs _ = []     assign :: Ident -> JS-    assign name = JSAssignment Nothing (accessorString (runIdent name) (JSVar Nothing "this"))+    assign name = JSAssignment Nothing (accessorString (mkString $ runIdent name) (JSVar Nothing "this"))                                (var name)   valueToJs' (Abs _ arg val) = do     ret <- valueToJs val@@ -272,7 +278,7 @@   literalToValueJS (NumericLiteral (Left i)) = return $ JSNumericLiteral Nothing (Left i)   literalToValueJS (NumericLiteral (Right n)) = return $ JSNumericLiteral Nothing (Right n)   literalToValueJS (StringLiteral s) = return $ JSStringLiteral Nothing s-  literalToValueJS (CharLiteral c) = return $ JSStringLiteral Nothing (T.singleton c)+  literalToValueJS (CharLiteral c) = return $ JSStringLiteral Nothing (fromString [c])   literalToValueJS (BooleanLiteral b) = return $ JSBooleanLiteral Nothing b   literalToValueJS (ArrayLiteral xs) = JSArrayLiteral Nothing <$> mapM valueToJs xs   literalToValueJS (ObjectLiteral ps) = JSObjectLiteral Nothing <$> mapM (sndM valueToJs) ps@@ -280,7 +286,7 @@   -- |   -- Shallow copy an object.   ---  extendObj :: JS -> [(Text, JS)] -> m JS+  extendObj :: JS -> [(PSString, JS)] -> m JS   extendObj obj sts = do     newObj <- freshName     key <- freshName@@ -317,7 +323,7 @@   qualifiedToJS f (Qualified _ a) = JSVar Nothing $ identToJs (f a)    foreignIdent :: Ident -> JS-  foreignIdent ident = accessorString (runIdent ident) (JSVar Nothing "$foreign")+  foreignIdent ident = accessorString (mkString $ runIdent ident) (JSVar Nothing "$foreign")    -- |   -- Generate code in the simplified Javascript intermediate representation for pattern match binders@@ -341,7 +347,7 @@       go _ _ _ = internalError "Invalid arguments to bindersToJs"        failedPatternError :: [Text] -> JS-      failedPatternError names = JSUnary Nothing JSNew $ JSApp Nothing (JSVar Nothing "Error") [JSBinary Nothing Add (JSStringLiteral Nothing failedPatternMessage) (JSArrayLiteral Nothing $ zipWith valueError names vals)]+      failedPatternError names = JSUnary Nothing JSNew $ JSApp Nothing (JSVar Nothing "Error") [JSBinary Nothing Add (JSStringLiteral Nothing $ mkString failedPatternMessage) (JSArrayLiteral Nothing $ zipWith valueError names vals)]        failedPatternMessage :: Text       failedPatternMessage = "Failed pattern match" <> maybe "" (((" at " <> runModuleName mn <> " ") <>) . displayStartEndPos) maybeSpan <> ": "@@ -402,7 +408,7 @@   literalToBinderJS varName done (NumericLiteral num) =     return [JSIfElse Nothing (JSBinary Nothing EqualTo (JSVar Nothing varName) (JSNumericLiteral Nothing num)) (JSBlock Nothing done) Nothing]   literalToBinderJS varName done (CharLiteral c) =-    return [JSIfElse Nothing (JSBinary Nothing EqualTo (JSVar Nothing varName) (JSStringLiteral Nothing (T.singleton c))) (JSBlock Nothing done) Nothing]+    return [JSIfElse Nothing (JSBinary Nothing EqualTo (JSVar Nothing varName) (JSStringLiteral Nothing (fromString [c]))) (JSBlock Nothing done) Nothing]   literalToBinderJS varName done (StringLiteral str) =     return [JSIfElse Nothing (JSBinary Nothing EqualTo (JSVar Nothing varName) (JSStringLiteral Nothing str)) (JSBlock Nothing done) Nothing]   literalToBinderJS varName done (BooleanLiteral True) =@@ -411,7 +417,7 @@     return [JSIfElse Nothing (JSUnary Nothing Not (JSVar Nothing varName)) (JSBlock Nothing done) Nothing]   literalToBinderJS varName done (ObjectLiteral bs) = go done bs     where-    go :: [JS] -> [(Text, Binder Ann)] -> m [JS]+    go :: [JS] -> [(PSString, Binder Ann)] -> m [JS]     go done' [] = return done'     go done' ((prop, binder):bs') = do       propVar <- freshName
src/Language/PureScript/CodeGen/JS/AST.hs view
@@ -11,6 +11,7 @@  import Language.PureScript.AST (SourceSpan(..)) import Language.PureScript.Comments+import Language.PureScript.PSString (PSString) import Language.PureScript.Traversals  -- |@@ -132,7 +133,7 @@   -- |   -- A string literal   ---  | JSStringLiteral (Maybe SourceSpan) Text+  | JSStringLiteral (Maybe SourceSpan) PSString   -- |   -- A boolean literal   --@@ -156,7 +157,7 @@   -- |   -- An object literal   ---  | JSObjectLiteral (Maybe SourceSpan) [(Text, JS)]+  | JSObjectLiteral (Maybe SourceSpan) [(PSString, JS)]   -- |   -- An object property accessor expression   --@@ -240,7 +241,8 @@   -- |   -- Commented Javascript   ---  | JSComment (Maybe SourceSpan) [Comment] JS deriving (Show, Eq)+  | JSComment (Maybe SourceSpan) [Comment] JS+  deriving (Show, Eq)  withSourceSpan :: SourceSpan -> JS -> JS withSourceSpan withSpan = go
src/Language/PureScript/CodeGen/JS/Optimizer/Common.hs view
@@ -11,6 +11,7 @@  import Language.PureScript.Crash import Language.PureScript.CodeGen.JS.AST+import Language.PureScript.PSString (mkString)  applyAll :: [a -> a] -> a -> a applyAll = foldl' (.) id@@ -73,7 +74,7 @@ isFn (moduleName, fnName) (JSAccessor _ x (JSVar _ y)) =   x == fnName && y == moduleName isFn (moduleName, fnName) (JSIndexer _ (JSStringLiteral _ x) (JSVar _ y)) =-  x == fnName && y == moduleName+  x == mkString fnName && y == moduleName isFn _ _ = False  isDict :: (Text, Text) -> JS -> Bool
src/Language/PureScript/CodeGen/JS/Optimizer/Inliner.hs view
@@ -239,7 +239,7 @@   isModFn _ _ = False    isModFnWithDict :: (Text, Text) -> JS -> Bool-  isModFnWithDict (m, op) (JSApp _ (JSAccessor _ op' (JSVar _ m')) [(JSVar _ _)]) = m == m' && op == op'+  isModFnWithDict (m, op) (JSApp _ (JSAccessor _ op' (JSVar _ m')) [JSVar _ _]) = m == m' && op == op'   isModFnWithDict _ _ = False  -- (f <<< g $ x) = f (g x)
src/Language/PureScript/CodeGen/JS/Optimizer/MagicDo.hs view
@@ -12,6 +12,7 @@ import Language.PureScript.CodeGen.JS.AST import Language.PureScript.CodeGen.JS.Optimizer.Common import Language.PureScript.Options+import Language.PureScript.PSString (mkString) import qualified Language.PureScript.Constants as C  magicDo :: Options -> JS -> JS@@ -104,7 +105,7 @@   -- or in a more aggressive way, turning wrappers into local variables depending on the   -- agg(ressive) parameter.   convert agg (JSApp s1 f [arg]) | isSTFunc C.newSTRef f =-   JSFunction s1 Nothing [] (JSBlock s1 [JSReturn s1 $ if agg then arg else JSObjectLiteral s1 [(C.stRefValue, arg)]])+   JSFunction s1 Nothing [] (JSBlock s1 [JSReturn s1 $ if agg then arg else JSObjectLiteral s1 [(mkString C.stRefValue, arg)]])   convert agg (JSApp _ (JSApp s1 f [ref]) []) | isSTFunc C.readSTRef f =     if agg then ref else JSAccessor s1 C.stRefValue ref   convert agg (JSApp _ (JSApp _ (JSApp s1 f [ref]) [arg]) []) | isSTFunc C.writeSTRef f =
src/Language/PureScript/CoreFn/Desugar.hs view
@@ -24,6 +24,7 @@ import Language.PureScript.Names import Language.PureScript.Sugar.TypeClasses (typeClassMemberName, superClassDictionaryNames) import Language.PureScript.Types+import Language.PureScript.PSString (mkString) import qualified Language.PureScript.AST as A  -- |@@ -119,7 +120,7 @@     in foldl (App (ss, com, Nothing, Nothing)) ctor args   exprToCoreFn ss com ty  (A.TypeClassDictionaryAccessor _ ident) =     Abs (ss, com, ty, Nothing) (Ident "dict")-      (Accessor nullAnn (runIdent ident) (Var nullAnn $ Qualified Nothing (Ident "dict")))+      (Accessor nullAnn (mkString $ runIdent ident) (Var nullAnn $ Qualified Nothing (Ident "dict")))   exprToCoreFn _ com ty (A.PositionedValue ss com1 v) =     exprToCoreFn (Just ss) (com ++ com1) ty v   exprToCoreFn _ _ _ e =@@ -265,7 +266,7 @@ mkTypeClassConstructor ss com [] [] = Literal (ss, com, Nothing, Just IsTypeClassConstructor) (ObjectLiteral []) mkTypeClassConstructor ss com supers members =   let args@(a:as) = sort $ map typeClassMemberName members ++ superClassDictionaryNames supers-      props = [ (arg, Var nullAnn $ Qualified Nothing (Ident arg)) | arg <- args ]+      props = [ (mkString arg, Var nullAnn $ Qualified Nothing (Ident arg)) | arg <- args ]       dict = Literal nullAnn (ObjectLiteral props)   in Abs (ss, com, Nothing, Just IsTypeClassConstructor)          (Ident a)
src/Language/PureScript/CoreFn/Expr.hs view
@@ -6,11 +6,11 @@ import Prelude.Compat  import Control.Arrow ((***))-import Data.Text (Text)  import Language.PureScript.AST.Literals import Language.PureScript.CoreFn.Binders import Language.PureScript.Names+import Language.PureScript.PSString (PSString)  -- | -- Data type for expressions and terms@@ -27,11 +27,11 @@   -- |   -- A record property accessor   ---  | Accessor a Text (Expr a)+  | Accessor a PSString (Expr a)   -- |   -- Partial record update   ---  | ObjectUpdate a (Expr a) [(Text, Expr a)]+  | ObjectUpdate a (Expr a) [(PSString, Expr a)]   -- |   -- Function introduction   --
src/Language/PureScript/CoreFn/ToJSON.hs view
@@ -9,6 +9,7 @@  import Prelude.Compat +import Data.Maybe (fromMaybe) import Data.Aeson import Data.Version (Version, showVersion) import Data.Text (Text)@@ -17,6 +18,7 @@ import Language.PureScript.AST.Literals import Language.PureScript.CoreFn import Language.PureScript.Names+import Language.PureScript.PSString (PSString, decodeString)  literalToJSON :: (a -> Value) -> Literal a -> Value literalToJSON _ (NumericLiteral (Left n)) = toJSON ("IntLiteral", n)@@ -51,8 +53,17 @@ bindToJSON (NonRec _ n e) = object [ runIdent n .= exprToJSON e ] bindToJSON (Rec bs) = object $ map (\((_, n), e) -> runIdent n .= exprToJSON e) bs -recordToJSON :: (a -> Value) -> [(Text, a)] -> Value-recordToJSON f = object . map (\(label, a) -> label .= f a)+-- If all of the labels in the record can safely be converted to JSON strings,+-- we generate a JSON object. Otherwise the labels must be represented as+-- arrays of integers in the JSON, and in this case we generate the record as+-- an array of pairs.+recordToJSON :: (a -> Value) -> [(PSString, a)] -> Value+recordToJSON f rec = fromMaybe (asArrayOfPairs rec) (asObject rec)+  where+  asObject = fmap object . traverse (uncurry maybePair)+  maybePair label a = fmap (\l -> l .= f a) (decodeString label)++  asArrayOfPairs = toJSON . map (\(label, a) -> (toJSON label, f a))  exprToJSON :: Expr a -> Value exprToJSON (Var _ i)              = toJSON ( "Var"
src/Language/PureScript/Docs/RenderedCode/Render.hs view
@@ -26,7 +26,9 @@ import Language.PureScript.Kinds import Language.PureScript.Names import Language.PureScript.Pretty.Kinds+import Language.PureScript.Pretty.Types import Language.PureScript.Types+import Language.PureScript.Label (Label)  typeLiterals :: Pattern () Type RenderedCode typeLiterals = mkPattern match@@ -79,13 +81,13 @@   where   renderRow' h t = renderHead h <> renderTail t -renderHead :: [(Text, Type)] -> RenderedCode+renderHead :: [(Label, Type)] -> RenderedCode renderHead = mintersperse (syntax "," <> sp) . map renderLabel -renderLabel :: (Text, Type) -> RenderedCode+renderLabel :: (Label, Type) -> RenderedCode renderLabel (label, ty) =   mintersperse sp-    [ ident label+    [ syntax $ prettyPrintLabel label     , syntax "::"     , renderType ty     ]@@ -125,9 +127,9 @@   match _ = Nothing  matchTypeAtom :: Pattern () Type RenderedCode-matchTypeAtom = typeLiterals <+> fmap parens matchType+matchTypeAtom = typeLiterals <+> fmap parens_ matchType   where-  parens x = syntax "(" <> x <> syntax ")"+  parens_ x = syntax "(" <> x <> syntax ")"  matchType :: Pattern () Type RenderedCode matchType = buildPrettyPrinter operators matchTypeAtom
src/Language/PureScript/Docs/Types.hs view
@@ -10,6 +10,7 @@ import Control.Monad (when) import Control.Monad.Error.Class (catchError) +import Data.Monoid ((<>)) import Data.Aeson ((.=)) import Data.Aeson.BetterErrors import Data.ByteString.Lazy (ByteString)@@ -358,8 +359,6 @@     "Invalid kind: \"" <> str <> "\""   InvalidDataDeclType str ->     "Invalid data declaration type: \"" <> str <> "\""-  where-  (<>) = T.append  instance A.FromJSON a => A.FromJSON (Package a) where   parseJSON = toAesonParser displayPackageError@@ -413,7 +412,7 @@  asInPackage :: Parse BowerError a -> Parse BowerError (InPackage a) asInPackage inner =-  build <$> key "package" (perhaps (withString parsePackageName))+  build <$> key "package" (perhaps (withText parsePackageName))         <*> key "item" inner   where   build Nothing = Local@@ -468,8 +467,8 @@   where   asTypeArgument = (,) <$> nth 0 asText <*> nth 1 (perhaps asKind) -asKind :: Parse e P.Kind-asKind = fromAesonParser+asKind :: Parse PackageError P.Kind+asKind = P.kindFromJSON .! InvalidKind  asType :: Parse e P.Type asType = fromAesonParser@@ -532,7 +531,7 @@  asResolvedDependencies :: Parse PackageError [(PackageName, Version)] asResolvedDependencies =-  eachInObjectWithKey (mapLeft ErrorInPackageMeta . parsePackageName . T.unpack) asVersion+  eachInObjectWithKey (mapLeft ErrorInPackageMeta . parsePackageName) asVersion   where   mapLeft f (Left x) = Left (f x)   mapLeft _ (Right x) = Right x@@ -557,7 +556,7 @@       , "versionTag"           .= pkgVersionTag       , "modules"              .= pkgModules       , "bookmarks"            .= map (fmap (first P.runModuleName)) pkgBookmarks-      , "resolvedDependencies" .= assocListToJSON (T.pack . runPackageName)+      , "resolvedDependencies" .= assocListToJSON runPackageName                                                   (T.pack . showVersion)                                                   pkgResolvedDependencies       , "github"               .= pkgGithub
src/Language/PureScript/Errors.hs view
@@ -32,10 +32,10 @@ import Language.PureScript.Pretty import Language.PureScript.Traversals import Language.PureScript.Types-import Language.PureScript.Pretty.Common (endWith)+import Language.PureScript.Label (Label(..))+import Language.PureScript.Pretty.Common (before, endWith) import qualified Language.PureScript.Bundle as Bundle import qualified Language.PureScript.Constants as C-import Language.PureScript.Pretty.Common (before)  import qualified System.Console.ANSI as ANSI @@ -264,7 +264,7 @@   gSimple (ExprDoesNotHaveType e t) = ExprDoesNotHaveType e <$> f t   gSimple (InvalidInstanceHead t) = InvalidInstanceHead <$> f t   gSimple (NoInstanceFound con) = NoInstanceFound <$> overConstraintArgs (traverse f) con-  gSimple (AmbiguousTypeVariables t con) = AmbiguousTypeVariables <$> (f t) <*> pure con+  gSimple (AmbiguousTypeVariables t con) = AmbiguousTypeVariables <$> f t <*> pure con   gSimple (OverlappingInstances cl ts insts) = OverlappingInstances cl <$> traverse f ts <*> pure insts   gSimple (PossiblyInfiniteInstance cl ts) = PossiblyInfiniteInstance cl <$> traverse f ts   gSimple (CannotDerive cl ts) = CannotDerive cl <$> traverse f ts@@ -498,6 +498,8 @@       line $ "The type declaration for " <> markCode (showIdent nm) <> " should be followed by its definition."     renderSimpleErrorMessage (RedefinedIdent name) =       line $ "The value " <> markCode (showIdent name) <> " has been defined multiple times"+    renderSimpleErrorMessage (UnknownName name@(Qualified Nothing (IdentName (Ident "bind")))) =+      line $ "Unknown " <> printName name <> ". You're probably using do-notation, which the compiler replaces with calls to the " <> markCode "bind" <> " function. Please import " <> markCode "bind" <> " from module " <> markCode "Prelude"     renderSimpleErrorMessage (UnknownName name) =       line $ "Unknown " <> printName name     renderSimpleErrorMessage (UnknownImport mn name) =@@ -563,12 +565,12 @@             sortRows t1 t2 = (t1, t2)              -- Put the common labels last-            sortRows' :: ([(Text, Type)], Type) -> ([(Text, Type)], Type) -> (Type, Type)+            sortRows' :: ([(Label, Type)], Type) -> ([(Label, Type)], Type) -> (Type, Type)             sortRows' (s1, r1) (s2, r2) =-              let common :: [(Text, (Type, Type))]+              let common :: [(Label, (Type, Type))]                   common = sortBy (comparing fst) [ (name, (t1, t2)) | (name, t1) <- s1, (name', t2) <- s2, name == name' ] -                  sd1, sd2 :: [(Text, Type)]+                  sd1, sd2 :: [(Label, Type)]                   sd1 = [ (name, t1) | (name, t1) <- s1, name `notElem` map fst s2 ]                   sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ]               in ( rowFromList (sortBy (comparing fst) sd1 ++ map (fst &&& fst . snd) common, r1)@@ -671,7 +673,7 @@     renderSimpleErrorMessage (CannotFindDerivingType nm) =       line $ "Cannot derive a type class instance, because the type declaration for " <> markCode (runProperName nm) <> " could not be found."     renderSimpleErrorMessage (DuplicateLabel l expr) =-      paras $ [ line $ "Label " <> markCode l <> " appears more than once in a row type." ]+      paras $ [ line $ "Label " <> markCode (prettyPrintLabel l) <> " appears more than once in a row type." ]                        <> foldMap (\expr' -> [ line "Relevant expression: "                                              , markCodeBox $ indent $ prettyPrintValue valueDepth expr'                                              ]) expr@@ -704,9 +706,9 @@             , markCodeBox $ indent $ typeAsBox ty             ]     renderSimpleErrorMessage (PropertyIsMissing prop) =-      line $ "Type of expression lacks required label " <> markCode prop <> "."+      line $ "Type of expression lacks required label " <> markCode (prettyPrintLabel prop) <> "."     renderSimpleErrorMessage (AdditionalProperty prop) =-      line $ "Type of expression contains additional label " <> markCode prop <> "."+      line $ "Type of expression contains additional label " <> markCode (prettyPrintLabel prop) <> "."     renderSimpleErrorMessage TypeSynonymInstance =       line "Type class instances for type synonyms are disallowed."     renderSimpleErrorMessage (OrphanInstance nm cnm ts) =@@ -1263,7 +1265,7 @@   whiteSpace = all isSpace  toTypelevelString :: Type -> Maybe Box.Box-toTypelevelString (TypeLevelString s) = Just $ Box.text (T.unpack s)+toTypelevelString (TypeLevelString s) = Just $ Box.text $ T.unpack $ prettyPrintString s toTypelevelString (TypeApp (TypeConstructor f) x)   | f == primName "TypeString" = Just $ typeAsBox x toTypelevelString (TypeApp (TypeApp (TypeConstructor f) x) ret)
src/Language/PureScript/Kinds.hs view
@@ -1,12 +1,15 @@-{-# LANGUAGE TemplateHaskell #-}- module Language.PureScript.Kinds where  import Prelude.Compat -import qualified Data.Aeson.TH as A+import Data.Text (Text)+import qualified Data.Text as T+import Data.Aeson.BetterErrors (Parse, key, asText, asIntegral, nth, fromAesonParser, toAesonParser, throwCustomError)+import Data.Aeson ((.=))+import qualified Data.Aeson as A  import Language.PureScript.Names+import qualified Language.PureScript.Constants as C  -- | The data type of kinds data Kind@@ -20,7 +23,66 @@   | NamedKind (Qualified (ProperName 'KindName))   deriving (Show, Eq, Ord) -$(A.deriveJSON A.defaultOptions ''Kind)+-- This is equivalent to the derived Aeson ToJSON instance, except that we+-- write it out manually so that we can define a parser which is+-- backwards-compatible.+instance A.ToJSON Kind where+  toJSON kind = case kind of+    KUnknown i ->+      obj "KUnknown" i+    Row k ->+      obj "Row" k+    FunKind k1 k2 ->+      obj "FunKind" [k1, k2]+    NamedKind n ->+      obj "NamedKind" n+    where+    obj :: A.ToJSON a => Text -> a -> A.Value+    obj tag contents =+      A.object [ "tag" .= tag, "contents" .= contents ]++-- This is equivalent to the derived Aeson FromJSON instance, except that it+-- also handles JSON generated by compilers up to 0.10.3 and maps them to the+-- new representations (i.e. NamedKinds which are defined in the Prim module).+kindFromJSON :: Parse Text Kind+kindFromJSON = do+  t <- key "tag" asText+  case t of+    "KUnknown" ->+      KUnknown <$> key "contents" (nth 0 asIntegral)+    "Star" ->+      pure kindType+    "Bang" ->+      pure kindEffect+    "Row" ->+      Row <$> key "contents" kindFromJSON+    "FunKind" ->+      let+        kindAt n = key "contents" (nth n kindFromJSON)+      in+        FunKind <$> kindAt 0 <*> kindAt 1+    "Symbol" ->+      pure kindSymbol+    "NamedKind" ->+      NamedKind <$> key "contents" fromAesonParser+    other ->+      throwCustomError (T.append "Unrecognised tag: " other)++  where+  -- The following are copied from Environment and reimplemented to avoid+  -- circular dependencies.+  primName :: Text -> Qualified (ProperName a)+  primName = Qualified (Just $ ModuleName [ProperName C.prim]) . ProperName++  primKind :: Text -> Kind+  primKind = NamedKind . primName++  kindType = primKind "Type"+  kindEffect = primKind "Effect"+  kindSymbol = primKind "Symbol"++instance A.FromJSON Kind where+  parseJSON = toAesonParser id kindFromJSON  everywhereOnKinds :: (Kind -> Kind) -> Kind -> Kind everywhereOnKinds f = go
+ src/Language/PureScript/Label.hs view
@@ -0,0 +1,16 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+module Language.PureScript.Label (Label(..)) where++import Prelude.Compat hiding (lex)+import Data.Monoid ()+import Data.String (IsString(..))+import qualified Data.Aeson as A++import Language.PureScript.PSString (PSString)++-- |+-- Labels are used as record keys and row entry names. Labels newtype PSString+-- because records are indexable by PureScript strings at runtime.+--+newtype Label = Label { runLabel :: PSString }+  deriving (Show, Eq, Ord, IsString, Monoid, A.ToJSON, A.FromJSON)
+ src/Language/PureScript/PSString.hs view
@@ -0,0 +1,187 @@+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+module Language.PureScript.PSString+  ( PSString+  , toUTF16CodeUnits+  , decodeString+  , decodeStringEither+  , prettyPrintString+  , prettyPrintStringJS+  , mkString+  ) where++import Prelude.Compat+import Control.Exception (try, evaluate)+import Control.Applicative ((<|>))+import Data.Char (chr)+import Data.Bits (shiftR)+import Data.List (unfoldr)+import Data.Monoid ((<>))+import Data.Scientific (toBoundedInteger)+import Data.String (IsString(..))+import Data.ByteString (ByteString)+import qualified Data.ByteString as BS+import Data.Text (Text)+import qualified Data.Text as T+import Data.Text.Encoding (decodeUtf16BE)+import Data.Text.Encoding.Error (UnicodeException)+import qualified Data.Vector as V+import Data.Word (Word16, Word8)+import Numeric (showHex)+import System.IO.Unsafe (unsafePerformIO)+import qualified Data.Aeson as A+import qualified Data.Aeson.Types as A++-- |+-- Strings in PureScript are sequences of UTF-16 code units, which do not+-- necessarily represent UTF-16 encoded text. For example, it is permissible+-- for a string to contain *lone surrogates,* i.e. characters in the range+-- U+D800 to U+DFFF which do not appear as a part of a surrogate pair.+--+-- The Show instance for PSString produces a string literal which would+-- represent the same data were it inserted into a PureScript source file.+--+-- Because JSON parsers vary wildly in terms of how they deal with lone+-- surrogates in JSON strings, the ToJSON instance for PSString produces JSON+-- strings where that would be safe (i.e. when there are no lone surrogates),+-- and arrays of UTF-16 code units (integers) otherwise.+--+newtype PSString = PSString { toUTF16CodeUnits :: [Word16] }+  deriving (Eq, Ord, Monoid)++instance Show PSString where+  show = show . codePoints++-- Decode a PSString to a String, representing any lone surrogates as the+-- reserved code point with that index. Warning: if there are any lone+-- surrogates, converting the result to Text via Data.Text.pack will result in+-- loss of information as those lone surrogates will be replaced with U+FFFD+-- REPLACEMENT CHARACTER. Because this function requires care to use correctly,+-- we do not export it.+codePoints :: PSString -> String+codePoints = map (either (chr . fromIntegral) id) . decodeStringEither++-- |+-- Decode a PSString as UTF-16. Lone surrogates in the input are represented in+-- the output with the Left constructor; characters which were successfully+-- decoded are represented with the Right constructor.+--+decodeStringEither :: PSString -> [Either Word16 Char]+decodeStringEither = unfoldr decode . toUTF16CodeUnits+  where+  decode :: [Word16] -> Maybe (Either Word16 Char, [Word16])+  decode (h:l:rest) | isLead h && isTrail l = Just (Right (unsurrogate h l), rest)+  decode (c:rest) | isSurrogate c = Just (Left c, rest)+  decode (c:rest) = Just (Right (toChar c), rest)+  decode [] = Nothing++  unsurrogate :: Word16 -> Word16 -> Char+  unsurrogate h l = toEnum ((toInt h - 0xD800) * 0x400 + (toInt l - 0xDC00) + 0x10000)++-- |+-- Pretty print a PSString, using Haskell/PureScript escape sequences.+-- This is identical to the Show instance except that we get a Text out instead+-- of a String.+--+prettyPrintString :: PSString -> Text+prettyPrintString = T.pack . show++-- |+-- Attempt to decode a PSString as UTF-16 text. This will fail (returning+-- Nothing) if the argument contains lone surrogates.+--+decodeString :: PSString -> Maybe Text+decodeString = hush . decodeEither . BS.pack . concatMap unpair . toUTF16CodeUnits+  where+  unpair w = [highByte w, lowByte w]++  lowByte :: Word16 -> Word8+  lowByte = fromIntegral++  highByte :: Word16 -> Word8+  highByte = fromIntegral . (`shiftR` 8)++  -- Based on a similar function from Data.Text.Encoding for utf8. This is a+  -- safe usage of unsafePerformIO because there are no side effects after+  -- handling any thrown UnicodeExceptions.+  decodeEither :: ByteString -> Either UnicodeException Text+  decodeEither = unsafePerformIO . try . evaluate . decodeUtf16BE++  hush = either (const Nothing) Just++instance IsString PSString where+  fromString a = PSString $ concatMap encodeUTF16 a+    where+    surrogates :: Char -> (Word16, Word16)+    surrogates c = (toWord (h + 0xD800), toWord (l + 0xDC00))+      where (h, l) = divMod (fromEnum c - 0x10000) 0x400++    encodeUTF16 :: Char -> [Word16]+    encodeUTF16 c | fromEnum c > 0xFFFF = [high, low]+      where (high, low) = surrogates c+    encodeUTF16 c = [toWord $ fromEnum c]++instance A.ToJSON PSString where+  toJSON str =+    case decodeString str of+      Just t -> A.toJSON t+      Nothing -> A.toJSON (toUTF16CodeUnits str)++instance A.FromJSON PSString where+  parseJSON a = jsonString <|> arrayOfCodeUnits+    where+    jsonString = fromString <$> A.parseJSON a++    arrayOfCodeUnits = PSString <$> parseArrayOfCodeUnits a++    parseArrayOfCodeUnits :: A.Value -> A.Parser [Word16]+    parseArrayOfCodeUnits = A.withArray "array of UTF-16 code units" (traverse parseCodeUnit . V.toList)++    parseCodeUnit :: A.Value -> A.Parser Word16+    parseCodeUnit b = A.withScientific "two-byte non-negative integer" (maybe (A.typeMismatch "" b) return . toBoundedInteger) b++-- |+-- Pretty print a PSString, using JavaScript escape sequences. Intended for+-- use in compiled JS output.+--+prettyPrintStringJS :: PSString -> Text+prettyPrintStringJS s = "\"" <> foldMap encodeChar (toUTF16CodeUnits s) <> "\""+  where+  encodeChar :: Word16 -> Text+  encodeChar c | c > 0xFF = "\\u" <> hex 4 c+  encodeChar c | c > 0x7E || c < 0x20 = "\\x" <> hex 2 c+  encodeChar c | toChar c == '\b' = "\\b"+  encodeChar c | toChar c == '\t' = "\\t"+  encodeChar c | toChar c == '\n' = "\\n"+  encodeChar c | toChar c == '\v' = "\\v"+  encodeChar c | toChar c == '\f' = "\\f"+  encodeChar c | toChar c == '\r' = "\\r"+  encodeChar c | toChar c == '"'  = "\\\""+  encodeChar c | toChar c == '\\' = "\\\\"+  encodeChar c = T.singleton $ toChar c++  hex :: (Enum a) => Int -> a -> Text+  hex width c =+    let hs = showHex (fromEnum c) "" in+    T.pack (replicate (width - length hs) '0' <> hs)++isLead :: Word16 -> Bool+isLead h = h >= 0xD800 && h <= 0xDBFF++isTrail :: Word16 -> Bool+isTrail l = l >= 0xDC00 && l <= 0xDFFF++isSurrogate :: Word16 -> Bool+isSurrogate c = isLead c || isTrail c++toChar :: Word16 -> Char+toChar = toEnum . fromIntegral++toWord :: Int -> Word16+toWord = fromIntegral++toInt :: Word16 -> Int+toInt = fromIntegral++mkString :: Text -> PSString+mkString = fromString . T.unpack
src/Language/PureScript/Parser/Common.hs view
@@ -16,6 +16,7 @@ import Language.PureScript.Names import Language.PureScript.Parser.Lexer import Language.PureScript.Parser.State+import Language.PureScript.PSString (PSString, mkString)  import qualified Text.Parsec as P @@ -71,6 +72,12 @@ -- parseIdent :: TokenParser Ident parseIdent = Ident <$> identifier++-- |+-- Parse a label, which may look like an identifier or a string+--+parseLabel :: TokenParser PSString+parseLabel = (mkString <$> lname) <|> stringLiteral  -- | -- Parse an operator.
src/Language/PureScript/Parser/Declarations.hs view
@@ -33,6 +33,7 @@ import Language.PureScript.Kinds import Language.PureScript.Names import Language.PureScript.Types+import Language.PureScript.PSString (PSString, mkString) import Language.PureScript.Parser.Common import Language.PureScript.Parser.Kinds import Language.PureScript.Parser.Lexer@@ -338,15 +339,15 @@ parseArrayLiteral :: TokenParser a -> TokenParser (Literal a) parseArrayLiteral p = ArrayLiteral <$> squares (commaSep p) -parseObjectLiteral :: TokenParser (Text, a) -> TokenParser (Literal a)+parseObjectLiteral :: TokenParser (PSString, a) -> TokenParser (Literal a) parseObjectLiteral p = ObjectLiteral <$> braces (commaSep p) -parseIdentifierAndValue :: TokenParser (Text, Expr)+parseIdentifierAndValue :: TokenParser (PSString, Expr) parseIdentifierAndValue =   do     name <- C.indented *> lname     b <- P.option (Var $ Qualified Nothing (Ident name)) rest-    return (name, b)+    return (mkString name, b)   <|> (,) <$> (C.indented *> stringLiteral) <*> rest   where   rest = C.indented *> colon *> C.indented *> parseValue@@ -428,16 +429,16 @@ parseHole :: TokenParser Expr parseHole = Hole <$> holeLit -parsePropertyUpdate :: TokenParser (Text, Expr)+parsePropertyUpdate :: TokenParser (PSString, Expr) parsePropertyUpdate = do-  name <- lname <|> stringLiteral+  name <- parseLabel   _ <- C.indented *> equals   value <- C.indented *> parseValue   return (name, value)  parseAccessor :: Expr -> TokenParser Expr parseAccessor (Constructor _) = P.unexpected "constructor"-parseAccessor obj = P.try $ Accessor <$> (C.indented *> dot *> C.indented *> (lname <|> stringLiteral)) <*> pure obj+parseAccessor obj = P.try $ Accessor <$> (C.indented *> dot *> C.indented *> parseLabel) <*> pure obj  parseDo :: TokenParser Expr parseDo = do@@ -520,11 +521,11 @@ parseNullBinder :: TokenParser Binder parseNullBinder = underscore *> return NullBinder -parseIdentifierAndBinder :: TokenParser (Text, Binder)+parseIdentifierAndBinder :: TokenParser (PSString, Binder) parseIdentifierAndBinder =     do name <- lname        b <- P.option (VarBinder (Ident name)) rest-       return (name, b)+       return (mkString name, b)     <|> (,) <$> stringLiteral <*> rest   where     rest = C.indented *> colon *> C.indented *> parseBinder
src/Language/PureScript/Parser/Lexer.hs view
@@ -70,11 +70,13 @@ import Control.Monad.Identity (Identity) import Data.Char (isSpace, isAscii, isSymbol, isAlphaNum) import Data.Monoid ((<>))+import Data.String (fromString) import Data.Text (Text) import qualified Data.Text as T  import Language.PureScript.Comments import Language.PureScript.Parser.State+import Language.PureScript.PSString (PSString)  import qualified Text.Parsec as P import qualified Text.Parsec.Token as PT@@ -106,7 +108,7 @@   | Qualifier Text   | Symbol Text   | CharLiteral Char-  | StringLiteral Text+  | StringLiteral PSString   | Number (Either Integer Double)   | HoleLit Text   deriving (Show, Eq, Ord)@@ -249,18 +251,6 @@   symbolChar :: Lexer u Char   symbolChar = P.satisfy isSymbolChar -  surrogates :: Char -> (Char, Char)-  surrogates c = (high, low)-    where-      (h, l) = divMod (fromEnum c - 0x10000) 0x400-      high = toEnum (h + 0xD800)-      low = toEnum (l + 0xDC00)--  expandAstralCodePointToUTF16Surrogates :: Char -> [Char]-  expandAstralCodePointToUTF16Surrogates c | fromEnum c > 0xFFFF = [high, low]-    where (high, low) = surrogates c-  expandAstralCodePointToUTF16Surrogates c = [c]-   parseCharLiteral :: Lexer u Char   parseCharLiteral = P.try $ do {     c <- PT.charLiteral tokenParser;@@ -269,11 +259,11 @@       else return c   } -  parseStringLiteral :: Lexer u Text-  parseStringLiteral = blockString <|> T.pack <$> concatMap expandAstralCodePointToUTF16Surrogates <$> PT.stringLiteral tokenParser+  parseStringLiteral :: Lexer u PSString+  parseStringLiteral = fromString <$> (blockString <|> PT.stringLiteral tokenParser)     where     delimiter   = P.try (P.string "\"\"\"")-    blockString = delimiter *> (T.pack <$> P.manyTill P.anyChar delimiter)+    blockString = delimiter *> P.manyTill P.anyChar delimiter    parseNumber :: Lexer u (Either Integer Double)   parseNumber = (consumeLeadingZero *> P.parserZero) <|>@@ -516,7 +506,7 @@   go (CharLiteral c) = Just c   go _ = Nothing -stringLiteral :: TokenParser Text+stringLiteral :: TokenParser PSString stringLiteral = token go P.<?> "string literal"   where   go (StringLiteral s) = Just s
src/Language/PureScript/Parser/Types.hs view
@@ -9,7 +9,6 @@  import Control.Monad (when, unless) import Control.Applicative ((<|>))-import Data.Text (Text) import qualified Data.Text as T  import Language.PureScript.AST.SourcePos@@ -18,6 +17,7 @@ import Language.PureScript.Parser.Kinds import Language.PureScript.Parser.Lexer import Language.PureScript.Types+import Language.PureScript.Label (Label(..))  import qualified Text.Parsec as P import qualified Text.Parsec.Expr as P@@ -118,8 +118,8 @@   when (containsWildcards ty) $ P.unexpected "type wildcard"   return ty -parseNameAndType :: TokenParser t -> TokenParser (Text, t)-parseNameAndType p = (,) <$> (indented *> (lname <|> stringLiteral) <* indented <* doubleColon) <*> p+parseNameAndType :: TokenParser t -> TokenParser (Label, t)+parseNameAndType p = (,) <$> (indented *> (Label <$> parseLabel) <* indented <* doubleColon) <*> p  parseRowEnding :: TokenParser Type parseRowEnding = P.option REmpty $ indented *> pipe *> indented *> parseType
src/Language/PureScript/Pretty.hs view
@@ -15,3 +15,4 @@ import Language.PureScript.Pretty.Kinds as P import Language.PureScript.Pretty.Types as P import Language.PureScript.Pretty.Values as P+import Language.PureScript.PSString as P (prettyPrintString)
src/Language/PureScript/Pretty/Common.hs view
@@ -15,7 +15,7 @@ import qualified Data.Text as T  import Language.PureScript.AST (SourcePos(..), SourceSpan(..))-import Language.PureScript.Parser.Lexer (reservedPsNames, isUnquotedKey)+import Language.PureScript.Parser.Lexer (isUnquotedKey, reservedPsNames)  import Text.PrettyPrint.Boxes hiding ((<>)) import qualified Text.PrettyPrint.Boxes as Box@@ -146,13 +146,9 @@   indentString <- currentIndent   return $ intercalate (emit "\n") $ map (mappend indentString) ss --- |--- Prints an object key, escaping reserved names.----prettyPrintObjectKey :: Text -> Text-prettyPrintObjectKey s | s `elem` reservedPsNames = T.pack (show s)-                       | isUnquotedKey s = s-                       | otherwise = T.pack (show s)+objectKeyRequiresQuoting :: Text -> Bool+objectKeyRequiresQuoting s =+  s `elem` reservedPsNames || isUnquotedKey s  -- | Place a box before another, vertically when the first box takes up multiple lines. before :: Box -> Box -> Box
src/Language/PureScript/Pretty/JS.hs view
@@ -25,8 +25,7 @@ import Language.PureScript.Comments import Language.PureScript.Crash import Language.PureScript.Pretty.Common--import Numeric+import Language.PureScript.PSString (PSString, decodeString, prettyPrintStringJS)  -- TODO (Christoph): Get rid of T.unpack / pack @@ -38,7 +37,7 @@    match :: (Emit gen) => JS -> StateT PrinterState Maybe gen   match (JSNumericLiteral _ n) = return $ emit $ T.pack $ either show show n-  match (JSStringLiteral _ s) = return $ string s+  match (JSStringLiteral _ s) = return $ emit $ prettyPrintStringJS s   match (JSBooleanLiteral _ True) = return $ emit "true"   match (JSBooleanLiteral _ False) = return $ emit "false"   match (JSArrayLiteral _ xs) = mconcat <$> sequence@@ -58,9 +57,13 @@     , return $ emit "}"     ]     where-    objectPropertyToString :: (Emit gen) => Text -> gen-    objectPropertyToString s | identNeedsEscaping s = string s-                             | otherwise = emit s+    objectPropertyToString :: (Emit gen) => PSString -> gen+    objectPropertyToString s =+      emit $ case decodeString s of+        Just s' | not (identNeedsEscaping s') ->+          s'+        _ ->+          prettyPrintStringJS s   match (JSBlock _ sts) = mconcat <$> sequence     [ return $ emit "{\n"     , withIndent $ prettyStatements sts@@ -150,29 +153,6 @@   match (JSRaw _ js) = return $ emit js   match _ = mzero -string :: (Emit gen) => Text -> gen-string s = emit $ "\"" <> T.concatMap encodeChar s <> "\""-  where-  encodeChar :: Char -> Text-  encodeChar '\b' = "\\b"-  encodeChar '\t' = "\\t"-  encodeChar '\n' = "\\n"-  encodeChar '\v' = "\\v"-  encodeChar '\f' = "\\f"-  encodeChar '\r' = "\\r"-  encodeChar '"'  = "\\\""-  encodeChar '\\' = "\\\\"-  -- PureScript strings are sequences of UTF-16 code units, so this case should never be hit.-  -- If it is somehow hit, though, output the designated Unicode replacement character U+FFFD.-  encodeChar c | fromEnum c > 0xFFFF = "\\uFFFD"-  encodeChar c | fromEnum c > 0xFFF = "\\u" <> showHex' (fromEnum c) ""-  encodeChar c | fromEnum c > 0xFF = "\\u0" <> showHex' (fromEnum c) ""-  encodeChar c | fromEnum c < 0x10 = "\\x0" <> showHex' (fromEnum c) ""-  encodeChar c | fromEnum c > 0x7E || fromEnum c < 0x20 = "\\x" <> showHex' (fromEnum c) ""-  encodeChar c = T.singleton c--  showHex' a b = T.pack (showHex a b)- conditional :: Pattern PrinterState JS ((Maybe SourceSpan, JS, JS), JS) conditional = mkPattern match   where@@ -182,6 +162,7 @@ accessor :: (Emit gen) => Pattern PrinterState JS (gen, JS) accessor = mkPattern match   where+  -- WARN: if `prop` does not match the `IdentifierName` grammar, this will generate invalid code; see #2513   match (JSAccessor _ prop val) = Just (emit prop, val)   match _ = Nothing @@ -189,7 +170,6 @@ indexer = mkPattern' match   where   match (JSIndexer _ index val) = (,) <$> prettyPrintJS' index <*> pure val-   match _ = mzero  lam :: Pattern PrinterState JS ((Maybe Text, [Text], Maybe SourceSpan), JS)
src/Language/PureScript/Pretty/Kinds.hs view
@@ -10,6 +10,7 @@ import Control.Arrow (ArrowPlus(..)) import Control.PatternArrows as PA +import Data.Monoid ((<>)) import Data.Maybe (fromMaybe) import qualified Data.Text as T import Data.Text (Text)@@ -19,11 +20,15 @@ import Language.PureScript.Names import Language.PureScript.Pretty.Common -typeLiterals :: Pattern () Kind String+typeLiterals :: Pattern () Kind Text typeLiterals = mkPattern match   where-  match (KUnknown u) = Just $ 'u' : show u-  match (NamedKind name) = Just $ T.unpack (showQualified runProperName name)+  match (KUnknown u) =+    Just $ T.cons 'k' (T.pack (show u))+  match (NamedKind name) =+    Just $ if isQualifiedWith (moduleNameFromString "Prim") name+      then runProperName (disqualify name)+      else showQualified runProperName name   match _ = Nothing  matchRow :: Pattern () Kind ((), Kind)@@ -41,15 +46,13 @@ -- | Generate a pretty-printed string representing a Kind prettyPrintKind :: Kind -> Text prettyPrintKind-  -- TODO(Christoph): get rid of T.pack-  = T.pack-  . fromMaybe (internalError "Incomplete pattern")+  = fromMaybe (internalError "Incomplete pattern")   . PA.pattern matchKind ()   where-  matchKind :: Pattern () Kind String-  matchKind = buildPrettyPrinter operators (typeLiterals <+> fmap parens matchKind)+  matchKind :: Pattern () Kind Text+  matchKind = buildPrettyPrinter operators (typeLiterals <+> fmap parensT matchKind) -  operators :: OperatorTable () Kind String+  operators :: OperatorTable () Kind Text   operators =-    OperatorTable [ [ Wrap matchRow $ \_ k -> "# " ++ k]-                  , [ AssocR funKind $ \arg ret -> arg ++ " -> " ++ ret ] ]+    OperatorTable [ [ Wrap matchRow $ \_ k -> "# " <> k]+                  , [ AssocR funKind $ \arg ret -> arg <> " -> " <> ret ] ]
src/Language/PureScript/Pretty/Types.hs view
@@ -10,6 +10,8 @@   , prettyPrintTypeAtom   , prettyPrintRowWith   , prettyPrintRow+  , prettyPrintLabel+  , prettyPrintObjectKey   ) where  import Prelude.Compat@@ -18,6 +20,7 @@ import Control.PatternArrows as PA  import Data.Maybe (fromMaybe)+import Data.Text (Text) import qualified Data.Text as T  import Language.PureScript.Crash@@ -27,6 +30,8 @@ import Language.PureScript.Pretty.Common import Language.PureScript.Pretty.Kinds import Language.PureScript.Types+import Language.PureScript.PSString (PSString, prettyPrintString, decodeString)+import Language.PureScript.Label (Label(..))  import Text.PrettyPrint.Boxes hiding ((<+>)) @@ -45,22 +50,22 @@ prettyPrintRowWith :: Char -> Char -> Type -> Box prettyPrintRowWith open close = uncurry listToBox . toList []   where-  nameAndTypeToPs :: Char -> String -> Type -> Box-  nameAndTypeToPs start name ty = text (start : ' ' : T.unpack (prettyPrintObjectKey (T.pack name)) ++ " :: ") <> typeAsBox ty+  nameAndTypeToPs :: Char -> Label -> Type -> Box+  nameAndTypeToPs start name ty = text (start : ' ' : T.unpack (prettyPrintLabel name) ++ " :: ") <> typeAsBox ty    tailToPs :: Type -> Box   tailToPs REmpty = nullBox   tailToPs other = text "| " <> typeAsBox other -  listToBox :: [(String, Type)] -> Type -> Box+  listToBox :: [(Label, Type)] -> Type -> Box   listToBox [] REmpty = text [open, close]   listToBox [] rest = text [ open, ' ' ] <> tailToPs rest <> text [ ' ', close ]   listToBox ts rest = vcat left $     zipWith (\(nm, ty) i -> nameAndTypeToPs (if i == 0 then open else ',') nm ty) ts [0 :: Int ..] ++     [ tailToPs rest, text [close] ] -  toList :: [(String, Type)] -> Type -> ([(String, Type)], Type)-  toList tys (RCons name ty row) = toList ((T.unpack name, ty):tys) row+  toList :: [(Label, Type)] -> Type -> ([(Label, Type)], Type)+  toList tys (RCons name ty row) = toList ((name, ty):tys) row   toList tys r = (reverse tys, r)  prettyPrintRow :: Type -> String@@ -116,7 +121,7 @@     typeLiterals = mkPattern match where       match TypeWildcard{} = Just $ text "_"       match (TypeVar var) = Just $ text $ T.unpack var-      match (TypeLevelString s) = Just . text $ show s+      match (TypeLevelString s) = Just $ text $ T.unpack $ prettyPrintString s       match (PrettyPrintObject row) = Just $ prettyPrintRowWith '{' '}' row       match (TypeConstructor ctor) = Just $ text $ T.unpack $ runProperName $ disqualify ctor       match (TUnknown u)@@ -186,3 +191,14 @@ -- | Generate a pretty-printed string representing a suggested 'Type' prettyPrintSuggestedType :: Type -> String prettyPrintSuggestedType = render . typeAsBoxImpl True++prettyPrintLabel :: Label -> Text+prettyPrintLabel (Label s) =+  case decodeString s of+    Just s' | not (objectKeyRequiresQuoting s') ->+      s'+    _ ->+      prettyPrintString s++prettyPrintObjectKey :: PSString -> Text+prettyPrintObjectKey = prettyPrintLabel . Label
src/Language/PureScript/Pretty/Values.hs view
@@ -20,8 +20,9 @@ import Language.PureScript.Crash import Language.PureScript.Names import Language.PureScript.Pretty.Common-import Language.PureScript.Pretty.Types (typeAsBox, typeAtomAsBox)+import Language.PureScript.Pretty.Types (typeAsBox, typeAtomAsBox, prettyPrintObjectKey) import Language.PureScript.Types (Constraint(..))+import Language.PureScript.PSString (PSString, prettyPrintString)  import Text.PrettyPrint.Boxes @@ -40,10 +41,10 @@ ellipsis :: Box ellipsis = text "..." -prettyPrintObject :: Int -> [(Text, Maybe Expr)] -> Box+prettyPrintObject :: Int -> [(PSString, Maybe Expr)] -> Box prettyPrintObject d = list '{' '}' prettyPrintObjectProperty   where-  prettyPrintObjectProperty :: (Text, Maybe Expr) -> Box+  prettyPrintObjectProperty :: (PSString, Maybe Expr) -> Box   prettyPrintObjectProperty (key, value) = textT (prettyPrintObjectKey key Monoid.<> ": ") <> maybe (text "_") (prettyPrintValue (d - 1)) value  -- | Pretty-print an expression@@ -55,7 +56,7 @@                             , text "else " <> prettyPrintValueAtom (d - 1) el                             ]) prettyPrintValue d (Accessor prop val) = prettyPrintValueAtom (d - 1) val `before` textT ("." Monoid.<> prettyPrintObjectKey prop)-prettyPrintValue d (ObjectUpdate o ps) = prettyPrintValueAtom (d - 1) o `beforeWithSpace` list '{' '}' (\(key, val) -> textT (key Monoid.<> " = ") <> prettyPrintValue (d - 1) val) ps+prettyPrintValue d (ObjectUpdate o ps) = prettyPrintValueAtom (d - 1) o `beforeWithSpace` list '{' '}' (\(key, val) -> textT (prettyPrintObjectKey key Monoid.<> " = ") <> prettyPrintValue (d - 1) val) ps prettyPrintValue d (App val arg) = prettyPrintValueAtom (d - 1) val `beforeWithSpace` prettyPrintValueAtom (d - 1) arg prettyPrintValue d (Abs (Left arg) val) = text ('\\' : T.unpack (showIdent arg) ++ " -> ") // moveRight 2 (prettyPrintValue (d - 1) val) prettyPrintValue d (Abs (Right arg) val) = text ('\\' : T.unpack (prettyPrintBinder arg) ++ " -> ") // moveRight 2 (prettyPrintValue (d - 1) val)@@ -105,7 +106,7 @@  prettyPrintLiteralValue :: Int -> Literal Expr -> Box prettyPrintLiteralValue _ (NumericLiteral n) = text $ either show show n-prettyPrintLiteralValue _ (StringLiteral s) = text $ show s+prettyPrintLiteralValue _ (StringLiteral s) = text $ T.unpack $ prettyPrintString s prettyPrintLiteralValue _ (CharLiteral c) = text $ show c prettyPrintLiteralValue _ (BooleanLiteral True) = text "true" prettyPrintLiteralValue _ (BooleanLiteral False) = text "false"@@ -169,7 +170,7 @@ prettyPrintBinderAtom (ParensInBinder b) = parensT (prettyPrintBinder b)  prettyPrintLiteralBinder :: Literal Binder -> Text-prettyPrintLiteralBinder (StringLiteral str) = T.pack (show str)+prettyPrintLiteralBinder (StringLiteral str) = prettyPrintString str prettyPrintLiteralBinder (CharLiteral c) = T.pack (show c) prettyPrintLiteralBinder (NumericLiteral num) = either (T.pack . show) (T.pack . show) num prettyPrintLiteralBinder (BooleanLiteral True) = "true"@@ -179,7 +180,7 @@   Monoid.<> T.intercalate ", " (map prettyPrintObjectPropertyBinder bs)   Monoid.<> " }"   where-  prettyPrintObjectPropertyBinder :: (Text, Binder) -> Text+  prettyPrintObjectPropertyBinder :: (PSString, Binder) -> Text   prettyPrintObjectPropertyBinder (key, binder) = prettyPrintObjectKey key Monoid.<> ": " Monoid.<> prettyPrintBinder binder prettyPrintLiteralBinder (ArrayLiteral bs) =   "[ "
src/Language/PureScript/Publish.hs view
@@ -209,7 +209,7 @@       Just Repository{..} -> do         unless (repositoryType == "git")           (Left (BadRepositoryType repositoryType))-        maybe (Left NotOnGithub) Right (extractGithub (T.pack repositoryUrl))+        maybe (Left NotOnGithub) Right (extractGithub repositoryUrl)  checkLicense :: PackageMeta -> PrepareM () checkLicense pkgMeta =@@ -217,7 +217,7 @@     [] ->       userError NoLicenseSpecified     ls ->-      unless (any isValidSPDX ls)+      unless (any (isValidSPDX . T.unpack) ls)         (userError InvalidLicense)  -- |@@ -320,8 +320,7 @@   go =     fmap (fromMaybe []) $       keyMay "dependencies" $-        (++) <$> eachInObjectWithKey (parsePackageName . T.unpack)-                                     asDependencyStatus+        (++) <$> eachInObjectWithKey parsePackageName asDependencyStatus              <*> (concatMap snd <$> eachInObject asResolvedDependencies)  -- | Extracts only the top level dependency names from the output of@@ -330,7 +329,7 @@ asToplevelDependencies =   fmap (map fst) $     key "dependencies" $-      eachInObjectWithKey (parsePackageName . T.unpack) (return ())+      eachInObjectWithKey parsePackageName (return ())  asDependencyStatus :: Parse e DependencyStatus asDependencyStatus = do@@ -371,7 +370,7 @@       ResolvedOther _   -> (ms, pkgName : os, is)       ResolvedVersion v -> (ms, os, (pkgName, v) : is) -  bowerDir pkgName = "bower_components/" ++ runPackageName pkgName+  bowerDir pkgName = T.unpack $ "bower_components/" <> runPackageName pkgName    -- Try to extract a version, and warn if unsuccessful.   tryExtractVersion' :: (PackageName, Text) -> PrepareM (Maybe (PackageName, Version))@@ -406,6 +405,6 @@   let xs = splitOn [pathSeparator] fp   ys <- stripPrefix ["bower_components"] xs   y <- headMay ys-  case Bower.mkPackageName y of+  case Bower.mkPackageName (T.pack y) of     Right name -> Just name     Left _ -> Nothing
src/Language/PureScript/Publish/BoxesHelpers.hs view
@@ -6,6 +6,8 @@  import Prelude.Compat +import Data.Text (Text)+import qualified Data.Text as T import System.IO (hPutStr, stderr)  import qualified Text.PrettyPrint.Boxes as Boxes@@ -36,6 +38,9 @@  bulletedList :: (a -> String) -> [a] -> [Boxes.Box] bulletedList f = map (indented . para . ("* " ++) . f)++bulletedListT :: (a -> Text) -> [a] -> [Boxes.Box]+bulletedListT f = bulletedList (T.unpack . f)  printToStderr :: Boxes.Box -> IO () printToStderr = hPutStr stderr . Boxes.render
src/Language/PureScript/Publish/ErrorsWarnings.hs view
@@ -65,7 +65,7 @@  data RepositoryFieldError   = RepositoryFieldMissing-  | BadRepositoryType String+  | BadRepositoryType Text   | NotOnGithub   deriving (Show) @@ -213,7 +213,7 @@         , "installed:"         ])       ] ++-        bulletedList runPackageName (NonEmpty.toList pkgs)+        bulletedListT runPackageName (NonEmpty.toList pkgs)         ++       [ spacer       , para (concat@@ -263,7 +263,7 @@   BadRepositoryType ty ->     para (concat       [ "In your bower.json file, the repository type is currently listed as "-      , "\"" ++ ty ++ "\". Currently, only git repositories are supported. "+      , "\"" ++ T.unpack ty ++ "\". Currently, only git repositories are supported. "       , "Please publish your code in a git repository, and then update the "       , "repository type in your bower.json file to \"git\"."       ])@@ -361,7 +361,7 @@       ["The following ", packages, " did not appear to have a resolved "       , "version:"])     ] ++-      bulletedList runPackageName (NonEmpty.toList pkgNames)+      bulletedListT runPackageName (NonEmpty.toList pkgNames)       ++     [ spacer     , para (concat@@ -385,7 +385,7 @@       [ "The following Bower ", packages, " ", are, " installed, but not "       , "declared as ", dependencies, " in your bower.json file:"       ])-    : bulletedList runPackageName (NonEmpty.toList pkgNames)+    : bulletedListT runPackageName (NonEmpty.toList pkgNames)  warnUnacceptableVersions :: NonEmpty (PackageName, Text) -> Box warnUnacceptableVersions pkgs =@@ -403,7 +403,7 @@       , "not be parsed:"       ])     ] ++-      bulletedList showTuple (NonEmpty.toList pkgs)+      bulletedListT showTuple (NonEmpty.toList pkgs)       ++     [ spacer     , para (concat@@ -414,7 +414,7 @@       ])     ]   where-  showTuple (pkgName, tag) = runPackageName pkgName ++ "#" ++ T.unpack tag+  showTuple (pkgName, tag) = runPackageName pkgName <> "#" <> tag  warnDirtyWorkingTree :: Box warnDirtyWorkingTree =
src/Language/PureScript/Sugar/Names/Env.hs view
@@ -242,7 +242,12 @@   -> m Exports exportType exportMode exps name dctors mn = do   let exTypes = exportedTypes exps-  let exClasses = exportedTypeClasses exps+      exClasses = exportedTypeClasses exps+      dctorNameCounts :: [(ProperName 'ConstructorName, Int)]+      dctorNameCounts = M.toList $ M.fromListWith (+) (map (,1) dctors)+  forM_ dctorNameCounts $ \(dctorName, count) ->+    when (count > 1) $+      throwDeclConflict (DctorName dctorName) (DctorName dctorName)   case exportMode of     Internal -> do       when (name `M.member` exTypes) $
src/Language/PureScript/Sugar/ObjectWildcards.hs view
@@ -11,11 +11,11 @@  import Data.List (partition) import Data.Maybe (catMaybes)-import Data.Text (Text)  import Language.PureScript.AST import Language.PureScript.Errors import Language.PureScript.Names+import Language.PureScript.PSString (PSString)  desugarObjectConstructors   :: forall m@@ -62,7 +62,7 @@     return $ foldr (Abs . Left) if_ (catMaybes [u', t', f'])   desugarExpr e = return e -  wrapLambda :: ([(Text, Expr)] -> Expr) -> [(Text, Expr)] -> m Expr+  wrapLambda :: ([(PSString, Expr)] -> Expr) -> [(PSString, Expr)] -> m Expr   wrapLambda mkVal ps =     let (args, props) = partition (isAnonymousArgument . snd) ps     in if null args@@ -75,7 +75,7 @@   stripPositionInfo (PositionedValue _ _ e) = stripPositionInfo e   stripPositionInfo e = e -  peelAnonAccessorChain :: Expr -> Maybe [Text]+  peelAnonAccessorChain :: Expr -> Maybe [PSString]   peelAnonAccessorChain (Accessor p e) = (p :) <$> peelAnonAccessorChain e   peelAnonAccessorChain (PositionedValue _ _ e) = peelAnonAccessorChain e   peelAnonAccessorChain AnonymousArgument = Just []@@ -86,7 +86,7 @@   isAnonymousArgument (PositionedValue _ _ e) = isAnonymousArgument e   isAnonymousArgument _ = False -  mkProp :: (Text, Expr) -> m (Maybe Ident, (Text, Expr))+  mkProp :: (PSString, Expr) -> m (Maybe Ident, (PSString, Expr))   mkProp (name, e) = do     arg <- freshIfAnon e     return (arg, (name, maybe e argToExpr arg))
src/Language/PureScript/Sugar/TypeClasses.hs view
@@ -19,6 +19,8 @@ import Language.PureScript.Sugar.CaseDeclarations import Control.Monad.Supply.Class import Language.PureScript.Types+import Language.PureScript.Label (Label(..))+import Language.PureScript.PSString (mkString)  import qualified Language.PureScript.Constants as C @@ -240,7 +242,7 @@         ]       members' = map (first runIdent . memberToNameAndType) members       mtys = members' ++ superclassTypes-  in TypeSynonymDeclaration (coerceProperName name) args (TypeApp tyRecord $ rowFromList (mtys, REmpty))+  in TypeSynonymDeclaration (coerceProperName name) args (TypeApp tyRecord $ rowFromList (map (first (Label . mkString)) mtys, REmpty))  typeClassMemberToDictionaryAccessor   :: ModuleName@@ -297,7 +299,7 @@             , let tyArgs = map (replaceAllTypeVars (zip (map fst typeClassArguments) tys)) suTyArgs             ] -      let props = Literal $ ObjectLiteral (members ++ superclasses)+      let props = Literal $ ObjectLiteral $ map (first mkString) (members ++ superclasses)           dictTy = foldl TypeApp (TypeConstructor (fmap coerceProperName className)) tys           constrainedTy = quantify (if null deps then dictTy else ConstrainedType deps dictTy)           dict = TypeClassDictionaryConstructorApp className props
src/Language/PureScript/Sugar/TypeClasses/Deriving.hs view
@@ -11,9 +11,11 @@ import           Control.Monad.Supply.Class (MonadSupply) import           Data.List (foldl', find, sortBy, unzip5) import qualified Data.Map as M+import           Data.Monoid ((<>)) import           Data.Maybe (fromMaybe, mapMaybe) import           Data.Ord (comparing) import           Data.Text (Text)+import qualified Data.Text as T import           Language.PureScript.AST import qualified Language.PureScript.Constants as C import           Language.PureScript.Crash@@ -22,6 +24,8 @@ import           Language.PureScript.Externs import           Language.PureScript.Kinds import           Language.PureScript.Names+import           Language.PureScript.Label (Label(..))+import           Language.PureScript.PSString (mkString, decodeStringEither) import           Language.PureScript.Types import           Language.PureScript.TypeChecker (checkNewtype) import           Language.PureScript.TypeChecker.Synonyms (SynonymMap, replaceAllTypeSynonymsM)@@ -207,7 +211,7 @@         idents <- replicateM (length tys) freshIdent'         tys' <- mapM (replaceAllTypeSynonymsM syns) tys         let caseResult =-              App (prodConstructor (Literal . StringLiteral . showQualified runProperName $ Qualified (Just mn) ctorName))+              App (prodConstructor (Literal . StringLiteral . mkString . showQualified runProperName $ Qualified (Just mn) ctorName))                 . Literal . ArrayLiteral                 $ zipWith toSpineFun (map (Var . Qualified Nothing) idents) tys'         return $ CaseAlternative [ConstructorBinder (Qualified (Just mn) ctorName) (map VarBinder idents)] (Right caseResult)@@ -216,7 +220,7 @@       toSpineFun i r | Just rec <- objectType r =         lamNull . recordConstructor . Literal . ArrayLiteral           . map-            (\(str,typ) ->+            (\((Label str),typ) ->               Literal $ ObjectLiteral                 [ ("recLabel", Literal (StringLiteral str))                 , ("recValue", toSpineFun (Accessor str i) typ)@@ -235,7 +239,7 @@         App           (App             (Constructor (Qualified (Just dataGeneric) (ProperName "SigProd")))-            (Literal (StringLiteral (showQualified runProperName (Qualified (Just mn) name))))+            (Literal (StringLiteral $ mkString (showQualified runProperName (Qualified (Just mn) name))))           )           . Literal           . ArrayLiteral@@ -249,7 +253,7 @@       mkProdClause :: (ProperName 'ConstructorName, [Type]) -> Expr       mkProdClause (ctorName, tys) =         Literal $ ObjectLiteral-          [ ("sigConstructor", Literal (StringLiteral (showQualified runProperName (Qualified (Just mn) ctorName))))+          [ ("sigConstructor", Literal (StringLiteral $ mkString (showQualified runProperName (Qualified (Just mn) ctorName))))           , ("sigValues", Literal . ArrayLiteral . map (mkProductSignature . instantiate) $ tys)           ] @@ -260,7 +264,7 @@                 [ ("recLabel", Literal (StringLiteral str))                 , ("recValue", mkProductSignature typ)                 ]-            | (str, typ) <- decomposeRec rec+            | ((Label str), typ) <- decomposeRec rec             ]       mkProductSignature typ = lamNull $ App (mkGenVar (Ident C.toSignature))                                (TypedValue False (mkGenVar (Ident "anyProxy")) (proxy typ))@@ -291,7 +295,7 @@         return $           CaseAlternative             [ prodBinder-                [ LiteralBinder (StringLiteral (showQualified runProperName (Qualified (Just mn) ctorName)))+                [ LiteralBinder (StringLiteral $ mkString (showQualified runProperName (Qualified (Just mn) ctorName)))                 , LiteralBinder (ArrayLiteral (map VarBinder idents))                 ]             ]@@ -314,16 +318,16 @@               (App e unitVal)       fromSpineFun e _ = App (mkGenVar (Ident C.fromSpine)) (App e unitVal) -      mkRecCase :: [(Text, Type)] -> CaseAlternative+      mkRecCase :: [(Label, Type)] -> CaseAlternative       mkRecCase rs =         CaseAlternative-          [ recordBinder [ LiteralBinder (ArrayLiteral (map (VarBinder . Ident . fst) rs)) ] ]+          [ recordBinder [ LiteralBinder (ArrayLiteral (map (VarBinder . labelToIdent . fst) rs)) ] ]           . Right-          $ liftApplicative (mkRecFun rs) (map (\(x, y) -> fromSpineFun (Accessor "recValue" (mkVar (Ident x))) y) rs)+          $ liftApplicative (mkRecFun rs) (map (\(x, y) -> fromSpineFun (Accessor "recValue" (mkVar $ labelToIdent x)) y) rs) -      mkRecFun :: [(Text, Type)] -> Expr-      mkRecFun xs = mkJust $ foldr (lam . Ident . fst) recLiteral xs-         where recLiteral = Literal . ObjectLiteral $ map (\(s,_) -> (s, mkVar (Ident s))) xs+      mkRecFun :: [(Label, Type)] -> Expr+      mkRecFun xs = mkJust $ foldr (lam . labelToIdent . fst) recLiteral xs+        where recLiteral = Literal . ObjectLiteral $ map (\(l@(Label s), _) -> (s, mkVar $ labelToIdent l)) xs     mkFromSpineFunction (PositionedDeclaration _ _ d) = mkFromSpineFunction d     mkFromSpineFunction _ = internalError "mkFromSpineFunction: expected DataDeclaration" @@ -405,7 +409,7 @@         args' <- mapM (replaceAllTypeSynonymsM syns) args         (ctorTy, matchProduct, ctorArgs, matchCtor, mkProduct) <- makeProduct args'         return ( TypeApp (TypeApp (TypeConstructor constructor)-                                  (TypeLevelString (runProperName ctorName)))+                                  (TypeLevelString $ mkString (runProperName ctorName)))                          ctorTy                , CaseAlternative [ ConstructorBinder constructor [matchProduct] ]                                  (Right (foldl App (Constructor (Qualified (Just mn) ctorName)) ctorArgs))@@ -430,19 +434,19 @@     makeArg :: Type -> m (Type, Binder, Expr, Binder, Expr)     makeArg arg | Just rec <- objectType arg = do       let fields = decomposeRec rec-      fieldNames <- traverse freshIdent (map fst fields)+      fieldNames <- traverse freshIdent (map (runIdent . labelToIdent . fst) fields)       pure ( TypeApp (TypeConstructor record)                (foldr1 (\f -> TypeApp (TypeApp (TypeConstructor productName) f))-                 (map (\(name, ty) ->+                 (map (\((Label name), ty) ->                    TypeApp (TypeApp (TypeConstructor field) (TypeLevelString name)) ty) fields))            , ConstructorBinder record                [ foldr1 (\b1 b2 -> ConstructorBinder productName [b1, b2])                    (map (\ident -> ConstructorBinder field [VarBinder ident]) fieldNames)                ]            , Literal . ObjectLiteral $-                zipWith (\(name, _) ident -> (name, Var (Qualified Nothing ident))) fields fieldNames+                zipWith (\((Label name), _) ident -> (name, Var (Qualified Nothing ident))) fields fieldNames            , LiteralBinder . ObjectLiteral $-                 zipWith (\(name, _) ident -> (name, VarBinder ident)) fields fieldNames+                 zipWith (\((Label name), _) ident -> (name, VarBinder ident)) fields fieldNames            , record' $                foldr1 (\e1 -> App (App (Constructor productName) e1))                  (map (field' . Var . Qualified Nothing) fieldNames)@@ -574,7 +578,7 @@     toEqTest :: Expr -> Expr -> Type -> Expr     toEqTest l r ty | Just rec <- objectType ty =       conjAll-      . map (\(str, typ) -> toEqTest (Accessor str l) (Accessor str r) typ)+      . map (\((Label str), typ) -> toEqTest (Accessor str l) (Accessor str r) typ)       $ decomposeRec rec     toEqTest l r _ = preludeEq l r @@ -661,7 +665,7 @@     toOrdering :: Expr -> Expr -> Type -> Expr     toOrdering l r ty | Just rec <- objectType ty =       appendAll-      . map (\(str, typ) -> toOrdering (Accessor str l) (Accessor str r) typ)+      . map (\((Label str), typ) -> toOrdering (Accessor str l) (Accessor str r) typ)       $ decomposeRec rec     toOrdering l r _ = ordCompare l r @@ -733,11 +737,22 @@ mkVar :: Ident -> Expr mkVar = mkVarMn Nothing +-- This function may seem a little obtuse, but it's only this way to ensure+-- that it is injective. Injectivity is important here; without it, we can end+-- up with accidental variable shadowing in the generated code.+labelToIdent :: Label -> Ident+labelToIdent =+  Ident . foldMap (either loneSurrogate char) . decodeStringEither . runLabel+  where+  char '_' = "__"+  char c = T.singleton c+  loneSurrogate x = "_" <> T.pack (show x) <> "_"+ objectType :: Type -> Maybe Type objectType (TypeApp (TypeConstructor (Qualified (Just (ModuleName [ProperName "Prim"])) (ProperName "Record"))) rec) = Just rec objectType _ = Nothing -decomposeRec :: Type -> [(Text, Type)]+decomposeRec :: Type -> [(Label, Type)] decomposeRec = sortBy (comparing fst) . go   where go (RCons str typ typs) = (str, typ) : decomposeRec typs         go _ = []@@ -790,17 +805,17 @@           goType recTy | Just row <- objectType recTy =               traverse buildUpdate (decomposeRec row) >>= (traverse buildRecord . justUpdates)             where-              justUpdates :: [Maybe (Text, Expr)] -> Maybe [(Text, Expr)]+              justUpdates :: [Maybe (Label, Expr)] -> Maybe [(Label, Expr)]               justUpdates = foldMap (fmap return) -              buildUpdate :: (Text, Type) -> m (Maybe (Text, Expr))+              buildUpdate :: (Label, Type) -> m (Maybe (Label, Expr))               buildUpdate (lbl, ty) = do upd <- goType ty                                          return ((lbl,) <$> upd) -              buildRecord :: [(Text, Expr)] -> m Expr+              buildRecord :: [(Label, Expr)] -> m Expr               buildRecord updates = do arg <- freshIdent "o"                                        let argVar = mkVar arg-                                           mkAssignment (l, x) = (l, App x (Accessor l argVar))+                                           mkAssignment ((Label l), x) = (l, App x (Accessor l argVar))                                        return (lam arg (ObjectUpdate argVar (mkAssignment <$> updates)))            -- under a `* -> *`, just assume functor for now
src/Language/PureScript/TypeChecker/Entailment.hs view
@@ -37,13 +37,15 @@ import Language.PureScript.TypeChecker.Unify import Language.PureScript.TypeClassDictionaries import Language.PureScript.Types+import Language.PureScript.Label (Label(..))+import Language.PureScript.PSString (PSString, mkString) import qualified Language.PureScript.Constants as C  -- | Describes what sort of dictionary to generate for type class instances data Evidence   = NamedInstance (Qualified Ident)   -- ^ An existing named instance-  | IsSymbolInstance Text+  | IsSymbolInstance PSString   -- ^ Computed instance of the IsSymbol type class for a given Symbol literal   | CompareSymbolInstance   -- ^ Computed instance of CompareSymbol@@ -319,7 +321,7 @@         -- Turn a DictionaryValue into a Expr         subclassDictionaryValue :: Expr -> Qualified (ProperName a) -> Integer -> Expr         subclassDictionaryValue dict superclassName index =-          App (Accessor (C.__superclass_ <> showQualified runProperName superclassName <> "_" <> T.pack (show index))+          App (Accessor (mkString (C.__superclass_ <> showQualified runProperName superclassName <> "_" <> T.pack (show index)))                         dict)               valUndefined @@ -387,7 +389,7 @@         sd1 = [ (name, t1) | (name, t1) <- s1, name `notElem` map fst s2 ]         sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ] -        go :: [(Text, Type)] -> Type -> [(Text, Type)] -> Type -> (Bool, Matching [Type])+        go :: [(Label, Type)] -> Type -> [(Label, Type)] -> Type -> (Bool, Matching [Type])         go l  (KindedType t1 _)  r  t2                 = go l t1 r t2         go l  t1                 r  (KindedType t2 _)  = go l t1 r t2         go [] REmpty             [] REmpty             = (True, M.empty)@@ -429,7 +431,7 @@               sd2 = [ (name, t2) | (name, t2) <- s2, name `notElem` map fst s1 ]           in all (uncurry typesAreEqual) int && go sd1 r1' sd2 r2'         where-          go :: [(Text, Type)] -> Type -> [(Text, Type)] -> Type -> Bool+          go :: [(Label, Type)] -> Type -> [(Label, Type)] -> Type -> Bool           go l  (KindedType t1 _) r  t2                = go l t1 r t2           go l  t1                r  (KindedType t2 _) = go l t1 r t2           go [] (TUnknown u1)     [] (TUnknown u2)     | u1 == u2 = True
src/Language/PureScript/TypeChecker/Kinds.hs view
@@ -229,6 +229,7 @@     unifyKinds k k'     return k'   go TypeWildcard{} = freshKind+  go TUnknown{} = freshKind   go (TypeLevelString _) = return kindSymbol   go (TypeVar v) = do     Just moduleName <- checkCurrentModule <$> get
src/Language/PureScript/TypeChecker/Types.hs view
@@ -34,14 +34,14 @@ import Control.Monad.Writer.Class (MonadWriter(..))  import Data.Bifunctor (bimap)-import Data.Either (lefts, rights)+import Data.Either (partitionEithers) import Data.Functor (($>)) import Data.List (transpose, nub, (\\), partition, delete) import Data.Maybe (fromMaybe) import Data.Monoid ((<>)) import qualified Data.Map as M import qualified Data.Set as S-import Data.Text (Text)+import Data.Traversable (for)  import Language.PureScript.AST import Language.PureScript.Crash@@ -60,7 +60,8 @@ import Language.PureScript.TypeChecker.TypeSearch import Language.PureScript.TypeChecker.Unify import Language.PureScript.Types-+import Language.PureScript.Label (Label(..))+import Language.PureScript.PSString (PSString)  data BindingGroupType   = RecursiveBindingGroup@@ -77,9 +78,9 @@   -> m [(Ident, (Expr, Type))] typesOf bindingGroupType moduleName vals = withFreshSubstitution $ do     tys <- capturingSubstitution tidyUp $ do-      (untyped, typed, dict, untypedDict) <- typeDictionaryForBindingGroup (Just moduleName) vals+      SplitBindingGroup untyped typed dict <- typeDictionaryForBindingGroup (Just moduleName) vals       ds1 <- parU typed $ \e -> withoutWarnings $ checkTypedBindingGroupElement moduleName e dict-      ds2 <- forM untyped $ \e -> withoutWarnings $ typeForBindingGroupElement e dict untypedDict+      ds2 <- forM untyped $ \e -> withoutWarnings $ typeForBindingGroupElement e dict       return (map (False, ) ds1 ++ map (True, ) ds2)      inferred <- forM tys $ \(shouldGeneralize, ((ident, (val, ty)), _)) -> do@@ -165,81 +166,101 @@     isHoleError (ErrorMessage _ HoleInferredType{}) = True     isHoleError _ = False -type TypeData = M.Map (Qualified Ident) (Type, NameKind, NameVisibility)--type UntypedData = [(Ident, Type)]+-- | A binding group contains multiple value definitions, some of which are typed+-- and some which are not.+--+-- This structure breaks down a binding group into typed and untyped parts.+data SplitBindingGroup = SplitBindingGroup+  { _splitBindingGroupUntyped :: [(Ident, (Expr, Type))]+  -- ^ The untyped expressions+  , _splitBindingGroupTyped :: [(Ident, (Expr, Type, Bool))]+  -- ^ The typed expressions, along with their type annotations+  , _splitBindingGroupNames :: M.Map (Qualified Ident) (Type, NameKind, NameVisibility)+  -- ^ A map containing all expressions and their assigned types (which might be+  -- fresh unification variables). These will be added to the 'Environment' after+  -- the binding group is checked, so the value type of the 'Map' is chosen to be+  -- compatible with the type of 'bindNames'.+  } +-- | This function breaks a binding group down into two sets of declarations:+-- those which contain type annotations, and those which don't.+-- This function also generates fresh unification variables for the types of+-- declarations without type annotations, returned in the 'UntypedData' structure. typeDictionaryForBindingGroup-  :: (MonadState CheckState m)+  :: (MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)   => Maybe ModuleName   -> [(Ident, Expr)]-  -> m ([(Ident, Expr)], [(Ident, (Expr, Type, Bool))], TypeData, UntypedData)+  -> m SplitBindingGroup typeDictionaryForBindingGroup moduleName vals = do-  let-    -- Map each declaration to a name/value pair, with an optional type, if the declaration is typed-    es = map isTyped vals-    -- Filter the typed and untyped declarations-    untyped = lefts es-    typed = rights es-    -- Make a map of names to typed declarations-    typedDict = map (\(ident, (_, ty, _)) -> (ident, ty)) typed--  -- Create fresh unification variables for the types of untyped declarations-  untypedNames <- replicateM (length untyped) freshType--  let-    -- Make a map of names to the unification variables of untyped declarations-    untypedDict = zip (map fst untyped) untypedNames-    -- Create the dictionary of all name/type pairs, which will be added to the environment during type checking-    dict = M.fromList (map (\(ident, ty) -> (Qualified moduleName ident, (ty, Private, Undefined))) $ typedDict ++ untypedDict)-  return (untyped, typed, dict, untypedDict)+    -- Filter the typed and untyped declarations and make a map of names to typed declarations.+    -- Replace type wildcards here so that the resulting dictionary of types contains the+    -- fully expanded types.+    let (untyped, typed) = partitionEithers (map splitTypeAnnotation vals)+    (typedDict, typed') <- fmap unzip . for typed $ \(ident, (expr, ty, checkType)) -> do+      ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty+      return ((ident, ty'), (ident, (expr, ty', checkType)))+    -- Create fresh unification variables for the types of untyped declarations+    (untypedDict, untyped') <- fmap unzip . for untyped $ \(ident, expr) -> do+      ty <- freshType+      return ((ident, ty), (ident, (expr, ty)))+    -- Create the dictionary of all name/type pairs, which will be added to the+    -- environment during type checking+    let dict = M.fromList [ (Qualified moduleName ident, (ty, Private, Undefined))+                          | (ident, ty) <- typedDict <> untypedDict+                          ]+    return (SplitBindingGroup untyped' typed' dict)+  where+    -- | Check if a value contains a type annotation, and if so, separate it+    -- from the value itself.+    splitTypeAnnotation :: (Ident, Expr) -> Either (Ident, Expr) (Ident, (Expr, Type, Bool))+    splitTypeAnnotation (name, TypedValue checkType value ty) = Right (name, (value, ty, checkType))+    splitTypeAnnotation (name, PositionedValue pos c value) =+      bimap (second (PositionedValue pos c))+            (second (\(e, t, b) -> (PositionedValue pos c e, t, b)))+            (splitTypeAnnotation (name, value))+    splitTypeAnnotation (name, value) = Left (name, value) +-- | Check the type annotation of a typed value in a binding group. checkTypedBindingGroupElement   :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)   => ModuleName   -> (Ident, (Expr, Type, Bool))-  -> TypeData+  -- ^ The identifier we are trying to define, along with the expression and its type annotation+  -> M.Map (Qualified Ident) (Type, NameKind, NameVisibility)+  -- ^ Names brought into scope in this binding group   -> m (Ident, (Expr, Type))-checkTypedBindingGroupElement mn (ident, (val', ty, checkType)) dict = do-  -- Replace type wildcards-  ty' <- replaceTypeWildcards ty+checkTypedBindingGroupElement mn (ident, (val, ty, checkType)) dict = do   -- Kind check   (kind, args) <- kindOfWithScopedVars ty   checkTypeKind ty kind   -- Check the type with the new names in scope-  ty'' <- introduceSkolemScope <=< replaceAllTypeSynonyms <=< replaceTypeWildcards $ ty'-  val'' <- if checkType-           then withScopedTypeVars mn args $ bindNames dict $ TypedValue True <$> check val' ty'' <*> pure ty''-           else return (TypedValue False val' ty'')-  return (ident, (val'', ty''))+  val' <- if checkType+            then withScopedTypeVars mn args $ bindNames dict $ TypedValue True <$> check val ty <*> pure ty+            else return (TypedValue False val ty)+  return (ident, (val', ty)) +-- | Infer a type for a value in a binding group which lacks an annotation. typeForBindingGroupElement   :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)-  => (Ident, Expr)-  -> TypeData-  -> UntypedData+  => (Ident, (Expr, Type))+  -- ^ The identifier we are trying to define, along with the expression and its assigned type+  -- (at this point, this should be a unification variable)+  -> M.Map (Qualified Ident) (Type, NameKind, NameVisibility)+  -- ^ Names brought into scope in this binding group   -> m (Ident, (Expr, Type))-typeForBindingGroupElement (ident, val) dict untypedDict = do+typeForBindingGroupElement (ident, (val, ty)) dict = do   -- Infer the type with the new names in scope-  TypedValue _ val' ty <- bindNames dict $ infer val-  unifyTypes ty $ fromMaybe (internalError "name not found in dictionary") (lookup ident untypedDict)-  return (ident, (TypedValue True val' ty, ty))---- | Check if a value contains a type annotation-isTyped :: (Ident, Expr) -> Either (Ident, Expr) (Ident, (Expr, Type, Bool))-isTyped (name, TypedValue checkType value ty) = Right (name, (value, ty, checkType))-isTyped (name, PositionedValue pos c value) =-  bimap (second (PositionedValue pos c))-        (second (\(e, t, b) -> (PositionedValue pos c e, t, b)))-        (isTyped (name, value))-isTyped (name, value) = Left (name, value)+  TypedValue _ val' ty' <- bindNames dict $ infer val+  -- Unify the type with the unification variable we chose for this definition+  unifyTypes ty ty'+  return (ident, (TypedValue True val' ty', ty'))  -- | Check the kind of a type, failing if it is not of kind *.-checkTypeKind ::-  (MonadError MultipleErrors m) =>-  Type ->-  Kind ->-  m ()+checkTypeKind+  :: MonadError MultipleErrors m+  => Type+  -> Kind+  -> m () checkTypeKind ty kind = guardWith (errorMessage (ExpectedType ty kind)) $ kind == kindType  -- | Remove any ForAlls and ConstrainedType constructors in a type by introducing new unknowns@@ -247,11 +268,11 @@ -- -- This is necessary during type checking to avoid unifying a polymorphic type with a -- unification variable.-instantiatePolyTypeWithUnknowns ::-  (MonadState CheckState m, MonadError MultipleErrors m) =>-  Expr ->-  Type ->-  m (Expr, Type)+instantiatePolyTypeWithUnknowns+  :: (MonadState CheckState m, MonadError MultipleErrors m)+  => Expr+  -> Type+  -> m (Expr, Type) instantiatePolyTypeWithUnknowns val (ForAll ident ty _) = do   ty' <- replaceVarWithUnknown ident ty   instantiatePolyTypeWithUnknowns val ty'@@ -262,17 +283,17 @@ instantiatePolyTypeWithUnknowns val ty = return (val, ty)  -- | Infer a type for a value, rethrowing any error to provide a more useful error message-infer ::-  (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>-  Expr ->-  m Expr+infer+  :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)+  => Expr+  -> m Expr infer val = withErrorMessageHint (ErrorInferringType val) $ infer' val  -- | Infer a type for a value-infer' ::-  (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>-  Expr ->-  m Expr+infer'+  :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)+  => Expr+  -> m Expr infer' v@(Literal (NumericLiteral (Left _))) = return $ TypedValue True v tyInt infer' v@(Literal (NumericLiteral (Right _))) = return $ TypedValue True v tyNumber infer' v@(Literal (StringLiteral _)) = return $ TypedValue True v tyString@@ -289,22 +310,22 @@ infer' (Literal (ObjectLiteral ps)) = do   ensureNoDuplicateProperties ps   ts <- traverse (infer . snd) ps-  let fields = zipWith (\name (TypedValue _ _ t) -> (name, t)) (map fst ps) ts+  let fields = zipWith (\name (TypedValue _ _ t) -> (Label name, t)) (map fst ps) ts       ty = TypeApp tyRecord $ rowFromList (fields, REmpty)   return $ TypedValue True (Literal (ObjectLiteral (zip (map fst ps) ts))) ty infer' (ObjectUpdate o ps) = do   ensureNoDuplicateProperties ps   row <- freshType   newVals <- zipWith (\(name, _) t -> (name, t)) ps <$> traverse (infer . snd) ps-  let newTys = map (\(name, TypedValue _ _ ty) -> (name, ty)) newVals-  oldTys <- zip (map fst ps) <$> replicateM (length ps) freshType+  let newTys = map (\(name, TypedValue _ _ ty) -> (Label name, ty)) newVals+  oldTys <- zip (map (Label . fst) ps) <$> replicateM (length ps) freshType   let oldTy = TypeApp tyRecord $ rowFromList (oldTys, row)   o' <- TypedValue True <$> check o oldTy <*> pure oldTy   return $ TypedValue True (ObjectUpdate o' newVals) $ TypeApp tyRecord $ rowFromList (newTys, row) infer' (Accessor prop val) = withErrorMessageHint (ErrorCheckingAccessor val prop) $ do   field <- freshType   rest <- freshType-  typed <- check val (TypeApp tyRecord (RCons prop field rest))+  typed <- check val (TypeApp tyRecord (RCons (Label prop) field rest))   return $ TypedValue True (Accessor prop typed) field infer' (Abs (Left arg) ret) = do   ty <- freshType@@ -369,13 +390,13 @@   return $ TypedValue t (PositionedValue pos c v) ty infer' v = internalError $ "Invalid argument to infer: " ++ show v -inferLetBinding ::-  (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>-  [Declaration] ->-  [Declaration] ->-  Expr ->-  (Expr -> m Expr) ->-  m ([Declaration], Expr)+inferLetBinding+  :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)+  => [Declaration]+  -> [Declaration]+  -> Expr+  -> (Expr -> m Expr)+  -> m ([Declaration], Expr) inferLetBinding seen [] ret j = (,) seen <$> withBindingGroupVisible (j ret) inferLetBinding seen (ValueDeclaration ident nameKind [] (Right (tv@(TypedValue checkType val ty))) : rest) ret j = do   Just moduleName <- checkCurrentModule <$> get@@ -393,9 +414,9 @@   bindNames (M.singleton (Qualified Nothing ident) (valTy', nameKind, Defined)) $ inferLetBinding (seen ++ [ValueDeclaration ident nameKind [] (Right val')]) rest ret j inferLetBinding seen (BindingGroupDeclaration ds : rest) ret j = do   Just moduleName <- checkCurrentModule <$> get-  (untyped, typed, dict, untypedDict) <- typeDictionaryForBindingGroup Nothing (map (\(i, _, v) -> (i, v)) ds)+  SplitBindingGroup untyped typed dict <- typeDictionaryForBindingGroup Nothing (map (\(i, _, v) -> (i, v)) ds)   ds1' <- parU typed $ \e -> checkTypedBindingGroupElement moduleName e dict-  ds2' <- forM untyped $ \e -> typeForBindingGroupElement e dict untypedDict+  ds2' <- forM untyped $ \e -> typeForBindingGroupElement e dict   let ds' = [(ident, Private, val') | (ident, (val', _)) <- ds1' ++ ds2']   bindNames dict $ do     makeBindingGroupVisible@@ -406,11 +427,12 @@ inferLetBinding _ _ _ _ = internalError "Invalid argument to inferLetBinding"  -- | Infer the types of variables brought into scope by a binder-inferBinder :: forall m.-  (MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>-  Type ->-  Binder ->-  m (M.Map Ident Type)+inferBinder+  :: forall m+   . (MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)+  => Type+  -> Binder+  -> m (M.Map Ident Type) inferBinder _ NullBinder = return M.empty inferBinder val (LiteralBinder (StringLiteral _)) = unifyTypes val tyString >> return M.empty inferBinder val (LiteralBinder (CharLiteral _)) = unifyTypes val tyChar >> return M.empty@@ -442,12 +464,12 @@   unifyTypes val (TypeApp tyRecord row)   return m1   where-  inferRowProperties :: Type -> Type -> [(Text, Binder)] -> m (M.Map Ident Type)+  inferRowProperties :: Type -> Type -> [(PSString, Binder)] -> m (M.Map Ident Type)   inferRowProperties nrow row [] = unifyTypes nrow row >> return M.empty   inferRowProperties nrow row ((name, binder):binders) = do     propTy <- freshType     m1 <- inferBinder propTy binder-    m2 <- inferRowProperties nrow (RCons name propTy row) binders+    m2 <- inferRowProperties nrow (RCons (Label name) propTy row) binders     return $ m1 `M.union` m2 inferBinder val (LiteralBinder (ArrayLiteral binders)) = do   el <- freshType@@ -485,11 +507,11 @@ binderRequiresMonotype _ = True  -- | Instantiate polytypes only when necessitated by a binder.-instantiateForBinders ::-  (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>-  [Expr] ->-  [CaseAlternative] ->-  m ([Expr], [Type])+instantiateForBinders+  :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)+  => [Expr]+  -> [CaseAlternative]+  -> m ([Expr], [Type]) instantiateForBinders vals cas = unzip <$> zipWithM (\val inst -> do   TypedValue _ val' ty <- infer val   if inst@@ -502,12 +524,12 @@ -- | -- Check the types of the return values in a set of binders in a case statement ---checkBinders ::-  (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>-  [Type] ->-  Type ->-  [CaseAlternative] ->-  m [CaseAlternative]+checkBinders+  :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)+  => [Type]+  -> Type+  -> [CaseAlternative]+  -> m [CaseAlternative] checkBinders _ _ [] = return [] checkBinders nvals ret (CaseAlternative binders result : bs) = do   guardWith (errorMessage $ OverlappingArgNames Nothing) $@@ -531,11 +553,11 @@ -- | -- Check the type of a value, rethrowing errors to provide a better error message ---check ::-  (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>-  Expr ->-  Type ->-  m Expr+check+  :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)+  => Expr+  -> Type+  -> m Expr check val ty = withErrorMessageHint (ErrorCheckingType val ty) $ check' val ty  -- |@@ -641,14 +663,14 @@   -- We need to be careful to avoid duplicate labels here.   -- We check _obj_ against the type _t_ with the types in _ps_ replaced with unknowns.   let (propsToCheck, rest) = rowToList row-      (removedProps, remainingProps) = partition (\(p, _) -> p `elem` map fst ps) propsToCheck+      (removedProps, remainingProps) = partition (\(p, _) -> p `elem` map (Label . fst) ps) propsToCheck   us <- zip (map fst removedProps) <$> replicateM (length ps) freshType   obj' <- check obj (TypeApp tyRecord (rowFromList (us ++ remainingProps, rest)))   ps' <- checkProperties e ps row True   return $ TypedValue True (ObjectUpdate obj' ps') t check' (Accessor prop val) ty = withErrorMessageHint (ErrorCheckingAccessor val prop) $ do   rest <- freshType-  val' <- check val (TypeApp tyRecord (RCons prop ty rest))+  val' <- check val (TypeApp tyRecord (RCons (Label prop) ty rest))   return $ TypedValue True (Accessor prop val') ty check' v@(Constructor c) ty = do   env <- getEnv@@ -678,13 +700,13 @@ -- -- The @lax@ parameter controls whether or not every record member has to be provided. For object updates, this is not the case. ---checkProperties ::-  (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m) =>-  Expr ->-  [(Text, Expr)] ->-  Type ->-  Bool ->-  m [(Text, Expr)]+checkProperties+  :: (MonadSupply m, MonadState CheckState m, MonadError MultipleErrors m, MonadWriter MultipleErrors m)+  => Expr+  -> [(PSString, Expr)]+  -> Type+  -> Bool+  -> m [(PSString, Expr)] checkProperties expr ps row lax = let (ts, r') = rowToList row in go ps ts r' where   go [] [] REmpty = return []   go [] [] u@(TUnknown _)@@ -694,18 +716,18 @@   go [] [] Skolem{} | lax = return []   go [] ((p, _): _) _ | lax = return []                       | otherwise = throwError . errorMessage $ PropertyIsMissing p-  go ((p,_):_) [] REmpty = throwError . errorMessage $ AdditionalProperty p+  go ((p,_):_) [] REmpty = throwError . errorMessage $ AdditionalProperty $ Label p   go ((p,v):ps') ts r =-    case lookup p ts of+    case lookup (Label p) ts of       Nothing -> do         v'@(TypedValue _ _ ty) <- infer v         rest <- freshType-        unifyTypes r (RCons p ty rest)+        unifyTypes r (RCons (Label p) ty rest)         ps'' <- go ps' ts rest         return $ (p, v') : ps''       Just ty -> do         v' <- check v ty-        ps'' <- go ps' (delete (p, ty) ts) r+        ps'' <- go ps' (delete (Label p, ty) ts) r         return $ (p, v') : ps''   go _ _ _ = throwError . errorMessage $ ExprDoesNotHaveType expr (TypeApp tyRecord row) @@ -771,9 +793,9 @@ -- | -- Ensure a set of property names and value does not contain duplicate labels ---ensureNoDuplicateProperties :: (MonadError MultipleErrors m) => [(Text, Expr)] -> m ()+ensureNoDuplicateProperties :: (MonadError MultipleErrors m) => [(PSString, Expr)] -> m () ensureNoDuplicateProperties ps =   let ls = map fst ps in   case ls \\ nub ls of-    l : _ -> throwError . errorMessage $ DuplicateLabel l Nothing+    l : _ -> throwError . errorMessage $ DuplicateLabel (Label l) Nothing     _ -> return ()
src/Language/PureScript/TypeChecker/Unify.hs view
@@ -31,6 +31,7 @@ import Language.PureScript.Errors import Language.PureScript.TypeChecker.Monad import Language.PureScript.TypeChecker.Skolems+import Language.PureScript.Label (Label(..)) import Language.PureScript.Types  -- | Generate a fresh type variable@@ -139,7 +140,7 @@     forM_ int (uncurry unifyTypes)     unifyRows' sd1 r1' sd2 r2'   where-  unifyRows' :: [(Text, Type)] -> Type -> [(Text, Type)] -> Type -> m ()+  unifyRows' :: [(Label, Type)] -> Type -> [(Label, Type)] -> Type -> m ()   unifyRows' [] (TUnknown u) sd r = solveType u (rowFromList (sd, r))   unifyRows' sd r [] (TUnknown u) = solveType u (rowFromList (sd, r))   unifyRows' sd1 (TUnknown u1) sd2 (TUnknown u2) = do
src/Language/PureScript/Types.hs view
@@ -20,6 +20,8 @@ import Language.PureScript.AST.SourcePos import Language.PureScript.Kinds import Language.PureScript.Names+import Language.PureScript.Label (Label)+import Language.PureScript.PSString (PSString)  -- | -- An identifier for the scope of a skolem variable@@ -36,7 +38,7 @@   -- | A named type variable   | TypeVar Text   -- | A type-level string-  | TypeLevelString Text+  | TypeLevelString PSString   -- | A type wildcard, as would appear in a partial type synonym   | TypeWildcard SourceSpan   -- | A type constructor@@ -55,7 +57,7 @@   -- | An empty row   | REmpty   -- | A non-empty row-  | RCons Text Type Type+  | RCons Label Type Type   -- | A type with a kind annotation   | KindedType Type Kind   -- | A placeholder used in pretty printing@@ -108,7 +110,7 @@ -- | -- Convert a row to a list of pairs of labels and types ---rowToList :: Type -> ([(Text, Type)], Type)+rowToList :: Type -> ([(Label, Type)], Type) rowToList (RCons name ty row) = let (tys, rest) = rowToList row                                 in ((name, ty):tys, rest) rowToList r = ([], r)@@ -116,7 +118,7 @@ -- | -- Convert a list of labels and types to a row ---rowFromList :: ([(Text, Type)], Type) -> Type+rowFromList :: ([(Label, Type)], Type) -> Type rowFromList ([], r) = r rowFromList ((name, t):ts, r) = RCons name t (rowFromList (ts, r)) 
stack.yaml view
@@ -1,3 +1,5 @@ resolver: lts-6.25 packages: - '.'+extra-deps:+- bower-json-1.0.0.1
tests/TestPsci.hs view
@@ -120,7 +120,7 @@ getPSCiState = do   cwd <- getCurrentDirectory   let supportDir = cwd </> "tests" </> "support" </> "bower_components"-  let supportFiles ext = Glob.globDir1 (Glob.compile ("purescript-*/**/*." ++ ext)) supportDir+  let supportFiles ext = Glob.globDir1 (Glob.compile ("purescript-*/src/**/*." ++ ext)) supportDir   pursFiles <- supportFiles "purs"    modulesOrFirstError <- loadAllModules pursFiles
tests/TestUtils.hs view
@@ -69,11 +69,15 @@   , "Control.Monad.Eff.Class"   , "Control.Monad.Eff.Console"   , "Control.Monad.Eff.Unsafe"+  , "Control.Monad.Rec.Class"   , "Control.Monad.ST"   , "Control.MonadPlus"   , "Control.MonadZero"   , "Control.Plus"   , "Control.Semigroupoid"+  , "Data.Array"+  , "Data.Array.Partial"+  , "Data.Array.ST"   , "Data.Bifoldable"   , "Data.Bifunctor"   , "Data.Bifunctor.Clown"@@ -86,7 +90,10 @@   , "Data.Boolean"   , "Data.BooleanAlgebra"   , "Data.Bounded"+  , "Data.Char"   , "Data.CommutativeRing"+  , "Data.Either"+  , "Data.Either.Nested"   , "Data.Eq"   , "Data.EuclideanRing"   , "Data.Field"@@ -95,6 +102,7 @@   , "Data.Function.Uncurried"   , "Data.Functor"   , "Data.Functor.Invariant"+  , "Data.Generic"   , "Data.Generic.Rep"   , "Data.Generic.Rep.Eq"   , "Data.Generic.Rep.Monoid"@@ -102,6 +110,7 @@   , "Data.Generic.Rep.Semigroup"   , "Data.Generic.Rep.Show"   , "Data.HeytingAlgebra"+  , "Data.Identity"   , "Data.Maybe"   , "Data.Maybe.First"   , "Data.Maybe.Last"@@ -115,6 +124,7 @@   , "Data.Monoid.Multiplicative"   , "Data.NaturalTransformation"   , "Data.Newtype"+  , "Data.NonEmpty"   , "Data.Ord"   , "Data.Ord.Unsafe"   , "Data.Ordering"@@ -122,15 +132,23 @@   , "Data.Semigroup"   , "Data.Semiring"   , "Data.Show"+  , "Data.String"+  , "Data.String.CaseInsensitive"+  , "Data.String.Regex"+  , "Data.String.Regex.Flags"+  , "Data.String.Regex.Unsafe"+  , "Data.String.Unsafe"   , "Data.Symbol"   , "Data.Traversable"+  , "Data.Tuple"+  , "Data.Tuple.Nested"+  , "Data.Unfoldable"   , "Data.Unit"   , "Data.Void"   , "Partial"   , "Partial.Unsafe"   , "Prelude"   , "Test.Assert"-  , "Test.Main"   , "Type.Data.Ordering"   , "Type.Data.Symbol"   , "Type.Equality"
tests/support/bower.json view
@@ -9,6 +9,7 @@     "purescript-st": "2.0.0",     "purescript-partial": "1.1.2",     "purescript-newtype": "1.1.0",+    "purescript-generics": "3.3.0",     "purescript-generics-rep": "4.0.0",     "purescript-symbols": "^2.0.0",     "purescript-typelevel-prelude": "https://github.com/purescript/purescript-typelevel-prelude.git#29a7123a0c29c85d4b923fcf4a7df8e45ebf9bac",