1{-# LANGUAGE PatternGuards #-}
3module IRTS.CodegenJavaScript (codegenJavaScript, JSTarget(..)) where
5import Idris.AbsSyntax hiding (TypeCase)
9import IRTS.CodegenCommon
19import System.Directory
22idrNamespace = "__IDR__"
23idrRTNamespace = "__IDRRT__"
24idrLTNamespace = "__IDRLT__"
26data JSTarget = Node | JavaScript deriving Eq
42 | JSFunction [String] JS
57 | JSObject [(String, JS)]
61 | JSAlloc String (Maybe JS)
66compileJS :: JS -> String
67compileJS (JSRaw code) =
70compileJS (JSFunction args body) =
72 ++ intercalate "," args
78 | JSIntTy <- ty = idrRTNamespace ++ "Int"
79 | JSStringTy <- ty = idrRTNamespace ++ "String"
80 | JSIntegerTy <- ty = idrRTNamespace ++ "Integer"
81 | JSFloatTy <- ty = idrRTNamespace ++ "Float"
82 | JSCharTy <- ty = idrRTNamespace ++ "Char"
83 | JSPtrTy <- ty = idrRTNamespace ++ "Ptr"
84 | JSForgotTy <- ty = idrRTNamespace ++ "Forgot"
86compileJS (JSSeq seq) =
87 intercalate ";\n" (map compileJS seq)
89compileJS (JSReturn val) =
90 "return " ++ compileJS val
92compileJS (JSApp lhs rhs)
93 | JSFunction {} <- lhs =
94 concat ["(", compileJS lhs, ")(", args, ")"]
96 concat [compileJS lhs, "(", args, ")"]
98 args = intercalate "," $ map compileJS rhs
100compileJS (JSNew name args) =
101 "new " ++ name ++ "(" ++ intercalate "," (map compileJS args) ++ ")"
103compileJS (JSError exc) =
104 "(function(){throw '" ++ exc ++ "';})()"
106compileJS (JSOp op lhs rhs) =
107 compileJS lhs ++ " " ++ op ++ " " ++ compileJS rhs
109compileJS (JSProj obj field)
110 | JSFunction {} <- obj =
111 concat ["(", compileJS obj, ").", field]
113 compileJS obj ++ '.' : field
115compileJS (JSVar var) =
116 translateVariableName var
130compileJS (JSArray elems) =
131 "[" ++ intercalate "," (map compileJS elems) ++ "]"
133compileJS (JSObject fields) =
134 "{" ++ intercalate ",\n" (map compileField fields) ++ "}"
136 compileField :: (String, JS) -> String
137 compileField (name, val) = '\'' : name ++ "' : " ++ compileJS val
139compileJS (JSString str) =
143 | JSInt i <- num = show i
144 | JSFloat f <- num = show f
145 | JSInteger i <- num = show i
147compileJS (JSAssign lhs rhs) =
148 compileJS lhs ++ "=" ++ compileJS rhs
150compileJS (JSAlloc name val) =
151 "var " ++ name ++ maybe "" ((" = " ++) . compileJS) val
153compileJS (JSIndex lhs rhs) =
154 compileJS lhs ++ "[" ++ compileJS rhs ++ "]"
156compileJS (JSCond branches) =
157 intercalate " else " $ map createIfBlock branches
159 createIfBlock (cond, e) =
160 "if (" ++ compileJS cond ++") {\n"
161 ++ "return " ++ compileJS e
164compileJS (JSTernary cond true false) =
165 let c = compileJS cond
167 f = compileJS false in
168 "(" ++ c ++ ")?(" ++ t ++ "):(" ++ f ++ ")"
170jsTailcall :: JS -> JS
172 jsCall (idrRTNamespace ++ "tailcall") [
173 JSFunction [] (JSReturn call)
176jsCall :: String -> [JS] -> JS
177jsCall fun = JSApp (JSRaw fun)
179jsMeth :: JS -> String -> [JS] -> JS
181 JSApp (JSProj obj meth)
183jsInstanceOf :: JS -> JS -> JS
184jsInstanceOf = JSOp "instanceof"
186jsEq :: JS -> JS -> JS
189jsAnd :: JS -> JS -> JS
193jsType = JSRaw $ idrRTNamespace ++ "Type"
196jsCon = JSRaw $ idrRTNamespace ++ "Con"
199jsTag obj = JSProj obj "tag"
202jsTypeTag obj = JSProj obj "type"
206 JSApp (JSRaw $ idrRTNamespace ++ "bigInt") [val]
208jsVar :: Int -> String
209jsVar = ("__var_" ++) . show
211jsLet :: String -> JS -> JS -> JS
212jsLet name value body =
219jsSubst :: String -> [JS] -> JS -> [JS]
221jsSubst var (x@(JSVar old) : xs) new
222 | var == translateVariableName old = new : xs
223 | otherwise = x : jsSubst var xs new
226optimizeJS :: JS -> JS
227optimizeJS (JSApp (JSFunction [arg] (JSReturn ret)) [val])
228 | JSNew con [tag, JSArray vals] <- ret =
229 JSNew con [tag, JSArray $ jsSubst arg vals (optimizeJS val)]
231 | JSNew con [JSFunction [] (JSReturn (JSApp fun vars))] <- ret =
232 JSNew con [JSFunction [] (
233 JSReturn $ JSApp fun (jsSubst arg vars (optimizeJS val))
236 | JSApp (JSRaw "__IDRRT__tailcall") [JSFunction [] (
237 JSReturn (JSApp fun args)
239 JSApp (JSRaw "__IDRRT__tailcall") [JSFunction [] (
240 JSReturn $ JSApp fun (jsSubst arg args (optimizeJS val))
243 | JSOp op lhs rhs <- ret =
244 JSOp op (head $ jsSubst arg [lhs] (optimizeJS val)) $
245 (head $ jsSubst arg [rhs] (optimizeJS val))
247optimizeJS (JSSeq seq) =
248 JSSeq (map optimizeJS seq)
250optimizeJS (JSFunction args body) =
251 JSFunction args (optimizeJS body)
253optimizeJS (JSApp fun args) =
254 JSApp (optimizeJS fun) (map optimizeJS args)
256optimizeJS (JSReturn js) =
257 JSReturn $ optimizeJS js
259optimizeJS (JSAlloc name (Just js)) =
260 JSAlloc name (Just $ optimizeJS js)
264optJS :: Int -> JS -> JS
265optJS c = foldr (.) id $ take c $ repeat optimizeJS
273codegenJavaScript target definitions filename outputType = do
274 let (header, runtime) = case target of
276 ("#!/usr/bin/env node\n", "-node")
280 idrRuntime <- readFile $ path ++ "/js/Runtime-common.js"
281 tgtRuntime <- readFile $ concat [path, "/js/Runtime", runtime, ".js"]
282 writeFile filename $ header ++ (
283 intercalate "\n" $ [ idrRuntime
285 ] ++ functions ++ [mainLoop, invokeLoop]
288 setPermissions filename (emptyPermissions { readable = True
289 , executable = target == Node
293 def :: [(String, SDecl)]
294 def = map (first translateNamespace) definitions
296 functions :: [String]
297 functions = map (compileJS . optJS 1 . translateDeclaration) def
300 mainLoop = compileJS $
301 JSAlloc "main" $ Just $ JSFunction [] (
304 JavaScript -> jsMeth (JSRaw "window") "addEventListener" [
305 JSString "DOMContentLoaded", JSFunction [] (
312 mainFun = jsTailcall $ jsCall runMain []
315 runMain = idrNamespace ++ translateName (MN 0 "runMain")
318 invokeLoop = compileJS $ jsCall "main" []
320translateIdentifier :: String -> String
322 replaceReserved . concatMap replaceBadChars
323 where replaceBadChars :: Char -> String
327 | isDigit c = '_' : show (ord c)
328 | not (isLetter c && isAscii c) = '_' : show (ord c)
331 | s `elem` reserved = '_' : s
378translateNamespace :: Name -> String
379translateNamespace (UN _) = idrNamespace
380translateNamespace (NS _ ns) = idrNamespace ++ concatMap translateIdentifier ns
381translateNamespace (MN _ _) = idrNamespace
382translateNamespace (SN name) = idrNamespace ++ translateSpecialName name
383translateNamespace NErased = idrNamespace
385translateName :: Name -> String
386translateName (UN name) = 'u' : translateIdentifier name
387translateName (NS name _) = 'n' : translateName name
388translateName (MN i name) = 'm' : translateIdentifier name ++ show i
389translateName (SN name) = 's' : translateSpecialName name
390translateName NErased = "e"
392translateSpecialName :: SpecialName -> String
393translateSpecialName name
394 | WhereN i m n <- name =
395 'w' : translateName m ++ translateName n ++ show i
396 | InstanceN n s <- name =
397 'i' : translateName n ++ concatMap translateIdentifier s
398 | ParentN n s <- name =
399 'p' : translateName n ++ translateIdentifier s
400 | MethodN n <- name =
401 'm' : translateName n
403 'c' : translateName n
405translateConstant :: Const -> JS
406translateConstant (I i) = JSNum (JSInt i)
407translateConstant (Fl f) = JSNum (JSFloat f)
408translateConstant (Ch c) = JSString [c]
409translateConstant (Str s) = JSString s
410translateConstant (AType (ATInt ITNative)) = JSType JSIntTy
411translateConstant StrType = JSType JSStringTy
412translateConstant (AType (ATInt ITBig)) = JSType JSIntegerTy
413translateConstant (AType ATFloat) = JSType JSFloatTy
414translateConstant (AType (ATInt ITChar)) = JSType JSCharTy
415translateConstant PtrType = JSType JSPtrTy
416translateConstant Forgot = JSType JSForgotTy
417translateConstant (BI i) = jsBigInt $ JSNum (JSInteger i)
419 JSError $ "Unimplemented Constant: " ++ show c
421translateDeclaration :: (String, SDecl) -> JS
422translateDeclaration (path, SFun name params stackSize body)
423 | (MN _ "APPLY") <- name
424 , (SLet var val next) <- body
425 , (SChkCase cvar cases) <- next =
426 let lvar = translateVariableName var
427 lookup = "[" ++ lvar ++ ".tag](fn0,arg0," ++ lvar ++ ")" in
428 JSSeq [ lookupTable [(var, "chk")] var cases
429 , jsDecl $ JSFunction ["fn0", "arg0"] (
430 JSSeq [ JSAlloc "__var_0" (Just $ JSRaw "fn0")
431 , JSReturn $ jsLet (translateVariableName var) (
432 translateExpression val
434 (JSVar var `jsInstanceOf` jsCon) `jsAnd`
435 (hasProp lookupTableName (translateVariableName var))
437 lookupTableName ++ lookup
444 | (MN _ "EVAL") <- name
445 , (SChkCase var cases) <- body =
446 JSSeq [ lookupTable [] var cases
447 , jsDecl $ JSFunction ["arg0"] (JSReturn $
449 (JSRaw "arg0" `jsInstanceOf` jsCon) `jsAnd`
450 (hasProp lookupTableName "arg0")
451 ) (JSRaw $ lookupTableName ++ "[arg0.tag](arg0)") (JSRaw "arg0")
455 let fun = translateExpression body in
459 hasProp :: String -> String -> JS
461 jsMeth (JSRaw table) "hasOwnProperty" [JSRaw $ var ++ ".tag"]
463 caseFun :: [(LVar, String)] -> LVar -> SAlt -> JS
464 caseFun aux var cse =
465 jsFunAux aux (translateCase (Just (translateVariableName var)) cse)
467 getTag :: SAlt -> Maybe String
468 getTag (SConCase _ tag _ _ _) = Just $ show tag
471 lookupTableName :: String
472 lookupTableName = idrLTNamespace ++ translateName name
474 lookupTable :: [(LVar, String)] -> LVar -> [SAlt] -> JS
475 lookupTable aux var cases =
476 JSAlloc lookupTableName $ Just (
477 JSObject $ catMaybes $ map (lookupEntry aux var) cases
480 lookupEntry :: [(LVar, String)] -> LVar -> SAlt -> Maybe (String, JS)
481 lookupEntry aux var alt = do
483 return (tag, caseFun aux var alt)
486 jsDecl = JSAlloc (path ++ translateName name) . Just
488 jsFun body = jsFunAux [] body
490 jsFunAux :: [(LVar, String)] -> JS -> JS
492 JSFunction (p ++ map snd aux) (
494 zipWith assignVar [0..] p ++
495 map allocVar [numP .. (numP + stackSize - 1)] ++
503 allocVar :: Int -> JS
504 allocVar n = JSAlloc (jsVar n) Nothing
506 assignVar :: Int -> String -> JS
507 assignVar n s = JSAlloc (jsVar n) (Just $ JSRaw s)
509 assignAux :: (LVar, String) -> JS
510 assignAux (var, val) =
511 JSAssign (JSRaw $ translateVariableName var) (JSRaw val)
514 p = map translateName params
516translateVariableName :: LVar -> String
517translateVariableName (Loc i) =
520translateExpression :: SExp -> JS
521translateExpression (SLet name value body) =
522 jsLet (translateVariableName name) (
523 translateExpression value
524 ) (translateExpression body)
526translateExpression (SConst cst) =
527 translateConstant cst
529translateExpression (SV var) =
532translateExpression (SApp tc name vars)
534 jsTailcall $ translateFunctionCall name vars
536 JSNew (idrRTNamespace ++ "Cont") [JSFunction [] (
537 JSReturn $ translateFunctionCall name vars
540 translateFunctionCall name vars =
541 jsCall (translateNamespace name ++ translateName name) (map JSVar vars)
543translateExpression (SOp op vars)
544 | LNoOp <- op = JSVar (last vars)
546 | (LZExt _ ITBig) <- op = jsBigInt $ JSVar (last vars)
547 | (LPlus (ATInt ITBig)) <- op
548 , (lhs:rhs:_) <- vars = invokeMeth lhs "add" [rhs]
549 | (LMinus (ATInt ITBig)) <- op
550 , (lhs:rhs:_) <- vars = invokeMeth lhs "minus" [rhs]
551 | (LTimes (ATInt ITBig)) <- op
552 , (lhs:rhs:_) <- vars = invokeMeth lhs "times" [rhs]
553 | (LSDiv (ATInt ITBig)) <- op
554 , (lhs:rhs:_) <- vars = invokeMeth lhs "divide" [rhs]
555 | (LSRem (ATInt ITBig)) <- op
556 , (lhs:rhs:_) <- vars = invokeMeth lhs "mod" [rhs]
557 | (LEq (ATInt ITBig)) <- op
558 , (lhs:rhs:_) <- vars = invokeMeth lhs "equals" [rhs]
559 | (LSLt (ATInt ITBig)) <- op
560 , (lhs:rhs:_) <- vars = invokeMeth lhs "lesser" [rhs]
561 | (LSLe (ATInt ITBig)) <- op
562 , (lhs:rhs:_) <- vars = invokeMeth lhs "lesserOrEquals" [rhs]
563 | (LSGt (ATInt ITBig)) <- op
564 , (lhs:rhs:_) <- vars = invokeMeth lhs "greater" [rhs]
565 | (LSGe (ATInt ITBig)) <- op
566 , (lhs:rhs:_) <- vars = invokeMeth lhs "greaterOrEquals" [rhs]
568 | (LPlus ATFloat) <- op
569 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
570 | (LMinus ATFloat) <- op
571 , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
572 | (LTimes ATFloat) <- op
573 , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
574 | (LSDiv ATFloat) <- op
575 , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
576 | (LEq ATFloat) <- op
577 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
578 | (LSLt ATFloat) <- op
579 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
580 | (LSLe ATFloat) <- op
581 , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
582 | (LSGt ATFloat) <- op
583 , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
584 | (LSGe ATFloat) <- op
585 , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
588 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
590 , (lhs:rhs:_) <- vars = translateBinaryOp "-" lhs rhs
592 , (lhs:rhs:_) <- vars = translateBinaryOp "*" lhs rhs
594 , (lhs:rhs:_) <- vars = translateBinaryOp "/" lhs rhs
596 , (lhs:rhs:_) <- vars = translateBinaryOp "%" lhs rhs
598 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
600 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
602 , (lhs:rhs:_) <- vars = translateBinaryOp "<=" lhs rhs
604 , (lhs:rhs:_) <- vars = translateBinaryOp ">" lhs rhs
606 , (lhs:rhs:_) <- vars = translateBinaryOp ">=" lhs rhs
608 , (lhs:rhs:_) <- vars = translateBinaryOp "&" lhs rhs
610 , (lhs:rhs:_) <- vars = translateBinaryOp "|" lhs rhs
612 , (lhs:rhs:_) <- vars = translateBinaryOp "^" lhs rhs
614 , (lhs:rhs:_) <- vars = translateBinaryOp "<<" rhs lhs
616 , (lhs:rhs:_) <- vars = translateBinaryOp ">>" rhs lhs
618 , (arg:_) <- vars = JSRaw $ '~' : translateVariableName arg
621 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
623 , (lhs:rhs:_) <- vars = translateBinaryOp "==" lhs rhs
625 , (lhs:rhs:_) <- vars = translateBinaryOp "<" lhs rhs
627 , (arg:_) <- vars = JSProj (JSVar arg) "length"
629 | (LStrInt ITNative) <- op
630 , (arg:_) <- vars = jsCall "parseInt" [JSVar arg]
631 | (LIntStr ITNative) <- op
632 , (arg:_) <- vars = jsCall "String" [JSVar arg]
633 | (LSExt ITNative ITBig) <- op
634 , (arg:_) <- vars = jsBigInt $ JSVar arg
635 | (LTrunc ITBig ITNative) <- op
636 , (arg:_) <- vars = jsMeth (JSVar arg) "valueOf" []
637 | (LIntStr ITBig) <- op
638 , (arg:_) <- vars = jsMeth (JSVar arg) "toString" []
639 | (LStrInt ITBig) <- op
640 , (arg:_) <- vars = jsBigInt $ JSVar arg
642 , (arg:_) <- vars = jsCall "String" [JSVar arg]
644 , (arg:_) <- vars = jsCall "parseFloat" [JSVar arg]
645 | (LIntFloat ITNative) <- op
646 , (arg:_) <- vars = JSVar arg
647 | (LFloatInt ITNative) <- op
648 , (arg:_) <- vars = JSVar arg
649 | (LChInt ITNative) <- op
650 , (arg:_) <- vars = JSProj (JSVar arg) "charCodeAt(0)"
651 | (LIntCh ITNative) <- op
652 , (arg:_) <- vars = jsCall "String.fromCharCode" [JSVar arg]
655 , (arg:_) <- vars = jsCall "Math.exp" [JSVar arg]
657 , (arg:_) <- vars = jsCall "Math.log" [JSVar arg]
659 , (arg:_) <- vars = jsCall "Math.sin" [JSVar arg]
661 , (arg:_) <- vars = jsCall "Math.cos" [JSVar arg]
663 , (arg:_) <- vars = jsCall "Math.tan" [JSVar arg]
665 , (arg:_) <- vars = jsCall "Math.asin" [JSVar arg]
667 , (arg:_) <- vars = jsCall "Math.acos" [JSVar arg]
669 , (arg:_) <- vars = jsCall "Math.atan" [JSVar arg]
671 , (arg:_) <- vars = jsCall "Math.sqrt" [JSVar arg]
673 , (arg:_) <- vars = jsCall "Math.floor" [JSVar arg]
675 , (arg:_) <- vars = jsCall "Math.ceil" [JSVar arg]
678 , (lhs:rhs:_) <- vars = translateBinaryOp "+" lhs rhs
680 , (arg:_) <- vars = JSIndex (JSVar arg) (JSRaw "0")
682 , (arg:_) <- vars = JSProj (JSVar arg) "split('').reverse().join('')"
684 , (lhs:rhs:_) <- vars = JSIndex (JSVar lhs) (JSVar rhs)
686 , (arg:_) <- vars = let v = translateVariableName arg in
687 JSRaw $ v ++ ".substr(1," ++ v ++ ".length-1)"
689 translateBinaryOp :: String -> LVar -> LVar -> JS
690 translateBinaryOp f lhs rhs = JSOp f (JSVar lhs) (JSVar rhs)
692 invokeMeth :: LVar -> String -> [LVar] -> JS
693 invokeMeth obj meth args = jsMeth (JSVar obj) meth (map JSVar args)
695translateExpression (SError msg) =
698translateExpression (SForeign _ _ "putStr" [(FString, var)]) =
699 jsCall (idrRTNamespace ++ "print") [JSVar var]
701translateExpression (SForeign _ _ fun args) =
702 ffi fun (map generateWrapper args)
704 generateWrapper (ffunc, name)
705 | FFunction <- ffunc =
706 idrRTNamespace ++ "ffiWrap(" ++ translateVariableName name ++ ")"
707 | FFunctionIO <- ffunc =
708 idrRTNamespace ++ "ffiWrap(" ++ translateVariableName name ++ ")"
710 generateWrapper (_, name) =
711 translateVariableName name
713translateExpression patterncase
714 | (SChkCase var cases) <- patterncase = caseHelper var cases "chk"
715 | (SCase var cases) <- patterncase = caseHelper var cases "cse"
717 caseHelper var cases param =
718 JSApp (JSFunction [param] (
719 JSCond $ map (expandCase param . translateCaseCond param) cases
722 expandCase :: String -> (Cond, JS) -> (JS, JS)
723 expandCase _ (RawCond cond, branch) = (cond, branch)
724 expandCase _ (CaseCond DefaultCase, branch) = (JSTrue , branch)
725 expandCase var (CaseCond caseTy, branch)
726 | ConCase tag <- caseTy =
727 let checkCon = JSRaw var `jsInstanceOf` jsCon
728 checkTag = (JSRaw $ show tag) `jsEq` jsTag (JSRaw var) in
729 (checkCon `jsAnd` checkTag, branch)
731 | TypeCase ty <- caseTy =
732 let checkTy = JSRaw var `jsInstanceOf` jsType
733 checkTag = jsTypeTag (JSRaw var) `jsEq` JSType ty in
734 (checkTy `jsAnd` checkTag, branch)
736translateExpression (SCon i name vars) =
737 JSNew (idrRTNamespace ++ "Con") [ JSRaw $ show i
738 , JSArray $ map JSVar vars
741translateExpression (SUpdate var e) =
742 JSAssign (JSVar var) (translateExpression e)
744translateExpression (SProj var i) =
745 JSIndex (JSProj (JSVar var) "vars") (JSRaw $ show i)
747translateExpression SNothing = JSNull
749translateExpression e =
750 JSError $ "Not yet implemented: " ++ filter (/= '\'') (show e)
752data FFI = FFICode Char | FFIArg Int | FFIError String
754ffi :: String -> [String] -> JS
755ffi code args = let parsed = ffiParse code in
756 case ffiError parsed of
757 Just err -> JSError err
758 Nothing -> JSRaw $ renderFFI parsed args
760 ffiParse :: String -> [FFI]
762 ffiParse ['%'] = [FFIError "Invalid positional argument"]
763 ffiParse ('%':'%':ss) = FFICode '%' : ffiParse ss
766 FFIArg (read $ s : takeWhile isDigit ss) : ffiParse (dropWhile isDigit ss)
768 [FFIError "Invalid positional argument"]
769 ffiParse (s:ss) = FFICode s : ffiParse ss
771 ffiError :: [FFI] -> Maybe String
772 ffiError [] = Nothing
773 ffiError ((FFIError s):xs) = Just s
774 ffiError (x:xs) = ffiError xs
776 renderFFI :: [FFI] -> [String] -> String
778 renderFFI ((FFICode c) : fs) args = c : renderFFI fs args
779 renderFFI ((FFIArg i) : fs) args
780 | i < length args && i >= 0 = args !! i ++ renderFFI fs args
781 | otherwise = "Argument index out of bounds"
783data CaseType = ConCase Int
788data Cond = CaseCond CaseType
791translateCaseCond :: String -> SAlt -> (Cond, JS)
792translateCaseCond _ cse@(SDefaultCase _) =
793 (CaseCond DefaultCase, translateCase Nothing cse)
795translateCaseCond var cse@(SConstCase ty _)
796 | StrType <- ty = matchHelper JSStringTy
797 | PtrType <- ty = matchHelper JSPtrTy
798 | Forgot <- ty = matchHelper JSForgotTy
799 | (AType ATFloat) <- ty = matchHelper JSFloatTy
800 | (AType (ATInt ITBig)) <- ty = matchHelper JSIntegerTy
801 | (AType (ATInt ITNative)) <- ty = matchHelper JSIntTy
802 | (AType (ATInt ITChar)) <- ty = matchHelper JSCharTy
804 matchHelper :: JSType -> (Cond, JS)
805 matchHelper ty = (CaseCond $ TypeCase ty, translateCase Nothing cse)
807translateCaseCond var cse@(SConstCase cst@(BI _) _) =
808 let cond = jsMeth (JSRaw var) "equals" [translateConstant cst] in
809 (RawCond cond, translateCase Nothing cse)
811translateCaseCond var cse@(SConstCase cst _) =
812 let cond = JSRaw var `jsEq` translateConstant cst in
813 (RawCond cond, translateCase Nothing cse)
815translateCaseCond var cse@(SConCase _ tag _ _ _) =
816 (CaseCond $ ConCase tag, translateCase (Just var) cse)
818translateCase :: Maybe String -> SAlt -> JS
819translateCase _ (SDefaultCase e) = translateExpression e
820translateCase _ (SConstCase _ e) = translateExpression e
821translateCase (Just var) (SConCase a _ _ vars e) =
822 let params = map jsVar [a .. (a + length vars)] in
823 jsMeth (JSFunction params (JSReturn $ translateExpression e)) "apply" [
824 JSThis, JSProj (JSRaw var) "vars"
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