module Parse.Type where
import Control.Applicative ((<$>),(<*>),(<*))
import Data.List (intercalate)
import Text.Parsec ((<|>), (<?>), char, many, optionMaybe, string, try)
import qualified AST.Type as T
import qualified AST.Variable as Var
import Parse.Helpers
tvar :: IParser T.RawType
tvar =
T.Var <$> lowVar <?> "type variable"
tuple :: IParser T.RawType
tuple =
do ts <- parens (commaSep expr)
case ts of
[t] -> return t
_ -> return (T.tupleOf ts)
record :: IParser T.RawType
record =
do char '{'
whitespace
rcrd <- extended <|> normal
dumbWhitespace
char '}'
return rcrd
where
normal = flip T.Record Nothing <$> commaSep field
extended = do
ext <- try (lowVar <* (whitespace >> string "|"))
whitespace
flip T.Record (Just (T.Var ext)) <$> commaSep1 field
field = do
lbl <- rLabel
whitespace >> hasType >> whitespace
(,) lbl <$> expr
capTypeVar :: IParser String
capTypeVar =
intercalate "." <$> dotSep1 capVar
constructor0 :: IParser T.RawType
constructor0 =
do name <- capTypeVar
return (T.Type (Var.Raw name))
term :: IParser T.RawType
term =
tuple <|> record <|> tvar <|> constructor0
app :: IParser T.RawType
app =
do f <- constructor0 <|> try tupleCtor <?> "type constructor"
args <- spacePrefix term
case args of
[] -> return f
_ -> return (T.App f args)
where
tupleCtor = do
n <- length <$> parens (many (char ','))
let ctor = "_Tuple" ++ show (if n == 0 then 0 else n+1)
return (T.Type (Var.Raw ctor))
expr :: IParser T.RawType
expr =
do t1 <- app <|> term
arr <- optionMaybe $ try (whitespace >> arrow)
case arr of
Just _ -> T.Lambda t1 <$> (whitespace >> expr)
Nothing -> return t1
constructor :: IParser (String, [T.RawType])
constructor =
(,) <$> (capTypeVar <?> "another type constructor")
<*> spacePrefix term