@@ -26,8 +26,8 @@ import Prelude ()
2626import Prelude.Compat
2727
2828import Language.PureScript.Crash
29- import Data.Maybe (catMaybes )
30- import Data.List (nub , groupBy )
29+ import Data.Maybe (catMaybes , mapMaybe )
30+ import Data.List (nub , groupBy , foldl1' )
3131
3232import Control.Monad ((<=<) , forM , replicateM , join , unless )
3333import Control.Monad.Error.Class (MonadError (.. ))
@@ -51,14 +51,42 @@ isLeft (Right _) = False
5151desugarCasesModule :: (Functor m , Applicative m , MonadSupply m , MonadError MultipleErrors m ) => [Module ] -> m [Module ]
5252desugarCasesModule ms = forM ms $ \ (Module ss coms name ds exps) ->
5353 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
5555
56- desugarAbs :: (Functor m , Applicative m , MonadSupply m , MonadError MultipleErrors m ) => [Declaration ] -> m [Declaration ]
56+ -- |
57+ -- Validates that case head and binder lengths match.
58+ --
59+ validateCases :: forall m . (Functor m , Applicative m , MonadSupply m , MonadError MultipleErrors m ) => [Declaration ] -> m [Declaration ]
60+ validateCases = flip parU f
61+ where
62+ (f, _, _) = everywhereOnValuesM return validate return
63+
64+ validate :: Expr -> m Expr
65+ validate c@ (Case vs alts) = do
66+ let l = length vs
67+ alts' = filter ((l /= ) . length . caseAlternativeBinders) alts
68+ unless (null alts') $
69+ throwError . MultipleErrors $ fmap (altError l) (caseAlternativeBinders <$> alts')
70+ return c
71+ validate other = return other
72+
73+ altError :: Int -> [Binder ] -> ErrorMessage
74+ altError l bs = withPosition pos $ ErrorMessage [] $ CaseBinderLengthDiffers l bs
75+ where
76+ pos = foldl1' widenSpan (mapMaybe positionedBinder bs)
77+
78+ widenSpan (SourceSpan n start end) (SourceSpan _ start' end') =
79+ SourceSpan n (min start start') (max end end')
80+
81+ positionedBinder (PositionedBinder p _ _) = Just p
82+ positionedBinder _ = Nothing
83+
84+ desugarAbs :: forall m . (Functor m , Applicative m , MonadSupply m , MonadError MultipleErrors m ) => [Declaration ] -> m [Declaration ]
5785desugarAbs = flip parU f
5886 where
5987 (f, _, _) = everywhereOnValuesM return replace return
6088
61- replace :: ( Functor m , Applicative m , MonadSupply m , MonadError MultipleErrors m ) => Expr -> m Expr
89+ replace :: Expr -> m Expr
6290 replace (Abs (Right binder) val) = do
6391 ident <- Ident <$> freshName
6492 return $ Abs (Left ident) $ Case [Var (Qualified Nothing ident)] [CaseAlternative [binder] (Right val)]
@@ -67,10 +95,10 @@ desugarAbs = flip parU f
6795-- |
6896-- Replace all top-level binders with case expressions.
6997--
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 ]
7199desugarCases = desugarRest <=< fmap join . flip parU toDecls . groupBy inSameGroup
72100 where
73- desugarRest :: ( Functor m , Applicative m , MonadSupply m , MonadError MultipleErrors m ) => [Declaration ] -> m [Declaration ]
101+ desugarRest :: [Declaration ] -> m [Declaration ]
74102 desugarRest (TypeInstanceDeclaration name constraints className tys ds : rest) =
75103 (:) <$> (TypeInstanceDeclaration name constraints className tys <$> traverseTypeInstanceBody desugarCases ds) <*> desugarRest rest
76104 desugarRest (ValueDeclaration name nameKind bs result : rest) =
0 commit comments