module ParseTypes where
import Ast
import Combinators
import Data.Char (isUpper,isLower)
import Data.Maybe (fromMaybe)
import Data.List (lookup)
import ParserLib
import Tokens
import Types
import Guid
import Control.Monad (liftM)
data ParseType = VarPT String
| LambdaPT ParseType ParseType
| ADTPT String [ParseType]
listPT t = ADTPT "List" [t]
tuplePT ts = ADTPT ("Tuple" ++ show (length ts)) ts
typeVar = liftM VarPT lowVar
typeList = do t LBRACKET; te <- typeExpr; t RBRACKET; return $ listPT te
typeTuple = do { t LPAREN; ts <- sepBy (t COMMA) typeExpr; t RPAREN
; return $ case ts of { [t] -> t ; _ -> tuplePT ts } }
typeUnambiguous = typeList +|+ typeTuple
typeSimple = liftM VarPT var
typeApp = do name <- capVar
args <- star (typeSimple +|+ typeUnambiguous)
return $ case args of
[] -> VarPT name
_ -> ADTPT name args
typeExpr = do
t1 <- typeVar +|+ typeApp +|+ typeUnambiguous
arrow <- optional $ t ARROW
case arrow of Just ARROW -> LambdaPT t1 `liftM` typeExpr
Nothing -> return t1
typeConstructor = do name <- capVar
args <- star (typeSimple +|+ typeUnambiguous)
return $ (,) name args
datatype = do
t DATA ; name <- capVar ; args <- star lowVar ; assign
tcs <- sepBy1 (opParser (=="|")) typeConstructor
return $ (map fst tcs , map toFunc tcs , toTypes name args tcs)
beta = VarT `liftM` 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 []