@@ -25,7 +25,7 @@ module Language.PureScript.CodeGen.JS (
2525
2626import Data.Maybe (catMaybes, fromJust, fromMaybe)
2727import Data.Function (on)
28−import Data.List (nub, (\\), delete)
28+import Data.List (nub, (\\), delete, sortBy)
2929
3030import Control.Monad (replicateM, forM)
3131import Control.Applicative
@@ -42,7 +42,6 @@ import Language.PureScript.CodeGen.Common
4242import Language.PureScript.Environment
4343import Language.PureScript.Supply
4444import Language.PureScript.Traversals (sndM)
45−
4645import qualified Language.PureScript.Constants as C
4746
4847-- |
@@ -89,6 +88,7 @@ imports other =
8988 collectV :: Value -> [ModuleName]
9089 collectV (Var (Qualified (Just mn) _)) = [mn]
9190 collectV (Constructor (Qualified (Just mn) _)) = [mn]
91+ collectV (TypeClassDictionaryConstructorApp (Qualified (Just mn) _) _) = [mn]
9292 collectV _ = []
9393 collectB :: Binder -> [ModuleName]
9494 collectB (ConstructorBinder (Qualified (Just mn) _) _) = [mn]
@@ -109,16 +109,16 @@ declToJs opts mp (BindingGroupDeclaration vals) e = do
109109declToJs _ _ (DataDeclaration _ _ ctors) _ = do
110110 return $ Just $ flip concatMap ctors $ \(pn@(ProperName ctor), tys) ->
111111 let _ctor = '_' : ctor
112− in [ JSVariableIntroduction _ctor (Just (makeConstructor (length tys)))
112+ in [ makeConstructor _ctor (length tys)
113113 , JSVariableIntroduction ctor (Just (go pn 0 (length tys) []))
114114 ]
115115 where
116− makeConstructor :: Int -> JS
117− makeConstructor n =
116+ makeConstructor :: String -> Int -> JS
117+ makeConstructor ctorName n =
118118 let
119119 args = [ "value" ++ show index | index <- [0..n-1] ]
120120 body = [ JSAssignment (JSAccessor arg (JSVar "this")) (JSVar arg) | arg <- args ]
121− in JSFunction Nothing args (JSBlock body)
121+ in JSFunction (Just ctorName) args (JSBlock body)
122122 go :: ProperName -> Int -> Int -> [JS] -> JS
123123 go pn _ 0 values = JSApp (JSNew (JSVar ('_' : runProperName pn))) (reverse values)
124124 go pn index n values =
@@ -127,6 +127,27 @@ declToJs _ _ (DataDeclaration _ _ ctors) _ = do
127127declToJs opts mp (DataBindingGroupDeclaration ds) e = do
128128 jss <- mapM (\decl -> declToJs opts mp decl e) ds
129129 return $ Just $ concat $ catMaybes jss
130+declToJs _ _ (TypeClassDeclaration name _ supers members) _ =
131+ return $ Just $ [
132+ JSFunction (Just $ runProperName name) (identToJs `map` args)
133+ (JSBlock $ assn `map` args)]
134+ where
135+ assn :: Ident -> JS
136+ assn arg = JSAssignment (accessor arg (JSVar "this")) (var arg)
137+ args :: [Ident]
138+ args = sortBy (compare `on` runIdent) $ memberNames ++ superNames
139+ memberNames :: [Ident]
140+ memberNames = memberToName `map` members
141+ superNames :: [Ident]
142+ superNames = [ toSuperName superclass index
143+ | (index, (superclass, _)) <- zip [0..] supers
144+ ]
145+ toSuperName :: Qualified ProperName -> Integer -> Ident
146+ toSuperName pn index = Ident $ C.__superclass_ ++ show pn ++ "_" ++ show index
147+ memberToName :: Declaration -> Ident
148+ memberToName (TypeDeclaration ident _) = ident
149+ memberToName (PositionedDeclaration _ d) = memberToName d
150+ memberToName _ = error "Invalid declaration in type class definition"
130151declToJs _ _ (ExternDeclaration _ _ (Just js) _) _ = return $ Just [js]
131152declToJs opts mp (PositionedDeclaration _ d) e = declToJs opts mp d e
132153declToJs _ _ _ _ = return Nothing
@@ -138,6 +159,7 @@ exportToJs :: DeclarationRef -> [(String, JS)]
138159exportToJs (TypeRef _ (Just dctors)) = concatMap ((\n -> [('_' : n, var (Ident ('_' : n))), (n, var (Ident n))]) . runProperName) dctors
139160exportToJs (ValueRef name) = [(runIdent name, var name)]
140161exportToJs (TypeInstanceRef name) = [(runIdent name, var name)]
162+exportToJs (TypeClassRef name) = [(runProperName name, var $ Ident $ runProperName name)]
141163exportToJs _ = []
142164
143165-- |
@@ -169,6 +191,10 @@ valueToJs _ _ _ (StringLiteral s) = return $ JSStringLiteral s
169191valueToJs _ _ _ (BooleanLiteral b) = return $ JSBooleanLiteral b
170192valueToJs opts m e (ArrayLiteral xs) = JSArrayLiteral <$> mapM (valueToJs opts m e) xs
171193valueToJs opts m e (ObjectLiteral ps) = JSObjectLiteral <$> mapM (sndM (valueToJs opts m e)) ps
194+valueToJs opts m e (TypeClassDictionaryConstructorApp name (TypedValue _ (ObjectLiteral ps) _)) =
195+ JSApp (JSNew (qualifiedToJS m (Ident . runProperName) name)) <$> mapM (valueToJs opts m e . snd) (sortBy (compare `on` fst) ps)
196+valueToJs _ _ _ TypeClassDictionaryConstructorApp{} =
197+ error "TypeClassDictionaryConstructorApp did not contain object literal"
172198valueToJs opts m e (ObjectUpdate o ps) = do
173199 obj <- valueToJs opts m e o
174200 sts <- mapM (sndM (valueToJs opts m e)) ps