Elm-0.2.0: src/Parse/Patterns.hs
module Patterns (patternTerm, patternExpr, makeFunction, flattenPatterns) where
import Ast
import Data.Char (isUpper)
import Control.Applicative ((<$>))
import Control.Monad
import Text.Parsec
import ParseLib
patternBasic :: Monad m => ParsecT [Char] u m Pattern
patternBasic =
choice [ char '_' >> return PAnything
, do x@(c:_) <- var
if isUpper c then PData x <$> spacePrefix patternTerm
else return $ PVar x
]
patternTuple :: Monad m => ParsecT [Char] u m Pattern
patternTuple = do ps <- parens (commaSep patternExpr)
return $ case ps of { [p] -> p; _ -> ptuple ps }
patternList :: Monad m => ParsecT [Char] u m Pattern
patternList = plist <$> braces (commaSep patternExpr)
patternTerm :: Monad m => ParsecT [Char] u m Pattern
patternTerm = patternTuple <|> patternList <|> patternBasic <?> "pattern"
patternExpr :: Monad m => ParsecT [Char] u m Pattern
patternExpr = foldl1 pcons <$> consSep1 patternTerm <?> "pattern"
makeFunction args body = foldr func body args
where func PAnything e = Lambda "_" e
func (PVar x) e = Lambda x e
func p e = "t" `Lambda` Case (Var "t") [(p,e)]
flattenPatterns (PVar f : args) exp = return [(f, makeFunction args exp)]
flattenPatterns [p] exp = return $ matchSingle p exp p
flattenPatterns ps _ =
fail $ "Pattern (" ++ unwords (map show ps) ++
") cannot be used on the left-hand side of an assign statement."
matchSingle pat exp p@(PData _ ps) =
(v, exp) : concatMap (matchSingle p $ Var v) ps
where v = "'" ++ getName p
matchSingle pat exp (PVar x) = [ (x, Case exp [(pat,Var x)]) ]
matchSingle pat exp PAnything = []
getName (PData n ps) = n ++ concatMap getName ps
getName (PAnything) = "_"
getName (PVar x) = x