2013-06-14 05:45:08 +00:00
|
|
|
module Generate.JavaScript (showErr, jsModule) where
|
2012-04-19 06:32:10 +00:00
|
|
|
|
2013-02-10 21:48:31 +00:00
|
|
|
import Control.Arrow (first,second)
|
2012-08-25 21:02:34 +00:00
|
|
|
import Control.Monad (liftM,(<=<),join,ap)
|
2012-06-12 06:28:45 +00:00
|
|
|
import Data.Char (isAlpha,isDigit)
|
2013-07-29 11:22:23 +00:00
|
|
|
import qualified Data.List as List
|
2012-12-26 22:07:09 +00:00
|
|
|
import qualified Data.Map as Map
|
2013-07-04 15:24:04 +00:00
|
|
|
import qualified Data.Set as Set
|
2012-11-23 03:48:54 +00:00
|
|
|
import Data.Either (partitionEithers)
|
2012-09-02 05:26:35 +00:00
|
|
|
import qualified Text.Pandoc as Pan
|
2012-04-19 06:32:10 +00:00
|
|
|
|
2013-06-14 05:45:08 +00:00
|
|
|
import Unique
|
|
|
|
import Generate.Cases
|
|
|
|
import SourceSyntax.Everything hiding (parens)
|
2013-07-04 15:24:04 +00:00
|
|
|
import SourceSyntax.Location as Loc
|
2013-07-16 19:43:56 +00:00
|
|
|
import qualified Transform.SortDefinitions as SD
|
2012-04-19 06:32:10 +00:00
|
|
|
|
2013-07-29 21:22:33 +00:00
|
|
|
deprime :: String -> String
|
|
|
|
deprime = map (\c -> if c == '\'' then '$' else c)
|
|
|
|
|
2012-06-09 16:13:10 +00:00
|
|
|
showErr :: String -> String
|
2013-04-05 16:51:45 +00:00
|
|
|
showErr err = globalAssign "Elm.Main" (jsFunc "elm" body)
|
2012-06-09 16:13:10 +00:00
|
|
|
where msg = show . concatMap (++"<br>") . lines $ err
|
2013-04-29 03:57:48 +00:00
|
|
|
body = "var T = Elm.Text(elm);\n\
|
2013-04-05 16:51:45 +00:00
|
|
|
\return { main : T.text(T.monospace(" ++ msg ++ ")) };"
|
2012-04-19 06:32:10 +00:00
|
|
|
|
2012-10-10 21:41:40 +00:00
|
|
|
indent = concatMap f
|
2013-05-21 20:28:18 +00:00
|
|
|
where f '\n' = "\n "
|
2012-10-10 21:41:40 +00:00
|
|
|
f c = [c]
|
|
|
|
|
2013-03-10 02:59:55 +00:00
|
|
|
internalImports =
|
2013-03-10 08:02:10 +00:00
|
|
|
[ ("N" , "Elm.Native"),
|
2013-03-12 07:48:11 +00:00
|
|
|
("_N", "N.Utils(elm)"),
|
2013-03-10 08:02:10 +00:00
|
|
|
("_L", "N.List(elm)"),
|
|
|
|
("_E", "N.Error(elm)"),
|
2013-06-21 04:25:10 +00:00
|
|
|
("_J", "N.JavaScript(elm)"),
|
|
|
|
("_str", "_J.toString")
|
2013-03-10 02:59:55 +00:00
|
|
|
]
|
|
|
|
|
2012-06-28 08:52:47 +00:00
|
|
|
parens s = "(" ++ s ++ ")"
|
2013-02-20 22:38:14 +00:00
|
|
|
brackets s = "{" ++ s ++ "}"
|
2013-07-29 11:22:23 +00:00
|
|
|
commaSep = List.intercalate ", "
|
|
|
|
dotSep = List.intercalate "."
|
|
|
|
jsObj = brackets . commaSep
|
|
|
|
jsList ss = "["++ List.intercalate "," ss ++"]"
|
2012-10-10 21:41:40 +00:00
|
|
|
jsFunc args body = "function(" ++ args ++ "){" ++ indent body ++ "}"
|
2013-03-10 08:02:10 +00:00
|
|
|
assign x e = "\nvar " ++ x ++ " = " ++ e ++ ";"
|
2012-06-12 06:28:45 +00:00
|
|
|
ret e = "\nreturn "++ e ++";"
|
2012-12-04 06:21:22 +00:00
|
|
|
quoted s = "'" ++ concatMap f s ++ "'"
|
|
|
|
where f '\n' = "\\n"
|
|
|
|
f '\'' = "\\'"
|
|
|
|
f '\t' = "\\t"
|
|
|
|
f '\"' = "\\\""
|
|
|
|
f '\\' = "\\\\"
|
|
|
|
f c = [c]
|
2012-04-19 06:32:10 +00:00
|
|
|
|
2013-02-27 07:33:47 +00:00
|
|
|
globalAssign n e = "\n" ++ assign' n e ++ ";"
|
|
|
|
assign' n e = n ++ " = " ++ e
|
|
|
|
|
2013-07-16 19:43:56 +00:00
|
|
|
jsModule :: MetadataModule t v -> String
|
|
|
|
jsModule modul =
|
|
|
|
run $ do
|
2013-07-19 15:43:37 +00:00
|
|
|
body <- toJS . fst . SD.flattenLets [] $ program modul
|
2013-07-16 19:43:56 +00:00
|
|
|
foreignImport <- mapM importEvent (foreignImports modul)
|
|
|
|
return $ concat [ setup ("Elm": names modul)
|
|
|
|
, globalAssign ("Elm." ++ modName)
|
2013-07-19 15:43:37 +00:00
|
|
|
(jsFunc "elm" $ makeProgram body foreignImport) ]
|
2013-03-06 17:25:23 +00:00
|
|
|
where
|
2013-07-29 11:22:23 +00:00
|
|
|
modName = dotSep (names modul)
|
2013-07-19 15:43:37 +00:00
|
|
|
makeProgram body foreignImport =
|
2013-07-16 19:43:56 +00:00
|
|
|
concat [ "\nvar " ++ usefulFuncs ++ ";"
|
|
|
|
, concatMap jsImport (imports modul)
|
|
|
|
, concat foreignImport
|
|
|
|
, concatMap exportEvent $ foreignExports modul
|
2013-07-29 21:22:33 +00:00
|
|
|
, assign "_op" "{}"
|
2013-07-16 19:43:56 +00:00
|
|
|
, body
|
2013-07-29 21:22:33 +00:00
|
|
|
, jsExports
|
2013-07-16 19:43:56 +00:00
|
|
|
]
|
2013-07-29 21:22:33 +00:00
|
|
|
setup names = concatMap (\n -> globalAssign n $ n ++ " || {}") .
|
2013-07-29 11:22:23 +00:00
|
|
|
map dotSep . drop 2 . List.inits $ init names
|
|
|
|
usefulFuncs = commaSep (map (uncurry assign') internalImports)
|
2013-02-27 07:33:47 +00:00
|
|
|
|
2013-07-29 21:22:33 +00:00
|
|
|
jsExports = setup ("elm" : names modul) ++
|
|
|
|
ret (assign' ("elm." ++ modName) (brackets exs))
|
|
|
|
where
|
|
|
|
exs = indent . commaSep . concatMap pair $ "_op" : exports modul
|
|
|
|
pair x | isOp x = []
|
|
|
|
| otherwise = ["\n" ++ x ++ " : " ++ x]
|
|
|
|
|
|
|
|
|
2013-07-16 19:43:56 +00:00
|
|
|
importEvent (js,base,elm,_) =
|
|
|
|
do v <- toJS' base
|
|
|
|
return $ concat [ "\nvar " ++ elm ++ "=Elm.Signal(elm).constant(" ++ v ++ ");"
|
|
|
|
, "\ndocument.addEventListener('", js
|
|
|
|
, "_' + elm.id, function(e) { elm.notify(", elm
|
|
|
|
, ".id, e.value); });" ]
|
2012-08-01 23:37:37 +00:00
|
|
|
|
2013-07-16 19:43:56 +00:00
|
|
|
exportEvent (js,elm,_) =
|
|
|
|
concat [ "\nlift(function(v) { "
|
|
|
|
, "var e = document.createEvent('Event');"
|
|
|
|
, "e.initEvent('", js, "_' + elm.id, true, true);"
|
|
|
|
, "e.value = v;"
|
|
|
|
, "document.dispatchEvent(e); return v; })(", elm, ");" ]
|
2012-06-25 12:07:52 +00:00
|
|
|
|
2013-07-29 21:22:33 +00:00
|
|
|
jsImport (modul, method) =
|
|
|
|
concat $ zipWith3 (\s n v -> s ++ assign' n v ++ ";") starters subnames values
|
2013-04-03 07:32:21 +00:00
|
|
|
where
|
2013-07-29 21:22:33 +00:00
|
|
|
starters = "\nvar " : repeat "\n"
|
|
|
|
values = map (\name -> name ++ " || {}") (init subnames) ++
|
|
|
|
["Elm." ++ modul ++ parens "elm"]
|
|
|
|
subnames = map dotSep . tail . List.inits $ split modul
|
|
|
|
|
|
|
|
split names = case go [] names of
|
|
|
|
(name, []) -> [name]
|
|
|
|
(name, ns) -> name : split ns
|
|
|
|
go name str = case str of
|
|
|
|
'.':rest -> (reverse name, rest)
|
|
|
|
c:rest -> go (c:name) rest
|
|
|
|
[] -> (reverse name, [])
|
2013-03-21 09:29:23 +00:00
|
|
|
|
2013-02-27 07:33:47 +00:00
|
|
|
|
2012-11-23 03:48:54 +00:00
|
|
|
class ToJS a where
|
2013-06-14 05:45:08 +00:00
|
|
|
toJS :: a -> Unique String
|
2012-11-23 03:48:54 +00:00
|
|
|
|
2013-07-16 19:43:56 +00:00
|
|
|
|
2013-06-14 05:45:08 +00:00
|
|
|
instance ToJS (Def t v) where
|
2013-07-04 15:24:04 +00:00
|
|
|
|
|
|
|
-- TODO: Make this handle patterns besides plain variables
|
2013-07-16 19:43:56 +00:00
|
|
|
toJS (Def (PVar x) e)
|
|
|
|
| isOp x = globalAssign ("_op['" ++ x ++ "']") `liftM` toJS' e
|
2013-07-29 21:22:33 +00:00
|
|
|
| otherwise = assign (deprime x) `liftM` toJS' e
|
2013-07-16 19:43:56 +00:00
|
|
|
|
|
|
|
toJS (Def pattern e) =
|
|
|
|
do n <- guid
|
|
|
|
let x = "_" ++ show n
|
|
|
|
var = Loc.none . Var
|
2013-07-29 21:22:33 +00:00
|
|
|
toDef y' = let y = deprime y' in
|
|
|
|
Def (PVar y) (Loc.none $ Case (var x) [(pattern, var y)])
|
2013-07-16 19:43:56 +00:00
|
|
|
stmt <- assign x `liftM` toJS' e
|
|
|
|
vars <- toJS . map toDef . Set.toList $ SD.boundVars pattern
|
|
|
|
return (stmt ++ vars)
|
2013-07-04 15:24:04 +00:00
|
|
|
|
2013-06-03 07:44:45 +00:00
|
|
|
toJS (TypeAnnotation _ _) = return ""
|
|
|
|
|
2012-11-23 03:48:54 +00:00
|
|
|
|
2013-07-16 19:43:56 +00:00
|
|
|
instance ToJS a => ToJS [a] where
|
|
|
|
toJS xs = concat `liftM` mapM toJS xs
|
2012-11-23 03:48:54 +00:00
|
|
|
|
2013-06-14 05:45:08 +00:00
|
|
|
toJS' :: LExpr t v -> Unique String
|
2013-05-29 23:20:38 +00:00
|
|
|
toJS' (L txt span expr) =
|
2012-12-25 08:39:18 +00:00
|
|
|
case expr of
|
|
|
|
MultiIf ps -> multiIfToJS span ps
|
|
|
|
Case e cases -> caseToJS span e cases
|
|
|
|
_ -> toJS expr
|
|
|
|
|
2013-07-29 21:22:33 +00:00
|
|
|
remove x e = "_N.remove('" ++ deprime x ++ "', " ++ e ++ ")"
|
|
|
|
addField x v e = "_N.insert('" ++ deprime x ++ "', " ++ v ++ ", " ++ e ++ ")"
|
2013-03-12 07:48:11 +00:00
|
|
|
setField fs e = "_N.replace(" ++ jsList (map f fs) ++ ", " ++ e ++ ")"
|
2013-07-29 21:22:33 +00:00
|
|
|
where f (x,v) = "['" ++ deprime x ++ "'," ++ v ++ "]"
|
|
|
|
access x e = e ++ "." ++ deprime x
|
2013-02-10 21:48:31 +00:00
|
|
|
makeRecord kvs = record `liftM` collect kvs
|
|
|
|
where
|
|
|
|
combine r (k,v) = Map.insertWith (++) k v r
|
2013-07-29 11:22:23 +00:00
|
|
|
collect = liftM (List.foldl' combine Map.empty) . mapM prep
|
2013-07-04 15:24:04 +00:00
|
|
|
prep (k, e) =
|
|
|
|
do v <- toJS' e
|
2013-07-29 21:22:33 +00:00
|
|
|
return (deprime k, [v])
|
2013-02-10 21:48:31 +00:00
|
|
|
fields fs =
|
2013-07-29 11:22:23 +00:00
|
|
|
brackets ("\n "++List.intercalate ",\n " (map (\(k,v) -> k++":"++v) fs))
|
2013-02-10 21:48:31 +00:00
|
|
|
hidden = fields . map (second jsList) .
|
|
|
|
filter (not . null . snd) . Map.toList . Map.map tail
|
|
|
|
record kvs = fields . (("_", hidden kvs) :) . Map.toList . Map.map head $ kvs
|
2012-12-26 22:07:09 +00:00
|
|
|
|
|
|
|
|
2013-06-14 05:45:08 +00:00
|
|
|
instance ToJS Literal where
|
|
|
|
toJS lit =
|
|
|
|
case lit of
|
2012-12-26 22:07:09 +00:00
|
|
|
Chr c -> return $ quoted [c]
|
2013-03-10 02:59:55 +00:00
|
|
|
Str s -> return $ "_str" ++ parens (quoted s)
|
2013-04-07 13:46:56 +00:00
|
|
|
IntNum n -> return $ show n
|
|
|
|
FloatNum n -> return $ show n
|
|
|
|
Boolean b -> return $ if b then "true" else "false"
|
2013-06-14 05:45:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
instance ToJS (Expr t v) where
|
|
|
|
toJS expr =
|
|
|
|
case expr of
|
2013-07-29 21:22:33 +00:00
|
|
|
Var x -> return (deprime x)
|
2013-06-14 05:45:08 +00:00
|
|
|
Literal lit -> toJS lit
|
2012-12-26 22:07:09 +00:00
|
|
|
Range lo hi -> jsRange `liftM` toJS' lo `ap` toJS' hi
|
|
|
|
Access e x -> access x `liftM` toJS' e
|
2013-02-10 21:48:31 +00:00
|
|
|
Remove e x -> remove x `liftM` toJS' e
|
|
|
|
Insert e x v -> addField x `liftM` toJS' v `ap` toJS' e
|
|
|
|
Modify e fs -> do fs' <- (mapM (\(x,v) -> (,) x `liftM` toJS' v) fs)
|
|
|
|
setField fs' `liftM` toJS' e
|
2012-12-26 22:07:09 +00:00
|
|
|
Record fs -> makeRecord fs
|
|
|
|
Binop op e1 e2 -> binop op `liftM` toJS' e1 `ap` toJS' e2
|
|
|
|
|
2013-07-29 21:22:33 +00:00
|
|
|
Lambda p e -> liftM (fastFunc . ret) (toJS' body)
|
2013-07-04 15:24:04 +00:00
|
|
|
where
|
2013-07-29 21:22:33 +00:00
|
|
|
fastFunc body
|
|
|
|
| length args < 2 || length args > 9 = foldr jsFunc body args
|
|
|
|
| otherwise = "F" ++ show (length args) ++ parens (jsFunc (commaSep args) body)
|
2013-07-29 21:44:15 +00:00
|
|
|
(args, body) = first reverse $ foldr depattern ([], innerBody) (zip patterns [1..])
|
2013-07-04 15:24:04 +00:00
|
|
|
|
|
|
|
depattern (pattern,n) (args, body) =
|
|
|
|
case pattern of
|
2013-07-29 21:22:33 +00:00
|
|
|
PVar x -> (deprime x : args, body)
|
2013-07-04 15:24:04 +00:00
|
|
|
_ -> let arg = "arg" ++ show n
|
|
|
|
in (arg:args, Loc.none (Case (Loc.none (Var arg)) [(pattern, body)]))
|
|
|
|
|
|
|
|
(patterns, innerBody) = collect [p] e
|
|
|
|
|
|
|
|
collect patterns lexpr@(L a b expr) =
|
|
|
|
case expr of
|
|
|
|
Lambda p e -> collect (p:patterns) e
|
|
|
|
_ -> (patterns, lexpr)
|
2012-12-26 22:07:09 +00:00
|
|
|
|
2013-02-28 16:56:21 +00:00
|
|
|
App e1 e2 -> jsApp e1 e2
|
2013-07-16 19:43:56 +00:00
|
|
|
Let defs e -> jsLet $ SD.flattenLets defs e
|
2013-06-21 04:25:10 +00:00
|
|
|
|
|
|
|
ExplicitList es ->
|
|
|
|
do es' <- mapM toJS' es
|
|
|
|
return $ "_J.toList" ++ parens (jsList es')
|
|
|
|
|
2013-02-20 22:38:14 +00:00
|
|
|
Data name es ->
|
|
|
|
do fs <- mapM toJS' es
|
2013-03-26 01:03:12 +00:00
|
|
|
return $ case name of
|
2013-06-21 04:25:10 +00:00
|
|
|
"[]" -> jsNil
|
|
|
|
"::" -> jsCons (head fs) ((head . tail) fs)
|
2013-04-03 07:32:21 +00:00
|
|
|
_ -> jsObj $ ("ctor:" ++ show name) : fields
|
2013-03-26 01:03:12 +00:00
|
|
|
where fields = zipWith (\n e -> "_" ++ show n ++ ":" ++ e) [0..] fs
|
2012-12-26 22:07:09 +00:00
|
|
|
|
|
|
|
Markdown doc -> return $ "text('" ++ pad ++ md ++ pad ++ "')"
|
|
|
|
where pad = "<div style=\"height:0;width:0;\"> </div>"
|
2013-01-25 10:31:41 +00:00
|
|
|
md = formatMarkdown $ Pan.writeHtmlString Pan.def doc
|
2012-09-11 09:53:45 +00:00
|
|
|
|
2013-02-28 16:56:21 +00:00
|
|
|
jsApp e1 e2 =
|
|
|
|
do f <- toJS' func
|
|
|
|
as <- mapM toJS' args
|
|
|
|
return $ case as of
|
|
|
|
[a] -> f ++ parens a
|
2013-07-29 11:22:23 +00:00
|
|
|
_ -> "A" ++ show (length as) ++ parens (commaSep (f:as))
|
2013-02-28 16:56:21 +00:00
|
|
|
where
|
|
|
|
(func, args) = go [e2] e1
|
|
|
|
go args e =
|
|
|
|
case e of
|
2013-05-29 23:20:38 +00:00
|
|
|
(L _ _ (App e1 e2)) -> go (e2 : args) e1
|
2013-02-28 16:56:21 +00:00
|
|
|
_ -> (e, args)
|
|
|
|
|
2012-09-11 09:53:45 +00:00
|
|
|
formatMarkdown = concatMap f
|
|
|
|
where f '\'' = "\\'"
|
2012-09-13 19:26:31 +00:00
|
|
|
f '\n' = "\\n"
|
2012-09-11 09:53:45 +00:00
|
|
|
f '"' = "\""
|
|
|
|
f c = [c]
|
2012-04-19 06:32:10 +00:00
|
|
|
|
2013-02-27 07:33:47 +00:00
|
|
|
multiIfToJS span ps =
|
|
|
|
case last ps of
|
2013-05-29 23:20:38 +00:00
|
|
|
(L _ _ (Var "otherwise"), e) -> toJS' e >>= \b -> format b (init ps)
|
2013-03-10 08:02:10 +00:00
|
|
|
_ -> format ("_E.If" ++ parens (quoted (show span))) ps
|
2013-02-27 07:33:47 +00:00
|
|
|
where
|
|
|
|
format base ps =
|
|
|
|
foldr (\c e -> parens $ c ++ " : " ++ e) base `liftM` mapM f ps
|
|
|
|
f (b,e) = do b' <- toJS' b
|
|
|
|
e' <- toJS' e
|
|
|
|
return (b' ++ " ? " ++ e')
|
|
|
|
|
2013-07-16 19:43:56 +00:00
|
|
|
jsLet (defs,e') = do ds <- mapM toJS defs
|
|
|
|
e <- toJS' e'
|
|
|
|
return $ jsFunc "" (concat ds ++ ret e) ++ "()"
|
2012-08-25 21:02:34 +00:00
|
|
|
|
2012-12-25 08:39:18 +00:00
|
|
|
caseToJS span e ps = do
|
2012-08-25 21:02:34 +00:00
|
|
|
match <- caseToMatch ps
|
2012-12-25 08:39:18 +00:00
|
|
|
e' <- toJS' e
|
2013-05-21 20:28:18 +00:00
|
|
|
let (match',stmt) = case (match,e) of
|
2013-07-29 21:22:33 +00:00
|
|
|
(Match name _ _, L _ _ (Var x)) -> (matchSubst [(name,deprime x)] match, "")
|
2013-05-21 21:47:15 +00:00
|
|
|
(Match name _ _, _) -> (match, assign name e')
|
|
|
|
_ -> (match, "")
|
2012-12-25 08:39:18 +00:00
|
|
|
matches <- matchToJS span match'
|
2013-05-21 21:47:15 +00:00
|
|
|
return $ "function(){ " ++ stmt ++ matches ++ " }()"
|
2013-02-28 16:56:21 +00:00
|
|
|
|
|
|
|
matchToJS span match =
|
2013-05-21 20:28:18 +00:00
|
|
|
case match of
|
2013-02-28 16:56:21 +00:00
|
|
|
Match name clauses def ->
|
2013-05-21 20:28:18 +00:00
|
|
|
do cases <- concat `liftM` mapM (clauseToJS span name) clauses
|
2013-02-28 16:56:21 +00:00
|
|
|
finally <- matchToJS span def
|
2013-06-23 08:36:23 +00:00
|
|
|
let isLiteral p = case p of
|
|
|
|
Clause (Right _) _ _ -> True
|
|
|
|
_ -> False
|
|
|
|
access = if any isLiteral clauses then "" else ".ctor"
|
|
|
|
return $ concat [ "\nswitch (", name, access, ") {"
|
|
|
|
, indent cases, "\n}", finally ]
|
2013-03-10 08:02:10 +00:00
|
|
|
Fail -> return ("_E.Case" ++ parens (quoted (show span)))
|
2013-05-21 20:28:18 +00:00
|
|
|
Break -> return "break;"
|
|
|
|
Other e -> ret `liftM` toJS' e
|
|
|
|
Seq ms -> concat `liftM` mapM (matchToJS span) (dropEnd [] ms)
|
|
|
|
where
|
|
|
|
dropEnd acc [] = acc
|
|
|
|
dropEnd acc (m:ms) =
|
|
|
|
case m of
|
|
|
|
Other _ -> acc ++ [m]
|
|
|
|
_ -> dropEnd (acc ++ [m]) ms
|
2012-08-25 21:02:34 +00:00
|
|
|
|
2013-06-23 08:36:23 +00:00
|
|
|
clauseToJS span var (Clause value vars e) = do
|
2013-02-28 16:56:21 +00:00
|
|
|
let vars' = map (\n -> var ++ "._" ++ show n) [0..]
|
2012-12-25 08:39:18 +00:00
|
|
|
s <- matchToJS span $ matchSubst (zip vars vars') e
|
2013-06-23 08:36:23 +00:00
|
|
|
return $ concat [ "\ncase ", case value of
|
|
|
|
Left name -> quoted name
|
|
|
|
Right (Boolean True) -> "true"
|
|
|
|
Right (Boolean False) -> "false"
|
|
|
|
Right lit -> show lit
|
|
|
|
, ":", indent s ]
|
2012-04-19 06:32:10 +00:00
|
|
|
|
2013-03-10 08:02:10 +00:00
|
|
|
jsNil = "_L.Nil"
|
|
|
|
jsCons e1 e2 = "_L.Cons(" ++ e1 ++ "," ++ e2 ++ ")"
|
|
|
|
jsRange e1 e2 = "_L.range" ++ parens (e1 ++ "," ++ e2)
|
2013-07-30 15:44:23 +00:00
|
|
|
jsCompare e1 e2 op = parens ("_N.cmp(" ++ e1 ++ "," ++ e2 ++ ")" ++ op)
|
2012-04-19 06:32:10 +00:00
|
|
|
|
2013-07-29 21:22:33 +00:00
|
|
|
|
|
|
|
binop op e1 e2 =
|
|
|
|
case Map.lookup op opDict of
|
|
|
|
Just e -> e
|
|
|
|
Nothing -> "A2" ++ parens (commaSep [ prefix ++ func, e1, e2 ])
|
|
|
|
where
|
|
|
|
func | isOp op' = "_op['" ++ op' ++ "']"
|
|
|
|
| otherwise = op'
|
|
|
|
(prefix, op') = case List.elemIndices '.' op of
|
|
|
|
[] -> ("", op)
|
|
|
|
xs -> splitAt (last xs + 1) op
|
|
|
|
where
|
|
|
|
opDict = Map.fromList $ basics ++
|
|
|
|
[ ("::", jsCons e1 e2)
|
|
|
|
, ("List.++", "_L.append" ++ parens (e1 ++ "," ++ e2)) ]
|
|
|
|
|
2013-07-30 02:34:00 +00:00
|
|
|
ops = pow : map (\op -> (op, parens (e1 ++ op ++ e2))) ["+","-","*","/","&&","||"]
|
|
|
|
where pow = ("^" , "Math.pow(" ++ e1 ++ "," ++ e2 ++ ")")
|
|
|
|
|
|
|
|
basics = ops ++ map (\(op,e) -> ("Basics." ++ op, e))
|
|
|
|
(ops ++ [ ("<|", e1 ++ parens e2)
|
|
|
|
, ("|>", e2 ++ parens e1)
|
|
|
|
, ("." , jsFunc "x" . ret $ e1 ++ parens (e2 ++ parens "x"))
|
|
|
|
, ("==", "_N.eq(" ++ e1 ++ "," ++ e2 ++ ")")
|
|
|
|
, ("/=", "!_N.eq(" ++ e1 ++ "," ++ e2 ++ ")")
|
2013-07-30 15:44:23 +00:00
|
|
|
, ("<" , jsCompare e1 e2 "<0")
|
|
|
|
, (">" , jsCompare e1 e2 ">0")
|
|
|
|
, ("<=", jsCompare e1 e2 "<1")
|
|
|
|
, (">=", jsCompare e1 e2 ">-1")
|
2013-07-30 02:34:00 +00:00
|
|
|
, ("div", parens (e1 ++ "/" ++ e2 ++ "|0"))
|
|
|
|
])
|