@@ -1,13 +1,12 @@
1module Generate.JavaScript where
1module Generate.JavaScript where
3−import Control.Monad (liftM,(<=<),join,ap)
3+import Control.Applicative ((<$>))
4import Data.Char (isAlpha,isDigit)
4import Data.Char (isAlpha,isDigit)
5import qualified Data.List as List
5import qualified Data.List as List
6import qualified Data.Map as Map
6import qualified Data.Map as Map
7import qualified Data.Set as Set
7import qualified Data.Set as Set
8import Data.Either (partitionEithers)
8import Data.Either (partitionEithers)
11import Unique
10import Unique
12import Generate.Cases
11import Generate.Cases
13import SourceSyntax.Everything
12import SourceSyntax.Everything
@@ -19,7 +18,9 @@ import Parse.Helpers (makeSafe, iParse)
20import Parse.Expression
19import Parse.Expression
21+testExpr str = case iParse expr "" str of
22−testExpr str = (prettyPrint . expression) `fmap` iParse expr "" str
22+ Right e -> prettyPrint (expression e)
23+ Left err -> error (show err)
24var name = Id () (makeSafe name)
25var name = Id () (makeSafe name)
25ref name = VarRef () (var name)
26ref name = VarRef () (var name)
@@ -65,14 +66,12 @@ expression (L span expr) =
65 Access e x -> DotRef () (expression e) (var x)
66 Access e x -> DotRef () (expression e) (var x)
66 Remove e x -> dotSep ["_N","remove"] `call` [ref x, expression e]
67 Remove e x -> dotSep ["_N","remove"] `call` [ref x, expression e]
67 Insert e x v -> dotSep ["_N","insert"] `call` [ref x, expression v, expression e]
68 Insert e x v -> dotSep ["_N","insert"] `call` [ref x, expression v, expression e]
70+ let modify (f,v) = ArrayLit () [ref f, expression e]
71+ in dotSep ["_N","replace"] `call` [ArrayLit () (map modify fs), expression e]
69− Modify e fs -> do fs' <- (mapM (\(x,v) -> (,) x `liftM` toJS' v) fs)
70− setField fs' `liftM` toJS' e
71 Record fs -> makeRecord fs
74 Record fs -> makeRecord fs
73−addField x v e = "_N.insert('" ++ x ++ "', " ++ v ++ ", " ++ e ++ ")"
74−setField fs e = "_N.replace(" ++ jsList (map f fs) ++ ", " ++ e ++ ")"
75− where f (x,v) = "['" ++ x ++ "'," ++ v ++ "]"
76makeRecord kvs = record `liftM` collect kvs
75makeRecord kvs = record `liftM` collect kvs
78 combine r (k,v) = Map.insertWith (++) k v r
77 combine r (k,v) = Map.insertWith (++) k v r
@@ -96,7 +95,7 @@ makeRecord kvs = record `liftM` collect kvs
96 | otherwise =
95 | otherwise =
97 ref ("F" ++ show (length args)) <| (args ==> expression body)
96 ref ("F" ++ show (length args)) <| (args ==> expression body)
99− (args, body) = foldr depattern ([], innerBody) (zip patterns [1..])
98+ (args, body) = foldr depattern ([], innerBody) (zip patterns [0..])
101 depattern (pattern,n) (args, body) =
100 depattern (pattern,n) (args, body) =
102 case pattern of
101 case pattern of
@@ -110,7 +109,7 @@ makeRecord kvs = record `liftM` collect kvs
110 case expr of
109 case expr of
111 Lambda p e -> collect (p:patterns) e
110 Lambda p e -> collect (p:patterns) e
112 _ -> (patterns, lexpr)
111 _ -> (patterns, lexpr)
114 App e1 e2 ->
113 App e1 e2 ->
115 case args of
114 case args of
116 [arg] -> func <| arg
115 [arg] -> func <| arg
@@ -122,9 +121,11 @@ makeRecord kvs = record `liftM` collect kvs
122 case func of
121 case func of
123 (L _ (App f arg)) -> getArgs f (arg : args)
122 (L _ (App f arg)) -> getArgs f (arg : args)
124 _ -> (expression func, map expression args)
123 _ -> (expression func, map expression args)
125+ Let defs e -> FuncExpr () Nothing [] stmts `call` []
126− Let defs e -> jsLet $ SD.flattenLets defs e
127+ (defs',e') = SD.flattenLets defs e
127−--}
128+ stmts = map definition defs' ++ [ ReturnStmt () (Just (expression e')) ]
129 MultiIf branches ->
130 MultiIf branches ->
130 case last branches of
131 case last branches of
@@ -148,6 +149,50 @@ makeRecord kvs = record `liftM` collect kvs
148 md = formatMarkdown $ Pan.writeHtmlString Pan.def doc
149 md = formatMarkdown $ Pan.writeHtmlString Pan.def doc
154+ TypeAnnotation _ _ -> EmptyStmt ()
155+ Def pattern expr@(L span _) ->
156+ let assign x = VarDecl () (var x) (Just (expression expr)) in
160+ let op = LBracket () (ref "_op") (string x) in
161+ ExprStmt () (AssignExpr () OpAssign op (expression expr))
163+ VarDeclStmt () [ assign x ]
165+ PRecord fields -> VarDeclStmt () (assign "$" : map setField fields)
167+ setField f = VarDecl () (var f) (Just (dotSep ["$",f]))
169+ PData name patterns | vars /= Nothing ->
171+ Just vs -> VarDeclStmt () (setup (zipWith varDecl vs [0..]))
173+ vars = getVars patterns
176+ PVar x : rest -> (x:) <$> getVars rest
180+ varDecl x n = VarDecl () (var x) (Just (dotSep ["$","_" ++ show n]))
182+ | isTuple name = assign "$" : vars
183+ | otherwise = safeAssign : vars
185+ safeAssign = VarDecl () (var "$") (Just $ CondExpr () if' (expression expr) exception)
186+ if' = InfixExpr () OpStrictEq (dotSep ["$","ctor"]) (string name)
187+ exception = dotSep ["_E","Case"] `call` [ref "$moduleName", string (show span)]
189+ _ -> BlockStmt () ( VarDeclStmt () [assign "$"] : map toDef vars )
191+ vars = Set.toList $ SD.boundVars pattern
192+ mkVar = L span . Var
193+ toDef y = definition $
194+ Def (PVar y) (L span $ Case (mkVar "$") [(pattern, mkVar y)])
153globalAssign n e = "\n" ++ assign' n e ++ ";"
198globalAssign n e = "\n" ++ assign' n e ++ ";"
@@ -216,50 +261,12 @@ jsImport (modul, method) =
216 [] -> (reverse name, [])
261 [] -> (reverse name, [])
220− toJS :: a -> Unique String
223−instance ToJS (Def t v) where
225− -- TODO: Make this handle patterns besides plain variables
226− toJS (Def (PVar x) e)
227− | isOp x = globalAssign ("_op['" ++ x ++ "']") `liftM` toJS' e
228− | otherwise = assign x `liftM` toJS' e
230− toJS (Def pattern e@(L s _)) =
232− let x = "_" ++ show n
234− toDef y = Def (PVar y) (L s $ Case (var x) [(pattern, var y)])
235− stmt <- assign x `liftM` toJS' e
236− vars <- toJS . map toDef . Set.toList $ SD.boundVars pattern
237− return (stmt ++ vars)
239− toJS (TypeAnnotation _ _) = return ""
242−instance ToJS a => ToJS [a] where
243− toJS xs = concat `liftM` mapM toJS xs
245−toJS' :: LExpr t v -> Unique String
246−toJS' (L span expr) =
248− Case e cases -> caseToJS span e cases
253formatMarkdown = concatMap f
264formatMarkdown = concatMap f
254 where f '\'' = "\\'"
265 where f '\'' = "\\'"
255 f '\n' = "\\n"
266 f '\n' = "\\n"
256 f '"' = "\""
267 f '"' = "\""
257 f c = [c]
268 f c = [c]
259−jsLet (defs,e') = do ds <- mapM toJS defs
261− return $ jsFunc "" (concat ds ++ ret e) ++ "()"
263caseToJS span e ps = do
270caseToJS span e ps = do
264 (tempVar,match) <- caseToMatch ps
271 (tempVar,match) <- caseToMatch ps
265 e' <- toJS' e
272 e' <- toJS' e
@@ -303,9 +310,6 @@ clauseToJS span var (Clause value vars e) = do
303 is -> drop (last is + 1) name
310 is -> drop (last is + 1) name
304 return $ concat [ "\ncase ", pattern, ":", indent s ]
311 return $ concat [ "\ncase ", pattern, ":", indent s ]
306−jsCons e1 e2 = "_L.Cons(" ++ e1 ++ "," ++ e2 ++ ")"
307−jsCompare e1 e2 op = parens ("_N.cmp(" ++ e1 ++ "," ++ e2 ++ ")" ++ op)
310binop span op e1 e2 =
314binop span op e1 e2 =
311 case op of
315 case op of
@@ -358,5 +362,4 @@ binop span op e1 e2 =
358 , specialOp "div" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
362 , specialOp "div" $ \a b -> InfixExpr () OpBOr (InfixExpr () OpDiv a b) (IntLit () 0)
361− cmp op n a b = InfixExpr () op (dotSep ["_N","cmp"] `call` [a,b]) (IntLit () n)
365+ cmp op n a b = InfixExpr () op (dotSep ["_N","cmp"] `call` [a,b]) (IntLit () n)