@@ -21,29 +21,34 @@ import Language.PureScript.Names
2121import Language.PureScript.Types
2222import Language.PureScript.Values
2323import Language.PureScript.CodeGen.JS.AST
24+import Language.PureScript.Sugar.CaseDeclarations
2425
2526import qualified Data.Map as M
2627
2728import Control.Applicative
2829import Control.Monad.State
2930import Data.Maybe (fromMaybe)
31+import Data.List (nub)
32+import Data.Generics (mkQ, everything)
3033
3134type MemberMap = M.Map (ModuleName, ProperName) (String, [(String, Type)])
3235
33−desugarTypeClasses :: [Module] -> [Module]
34−desugarTypeClasses = flip evalState M.empty . mapM desugarModule
36+type Desugar = StateT MemberMap (Either String)
3537
36−desugarModule :: Module -> State MemberMap Module
38+desugarTypeClasses :: [Module] -> Either String [Module]
39+desugarTypeClasses = flip evalStateT M.empty . mapM desugarModule
40+
41+desugarModule :: Module -> Desugar Module
3742desugarModule (Module name decls) = Module name <$> concat <$> mapM (desugarDecl (ModuleName name)) decls
3843
39−desugarDecl :: ModuleName -> Declaration -> State MemberMap [Declaration]
44+desugarDecl :: ModuleName -> Declaration -> Desugar [Declaration]
4045desugarDecl mn d@(TypeClassDeclaration name arg members) = do
4146 let tys = map memberToNameAndType members
4247 modify (M.insert (mn, name) (arg, tys))
4348 return $ d : typeClassDictionaryDeclaration name arg members : map (typeClassMemberToDictionaryAccessor name arg) members
4449desugarDecl mn d@(TypeInstanceDeclaration deps name ty members) = do
4550 entries <- mapM (typeInstanceDictionaryEntryDeclaration mn deps name ty) members
46− return $ d : typeInstanceDictionaryDeclaration deps name ty members : entries
51+ return $ d : typeInstanceDictionaryDeclaration mn deps name ty members : entries
4752desugarDecl _ other = return [other]
4853
4954memberToNameAndType :: Declaration -> (String, Type)
@@ -61,52 +66,61 @@ typeClassMemberToDictionaryAccessor name arg (TypeDeclaration ident ty) =
6166 (ForAll arg (ConstrainedType [(Qualified Nothing name, TypeVar arg)] ty))
6267typeClassMemberToDictionaryAccessor _ _ _ = error "Invalid declaration in type class definition"
6368
64−typeInstanceDictionaryDeclaration :: [(Qualified ProperName, Type)] -> Qualified ProperName -> Type -> [Declaration] -> Declaration
65−typeInstanceDictionaryDeclaration deps name ty decls =
66− ExternDeclaration (mkDictionaryValueName name ty)
67− (Just (JSFunction (Just (mkDictionaryValueName name ty))
69+typeInstanceDictionaryDeclaration :: ModuleName -> [(Qualified ProperName, Type)] -> Qualified ProperName -> Type -> [Declaration] -> Declaration
70+typeInstanceDictionaryDeclaration mn deps name ty decls =
71+ ExternDeclaration (mkDictionaryValueName mn name ty)
72+ (Just (JSFunction (Just (mkDictionaryValueName mn name ty))
6873 (map (\n -> Ident ('_' : show n)) [1..length deps])
6974 (JSBlock [JSReturn (JSObjectLiteral $ map memberToNameAndValue decls)])))
70− (Function (map (\(pn, ty') -> TypeApp (TypeConstructor pn) ty') deps) (TypeApp (TypeConstructor name) ty))
75+ (quantify (Function (map (\(pn, ty') -> TypeApp (TypeConstructor pn) ty') deps) (TypeApp (TypeConstructor name) ty)))
7176 where
7277 memberToNameAndValue :: Declaration -> (String, JS)
7378 memberToNameAndValue (ValueDeclaration ident _ _ _) =
74− (identToString ident, let dict = JSVar $ mkDictionaryEntryName name ty ident
79+ (identToString ident, let dict = JSVar $ mkDictionaryEntryName mn name ty ident
7580 in if null deps then dict
7681 else JSApp dict (map (\n -> JSVar (Ident ('_' : show n))) [1..length deps]))
7782 memberToNameAndValue _ = error "Invalid declaration in type instance definition"
7883
79−typeInstanceDictionaryEntryDeclaration :: ModuleName -> [(Qualified ProperName, Type)] -> Qualified ProperName -> Type -> Declaration -> State MemberMap Declaration
84+typeInstanceDictionaryEntryDeclaration :: ModuleName -> [(Qualified ProperName, Type)] -> Qualified ProperName -> Type -> Declaration -> Desugar Declaration
8085typeInstanceDictionaryEntryDeclaration mn deps name ty (ValueDeclaration ident binders grd val) = do
8186 m <- get
8287 let valTy = fromMaybe (error "Type class instance dictionary member is missing in typeInstanceDictionaryEntryDeclaration") $
8388 do (arg, members) <- M.lookup (qualify mn name) m
8489 ty' <- lookup (identToString ident) members
8590 return $ replaceTypeVars arg ty ty'
86− return $ ValueDeclaration (mkDictionaryEntryName name ty ident) binders grd
87− (TypedValue val (if null deps then valTy else ConstrainedType deps valTy))
91+ entryName = mkDictionaryEntryName mn name ty ident
92+ [ValueDeclaration _ _ _ val'] <- lift $ desugarCases [ValueDeclaration entryName binders grd val]
93+ return $ ValueDeclaration entryName [] Nothing
94+ (TypedValue val' (quantify (if null deps then valTy else ConstrainedType deps valTy)))
8895typeInstanceDictionaryEntryDeclaration _ _ _ _ _ = error "Invalid declaration in type instance definition"
8996
9097identToString :: Ident -> String
9198identToString (Ident s) = s
9299identToString (Op _) = error "TODO: Unsupported type class instance name"
93100
94−qualifiedToString :: Qualified ProperName -> String
95−qualifiedToString (Qualified Nothing _) = error "TODO: handle unqualified instances"
96−qualifiedToString (Qualified (Just (ModuleName mn)) pn) = runProperName mn ++ "_" ++ runProperName pn
101+qualifiedToString :: ModuleName -> Qualified ProperName -> String
102+qualifiedToString mn (Qualified Nothing pn) = qualifiedToString mn (Qualified (Just mn) pn)
103+qualifiedToString _ (Qualified (Just (ModuleName mn)) pn) = runProperName mn ++ "_" ++ runProperName pn
104+
105+quantify :: Type -> Type
106+quantify ty' = foldr ForAll ty' tyVars
107+ where
108+ tyVars = nub $ everything (++) (mkQ [] collect) ty'
109+ collect (TypeVar v) = [v]
110+ collect _ = []
97111
98−mkDictionaryValueName :: Qualified ProperName -> Type -> Ident
99−mkDictionaryValueName cl ty = Ident $ "__" ++ qualifiedToString cl ++ "_" ++ typeToString ty
112+mkDictionaryValueName :: ModuleName -> Qualified ProperName -> Type -> Ident
113+mkDictionaryValueName mn cl ty = Ident $ "__" ++ qualifiedToString mn cl ++ "_" ++ typeToString ty
100114 where
101115 typeToString :: Type -> String
102116 typeToString String = "string"
103117 typeToString Number = "number"
104118 typeToString Boolean = "boolean"
105119 typeToString (Array (TypeVar _)) = "array"
106− typeToString (TypeConstructor ty') = qualifiedToString ty'
120+ typeToString (TypeConstructor ty') = qualifiedToString mn ty'
107121 typeToString (TypeApp ty' (TypeVar _)) = typeToString ty'
108122 typeToString _ = error "TODO: Type class instance must be of the form T a1 ... an"
109123
110−mkDictionaryEntryName :: Qualified ProperName -> Type -> Ident -> Ident
111−mkDictionaryEntryName name ty ident = let Ident dictName = mkDictionaryValueName name ty
112− in Ident $ dictName ++ "_" ++ identToString ident
124+mkDictionaryEntryName :: ModuleName -> Qualified ProperName -> Type -> Ident -> Ident
125+mkDictionaryEntryName mn name ty ident = let Ident dictName = mkDictionaryValueName mn name ty
126+ in Ident $ dictName ++ "_" ++ identToString ident