@@ -26,8 +26,8 @@ import Prelude ()
26import Prelude.Compat
26import Prelude.Compat
28import Language.PureScript.Crash
28import Language.PureScript.Crash
29−import Data.Maybe (catMaybes)
29+import Data.Maybe (catMaybes, mapMaybe)
30−import Data.List (nub, groupBy)
30+import Data.List (nub, groupBy, foldl1')
32import Control.Monad ((<=<), forM, replicateM, join, unless)
32import Control.Monad ((<=<), forM, replicateM, join, unless)
33import Control.Monad.Error.Class (MonadError(..))
33import Control.Monad.Error.Class (MonadError(..))
@@ -51,14 +51,42 @@ isLeft (Right _) = False
51desugarCasesModule :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Module] -> m [Module]
51desugarCasesModule :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Module] -> m [Module]
52desugarCasesModule ms = forM ms $ \(Module ss coms name ds exps) ->
52desugarCasesModule ms = forM ms $ \(Module ss coms name ds exps) ->
53 rethrow (addHint (ErrorInModule name)) $
53 rethrow (addHint (ErrorInModule name)) $
54− Module ss coms name <$> (desugarCases <=< desugarAbs $ ds) <*> pure exps
54+ Module ss coms name <$> (desugarCases <=< desugarAbs <=< validateCases $ ds) <*> pure exps
57+-- Validates that case head and binder lengths match.
59+validateCases :: forall m. (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
60+validateCases = flip parU f
62+ (f, _, _) = everywhereOnValuesM return validate return
64+ validate :: Expr -> m Expr
65+ validate c@(Case vs alts) = do
67+ alts' = filter ((l /=) . length . caseAlternativeBinders) alts
68+ unless (null alts') $
69+ throwError . MultipleErrors $ fmap (altError l) (caseAlternativeBinders <$> alts')
71+ validate other = return other
73+ altError :: Int -> [Binder] -> ErrorMessage
74+ altError l bs = withPosition pos $ ErrorMessage [] $ CaseBinderLengthDiffers l bs
76+ pos = foldl1' widenSpan (mapMaybe positionedBinder bs)
78+ widenSpan (SourceSpan n start end) (SourceSpan _ start' end') =
79+ SourceSpan n (min start start') (max end end')
81+ positionedBinder (PositionedBinder p _ _) = Just p
82+ positionedBinder _ = Nothing
56−desugarAbs :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
84+desugarAbs :: forall m. (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
57desugarAbs = flip parU f
85desugarAbs = flip parU f
59 (f, _, _) = everywhereOnValuesM return replace return
87 (f, _, _) = everywhereOnValuesM return replace return
61− replace :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => Expr -> m Expr
89+ replace :: Expr -> m Expr
62 replace (Abs (Right binder) val) = do
90 replace (Abs (Right binder) val) = do
63 ident <- Ident <$> freshName
91 ident <- Ident <$> freshName
64 return $ Abs (Left ident) $ Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] (Right val)]
92 return $ Abs (Left ident) $ Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] (Right val)]
@@ -67,10 +95,10 @@ desugarAbs = flip parU f
68-- Replace all top-level binders with case expressions.
96-- Replace all top-level binders with case expressions.
70−desugarCases :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
98+desugarCases :: forall m. (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
71desugarCases = desugarRest <=< fmap join . flip parU toDecls . groupBy inSameGroup
99desugarCases = desugarRest <=< fmap join . flip parU toDecls . groupBy inSameGroup
73− desugarRest :: (Functor m, Applicative m, MonadSupply m, MonadError MultipleErrors m) => [Declaration] -> m [Declaration]
101+ desugarRest :: [Declaration] -> m [Declaration]
74 desugarRest (TypeInstanceDeclaration name constraints className tys ds : rest) =
102 desugarRest (TypeInstanceDeclaration name constraints className tys ds : rest) =
75 (:) <$> (TypeInstanceDeclaration name constraints className tys <$> traverseTypeInstanceBody desugarCases ds) <*> desugarRest rest
103 (:) <$> (TypeInstanceDeclaration name constraints className tys <$> traverseTypeInstanceBody desugarCases ds) <*> desugarRest rest
76 desugarRest (ValueDeclaration name nameKind bs result : rest) =
104 desugarRest (ValueDeclaration name nameKind bs result : rest) =