module ParseTypes where
import Ast
import Control.Applicative ((<$>),(<*>))
import Control.Monad (liftM)
import Data.Char (isUpper,isLower)
import Data.Maybe (fromMaybe)
import Data.List (lookup)
import Text.Parsec
import ParseLib
import Types hiding (string,parens)
import Guid
data ParseType = VarPT String
| LambdaPT ParseType ParseType
| ADTPT String [ParseType]
listPT t = ADTPT "List" [t]
tuplePT ts = ADTPT ("Tuple" ++ show (length ts)) ts
typeVar :: (Monad m) => ParsecT [Char] u m ParseType
typeVar = VarPT <$> lowVar <?> "type variable"
typeList :: (Monad m) => ParsecT [Char] u m ParseType
typeList = listPT <$> braces typeExpr
typeTuple :: (Monad m) => ParsecT [Char] u m ParseType
typeTuple = do ts <- parens (commaSep typeExpr)
return $ case ts of { [t] -> t ; _ -> tuplePT ts }
typeUnambiguous :: (Monad m) => ParsecT [Char] u m ParseType
typeUnambiguous = typeList <|> typeTuple
typeSimple :: (Monad m) => ParsecT [Char] u m ParseType
typeSimple = VarPT <$> var
typeApp :: (Monad m) => ParsecT [Char] u m ParseType
typeApp = do name <- capVar
args <- spacePrefix (typeUnambiguous <|> typeSimple)
return $ case args of
[] -> VarPT name
_ -> ADTPT name args
typeExpr :: (Monad m) => ParsecT [Char] u m ParseType
typeExpr = do
t1 <- typeVar <|> typeApp <|> typeUnambiguous
whitespace ; arr <- optionMaybe arrow ; whitespace
case arr of Just _ -> LambdaPT t1 <$> typeExpr
Nothing -> return t1
typeConstructor :: (Monad m) => ParsecT [Char] u m (String, [ParseType])
typeConstructor = (,) <$> capVar <*> spacePrefix (typeSimple <|> typeUnambiguous)
datatype :: (Monad m) => ParsecT [Char] u m ([String], [Expr], GuidCounter [Type])
datatype = do
reserved "data" <?> "datatype definition (data T = A | B | ...)"
forcedWS ; name <- capVar ; args <- spacePrefix lowVar
whitespace ; string "=" ; whitespace
tcs <- pipeSep1 typeConstructor
return $ (map fst tcs , map toFunc tcs , toTypes name args tcs)
beta = liftM VarT guid
toFunc (name,args) = foldr Lambda (Data name $ map Var argNames) argNames
where argNames = map (("a"++) . show) [1..length args]
toTypes name args constructors = do
pairs <- mapM (\x -> (,) x `liftM` guid) args
return $ map (toType pairs . ADT name $ map (VarT . snd) pairs) constructors
toType pairs outType (name,args) =
foldr (==>) outType (map toT args)
where toT (LambdaPT t1 t2) = toT t1 ==> toT t2
toT (ADTPT name args) = ADT name $ map toT args
toT (VarPT x@(c:_))
| isLower c = VarT . fromMaybe (1) $ lookup x pairs
| otherwise = case x of "Int" -> IntT
"Number" -> IntT
"String" -> StringT
"Char" -> CharT
"Bool" -> BoolT
_ -> ADT x []