@@ -41,6 +41,7 @@ import Language.PureScript.Options
41import Language.PureScript.CodeGen.JS.AST as AST
41import Language.PureScript.CodeGen.JS.AST as AST
42import Language.PureScript.Types
42import Language.PureScript.Types
43import Language.PureScript.CodeGen.Optimize
43import Language.PureScript.CodeGen.Optimize
44+import Language.PureScript.CodeGen.Common (identToJs)
44import Language.PureScript.TypeChecker.Monad (canonicalizeDataConstructor)
45import Language.PureScript.TypeChecker.Monad (canonicalizeDataConstructor)
@@ -48,11 +49,11 @@ import Language.PureScript.TypeChecker.Monad (canonicalizeDataConstructor)
49moduleToJs :: Options -> Module -> Environment -> [JS]
50moduleToJs :: Options -> Module -> Environment -> [JS]
50moduleToJs opts (Module pname@(ProperName name) decls) env =
51moduleToJs opts (Module pname@(ProperName name) decls) env =
51− [ JSVariableIntroduction (Ident name) Nothing
52+ [ JSVariableIntroduction name Nothing
52− , JSApp (JSFunction Nothing [Ident name]
53+ , JSApp (JSFunction Nothing [name]
53 (JSBlock (concat $ mapMaybe (\decl -> fmap (map $ optimize opts) $ declToJs opts (ModuleName pname) decl env) (sortBy typeClassesLast decls))))
54 (JSBlock (concat $ mapMaybe (\decl -> fmap (map $ optimize opts) $ declToJs opts (ModuleName pname) decl env) (sortBy typeClassesLast decls))))
54− [JSAssignment (JSAssignVariable (Ident name))
55+ [JSAssignment (JSAssignVariable name)
55− (JSBinary Or (JSVar (Ident name)) (JSObjectLiteral []))]
56+ (JSBinary Or (JSVar name) (JSObjectLiteral []))]
58 typeClassesLast (ExternDeclaration TypeClassDictionaryImport _ _ _) (ExternDeclaration TypeClassDictionaryImport _ _ _) = EQ
59 typeClassesLast (ExternDeclaration TypeClassDictionaryImport _ _ _) (ExternDeclaration TypeClassDictionaryImport _ _ _) = EQ
@@ -65,33 +66,36 @@ moduleToJs opts (Module pname@(ProperName name) decls) env =
66declToJs :: Options -> ModuleName -> Declaration -> Environment -> Maybe [JS]
67declToJs :: Options -> ModuleName -> Declaration -> Environment -> Maybe [JS]
67declToJs opts mp (ValueDeclaration ident _ _ val) e =
68declToJs opts mp (ValueDeclaration ident _ _ val) e =
68− Just [ JSVariableIntroduction ident (Just (valueToJs opts mp e val)),
69+ Just [ JSVariableIntroduction (identToJs ident) (Just (valueToJs opts mp e val)),
69− setProperty (identToJs ident) (JSVar ident) mp ]
70+ setProperty (identToJs ident) (var ident) mp ]
70declToJs opts mp (BindingGroupDeclaration vals) e =
71declToJs opts mp (BindingGroupDeclaration vals) e =
71 Just $ concatMap (\(ident, val) ->
72 Just $ concatMap (\(ident, val) ->
72− [ JSVariableIntroduction ident (Just (valueToJs opts mp e val)),
73+ [ JSVariableIntroduction (identToJs ident) (Just (valueToJs opts mp e val)),
73− setProperty (identToJs ident) (JSVar ident) mp ]
74+ setProperty (identToJs ident) (var ident) mp ]
75declToJs _ mp (DataDeclaration _ _ ctors) _ =
76declToJs _ mp (DataDeclaration _ _ ctors) _ =
76 Just $ flip concatMap ctors $ \(pn@(ProperName ctor), maybeTy) ->
77 Just $ flip concatMap ctors $ \(pn@(ProperName ctor), maybeTy) ->
79 case maybeTy of
80 case maybeTy of
80− Nothing -> JSVariableIntroduction (Ident ctor) (Just (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn))) ]))
81+ Nothing -> JSVariableIntroduction ctor (Just (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn))) ]))
81− Just _ -> JSFunction (Just (Ident ctor)) [Ident "value"]
82+ Just _ -> JSFunction (Just ctor) ["value"]
82 (JSBlock [JSReturn
83 (JSBlock [JSReturn
83 (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn)))
84 (JSObjectLiteral [ ("ctor", JSStringLiteral (show (Qualified (Just mp) pn)))
84− , ("value", JSVar (Ident "value")) ])])
85+ , ("value", JSVar "value") ])])
85− in [ ctorJs, setProperty ctor (JSVar (Ident ctor)) mp ]
86+ in [ ctorJs, setProperty ctor (JSVar ctor) mp ]
86declToJs opts mp (DataBindingGroupDeclaration ds) e =
87declToJs opts mp (DataBindingGroupDeclaration ds) e =
87 Just $ concat $ mapMaybe (flip (declToJs opts mp) e) ds
88 Just $ concat $ mapMaybe (flip (declToJs opts mp) e) ds
88declToJs _ mp (ExternDeclaration importTy ident (Just js) _) _ =
89declToJs _ mp (ExternDeclaration importTy ident (Just js) _) _ =
90− , setProperty (identToJs ident) (JSVar ident) mp ]
91+ , setProperty (identToJs ident) (var ident) mp ]
91declToJs _ _ _ _ = Nothing
92declToJs _ _ _ _ = Nothing
93setProperty :: String -> JS -> ModuleName -> JS
94setProperty :: 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
98+var name = JSVar $ identToJs name
96valueToJs :: Options -> ModuleName -> Environment -> Value -> JS
100valueToJs :: Options -> ModuleName -> Environment -> Value -> JS
97valueToJs _ _ _ (NumericLiteral n) = JSNumericLiteral n
101valueToJs _ _ _ (NumericLiteral n) = JSNumericLiteral n
@@ -99,11 +103,11 @@ valueToJs _ _ _ (StringLiteral s) = JSStringLiteral s
99valueToJs _ _ _ (BooleanLiteral b) = JSBooleanLiteral b
103valueToJs _ _ _ (BooleanLiteral b) = JSBooleanLiteral b
100valueToJs opts m e (ArrayLiteral xs) = JSArrayLiteral (map (valueToJs opts m e) xs)
104valueToJs opts m e (ArrayLiteral xs) = JSArrayLiteral (map (valueToJs opts m e) xs)
101valueToJs opts m e (ObjectLiteral ps) = JSObjectLiteral (map (second (valueToJs opts m e)) ps)
105valueToJs 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)]
103valueToJs _ m e (Constructor (Qualified Nothing name)) =
107valueToJs _ m e (Constructor (Qualified Nothing name)) =
104 case M.lookup (m, name) (dataConstructors e) of
108 case M.lookup (m, name) (dataConstructors e) of
105 Just (_, Alias aliasModule aliasIdent) -> qualifiedToJS identToJs (Qualified (Just aliasModule) aliasIdent)
109 Just (_, Alias aliasModule aliasIdent) -> qualifiedToJS identToJs (Qualified (Just aliasModule) aliasIdent)
106− _ -> JSVar . Ident . runProperName $ name
110+ _ -> JSVar . runProperName $ name
107valueToJs _ _ _ (Constructor name) = qualifiedToJS runProperName name
111valueToJs _ _ _ (Constructor name) = qualifiedToJS runProperName name
108valueToJs opts m e (Block sts) = JSApp (JSFunction Nothing [] (JSBlock (map (statementToJs opts m e) sts))) []
112valueToJs opts m e (Block sts) = JSApp (JSFunction Nothing [] (JSBlock (map (statementToJs opts m e) sts))) []
109valueToJs opts m e (Case values binders) = bindersToJs opts m e binders (map (valueToJs opts m e) values)
113valueToJs 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
111valueToJs opts m e (Accessor prop val) = JSAccessor prop (valueToJs opts m e val)
115valueToJs opts m e (Accessor prop val) = JSAccessor prop (valueToJs opts m e val)
112valueToJs opts m e (Indexer index val) = JSIndexer (valueToJs opts m e index) (valueToJs opts m e val)
116valueToJs opts m e (Indexer index val) = JSIndexer (valueToJs opts m e index) (valueToJs opts m e val)
113valueToJs opts m e (App val arg) = JSApp (valueToJs opts m e val) [valueToJs opts m e arg]
117valueToJs 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)])
118+valueToJs opts m e (Abs arg val) = JSFunction Nothing [identToJs 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)])
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)])
116valueToJs opts m e (Unary op val) = JSUnary op (valueToJs opts m e val)
120valueToJs opts m e (Unary op val) = JSUnary op (valueToJs opts m e val)
117valueToJs opts m e (Binary op v1 v2) = JSBinary op (valueToJs opts m e v1) (valueToJs opts m e v2)
121valueToJs opts m e (Binary op v1 v2) = JSBinary op (valueToJs opts m e v1) (valueToJs opts m e v2)
118valueToJs _ m e (Var ident) = varToJs m e ident
122valueToJs _ m e (Var ident) = varToJs m e ident
@@ -120,7 +124,7 @@ valueToJs opts m e (TypedValue _ val _) = valueToJs opts m e val
120valueToJs _ _ _ (TypeClassDictionary _ _) = error "Type class dictionary was not replaced"
124valueToJs _ _ _ (TypeClassDictionary _ _) = error "Type class dictionary was not replaced"
121valueToJs _ _ _ _ = error "Invalid argument to valueToJs"
125valueToJs _ _ _ _ = error "Invalid argument to valueToJs"
123−runtimeTypeChecks :: Ident -> Type -> [JS]
127+runtimeTypeChecks :: String -> Type -> [JS]
124runtimeTypeChecks arg ty =
128runtimeTypeChecks arg ty =
126 argTy = getFunctionArgumentType ty
130 argTy = getFunctionArgumentType ty
@@ -147,14 +151,14 @@ runtimeTypeChecks arg ty =
147 typeCheck :: JS -> String -> JS
151 typeCheck :: JS -> String -> JS
148 typeCheck js ty' = JSIfElse (JSBinary NotEqualTo (JSTypeOf js) (JSStringLiteral ty')) (JSBlock [JSThrow (JSStringLiteral $ ty' ++ " expected")]) Nothing
152 typeCheck js ty' = JSIfElse (JSBinary NotEqualTo (JSTypeOf js) (JSStringLiteral ty')) (JSBlock [JSThrow (JSStringLiteral $ ty' ++ " expected")]) Nothing
149 arrayCheck :: JS -> JS
153 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
152varToJs :: ModuleName -> Environment -> Qualified Ident -> JS
156varToJs :: ModuleName -> Environment -> Qualified Ident -> JS
153varToJs m e qual@(Qualified _ ident) = case M.lookup (qualify m qual) (names e) of
157varToJs 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
155 Just (_, Alias aliasModule aliasIdent) -> qualifiedToJS identToJs (Qualified (Just aliasModule) aliasIdent)
159 Just (_, Alias aliasModule aliasIdent) -> qualifiedToJS identToJs (Qualified (Just aliasModule) aliasIdent)
156 _ -> case qual of
160 _ -> case qual of
157− Qualified Nothing _ -> JSVar ident
161+ Qualified Nothing _ -> var ident
158 _ -> qualifiedToJS identToJs qual
162 _ -> qualifiedToJS identToJs qual
160 isExtern (Extern ForeignImport) = True
164 isExtern (Extern ForeignImport) = True
@@ -164,17 +168,17 @@ varToJs m e qual@(Qualified _ ident) = case M.lookup (qualify m qual) (names e)
164 isExtern _ = False
168 isExtern _ = False
166qualifiedToJS :: (a -> String) -> Qualified a -> JS
170qualifiedToJS :: (a -> String) -> Qualified a -> JS
167−qualifiedToJS f (Qualified (Just (ModuleName (ProperName m))) a) = JSAccessor (f a) (JSVar (Ident m))
171+qualifiedToJS f (Qualified (Just (ModuleName (ProperName m))) a) = JSAccessor (f a) (JSVar m)
168−qualifiedToJS f (Qualified Nothing a) = JSVar (Ident (f a))
172+qualifiedToJS f (Qualified Nothing a) = JSVar (f a)
170bindersToJs :: Options -> ModuleName -> Environment -> [([Binder], Maybe Guard, Value)] -> [JS] -> JS
174bindersToJs :: 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
172 valNames <- replicateM (length vals) fresh
176 valNames <- replicateM (length vals) fresh
173 jss <- forM binders $ \(bs, grd, result) -> go valNames [JSReturn (valueToJs opts m e result)] bs grd
177 jss <- forM binders $ \(bs, grd, result) -> go valNames [JSReturn (valueToJs opts m e result)] bs grd
174 return $ JSApp (JSFunction Nothing valNames (JSBlock (concat jss ++ [JSThrow (JSStringLiteral "Failed pattern match")])))
178 return $ JSApp (JSFunction Nothing valNames (JSBlock (concat jss ++ [JSThrow (JSStringLiteral "Failed pattern match")])))
177− go :: [Ident] -> [JS] -> [Binder] -> Maybe Guard -> Gen [JS]
181+ go :: [String] -> [JS] -> [Binder] -> Maybe Guard -> Gen [JS]
178 go _ done [] Nothing = return done
182 go _ done [] Nothing = return done
179 go _ done [] (Just cond) = return [JSIfElse (valueToJs opts m e cond) (JSBlock done) Nothing]
183 go _ done [] (Just cond) = return [JSIfElse (valueToJs opts m e cond) (JSBlock done) Nothing]
180 go (v:vs) done' (b:bs) grd = do
184 go (v:vs) done' (b:bs) grd = do
@@ -182,7 +186,7 @@ bindersToJs opts m e binders vals = runGen (unusedNames (binders, vals)) $ do
182 binderToJs m e v done'' b
186 binderToJs m e v done'' b
183 go _ _ _ _ = error "Invalid arguments to bindersToJs"
187 go _ _ _ _ = error "Invalid arguments to bindersToJs"
185−binderToJs :: ModuleName -> Environment -> Ident -> [JS] -> Binder -> Gen [JS]
189+binderToJs :: ModuleName -> Environment -> String -> [JS] -> Binder -> Gen [JS]
186binderToJs _ _ _ done NullBinder = return done
190binderToJs _ _ _ done NullBinder = return done
187binderToJs _ _ varName done (StringBinder str) =
191binderToJs _ _ varName done (StringBinder str) =
188 return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSStringLiteral str)) (JSBlock done) Nothing]
192 return [JSIfElse (JSBinary EqualTo (JSVar varName) (JSStringLiteral str)) (JSBlock done) Nothing]
@@ -193,7 +197,7 @@ binderToJs _ _ varName done (BooleanBinder True) =
193binderToJs _ _ varName done (BooleanBinder False) =
197binderToJs _ _ varName done (BooleanBinder False) =
194 return [JSIfElse (JSUnary Not (JSVar varName)) (JSBlock done) Nothing]
198 return [JSIfElse (JSUnary Not (JSVar varName)) (JSBlock done) Nothing]
195binderToJs _ _ varName done (VarBinder ident) =
199binderToJs _ _ varName done (VarBinder ident) =
196− return (JSVariableIntroduction ident (Just (JSVar varName)) : done)
200+ return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : done)
197binderToJs m e varName done (NullaryBinder ctor) =
201binderToJs m e varName done (NullaryBinder ctor) =
198 if isOnlyConstructor m e ctor
202 if isOnlyConstructor m e ctor
@@ -243,7 +247,7 @@ binderToJs m e varName done (ConsBinder headBinder tailBinder) = do
243 )) Nothing]
247 )) Nothing]
244binderToJs m e varName done (NamedBinder ident binder) = do
248binderToJs m e varName done (NamedBinder ident binder) = do
245 js <- binderToJs m e varName done binder
249 js <- binderToJs m e varName done binder
246− return (JSVariableIntroduction ident (Just (JSVar varName)) : js)
250+ return (JSVariableIntroduction (identToJs ident) (Just (JSVar varName)) : js)
248isOnlyConstructor :: ModuleName -> Environment -> Qualified ProperName -> Bool
252isOnlyConstructor :: ModuleName -> Environment -> Qualified ProperName -> Bool
249isOnlyConstructor m e ctor =
253isOnlyConstructor m e ctor =
@@ -258,10 +262,10 @@ isOnlyConstructor m e ctor =
258 typeConstructor fn = error $ "Invalid arguments to typeConstructor: " ++ show fn
262 typeConstructor fn = error $ "Invalid arguments to typeConstructor: " ++ show fn
260statementToJs :: Options -> ModuleName -> Environment -> Statement -> JS
264statementToJs :: Options -> ModuleName -> Environment -> Statement -> JS
261−statementToJs opts m e (VariableIntroduction ident value) = JSVariableIntroduction ident (Just (valueToJs opts m e value))
265+statementToJs opts m e (VariableIntroduction ident value) = JSVariableIntroduction (identToJs ident) (Just (valueToJs opts m e value))
262−statementToJs opts m e (Assignment target value) = JSAssignment (JSAssignVariable target) (valueToJs opts m e value)
266+statementToJs opts m e (Assignment target value) = JSAssignment (JSAssignVariable (identToJs target)) (valueToJs opts m e value)
263statementToJs opts m e (While cond sts) = JSWhile (valueToJs opts m e cond) (JSBlock (map (statementToJs opts m e) sts))
267statementToJs 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))
265statementToJs opts m e (If ifst) = ifToJs ifst
269statementToJs opts m e (If ifst) = ifToJs ifst
267 ifToJs :: IfStatement -> JS
271 ifToJs :: IfStatement -> JS