module Helium.StaticAnalysis.Miscellaneous.TypeConversion where
import Helium.Syntax.UHA_Utils (getNameName, nameFromString)
import Helium.Syntax.UHA_Range (noRange)
import Helium.Utils.Utils (internalError)
import Data.List (union)
import Data.Maybe
import Helium.Syntax.UHA_Syntax
import Top.Types
namesInTypes :: Types -> Names
namesInTypes = foldr (union . namesInType) []
namesInType :: Type -> Names
namesInType uhaType = case uhaType of
Type_Application _ _ fun args -> namesInTypes (fun : args)
Type_Variable _ name -> [name]
Type_Constructor _ _ -> []
Type_Parenthesized _ t -> namesInType t
Type_Qualified _ _ t -> namesInType t
Type_Forall{} -> internalError "TypeConversion.hs" "namesInType" "universal types are currently not supported"
Type_Exists{} -> internalError "TypeConversion.hs" "namesInType" "existential types are currently not supported"
makeNameMap :: Names -> [(Name,Tp)]
makeNameMap = flip zip (map TVar [0..])
makeTpSchemeFromType' :: Type -> (TpScheme, [(Int, Name)])
makeTpSchemeFromType' uhaType =
let names = namesInType uhaType
nameMap = makeNameMap names
intMap = zip [0..] names
context = predicatesFromContext nameMap uhaType
tp = makeTpFromType nameMap uhaType
scheme = Quantification (ftv tp, [ (i,getNameName n) | (n,TVar i) <- nameMap], context .=>. tp)
in (scheme, intMap)
makeTpSchemeFromType :: Type -> TpScheme
makeTpSchemeFromType = fst . makeTpSchemeFromType'
predicatesFromContext :: [(Name,Tp)] -> Type -> Predicates
predicatesFromContext nameMap (Type_Qualified _ is _) =
concatMap predicateFromContext is
where
predicateFromContext (ContextItem_ContextItem _ cn [Type_Variable _ vn]) =
case lookup vn nameMap of
Nothing -> []
Just tp -> [Predicate (getNameName cn) tp]
predicateFromContext _ = internalError "TypeConversion.hs" "predicateFromContext" "malformed type in context"
predicatesFromContext _ _ = []
makeTpFromType :: [(Name,Tp)] -> Type -> Tp
makeTpFromType nameMap = rec_
where
rec_ :: Type -> Tp
rec_ uhaType = case uhaType of
Type_Application _ _ fun args -> foldl TApp (rec_ fun) (map rec_ args)
Type_Variable _ name -> fromMaybe (TCon "???") (lookup name nameMap)
Type_Constructor _ name -> TCon (getNameName name)
Type_Parenthesized _ t -> rec_ t
Type_Qualified _ _ t -> rec_ t
Type_Forall{} -> internalError "TypeConversion.hs" "makeTpFromType" "universal types are currently not supported"
Type_Exists{} -> internalError "TypeConversion.hs" "makeTpFromType" "existential types are currently not supported"
convertFromSimpleTypeAndTypes :: SimpleType -> Types -> (Tp,Tps)
convertFromSimpleTypeAndTypes stp tps =
let SimpleType_SimpleType _ name typevariables = stp
nameMap = makeNameMap (foldr union [] (typevariables : map namesInType tps))
simpletype = foldl TApp (TCon (getNameName name)) (take (length typevariables) (map TVar [0..]))
in (simpletype,map (makeTpFromType nameMap) tps)
makeTypeFromTp :: Tp -> Type
makeTypeFromTp t =
let (x,xs) = leftSpine t
in if null xs
then f x
else Type_Application noRange True (f x) (map makeTypeFromTp xs)
where f (TVar i) = Type_Variable noRange (nameFromString ('v' : show i))
f (TCon s) = Type_Constructor noRange (nameFromString s)
f (TApp _ _) = error "TApp case in makeTypeFromTp"