1{-# LANGUAGE PatternGuards #-}
2module IRTS.CodegenJavaScript (codegenJavaScript, codegenNode, JSTarget(..)) where
4import Idris.AbsSyntax hiding (TypeCase)
8import IRTS.CodegenCommon
14import Control.Applicative ((<$>), (<*>), pure)
21import System.Directory
25idrNamespace = "__IDR__"
26idrRTNamespace = "__IDRRT__"
27idrLTNamespace = "__IDRLT__"
28idrCTRNamespace = "__IDRCTR__"
31data JSTarget = Node | JavaScript deriving Eq
44data JSInteger = JSBigZero
57data JSWord = JSWord8 Word8
64data JSAnnotation = JSConstructor deriving Eq
67instance Show JSAnnotation where
68 show JSConstructor = "constructor"
73 | JSFunction [String] JS
80 | JSBinOp String JS JS
93 | JSAlloc String (Maybe JS)
95 | JSSwitch JS [(JS, JS)] (Maybe JS)
101 | JSAnnotation JSAnnotation JS
106data FFI = FFICode Char | FFIArg Int | FFIError String
108compileJS :: JS -> String
111compileJS (JSAnnotation annotation js) =
112 "/** @" ++ show annotation ++ " */\n" ++ compileJS js
114{-compileJS (JSFFI raw args) =-}
115 {-ffi raw (map compileJS args)-}
117compileJS (JSRaw code) =
120compileJS (JSIdent ident) =
123compileJS (JSFunction args body) =
125 ++ intercalate "," args
131 | JSIntTy <- ty = idrRTNamespace ++ "Int"
132 | JSStringTy <- ty = idrRTNamespace ++ "String"
133 | JSIntegerTy <- ty = idrRTNamespace ++ "Integer"
134 | JSFloatTy <- ty = idrRTNamespace ++ "Float"
135 | JSCharTy <- ty = idrRTNamespace ++ "Char"
136 | JSPtrTy <- ty = idrRTNamespace ++ "Ptr"
137 | JSForgotTy <- ty = idrRTNamespace ++ "Forgot"
139compileJS (JSSeq seq) =
140 intercalate ";\n" (map compileJS $ filter (/= JSNoop) seq) ++ ";"
142compileJS (JSReturn val) =
143 "return " ++ compileJS val
145compileJS (JSApp lhs rhs)
146 | JSFunction {} <- lhs =
147 concat ["(", compileJS lhs, ")(", args, ")"]
149 concat [compileJS lhs, "(", args, ")"]
151 args = intercalate "," $ map compileJS rhs
153compileJS (JSNew name args) =
154 "new " ++ name ++ "(" ++ intercalate "," (map compileJS args) ++ ")"
156compileJS (JSError exc) =
157 "throw new Error(\"" ++ exc ++ "\")"
159compileJS (JSBinOp op lhs rhs) =
160 compileJS lhs ++ " " ++ op ++ " " ++ compileJS rhs
162compileJS (JSPreOp op val) =
165compileJS (JSProj obj field)
166 | JSFunction {} <- obj =
167 concat ["(", compileJS obj, ").", field]
168 | JSAssign {} <- obj =
169 concat ["(", compileJS obj, ").", field]
171 compileJS obj ++ '.' : field
185compileJS (JSArray elems) =
186 "[" ++ intercalate "," (map compileJS elems) ++ "]"
188compileJS (JSString str) =
192 | JSInt i <- num = show i
193 | JSFloat f <- num = show f
194 | JSInteger JSBigZero <- num = "__IDRRT__ZERO"
195 | JSInteger JSBigOne <- num = "__IDRRT__ONE"
196 | JSInteger (JSBigInt i) <- num = show i
197 | JSInteger (JSBigIntExpr e) <- num = "__IDRRT__bigInt(" ++ compileJS e ++ ")"
199compileJS (JSAssign lhs rhs) =
200 compileJS lhs ++ " = " ++ compileJS rhs
202compileJS (JSAlloc name val) =
203 "var " ++ name ++ maybe "" ((" = " ++) . compileJS) val
205compileJS (JSIndex lhs rhs) =
206 compileJS lhs ++ "[" ++ compileJS rhs ++ "]"
208compileJS (JSCond branches) =
209 intercalate " else " $ map createIfBlock branches
211 createIfBlock (JSNoop, e) =
215 createIfBlock (cond, e) =
216 "if (" ++ compileJS cond ++") {\n"
220compileJS (JSSwitch val branches def) =
221 "switch(" ++ compileJS val ++ "){\n"
222 ++ concatMap mkBranch branches
226 mkBranch :: (JS, JS) -> String
227 mkBranch (tag, code) =
228 "case " ++ compileJS tag ++ ":\n"
232 mkDefault :: Maybe JS -> String
233 mkDefault Nothing = ""
234 mkDefault (Just def) =
240compileJS (JSTernary cond true false) =
241 let c = compileJS cond
243 f = compileJS false in
244 "(" ++ c ++ ")?(" ++ t ++ "):(" ++ f ++ ")"
246compileJS (JSParens js) =
247 "(" ++ compileJS js ++ ")"
249compileJS (JSWhile cond body) =
250 "while (" ++ compileJS cond ++ ") {\n"
254compileJS (JSWord word)
255 | JSWord8 b <- word = "new Uint8Array([" ++ show b ++ "])"
256 | JSWord16 b <- word = "new Uint16Array([" ++ show b ++ "])"
257 | JSWord32 b <- word = "new Uint32Array([" ++ show b ++ "])"
258 | JSWord64 b <- word = idrRTNamespace ++ "bigInt(\"" ++ show b ++ "\")"
260codegenJavaScript :: CodeGenerator
261codegenJavaScript ci = codegenJS_all JavaScript (simpleDecls ci)
262 (includes ci) (outputFile ci) (outputType ci)
264codegenNode :: CodeGenerator
265codegenNode ci = codegenJS_all Node (simpleDecls ci)
266 (includes ci) (outputFile ci) (outputType ci)
275codegenJS_all target definitions includes filename outputType = do
276 let code = map (compileJS . translateDecl . toBC) definitions
277 let (header, rt) = case target of
279 ("#!/usr/bin/env node\n", "-node")
282 path <- (++) <$> getDataDir <*> (pure "/jsrts/")
283 idrRuntime <- readFile $ path ++ "Runtime-common.js"
284 tgtRuntime <- readFile $ concat [path, "Runtime", rt, ".js"]
285 jsbn <- readFile $ path ++ "jsbn/jsbn.js"
286 let runtime = header ++ jsbn ++ idrRuntime ++ tgtRuntime
287 writeFile filename $ runtime ++ concat code ++ main ++ invokeMain
288 setPermissions filename (emptyPermissions { readable = True
289 , executable = target == Node
295 JSAlloc "main" $ Just $ JSFunction [] (
296 JSSeq [ JSAlloc "vm" (Just $ JSNew "i$VM" [])
298 JSIdent (translateName (sMN 0 "runMain"))
306 invokeMain = compileJS $ JSApp (JSIdent "main") []
309translateDecl :: (Name, [BC]) -> JS
310translateDecl (name, bc) =
313 ) (Just $ JSFunction ["vm", "oldbase"] (
314 JSSeq $ JSAlloc "myoldbase" Nothing : map translateBC bc)
317translateReg :: Reg -> JS
319 | RVal <- reg = JSProj (JSIdent "vm") "ret"
320 | Tmp <- reg = JSProj (JSIdent "vm") "reg1"
323 JSProj (JSIdent "vm") "valstack"
324 ) (JSProj (JSIdent "vm") "valstack_base")
327 JSProj (JSIdent "vm") "valstack"
329 JSBinOp "+" (JSProj (JSIdent "vm") "valstack_base") (JSNum (JSInt n))
333 JSProj (JSIdent "vm") "valstack"
334 ) (JSProj (JSIdent "vm") "valstack_top")
337 JSProj (JSIdent "vm") "valstack"
339 JSBinOp "+" (JSProj (JSIdent "vm") "valstack_top") (JSNum (JSInt n))
342translateConstant :: Const -> JS
343translateConstant (I i) = JSNum (JSInt i)
344translateConstant (Fl f) = JSNum (JSFloat f)
345translateConstant (Ch c) = JSString $ translateChar c
346translateConstant (Str s) = JSString $ concatMap translateChar s
347translateConstant (AType (ATInt ITNative)) = JSType JSIntTy
348translateConstant StrType = JSType JSStringTy
349translateConstant (AType (ATInt ITBig)) = JSType JSIntegerTy
350translateConstant (AType ATFloat) = JSType JSFloatTy
351translateConstant (AType (ATInt ITChar)) = JSType JSCharTy
352translateConstant PtrType = JSType JSPtrTy
353translateConstant Forgot = JSType JSForgotTy
354translateConstant (BI i) = jsBigInt (JSString $ show i)
355translateConstant (BI 0) = JSNum (JSInteger JSBigZero)
356translateConstant (BI 1) = JSNum (JSInteger JSBigOne)
357translateConstant (B8 b) = JSWord (JSWord8 b)
358translateConstant (B16 b) = JSWord (JSWord16 b)
359translateConstant (B32 b) = JSWord (JSWord32 b)
360translateConstant (B64 b) = JSWord (JSWord64 b)
362 jsERROR $ "Unimplemented Constant: " ++ show c
365translateChar :: Char -> String
367 | '\a' <- ch = "\\u0007"
374 | '\SO' <- ch = "\\u000E"
375 | '\DEL' <- ch = "\\u007F"
376 | '\\' <- ch = "\\\\"
377 | '\"' <- ch = "\\\""
378 | '\'' <- ch = "\\\'"
379 | ch `elem` asciiTab = "\\u00" ++ fill (showIntAtBase 16 intToDigit (ord ch) "")
382 fill :: String -> String
383 fill s = if length s == 1
388 ['\NUL', '\SOH', '\STX', '\ETX', '\EOT', '\ENQ', '\ACK', '\BEL',
389 '\BS', '\HT', '\LF', '\VT', '\FF', '\CR', '\SO', '\SI',
390 '\DLE', '\DC1', '\DC2', '\DC3', '\DC4', '\NAK', '\SYN', '\ETB',
391 '\CAN', '\EM', '\SUB', '\ESC', '\FS', '\GS', '\RS', '\US']
393translateName :: Name -> String
394translateName n = "_idris_" ++ concatMap cchar (showCG n)
395 where cchar x | isAlpha x || isDigit x = [x]
396 | otherwise = "_" ++ show (fromEnum x) ++ "_"
398jsASSIGN :: Reg -> Reg -> JS
399jsASSIGN r1 r2 = JSAssign (translateReg r1) (translateReg r2)
401jsASSIGNCONST :: Reg -> Const -> JS
402jsASSIGNCONST r c = JSAssign (translateReg r) (translateConstant c)
405jsCALL n = JSApp (JSIdent (translateName n)) [JSIdent "vm", JSIdent "myoldbase"]
407jsTAILCALL :: Name -> JS
408jsTAILCALL n = JSApp (JSIdent (translateName n)) [JSIdent "vm", JSIdent "oldbase"]
410jsFOREIGN :: Reg -> String -> [(FType, Reg)] -> JS
411jsFOREIGN reg n args =
415 JSApp (JSIdent n) (map (translateReg . snd) args)
421 JSProj (JSIdent "vm") "valstack_base"
431 JSProj (JSIdent "vm") "valstack_base"
438 JSBinOp "+=" (JSProj (JSIdent "vm") "valstack_top") (JSNum (JSInt n))
440jsTOPBASE :: Int -> JS
444 JSProj (JSIdent "vm") "valstack_top"
446 JSProj (JSIdent "vm") "valstack_base"
450 JSProj (JSIdent "vm") "valstack_top"
452 JSBinOp "+" (JSProj (JSIdent "vm") "valstack_base") (JSNum (JSInt n))
455jsBASETOP :: Int -> JS
459 JSProj (JSIdent "vm") "valstack_base"
461 JSProj (JSIdent "vm") "valstack_top"
465 JSProj (JSIdent "vm") "valstack_base"
467 JSBinOp "+" (JSProj (JSIdent "vm") "valstack_top") (JSNum (JSInt n))
471jsNULL r = JSAssign (translateReg r) JSNull
473jsERROR :: String -> JS
477jsSLIDE n = JSApp (JSIdent "i$SLIDE") [JSIdent "vm", JSNum (JSInt n)]
479jsMKCON :: Reg -> Int -> [Reg] -> JS
481 JSAssign (translateReg r) (
482 JSNew "i$CON" [JSNum (JSInt t), JSArray (map translateReg rs)]
485jsInstanceOf :: JS -> String -> JS
486jsInstanceOf obj cls = JSBinOp "instanceof" obj (JSIdent cls)
488jsOr :: JS -> JS -> JS
489jsOr lhs rhs = JSBinOp "||" lhs rhs
492jsTypeOf js = JSPreOp "typeof " js
494jsEq :: JS -> JS -> JS
495jsEq lhs@(JSNum (JSInteger _)) rhs = JSApp (JSProj lhs "equals") [rhs]
496jsEq lhs rhs@(JSNum (JSInteger _)) = JSApp (JSProj lhs "equals") [rhs]
497jsEq lhs rhs = JSBinOp "==" lhs rhs
499jsIsNumber :: JS -> JS
500jsIsNumber js = (jsTypeOf js) `jsEq` (JSString "number")
503jsIsNull js = JSBinOp "==" js JSNull
506jsBigInt (JSString "0") = JSNum (JSInteger JSBigZero)
507jsBigInt (JSString "1") = JSNum (JSInteger JSBigOne)
508jsBigInt js = JSNum $ JSInteger $ JSBigIntExpr js
510jsUnPackBits :: JS -> JS
511jsUnPackBits js = JSIndex js $ JSNum (JSInt 0)
513jsPackUBits8 :: JS -> JS
514jsPackUBits8 js = JSNew "Uint8Array" [JSArray [js]]
516jsPackUBits16 :: JS -> JS
517jsPackUBits16 js = JSNew "Uint16Array" [JSArray [js]]
519jsPackUBits32 :: JS -> JS
520jsPackUBits32 js = JSNew "Uint32Array" [JSArray [js]]
522jsPackSBits8 :: JS -> JS
523jsPackSBits8 js = JSNew "Int8Array" [JSArray [js]]
525jsPackSBits16 :: JS -> JS
526jsPackSBits16 js = JSNew "Int16Array" [JSArray [js]]
528jsPackSBits32 :: JS -> JS
529jsPackSBits32 js = JSNew "Int32Array" [JSArray [js]]
531jsCASE :: Bool -> Reg -> [(Int, [BC])] -> Maybe [BC] -> JS
532jsCASE safe reg cases def =
533 JSSwitch (tag safe $ translateReg reg) (
534 map ((JSNum . JSInt) *** prepBranch) cases
535 ) (fmap prepBranch def)
537 tag :: Bool -> JS -> JS
541 prepBranch :: [BC] -> JS
542 prepBranch bc = JSSeq $ map translateBC bc
546 JSTernary (jsIsNumber js `jsOr` jsIsNull js) (
547 JSNum (JSInt $ negate 1)
548 ) (JSTernary (js `jsInstanceOf` "i$CON") (
550 ) (JSNum (JSInt $ negate 1)))
553 jsCTAG js = JSProj js "tag"
556jsCONSTCASE :: Reg -> [(Const, [BC])] -> Maybe [BC] -> JS
557jsCONSTCASE reg cases def =
559 map (jsEq (translateReg reg) . translateConstant *** prepBranch) cases
560 ) ++ (maybe [] ((:[]) . ((,) JSNoop) . prepBranch) def)
562 prepBranch :: [BC] -> JS
563 prepBranch bc = JSSeq $ map translateBC bc
565jsPROJECT :: Reg -> Int -> Int -> JS
566jsPROJECT reg loc ar =
567 JSApp (JSIdent "i$PROJECT") [ JSIdent "vm"
573jsOP :: Reg -> PrimFn -> [Reg] -> JS
574jsOP reg op args = JSAssign (translateReg reg) jsOP'
578 | LNoOp <- op = translateReg (last args)
580 | (LZExt (ITFixed IT8) ITNative) <- op = jsUnPackBits $ translateReg (last args)
581 | (LZExt (ITFixed IT16) ITNative) <- op = jsUnPackBits $ translateReg (last args)
582 | (LZExt (ITFixed IT32) ITNative) <- op = jsUnPackBits $ translateReg (last args)
584 | (LZExt _ ITBig) <- op = jsBigInt $ JSApp (JSIdent "String") [translateReg (last args)]
585 | (LPlus (ATInt ITBig)) <- op
586 , (lhs:rhs:_) <- args = invokeMeth lhs "add" [rhs]
587 | (LMinus (ATInt ITBig)) <- op
588 , (lhs:rhs:_) <- args = invokeMeth lhs "subtract" [rhs]
589 | (LTimes (ATInt ITBig)) <- op
590 , (lhs:rhs:_) <- args = invokeMeth lhs "multiply" [rhs]
591 | (LSDiv (ATInt ITBig)) <- op
592 , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
593 | (LSRem (ATInt ITBig)) <- op
594 , (lhs:rhs:_) <- args = invokeMeth lhs "mod" [rhs]
595 | (LEq (ATInt ITBig)) <- op
596 , (lhs:rhs:_) <- args = invokeMeth lhs "equals" [rhs]
597 | (LSLt (ATInt ITBig)) <- op
598 , (lhs:rhs:_) <- args = invokeMeth lhs "lesser" [rhs]
599 | (LSLe (ATInt ITBig)) <- op
600 , (lhs:rhs:_) <- args = invokeMeth lhs "lesserOrEquals" [rhs]
601 | (LSGt (ATInt ITBig)) <- op
602 , (lhs:rhs:_) <- args = invokeMeth lhs "greater" [rhs]
603 | (LSGe (ATInt ITBig)) <- op
604 , (lhs:rhs:_) <- args = invokeMeth lhs "greaterOrEquals" [rhs]
606 | (LPlus ATFloat) <- op
607 , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
608 | (LMinus ATFloat) <- op
609 , (lhs:rhs:_) <- args = translateBinaryOp "-" lhs rhs
610 | (LTimes ATFloat) <- op
611 , (lhs:rhs:_) <- args = translateBinaryOp "*" lhs rhs
612 | (LSDiv ATFloat) <- op
613 , (lhs:rhs:_) <- args = translateBinaryOp "/" lhs rhs
614 | (LEq ATFloat) <- op
615 , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
616 | (LSLt ATFloat) <- op
617 , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
618 | (LSLe ATFloat) <- op
619 , (lhs:rhs:_) <- args = translateBinaryOp "<=" lhs rhs
620 | (LSGt ATFloat) <- op
621 , (lhs:rhs:_) <- args = translateBinaryOp ">" lhs rhs
622 | (LSGe ATFloat) <- op
623 , (lhs:rhs:_) <- args = translateBinaryOp ">=" lhs rhs
625 | (LPlus (ATInt ITChar)) <- op
626 , (lhs:rhs:_) <- args =
627 jsCall "__IDRRT__fromCharCode" [
629 jsCall "__IDRRT__charCode" [translateReg lhs]
631 jsCall "__IDRRT__charCode" [translateReg rhs]
635 | (LTrunc (ITFixed IT16) (ITFixed IT8)) <- op
638 JSBinOp "&" (jsUnPackBits $ translateReg arg) (JSNum (JSInt 0xFF))
641 | (LTrunc (ITFixed IT32) (ITFixed IT16)) <- op
644 JSBinOp "&" (jsUnPackBits $ translateReg arg) (JSNum (JSInt 0xFFFF))
647 | (LTrunc (ITFixed IT64) (ITFixed IT32)) <- op
650 jsMeth (jsMeth (translateReg arg) "and" [
651 jsBigInt (JSString $ show 0xFFFFFFFF)
655 | (LTrunc ITBig (ITFixed IT64)) <- op
657 jsMeth (translateReg arg) "and" [
658 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
661 | (LLSHR (ITFixed IT8)) <- op
662 , (lhs:rhs:_) <- args =
664 JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
667 | (LLSHR (ITFixed IT16)) <- op
668 , (lhs:rhs:_) <- args =
670 JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
673 | (LLSHR (ITFixed IT32)) <- op
674 , (lhs:rhs:_) <- args =
676 JSBinOp ">>" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
679 | (LLSHR (ITFixed IT64)) <- op
680 , (lhs:rhs:_) <- args =
681 jsMeth (translateReg lhs) "shiftRight" [translateReg rhs]
683 | (LSHL (ITFixed IT8)) <- op
684 , (lhs:rhs:_) <- args =
686 JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
689 | (LSHL (ITFixed IT16)) <- op
690 , (lhs:rhs:_) <- args =
692 JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
695 | (LSHL (ITFixed IT32)) <- op
696 , (lhs:rhs:_) <- args =
698 JSBinOp "<<" (jsUnPackBits $ translateReg lhs) (jsUnPackBits $ translateReg rhs)
701 | (LSHL (ITFixed IT64)) <- op
702 , (lhs:rhs:_) <- args =
703 jsMeth (jsMeth (translateReg lhs) "shiftLeft" [translateReg rhs]) "and" [
704 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
707 | (LAnd (ITFixed IT8)) <- op
708 , (lhs:rhs:_) <- args =
710 JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
713 | (LAnd (ITFixed IT16)) <- op
714 , (lhs:rhs:_) <- args =
716 JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
719 | (LAnd (ITFixed IT32)) <- op
720 , (lhs:rhs:_) <- args =
722 JSBinOp "&" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
725 | (LAnd (ITFixed IT64)) <- op
726 , (lhs:rhs:_) <- args =
727 jsMeth (translateReg lhs) "and" [translateReg rhs]
729 | (LOr (ITFixed IT8)) <- op
730 , (lhs:rhs:_) <- args =
732 JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
735 | (LOr (ITFixed IT16)) <- op
736 , (lhs:rhs:_) <- args =
738 JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
741 | (LOr (ITFixed IT32)) <- op
742 , (lhs:rhs:_) <- args =
744 JSBinOp "|" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
747 | (LOr (ITFixed IT64)) <- op
748 , (lhs:rhs:_) <- args =
749 jsMeth (translateReg lhs) "or" [translateReg rhs]
751 | (LXOr (ITFixed IT8)) <- op
752 , (lhs:rhs:_) <- args =
754 JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
757 | (LXOr (ITFixed IT16)) <- op
758 , (lhs:rhs:_) <- args =
760 JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
763 | (LXOr (ITFixed IT32)) <- op
764 , (lhs:rhs:_) <- args =
766 JSBinOp "^" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
769 | (LXOr (ITFixed IT64)) <- op
770 , (lhs:rhs:_) <- args =
771 jsMeth (translateReg lhs) "xor" [translateReg rhs]
773 | (LPlus (ATInt (ITFixed IT8))) <- op
774 , (lhs:rhs:_) <- args =
776 JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
779 | (LPlus (ATInt (ITFixed IT16))) <- op
780 , (lhs:rhs:_) <- args =
782 JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
785 | (LPlus (ATInt (ITFixed IT32))) <- op
786 , (lhs:rhs:_) <- args =
788 JSBinOp "+" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
791 | (LPlus (ATInt (ITFixed IT64))) <- op
792 , (lhs:rhs:_) <- args =
793 jsMeth (jsMeth (translateReg lhs) "add" [translateReg rhs]) "and" [
794 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
797 | (LMinus (ATInt (ITFixed IT8))) <- op
798 , (lhs:rhs:_) <- args =
800 JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
803 | (LMinus (ATInt (ITFixed IT16))) <- op
804 , (lhs:rhs:_) <- args =
806 JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
809 | (LMinus (ATInt (ITFixed IT32))) <- op
810 , (lhs:rhs:_) <- args =
812 JSBinOp "-" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
815 | (LMinus (ATInt (ITFixed IT64))) <- op
816 , (lhs:rhs:_) <- args =
817 jsMeth (jsMeth (translateReg lhs) "subtract" [translateReg rhs]) "and" [
818 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
821 | (LTimes (ATInt (ITFixed IT8))) <- op
822 , (lhs:rhs:_) <- args =
824 JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
827 | (LTimes (ATInt (ITFixed IT16))) <- op
828 , (lhs:rhs:_) <- args =
830 JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
833 | (LTimes (ATInt (ITFixed IT32))) <- op
834 , (lhs:rhs:_) <- args =
836 JSBinOp "*" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
839 | (LTimes (ATInt (ITFixed IT64))) <- op
840 , (lhs:rhs:_) <- args =
841 jsMeth (jsMeth (translateReg lhs) "multiply" [translateReg rhs]) "and" [
842 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
845 | (LEq (ATInt (ITFixed IT8))) <- op
846 , (lhs:rhs:_) <- args =
848 JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
851 | (LEq (ATInt (ITFixed IT16))) <- op
852 , (lhs:rhs:_) <- args =
854 JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
857 | (LEq (ATInt (ITFixed IT32))) <- op
858 , (lhs:rhs:_) <- args =
860 JSBinOp "==" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
863 | (LEq (ATInt (ITFixed IT64))) <- op
864 , (lhs:rhs:_) <- args =
865 jsMeth (jsMeth (translateReg lhs) "equals" [translateReg rhs]) "and" [
866 jsBigInt (JSString $ show 0xFFFFFFFFFFFFFFFF)
869 | (LLt (ITFixed IT8)) <- op
870 , (lhs:rhs:_) <- args =
872 JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
875 | (LLt (ITFixed IT16)) <- op
876 , (lhs:rhs:_) <- args =
878 JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
881 | (LLt (ITFixed IT32)) <- op
882 , (lhs:rhs:_) <- args =
884 JSBinOp "<" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
887 | (LLt (ITFixed IT64)) <- op
888 , (lhs:rhs:_) <- args = invokeMeth lhs "lesser" [rhs]
890 | (LLe (ITFixed IT8)) <- op
891 , (lhs:rhs:_) <- args =
893 JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
896 | (LLe (ITFixed IT16)) <- op
897 , (lhs:rhs:_) <- args =
899 JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
902 | (LLe (ITFixed IT32)) <- op
903 , (lhs:rhs:_) <- args =
905 JSBinOp "<=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
908 | (LLe (ITFixed IT64)) <- op
909 , (lhs:rhs:_) <- args = invokeMeth lhs "lesserOrEquals" [rhs]
911 | (LGt (ITFixed IT8)) <- op
912 , (lhs:rhs:_) <- args =
914 JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
917 | (LGt (ITFixed IT16)) <- op
918 , (lhs:rhs:_) <- args =
920 JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
922 | (LGt (ITFixed IT32)) <- op
923 , (lhs:rhs:_) <- args =
925 JSBinOp ">" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
928 | (LGt (ITFixed IT64)) <- op
929 , (lhs:rhs:_) <- args = invokeMeth lhs "greater" [rhs]
931 | (LGe (ITFixed IT8)) <- op
932 , (lhs:rhs:_) <- args =
934 JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
937 | (LGe (ITFixed IT16)) <- op
938 , (lhs:rhs:_) <- args =
940 JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
942 | (LGe (ITFixed IT32)) <- op
943 , (lhs:rhs:_) <- args =
945 JSBinOp ">=" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
948 | (LGe (ITFixed IT64)) <- op
949 , (lhs:rhs:_) <- args = invokeMeth lhs "greaterOrEquals" [rhs]
951 | (LUDiv (ITFixed IT8)) <- op
952 , (lhs:rhs:_) <- args =
954 JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
957 | (LUDiv (ITFixed IT16)) <- op
958 , (lhs:rhs:_) <- args =
960 JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
963 | (LUDiv (ITFixed IT32)) <- op
964 , (lhs:rhs:_) <- args =
966 JSBinOp "/" (jsUnPackBits (translateReg lhs)) (jsUnPackBits (translateReg rhs))
969 | (LUDiv (ITFixed IT64)) <- op
970 , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
972 | (LSDiv (ATInt (ITFixed IT8))) <- op
973 , (lhs:rhs:_) <- args =
976 jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg lhs)
978 jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg rhs)
982 | (LSDiv (ATInt (ITFixed IT16))) <- op
983 , (lhs:rhs:_) <- args =
986 jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg lhs)
988 jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg rhs)
992 | (LSDiv (ATInt (ITFixed IT32))) <- op
993 , (lhs:rhs:_) <- args =
996 jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg lhs)
998 jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg rhs)
1002 | (LSDiv (ATInt (ITFixed IT64))) <- op
1003 , (lhs:rhs:_) <- args = invokeMeth lhs "divide" [rhs]
1005 | (LSRem (ATInt (ITFixed IT8))) <- op
1006 , (lhs:rhs:_) <- args =
1009 jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg lhs)
1011 jsUnPackBits $ jsPackSBits8 $ jsUnPackBits (translateReg rhs)
1015 | (LSRem (ATInt (ITFixed IT16))) <- op
1016 , (lhs:rhs:_) <- args =
1019 jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg lhs)
1021 jsUnPackBits $ jsPackSBits16 $ jsUnPackBits (translateReg rhs)
1025 | (LSRem (ATInt (ITFixed IT32))) <- op
1026 , (lhs:rhs:_) <- args =
1029 jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg lhs)
1031 jsUnPackBits $ jsPackSBits32 $ jsUnPackBits (translateReg rhs)
1035 | (LSRem (ATInt (ITFixed IT64))) <- op
1036 , (lhs:rhs:_) <- args = invokeMeth lhs "mod" [rhs]
1038 | (LCompl (ITFixed IT8)) <- op
1040 jsPackSBits8 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1042 | (LCompl (ITFixed IT16)) <- op
1044 jsPackSBits16 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1046 | (LCompl (ITFixed IT32)) <- op
1048 jsPackSBits32 $ JSPreOp "~" $ jsUnPackBits (translateReg arg)
1050 | (LCompl (ITFixed IT64)) <- op
1052 invokeMeth arg "not" []
1055 , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
1057 , (lhs:rhs:_) <- args = translateBinaryOp "-" lhs rhs
1059 , (lhs:rhs:_) <- args = translateBinaryOp "*" lhs rhs
1061 , (lhs:rhs:_) <- args = translateBinaryOp "/" lhs rhs
1063 , (lhs:rhs:_) <- args = translateBinaryOp "%" lhs rhs
1065 , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
1067 , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
1069 , (lhs:rhs:_) <- args = translateBinaryOp "<=" lhs rhs
1071 , (lhs:rhs:_) <- args = translateBinaryOp ">" lhs rhs
1073 , (lhs:rhs:_) <- args = translateBinaryOp ">=" lhs rhs
1075 , (lhs:rhs:_) <- args = translateBinaryOp "&" lhs rhs
1077 , (lhs:rhs:_) <- args = translateBinaryOp "|" lhs rhs
1079 , (lhs:rhs:_) <- args = translateBinaryOp "^" lhs rhs
1081 , (lhs:rhs:_) <- args = translateBinaryOp "<<" rhs lhs
1083 , (lhs:rhs:_) <- args = translateBinaryOp ">>" rhs lhs
1085 , (arg:_) <- args = JSPreOp "~" (translateReg arg)
1088 , (lhs:rhs:_) <- args = translateBinaryOp "+" lhs rhs
1090 , (lhs:rhs:_) <- args = translateBinaryOp "==" lhs rhs
1092 , (lhs:rhs:_) <- args = translateBinaryOp "<" lhs rhs
1094 , (arg:_) <- args = JSProj (translateReg arg) "length"
1095 | (LStrInt ITNative) <- op
1096 , (arg:_) <- args = jsCall "parseInt" [translateReg arg]
1097 | (LIntStr ITNative) <- op
1098 , (arg:_) <- args = jsCall "String" [translateReg arg]
1099 | (LSExt ITNative ITBig) <- op
1100 , (arg:_) <- args = jsBigInt $ jsCall "String" [translateReg arg]
1101 | (LTrunc ITBig ITNative) <- op
1102 , (arg:_) <- args = jsMeth (translateReg arg) "intValue" []
1103 | (LIntStr ITBig) <- op
1104 , (arg:_) <- args = jsMeth (translateReg arg) "toString" []
1105 | (LStrInt ITBig) <- op
1106 , (arg:_) <- args = jsBigInt $ translateReg arg
1108 , (arg:_) <- args = jsCall "String" [translateReg arg]
1110 , (arg:_) <- args = jsCall "parseFloat" [translateReg arg]
1111 | (LIntFloat ITNative) <- op
1112 , (arg:_) <- args = translateReg arg
1113 | (LFloatInt ITNative) <- op
1114 , (arg:_) <- args = translateReg arg
1115 | (LChInt ITNative) <- op
1116 , (arg:_) <- args = jsCall "__IDRRT__charCode" [translateReg arg]
1117 | (LIntCh ITNative) <- op
1118 , (arg:_) <- args = jsCall "__IDRRT__fromCharCode" [translateReg arg]
1121 , (arg:_) <- args = jsCall "Math.exp" [translateReg arg]
1123 , (arg:_) <- args = jsCall "Math.log" [translateReg arg]
1125 , (arg:_) <- args = jsCall "Math.sin" [translateReg arg]
1127 , (arg:_) <- args = jsCall "Math.cos" [translateReg arg]
1129 , (arg:_) <- args = jsCall "Math.tan" [translateReg arg]
1131 , (arg:_) <- args = jsCall "Math.asin" [translateReg arg]
1133 , (arg:_) <- args = jsCall "Math.acos" [translateReg arg]
1135 , (arg:_) <- args = jsCall "Math.atan" [translateReg arg]
1137 , (arg:_) <- args = jsCall "Math.sqrt" [translateReg arg]
1139 , (arg:_) <- args = jsCall "Math.floor" [translateReg arg]
1141 , (arg:_) <- args = jsCall "Math.ceil" [translateReg arg]
1144 , (lhs:rhs:_) <- args = invokeMeth lhs "concat" [rhs]
1146 , (arg:_) <- args = JSIndex (translateReg arg) (JSNum (JSInt 0))
1148 , (arg:_) <- args = JSProj (translateReg arg) "split('').reverse().join('')"
1150 , (lhs:rhs:_) <- args = JSIndex (translateReg lhs) (translateReg rhs)
1153 let v = translateReg arg in
1154 JSApp (JSProj v "substr") [
1156 JSBinOp "-" (JSProj v "length") (JSNum (JSInt 1))
1160 , (arg:_) <- args = jsCall "__IDRRT__systemInfo" [translateReg arg]
1162 , (_) <- args = JSNull
1163 | otherwise = JSError $ "Not implemented: " ++ show op
1165 translateBinaryOp :: String -> Reg -> Reg -> JS
1166 translateBinaryOp op lhs rhs =
1167 JSBinOp op (translateReg lhs) (translateReg rhs)
1169 invokeMeth :: Reg -> String -> [Reg] -> JS
1170 invokeMeth obj meth args =
1171 JSApp (JSProj (translateReg obj) meth) $ map translateReg args
1173 jsMeth :: JS -> String -> [JS] -> JS
1174 jsMeth obj meth args = JSApp (JSProj obj meth) args
1177 jsCall :: String -> [JS] -> JS
1178 jsCall fun args = JSApp (JSIdent fun) args
1180jsRESERVE :: Int -> JS
1181jsRESERVE n = JSApp (JSIdent "i$RESERVE") [JSIdent "vm", JSNum $ JSInt n]
1183translateBC :: BC -> JS
1185 | ASSIGN r1 r2 <- bc = jsASSIGN r1 r2
1186 | ASSIGNCONST r c <- bc = jsASSIGNCONST r c
1187 | UPDATE r1 r2 <- bc = jsASSIGN r1 r2
1188 | ADDTOP n <- bc = jsADDTOP n
1189 | NULL r <- bc = jsNULL r
1190 | CALL n <- bc = jsCALL n
1191 | TAILCALL n <- bc = jsTAILCALL n
1192 | FOREIGNCALL r _ _ n a <- bc = jsFOREIGN r n a
1193 | TOPBASE n <- bc = jsTOPBASE n
1194 | BASETOP n <- bc = jsBASETOP n
1195 | STOREOLD <- bc = jsSTOREOLD
1196 | SLIDE n <- bc = jsSLIDE n
1197 | REBASE <- bc = jsREBASE
1198 | RESERVE n <- bc = jsRESERVE n
1199 | MKCON r t rs <- bc = jsMKCON r t rs
1200 | CASE s r c d <- bc = jsCASE s r c d
1201 | CONSTCASE r c d <- bc = jsCONSTCASE r c d
1202 | PROJECT r l a <- bc = jsPROJECT r l a
1203 | OP r o a <- bc = jsOP r o a
1204 | ERROR e <- bc = jsERROR e
1205 | otherwise = JSRaw $ show bc
1206 {-| PROJECTINTO _ _ _ <- bc = undefined-}
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