@@ -27,30 +27,40 @@ desugarCases :: [Declaration] -> Either String [Declaration]
2727desugarCases = fmap join . mapM toDecls . groupBy inSameGroup
2828
2929inSameGroup :: Declaration -> Declaration -> Bool
30−inSameGroup (ValueDeclaration ident1 _ _) (ValueDeclaration ident2 _ _) = ident1 == ident2
30+inSameGroup (ValueDeclaration ident1 _ _ _) (ValueDeclaration ident2 _ _ _) = ident1 == ident2
3131inSameGroup _ _ = False
3232
3333toDecls :: [Declaration] -> Either String [Declaration]
34−toDecls d@[ValueDeclaration _ [] _] = return d
35−toDecls ds@(ValueDeclaration ident bs _ : _) = do
36− let pairs = map toPair ds
37− unless (all ((== length bs) . length . fst) pairs) $
38− throwError $ "Argument list lengths differ in declaration " ++ show pairs
39− return [makeCaseDeclaration ident pairs]
34+toDecls d@[ValueDeclaration _ [] Nothing _] = return d
35+toDecls ds@(ValueDeclaration ident bs _ _ : _) = do
36+ let tuples = map toTuple ds
37+ unless (all ((== map length bs) . map length . fst) tuples) $
38+ throwError $ "Argument list lengths differ in declaration " ++ show ident
39+ return [makeCaseDeclaration ident tuples]
4040toDecls ds = return ds
4141
42−toPair :: Declaration -> ([Binder], Value)
43−toPair (ValueDeclaration _ bs val) = (bs, val)
44−toPair _ = error "Not a value declaration"
42+toTuple :: Declaration -> ([[Binder]], (Maybe Guard, Value))
43+toTuple (ValueDeclaration _ bs g val) = (bs, (g, val))
44+toTuple _ = error "Not a value declaration"
4545
46−makeCaseDeclaration :: Ident -> [([Binder], Value)] -> Declaration
46+makeCaseDeclaration :: Ident -> [([[Binder]], (Maybe Guard, Value))] -> Declaration
4747makeCaseDeclaration ident alternatives =
4848 let
49− numArgs = length (fst . head $ alternatives)
50− args = map (('_' :) . show) [1..numArgs]
51− obj = ObjectLiteral $ map (\arg -> (arg, Var (Qualified global (Ident arg)))) args
52− objBinders = [ (ObjectBinder (zip args bs), val) | (bs, val) <- alternatives ]
53− value = foldr (\arg ret -> Abs [Ident arg] ret) (Case obj objBinders) args
49+ argPattern = map length . fst . head $ alternatives
50+ args = map (map (('_' :) . show)) $ toArgs argPattern
51+ obj = ObjectLiteral $ concatMap (map (\arg -> (arg, Var (Qualified global (Ident arg))))) args
52+ objBinders = [ (applyGuard g $ ObjectBinder (join $ zipWith zip args bs), val) | (bs, (g, val)) <- alternatives ]
53+ value = foldr (\args' ret -> Abs (map Ident args') ret) (Case obj objBinders) args
5454 in
55− ValueDeclaration ident [] value
55+ ValueDeclaration ident [] Nothing value
56+
57+applyGuard :: Maybe Guard -> Binder -> Binder
58+applyGuard Nothing = id
59+applyGuard (Just g) = GuardedBinder g
60+
61+toArgs :: [Int] -> [[Int]]
62+toArgs = go 1
63+ where
64+ go _ [] = []
65+ go start (n:ns) = [start..start + n - 1] : go (start + n) ns
5666