purescript 0.4.2.1 → 0.4.3
raw patch · 27 files changed
+699/−480 lines, 27 files
Files
- docgen/Main.hs +3/−3
- prelude/prelude.purs +93/−66
- psci/Main.hs +15/−14
- purescript.cabal +2/−1
- src/Data/Generics/Extras.hs +21/−10
- src/Language/PureScript/CodeGen/Externs.hs +1/−1
- src/Language/PureScript/CodeGen/JS.hs +5/−23
- src/Language/PureScript/CodeGen/Optimize.hs +38/−48
- src/Language/PureScript/DeadCodeElimination.hs +7/−6
- src/Language/PureScript/Declarations.hs +20/−2
- src/Language/PureScript/Parser/Declarations.hs +20/−10
- src/Language/PureScript/Parser/Values.hs +5/−5
- src/Language/PureScript/Pretty/Values.hs +3/−2
- src/Language/PureScript/Sugar.hs +7/−3
- src/Language/PureScript/Sugar/BindingGroups.hs +4/−4
- src/Language/PureScript/Sugar/CaseDeclarations.hs +11/−5
- src/Language/PureScript/Sugar/DoNotation.hs +2/−2
- src/Language/PureScript/Sugar/Let.hs +1/−1
- src/Language/PureScript/Sugar/Names.hs +303/−0
- src/Language/PureScript/Sugar/TypeClasses.hs +25/−43
- src/Language/PureScript/TypeChecker.hs +21/−86
- src/Language/PureScript/TypeChecker/Kinds.hs +3/−3
- src/Language/PureScript/TypeChecker/Monad.hs +13/−83
- src/Language/PureScript/TypeChecker/Synonyms.hs +8/−7
- src/Language/PureScript/TypeChecker/Types.hs +21/−30
- src/Language/PureScript/Values.hs +41/−11
- tests/Main.hs +6/−11
docgen/Main.hs view
@@ -102,11 +102,11 @@ renderDeclaration n (P.TypeClassDeclaration name args ds) = do atIndent n $ "class " ++ P.runProperName name ++ " " ++ unwords args ++ " where" mapM_ (renderDeclaration (n + 2)) ds-renderDeclaration n (P.TypeInstanceDeclaration constraints name tys _) = do+renderDeclaration n (P.TypeInstanceDeclaration name constraints className tys _) = do let constraintsText = case constraints of [] -> "" cs -> "(" ++ intercalate "," (map (\(pn, tys') -> show pn ++ " (" ++ unwords (map (("(" ++) . (++ ")") . P.prettyPrintType) tys') ++ ")") cs) ++ ") => "- atIndent n $ constraintsText ++ "instance " ++ show name ++ " " ++ unwords (map (("(" ++) . (++ ")") . P.prettyPrintType) tys)+ atIndent n $ constraintsText ++ "instance " ++ show name ++ " :: " ++ show className ++ " " ++ unwords (map (("(" ++) . (++ ")") . P.prettyPrintType) tys) renderDeclaration _ _ = return () getName :: P.Declaration -> String@@ -116,7 +116,7 @@ getName (P.ExternDataDeclaration name _) = P.runProperName name getName (P.TypeSynonymDeclaration name _ _) = P.runProperName name getName (P.TypeClassDeclaration name _ _) = P.runProperName name-getName (P.TypeInstanceDeclaration _ name _ _) = show name+getName (P.TypeInstanceDeclaration name _ _ _ _) = show name getName _ = error "Invalid argument to getName" isValueDeclaration :: P.Declaration -> Bool
prelude/prelude.purs view
@@ -14,7 +14,7 @@ (<<<) :: forall b c d. a c d -> a b c -> a b d (>>>) :: forall b c d. a b c -> a c d -> a b d - instance Category (->) where+ instance categoryArr :: Category (->) where id x = x (<<<) f g x = f (g x) (>>>) f g x = g (f x)@@ -31,36 +31,36 @@ class Show a where show :: a -> String - instance Show String where+ instance showString :: Show String where show s = s - instance Show Boolean where+ instance showBoolean :: Show Boolean where show true = "true" show false = "false" - foreign import showNumber "function showNumber(n) {\- \ return n.toString();\- \}" :: Number -> String+ foreign import showNumberImpl "function showNumberImpl(n) {\+ \ return n.toString();\+ \}" :: Number -> String - instance Prelude.Show Number where- show = showNumber+ instance showNumber :: Show Number where+ show = showNumberImpl class Read a where read :: String -> a - instance Read String where+ instance readString :: Read String where read s = s - instance Read Boolean where+ instance readBoolean :: Read Boolean where read "true" = true read _ = false - foreign import readNumber "function readNumber(n) {\- \ return parseFloat(n);\- \}" :: String -> Number+ foreign import readNumberImpl "function readNumber(n) {\+ \ return parseFloat(n);\+ \}" :: String -> Number - instance Read Number where- read = readNumber+ instance readNumber :: Read Number where+ read = readNumberImpl infixl 4 <$> @@ -73,7 +73,7 @@ pure :: forall a. a -> f a (<*>) :: forall a b. f (a -> b) -> f a -> f b - instance (Applicative f) => Functor f where+ instance functorFromApplicative :: (Applicative f) => Functor f where (<$>) f a = pure f <*> a infixl 3 <|>@@ -88,7 +88,7 @@ return :: forall a. a -> m a (>>=) :: forall a b. m a -> (a -> m b) -> m b - instance (Monad m) => Applicative m where+ instance applicativeFromMonad :: (Monad m) => Applicative m where pure = return (<*>) f a = do f' <- f@@ -144,7 +144,7 @@ \ return -n;\ \}" :: Number -> Number - instance Num Number where+ instance numNumber :: Num Number where (+) = numAdd (-) = numSub (*) = numMul@@ -159,18 +159,6 @@ (==) :: a -> a -> Boolean (/=) :: a -> a -> Boolean - -- Referential equality- data Ref a = Ref a-- liftRef :: forall a b. (a -> a -> b) -> Ref a -> Ref a -> b- liftRef f (Ref x) (Ref y) = f x y- - refEq :: forall a. Ref a -> Ref a -> Boolean- refEq = liftRef unsafeRefEq- - refIneq :: forall a. Ref a -> Ref a -> Boolean- refIneq = liftRef unsafeRefIneq- foreign import unsafeRefEq "function unsafeRefEq(r1) {\ \ return function(r2) {\ \ return r1 === r2;\@@ -183,23 +171,19 @@ \ };\ \}" :: forall a. a -> a -> Boolean - instance Eq (Ref a) where- (==) = refEq- (/=) = refIneq-- instance Eq String where+ instance eqString :: Eq String where (==) = unsafeRefEq (/=) = unsafeRefIneq - instance Eq Number where+ instance eqNumber :: Eq Number where (==) = unsafeRefEq (/=) = unsafeRefIneq - instance Eq Boolean where+ instance eqBoolean :: Eq Boolean where (==) = unsafeRefEq (/=) = unsafeRefIneq - instance (Eq a) => Eq [a] where+ instance eqArray :: (Eq a) => Eq [a] where (==) [] [] = true (==) (x:xs) (y:ys) = x == y && xs == ys (==) _ _ = false@@ -240,7 +224,7 @@ \ };\ \}" :: Number -> Number -> Boolean - instance Ord Number where+ instance ordNumber :: Ord Number where (<) = numLess (>) = numGreater (<=) = numLessEq@@ -299,7 +283,7 @@ \ return ~n;\ \}" :: Number -> Number - instance Bits Number where+ instance bitsNumber :: Bits Number where (&) = numAnd (|) = numOr (^) = numXor@@ -340,7 +324,7 @@ \ return !b;\ \}" :: Boolean -> Boolean - instance BoolLike Boolean where+ instance boolLikeBoolean :: BoolLike Boolean where (&&) = boolAnd (||) = boolOr not = boolNot@@ -364,11 +348,11 @@ mempty :: m (<>) :: m -> m -> m - instance Monoid String where+ instance monoidString :: Monoid String where mempty = "" (<>) = (++) - instance Monoid [a] where+ instance monoidArray :: Monoid [a] where mempty = [] (<>) = Data.Array.concat @@ -425,6 +409,9 @@ when true m = m when false _ = return {} + zipWithM :: forall m a b c. (Monad m) => (a -> b -> m c) -> [a] -> [b] -> m [c]+ zipWithM f xs ys = sequence $ zipWith f xs ys+ module Data.Maybe where import Prelude@@ -436,22 +423,22 @@ maybe _ f (Just a) = f a fromMaybe :: forall a. a -> Maybe a -> a- fromMaybe a = maybe a (Prelude.id :: forall a. a -> a)+ fromMaybe a = maybe a (id :: forall a. a -> a) - instance Prelude.Monad Maybe where+ instance monadMaybe :: Monad Maybe where return = Just (>>=) m f = maybe Nothing f m - instance Prelude.Applicative Maybe where+ instance applicativeMaybe :: Applicative Maybe where pure = Just (<*>) (Just fn) x = fn <$> x (<*>) Nothing _ = Nothing - instance Prelude.Functor Maybe where+ instance functorMaybe :: Functor Maybe where (<$>) fn (Just x) = Just (fn x) (<$>) _ _ = Nothing - instance (Show a) => Prelude.Show (Maybe a) where+ instance showMaybe :: (Show a) => Show (Maybe a) where show (Just x) = "Just " ++ (show x) show Nothing = "Nothing" @@ -465,20 +452,20 @@ either f _ (Left a) = f a either _ g (Right b) = g b - instance Prelude.Monad (Either e) where+ instance monadEither :: Monad (Either e) where return = Right (>>=) = either (\e _ -> Left e) (\a f -> f a) - instance Prelude.Applicative (Either e) where+ instance applicativeEither :: Applicative (Either e) where pure = Right (<*>) (Left e) _ = Left e (<*>) (Right f) r = f <$> r - instance Prelude.Functor (Either a) where+ instance functorEither :: Functor (Either a) where (<$>) _ (Left x) = Left x (<$>) f (Right y) = Right (f y) - instance (Show a, Show b) => Prelude.Show (Either a b) where+ instance showEither :: (Show a, Show b) => Show (Either a b) where show (Left x) = "Left " ++ (show x) show (Right y) = "Right " ++ (show y) @@ -573,7 +560,7 @@ \ return l1;\ \}" :: forall a. [a] -> [a] - foreign import insertAt + foreign import insertAt "function insertAt(index) {\ \ return function(a) {\ \ return function(l) {\@@ -584,7 +571,7 @@ \ };\ \}":: forall a. Number -> a -> [a] -> [a] - foreign import deleteAt + foreign import deleteAt "function deleteAt(index) {\ \ return function(n) {\ \ return function(l) {\@@ -595,7 +582,7 @@ \ };\ \}":: forall a. Number -> Number -> [a] -> [a] - foreign import updateAt + foreign import updateAt "function updateAt(index) {\ \ return function(a) {\ \ return function(l) {\@@ -622,7 +609,7 @@ filter _ [] = [] filter p (x:xs) | p x = x : filter p xs filter p (_:xs) = filter p xs- + find :: forall a. (a -> Boolean) -> [a] -> Maybe a find _ [] = Nothing find p (x:xs) | p x = Just x@@ -648,20 +635,50 @@ all _ [] = true all p (a:as) = p a && all p as - instance (Prelude.Show a) => Prelude.Show [a] where- show xs = "[" ++ joinWith (map show xs) "," ++ "]"+ drop :: forall a. Number -> [a] -> [a]+ drop 0 xs = xs+ drop _ [] = []+ drop n (x:xs) = drop (n - 1) xs - instance Prelude.Functor [] where- (<$>) = map+ take :: forall a. Number -> [a] -> [a]+ take 0 _ = []+ take _ [] = []+ take n (x:xs) = x : take (n - 1) xs - instance Prelude.Monad [] where+ instance showArray :: (Show a) => Show [a] where+ show xs = "[" ++ joinWith (map show xs) "," ++ "]"++ instance monadArray :: Monad [] where return = singleton (>>=) = concatMap - instance Prelude.Alternative [] where+ instance functorArray :: Functor [] where+ (<$>) = map++ instance alternativeArray :: Alternative [] where empty = [] (<|>) = concat- ++module Data.Eq where++ import Prelude++ -- Referential equality+ data Ref a = Ref a++ liftRef :: forall a b. (a -> a -> b) -> Ref a -> Ref a -> b+ liftRef f (Ref x) (Ref y) = f x y++ refEq :: forall a. Ref a -> Ref a -> Boolean+ refEq = liftRef unsafeRefEq++ refIneq :: forall a. Ref a -> Ref a -> Boolean+ refIneq = liftRef unsafeRefIneq++ instance eqRef :: Eq (Ref a) where+ (==) = refEq+ (/=) = refIneq+ module Data.Array.Unsafe where head :: forall a. [a] -> a@@ -677,7 +694,7 @@ data Tuple a b = Tuple a b - instance (Prelude.Show a, Prelude.Show b) => Prelude.Show (Tuple a b) where+ instance showTuple :: (Show a, Show b) => Show (Tuple a b) where show (Tuple a b) = "Tuple(" ++ show a ++ ", " ++ show b ++ ")" curry :: forall a b c. (Tuple a b -> c) -> a -> b -> c@@ -931,6 +948,8 @@ module Control.Monad.Eff where + import Prelude+ foreign import data Eff :: # ! -> * -> * foreign import retEff "function retEff(a) {\@@ -953,7 +972,7 @@ \ return f();\ \}" :: forall a. Pure a -> a - instance Prelude.Monad (Eff e) where+ instance monadEff :: Monad (Eff e) where return = retEff (>>=) = bindEff @@ -996,7 +1015,15 @@ \ };\ \}" :: forall e a. [a] -> (a -> Eff e {}) -> Eff e {} +module Control.Monad.Eff.Unsafe where + import Control.Monad.Eff++ foreign import unsafeInterleaveEff+ "function unsafeInterleaveEff(f) {\+ \ return f;\+ \}" :: forall eff1 eff2 a. Eff eff1 a -> Eff eff2 a+ module Random where import Control.Monad.Eff@@ -1088,7 +1115,7 @@ \ };\ \}" :: forall r. String -> Eff (trace :: Trace | r) {} - print :: forall a r. (Prelude.Show a) => a -> Eff (trace :: Trace | r) {}+ print :: forall a r. (Show a) => a -> Eff (trace :: Trace | r) {} print o = trace (show o) module Control.Monad.ST where
psci/Main.hs view
@@ -84,7 +84,7 @@ -- Updates the state to have more let bindings. -- updateLets :: (P.Value -> P.Value) -> PSCiState -> PSCiState-updateLets name st = st { psciLetBindings = psciLetBindings st ++ [name] }+updateLets name st = st { psciLetBindings = name : psciLetBindings st } -- File helpers -- |@@ -194,30 +194,32 @@ -- | -- Makes a volatile module to execute the current expression. ---createTemporaryModule :: Bool -> [P.ModuleName] -> [P.Value -> P.Value] -> P.Value -> P.Module-createTemporaryModule exec imports lets value =+createTemporaryModule :: Bool -> PSCiState -> P.Value -> P.Module+createTemporaryModule exec PSCiState{psciImportedModuleNames = imports, psciLetBindings = lets} value = let moduleName = P.ModuleName [P.ProperName "Main"] importDecl m = P.ImportDeclaration m Nothing traceModule = P.ModuleName [P.ProperName "Debug", P.ProperName "Trace"] trace = P.Var (P.Qualified (Just traceModule) (P.Ident "print"))- value' = foldr ($) value lets- itDecl = P.ValueDeclaration (P.Ident "it") [] Nothing value'- mainDecl = P.ValueDeclaration (P.Ident "main") [] Nothing (P.App trace (P.Var (P.Qualified Nothing (P.Ident "it"))))+ itValue = foldl (\x f -> f x) value lets+ mainValue = P.App trace (P.Var (P.Qualified Nothing (P.Ident "it")))+ itDecl = P.ValueDeclaration (P.Ident "it") [] Nothing itValue+ mainDecl = P.ValueDeclaration (P.Ident "main") [] Nothing mainValue+ decls = if exec then [itDecl, mainDecl] else [itDecl] in- P.Module moduleName $ map importDecl imports ++ if exec then [itDecl, mainDecl] else [itDecl]+ P.Module moduleName $ map importDecl imports ++ decls -- | -- Takes a value declaration and evaluates it with the current state. -- handleDeclaration :: P.Value -> PSCiState -> InputT (StateT PSCiState IO) () handleDeclaration value st = do- let m = createTemporaryModule True (psciImportedModuleNames st) (psciLetBindings st) value+ let m = createTemporaryModule True st value case P.compile options (psciLoadedModules st ++ [m]) of Left err -> outputStrLn err Right (js, _, _) -> do process <- lift . lift $ findNodeProcess- result <- lift . lift $ traverse (\node -> readProcessWithExitCode node [] js) process+ result <- lift . lift $ traverse (\node -> readProcessWithExitCode node [] js) process case result of Just (ExitSuccess, out, _) -> outputStrLn out Just (ExitFailure _, _, err) -> outputStrLn err@@ -228,7 +230,7 @@ -- handleTypeOf :: P.Value -> PSCiState -> InputT (StateT PSCiState IO) () handleTypeOf value st = do- let m = createTemporaryModule False (psciImportedModuleNames st) (psciLetBindings st) value+ let m = createTemporaryModule False st value case P.compile options { P.optionsMain = Nothing } (psciLoadedModules st ++ [m]) of Left err -> outputStrLn err Right (_, _, env') ->@@ -257,9 +259,9 @@ -- handleCommand :: Command -> InputT (StateT PSCiState IO) () handleCommand (Expression val) = lift get >>= handleDeclaration val-handleCommand (Let l) = lift $ modify (updateLets l) handleCommand Help = outputStrLn helpMessage handleCommand (Import moduleName) = lift $ modify (updateImports moduleName)+handleCommand (Let l) = lift $ modify (updateLets l) handleCommand (LoadFile filePath) = do absPath <- lift . lift $ expandTilde filePath exists <- lift . lift $ doesFileExist absPath@@ -269,12 +271,11 @@ else outputStrLn $ "Couldn't locate: " ++ filePath handleCommand Reset = do- preludeFilename <- lift . lift $ getPreludeFilename files <- psciImportedFilenames <$> lift get- modulesOrFirstError <- fmap concat . sequence <$> mapM (lift . lift . loadModule) (preludeFilename : files)+ modulesOrFirstError <- fmap concat . sequence <$> mapM (lift . lift . loadModule) files case modulesOrFirstError of Left err -> lift . lift $ putStrLn err >> exitFailure- Right modules -> lift $ put (PSCiState (preludeFilename : files) defaultImports modules [])+ Right modules -> lift $ put (PSCiState files defaultImports modules []) handleCommand (TypeOf val) = lift get >>= handleTypeOf val handleCommand _ = outputStrLn "Unknown command"
purescript.cabal view
@@ -1,5 +1,5 @@ name: purescript-version: 0.4.2.1+version: 0.4.3 cabal-version: >=1.8 build-type: Custom license: MIT@@ -43,6 +43,7 @@ Language.PureScript.Sugar.Operators Language.PureScript.Sugar.TypeClasses Language.PureScript.Sugar.Let+ Language.PureScript.Sugar.Names Language.PureScript.CodeGen Language.PureScript.CodeGen.Common Language.PureScript.CodeGen.Externs
src/Data/Generics/Extras.hs view
@@ -47,17 +47,28 @@ -- > go locals lam@(Lam local _) = (local : locals, lam) -- > go locals other = (locals, other) ---everywhereWithContext' :: (Data d) => s -> (forall d1. (Data d1) => s -> d1 -> (s, d1)) -> d -> d-everywhereWithContext' s0 f x =- let (s, y) = f s0 x in- gmapT (everywhereWithContext' s f) y+everywhereWithContextM' :: (Monad m, Data d) => s -> (forall d1. (Data d1) => s -> d1 -> m (s, d1)) -> d -> m d+everywhereWithContextM' s0 f x = do+ (s, y) <- f s0 x+ gmapM (everywhereWithContextM' s f) y -- | -- Make a stateful transformation function ---mkS :: (Data a, Data b) => (s -> a -> (s, a)) -> s -> b -> (s, b)-mkS f s b = fromMaybe (s, b) $ do- a <- cast b- let (s', a') = f s a- b' <- cast a'- return (s', b')+mkS :: (Monad m, Data a, Data b) => (s -> a -> m (s, a)) -> s -> b -> m (s, b)+mkS = extS (curry return)++-- |+-- Extend a stateful transformation function+--+extS :: (Monad m, Data a, Data b) => (s -> a -> m (s, a)) -> (s -> b -> m (s, b)) -> (s -> a -> m (s, a))+extS f g s a = do+ (s', a') <- f s a+ case cast a' of+ Just b -> do+ (s'', b') <- g s' b+ case cast b' of+ Just a'' -> return (s'', a'')+ Nothing -> return (s', a')+ Nothing -> return (s', a')+
src/Language/PureScript/CodeGen/Externs.hs view
@@ -42,7 +42,7 @@ (ty, _) <- M.lookup (path, name) $ names env return $ "foreign import " ++ show name ++ " :: " ++ prettyPrintType ty declToPs path env (DataDeclaration name _ _) = maybeToList $ do- (kind, _) <- M.lookup (path, name) $ types env+ kind <- M.lookup (Qualified (Just path) name) $ types env return $ "foreign import data " ++ show name ++ " :: " ++ prettyPrintKind kind declToPs _ _ (ExternDataDeclaration name kind) = return $ "foreign import data " ++ show name ++ " :: " ++ prettyPrintKind kind
src/Language/PureScript/CodeGen/JS.hs view
@@ -43,7 +43,6 @@ import Language.PureScript.Types import Language.PureScript.CodeGen.Optimize import Language.PureScript.CodeGen.Common-import Language.PureScript.TypeChecker.Monad (canonicalizeDataConstructor) -- | -- Generate code in the simplified Javascript intermediate representation for all declarations in a@@ -121,10 +120,6 @@ valueToJs opts m e (ArrayLiteral xs) = JSArrayLiteral (map (valueToJs opts m e) xs) valueToJs opts m e (ObjectLiteral ps) = JSObjectLiteral (map (second (valueToJs opts m e)) ps) valueToJs opts m e (ObjectUpdate o ps) = JSApp (JSAccessor "extend" (JSVar "Object")) [ valueToJs opts m e o, JSObjectLiteral (map (second (valueToJs opts m e)) ps)]-valueToJs _ m e (Constructor (Qualified Nothing name)) =- case M.lookup (m, name) (dataConstructors e) of- Just (_, Alias aliasModule aliasIdent) -> qualifiedToJS m id (Qualified (Just aliasModule) aliasIdent)- _ -> JSVar . runProperName $ name valueToJs _ m _ (Constructor name) = qualifiedToJS m (Ident . runProperName) name valueToJs opts m e (Case values binders) = bindersToJs opts m e binders (map (valueToJs opts m e) values) valueToJs opts m e (IfThenElse cond th el) = JSConditional (valueToJs opts m e cond) (valueToJs opts m e th) (valueToJs opts m e el)@@ -194,14 +189,10 @@ where go qual' = case M.lookup (qualify m qual') (names e) of Just (_, ty) | isExtern ty -> var ident- Just (_, Alias aliasModule aliasIdent) -> go (Qualified (Just aliasModule) aliasIdent) _ -> case qual' of Qualified Nothing _ -> var ident _ -> qualifiedToJS m id qual' isExtern (Extern ForeignImport) = True- isExtern (Alias m' ident') = case M.lookup (m', ident') (names e) of- Just (_, ty') -> isExtern ty'- Nothing -> error "Undefined alias in varToJs" isExtern _ = False -- |@@ -216,10 +207,10 @@ -- Generate code in the simplified Javascript intermediate representation for pattern match binders -- and guards. ---bindersToJs :: Options -> ModuleName -> Environment -> [([Binder], Maybe Guard, Value)] -> [JS] -> JS+bindersToJs :: Options -> ModuleName -> Environment -> [CaseAlternative] -> [JS] -> JS bindersToJs opts m e binders vals = runGen (map identToJs (unusedNames (binders, vals))) $ do valNames <- replicateM (length vals) fresh- jss <- forM binders $ \(bs, grd, result) -> go valNames [JSReturn (valueToJs opts m (bindNames m (binderNames bs) e) result)] bs grd+ jss <- forM binders $ \(CaseAlternative bs grd result) -> go valNames [JSReturn (valueToJs opts m (bindNames m (binderNames bs) e) result)] bs grd return $ JSApp (JSFunction Nothing valNames (JSBlock (concat jss ++ [JSThrow (JSStringLiteral "Failed pattern match")]))) vals where@@ -232,15 +223,6 @@ go _ _ _ _ = error "Invalid arguments to bindersToJs" -- |--- Collect all names introduced in binders in an expression----binderNames :: (Data d) => d -> [Ident]-binderNames = everything (++) (mkQ [] go)- where- go (VarBinder ident) = [ident]- go _ = []---- | -- Generate code in the simplified Javascript intermediate representation for a pattern match -- binder. --@@ -262,7 +244,7 @@ then return js else- return [JSIfElse (JSBinary EqualTo (JSAccessor "ctor" (JSVar varName)) (JSStringLiteral (show ((\(mp, nm) -> Qualified (Just mp) nm) $ canonicalizeDataConstructor m e ctor))))+ return [JSIfElse (JSBinary EqualTo (JSAccessor "ctor" (JSVar varName)) (JSStringLiteral (show ctor))) (JSBlock js) Nothing] where@@ -313,10 +295,10 @@ -- isOnlyConstructor :: ModuleName -> Environment -> Qualified ProperName -> Bool isOnlyConstructor m e ctor =- let (ty, _) = fromMaybe (error "Data constructor not found") $ qualify m ctor `M.lookup` dataConstructors e+ let ty = fromMaybe (error "Data constructor not found") $ ctor `M.lookup` dataConstructors e in numConstructors ty == 1 where- numConstructors ty = length $ filter (\(ty1, _) -> ((==) `on` typeConstructor) ty ty1) $ M.elems $ dataConstructors e+ numConstructors ty = length $ filter (((==) `on` typeConstructor) ty) $ M.elems $ dataConstructors e typeConstructor (TypeConstructor qual) = qualify m qual typeConstructor (ForAll _ ty _) = typeConstructor ty typeConstructor (TypeApp (TypeApp t _) ty) | t == tyFunction = typeConstructor ty
src/Language/PureScript/CodeGen/Optimize.hs view
@@ -46,8 +46,6 @@ import Language.PureScript.CodeGen.JS.AST import Language.PureScript.Options import Language.PureScript.CodeGen.Common (identToJs)-import Language.PureScript.Sugar.TypeClasses- (mkDictionaryValueName) import Language.PureScript.Types -- |@@ -316,10 +314,7 @@ prelude = ModuleName [ProperName "Prelude"] effModule = ModuleName [ProperName "Control", ProperName "Monad", ProperName "Eff"] -- The name of the type class dictionary for the Monad Eff instance- Right (Ident effDictName) = mkDictionaryValueName- effModule- (Qualified (Just prelude) (ProperName "Monad"))- [TypeConstructor (Qualified (Just effModule) (ProperName "Eff"))]+ effDictName = "monadEff" -- Check if an expression represents the Monad Eff dictionary isEffDict (JSApp (JSVar ident) [JSObjectLiteral []]) | ident == effDictName = True isEffDict (JSApp (JSAccessor prop (JSAccessor "Control_Monad_Eff" (JSVar "_ps"))) [JSObjectLiteral []]) | prop == effDictName = True@@ -406,67 +401,62 @@ inlineCommonOperators :: JS -> JS inlineCommonOperators = applyAll- [ binary "+" "Num" tyNumber Add- , binary "-" "Num" tyNumber Subtract- , binary "*" "Num" tyNumber Multiply- , binary "/" "Num" tyNumber Divide- , binary "%" "Num" tyNumber Modulus- , unary "negate" "Num" tyNumber Negate+ [ binary "numNumber" "+" "Num" tyNumber Add+ , binary "numNumber" "-" "Num" tyNumber Subtract+ , binary "numNumber" "*" "Num" tyNumber Multiply+ , binary "numNumber" "/" "Num" tyNumber Divide+ , binary "numNumber" "%" "Num" tyNumber Modulus+ , unary "numNumber" "negate" "Num" tyNumber Negate - , binary "<" "Ord" tyNumber LessThan- , binary ">" "Ord" tyNumber GreaterThan- , binary "<=" "Ord" tyNumber LessThanOrEqualTo- , binary ">=" "Ord" tyNumber GreaterThanOrEqualTo+ , binary "ordNumber" "<" "Ord" tyNumber LessThan+ , binary "ordNumber" ">" "Ord" tyNumber GreaterThan+ , binary "ordNumber" "<=" "Ord" tyNumber LessThanOrEqualTo+ , binary "ordNumber" ">=" "Ord" tyNumber GreaterThanOrEqualTo - , binary "==" "Eq" tyNumber EqualTo- , binary "/=" "Eq" tyNumber NotEqualTo- , binary "==" "Eq" tyString EqualTo- , binary "/=" "Eq" tyString NotEqualTo- , binary "==" "Eq" tyBoolean EqualTo- , binary "/=" "Eq" tyBoolean NotEqualTo+ , binary "eqNumber" "==" "Eq" tyNumber EqualTo+ , binary "eqNumber" "/=" "Eq" tyNumber NotEqualTo+ , binary "eqString" "==" "Eq" tyString EqualTo+ , binary "eqString" "/=" "Eq" tyString NotEqualTo+ , binary "eqBoolean" "==" "Eq" tyBoolean EqualTo+ , binary "eqBoolean" "/=" "Eq" tyBoolean NotEqualTo - , binaryFunction "shl" "Bits" tyNumber ShiftLeft- , binaryFunction "shr" "Bits" tyNumber ShiftRight- , binaryFunction "zshr" "Bits" tyNumber ZeroFillShiftRight- , binary "&" "Bits" tyNumber BitwiseAnd- , binary "|" "Bits" tyNumber BitwiseOr- , binary "^" "Bits" tyNumber BitwiseXor- , unary "complement" "Bits" tyNumber BitwiseNot+ , binaryFunction "bitsNumber" "shl" "Bits" tyNumber ShiftLeft+ , binaryFunction "bitsNumber" "shr" "Bits" tyNumber ShiftRight+ , binaryFunction "bitsNumber" "zshr" "Bits" tyNumber ZeroFillShiftRight+ , binary "bitsNumber" "&" "Bits" tyNumber BitwiseAnd+ , binary "bitsNumber" "|" "Bits" tyNumber BitwiseOr+ , binary "bitsNumber" "^" "Bits" tyNumber BitwiseXor+ , unary "bitsNumber" "complement" "Bits" tyNumber BitwiseNot - , binary "&&" "BoolLike" tyBoolean And- , binary "||" "BoolLike" tyBoolean Or- , unary "not" "BoolLike" tyBoolean Not+ , binary "boolLikeBoolean" "&&" "BoolLike" tyBoolean And+ , binary "boolLikeBoolean" "||" "BoolLike" tyBoolean Or+ , unary "boolLikeBoolean" "not" "BoolLike" tyBoolean Not ] where- binary :: String -> String -> Type -> BinaryOperator -> JS -> JS- binary opString className classTy op = everywhere (mkT convert)+ binary :: String -> String -> String -> Type -> BinaryOperator -> JS -> JS+ binary dictName opString className classTy op = everywhere (mkT convert) where convert :: JS -> JS- convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isOp fn && isOpDict className classTy dict = JSBinary op x y+ convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isOp fn && isOpDict dictName className classTy dict = JSBinary op x y convert other = other isOp (JSAccessor longForm (JSAccessor "Prelude" (JSVar _))) | longForm == identToJs (Op opString) = True isOp (JSIndexer (JSStringLiteral op') (JSAccessor "Prelude" (JSVar "_ps"))) | opString == op' = True isOp _ = False- binaryFunction :: String -> String -> Type -> BinaryOperator -> JS -> JS- binaryFunction fnName className classTy op = everywhere (mkT convert)+ binaryFunction :: String -> String -> String -> Type -> BinaryOperator -> JS -> JS+ binaryFunction dictName fnName className classTy op = everywhere (mkT convert) where convert :: JS -> JS- convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isOp fn && isOpDict className classTy dict = JSBinary op x y+ convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isOp fn && isOpDict dictName className classTy dict = JSBinary op x y convert other = other isOp (JSAccessor fnName' (JSAccessor "Prelude" (JSVar "_ps"))) | fnName == fnName' = True isOp _ = False- unary :: String -> String -> Type -> UnaryOperator -> JS -> JS- unary fnName className classTy op = everywhere (mkT convert)+ unary :: String -> String -> String -> Type -> UnaryOperator -> JS -> JS+ unary dictName fnName className classTy op = everywhere (mkT convert) where convert :: JS -> JS- convert (JSApp (JSApp fn [dict]) [x]) | isOp fn && isOpDict className classTy dict = JSUnary op x+ convert (JSApp (JSApp fn [dict]) [x]) | isOp fn && isOpDict dictName className classTy dict = JSUnary op x convert other = other isOp (JSAccessor fnName' (JSAccessor "Prelude" (JSVar "_ps"))) | fnName' == fnName = True isOp _ = False- isOpDict className ty (JSApp (JSAccessor prop (JSAccessor "Prelude" (JSVar "_ps"))) [JSObjectLiteral []]) | prop == dictName = True- where- Right (Ident dictName) = mkDictionaryValueName- (ModuleName [ProperName "Prim"])- (Qualified (Just (ModuleName [ProperName "Prelude"])) (ProperName className))- [ty]- isOpDict _ _ _ = False+ isOpDict dictName className ty (JSApp (JSAccessor prop (JSAccessor "Prelude" (JSVar "_ps"))) [JSObjectLiteral []]) | prop == dictName = True+ isOpDict _ _ _ _ = False
src/Language/PureScript/DeadCodeElimination.hs view
@@ -43,19 +43,20 @@ declarationsByModule env (Module moduleName ds) = concatMap go ds where go :: Declaration -> [(Key, [Key])]- go d@(ValueDeclaration name _ _ _) = [((moduleName, Left name), dependencies env moduleName d)]+ go d@(ValueDeclaration name _ _ _) = [((moduleName, Left name), dependencies moduleName d)] go (DataDeclaration _ _ dctors) = map (\(name, _) -> ((moduleName, Right name), [])) dctors go (ExternDeclaration _ name _ _) = [((moduleName, Left name), [])]- go d@(BindingGroupDeclaration names') = map (\(name, _) -> ((moduleName, Left name), dependencies env moduleName d)) names'+ go d@(BindingGroupDeclaration names') = map (\(name, _) -> ((moduleName, Left name), dependencies moduleName d)) names' go (DataBindingGroupDeclaration ds') = concatMap go ds' go _ = [] -dependencies :: (Data d) => Environment -> ModuleName -> d -> [Key]-dependencies env moduleName = nub . everything (++) (mkQ [] values)+dependencies :: (Data d) => ModuleName -> d -> [Key]+dependencies moduleName = nub . everything (++) (mkQ [] values) where values :: Value -> [Key]- values (Var ident) = let (mn, name) = canonicalize moduleName env ident in [(mn, Left name)]- values (Constructor pn) = let (mn, name) = canonicalizeDataConstructor moduleName env pn in [(mn, Right name)]+ values (Var ident) = let (mn, name) = qualify moduleName ident in [(mn, Left name)]+ values (Constructor (Qualified (Just mn) name)) = [(mn, Right name)]+ values (Constructor (Qualified Nothing _)) = error "Found unqualified data constructor" values _ = [] isUsed :: ModuleName -> Graph -> (Key -> Maybe Vertex) -> [Vertex] -> Declaration -> Bool
src/Language/PureScript/Declarations.hs view
@@ -66,6 +66,24 @@ | TypeClassAccessorImport deriving (Show, Eq, D.Data, D.Typeable) -- |+-- An item in a list of explicit imports+--+data ImportType+ -- |+ -- A type constructor import+ --+ = TypeImport ProperName (Maybe [ProperName])+ -- |+ -- A declaration import+ --+ | NameImport Ident+ -- |+ -- A type class import+ --+ | TypeClassImport ProperName+ deriving (Show, D.Data, D.Typeable)++-- | -- The data type of declarations -- data Declaration@@ -108,7 +126,7 @@ -- | -- A module import (module name, optional set of identifiers to import) --- | ImportDeclaration ModuleName (Maybe [Either Ident ProperName])+ | ImportDeclaration ModuleName (Maybe [ImportType]) -- | -- A type class declaration (name, argument, member declarations) --@@ -116,7 +134,7 @@ -- | -- A type instance declaration (dependencies, class name, instance type, member declarations) --- | TypeInstanceDeclaration [(Qualified ProperName, [Type])] (Qualified ProperName) [Type] [Declaration]+ | TypeInstanceDeclaration Ident [(Qualified ProperName, [Type])] (Qualified ProperName) [Type] [Declaration] deriving (Show, D.Data, D.Typeable) -- |
src/Language/PureScript/Parser/Declarations.hs view
@@ -36,8 +36,9 @@ reserved "data" name <- indented *> properName tyArgs <- many (indented *> identifier)- _ <- lexeme $ indented *> P.char '='- ctors <- sepBy1 ((,) <$> properName <*> P.many (indented *> parseTypeAtom)) pipe+ ctors <- P.option [] $ do+ _ <- lexeme $ indented *> P.char '='+ sepBy1 ((,) <$> properName <*> P.many (indented *> parseTypeAtom)) pipe return $ DataDeclaration name tyArgs ctors parseTypeDeclaration :: P.Parsec String ParseState Declaration@@ -87,31 +88,40 @@ reserved "import" indented moduleName' <- moduleName- idents <- P.optionMaybe $ parens $ commaSep1 (Left <$> parseIdent <|> Right <$> properName)+ idents <- P.optionMaybe $ parens $ commaSep1 parseExplicitImport return $ ImportDeclaration moduleName' idents +parseExplicitImport :: P.Parsec String ParseState ImportType+parseExplicitImport = NameImport <$> parseIdent+ <|> do name <- properName+ dctors <- P.optionMaybe $ parens (Just <$> commaSep1 properName <|> lexeme (P.string "..") *> pure Nothing)+ return $ maybe (TypeClassImport name) (TypeImport name) dctors+ parseTypeClassDeclaration :: P.Parsec String ParseState Declaration parseTypeClassDeclaration = do reserved "class" className <- indented *> properName- idents <- indented *> P.many identifier- indented *> reserved "where"- members <- mark (P.many (same *> parseTypeDeclaration))+ idents <- P.many (indented *> identifier)+ members <- P.option [] . P.try $ do+ indented *> reserved "where"+ mark (P.many (same *> parseTypeDeclaration)) return $ TypeClassDeclaration className idents members parseTypeInstanceDeclaration :: P.Parsec String ParseState Declaration parseTypeInstanceDeclaration = do reserved "instance"+ name <- parseIdent <* lexeme (indented *> P.string "::") deps <- P.optionMaybe $ do deps <- parens (commaSep1 ((,) <$> parseQualified properName <*> P.many parseTypeAtom)) indented reservedOp "=>" return deps className <- indented *> parseQualified properName- ty <- indented *> P.many parseTypeAtom- indented *> reserved "where"- members <- mark (P.many (same *> parseValueDeclaration))- return $ TypeInstanceDeclaration (fromMaybe [] deps) className ty members+ ty <- P.many (indented *> parseTypeAtom)+ members <- P.option [] . P.try $ do+ indented *> reserved "where"+ mark (P.many (same *> parseValueDeclaration))+ return $ TypeInstanceDeclaration name (fromMaybe [] deps) className ty members -- | -- Parse a single declaration
src/Language/PureScript/Parser/Values.hs view
@@ -74,11 +74,11 @@ parseCase = Case <$> P.between (P.try (C.reserved "case")) (C.indented *> C.reserved "of") (return <$> parseValue) <*> (C.indented *> C.mark (P.many (C.same *> C.mark parseCaseAlternative))) -parseCaseAlternative :: P.Parsec String ParseState ([Binder], Maybe Guard, Value)-parseCaseAlternative = (,,) <$> (return <$> parseBinder)- <*> P.optionMaybe parseGuard- <*> (C.indented *> C.reservedOp "->" *> parseValue)- P.<?> "case alternative"+parseCaseAlternative :: P.Parsec String ParseState CaseAlternative+parseCaseAlternative = CaseAlternative <$> (return <$> parseBinder)+ <*> P.optionMaybe parseGuard+ <*> (C.indented *> C.reservedOp "->" *> parseValue)+ P.<?> "case alternative" parseIfThenElse :: P.Parsec String ParseState Value parseIfThenElse = IfThenElse <$> (P.try (C.reserved "if") *> C.indented *> parseValue)
src/Language/PureScript/Pretty/Values.hs view
@@ -45,8 +45,9 @@ match (TypeClassDictionary _ _) = error "Type class dictionary was not replaced" match _ = Nothing -prettyPrintCaseAlternative :: ([Binder], Maybe Guard, Value) -> String-prettyPrintCaseAlternative (binders, grd, val) = "(" ++ intercalate ", " (map prettyPrintBinder binders) ++ ") " +++prettyPrintCaseAlternative :: CaseAlternative -> String+prettyPrintCaseAlternative (CaseAlternative binders grd val) =+ "(" ++ intercalate ", " (map prettyPrintBinder binders) ++ ") " ++ maybe "" (("| " ++) . prettyPrintValue) grd ++ " -> " ++ prettyPrintValue val ifThenElse :: Pattern () Value ((Value, Value), Value)
src/Language/PureScript/Sugar.hs view
@@ -27,6 +27,7 @@ import Language.PureScript.Sugar.BindingGroups as S import Language.PureScript.Sugar.TypeClasses as S import Language.PureScript.Sugar.Let as S+import Language.PureScript.Sugar.Names as S -- | -- The desugaring pipeline proceeds as follows:@@ -45,11 +46,14 @@ -- -- * Group mutually recursive value and data declarations into binding groups. --+-- * Qualify any unqualified names and types+-- desugar :: [Module] -> Either String [Module]-desugar = desugarTypeClasses- >=> rebracket+desugar = rebracket >=> desugarDo+ >=> desugarCasesModule >=> desugarLetBindings- >>> desugarCasesModule+ >>> desugarImports >=> desugarTypeDeclarationsModule+ >=> desugarTypeClasses >=> createBindingGroupsModule
src/Language/PureScript/Sugar/BindingGroups.hs view
@@ -52,7 +52,7 @@ let values = filter isValueDecl ds dataDecls = filter isDataDecl ds allProperNames = map getProperName dataDecls- dataVerts = map (\d -> (d, getProperName d, usedProperNames d `intersect` allProperNames)) dataDecls+ dataVerts = map (\d -> (d, getProperName d, usedProperNames moduleName d `intersect` allProperNames)) dataDecls dataBindingGroupDecls <- mapM toDataBindingGroup $ stronglyConnComp dataVerts let allIdents = map getIdent values valueVerts = map (\d -> (d, getIdent d, usedIdents moduleName d `intersect` allIdents)) values@@ -83,11 +83,11 @@ names (Var (Qualified (Just moduleName') name)) | moduleName == moduleName' = [name] names _ = [] -usedProperNames :: (Data d) => d -> [ProperName]-usedProperNames = nub . everything (++) (mkQ [] names)+usedProperNames :: (Data d) => ModuleName -> d -> [ProperName]+usedProperNames moduleName = nub . everything (++) (mkQ [] names) where names :: Type -> [ProperName]- names (TypeConstructor (Qualified Nothing name)) = [name]+ names (TypeConstructor (Qualified (Just moduleName') name)) | moduleName == moduleName' = [name] names _ = [] getIdent :: Declaration -> Ident
src/Language/PureScript/Sugar/CaseDeclarations.hs view
@@ -22,8 +22,8 @@ import Data.List (groupBy) import Data.Generics (mkT, everywhere) -import Control.Applicative ((<$>))-import Control.Monad (forM, join, unless)+import Control.Applicative+import Control.Monad ((<=<), forM, join, unless) import Control.Monad.Error.Class import Language.PureScript.Names@@ -44,14 +44,20 @@ let ident = head $ unusedNames (binder, val) in- Abs (Left ident) $ Case [Var (Qualified Nothing ident)] [([binder], Nothing, val)]+ Abs (Left ident) $ Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] Nothing val] replace other = other -- | -- Replace all top-level binders with case expressions. -- desugarCases :: [Declaration] -> Either String [Declaration]-desugarCases = fmap join . mapM toDecls . groupBy inSameGroup+desugarCases = desugarRest <=< fmap join . mapM toDecls . groupBy inSameGroup+ where+ desugarRest :: [Declaration] -> Either String [Declaration]+ desugarRest ((TypeInstanceDeclaration name constraints className tys ds) : rest) =+ (:) <$> (TypeInstanceDeclaration name constraints className tys <$> desugarCases ds) <*> desugarRest rest+ desugarRest (d : ds) = (:) d <$> desugarRest ds+ desugarRest [] = pure [] inSameGroup :: Declaration -> Declaration -> Bool inSameGroup (ValueDeclaration ident1 _ _ _) (ValueDeclaration ident2 _ _ _) = ident1 == ident2@@ -76,7 +82,7 @@ argPattern = length . fst . head $ alternatives args = take argPattern $ unusedNames (ident, alternatives) vars = map (Var . Qualified Nothing) args- binders = [ (bs, g, val) | (bs, (g, val)) <- alternatives ]+ binders = [ CaseAlternative bs g val | (bs, (g, val)) <- alternatives ] value = foldr (\arg ret -> Abs (Left arg) ret) (Case vars binders) args in ValueDeclaration ident [] Nothing value
src/Language/PureScript/Sugar/DoNotation.hs view
@@ -55,8 +55,8 @@ go (DoNotationBind binder val : rest) = do rest' <- go rest let ident = head $ unusedNames rest'- return $ App (App bind val) (Abs (Left ident) (Case [Var (Qualified Nothing ident)] [([binder], Nothing, rest')]))+ return $ App (App bind val) (Abs (Left ident) (Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] Nothing rest'])) go [DoNotationLet _ _] = Left "Let statement cannot be the last statement in a do block" go (DoNotationLet binder val : rest) = do rest' <- go rest- return $ Case [val] [([binder], Nothing, rest')]+ return $ Case [val] [CaseAlternative [binder] Nothing rest']
src/Language/PureScript/Sugar/Let.hs view
@@ -28,5 +28,5 @@ desugarLetBindings :: [Module] -> [Module] desugarLetBindings = everywhere (mkT go) where- go (Let binder value result) = Case [value] [([binder], Nothing, result)]+ go (Let binder value result) = Case [value] [CaseAlternative [binder] Nothing result] go other = other
+ src/Language/PureScript/Sugar/Names.hs view
@@ -0,0 +1,303 @@+-----------------------------------------------------------------------------+--+-- Module : Language.PureScript.Sugar.Names+-- Copyright : (c) 2013-14 Phil Freeman, (c) 2014 Gary Burgess, and other contributors+-- License : MIT+--+-- Maintainer : Phil Freeman <paf31@cantab.net>+-- Stability : experimental+-- Portability :+--+-- |+--+-----------------------------------------------------------------------------++module Language.PureScript.Sugar.Names (+ desugarImports+) where++import Data.Maybe (fromMaybe)+import Data.Data+import Data.Generics (extM, mkM, everywhereM)+import Data.Generics.Extras (mkS, extS, everywhereWithContextM')++import Control.Applicative (Applicative(..), (<$>), (<*>))+import Control.Monad (foldM)+import Control.Monad.Error++import qualified Data.Map as M+import qualified Data.Set as S++import Language.PureScript.Declarations+import Language.PureScript.Names+import Language.PureScript.Types+import Language.PureScript.Values++-- |+-- The global export environment - every declaration exported from every module.+--+type ExportEnvironment = M.Map ModuleName Exports++-- |+-- The exported declarations from a module.+--+data Exports = Exports+ -- |+ -- The types exported from each module+ --+ { exportedTypes :: S.Set (ProperName, [ProperName])+ -- |+ -- The classes exported from each module+ --+ , exportedTypeClasses :: S.Set ProperName+ -- |+ -- The values exported from each module+ , exportedValues :: S.Set Ident+ --+ } deriving (Show)++-- |+-- An imported environment for a particular module. This also contains the module's own members.+--+data ImportEnvironment = ImportEnvironment+ -- |+ -- Local names for types within a module mapped to to their qualified names+ --+ { importedTypes :: M.Map ProperName (Qualified ProperName)+ -- |+ -- Local names for data constructors within a module mapped to to their qualified names+ --+ , importedDataConstructors :: M.Map ProperName (Qualified ProperName)+ -- |+ -- Local names for classes within a module mapped to to their qualified names+ --+ , importedTypeClasses :: M.Map ProperName (Qualified ProperName)+ -- |+ -- Local names for values within a module mapped to to their qualified names+ --+ , importedValues :: M.Map Ident (Qualified Ident)+ } deriving (Show)++-- |+-- Updates the exports for a module from the global environment. If the module was not previously+-- present in the global environment, it is created.+--+updateExportedModule :: ExportEnvironment -> ModuleName -> (Exports -> Either String Exports) -> Either String ExportEnvironment+updateExportedModule env mn update = do+ let exports = fromMaybe (error "Module was undefined in updateExportedModule") $ mn `M.lookup` env+ exports' <- update exports+ return $ M.insert mn exports' env++-- |+-- Adds an empty module to an ExportEnvironment.+--+addEmptyModule :: ExportEnvironment -> ModuleName -> ExportEnvironment+addEmptyModule env name = M.insert name (Exports S.empty S.empty S.empty) env++-- |+-- Adds a type belonging to a module to the export environment.+--+addType :: ExportEnvironment -> ModuleName -> ProperName -> [ProperName] -> Either String ExportEnvironment+addType env mn name dctors = updateExportedModule env mn $ \m -> do+ types <- addExport (exportedTypes m) (name, dctors)+ return $ m { exportedTypes = types }++-- |+-- Adds a class to the export environment.+--+addTypeClass :: ExportEnvironment -> ModuleName -> ProperName -> Either String ExportEnvironment+addTypeClass env mn name = updateExportedModule env mn $ \m -> do+ classes <- addExport (exportedTypeClasses m) name+ return $ m { exportedTypeClasses = classes }++-- |+-- Adds a class to the export environment.+--+addValue :: ExportEnvironment -> ModuleName -> Ident -> Either String ExportEnvironment+addValue env mn name = updateExportedModule env mn $ \m -> do+ values <- addExport (exportedValues m) name+ return $ m { exportedValues = values }++-- |+-- Adds an export to a map of exports of that type.+--+addExport :: (Ord s, Show s) => S.Set s -> s -> Either String (S.Set s)+addExport exports name =+ if S.member name exports+ then throwError $ "Multiple definitions for '" ++ show name ++ "'"+ else return $ S.insert name exports++-- |+-- Replaces all local names with qualified names within a set of modules.+--+desugarImports :: [Module] -> Either String [Module]+desugarImports modules = do+ exports <- findExports modules+ mapM (renameInModule' exports) modules+ where+ renameInModule' exports m = rethrowForModule m $ do+ imports <- resolveImports exports m+ renameInModule imports m++-- |+-- Rethrow an error with the name of the current module in the case of a failure+--+rethrowForModule :: Module -> Either String a -> Either String a+rethrowForModule (Module mn _) = flip catchError $ \e -> throwError ("Error in module '" ++ show mn ++ "':\n" ++ e)++-- |+-- Replaces all local names with qualified names within a module.+--+renameInModule :: ImportEnvironment -> Module -> Either String Module+renameInModule imports (Module mn decls) =+ Module mn <$> mapM updateDecl decls >>= everywhereM (mkM updateType `extM` updateValue `extM` updateBinder `extM` updateVars)+ where+ updateDecl (TypeInstanceDeclaration name cs (Qualified Nothing cn) ts ds) =+ TypeInstanceDeclaration name <$> updateConstraints cs <*> updateClassName cn <*> pure ts <*> pure ds+ updateDecl d = return d++ updateVars :: Declaration -> Either String Declaration+ updateVars (ValueDeclaration name [] Nothing val) =+ ValueDeclaration name [] Nothing <$> everywhereWithContextM' [] (mkS bindFunctionArgs `extS` bindBinders) val+ where+ bindFunctionArgs bound (Abs (Left arg) val) = return (arg : bound, Abs (Left arg) val)+ bindFunctionArgs bound (Var (Qualified Nothing ident)) | ident `notElem` bound = (,) bound <$> (Var <$> updateValueName ident)+ bindFunctionArgs bound other = return (bound, other)+ bindBinders :: [Ident] -> CaseAlternative -> Either String ([Ident], CaseAlternative)+ bindBinders bound c@(CaseAlternative bs _ _) = return (binderNames bs ++ bound, c)+ updateVars (ValueDeclaration name _ _ _) = error $ "Binders should have been desugared in " ++ show name+ updateVars other = return other++ updateValue (Constructor (Qualified Nothing nm)) =+ Constructor <$> updateDataConstructorName nm+ updateValue v = return v++ updateBinder (ConstructorBinder (Qualified Nothing nm) b) =+ ConstructorBinder <$> updateDataConstructorName nm <*> pure b+ updateBinder v = return v+ updateType (TypeConstructor (Qualified Nothing nm)) =+ TypeConstructor <$> updateTypeName nm+ updateType (SaturatedTypeSynonym (Qualified Nothing nm) tys) =+ SaturatedTypeSynonym <$> updateTypeName nm <*> mapM updateType tys+ updateType (ConstrainedType cs t) =+ ConstrainedType <$> updateConstraints cs <*> pure t+ updateType t = return t+ updateConstraints = mapM updateConstraint+ updateConstraint (Qualified Nothing nm, ts) = (,) <$> updateClassName nm <*> pure ts+ updateConstraint other = return other+ updateTypeName = update "type" importedTypes+ updateClassName = update "type class" importedTypeClasses+ updateValueName = update "value" importedValues+ updateDataConstructorName = update "data constructor" importedDataConstructors+ update t get nm = maybe (throwError $ "Unknown " ++ t ++ " '" ++ show nm ++ "'") return $ M.lookup nm (get imports)++-- |+-- Finds all exported declarations in a set of modules.+--+findExports :: [Module] -> Either String ExportEnvironment+findExports = foldM addModule M.empty+ where+ addModule env m@(Module mn ds) = rethrowForModule m $ foldM (addDecl mn) (addEmptyModule env mn) ds+ addDecl mn env (TypeClassDeclaration tcn _ ds) = do+ env' <- addTypeClass env mn tcn+ foldM (\env'' (TypeDeclaration name _) -> addValue env'' mn name) env' ds+ addDecl mn env (DataDeclaration tn _ dcs) = addType env mn tn (map fst dcs)+ addDecl mn env (TypeSynonymDeclaration tn _ _) = addType env mn tn []+ addDecl mn env (ExternDataDeclaration tn _) = addType env mn tn []+ addDecl mn env (ValueDeclaration name _ _ _) = addValue env mn name+ addDecl mn env (ExternDeclaration _ name _ _) = addValue env mn name+ addDecl _ env _ = return env++-- |+-- Type representing a set of declarations being explicitly imported from a module+--+type ExplicitImports = [ImportType]++-- |+-- Finds the imports within a module, mapping the imported module name to an optional set of+-- explicitly imported declarations.+--+findImports :: [Declaration] -> M.Map ModuleName (Maybe ExplicitImports)+findImports = foldl findImports' M.empty+ where+ findImports' result (ImportDeclaration mn expl) = M.insert mn expl result+ findImports' result _ = result++-- |+-- Constructs a local environment for a module.+--+resolveImports :: ExportEnvironment -> Module -> Either String ImportEnvironment+resolveImports env (Module currentModule decls) =+ foldM resolveImport' (ImportEnvironment M.empty M.empty M.empty M.empty) (M.toList scope)+ where+ -- A Map from module name to imports from that module, where Nothing indicates everything is to be imported+ scope :: M.Map ModuleName (Maybe ExplicitImports)+ scope = M.insert currentModule Nothing (findImports decls)+ resolveImport' imp (mn, i) = do+ m <- maybe (throwError $ "Cannot import unknown module '" ++ show mn ++ "'") return $ mn `M.lookup` env+ resolveImport currentModule mn m imp i++-- |+-- Extends the local environment for a module by resolving an import of another module.+--+resolveImport :: ModuleName -> ModuleName -> Exports -> ImportEnvironment -> Maybe ExplicitImports -> Either String ImportEnvironment+resolveImport currentModule importModule exp imp i = case i of+ Nothing -> importAll imp+ (Just expl) -> foldM importExplicit imp expl+ where++ -- Import everything from a module+ importAll :: ImportEnvironment -> Either String ImportEnvironment+ importAll imp = do+ imp' <- foldM (\m (name, dctors) -> importExplicit m (TypeImport name (Just dctors))) imp (S.toList $ exportedTypes exp)+ imp'' <- foldM (\m name -> importExplicit m (NameImport name)) imp' (S.toList $ exportedValues exp)+ foldM (\m name -> importExplicit m (TypeClassImport name)) imp'' (S.toList $ exportedTypeClasses exp)++ -- Import something explicitly+ importExplicit :: ImportEnvironment -> ImportType -> Either String ImportEnvironment+ importExplicit imp (NameImport name) = do+ checkImportExists "value" values name+ values' <- updateImports (importedValues imp) name+ return $ imp { importedValues = values' }+ importExplicit imp (TypeImport name dctors) = do+ checkImportExists "type" types name+ types' <- updateImports (importedTypes imp) name+ let allDctors = allExportedDataConstructors name+ dctors' <- maybe (return allDctors) (mapM $ checkDctorExists allDctors) dctors+ dctors'' <- foldM updateImports (importedDataConstructors imp) dctors'+ return $ imp { importedTypes = types', importedDataConstructors = dctors'' }+ importExplicit imp (TypeClassImport name) = do+ checkImportExists "type class" classes name+ typeClasses' <- updateImports (importedTypeClasses imp) name+ return $ imp { importedTypeClasses = typeClasses' }++ -- Find all exported data constructors for a given type+ allExportedDataConstructors :: ProperName -> [ProperName]+ allExportedDataConstructors name = fromMaybe [] $ name `lookup` S.toList (exportedTypes exp)++ -- Add something to the ImportEnvironment if it does not already exist there+ updateImports :: (Ord id, Show id) => M.Map id (Qualified id) -> id -> Either String (M.Map id (Qualified id))+ updateImports m name = case M.lookup name m of+ Nothing -> return $ M.insert name (Qualified (Just importModule) name) m+ Just x@(Qualified (Just mn) _) -> throwError $+ if mn == currentModule || importModule == currentModule+ then "Definition '" ++ show name ++ "' conflicts with import '" ++ show (Qualified (Just importModule) name) ++ "'"+ else "Conflicting imports for '" ++ show name ++ "': '" ++ show x ++ "', '" ++ show (Qualified (Just importModule) name) ++ "'"++ -- The available values, types, and classes in the module being imported+ values = exportedValues exp+ types = fst `S.map` exportedTypes exp+ classes = exportedTypeClasses exp++ -- Ensure that an explicitly imported data constructor exists for the type it is being imported+ -- from+ checkDctorExists :: [ProperName] -> ProperName -> Either String ProperName+ checkDctorExists names = checkImportExists "data constructor" (S.fromList names)++ -- Check that an explicitly imported item exists in the module it is being imported from+ checkImportExists :: (Show a, Ord a, Eq a) => String -> S.Set a -> a -> Either String a+ checkImportExists t exports item =+ if item `S.member` exports+ then return item+ else throwError $ "Unable to find " ++ t ++ " '" ++ show (Qualified (Just importModule) item) ++ "'"+
src/Language/PureScript/Sugar/TypeClasses.hs view
@@ -16,7 +16,6 @@ module Language.PureScript.Sugar.TypeClasses ( desugarTypeClasses,- mkDictionaryValueName, mkDictionaryEntryName ) where @@ -92,11 +91,11 @@ desugarDecl mn d@(TypeClassDeclaration name args members) = do let tys = map memberToNameAndType members modify (M.insert (mn, name) (args, tys))- return $ d : typeClassDictionaryDeclaration name args members : map (typeClassMemberToDictionaryAccessor name args) members-desugarDecl mn d@(TypeInstanceDeclaration deps name ty members) = do+ return $ d : typeClassDictionaryDeclaration name args members : map (typeClassMemberToDictionaryAccessor mn name args) members+desugarDecl mn d@(TypeInstanceDeclaration name deps className ty members) = do desugared <- lift $ desugarCases members- entries <- mapM (typeInstanceDictionaryEntryDeclaration mn deps name ty) desugared- dictDecl <- typeInstanceDictionaryDeclaration mn deps name ty desugared+ entries <- mapM (typeInstanceDictionaryEntryDeclaration name mn deps className ty) desugared+ dictDecl <- typeInstanceDictionaryDeclaration name mn deps className ty desugared return $ d : entries ++ [dictDecl] desugarDecl _ other = return [other] @@ -108,76 +107,59 @@ typeClassDictionaryDeclaration name args members = TypeSynonymDeclaration name args (Object $ rowFromList (map memberToNameAndType members, REmpty)) -typeClassMemberToDictionaryAccessor :: ProperName -> [String] -> Declaration -> Declaration-typeClassMemberToDictionaryAccessor name args (TypeDeclaration ident ty) =+typeClassMemberToDictionaryAccessor :: ModuleName -> ProperName -> [String] -> Declaration -> Declaration+typeClassMemberToDictionaryAccessor mn name args (TypeDeclaration ident ty) = ExternDeclaration TypeClassAccessorImport ident (Just (JSFunction (Just $ identToJs ident) ["dict"] (JSBlock [JSReturn (JSAccessor (identToJs ident) (JSVar "dict"))])))- (quantify (ConstrainedType [(Qualified Nothing name, map TypeVar args)] ty))-typeClassMemberToDictionaryAccessor _ _ _ = error "Invalid declaration in type class definition"+ (quantify (ConstrainedType [(Qualified (Just mn) name, map TypeVar args)] ty))+typeClassMemberToDictionaryAccessor _ _ _ _ = error "Invalid declaration in type class definition" -typeInstanceDictionaryDeclaration :: ModuleName -> [(Qualified ProperName, [Type])] -> Qualified ProperName -> [Type] -> [Declaration] -> Desugar Declaration-typeInstanceDictionaryDeclaration mn deps name tys decls = do+typeInstanceDictionaryDeclaration :: Ident -> ModuleName -> [(Qualified ProperName, [Type])] -> Qualified ProperName -> [Type] -> [Declaration] -> Desugar Declaration+typeInstanceDictionaryDeclaration name mn deps className tys decls = do m <- get- (args, instanceTys) <- lift $ maybe (Left $ "Type class " ++ show name ++ " is undefined. Type class names must be qualified.") Right- $ M.lookup (qualify mn name) m+ (args, instanceTys) <- lift $ maybe (Left $ "Type class " ++ show className ++ " is undefined. Type class names must be qualified.") Right+ $ M.lookup (qualify mn className) m let memberTypes = map (second (replaceAllTypeVars (zip args tys))) instanceTys- entryName <- lift $ mkDictionaryValueName mn name tys+ let entryName = Escaped (show name) memberNames <- mapM (memberToNameAndValue memberTypes) decls return $ ValueDeclaration entryName [] Nothing (TypedValue True (foldr (Abs . (\n -> Left . Ident $ '_' : show n)) (ObjectLiteral memberNames) [1..max 1 (length deps)]) (quantify (if null deps then- function unit (foldl TypeApp (TypeConstructor name) tys)+ function unit (foldl TypeApp (TypeConstructor className) tys) else- foldr (function . (\(pn, tys') -> foldl TypeApp (TypeConstructor pn) tys')) (foldl TypeApp (TypeConstructor name) tys) deps))+ foldr (function . (\(pn, tys') -> foldl TypeApp (TypeConstructor pn) tys')) (foldl TypeApp (TypeConstructor className) tys) deps)) ) where memberToNameAndValue :: [(String, Type)] -> Declaration -> Desugar (String, Value) memberToNameAndValue tys' (ValueDeclaration ident _ _ _) = do memberType <- lift . maybe (Left "Type class member type not found") Right $ lookup (identToJs ident) tys'- memberName <- mkDictionaryEntryName mn name tys ident+ memberName <- mkDictionaryEntryName name ident return (identToJs ident, TypedValue False (foldl App (Var (Qualified Nothing memberName)) (map (\n -> Var (Qualified Nothing (Ident ('_' : show n)))) [1..length deps])) (quantify memberType)) memberToNameAndValue _ _ = error "Invalid declaration in type instance definition" -typeInstanceDictionaryEntryDeclaration :: ModuleName -> [(Qualified ProperName, [Type])] -> Qualified ProperName -> [Type] -> Declaration -> Desugar Declaration-typeInstanceDictionaryEntryDeclaration mn deps name tys (ValueDeclaration ident [] _ val) = do+typeInstanceDictionaryEntryDeclaration :: Ident -> ModuleName -> [(Qualified ProperName, [Type])] -> Qualified ProperName -> [Type] -> Declaration -> Desugar Declaration+typeInstanceDictionaryEntryDeclaration name mn deps className tys (ValueDeclaration ident [] _ val) = do m <- get valTy <- lift $ do (args, members) <- lookupTypeClass m ty' <- lookupIdent members return $ replaceAllTypeVars (zip args tys) ty'- entryName <- mkDictionaryEntryName mn name tys ident+ entryName <- mkDictionaryEntryName name ident return $ ValueDeclaration entryName [] Nothing (TypedValue True val (quantify (if null deps then valTy else ConstrainedType deps valTy))) where- lookupTypeClass m = maybe (Left $ "Type class " ++ show name ++ " is undefined. Type class names must be qualified.") Right $ M.lookup (qualify mn name) m- lookupIdent members = maybe (Left $ "Type class " ++ show name ++ " does not have method " ++ show ident) Right $ lookup (identToJs ident) members-typeInstanceDictionaryEntryDeclaration _ _ _ _ _ = error "Invalid declaration in type instance definition"+ lookupTypeClass m = maybe (Left $ "Type class " ++ show className ++ " is undefined. Type class names must be qualified.") Right $ M.lookup (qualify mn className) m+ lookupIdent members = maybe (Left $ "Type class " ++ show className ++ " does not have method " ++ show ident) Right $ lookup (identToJs ident) members+typeInstanceDictionaryEntryDeclaration _ _ _ _ _ _ = error "Invalid declaration in type instance definition" qualifiedToString :: ModuleName -> Qualified ProperName -> String-qualifiedToString mn (Qualified Nothing pn) = qualifiedToString mn (Qualified (Just mn) pn)-qualifiedToString _ (Qualified (Just mn) pn) = moduleNameToJs mn ++ "_" ++ runProperName pn---- |--- Generate a name for a type class dictionary, based on the module name, class name and type name----mkDictionaryValueName :: ModuleName -> Qualified ProperName -> [Type] -> Either String Ident-mkDictionaryValueName mn cl tys = do- tyStr <- mapM (typeToString mn) tys- return $ Ident $ "__" ++ qualifiedToString mn cl ++ "_" ++ intercalate "_" tyStr--typeToString :: ModuleName -> Type -> Either String String-typeToString _ (TypeVar _) = return "var"-typeToString mn (TypeConstructor ty') = return $ qualifiedToString mn ty'-typeToString mn (TypeApp ty' (TypeVar _)) = typeToString mn ty'-typeToString _ _ = Left "Type class instance must be of the form T a1 ... an"+qualifiedToString mn (Qualified _ pn) = moduleNameToJs mn ++ "_" ++ runProperName pn -- | -- Generate a name for a type class dictionary member, based on the module name, class name, type name and -- member name ---mkDictionaryEntryName :: ModuleName -> Qualified ProperName -> [Type] -> Ident -> Desugar Ident-mkDictionaryEntryName mn name tys ident = do- Ident dictName <- lift $ mkDictionaryValueName mn name tys- return $ Escaped $ dictName ++ "_" ++ identToJs ident+mkDictionaryEntryName :: Ident -> Ident -> Desugar Ident+mkDictionaryEntryName dictName ident = return $ Escaped $ show dictName ++ "_" ++ identToJs ident
src/Language/PureScript/TypeChecker.hs view
@@ -41,7 +41,7 @@ addDataType :: ModuleName -> ProperName -> [String] -> [(ProperName, [Type])] -> Kind -> Check () addDataType moduleName name args dctors ctorKind = do env <- getEnv- putEnv $ env { types = M.insert (moduleName, name) (ctorKind, Data) (types env) }+ putEnv $ env { types = M.insert (Qualified (Just moduleName) name) ctorKind (types env) } forM_ dctors $ \(dctor, tys) -> rethrow (("Error in data constructor " ++ show dctor ++ ":\n") ++) $ addDataConstructor moduleName name args dctor tys@@ -49,29 +49,16 @@ addDataConstructor :: ModuleName -> ProperName -> [String] -> ProperName -> [Type] -> Check () addDataConstructor moduleName name args dctor tys = do env <- getEnv- dataConstructorIsNotDefined moduleName dctor let retTy = foldl TypeApp (TypeConstructor (Qualified (Just moduleName) name)) (map TypeVar args) let dctorTy = foldr function retTy tys let polyType = mkForAll args dctorTy- putEnv $ env { dataConstructors = M.insert (moduleName, dctor) (qualifyAllUnqualifiedNames moduleName env polyType, DataConstructor) (dataConstructors env) }+ putEnv $ env { dataConstructors = M.insert (Qualified (Just moduleName) dctor) polyType (dataConstructors env) } addTypeSynonym :: ModuleName -> ProperName -> [String] -> Type -> Kind -> Check () addTypeSynonym moduleName name args ty kind = do env <- getEnv- putEnv $ env { types = M.insert (moduleName, name) (kind, TypeSynonym) (types env)- , typeSynonyms = M.insert (moduleName, name) (args, qualifyAllUnqualifiedNames moduleName env ty) (typeSynonyms env) }--typeIsNotDefined :: ModuleName -> ProperName -> Check ()-typeIsNotDefined moduleName name = do- env <- getEnv- guardWith (show name ++ " is already defined") $- not $ M.member (moduleName, name) (types env)--dataConstructorIsNotDefined :: ModuleName -> ProperName -> Check ()-dataConstructorIsNotDefined moduleName dctor = do- env <- getEnv- guardWith (show dctor ++ " is already defined") $- not $ M.member (moduleName, dctor) (dataConstructors env)+ putEnv $ env { types = M.insert (Qualified (Just moduleName) name) kind (types env)+ , typeSynonyms = M.insert (Qualified (Just moduleName) name) (args, ty) (typeSynonyms env) } valueIsNotDefined :: ModuleName -> Ident -> Check () valueIsNotDefined moduleName name = do@@ -83,7 +70,7 @@ addValue :: ModuleName -> Ident -> Type -> Check () addValue moduleName name ty = do env <- getEnv- putEnv (env { names = M.insert (moduleName, name) (qualifyAllUnqualifiedNames moduleName env ty, Value) (names env) })+ putEnv (env { names = M.insert (moduleName, name) (ty, Value) (names env) }) addTypeClassDictionaries :: [TypeClassDictionaryInScope] -> Check () addTypeClassDictionaries entries =@@ -93,7 +80,7 @@ checkTypeClassInstance _ (TypeVar _) = return () checkTypeClassInstance m (TypeConstructor ctor) = do env <- getEnv- when (canonicalizeType m env ctor `M.member` typeSynonyms env) $ throwError "Type synonym instances are disallowed"+ when (ctor `M.member` typeSynonyms env) $ throwError "Type synonym instances are disallowed" return () checkTypeClassInstance m (TypeApp ty (TypeVar _)) = checkTypeClassInstance m ty checkTypeClassInstance _ _ = throwError "Type class instance must be of the form T a1 ... an"@@ -115,7 +102,6 @@ typeCheckAll _ _ [] = return [] typeCheckAll mainModuleName moduleName (d@(DataDeclaration name args dctors) : rest) = do rethrow (("Error in type constructor " ++ show name ++ ":\n") ++) $ do- typeIsNotDefined moduleName name ctorKind <- kindsOf moduleName name args (concatMap snd dctors) addDataType moduleName name args dctors ctorKind ds <- typeCheckAll mainModuleName moduleName rest@@ -125,11 +111,9 @@ let syns = mapMaybe toTypeSynonym tys let dataDecls = mapMaybe toDataDecl tys (syn_ks, data_ks) <- kindsOfAll moduleName syns (map (\(name, args, dctors) -> (name, args, concatMap snd dctors)) dataDecls)- forM_ (zip dataDecls data_ks) $ \((name, args, dctors), ctorKind) -> do- typeIsNotDefined moduleName name+ forM_ (zip dataDecls data_ks) $ \((name, args, dctors), ctorKind) -> addDataType moduleName name args dctors ctorKind- forM_ (zip syns syn_ks) $ \((name, args, ty), kind) -> do- typeIsNotDefined moduleName name+ forM_ (zip syns syn_ks) $ \((name, args, ty), kind) -> addTypeSynonym moduleName name args ty kind ds <- typeCheckAll mainModuleName moduleName rest return $ d : ds@@ -140,7 +124,6 @@ toDataDecl _ = Nothing typeCheckAll mainModuleName moduleName (d@(TypeSynonymDeclaration name args ty) : rest) = do rethrow (("Error in type synonym " ++ show name ++ ":\n") ++) $ do- typeIsNotDefined moduleName name kind <- kindsOf moduleName name args [ty] addTypeSynonym moduleName name args ty kind ds <- typeCheckAll mainModuleName moduleName rest@@ -168,8 +151,7 @@ return $ d : ds typeCheckAll mainModuleName moduleName (d@(ExternDataDeclaration name kind) : rest) = do env <- getEnv- guardWith (show name ++ " is already defined") $ not $ M.member (moduleName, name) (types env)- putEnv $ env { types = M.insert (moduleName, name) (kind, TypeSynonym) (types env) }+ putEnv $ env { types = M.insert (Qualified (Just moduleName) name) kind (types env) } ds <- typeCheckAll mainModuleName moduleName rest return $ d : ds typeCheckAll mainModuleName moduleName (d@(ExternDeclaration importTy name _ ty) : rest) = do@@ -179,7 +161,7 @@ guardWith "Expected kind *" $ kind == Star case M.lookup (moduleName, name) (names env) of Just _ -> throwError $ show name ++ " is already defined"- Nothing -> putEnv (env { names = M.insert (moduleName, name) (qualifyAllUnqualifiedNames moduleName env ty, Extern importTy) (names env) })+ Nothing -> putEnv (env { names = M.insert (moduleName, name) (ty, Extern importTy) (names env) }) ds <- typeCheckAll mainModuleName moduleName rest return $ d : ds typeCheckAll mainModuleName moduleName (d@(FixityDeclaration _ name) : rest) = do@@ -189,70 +171,23 @@ return $ d : ds typeCheckAll mainModuleName currentModule (d@(ImportDeclaration moduleName idents) : rest) = do env <- getEnv- rethrow errorMessage $ do- guardWith ("Module " ++ show moduleName ++ " does not exist") $ moduleExists env- case idents of- Nothing -> do- shadowIdents (map snd $ filterModule (names env)) env- shadowTypes (map snd $ filterModule (types env)) env- Just idents' -> do- shadowIdents (lefts idents') env- shadowTypes (rights idents') env- shadowTypeClassInstances env+ let instances = filter (\tcd ->+ let Qualified (Just mn) _ = tcdName tcd in+ moduleName == mn && tcdType tcd == TCDRegular+ ) (typeClassDictionaries env)+ forM_ instances $ \tcd -> do+ let (Qualified _ ident) = tcdName tcd+ addTypeClassDictionaries [tcd { tcdName = Qualified (Just currentModule) ident, tcdType = TCDAlias (tcdName tcd) }] ds <- typeCheckAll mainModuleName currentModule rest return $ d : ds- where- errorMessage = (("Error in import declaration " ++ show moduleName ++ ":\n") ++)- filterModule = filter ((== moduleName) . fst) . M.keys- moduleExists env = not (null (filterModule (names env))) || not (null (filterModule (types env)))- shadowIdents idents' env =- forM_ idents' $ \ident ->- case (moduleName, ident) `M.lookup` names env of- Just (_, Alias _ _) -> return ()- Just (pt, _) -> do- guardWith (show currentModule ++ "." ++ show ident ++ " is already defined") $ (currentModule, ident) `M.notMember` names env- modifyEnv (\e -> e { names = M.insert (currentModule, ident) (pt, Alias moduleName ident) (names e) })- Nothing -> throwError (show moduleName ++ "." ++ show ident ++ " is undefined")- shadowTypes pns env =- forM_ pns $ \pn ->- case (moduleName, pn) `M.lookup` types env of- Nothing -> throwError (show moduleName ++ "." ++ show pn ++ " is undefined")- Just (_, DataAlias _ _) -> return ()- Just (k, _) -> do- guardWith (show currentModule ++ "." ++ show pn ++ " is already defined") $ (currentModule, pn) `M.notMember` types env- modifyEnv (\e -> e { types = M.insert (currentModule, pn) (k, DataAlias moduleName pn) (types e) })- let keys = map (snd . fst) . filter (\(_, (fn, _)) -> fn `constructs` pn) . M.toList . dataConstructors $ env- forM_ keys $ \dctor ->- case (moduleName, dctor) `M.lookup` dataConstructors env of- Just (_, Alias _ _) -> return ()- Just (ctorTy, _) -> do- guardWith (show currentModule ++ "." ++ show dctor ++ " is already defined") $ (currentModule, dctor) `M.notMember` dataConstructors env- modifyEnv (\e -> e { dataConstructors = M.insert (currentModule, dctor) (ctorTy, Alias moduleName (Ident (runProperName dctor))) (dataConstructors e) })- Nothing -> throwError (show moduleName ++ "." ++ show dctor ++ " is undefined")- shadowTypeClassInstances env = do- let instances = filter (\tcd ->- let Qualified (Just mn) _ = tcdName tcd in- moduleName == mn && tcdType tcd == TCDRegular- ) (typeClassDictionaries env)- forM_ instances $ \tcd -> do- let (Qualified _ ident) = tcdName tcd- addTypeClassDictionaries [tcd { tcdName = Qualified (Just currentModule) ident, tcdType = TCDAlias (tcdName tcd) }]- constructs (TypeConstructor (Qualified (Just mn) pn')) pn- = mn == moduleName && pn' == pn- constructs (ForAll _ ty _) pn = ty `constructs` pn- constructs (TypeApp (TypeApp t _) ty) pn | t == tyFunction = ty `constructs` pn- constructs (TypeApp ty _) pn = ty `constructs` pn- constructs fn _ = error $ "Invalid arguments to constructs: " ++ show fn typeCheckAll mainModuleName moduleName (d@TypeClassDeclaration{} : rest) = do env <- getEnv ds <- typeCheckAll mainModuleName moduleName rest- return $ qualifyAllUnqualifiedNames moduleName env d : ds-typeCheckAll mainModuleName moduleName (d@(TypeInstanceDeclaration deps className tys _) : rest) = do+ return $ d : ds+typeCheckAll mainModuleName moduleName (d@(TypeInstanceDeclaration dictName deps className tys _) : rest) = do env <- getEnv- dictName <- Check . lift $ mkDictionaryValueName moduleName className tys mapM_ (checkTypeClassInstance moduleName) tys forM_ deps $ mapM_ (checkTypeClassInstance moduleName) . snd- addTypeClassDictionaries (qualifyAllUnqualifiedNames moduleName env- [TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) className tys (Just deps) TCDRegular])+ addTypeClassDictionaries [TypeClassDictionaryInScope (Qualified (Just moduleName) dictName) className tys (Just deps) TCDRegular] ds <- typeCheckAll mainModuleName moduleName rest- return $ qualifyAllUnqualifiedNames moduleName env d : ds+ return $ d : ds
src/Language/PureScript/TypeChecker/Kinds.hs view
@@ -133,9 +133,9 @@ infer (TypeConstructor v) = do env <- liftCheck getEnv Just moduleName <- checkCurrentModule <$> get- case M.lookup (qualify moduleName v) (types env) of- Nothing -> UnifyT . lift . throwError $ "Unknown type constructor '" ++ show v ++ "'"- Just (kind, _) -> return kind+ case M.lookup v (types env) of+ Nothing -> UnifyT . lift . throwError $ "Unknown type constructor '" ++ show v ++ "'" ++ show (M.keys (types env))+ Just kind -> return kind infer (TypeApp t1 t2) = do k0 <- fresh k1 <- infer t1
src/Language/PureScript/TypeChecker/Monad.hs view
@@ -49,10 +49,6 @@ -- | Extern ForeignImportType -- |- -- An alias for a value in another module, introduced using an import declaration- --- | Alias ModuleName Ident- -- | -- A local name introduced using a lambda abstraction, variable introduction or binder -- | LocalVariable@@ -62,31 +58,6 @@ | DataConstructor deriving Show -- |--- The type of a type declaration----data TypeDeclarationKind- -- |- -- A data constructor- --- = Data- -- |- -- A data type foreign import- --- | ExternData- -- |- -- A type synonym- --- | TypeSynonym- -- |- -- An alias for a type in another module, introduced using an import declaration- --- | DataAlias ModuleName ProperName- -- |- -- A local type name introduced using a forall quantifier- --- | LocalTypeVariable deriving Show---- | -- The @Environment@ defines all values and types which are currently in scope: -- data Environment = Environment {@@ -97,15 +68,15 @@ -- | -- Type names currently in scope --- , types :: M.Map (ModuleName, ProperName) (Kind, TypeDeclarationKind)+ , types :: M.Map (Qualified ProperName) Kind -- | -- Data constructors currently in scope, along with their associated data type constructors --- , dataConstructors :: M.Map (ModuleName, ProperName) (Type, NameKind)+ , dataConstructors :: M.Map (Qualified ProperName) Type -- | -- Type synonyms currently in scope --- , typeSynonyms :: M.Map (ModuleName, ProperName) ([String], Type)+ , typeSynonyms :: M.Map (Qualified ProperName) ([String], Type) -- | -- Available type class dictionaries --@@ -115,12 +86,12 @@ -- | -- The basic types existing in the external javascript environment ---jsTypes ::M.Map (ModuleName, ProperName) (Kind, TypeDeclarationKind)-jsTypes = M.fromList [ ((ModuleName [ProperName "Prim"], ProperName "Function"), (FunKind Star $ FunKind Star Star, ExternData))- , ((ModuleName [ProperName "Prim"], ProperName "Array"), (FunKind Star Star, ExternData))- , ((ModuleName [ProperName "Prim"], ProperName "String"), (Star, ExternData))- , ((ModuleName [ProperName "Prim"], ProperName "Number"), (Star, ExternData))- , ((ModuleName [ProperName "Prim"], ProperName "Boolean"), (Star, ExternData)) ]+jsTypes ::M.Map (Qualified ProperName) Kind+jsTypes = M.fromList [ (Qualified (Just $ ModuleName [ProperName "Prim"]) (ProperName "Function"), FunKind Star (FunKind Star Star))+ , (Qualified (Just $ ModuleName [ProperName "Prim"]) (ProperName "Array"), FunKind Star Star)+ , (Qualified (Just $ ModuleName [ProperName "Prim"]) (ProperName "String"), Star)+ , (Qualified (Just $ ModuleName [ProperName "Prim"]) (ProperName "Number"), Star)+ , (Qualified (Just $ ModuleName [ProperName "Prim"]) (ProperName "Boolean"), Star) ] -- | -- The initial environment with no values and only the default javascript types defined@@ -142,7 +113,7 @@ -- | -- Temporarily bind a collection of names to types ---bindTypes :: (MonadState CheckState m) => M.Map (ModuleName, ProperName) (Kind, TypeDeclarationKind) -> m a -> m a+bindTypes :: (MonadState CheckState m) => M.Map (Qualified ProperName) Kind -> m a -> m a bindTypes newNames action = do orig <- get modify $ \st -> st { checkEnv = (checkEnv st) { types = newNames `M.union` (types . checkEnv $ st) } }@@ -179,7 +150,7 @@ -- bindLocalTypeVariables :: (Functor m, MonadState CheckState m) => ModuleName -> [(ProperName, Kind)] -> m a -> m a bindLocalTypeVariables moduleName bindings =- bindTypes (M.fromList $ flip map bindings $ \(name, k) -> ((moduleName, name), (k, LocalTypeVariable)))+ bindTypes (M.fromList $ flip map bindings $ first $ Qualified (Just moduleName)) -- | -- Lookup the type of a value by name in the @Environment@@@ -197,36 +168,9 @@ lookupTypeVariable :: (Functor m, MonadState CheckState m, MonadError String m) => ModuleName -> Qualified ProperName -> m Kind lookupTypeVariable currentModule (Qualified moduleName name) = do env <- getEnv- case M.lookup (fromMaybe currentModule moduleName, name) (types env) of+ case M.lookup (Qualified (Just $ fromMaybe currentModule moduleName) name) (types env) of Nothing -> throwError $ "Type variable " ++ show name ++ " is undefined"- Just (k, _) -> return k---- |--- Canonicalize an identifier by resolving any aliases introduced by module imports----canonicalize :: ModuleName -> Environment -> Qualified Ident -> (ModuleName, Ident)-canonicalize _ _ (Qualified (Just mn) i) = (mn, i)-canonicalize mn env (Qualified Nothing i) = case (mn, i) `M.lookup` names env of- Just (_, Alias mn' i') -> (mn', i')- _ -> (mn, i)---- |--- Canonicalize a type variable by resolving any aliases introduced by module imports----canonicalizeType :: ModuleName -> Environment -> Qualified ProperName -> (ModuleName, ProperName)-canonicalizeType _ _ (Qualified (Just mn) nm) = (mn, nm)-canonicalizeType mn env (Qualified Nothing nm) = case (mn, nm) `M.lookup` types env of- Just (_, DataAlias mn' pn') -> (mn', pn')- _ -> (mn, nm)---- |--- Canonicalize a data constructor by resolving any aliases introduced by module imports----canonicalizeDataConstructor :: ModuleName -> Environment -> Qualified ProperName -> (ModuleName, ProperName)-canonicalizeDataConstructor _ _ (Qualified (Just mn) pn) = (mn, pn)-canonicalizeDataConstructor mn env (Qualified Nothing pn) = case (mn, pn) `M.lookup` dataConstructors env of- Just (_, Alias mn' (Ident pn')) -> (mn', ProperName pn')- _ -> (mn, pn)+ Just k -> return k -- | -- State required for type checking:@@ -322,17 +266,3 @@ Right (a, ust) -> do modify $ \st' -> st' { checkNextVar = unifyNextVar ust } return (a, unifyCurrentSubstitution ust)---- |--- Replace any unqualified names in a type wit their qualified versionss----qualifyAllUnqualifiedNames :: (Data d) => ModuleName -> Environment -> d -> d-qualifyAllUnqualifiedNames mn env = everywhere (mkT go)- where- go :: Type -> Type- go (TypeConstructor nm) = TypeConstructor $ qualify' nm- go (SaturatedTypeSynonym nm args) = SaturatedTypeSynonym (qualify' nm) args- go (ConstrainedType constraints ty) = ConstrainedType (map (first qualify') constraints) ty- go other = other- qualify' qual = let (mn', pn') = canonicalizeType mn env qual- in Qualified (Just mn') pn'
src/Language/PureScript/TypeChecker/Synonyms.hs view
@@ -20,8 +20,9 @@ import Language.PureScript.Types import Language.PureScript.Names-import Language.PureScript.TypeChecker.Monad (Environment(..), canonicalizeType)+import Language.PureScript.TypeChecker.Monad (Environment(..)) +import Control.Applicative ((<$>)) import Data.Maybe (fromMaybe) import Data.Data import Data.Generics@@ -32,27 +33,27 @@ -- | -- Build a type substitution for a type synonym ---buildTypeSubstitution :: Environment -> ModuleName -> (ModuleName, ProperName) -> Int -> Type -> Either String (Maybe Type)+buildTypeSubstitution :: Environment -> ModuleName -> Qualified ProperName -> Int -> Type -> Either String (Maybe Type) buildTypeSubstitution env moduleName name n = go n [] where go :: Int -> [Type] -> Type -> Either String (Maybe Type)- go 0 args (TypeConstructor ctor) | name == canonicalizeType moduleName env ctor = return (Just $ SaturatedTypeSynonym ctor args)- go m _ (TypeConstructor ctor) | m > 0 && name == qualify moduleName ctor = throwError $ "Partially applied type synonym " ++ show name+ go 0 args (TypeConstructor ctor) | name == ctor = return (Just $ SaturatedTypeSynonym ctor args)+ go m _ (TypeConstructor ctor) | m > 0 && name == ctor = throwError $ "Partially applied type synonym " ++ show name go m args (TypeApp f arg) = go (m - 1) (arg:args) f go _ _ _ = return Nothing -- | -- Replace all instances of a specific type synonym with the @SaturatedTypeSynonym@ data constructor ---saturateTypeSynonym :: (Data d) => Environment -> ModuleName -> (ModuleName, ProperName) -> Int -> d -> Either String d+saturateTypeSynonym :: (Data d) => Environment -> ModuleName -> Qualified ProperName -> Int -> d -> Either String d saturateTypeSynonym env moduleName name n = everywhereM' (mkM replace) where- replace t = fmap (fromMaybe t) $ buildTypeSubstitution env moduleName name n t+ replace t = fromMaybe t <$> buildTypeSubstitution env moduleName name n t -- | -- Replace all type synonyms with the @SaturatedTypeSynonym@ data constructor ---saturateAllTypeSynonyms :: (Data d) => Environment -> ModuleName -> [((ModuleName, ProperName), Int)] -> d -> Either String d+saturateAllTypeSynonyms :: (Data d) => Environment -> ModuleName -> [(Qualified ProperName, Int)] -> d -> Either String d saturateAllTypeSynonyms env moduleName syns d = foldM (\result (name, n) -> saturateTypeSynonym env moduleName name n result) d syns
src/Language/PureScript/TypeChecker/Types.hs view
@@ -109,7 +109,7 @@ unifyTypes' (TypeConstructor c1) (TypeConstructor c2) = do env <- getEnv Just moduleName <- checkCurrentModule <$> get- guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (typeConstructorsAreEqual env moduleName c1 c2)+ guardWith ("Cannot unify " ++ show c1 ++ " with " ++ show c2 ++ ".") (c1 == c2) unifyTypes' (TypeApp t3 t4) (TypeApp t5 t6) = do t3 `unifyTypes` t5 t4 `unifyTypes` t6@@ -154,12 +154,6 @@ unifyRows' sd3 r3 sd4 r4 = throwError $ "Cannot unify (" ++ prettyPrintRow (rowFromList (sd3, r3)) ++ ") with (" ++ prettyPrintRow (rowFromList (sd4, r4)) ++ ")." -- |--- Ensure type constructors are equal after canonicalization----typeConstructorsAreEqual :: Environment -> ModuleName -> Qualified ProperName -> Qualified ProperName -> Bool-typeConstructorsAreEqual env moduleName = (==) `on` canonicalizeType moduleName env---- | -- Infer the types of multiple mutually-recursive values, and return elaborated values including -- type class dictionaries and type annotations. --@@ -271,7 +265,7 @@ -- Choose type class dictionaries in scope in the current module , filterModule tcd -- Make sure the type class name matches the one we are trying to satisfy- , typeConstructorsAreEqual env moduleName className' (tcdClassName tcd)+ , className' == tcdClassName tcd -- Make sure the type unifies with the type in the type instance definition , subst <- maybeToList . (>>= verifySubstitution) . fmap concat $ zipWithM (typeHeadsAreEqual moduleName env) tys' (tcdInstanceTypes tcd) -- Solve any necessary subgoals@@ -294,8 +288,6 @@ filterModule (TypeClassDictionaryInScope { tcdName = Qualified (Just mn) _ }) | mn == moduleName = True filterModule (TypeClassDictionaryInScope { tcdName = Qualified Nothing _ }) = True filterModule _ = False- -- Resolve a type class dictionary in scope to an actual value by following any (TCDAlias) pointers- -- which originated from module imports canonicalizeDictionary :: TypeClassDictionaryInScope -> Qualified Ident canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDRegular, tcdName = nm }) = nm canonicalizeDictionary (TypeClassDictionaryInScope { tcdType = TCDAlias nm }) = nm@@ -314,7 +306,7 @@ typeHeadsAreEqual _ _ (Skolem s1 _) (Skolem s2 _) | s1 == s2 = Just [] typeHeadsAreEqual _ _ (TypeVar v) t = Just [(v, t)] typeHeadsAreEqual _ _ t (TypeVar v) = Just [(v, t)]-typeHeadsAreEqual m e (TypeConstructor c1) (TypeConstructor c2) | typeConstructorsAreEqual e m c1 c2 = Just []+typeHeadsAreEqual m e (TypeConstructor c1) (TypeConstructor c2) | c1 == c2 = Just [] typeHeadsAreEqual m e (TypeApp h1 (TypeVar v)) (TypeApp h2 arg) = (:) (v, arg) <$> typeHeadsAreEqual m e h1 h2 typeHeadsAreEqual m e t1@(TypeApp _ _) t2@(TypeApp _ (TypeVar _)) = typeHeadsAreEqual m e t2 t1 typeHeadsAreEqual m e (SaturatedTypeSynonym name args) t2 = case expandTypeSynonym' e m name args of@@ -419,7 +411,7 @@ Just moduleName <- checkCurrentModule <$> get dicts <- getTypeClassDictionaries (_, ty') <- instantiatePolyTypeWithUnknowns (error "Types under a constraint cannot themselves be constrained") ty- return (foldl App val (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints)), ty')+ return (foldl App val (map (flip TypeClassDictionary dicts) constraints), ty') instantiatePolyTypeWithUnknowns val ty = return (val, ty) -- |@@ -437,7 +429,7 @@ replaceAllTypeSynonyms' :: (D.Data d) => Environment -> ModuleName -> d -> Either String d replaceAllTypeSynonyms' env moduleName d = let- syns = map (\((path, name), (args, _)) -> ((path, name), length args)) . M.toList $ typeSynonyms env+ syns = map (\(name, (args, _)) -> (name, length args)) . M.toList $ typeSynonyms env in saturateAllTypeSynonyms env moduleName syns d @@ -461,7 +453,7 @@ -- expandTypeSynonym' :: Environment -> ModuleName -> Qualified ProperName -> [Type] -> Either String Type expandTypeSynonym' env moduleName name args =- case M.lookup (canonicalizeType moduleName env name) (typeSynonyms env) of+ case M.lookup name (typeSynonyms env) of Just (synArgs, body) -> do let repl = replaceAllTypeVars (zip synArgs args) body replaceAllTypeSynonyms' env moduleName repl@@ -540,15 +532,15 @@ ConstrainedType constraints ty' -> do env <- getEnv dicts <- getTypeClassDictionaries- return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) ty'+ return $ TypedValue True (foldl App (Var var) (map (flip TypeClassDictionary dicts) constraints)) ty' _ -> return $ TypedValue True (Var var) ty infer' v@(Constructor c) = do env <- getEnv Just moduleName <- checkCurrentModule <$> get- case M.lookup (qualify moduleName c) (dataConstructors env) of+ case M.lookup c (dataConstructors env) of Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"- Just (ty, _) -> do ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty- return $ TypedValue True v ty'+ Just ty -> do ty' <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty+ return $ TypedValue True v ty' infer' (Case vals binders) = do ts <- mapM infer vals ret <- fresh@@ -596,8 +588,8 @@ inferBinder val (ConstructorBinder ctor binders) = do env <- getEnv Just moduleName <- checkCurrentModule <$> get- case M.lookup (qualify moduleName ctor) (dataConstructors env) of- Just (ty, _) -> do+ case M.lookup ctor (dataConstructors env) of+ Just ty -> do (_, fn) <- instantiatePolyTypeWithUnknowns (error "Data constructor types cannot contains constraints") ty go binders fn where@@ -640,18 +632,18 @@ -- | -- Check the types of the return values in a set of binders in a case statement ---checkBinders :: [Type] -> Type -> [([Binder], Maybe Guard, Value)] -> UnifyT Type Check [([Binder], Maybe Guard, Value)]+checkBinders :: [Type] -> Type -> [CaseAlternative] -> UnifyT Type Check [CaseAlternative] checkBinders _ _ [] = return []-checkBinders nvals ret ((binders, grd, val):bs) = do+checkBinders nvals ret (CaseAlternative binders grd val : bs) = do Just moduleName <- checkCurrentModule <$> get m1 <- M.unions <$> zipWithM inferBinder nvals binders r <- bindLocalVariables moduleName (M.toList m1) $ do val' <- TypedValue True <$> check val ret <*> pure ret case grd of- Nothing -> return (binders, Nothing, val')+ Nothing -> return $ CaseAlternative binders Nothing val' Just g -> do g' <- check g tyBoolean- return (binders, Just g', val')+ return $ CaseAlternative binders (Just g') val' rs <- checkBinders nvals ret bs return $ r : rs @@ -725,8 +717,7 @@ return $ Ident $ "__dict_" ++ className ++ "_" ++ show n val' <- withTypeClassDictionaries (zipWith (\name (className, instanceTy) -> TypeClassDictionaryInScope name className instanceTy Nothing TCDRegular) (map (Qualified Nothing) dictNames)- (qualifyAllUnqualifiedNames moduleName env constraints)) $- check val ty+ constraints) $ check val ty return $ TypedValue True (foldr (Abs . Left) val' dictNames) t check' val (SaturatedTypeSynonym name args) = do ty <- introduceSkolemScope <=< expandTypeSynonym name $ args@@ -806,9 +797,9 @@ check' (Constructor c) ty = do env <- getEnv Just moduleName <- checkCurrentModule <$> get- case M.lookup (qualify moduleName c) (dataConstructors env) of+ case M.lookup c (dataConstructors env) of Nothing -> throwError $ "Constructor " ++ show c ++ " is undefined"- Just (ty1, _) -> do+ Just ty1 -> do repl <- introduceSkolemScope <=< replaceAllTypeSynonyms $ ty1 _ <- subsumes Nothing repl ty return $ TypedValue True (Constructor c) ty@@ -886,7 +877,7 @@ env <- getEnv dicts <- getTypeClassDictionaries Just moduleName <- checkCurrentModule <$> get- checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))) fnTy arg+ checkFunctionApplication' (foldl App fn (map (flip TypeClassDictionary dicts) constraints)) fnTy arg checkFunctionApplication' _ fnTy arg = throwError $ "Cannot apply a function of type " ++ prettyPrintType fnTy ++ " to argument " ++ prettyPrintValue arg@@ -932,7 +923,7 @@ dicts <- getTypeClassDictionaries Just moduleName <- checkCurrentModule <$> get _ <- subsumes' Nothing ty1 ty2- return . Just $ foldl App val (map (flip TypeClassDictionary dicts) (qualifyAllUnqualifiedNames moduleName env constraints))+ return . Just $ foldl App val (map (flip TypeClassDictionary dicts) constraints) subsumes' val (Object r1) (Object r2) = do let (ts1, r1') = rowToList r1
src/Language/PureScript/Values.hs view
@@ -21,6 +21,7 @@ import Language.PureScript.Names import Data.Data+import Data.Generics (mkQ, everything) -- | -- A guard is just a boolean-valued expression that appears alongside a set of binders@@ -93,7 +94,7 @@ -- A case expression. During the case expansion phase of desugaring, top-level binders will get -- desugared into case expressions, hence the need for guards and multiple binders per branch here. --- | Case [Value] [([Binder], Maybe Guard, Value)]+ | Case [Value] [CaseAlternative] -- | -- A value with a type annotation --@@ -115,17 +116,22 @@ | TypeClassDictionary (Qualified ProperName, [Type]) [TypeClassDictionaryInScope] deriving (Show, Data, Typeable) -- |--- The type of a type class dictionary+-- An alternative in a case statement ---data TypeClassDictionaryType- -- |- -- A regular type class dictionary- --- = TCDRegular- -- |- -- A type class dictionary which is an alias for an imported dictionary from another module- --- | TCDAlias (Qualified Ident) deriving (Show, Eq, Data, Typeable)+data CaseAlternative = CaseAlternative+ { -- |+ -- A collection of binders with which to match the inputs+ --+ caseAlternativeBinders :: [Binder]+ -- |+ -- An optional guard+ --+ , caseAlternativeGuard :: Maybe Guard+ -- |+ -- The result expression+ --+ , caseAlternativeResult :: Value+ } deriving (Show, Data, Typeable) -- | -- Data representing a type class dictionary which is in scope@@ -155,6 +161,19 @@ } deriving (Show, Data, Typeable) -- |+-- The type of a type class dictionary+--+data TypeClassDictionaryType+ -- |+ -- A regular type class dictionary+ --+ = TCDRegular+ -- |+ -- A type class dictionary which is an alias for an imported dictionary from another module+ --+ | TCDAlias (Qualified Ident) deriving (Show, Eq, Data, Typeable)++-- | -- A statement in a do-notation block -- data DoNotationElement@@ -215,3 +234,14 @@ -- A binder which binds its input to an identifier -- | NamedBinder Ident Binder deriving (Show, Data, Typeable)+++-- |+-- Collect all names introduced in binders in an expression+--+binderNames :: (Data d) => d -> [Ident]+binderNames = everything (++) (mkQ [] go)+ where+ go (VarBinder ident) = [ident]+ go (NamedBinder ident _) = [ident]+ go _ = []
tests/Main.hs view
@@ -26,7 +26,6 @@ import System.Process import System.FilePath (pathSeparator) import System.Directory (getCurrentDirectory, getDirectoryContents, findExecutable)-import System.Environment (getArgs) import Text.Parsec (ParseError) import qualified Paths_purescript as Paths import qualified System.IO.UTF8 as U@@ -65,16 +64,12 @@ putStrLn $ "assert " ++ inputFile ++ " compiles successfully" prelude <- preludeFilename assert (P.defaultOptions { P.optionsMain = Just "Main", P.optionsNoOptimizations = True, P.optionsModules = ["Main"] }) [prelude, inputFile] $ either (return . Just) $ \js -> do- args <- getArgs- if "--run-js" `elem` args- then do- process <- findNodeProcess- result <- traverse (\node -> readProcessWithExitCode node [] js) process- case result of- Just (ExitSuccess, out, _) -> putStrLn out >> return Nothing- Just (ExitFailure _, _, err) -> return $ Just err- Nothing -> return $ Just "Couldn't find node.js executable"- else return Nothing+ process <- findNodeProcess+ result <- traverse (\node -> readProcessWithExitCode node [] js) process+ case result of+ Just (ExitSuccess, out, _) -> putStrLn out >> return Nothing+ Just (ExitFailure _, _, err) -> return $ Just err+ Nothing -> return $ Just "Couldn't find node.js executable" findNodeProcess :: IO (Maybe String) findNodeProcess = runMaybeT . msum $ map (MaybeT . findExecutable) names