module AST.Pattern where
import qualified AST.Helpers as Help
import AST.PrettyPrint
import Text.PrettyPrint as PP
import qualified Data.Set as Set
import qualified AST.Variable as Var
import AST.Literal as Literal
data Pattern var
= Data var [Pattern var]
| Record [String]
| Alias String (Pattern var)
| Var String
| Anything
| Literal Literal.Literal
deriving (Eq, Ord, Show)
type RawPattern =
Pattern Var.Raw
type CanonicalPattern =
Pattern Var.Canonical
cons :: RawPattern -> RawPattern -> RawPattern
cons h t =
Data (Var.Raw "::") [h,t]
nil :: RawPattern
nil =
Data (Var.Raw "[]") []
list :: [RawPattern] -> RawPattern
list patterns =
foldr cons nil patterns
tuple :: [RawPattern] -> RawPattern
tuple patterns =
Data (Var.Raw ("_Tuple" ++ show (length patterns))) patterns
boundVarList :: Pattern var -> [String]
boundVarList pattern =
Set.toList (boundVars pattern)
boundVars :: Pattern var -> Set.Set String
boundVars pattern =
case pattern of
Var x -> Set.singleton x
Alias x p -> Set.insert x (boundVars p)
Data _ ps -> Set.unions (map boundVars ps)
Record fields -> Set.fromList fields
Anything -> Set.empty
Literal _ -> Set.empty
instance Var.ToString var => Pretty (Pattern var) where
pretty pattern =
case pattern of
Var x ->
variable x
Literal literal ->
pretty literal
Record fields ->
PP.braces (commaCat (map variable fields))
Alias x p ->
prettyParens p <+> PP.text "as" <+> variable x
Anything ->
PP.text "_"
Data name [hd,tl] | Var.toString name == "::" ->
parensIf isCons (pretty hd) <+> PP.text "::" <+> pretty tl
where
isCons =
case hd of
Data ctor _ -> Var.toString ctor == "::"
_ -> False
Data name ps ->
let name' = Var.toString name
in
if Help.isTuple name'
then PP.parens (commaCat (map pretty ps))
else hsep (PP.text name' : map prettyParens ps)
prettyParens :: Var.ToString var => Pattern var -> Doc
prettyParens pattern =
parensIf needsThem (pretty pattern)
where
needsThem =
case pattern of
Data name (_:_) | not (Help.isTuple (Var.toString name)) -> True
Alias _ _ -> True
_ -> False