@@ -41,6 +41,7 @@ import Language.PureScript.Options
4141import Language.PureScript.CodeGen.JS.AST as AST
4242import Language.PureScript.Types
4343import Language.PureScript.CodeGen.Optimize
44+import Language.PureScript.CodeGen.Common (identToJs)
4445import Language.PureScript.TypeChecker.Monad (canonicalizeDataConstructor)
4546
4647-- |
@@ -48,11 +49,11 @@ import Language.PureScript.TypeChecker.Monad (canonicalizeDataConstructor)
4849--
4950moduleToJs :: Options -> Module -> Environment -> [JS]
5051moduleToJs opts (Module pname@(ProperName name) decls) env =
51− [ JSVariableIntroduction (Ident name) Nothing
52− , JSApp (JSFunction Nothing [Ident name]
52+ [ JSVariableIntroduction name Nothing
53+ , JSApp (JSFunction Nothing [name]
5354 (JSBlock (concat $ mapMaybe (\decl -> fmap (map $ optimize opts) $ declToJs opts (ModuleName pname) decl env) (sortBy typeClassesLast decls))))
54− [JSAssignment (JSAssignVariable (Ident name))
55− (JSBinary Or (JSVar (Ident name)) (JSObjectLiteral []))]
55+ [JSAssignment (JSAssignVariable name)
56+ (JSBinary Or (JSVar name) (JSObjectLiteral []))]
5657 ]
5758 where
5859 typeClassesLast (ExternDeclaration TypeClassDictionaryImport _ _ _) (ExternDeclaration TypeClassDictionaryImport _ _ _) = EQ
@@ -65,33 +66,36 @@ moduleToJs opts (Module pname@(ProperName name) decls) env =
6566--
6667declToJs :: Options -> ModuleName -> Declaration -> Environment -> Maybe [JS]
6768declToJs opts mp (ValueDeclaration ident _ _ val) e =
68− Just [ JSVariableIntroduction ident (Just (valueToJs opts mp e val)),
69− setProperty (identToJs ident) (JSVar ident) mp ]
69+ Just [ JSVariableIntroduction (identToJs ident) (Just (valueToJs opts mp e val)),
70+ setProperty (identToJs ident) (var ident) mp ]
7071declToJs opts mp (BindingGroupDeclaration vals) e =
7172 Just $ concatMap (\(ident, val) ->
72− [ JSVariableIntroduction ident (Just (valueToJs opts mp e val)),
73− setProperty (identToJs ident) (JSVar ident) mp ]
73+ [ JSVariableIntroduction (identToJs ident) (Just (valueToJs opts mp e val)),
74+ setProperty (identToJs ident) (var ident) mp ]
7475 ) vals
7576declToJs _ mp (DataDeclaration _ _ ctors) _ =
7677 Just $ flip concatMap ctors $ \(pn@(ProperName ctor), maybeTy) ->
7778 let
7879 ctorJs =
7980 case maybeTy of
80− Nothing -> JSVariableIntroduction (Ident ctor) (Just (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn))) ]))
81− Just _ -> JSFunction (Just (Ident ctor)) [Ident "value"]
81+ Nothing -> JSVariableIntroduction ctor (Just (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn))) ]))
82+ Just _ -> JSFunction (Just ctor) ["value"]
8283 (JSBlock [JSReturn
8384 (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn)))
84− , ("value", JSVar (Ident "value")) ])])
85− in [ ctorJs, setProperty ctor (JSVar (Ident ctor)) mp ]
85+ , ("value", JSVar "value") ])])
86+ in [ ctorJs, setProperty ctor (JSVar ctor) mp ]
8687declToJs opts mp (DataBindingGroupDeclaration ds) e =
8788 Just $ concat $ mapMaybe (flip (declToJs opts mp) e) ds
8889declToJs _ mp (ExternDeclaration importTy ident (Just js) _) _ =
8990 Just [ js
90− , setProperty (identToJs ident) (JSVar ident) mp ]
91+ , setProperty (identToJs ident) (var ident) mp ]
9192declToJs _ _ _ _ = Nothing
9293
9394setProperty :: String -> JS -> ModuleName -> JS
94−setProperty prop val (ModuleName (ProperName moduleName)) = JSAssignment (JSAssignProperty prop (JSAssignVariable (Ident moduleName))) val
95+setProperty prop val (ModuleName (ProperName moduleName)) = JSAssignment (JSAssignProperty prop (JSAssignVariable moduleName)) val
96+
97+var :: Ident -> JS
98+var name = JSVar $ identToJs name
9599
96100valueToJs :: Options -> ModuleName -> Environment -> Value -> JS
97101valueToJs _ _ _ (NumericLiteral n) = JSNumericLiteral n
@@ -99,11 +103,11 @@ valueToJs _ _ _ (StringLiteral s) = JSStringLiteral s
99103valueToJs _ _ _ (BooleanLiteral b) = JSBooleanLiteral b
100104valueToJs opts m e (ArrayLiteral xs) = JSArrayLiteral (map (valueToJs opts m e) xs)
101105valueToJs opts m e (ObjectLiteral ps) = JSObjectLiteral (map (second (valueToJs opts m e)) ps)
102−valueToJs opts m e (ObjectUpdate o ps) = JSApp (JSAccessor "extend" (JSVar (Ident "Object"))) [ valueToJs opts m e o, JSObjectLiteral (map (second (valueToJs opts m e)) ps)]
106+valueToJs opts m e (ObjectUpdate o ps) = JSApp (JSAccessor "extend" (JSVar "Object")) [ valueToJs opts m e o, JSObjectLiteral (map (second (valueToJs opts m e)) ps)]
103107valueToJs _ m e (Constructor (Qualified Nothing name)) =
104108 case M.lookup (m, name) (dataConstructors e) of
105109 Just (_, Alias aliasModule aliasIdent) -> qualifiedToJS identToJs (Qualified (Just aliasModule) aliasIdent)
106− _ -> JSVar . Ident . runProperName $ name
110+ _ -> JSVar . runProperName $ name
107111valueToJs _ _ _ (Constructor name) = qualifiedToJS runProperName name
108112valueToJs opts m e (Block sts) = JSApp (JSFunction Nothing [] (JSBlock (map (statementToJs opts m e) sts))) []
109113valueToJs opts m e (Case values binders) = bindersToJs opts m e binders (map (valueToJs opts m e) values)
@@ -111,8 +115,8 @@ valueToJs opts m e (IfThenElse cond th el) = JSConditional (valueToJs opts m e c
111115valueToJs opts m e (Accessor prop val) = JSAccessor prop (valueToJs opts m e val)
112116valueToJs opts m e (Indexer index val) = JSIndexer (valueToJs opts m e index) (valueToJs opts m e val)
113117valueToJs opts m e (App val arg) = JSApp (valueToJs opts m e val) [valueToJs opts m e arg]
114−valueToJs opts m e (Abs arg val) = JSFunction Nothing [arg] (JSBlock [JSReturn (valueToJs opts m e val)])
115−valueToJs opts m e (TypedValue _ (Abs arg val) ty) | optionsPerformRuntimeTypeChecks opts = JSFunction Nothing [arg] (JSBlock $ runtimeTypeChecks arg ty ++ [JSReturn (valueToJs opts m e val)])
118+valueToJs opts m e (Abs arg val) = JSFunction Nothing [identToJs arg] (JSBlock [JSReturn (valueToJs opts m e val)])
119+valueToJs opts m e (TypedValue _ (Abs arg val) ty) | optionsPerformRuntimeTypeChecks opts = let arg' = identToJs arg in JSFunction Nothing [arg'] (JSBlock $ runtimeTypeChecks arg' ty ++ [JSReturn (valueToJs opts m e val)])
116120valueToJs opts m e (Unary op val) = JSUnary op (valueToJs opts m e val)
117121valueToJs opts m e (Binary op v1 v2) = JSBinary op (valueToJs opts m e v1) (valueToJs opts m e v2)
118122valueToJs _ m e (Var ident) = varToJs m e ident
@@ -120,7 +124,7 @@ valueToJs opts m e (TypedValue _ val _) = valueToJs opts m e val
120124valueToJs _ _ _ (TypeClassDictionary _ _) = error "Type class dictionary was not replaced"
121125valueToJs _ _ _ _ = error "Invalid argument to valueToJs"
122126
123−runtimeTypeChecks :: Ident -> Type -> [JS]
127+runtimeTypeChecks :: String -> Type -> [JS]
124128runtimeTypeChecks arg ty =
125129 let
126130 argTy = getFunctionArgumentType ty
@@ -147,14 +151,14 @@ runtimeTypeChecks arg ty =
147151 typeCheck :: JS -> String -> JS
148152 typeCheck js ty' = JSIfElse (JSBinary NotEqualTo (JSTypeOf js) (JSStringLiteral ty')) (JSBlock [JSThrow (JSStringLiteral $ ty' ++ " expected")]) Nothing
149153 arrayCheck :: JS -> JS
150− arrayCheck js = JSIfElse (JSUnary Not (JSApp (JSAccessor "isArray" (JSVar (Ident "Array"))) [js])) (JSBlock [JSThrow (JSStringLiteral "Array expected")]) Nothing
154+ arrayCheck js = JSIfElse (JSUnary Not (JSApp (JSAccessor "isArray" (JSVar "Array")) [js])) (JSBlock [JSThrow (JSStringLiteral "Array expected")]) Nothing
151155
152156varToJs :: ModuleName -> Environment -> Qualified Ident -> JS
153157varToJs m e qual@(Qualified _ ident) = case M.lookup (qualify m qual) (names e) of
154− Just (_, ty) | isExtern ty -> JSVar ident
158+ Just (_, ty) | isExtern ty -> var ident
155159 Just (_, Alias aliasModule aliasIdent) -> qualifiedToJS identToJs (Qualified (Just aliasModule) aliasIdent)
156160 _ -> case qual of
157− Qualified Nothing _ -> JSVar ident
161+ Qualified Nothing _ -> var ident
158162 _ -> qualifiedToJS identToJs qual
159163 where
160164 isExtern (Extern ForeignImport) = True
@@ -164,17 +168,17 @@ varToJs m e qual@(Qualified _ ident) = case M.lookup (qualify m qual) (names e)
164168 isExtern _ = False
165169
166170qualifiedToJS :: (a -> String) -> Qualified a -> JS
167−qualifiedToJS f (Qualified (Just (ModuleName (ProperName m))) a) = JSAccessor (f a) (JSVar (Ident m))
168−qualifiedToJS f (Qualified Nothing a) = JSVar (Ident (f a))
171+qualifiedToJS f (Qualified (Just (ModuleName (ProperName m))) a) = JSAccessor (f a) (JSVar m)
172+qualifiedToJS f (Qualified Nothing a) = JSVar (f a)
169173
170174bindersToJs :: Options -> ModuleName -> Environment -> [([Binder], Maybe Guard, Value)] -> [JS] -> JS
171−bindersToJs opts m e binders vals = runGen (unusedNames (binders, vals)) $ do
175+bindersToJs opts m e binders vals = runGen (map identToJs (unusedNames (binders, vals))) $ do
172176 valNames <- replicateM (length vals) fresh
173177 jss <- forM binders $ \(bs, grd, result) -> go valNames [JSReturn (valueToJs opts m e result)] bs grd
174178 return $ JSApp (JSFunction Nothing valNames (JSBlock (concat jss ++ [JSThrow (JSStringLiteral "Failed pattern match")])))
175179 vals
176180 where
177− go :: [Ident] -> [JS] -> [Binder] -> Maybe Guard -> Gen [JS]
181+ go :: [String] -> [JS] -> [Binder] -> Maybe Guard -> Gen [JS]
178182 go _ done [] Nothing = return done
179183 go _ done [] (Just cond) = return [JSIfElse (valueToJs opts m e cond) (JSBlock done) Nothing]
180184 go (v:vs) done' (b:bs) grd = do
@@ -182,7 +186,7 @@ bindersToJs opts m e binders vals = runGen (unusedNames (binders, vals)) $ do
182186 binderToJs m e v done'' b
183187 go _ _ _ _ = error "Invalid arguments to bindersToJs"
184188
185−binderToJs :: ModuleName -> Environment -> Ident -> [JS] -> Binder -> Gen [JS]
189+binderToJs :: ModuleName -> Environment -> String -> [JS] -> Binder -> Gen [JS]
186190binderToJs _ _ _ done NullBinder = return done
187191binderToJs _ _ varName done (StringBinder str) =
188192 return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSStringLiteral str)) (JSBlock done) Nothing]
@@ -193,7 +197,7 @@ binderToJs _ _ varName done (BooleanBinder True) =
193197binderToJs _ _ varName done (BooleanBinder False) =
194198 return [JSIfElse (JSUnary Not (JSVar varName)) (JSBlock done) Nothing]
195199binderToJs _ _ varName done (VarBinder ident) =
196− return (JSVariableIntroduction ident (Just (JSVar varName)) : done)
200+ return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : done)
197201binderToJs m e varName done (NullaryBinder ctor) =
198202 if isOnlyConstructor m e ctor
199203 then
@@ -243,7 +247,7 @@ binderToJs m e varName done (ConsBinder headBinder tailBinder) = do
243247 )) Nothing]
244248binderToJs m e varName done (NamedBinder ident binder) = do
245249 js <- binderToJs m e varName done binder
246− return (JSVariableIntroduction ident (Just (JSVar varName)) : js)
250+ return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : js)
247251
248252isOnlyConstructor :: ModuleName -> Environment -> Qualified ProperName -> Bool
249253isOnlyConstructor m e ctor =
@@ -258,10 +262,10 @@ isOnlyConstructor m e ctor =
258262 typeConstructor fn = error $ "Invalid arguments to typeConstructor: " ++ show fn
259263
260264statementToJs :: Options -> ModuleName -> Environment -> Statement -> JS
261−statementToJs opts m e (VariableIntroduction ident value) = JSVariableIntroduction ident (Just (valueToJs opts m e value))
262−statementToJs opts m e (Assignment target value) = JSAssignment (JSAssignVariable target) (valueToJs opts m e value)
265+statementToJs opts m e (VariableIntroduction ident value) = JSVariableIntroduction (identToJs ident) (Just (valueToJs opts m e value))
266+statementToJs opts m e (Assignment target value) = JSAssignment (JSAssignVariable (identToJs target)) (valueToJs opts m e value)
263267statementToJs opts m e (While cond sts) = JSWhile (valueToJs opts m e cond) (JSBlock (map (statementToJs opts m e) sts))
264−statementToJs opts m e (For ident start end sts) = JSFor ident (valueToJs opts m e start) (valueToJs opts m e end) (JSBlock (map (statementToJs opts m e) sts))
268+statementToJs opts m e (For ident start end sts) = JSFor (identToJs ident) (valueToJs opts m e start) (valueToJs opts m e end) (JSBlock (map (statementToJs opts m e) sts))
265269statementToJs opts m e (If ifst) = ifToJs ifst
266270 where
267271 ifToJs :: IfStatement -> JS