1{-# LANGUAGE PatternGuards #-}
2{-# LANGUAGE OverloadedStrings #-}
3module IRTS.CodegenJavaScript (codegenJavaScript, codegenNode, JSTarget(..)) where
5import IRTS.JavaScript.AST
7import Idris.AbsSyntax hiding (TypeCase)
11import IRTS.CodegenCommon
17import Control.Monad (mapM)
18import Control.Applicative ((<$>), (<*>), pure)
19import Control.Monad.RWS hiding (mapM)
20import Control.Monad.State
26import Data.Traversable hiding (mapM)
28import System.Directory
30import qualified Data.Map.Strict as M
31import qualified Data.Text as T
32import qualified Data.Text.IO as TIO
35data CompileInfo = CompileInfo { compileInfoApplyCases :: [Int]
36 , compileInfoEvalCases :: [Int]
37 , compileInfoNeedsBigInt :: Bool
41initCompileInfo :: [(Name, [BC])] -> CompileInfo
43 CompileInfo (collectCases "APPLY" bc) (collectCases "EVAL" bc) (lookupBigInt bc)
45 lookupBigInt :: [(Name, [BC])] -> Bool
46 lookupBigInt = any (needsBigInt . snd)
48 needsBigInt :: [BC] -> Bool
49 needsBigInt bc = or $ map testBCForBigInt bc
51 testBCForBigInt :: BC -> Bool
52 testBCForBigInt (ASSIGNCONST _ c) =
55 testBCForBigInt (CONSTCASE _ c d) =
56 maybe False needsBigInt d
57 || (or $ map (needsBigInt . snd) c)
58 || (or $ map (testConstForBigInt . fst) c)
60 testBCForBigInt _ = False
62 testConstForBigInt :: Const -> Bool
63 testConstForBigInt (BI _) = True
64 testConstForBigInt (B64 _) = True
65 testConstForBigInt _ = False
68 collectCases :: String -> [(Name, [BC])] -> [Int]
69 collectCases fun bc = getCases $ findFunction fun bc
71 findFunction :: String -> [(Name, [BC])] -> [BC]
72 findFunction f ((MN 0 fun, bc):_)
74 findFunction f (_:bc) = findFunction f bc
76 getCases :: [BC] -> [Int]
77 getCases = concatMap analyze
79 analyze :: BC -> [Int]
80 analyze (CASE _ _ b _) = map fst b
84data JSTarget = Node | JavaScript deriving Eq
87codegenJavaScript :: CodeGenerator
89 codegenJS_all JavaScript (simpleDecls ci)
90 (includes ci) [] (outputFile ci) (outputType ci)
92codegenNode :: CodeGenerator
94 codegenJS_all Node (simpleDecls ci)
95 (includes ci) (compileLibs ci) (outputFile ci) (outputType ci)
105codegenJS_all target definitions includes libs filename outputType = do
106 let bytecode = map toBC definitions
107 let info = initCompileInfo bytecode
108 let js = concatMap (translateDecl info) bytecode
109 let full = concatMap processFunction js
110 let code = deadCodeElim full
111 let (cons, opt) = optimizeConstructors code
112 let (header, rt) = case target of
113 Node -> ("#!/usr/bin/env node\n", "-node")
114 JavaScript -> ("", "-browser")
116 included <- concat <$> getIncludes includes
117 path <- (++) <$> getDataDir <*> (pure "/jsrts/")
118 idrRuntime <- readFile $ path ++ "Runtime-common.js"
119 tgtRuntime <- readFile $ concat [path, "Runtime", rt, ".js"]
120 jsbn <- if compileInfoNeedsBigInt info
121 then readFile $ path ++ "jsbn/jsbn.js"
123 let runtime = ( header
130 TIO.writeFile filename ( T.pack runtime
131 `T.append` T.concat (map compileJS opt)
132 `T.append` T.concat (map compileJS cons)
134 `T.append` invokeMain
136 setPermissions filename (emptyPermissions { readable = True
137 , executable = target == Node
141 deadCodeElim :: [JS] -> [JS]
142 deadCodeElim js = concatMap collectFunctions js
144 collectFunctions :: JS -> [JS]
145 collectFunctions fun@(JSAlloc name _)
146 | name == translateName (sMN 0 "runMain") = [fun]
148 collectFunctions fun@(JSAlloc name (Just (JSFunction _ body))) =
149 let invokations = sum $ map (
150 \x -> execState (countInvokations name x) 0
152 in if invokations == 0
156 countInvokations :: String -> JS -> State Int ()
157 countInvokations name (JSAlloc _ (Just (JSFunction _ body))) =
158 countInvokations name body
160 countInvokations name (JSSeq seq) =
161 void $ traverse (countInvokations name) seq
163 countInvokations name (JSAssign _ rhs) =
164 countInvokations name rhs
166 countInvokations name (JSCond conds) =
168 runKleisli $ arr id *** Kleisli (countInvokations name)
171 countInvokations name (JSSwitch _ conds def) =
173 runKleisli $ arr id *** Kleisli (countInvokations name)
174 ) conds >> traverse (countInvokations name) def
176 countInvokations name (JSApp lhs rhs) =
177 void $ countInvokations name lhs >> traverse (countInvokations name) rhs
179 countInvokations name (JSNew _ args) =
180 void $ traverse (countInvokations name) args
182 countInvokations name (JSArray args) =
183 void $ traverse (countInvokations name) args
185 countInvokations name (JSIdent name')
186 | name == name' = get >>= put . (+1)
187 | otherwise = return ()
189 countInvokations _ _ = return ()
191 processFunction :: JS -> [JS]
193 collectSplitFunctions . (\x -> evalRWS (splitFunction x) () 0)
195 includeLibs :: [String] -> String
197 concatMap (\lib -> "var " ++ lib ++ " = require(\"" ++ lib ++"\");\n")
199 getIncludes :: [FilePath] -> IO [String]
200 getIncludes = mapM readFile
204 compileJS $ JSAlloc "main" (Just $
214 JSCond [ (exists document `jsAnd` isReady, mainFun)
215 , (exists window, windowMainFun)
220 exists js = jsTypeOf js `jsNotEq` JSString "undefined"
223 window = JSIdent "window"
226 document = JSIdent "document"
230 jsMeth window "addEventListener" [ JSString "DOMContentLoaded"
231 , JSFunction [] ( mainFun )
236 isReady = JSParens $ readyState `jsEq` JSString "complete" `jsOr` readyState `jsEq` JSString "loaded"
239 readyState = JSProj (JSIdent "document") "readyState"
243 JSSeq [ JSAlloc "vm" (Just $ JSNew "i$VM" [])
244 , JSApp (JSIdent "i$SCHED") [JSIdent "vm"]
246 JSIdent (translateName (sMN 0 "runMain"))
248 , JSWhile (JSProj jsCALLSTACK "length") (
249 JSSeq [ JSAlloc "func" (Just jsPOP)
250 , JSAlloc "args" (Just jsPOP)
251 , JSApp (JSProj (JSIdent "func") "apply") [JSThis, JSIdent "args"]
257 invokeMain = compileJS $ JSApp (JSIdent "main") []
259optimizeConstructors :: [JS] -> ([JS], [JS])
260optimizeConstructors js =
261 let (js', cons) = runState (traverse optimizeConstructor' js) M.empty in
262 (map (allocCon . snd) (M.toList cons), js')
264 allocCon :: (String, JS) -> JS
265 allocCon (name, con) = JSAlloc name (Just con)
267 newConstructor :: Int -> String
268 newConstructor n = "i$CON$" ++ show n
270 optimizeConstructor' :: JS -> State (M.Map Int (String, JS)) JS
271 optimizeConstructor' js@(JSNew "i$CON" [ JSNum (JSInt tag)
277 case M.lookup tag s of
278 Just (i, c) -> return $ JSIdent i
279 Nothing -> do let n = newConstructor tag
280 put $ M.insert tag (n, js) s
283 optimizeConstructor' (JSSeq seq) =
284 JSSeq <$> traverse optimizeConstructor' seq
286 optimizeConstructor' (JSSwitch reg cond def) = do
287 cond' <- traverse (runKleisli $ arr id *** Kleisli optimizeConstructor') cond
288 def' <- traverse optimizeConstructor' def
289 return $ JSSwitch reg cond' def'
291 optimizeConstructor' (JSCond cond) =
292 JSCond <$> traverse (runKleisli $ arr id *** Kleisli optimizeConstructor') cond
294 optimizeConstructor' (JSAlloc fun (Just (JSFunction args body))) = do
295 body' <- optimizeConstructor' body
296 return $ JSAlloc fun (Just (JSFunction args body'))
298 optimizeConstructor' (JSAssign lhs rhs) = do
299 lhs' <- optimizeConstructor' lhs
300 rhs' <- optimizeConstructor' rhs
301 return $ JSAssign lhs' rhs'
303 optimizeConstructor' js = return js
305collectSplitFunctions :: (JS, [(Int,JS)]) -> [JS]
306collectSplitFunctions (fun, splits) = map generateSplitFunction splits ++ [fun]
308 generateSplitFunction :: (Int,JS) -> JS
309 generateSplitFunction (depth, JSAlloc name fun) =
310 JSAlloc (name ++ "$" ++ show depth) fun
312splitFunction :: JS -> RWS () [(Int,JS)] Int JS
313splitFunction (JSAlloc name (Just (JSFunction args body@(JSSeq _)))) = do
314 body' <- splitSequence body
315 return $ JSAlloc name (Just (JSFunction args body'))
317 splitCondition :: JS -> RWS () [(Int,JS)] Int JS
319 | JSCond branches <- js =
320 JSCond <$> processBranches branches
321 | JSSwitch cond branches def <- js =
322 JSSwitch cond <$> (processBranches branches) <*> (traverse splitSequence def)
323 | otherwise = return js
325 processBranches :: [(JS,JS)] -> RWS () [(Int,JS)] Int [(JS,JS)]
327 traverse (runKleisli (arr id *** Kleisli splitSequence))
329 splitSequence :: JS -> RWS () [(Int, JS)] Int JS
330 splitSequence js@(JSSeq seq) =
331 let (pre,post) = break isCall seq in
333 [] -> JSSeq <$> traverse splitCondition seq
334 [js@(JSCond _)] -> splitCondition js
335 [js@(JSSwitch {})] -> splitCondition js
340 new <- splitFunction (newFun rest)
342 return $ JSSeq (pre ++ (newCall depth : [call]))
344 splitSequence js = return js
347 isCall (JSApp (JSIdent "i$CALL") _) = True
352 JSApp (JSIdent "i$CALL") [ JSIdent $ name ++ "$" ++ show depth
353 , JSArray [jsOLDBASE, jsMYOLDBASE]
358 JSAlloc name (Just $ JSFunction ["oldbase", "myoldbase"] (JSSeq seq))
360splitFunction js = return js
362translateDecl :: CompileInfo -> (Name, [BC]) -> [JS]
363translateDecl info (name@(MN 0 fun), bc)
364 | txt "APPLY" == fun =
365 allocCaseFunctions (snd body)
368 ) (Just $ JSFunction ["oldbase"] (
369 JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info) (fst body) ++ [
370 JSCond [ ( (translateReg $ caseReg (snd body)) `jsInstanceOf` "i$CON" `jsAnd` (JSProj (translateReg $ caseReg (snd body)) "app")
371 , JSApp (JSProj (translateReg $ caseReg (snd body)) "app") [jsOLDBASE, jsMYOLDBASE]
374 , JSSeq $ map (translateBC info) (defaultCase (snd body))
382 | txt "EVAL" == fun =
383 allocCaseFunctions (snd body)
386 ) (Just $ JSFunction ["oldbase"] (
387 JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info) (fst body) ++ [
388 JSCond [ ( (translateReg $ caseReg (snd body)) `jsInstanceOf` "i$CON" `jsAnd` (JSProj (translateReg $ caseReg (snd body)) "ev")
389 , JSApp (JSProj (translateReg $ caseReg (snd body)) "ev") [jsOLDBASE, jsMYOLDBASE]
392 , JSSeq $ map (translateBC info) (defaultCase (snd body))
401 body = break isCase bc
405 | CASE {} <- bc = True
408 defaultCase :: [BC] -> [BC]
409 defaultCase ((CASE _ _ _ (Just d)):_) = d
411 caseReg :: [BC] -> Reg
412 caseReg ((CASE _ r _ _):_) = r
414 allocCaseFunctions :: [BC] -> [JS]
415 allocCaseFunctions ((CASE _ _ c _):_) = splitBranches c
416 allocCaseFunctions _ = []
418 splitBranches :: [(Int, [BC])] -> [JS]
419 splitBranches = map prepBranch
421 prepBranch :: (Int, [BC]) -> JS
422 prepBranch (tag, code) =
424 translateName name ++ "$" ++ show tag
425 ) (Just $ JSFunction ["oldbase", "myoldbase"] (
426 JSSeq $ map (translateBC info) code
430translateDecl info (name, bc) =
433 ) (Just $ JSFunction ["oldbase"] (
434 JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info)bc
440translateReg :: Reg -> JS
442 | RVal <- reg = jsRET
443 | Tmp <- reg = JSRaw "//TMPREG"
444 | L n <- reg = jsLOC n
445 | T n <- reg = jsTOP n
447translateConstant :: Const -> JS
448translateConstant (I i) = JSNum (JSInt i)
449translateConstant (Fl f) = JSNum (JSFloat f)
450translateConstant (Ch c) = JSString $ translateChar c
451translateConstant (Str s) = JSString $ concatMap translateChar s
452translateConstant (AType (ATInt ITNative)) = JSType JSIntTy
453translateConstant StrType = JSType JSStringTy
454translateConstant (AType (ATInt ITBig)) = JSType JSIntegerTy
455translateConstant (AType ATFloat) = JSType JSFloatTy
456translateConstant (AType (ATInt ITChar)) = JSType JSCharTy
457translateConstant PtrType = JSType JSPtrTy
458translateConstant Forgot = JSType JSForgotTy
459translateConstant (BI 0) = JSNum (JSInteger JSBigZero)
460translateConstant (BI 1) = JSNum (JSInteger JSBigOne)
461translateConstant (BI i) = jsBigInt (JSString $ show i)
462translateConstant (B8 b) = JSWord (JSWord8 b)
463translateConstant (B16 b) = JSWord (JSWord16 b)
464translateConstant (B32 b) = JSWord (JSWord32 b)
465translateConstant (B64 b) = JSWord (JSWord64 b)
467 JSError $ "Unimplemented Constant: " ++ show c
470translateChar :: Char -> String
472 | '\a' <- ch = "\\u0007"
479 | '\SO' <- ch = "\\u000E"
480 | '\DEL' <- ch = "\\u007F"
481 | '\\' <- ch = "\\\\"
482 | '\"' <- ch = "\\\""
483 | '\'' <- ch = "\\\'"
484 | ch `elem` asciiTab = "\\u00" ++ fill (showHex (ord ch) "")
487 fill :: String -> String
488 fill s = if length s == 1
493 ['\NUL', '\SOH', '\STX', '\ETX', '\EOT', '\ENQ', '\ACK', '\BEL',
494 '\BS', '\HT', '\LF', '\VT', '\FF', '\CR', '\SO', '\SI',
495 '\DLE', '\DC1', '\DC2', '\DC3', '\DC4', '\NAK', '\SYN', '\ETB',
496 '\CAN', '\EM', '\SUB', '\ESC', '\FS', '\GS', '\RS', '\US']
498translateName :: Name -> String
499translateName n = "_idris_" ++ concatMap cchar (showCG n)
500 where cchar x | isAlphaNum x = [x]
501 | otherwise = "_" ++ show (fromEnum x) ++ "_"
503jsASSIGN :: CompileInfo -> Reg -> Reg -> JS
504jsASSIGN _ r1 r2 = JSAssign (translateReg r1) (translateReg r2)
506jsASSIGNCONST :: CompileInfo -> Reg -> Const -> JS
507jsASSIGNCONST _ r c = JSAssign (translateReg r) (translateConstant c)
509jsCALL :: CompileInfo -> Name -> JS
513 ) [JSIdent (translateName n), JSArray [jsMYOLDBASE]]
515jsTAILCALL :: CompileInfo -> Name -> JS
519 ) [JSIdent (translateName n), JSArray [jsOLDBASE]]
521jsFOREIGN :: CompileInfo -> Reg -> String -> [(FType, Reg)] -> JS
522jsFOREIGN _ reg n args
524 , [(FString, arg)] <- args =
528 JSApp (JSIdent "i$putStr") [translateReg arg]
532 , [(FPtr, arg)] <- args =
536 JSBinOp "==" (translateReg arg) JSNull
540 , [(_, lhs),(_, rhs)] <- args =
544 JSBinOp "==" (translateReg lhs) (translateReg rhs)
550 JSFFI n (map generateWrapper args)
553 generateWrapper :: (FType, Reg) -> JS
554 generateWrapper (ty, reg)
556 JSApp (JSIdent "i$ffiWrap") [ translateReg reg
558 , JSIdent "myoldbase"
560 | FFunctionIO <- ty =
561 JSApp (JSIdent "i$ffiWrap") [ translateReg reg
563 , JSIdent "myoldbase"
566 generateWrapper (_, reg) =
569jsREBASE :: CompileInfo -> JS
570jsREBASE _ = JSAssign jsSTACKBASE jsOLDBASE
572jsSTOREOLD :: CompileInfo ->JS
573jsSTOREOLD _ = JSAssign jsMYOLDBASE jsSTACKBASE
575jsADDTOP :: CompileInfo -> Int -> JS
579 JSBinOp "+=" jsSTACKTOP (JSNum (JSInt n))
581jsTOPBASE :: CompileInfo -> Int -> JS
582jsTOPBASE _ 0 = JSAssign jsSTACKTOP jsSTACKBASE
583jsTOPBASE _ n = JSAssign jsSTACKTOP (JSBinOp "+" jsSTACKBASE (JSNum (JSInt n)))
586jsBASETOP :: CompileInfo -> Int -> JS
587jsBASETOP _ 0 = JSAssign jsSTACKBASE jsSTACKTOP
588jsBASETOP _ n = JSAssign jsSTACKBASE (JSBinOp "+" jsSTACKTOP (JSNum (JSInt n)))
590jsNULL :: CompileInfo -> Reg -> JS
591jsNULL _ r = JSAssign (translateReg r) JSNull
593jsERROR :: CompileInfo -> String -> JS
596jsSLIDE :: CompileInfo -> Int -> JS
597jsSLIDE _ 1 = JSAssign (jsLOC 0) (jsTOP 0)
598jsSLIDE _ n = JSApp (JSIdent "i$SLIDE") [JSNum (JSInt n)]
600jsMKCON :: CompileInfo -> Reg -> Int -> [Reg] -> JS
602 JSAssign (translateReg r) (
603 JSNew "i$CON" [ JSNum (JSInt t)
604 , JSArray (map translateReg rs)
605 , if t `elem` compileInfoApplyCases info
606 then JSIdent $ translateName (sMN 0 "APPLY") ++ "$" ++ show t
608 , if t `elem` compileInfoEvalCases info
609 then JSIdent $ translateName (sMN 0 "EVAL") ++ "$" ++ show t
614jsCASE :: CompileInfo -> Bool -> Reg -> [(Int, [BC])] -> Maybe [BC] -> JS
615jsCASE info safe reg cases def =
616 JSSwitch (tag safe $ translateReg reg) (
617 map ((JSNum . JSInt) *** prepBranch) cases
618 ) (fmap prepBranch def)
620 tag :: Bool -> JS -> JS
624 prepBranch :: [BC] -> JS
625 prepBranch bc = JSSeq $ map (translateBC info) bc
629 (JSTernary (js `jsInstanceOf` "i$CON") (
631 ) (JSNum (JSInt $ negate 1)))
634 jsCTAG js = JSProj js "tag"
637jsCONSTCASE :: CompileInfo -> Reg -> [(Const, [BC])] -> Maybe [BC] -> JS
638jsCONSTCASE info reg cases def =
640 map (jsEq (translateReg reg) . translateConstant *** prepBranch) cases
641 ) ++ (maybe [] ((:[]) . ((,) JSNoop) . prepBranch) def)
643 prepBranch :: [BC] -> JS
644 prepBranch bc = JSSeq $ map (translateBC info) bc
646jsPROJECT :: CompileInfo -> Reg -> Int -> Int -> JS
647jsPROJECT _ reg loc 0 = JSNoop
648jsPROJECT _ reg loc 1 =
649 JSAssign (jsLOC loc) (
651 JSProj (translateReg reg) "args"
656jsPROJECT _ reg loc ar =
657 JSApp (JSIdent "i$PROJECT") [ translateReg reg
662jsOP :: CompileInfo -> Reg -> PrimFn -> [Reg] -> JS
663jsOP _ reg op args = JSAssign (translateReg reg) jsOP'
667 | LNoOp <- op = translateReg (last args)
669 | (LZExt (ITFixed IT8) ITNative) <- op = jsUnPackBits $ translateReg (last args)
670 | (LZExt (ITFixed IT16) ITNative) <- op = jsUnPackBits $ translateReg (last args)
671 | (LZExt (ITFixed IT32) ITNative) <- op = jsUnPackBits $ translateReg (last args)
673 | (LZExt _ ITBig) <- op = jsBigInt $ JSApp (JSIdent "String") [translateReg (last args)]
674 | (LPlus (ATInt ITBig)) <- op
675 , (lhs:rhs:_) <- args = invokeMeth lhs "add" [rhs]
676 | (LMinus (ATInt ITBig)) <- op
677 , (lhs:rhs:_) <- args = invokeMeth lhs "subtract" [rhs]
678 | (LTimes (ATInt ITBig)) <- op
679 , (lhs:rhs:_) <- args = invokeMeth lhs "multiply" [rhs]
680 | (LSDiv (ATInt ITBig)) <- op
681 , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
682 | (LSRem (ATInt ITBig)) <- op
683 , (lhs:rhs:_) <- args = invokeMeth lhs "mod" [rhs]
684 | (LEq (ATInt ITBig)) <- op
685 , (lhs:rhs:_) <- args = invokeMeth lhs "equals" [rhs]
686 | (LSLt (ATInt ITBig)) <- op
687 , (lhs:rhs:_) <- args = invokeMeth lhs "lesser" [rhs]
688 | (LSLe (ATInt ITBig)) <- op
689 , (lhs:rhs:_) <- args = invokeMeth lhs "lesserOrEquals" [rhs]
690 | (LSGt (ATInt ITBig)) <- op
691 , (lhs:rhs:_) <- args = invokeMeth lhs "greater" [rhs]
692 | (LSGe (ATInt ITBig)) <- op
693 , (lhs:rhs:_) <- args = invokeMeth lhs "greaterOrEquals" [rhs]
695 | (LPlus ATFloat) <- op
696 , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
697 | (LMinus ATFloat) <- op
698 , (lhs:rhs:_) <- args = translateBinaryOp "-" lhs rhs
699 | (LTimes ATFloat) <- op
700 , (lhs:rhs:_) <- args = translateBinaryOp "*" lhs rhs
701 | (LSDiv ATFloat) <- op
702 , (lhs:rhs:_) <- args = translateBinaryOp "/" lhs rhs
703 | (LEq ATFloat) <- op
704 , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
705 | (LSLt ATFloat) <- op
706 , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
707 | (LSLe ATFloat) <- op
708 , (lhs:rhs:_) <- args = translateBinaryOp "<=" lhs rhs
709 | (LSGt ATFloat) <- op
710 , (lhs:rhs:_) <- args = translateBinaryOp ">" lhs rhs
711 | (LSGe ATFloat) <- op
712 , (lhs:rhs:_) <- args = translateBinaryOp ">=" lhs rhs
714 | (LPlus (ATInt ITChar)) <- op
715 , (lhs:rhs:_) <- args =
716 jsCall "i$fromCharCode" [
718 jsCall "i$charCode" [translateReg lhs]
720 jsCall "i$charCode" [translateReg rhs]
724 | (LTrunc (ITFixed IT16) (ITFixed IT8)) <- op
727 JSBinOp "&" (jsUnPackBits $ translateReg arg) (JSNum (JSInt 0xFF))
730 | (LTrunc (ITFixed IT32) (ITFixed IT16)) <- op
733 JSBinOp "&" (jsUnPackBits $ translateReg arg) (JSNum (JSInt 0xFFFF))
736 | (LTrunc (ITFixed IT64) (ITFixed IT32)) <- op
739 jsMeth (jsMeth (translateReg arg) "and" [
740 jsBigInt (JSString $ show 0xFFFFFFFF)
744 | (LTrunc ITBig (ITFixed IT64)) <- op
746 jsMeth (translateReg arg) "and" [
747 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
750 | (LLSHR (ITFixed IT8)) <- op
751 , (lhs:rhs:_) <- args =
753 JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
756 | (LLSHR (ITFixed IT16)) <- op
757 , (lhs:rhs:_) <- args =
759 JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
762 | (LLSHR (ITFixed IT32)) <- op
763 , (lhs:rhs:_) <- args =
765 JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
768 | (LLSHR (ITFixed IT64)) <- op
769 , (lhs:rhs:_) <- args =
770 jsMeth (translateReg lhs) "shiftRight" [translateReg rhs]
772 | (LSHL (ITFixed IT8)) <- op
773 , (lhs:rhs:_) <- args =
775 JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
778 | (LSHL (ITFixed IT16)) <- op
779 , (lhs:rhs:_) <- args =
781 JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
784 | (LSHL (ITFixed IT32)) <- op
785 , (lhs:rhs:_) <- args =
787 JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
790 | (LSHL (ITFixed IT64)) <- op
791 , (lhs:rhs:_) <- args =
792 jsMeth (jsMeth (translateReg lhs) "shiftLeft" [translateReg rhs]) "and" [
793 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
796 | (LAnd (ITFixed IT8)) <- op
797 , (lhs:rhs:_) <- args =
799 JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
802 | (LAnd (ITFixed IT16)) <- op
803 , (lhs:rhs:_) <- args =
805 JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
808 | (LAnd (ITFixed IT32)) <- op
809 , (lhs:rhs:_) <- args =
811 JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
814 | (LAnd (ITFixed IT64)) <- op
815 , (lhs:rhs:_) <- args =
816 jsMeth (translateReg lhs) "and" [translateReg rhs]
818 | (LOr (ITFixed IT8)) <- op
819 , (lhs:rhs:_) <- args =
821 JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
824 | (LOr (ITFixed IT16)) <- op
825 , (lhs:rhs:_) <- args =
827 JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
830 | (LOr (ITFixed IT32)) <- op
831 , (lhs:rhs:_) <- args =
833 JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
836 | (LOr (ITFixed IT64)) <- op
837 , (lhs:rhs:_) <- args =
838 jsMeth (translateReg lhs) "or" [translateReg rhs]
840 | (LXOr (ITFixed IT8)) <- op
841 , (lhs:rhs:_) <- args =
843 JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
846 | (LXOr (ITFixed IT16)) <- op
847 , (lhs:rhs:_) <- args =
849 JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
852 | (LXOr (ITFixed IT32)) <- op
853 , (lhs:rhs:_) <- args =
855 JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
858 | (LXOr (ITFixed IT64)) <- op
859 , (lhs:rhs:_) <- args =
860 jsMeth (translateReg lhs) "xor" [translateReg rhs]
862 | (LPlus (ATInt (ITFixed IT8))) <- op
863 , (lhs:rhs:_) <- args =
865 JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
868 | (LPlus (ATInt (ITFixed IT16))) <- op
869 , (lhs:rhs:_) <- args =
871 JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
874 | (LPlus (ATInt (ITFixed IT32))) <- op
875 , (lhs:rhs:_) <- args =
877 JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
880 | (LPlus (ATInt (ITFixed IT64))) <- op
881 , (lhs:rhs:_) <- args =
882 jsMeth (jsMeth (translateReg lhs) "add" [translateReg rhs]) "and" [
883 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
886 | (LMinus (ATInt (ITFixed IT8))) <- op
887 , (lhs:rhs:_) <- args =
889 JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
892 | (LMinus (ATInt (ITFixed IT16))) <- op
893 , (lhs:rhs:_) <- args =
895 JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
898 | (LMinus (ATInt (ITFixed IT32))) <- op
899 , (lhs:rhs:_) <- args =
901 JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
904 | (LMinus (ATInt (ITFixed IT64))) <- op
905 , (lhs:rhs:_) <- args =
906 jsMeth (jsMeth (translateReg lhs) "subtract" [translateReg rhs]) "and" [
907 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
910 | (LTimes (ATInt (ITFixed IT8))) <- op
911 , (lhs:rhs:_) <- args =
913 JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
916 | (LTimes (ATInt (ITFixed IT16))) <- op
917 , (lhs:rhs:_) <- args =
919 JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
922 | (LTimes (ATInt (ITFixed IT32))) <- op
923 , (lhs:rhs:_) <- args =
925 JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
928 | (LTimes (ATInt (ITFixed IT64))) <- op
929 , (lhs:rhs:_) <- args =
930 jsMeth (jsMeth (translateReg lhs) "multiply" [translateReg rhs]) "and" [
931 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
934 | (LEq (ATInt (ITFixed IT8))) <- op
935 , (lhs:rhs:_) <- args =
937 JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
940 | (LEq (ATInt (ITFixed IT16))) <- op
941 , (lhs:rhs:_) <- args =
943 JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
946 | (LEq (ATInt (ITFixed IT32))) <- op
947 , (lhs:rhs:_) <- args =
949 JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
952 | (LEq (ATInt (ITFixed IT64))) <- op
953 , (lhs:rhs:_) <- args =
954 jsMeth (jsMeth (translateReg lhs) "equals" [translateReg rhs]) "and" [
955 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
958 | (LLt (ITFixed IT8)) <- op
959 , (lhs:rhs:_) <- args =
961 JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
964 | (LLt (ITFixed IT16)) <- op
965 , (lhs:rhs:_) <- args =
967 JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
970 | (LLt (ITFixed IT32)) <- op
971 , (lhs:rhs:_) <- args =
973 JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
976 | (LLt (ITFixed IT64)) <- op
977 , (lhs:rhs:_) <- args = invokeMeth lhs "lesser" [rhs]
979 | (LLe (ITFixed IT8)) <- op
980 , (lhs:rhs:_) <- args =
982 JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
985 | (LLe (ITFixed IT16)) <- op
986 , (lhs:rhs:_) <- args =
988 JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
991 | (LLe (ITFixed IT32)) <- op
992 , (lhs:rhs:_) <- args =
994 JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
997 | (LLe (ITFixed IT64)) <- op
998 , (lhs:rhs:_) <- args = invokeMeth lhs "lesserOrEquals" [rhs]
1000 | (LGt (ITFixed IT8)) <- op
1001 , (lhs:rhs:_) <- args =
1003 JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1006 | (LGt (ITFixed IT16)) <- op
1007 , (lhs:rhs:_) <- args =
1009 JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1011 | (LGt (ITFixed IT32)) <- op
1012 , (lhs:rhs:_) <- args =
1014 JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1017 | (LGt (ITFixed IT64)) <- op
1018 , (lhs:rhs:_) <- args = invokeMeth lhs "greater" [rhs]
1020 | (LGe (ITFixed IT8)) <- op
1021 , (lhs:rhs:_) <- args =
1023 JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1026 | (LGe (ITFixed IT16)) <- op
1027 , (lhs:rhs:_) <- args =
1029 JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1031 | (LGe (ITFixed IT32)) <- op
1032 , (lhs:rhs:_) <- args =
1034 JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1037 | (LGe (ITFixed IT64)) <- op
1038 , (lhs:rhs:_) <- args = invokeMeth lhs "greaterOrEquals" [rhs]
1040 | (LUDiv (ITFixed IT8)) <- op
1041 , (lhs:rhs:_) <- args =
1043 JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1046 | (LUDiv (ITFixed IT16)) <- op
1047 , (lhs:rhs:_) <- args =
1049 JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1052 | (LUDiv (ITFixed IT32)) <- op
1053 , (lhs:rhs:_) <- args =
1055 JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
1058 | (LUDiv (ITFixed IT64)) <- op
1059 , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
1061 | (LSDiv (ATInt (ITFixed IT8))) <- op
1062 , (lhs:rhs:_) <- args =
1065 jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg lhs)
1067 jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg rhs)
1071 | (LSDiv (ATInt (ITFixed IT16))) <- op
1072 , (lhs:rhs:_) <- args =
1075 jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg lhs)
1077 jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg rhs)
1081 | (LSDiv (ATInt (ITFixed IT32))) <- op
1082 , (lhs:rhs:_) <- args =
1085 jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg lhs)
1087 jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg rhs)
1091 | (LSDiv (ATInt (ITFixed IT64))) <- op
1092 , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
1094 | (LSRem (ATInt (ITFixed IT8))) <- op
1095 , (lhs:rhs:_) <- args =
1098 jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg lhs)
1100 jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg rhs)
1104 | (LSRem (ATInt (ITFixed IT16))) <- op
1105 , (lhs:rhs:_) <- args =
1108 jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg lhs)
1110 jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg rhs)
1114 | (LSRem (ATInt (ITFixed IT32))) <- op
1115 , (lhs:rhs:_) <- args =
1118 jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg lhs)
1120 jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg rhs)
1124 | (LSRem (ATInt (ITFixed IT64))) <- op
1125 , (lhs:rhs:_) <- args = invokeMeth lhs "mod" [rhs]
1127 | (LCompl (ITFixed IT8)) <- op
1129 jsPackSBits8 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1131 | (LCompl (ITFixed IT16)) <- op
1133 jsPackSBits16 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1135 | (LCompl (ITFixed IT32)) <- op
1137 jsPackSBits32 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1139 | (LCompl (ITFixed IT64)) <- op
1141 invokeMeth arg "not" []
1144 , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
1146 , (lhs:rhs:_) <- args = translateBinaryOp "-" lhs rhs
1148 , (lhs:rhs:_) <- args = translateBinaryOp "*" lhs rhs
1150 , (lhs:rhs:_) <- args = translateBinaryOp "/" lhs rhs
1152 , (lhs:rhs:_) <- args = translateBinaryOp "%" lhs rhs
1154 , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
1156 , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
1158 , (lhs:rhs:_) <- args = translateBinaryOp "<=" lhs rhs
1160 , (lhs:rhs:_) <- args = translateBinaryOp ">" lhs rhs
1162 , (lhs:rhs:_) <- args = translateBinaryOp ">=" lhs rhs
1164 , (lhs:rhs:_) <- args = translateBinaryOp "&" lhs rhs
1166 , (lhs:rhs:_) <- args = translateBinaryOp "|" lhs rhs
1168 , (lhs:rhs:_) <- args = translateBinaryOp "^" lhs rhs
1170 , (lhs:rhs:_) <- args = translateBinaryOp "<<" rhs lhs
1172 , (lhs:rhs:_) <- args = translateBinaryOp ">>" rhs lhs
1174 , (arg:_) <- args = JSPreOp "~" (translateReg arg)
1177 , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
1179 , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
1181 , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
1183 , (arg:_) <- args = JSProj (translateReg arg) "length"
1184 | (LStrInt ITNative) <- op
1185 , (arg:_) <- args = jsCall "parseInt" [translateReg arg]
1186 | (LIntStr ITNative) <- op
1187 , (arg:_) <- args = jsCall "String" [translateReg arg]
1188 | (LSExt ITNative ITBig) <- op
1189 , (arg:_) <- args = jsBigInt $ jsCall "String" [translateReg arg]
1190 | (LTrunc ITBig ITNative) <- op
1191 , (arg:_) <- args = jsMeth (translateReg arg) "intValue" []
1192 | (LIntStr ITBig) <- op
1193 , (arg:_) <- args = jsMeth (translateReg arg) "toString" []
1194 | (LStrInt ITBig) <- op
1195 , (arg:_) <- args = jsBigInt $ translateReg arg
1197 , (arg:_) <- args = jsCall "String" [translateReg arg]
1199 , (arg:_) <- args = jsCall "parseFloat" [translateReg arg]
1200 | (LIntFloat ITNative) <- op
1201 , (arg:_) <- args = translateReg arg
1202 | (LFloatInt ITNative) <- op
1203 , (arg:_) <- args = translateReg arg
1204 | (LChInt ITNative) <- op
1205 , (arg:_) <- args = jsCall "i$charCode" [translateReg arg]
1206 | (LIntCh ITNative) <- op
1207 , (arg:_) <- args = jsCall "i$fromCharCode" [translateReg arg]
1210 , (arg:_) <- args = jsCall "Math.exp" [translateReg arg]
1212 , (arg:_) <- args = jsCall "Math.log" [translateReg arg]
1214 , (arg:_) <- args = jsCall "Math.sin" [translateReg arg]
1216 , (arg:_) <- args = jsCall "Math.cos" [translateReg arg]
1218 , (arg:_) <- args = jsCall "Math.tan" [translateReg arg]
1220 , (arg:_) <- args = jsCall "Math.asin" [translateReg arg]
1222 , (arg:_) <- args = jsCall "Math.acos" [translateReg arg]
1224 , (arg:_) <- args = jsCall "Math.atan" [translateReg arg]
1226 , (arg:_) <- args = jsCall "Math.sqrt" [translateReg arg]
1228 , (arg:_) <- args = jsCall "Math.floor" [translateReg arg]
1230 , (arg:_) <- args = jsCall "Math.ceil" [translateReg arg]
1233 , (lhs:rhs:_) <- args = invokeMeth lhs "concat" [rhs]
1235 , (arg:_) <- args = JSIndex (translateReg arg) (JSNum (JSInt 0))
1237 , (arg:_) <- args = JSProj (translateReg arg) "split('').reverse().join('')"
1239 , (lhs:rhs:_) <- args = JSIndex (translateReg lhs) (translateReg rhs)
1242 let v = translateReg arg in
1243 JSApp (JSProj v "substr") [
1245 JSBinOp "-" (JSProj v "length") (JSNum (JSInt 1))
1249 , (arg:_) <- args = jsCall "i$systemInfo" [translateReg arg]
1251 , (_) <- args = JSNull
1252 | otherwise = JSError $ "Not implemented: " ++ show op
1254 translateBinaryOp :: String -> Reg -> Reg -> JS
1255 translateBinaryOp op lhs rhs =
1256 JSBinOp op (translateReg lhs) (translateReg rhs)
1258 invokeMeth :: Reg -> String -> [Reg] -> JS
1259 invokeMeth obj meth args =
1260 JSApp (JSProj (translateReg obj) meth) $ map translateReg args
1263jsRESERVE :: CompileInfo -> Int -> JS
1264jsRESERVE _ _ = JSNoop
1267jsSTACK = JSIdent "i$valstack"
1270jsCALLSTACK = JSIdent "i$callstack"
1273jsSTACKBASE = JSIdent "i$valstack_base"
1276jsSTACKTOP = JSIdent "i$valstack_top"
1279jsOLDBASE = JSIdent "oldbase"
1282jsMYOLDBASE = JSIdent "myoldbase"
1285jsRET = JSIdent "i$ret"
1288jsLOC 0 = JSIndex jsSTACK jsSTACKBASE
1289jsLOC n = JSIndex jsSTACK (JSBinOp "+" jsSTACKBASE (JSNum (JSInt n)))
1292jsTOP 0 = JSIndex jsSTACK jsSTACKTOP
1293jsTOP n = JSIndex jsSTACK (JSBinOp "+" jsSTACKTOP (JSNum (JSInt n)))
1296jsPUSH args = JSApp (JSProj jsCALLSTACK "push") args
1299jsPOP = JSApp (JSProj jsCALLSTACK "pop") []
1301translateBC :: CompileInfo -> BC -> JS
1303 | ASSIGN r1 r2 <- bc = jsASSIGN info r1 r2
1304 | ASSIGNCONST r c <- bc = jsASSIGNCONST info r c
1305 | UPDATE r1 r2 <- bc = jsASSIGN info r1 r2
1306 | ADDTOP n <- bc = jsADDTOP info n
1307 | NULL r <- bc = jsNULL info r
1308 | CALL n <- bc = jsCALL info n
1309 | TAILCALL n <- bc = jsTAILCALL info n
1310 | FOREIGNCALL r _ _ n a <- bc = jsFOREIGN info r n a
1311 | TOPBASE n <- bc = jsTOPBASE info n
1312 | BASETOP n <- bc = jsBASETOP info n
1313 | STOREOLD <- bc = jsSTOREOLD info
1314 | SLIDE n <- bc = jsSLIDE info n
1315 | REBASE <- bc = jsREBASE info
1316 | RESERVE n <- bc = jsRESERVE info n
1317 | MKCON r t rs <- bc = jsMKCON info r t rs
1318 | CASE s r c d <- bc = jsCASE info s r c d
1319 | CONSTCASE r c d <- bc = jsCONSTCASE info r c d
1320 | PROJECT r l a <- bc = jsPROJECT info r l a
1321 | OP r o a <- bc = jsOP info r o a
1322 | ERROR e <- bc = jsERROR info e
1323 | otherwise = JSRaw $ "//" ++ show bc
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list