@@ -1,13 +1,12 @@
1module Generate.JavaScript where
1module Generate.JavaScript where
3import Control.Applicative ((<$>))
3import Control.Applicative ((<$>))
4−import Data.Char (isAlpha,isDigit)
4+import Control.Arrow ((***))
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 Generate.Cases
10import Generate.Cases
12import SourceSyntax.Everything
11import SourceSyntax.Everything
13import SourceSyntax.Location
12import SourceSyntax.Location
@@ -19,7 +18,7 @@ import Parse.Helpers (makeSafe, iParse)
19import Parse.Expression
18import Parse.Expression
21testExpr str = case iParse expr "" str of
20testExpr str = case iParse expr "" str of
22− Right e -> prettyPrint (expression e)
21+ Right e -> prettyPrint (expression (e :: LExpr () ()))
23 Left err -> error (show err)
22 Left err -> error (show err)
25var name = Id () (makeSafe name)
24var name = Id () (makeSafe name)
@@ -57,6 +56,7 @@ literal lit =
57-- FloatNum n -> NumLit () (float2Double n) -- wrong!!!
56-- FloatNum n -> NumLit () (float2Double n) -- wrong!!!
58 Boolean b -> BoolLit () b
57 Boolean b -> BoolLit () b
59+expression :: LExpr () () -> Expression ()
60expression (L span expr) =
60expression (L span expr) =
61 case expr of
61 case expr of
62 Var x -> ref x
62 Var x -> ref x
@@ -70,21 +70,14 @@ expression (L span expr) =
70 let modify (f,v) = ArrayLit () [ref f, expression e]
70 let modify (f,v) = ArrayLit () [ref f, expression e]
71 in dotSep ["_N","replace"] `call` [ArrayLit () (map modify fs), expression e]
71 in dotSep ["_N","replace"] `call` [ArrayLit () (map modify fs), expression e]
73−{--
73+ Record fields -> ObjectLit () $ (PropId () (var "_"), hidden) : visible
74− Record fs -> makeRecord fs
75−makeRecord kvs = record `liftM` collect kvs
77− combine r (k,v) = Map.insertWith (++) k v r
75+ combine r (k,v) = Map.insertWith (++) k [v] r
78− collect = liftM (List.foldl' combine Map.empty) . mapM prep
76+ fieldMap = List.foldl' combine Map.empty fields
79− prep (k, e) =
77+ hidden = ObjectLit () . map ((PropId () . var) *** (ArrayLit () . map expression)) .
83− brackets ("\n "++List.intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
84− hidden = fields . map (second jsList) .
85− filter (not . null . snd) . Map.toList . Map.map tail
78+ Map.toList . Map.filter (not . null) $ Map.map tail fieldMap
86− record kvs = fields . (("_", hidden kvs) :) . Map.toList . Map.map head $ kvs
79+ visible = map ((PropId () . var) *** expression) . Map.toList $ Map.map head fieldMap
88 Binop op e1 e2 -> binop span op e1 e2
81 Binop op e1 e2 -> binop span op e1 e2
90 Lambda p e@(L s _) -> fastFunc
83 Lambda p e@(L s _) -> fastFunc
@@ -135,6 +128,15 @@ makeRecord kvs = record `liftM` collect kvs
135 ifs branches finally = foldr iff finally branches
128 ifs branches finally = foldr iff finally branches
136 iff (if', then') else' = CondExpr () (expression if') (expression then') else'
129 iff (if', then') else' = CondExpr () (expression if') (expression then') else'
131+ Case e cases -> FuncExpr () Nothing [] (stmt ++ match span revisedMatch) `call` []
133+ (tempVar,initialMatch) = caseToMatch cases
134+ (revisedMatch, stmt) =
136+ L _ (Var x) -> (matchSubst [(tempVar,x)] initialMatch, [])
137+ _ -> let decl = VarDecl () (var tempVar) (Just $ expression e)
138+ in (initialMatch, [VarDeclStmt () [decl]])
138 ExplicitList es ->
140 ExplicitList es ->
139 dotSep ["_J","toList"] <| ArrayLit () (map expression es)
141 dotSep ["_J","toList"] <| ArrayLit () (map expression es)
@@ -187,16 +189,47 @@ definition def =
187 exception = dotSep ["_E","Case"] `call` [ref "$moduleName", string (show span)]
189 exception = dotSep ["_E","Case"] `call` [ref "$moduleName", string (show span)]
189 _ -> BlockStmt () ( VarDeclStmt () [assign "$"] : map toDef vars )
191 _ -> BlockStmt () ( VarDeclStmt () [assign "$"] : map toDef vars )
191− vars = Set.toList $ SD.boundVars pattern
193+ vars = Set.toList $ SD.boundVars pattern
192− mkVar = L span . Var
194+ mkVar = L span . Var
193− toDef y = definition $
195+ toDef y = definition $
194 Def (PVar y) (L span $ Case (mkVar "$") [(pattern, mkVar y)])
196 Def (PVar y) (L span $ Case (mkVar "$") [(pattern, mkVar y)])
198−globalAssign n e = "\n" ++ assign' n e ++ ";"
199+match span mtch =
199−assign' n e = n ++ " = " ++ e
200+ case mtch of
201+ Match name clauses mtch' -> SwitchStmt () (access name) clauses' : match span mtch'
203+ clauses' = map (clause span name) clauses
204+ isLiteral p = case p of
205+ Clause (Right _) _ _ -> True
207+ access name = if any isLiteral clauses then ref name else dotSep [name,"ctor"]
209+ Fail -> [ ExprStmt () (dotSep ["_E","Case"] `call` [ref "$moduleName", string (show span)]) ]
211+ Other e -> [ ReturnStmt () (Just $ expression e) ]
212+ Seq ms -> concatMap (match span) (dropEnd [] ms)
214+ dropEnd acc [] = acc
215+ dropEnd acc (m:ms) =
217+ Other _ -> acc ++ [m]
218+ _ -> dropEnd (acc ++ [m]) ms
220+clause span variable (Clause value vars mtch) =
221+ CaseClause () pattern stmt
223+ vars' = map (\n -> variable ++ "._" ++ show n) [0..]
224+ stmt = match span $ matchSubst (zip vars vars') mtch
225+ pattern = case value of
226+ Right (Boolean b) -> BoolLit () b
227+ Right lit -> literal lit
228+ Left name -> string $ case List.elemIndices '.' name of
230+ is -> drop (last is + 1) name
201jsModule :: MetadataModule t v -> String
234jsModule :: MetadataModule t v -> String
202jsModule modul =
235jsModule modul =
@@ -266,50 +299,6 @@ formatMarkdown = concatMap f
266 f '\n' = "\\n"
299 f '\n' = "\\n"
267 f '"' = "\""
300 f '"' = "\""
268 f c = [c]
301 f c = [c]
270−caseToJS span e ps = do
271− (tempVar,match) <- caseToMatch ps
273− let (match',stmt) = case e of
274− L _ (Var x) -> (matchSubst [(tempVar,x)] match, "")
275− _ -> (match, assign tempVar e')
276− matches <- matchToJS span match'
277− return $ jsFunc "" (stmt ++ matches) ++ "()"
279−matchToJS span match =
281− Match name clauses def ->
282− do cases <- concat `liftM` mapM (clauseToJS span name) clauses
283− finally <- matchToJS span def
284− let isLiteral p = case p of
285− Clause (Right _) _ _ -> True
287− access = if any isLiteral clauses then "" else ".ctor"
288− return $ concat [ "\nswitch (", name, access, ") {"
289− , indent cases, "\n}", finally ]
290− Fail -> return ("_E.Case" ++ parens ("$moduleName," ++ quoted (show span)))
291− Break -> return "break;"
292− Other e -> ret `liftM` toJS' e
293− Seq ms -> concat `liftM` mapM (matchToJS span) (dropEnd [] ms)
295− dropEnd acc [] = acc
296− dropEnd acc (m:ms) =
298− Other _ -> acc ++ [m]
299− _ -> dropEnd (acc ++ [m]) ms
301−clauseToJS span var (Clause value vars e) = do
302− let vars' = map (\n -> var ++ "._" ++ show n) [0..]
303− s <- matchToJS span $ matchSubst (zip vars vars') e
304− pattern <- case value of
305− Right (Boolean True) -> return "true"
306− Right (Boolean False) -> return "false"
307− Right lit -> toJS lit
308− Left name -> return . quoted $ case List.elemIndices '.' name of
310− is -> drop (last is + 1) name
311− return $ concat [ "\ncase ", pattern, ":", indent s ]
314binop span op e1 e2 =
303binop span op e1 e2 =
315 case op of
304 case op of