@@ -6,7 +6,7 @@ import Control.Arrow (first)
6import Control.Monad (liftM,(<=<),join,ap)
6import Control.Monad (liftM,(<=<),join,ap)
7import Data.Char (isAlpha,isDigit)
7import Data.Char (isAlpha,isDigit)
8import Data.List (intercalate,sortBy,inits,foldl')
8import Data.List (intercalate,sortBy,inits,foldl')
9−import Data.Map (toList)
9+import qualified Data.Map as Map
10import Data.Either (partitionEithers)
10import Data.Either (partitionEithers)
11import qualified Text.Pandoc as Pan
11import qualified Text.Pandoc as Pan
@@ -175,54 +175,75 @@ toJS' (C txt span expr) =
175 Case e cases -> caseToJS span e cases
175 Case e cases -> caseToJS span e cases
176 _ -> toJS expr
176 _ -> toJS expr
178+recordToJS e loop cmds =
180+ return $ jsFunc "" (concat [ assign "r" "{_:[true]}"
182+ , "\nfor(var i in e){", loop, "}"
184+ , ret "r" ]) ++ "()"
186+remove x = concat [ "\n if (i!='", x, "') { r[i]=e[i]; }"
187+ , "\n else if (e[i].length>1) { r[i]=e[i].slice(1); }" ]
188+addField (x,e) = ((++add) . assign "v") `liftM` toJS' e
189+ where add = concat [ "\nif (r.hasOwnProperty('", x, "')) {"
190+ , "\n r.", x, " = r.", x, ".slice(0);"
191+ , "\n r.", x, ".unshift(v);"
192+ , "\n} else { r.", x, " = [v]; }" ]
194+ set <- globalAssign ("r." ++ x ++ "[0]") `liftM` toJS' e
195+ return (globalAssign ("r." ++ x) ("r." ++ x ++ ".slice(0)") ++ set)
196+access x e = jsFunc "r" (ret body) ++ parens e
197+ where body = "r.hasOwnProperty('_') ? r." ++ x ++ "[0] : r." ++ x
199+ kvs' <- (Map.toList . foldl' combine Map.empty) `liftM` mapM prep kvs
200+ let fs = map (\(k,vs) -> k ++ " : " ++ jsList vs) kvs' ++ ["_ : [true]"]
201+ return $ "\n " ++ braces (intercalate ",\n " fs)
202+ where combine r (k,v) = Map.insertWith (++) k v r
203+ prep (k, as, e@(C t s _)) =
204+ do v <- toJS' (foldr (\x e -> C t s $ Lambda x e) e as)
178instance ToJS Expr where
208instance ToJS Expr where
179− toJS expr =
209+ toJS expr =
180− case expr of
210+ case expr of
181− IntNum n -> return $ show n
211+ IntNum n -> return $ show n
182− FloatNum n -> return $ show n
212+ FloatNum n -> return $ show n
183− Var x -> return $ x
213+ Var x -> return $ x
184− Chr c -> return $ quoted [c]
214+ Chr c -> return $ quoted [c]
185− Str s -> return $ "Value.str" ++ parens (quoted s)
215+ Str s -> return $ "Value.str" ++ parens (quoted s)
186− Boolean b -> return $ if b then "true" else "false"
216+ Boolean b -> return $ if b then "true" else "false"
187− Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
217+ Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
188− Access e lbl -> (\s -> s ++ "." ++ lbl) `liftM` toJS' e
218+ Access e x -> access x `liftM` toJS' e
189−
219+ Remove e x -> recordToJS e (remove x) ""
190− Modify e lbl v -> do e' <- toJS' e
220+ Insert e x v -> recordToJS e "r[i]=e[i];" =<< addField (x,v)
191− v' <- toJS' v
221+ Modify e fs -> recordToJS e "r[i]=e[i];" . concat =<< mapM setField fs
192− let body = concat [ assign "r" e'
222+ Record fs -> makeRecord fs
193− , globalAssign ("r." ++ lbl) v'
195− return $ jsFunc "" body ++ "()"
197− Record fs -> (braces . intercalate ",\n") `liftM` mapM toField fs
198− where toField (f, as, ce@(C t s e)) =
199− do v <- toJS' (foldr (\x e -> C t s $ Lambda x e) ce as)
200− return (f ++ " : " ++ v)
202− Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
223+ Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
204− If eb et ef ->
225+ If eb et ef ->
205− parens `liftM` (iff `liftM` toJS' eb `ap` toJS' et `ap` toJS' ef)
226+ parens `liftM` (iff `liftM` toJS' eb `ap` toJS' et `ap` toJS' ef)
207− Lambda v e -> liftM (jsFunc v . ret) (toJS' e)
228+ Lambda v e -> liftM (jsFunc v . ret) (toJS' e)
209− App (C _ _ (Var "toText")) (C _ _ (Str s)) ->
230+ App (C _ _ (Var "toText")) (C _ _ (Str s)) ->
210− return $ "toText" ++ parens (quoted s)
231+ return $ "toText" ++ parens (quoted s)
212− App (C _ _ (Var "link")) (C _ _ (Str s)) ->
233+ App (C _ _ (Var "link")) (C _ _ (Str s)) ->
213− return $ "link(" ++ quoted s ++ ")"
234+ return $ "link(" ++ quoted s ++ ")"
215− App (C _ _ (Var "plainText")) (C _ _ (Str s)) ->
236+ App (C _ _ (Var "plainText")) (C _ _ (Str s)) ->
216− return $ "plainText(" ++ quoted s ++ ")"
237+ return $ "plainText(" ++ quoted s ++ ")"
218− App e1 e2 -> (++) `liftM` (toJS' e1) `ap` (parens `liftM` toJS' e2)
239+ App e1 e2 -> (++) `liftM` (toJS' e1) `ap` (parens `liftM` toJS' e2)
219− Let defs e -> jsLet defs e
240+ Let defs e -> jsLet defs e
220− Data name es -> (\ss -> jsList $ quoted name : ss) `liftM` mapM toJS' es
241+ Data name es -> (\ss -> jsList $ quoted name : ss) `liftM` mapM toJS' es
222− Markdown doc -> return $ "text('" ++ pad ++ md ++ pad ++ "')"
243+ Markdown doc -> return $ "text('" ++ pad ++ md ++ pad ++ "')"
223− where pad = "<div style=\"height:0;width:0;\"> </div>"
244+ where pad = "<div style=\"height:0;width:0;\"> </div>"
224− md = formatMarkdown $
245+ md = formatMarkdown $
225− Pan.writeHtmlString Pan.defaultWriterOptions doc
246+ Pan.writeHtmlString Pan.defaultWriterOptions doc
227formatMarkdown = concatMap f
248formatMarkdown = concatMap f
228 where f '\'' = "\\'"
249 where f '\'' = "\\'"