@@ -27,6 +27,29 @@ idrRTNamespace = "__IDRRT__"
27idrLTNamespace = "__IDRLT__"
27idrLTNamespace = "__IDRLT__"
28idrCTRNamespace = "__IDRCTR__"
28idrCTRNamespace = "__IDRCTR__"
30+data CompileInfo = CompileInfo { compileInfoApplyCases :: [Int]
31+ , compileInfoEvalCases :: [Int]
35+initCompileInfo :: [(Name, [BC])] -> CompileInfo
36+initCompileInfo bc = CompileInfo (collectApplyCases bc) []
38+ collectApplyCases :: [(Name, [BC])] -> [Int]
39+ collectApplyCases bc = getCases $ findApply bc
41+ findApply :: [(Name, [BC])] -> [BC]
42+ findApply ((MN 0 fun, bc):_)
43+ | fun == txt "APPLY" = bc
44+ findApply (_:bc) = findApply bc
46+ getCases :: [BC] -> [Int]
47+ getCases = concatMap analyze
49+ analyze :: BC -> [Int]
50+ analyze (CASE _ _ b _) = map fst b
31data JSTarget = Node | JavaScript deriving Eq
54data JSTarget = Node | JavaScript deriving Eq
@@ -82,6 +105,7 @@ data JS = JSRaw String
82 | JSPostOp String JS
105 | JSPostOp String JS
83 | JSProj JS String
106 | JSProj JS String
87 | JSFalse
111 | JSFalse
@@ -173,6 +197,9 @@ compileJS (JSProj obj field)
173compileJS JSNull =
197compileJS JSNull =
200+compileJS JSUndefined =
176compileJS JSThis =
203compileJS JSThis =
@@ -273,7 +300,9 @@ codegenJS_all
273 -> OutputType
300 -> OutputType
275codegenJS_all target definitions includes filename outputType = do
302codegenJS_all target definitions includes filename outputType = do
303+ let bytecode = map toBC definitions
304+ let info = initCompileInfo bytecode
276− let code = map (compileJS . translateDecl . toBC) definitions
305+ let code = concat $ map ((concatMap compileJS) . (translateDecl info)) bytecode
277 let (header, rt) = case target of
306 let (header, rt) = case target of
279 ("#!/usr/bin/env node\n", "-node")
308 ("#!/usr/bin/env node\n", "-node")
@@ -284,7 +313,7 @@ codegenJS_all target definitions includes filename outputType = do
284 tgtRuntime <- readFile $ concat [path, "Runtime", rt, ".js"]
313 tgtRuntime <- readFile $ concat [path, "Runtime", rt, ".js"]
285 jsbn <- readFile $ path ++ "jsbn/jsbn.js"
314 jsbn <- readFile $ path ++ "jsbn/jsbn.js"
286 let runtime = header ++ jsbn ++ idrRuntime ++ tgtRuntime
315 let runtime = header ++ jsbn ++ idrRuntime ++ tgtRuntime
287− writeFile filename $ runtime ++ concat code ++ main ++ invokeMain
316+ writeFile filename $ runtime ++ code ++ main ++ invokeMain
288 setPermissions filename (emptyPermissions { readable = True
317 setPermissions filename (emptyPermissions { readable = True
289 , executable = target == Node
318 , executable = target == Node
290 , writable = True
319 , writable = True
@@ -306,13 +335,68 @@ codegenJS_all target definitions includes filename outputType = do
306 invokeMain = compileJS $ JSApp (JSIdent "main") []
335 invokeMain = compileJS $ JSApp (JSIdent "main") []
309−translateDecl :: (Name, [BC]) -> JS
338+translateDecl :: CompileInfo -> (Name, [BC]) -> [JS]
339+translateDecl info (name@(MN 0 fun), bc)
340+ | txt "APPLY" == fun =
341+ allocCaseFunctions (snd body)
344+ ) (Just $ JSFunction ["vm", "oldbase"] (
345+ JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info) (fst body) ++ [
346+ JSCond [ ( (translateReg $ caseReg (snd body)) `jsInstanceOf` "i$CON"
347+ , JSApp (JSProj (translateReg $ caseReg (snd body)) "app") [ JSIdent "vm"
349+ , JSIdent "myoldbase"
353+ , JSSeq $ map (translateBC info) (defaultCase (snd body))
361+ body :: ([BC], [BC])
362+ body = break isCase bc
364+ isCase :: BC -> Bool
366+ | CASE _ _ _ _ <- bc = True
369+ defaultCase :: [BC] -> [BC]
370+ defaultCase ((CASE _ _ _ (Just d)):_) = d
372+ caseReg :: [BC] -> Reg
373+ caseReg ((CASE _ r _ _):_) = r
375+ allocCaseFunctions :: [BC] -> [JS]
376+ allocCaseFunctions ((CASE _ _ c _):_) = splitBranches c
377+ allocCaseFunctions _ = []
379+ splitBranches :: [(Int, [BC])] -> [JS]
380+ splitBranches = map prepBranch
382+ prepBranch :: (Int, [BC]) -> JS
383+ prepBranch (tag, code) =
385+ translateName name ++ "$" ++ show tag
386+ ) (Just $ JSFunction ["vm", "oldbase", "myoldbase"] (
387+ JSSeq $ map (translateBC info) code
310−translateDecl (name, bc) =
391+translateDecl info (name, bc) =
311− JSAlloc (
392+ [ JSAlloc (
312− translateName name
393+ translateName name
313− ) (Just $ JSFunction ["vm", "oldbase"] (
394+ ) (Just $ JSFunction ["vm", "oldbase"] (
314− JSSeq $ JSAlloc "myoldbase" Nothing : map translateBC bc)
395+ JSSeq $ JSAlloc "myoldbase" Nothing : map (translateBC info)bc
317translateReg :: Reg -> JS
401translateReg :: Reg -> JS
318translateReg reg
402translateReg reg
@@ -359,7 +443,7 @@ translateConstant (B16 b) = JSWord (JSWord16 b)
359translateConstant (B32 b) = JSWord (JSWord32 b)
443translateConstant (B32 b) = JSWord (JSWord32 b)
360translateConstant (B64 b) = JSWord (JSWord64 b)
444translateConstant (B64 b) = JSWord (JSWord64 b)
361translateConstant c =
445translateConstant c =
362− jsERROR $ "Unimplemented Constant: " ++ show c
446+ JSError $ "Unimplemented Constant: " ++ show c
365translateChar :: Char -> String
449translateChar :: Char -> String
@@ -395,50 +479,50 @@ translateName n = "_idris_" ++ concatMap cchar (showCG n)
395 where cchar x | isAlpha x || isDigit x = [x]
479 where cchar x | isAlpha x || isDigit x = [x]
396 | otherwise = "_" ++ show (fromEnum x) ++ "_"
480 | otherwise = "_" ++ show (fromEnum x) ++ "_"
398−jsASSIGN :: Reg -> Reg -> JS
482+jsASSIGN :: CompileInfo -> Reg -> Reg -> JS
399−jsASSIGN r1 r2 = JSAssign (translateReg r1) (translateReg r2)
483+jsASSIGN _ r1 r2 = JSAssign (translateReg r1) (translateReg r2)
401−jsASSIGNCONST :: Reg -> Const -> JS
485+jsASSIGNCONST :: CompileInfo -> Reg -> Const -> JS
402−jsASSIGNCONST r c = JSAssign (translateReg r) (translateConstant c)
486+jsASSIGNCONST _ r c = JSAssign (translateReg r) (translateConstant c)
404−jsCALL :: Name -> JS
488+jsCALL :: CompileInfo -> Name -> JS
405−jsCALL n = JSApp (JSIdent (translateName n)) [JSIdent "vm", JSIdent "myoldbase"]
489+jsCALL _ n = JSApp (JSIdent (translateName n)) [JSIdent "vm", JSIdent "myoldbase"]
407−jsTAILCALL :: Name -> JS
491+jsTAILCALL :: CompileInfo -> Name -> JS
408−jsTAILCALL n = JSApp (JSIdent (translateName n)) [JSIdent "vm", JSIdent "oldbase"]
492+jsTAILCALL _ n = JSApp (JSIdent (translateName n)) [JSIdent "vm", JSIdent "oldbase"]
410−jsFOREIGN :: Reg -> String -> [(FType, Reg)] -> JS
494+jsFOREIGN :: CompileInfo -> Reg -> String -> [(FType, Reg)] -> JS
411−jsFOREIGN reg n args =
495+jsFOREIGN _ reg n args =
412 JSAssign (
496 JSAssign (
413 translateReg reg
497 translateReg reg
415 JSApp (JSIdent n) (map (translateReg . snd) args)
499 JSApp (JSIdent n) (map (translateReg . snd) args)
418−jsREBASE :: JS
502+jsREBASE :: CompileInfo -> JS
419−jsREBASE =
503+jsREBASE _ =
420 JSAssign (
504 JSAssign (
421 JSProj (JSIdent "vm") "valstack_base"
505 JSProj (JSIdent "vm") "valstack_base"
423 JSIdent "oldbase"
507 JSIdent "oldbase"
426−jsSTOREOLD :: JS
510+jsSTOREOLD :: CompileInfo ->JS
427−jsSTOREOLD =
511+jsSTOREOLD _ =
428 JSAssign (
512 JSAssign (
429 JSIdent "myoldbase"
513 JSIdent "myoldbase"
431 JSProj (JSIdent "vm") "valstack_base"
515 JSProj (JSIdent "vm") "valstack_base"
434−jsADDTOP :: Int -> JS
518+jsADDTOP :: CompileInfo -> Int -> JS
435−jsADDTOP n
519+jsADDTOP info n
436 | 0 <- n = JSNoop
520 | 0 <- n = JSNoop
437 | otherwise =
521 | otherwise =
438 JSBinOp "+=" (JSProj (JSIdent "vm") "valstack_top") (JSNum (JSInt n))
522 JSBinOp "+=" (JSProj (JSIdent "vm") "valstack_top") (JSNum (JSInt n))
440−jsTOPBASE :: Int -> JS
524+jsTOPBASE :: CompileInfo -> Int -> JS
441−jsTOPBASE n
525+jsTOPBASE info n
442 | 0 <- n =
526 | 0 <- n =
443 JSAssign (
527 JSAssign (
444 JSProj (JSIdent "vm") "valstack_top"
528 JSProj (JSIdent "vm") "valstack_top"
@@ -452,8 +536,8 @@ jsTOPBASE n
452 JSBinOp "+" (JSProj (JSIdent "vm") "valstack_base") (JSNum (JSInt n))
536 JSBinOp "+" (JSProj (JSIdent "vm") "valstack_base") (JSNum (JSInt n))
455−jsBASETOP :: Int -> JS
539+jsBASETOP :: CompileInfo -> Int -> JS
456−jsBASETOP n
540+jsBASETOP info n
457 | 0 <- n =
541 | 0 <- n =
458 JSAssign (
542 JSAssign (
459 JSProj (JSIdent "vm") "valstack_base"
543 JSProj (JSIdent "vm") "valstack_base"
@@ -467,19 +551,24 @@ jsBASETOP n
467 JSBinOp "+" (JSProj (JSIdent "vm") "valstack_top") (JSNum (JSInt n))
551 JSBinOp "+" (JSProj (JSIdent "vm") "valstack_top") (JSNum (JSInt n))
470−jsNULL :: Reg -> JS
554+jsNULL :: CompileInfo -> Reg -> JS
471−jsNULL r = JSAssign (translateReg r) JSNull
555+jsNULL _ r = JSAssign (translateReg r) JSNull
473−jsERROR :: String -> JS
557+jsERROR :: CompileInfo -> String -> JS
474−jsERROR = JSError
558+jsERROR _ = JSError
476−jsSLIDE :: Int -> JS
560+jsSLIDE :: CompileInfo -> Int -> JS
477−jsSLIDE n = JSApp (JSIdent "i$SLIDE") [JSIdent "vm", JSNum (JSInt n)]
561+jsSLIDE _ n = JSApp (JSIdent "i$SLIDE") [JSIdent "vm", JSNum (JSInt n)]
479−jsMKCON :: Reg -> Int -> [Reg] -> JS
563+jsMKCON :: CompileInfo -> Reg -> Int -> [Reg] -> JS
480−jsMKCON r t rs =
564+jsMKCON info r t rs =
481 JSAssign (translateReg r) (
565 JSAssign (translateReg r) (
566+ JSNew "i$CON" [ JSNum (JSInt t)
482− JSNew "i$CON" [JSNum (JSInt t), JSArray (map translateReg rs)]
567+ , JSArray (map translateReg rs)
568+ , if t `elem` compileInfoApplyCases info
569+ then JSIdent $ translateName (sMN 0 "APPLY") ++ "$" ++ show t
485jsInstanceOf :: JS -> String -> JS
574jsInstanceOf :: JS -> String -> JS
@@ -488,6 +577,9 @@ jsInstanceOf obj cls = JSBinOp "instanceof" obj (JSIdent cls)
488jsOr :: JS -> JS -> JS
577jsOr :: JS -> JS -> JS
489jsOr lhs rhs = JSBinOp "||" lhs rhs
578jsOr lhs rhs = JSBinOp "||" lhs rhs
580+jsAnd :: JS -> JS -> JS
581+jsAnd lhs rhs = JSBinOp "&&" lhs rhs
491jsTypeOf :: JS -> JS
583jsTypeOf :: JS -> JS
492jsTypeOf js = JSPreOp "typeof " js
584jsTypeOf js = JSPreOp "typeof " js
@@ -496,6 +588,9 @@ jsEq lhs@(JSNum (JSInteger _)) rhs = JSApp (JSProj lhs "equals") [rhs]
496jsEq lhs rhs@(JSNum (JSInteger _)) = JSApp (JSProj lhs "equals") [rhs]
588jsEq lhs rhs@(JSNum (JSInteger _)) = JSApp (JSProj lhs "equals") [rhs]
497jsEq lhs rhs = JSBinOp "==" lhs rhs
589jsEq lhs rhs = JSBinOp "==" lhs rhs
591+jsNotEq :: JS -> JS -> JS
592+jsNotEq lhs rhs = JSBinOp "!=" lhs rhs
499jsIsNumber :: JS -> JS
594jsIsNumber :: JS -> JS
500jsIsNumber js = (jsTypeOf js) `jsEq` (JSString "number")
595jsIsNumber js = (jsTypeOf js) `jsEq` (JSString "number")
@@ -528,8 +623,8 @@ jsPackSBits16 js = JSNew "Int16Array" [JSArray [js]]
528jsPackSBits32 :: JS -> JS
623jsPackSBits32 :: JS -> JS
529jsPackSBits32 js = JSNew "Int32Array" [JSArray [js]]
624jsPackSBits32 js = JSNew "Int32Array" [JSArray [js]]
531−jsCASE :: Bool -> Reg -> [(Int, [BC])] -> Maybe [BC] -> JS
626+jsCASE :: CompileInfo -> Bool -> Reg -> [(Int, [BC])] -> Maybe [BC] -> JS
532−jsCASE safe reg cases def =
627+jsCASE info safe reg cases def =
533 JSSwitch (tag safe $ translateReg reg) (
628 JSSwitch (tag safe $ translateReg reg) (
534 map ((JSNum . JSInt) *** prepBranch) cases
629 map ((JSNum . JSInt) *** prepBranch) cases
535 ) (fmap prepBranch def)
630 ) (fmap prepBranch def)
@@ -539,7 +634,7 @@ jsCASE safe reg cases def =
539 tag False = jsTAG
634 tag False = jsTAG
541 prepBranch :: [BC] -> JS
636 prepBranch :: [BC] -> JS
542− prepBranch bc = JSSeq $ map translateBC bc
637+ prepBranch bc = JSSeq $ map (translateBC info) bc
544 jsTAG :: JS -> JS
639 jsTAG :: JS -> JS
545 jsTAG js =
640 jsTAG js =
@@ -553,25 +648,25 @@ jsCASE safe reg cases def =
553 jsCTAG js = JSProj js "tag"
648 jsCTAG js = JSProj js "tag"
556−jsCONSTCASE :: Reg -> [(Const, [BC])] -> Maybe [BC] -> JS
651+jsCONSTCASE :: CompileInfo -> Reg -> [(Const, [BC])] -> Maybe [BC] -> JS
557−jsCONSTCASE reg cases def =
652+jsCONSTCASE info reg cases def =
558 JSCond $ (
653 JSCond $ (
559 map (jsEq (translateReg reg) . translateConstant *** prepBranch) cases
654 map (jsEq (translateReg reg) . translateConstant *** prepBranch) cases
560 ) ++ (maybe [] ((:[]) . ((,) JSNoop) . prepBranch) def)
655 ) ++ (maybe [] ((:[]) . ((,) JSNoop) . prepBranch) def)
562 prepBranch :: [BC] -> JS
657 prepBranch :: [BC] -> JS
563− prepBranch bc = JSSeq $ map translateBC bc
658+ prepBranch bc = JSSeq $ map (translateBC info) bc
565−jsPROJECT :: Reg -> Int -> Int -> JS
660+jsPROJECT :: CompileInfo -> Reg -> Int -> Int -> JS
566−jsPROJECT reg loc ar =
661+jsPROJECT _ reg loc ar =
567 JSApp (JSIdent "i$PROJECT") [ JSIdent "vm"
662 JSApp (JSIdent "i$PROJECT") [ JSIdent "vm"
568 , translateReg reg
663 , translateReg reg
569 , JSNum (JSInt loc)
664 , JSNum (JSInt loc)
570 , JSNum (JSInt ar)
665 , JSNum (JSInt ar)
573−jsOP :: Reg -> PrimFn -> [Reg] -> JS
668+jsOP :: CompileInfo -> Reg -> PrimFn -> [Reg] -> JS
574−jsOP reg op args = JSAssign (translateReg reg) jsOP'
669+jsOP _ reg op args = JSAssign (translateReg reg) jsOP'
576 jsOP' :: JS
671 jsOP' :: JS
@@ -1177,31 +1272,31 @@ jsOP reg op args = JSAssign (translateReg reg) jsOP'
1177 jsCall :: String -> [JS] -> JS
1272 jsCall :: String -> [JS] -> JS
1178 jsCall fun args = JSApp (JSIdent fun) args
1273 jsCall fun args = JSApp (JSIdent fun) args
1180−jsRESERVE :: Int -> JS
1275+jsRESERVE :: CompileInfo -> Int -> JS
1181−jsRESERVE n = JSApp (JSIdent "i$RESERVE") [JSIdent "vm", JSNum $ JSInt n]
1276+jsRESERVE _ _ = JSNoop
1183−translateBC :: BC -> JS
1278+translateBC :: CompileInfo -> BC -> JS
1184−translateBC bc
1279+translateBC info bc
1185− | ASSIGN r1 r2 <- bc = jsASSIGN r1 r2
1280+ | ASSIGN r1 r2 <- bc = jsASSIGN info r1 r2
1186− | ASSIGNCONST r c <- bc = jsASSIGNCONST r c
1281+ | ASSIGNCONST r c <- bc = jsASSIGNCONST info r c
1187− | UPDATE r1 r2 <- bc = jsASSIGN r1 r2
1282+ | UPDATE r1 r2 <- bc = jsASSIGN info r1 r2
1188− | ADDTOP n <- bc = jsADDTOP n
1283+ | ADDTOP n <- bc = jsADDTOP info n
1189− | NULL r <- bc = jsNULL r
1284+ | NULL r <- bc = jsNULL info r
1190− | CALL n <- bc = jsCALL n
1285+ | CALL n <- bc = jsCALL info n
1191− | TAILCALL n <- bc = jsTAILCALL n
1286+ | TAILCALL n <- bc = jsTAILCALL info n
1192− | FOREIGNCALL r _ _ n a <- bc = jsFOREIGN r n a
1287+ | FOREIGNCALL r _ _ n a <- bc = jsFOREIGN info r n a
1193− | TOPBASE n <- bc = jsTOPBASE n
1288+ | TOPBASE n <- bc = jsTOPBASE info n
1194− | BASETOP n <- bc = jsBASETOP n
1289+ | BASETOP n <- bc = jsBASETOP info n
1195− | STOREOLD <- bc = jsSTOREOLD
1290+ | STOREOLD <- bc = jsSTOREOLD info
1196− | SLIDE n <- bc = jsSLIDE n
1291+ | SLIDE n <- bc = jsSLIDE info n
1197− | REBASE <- bc = jsREBASE
1292+ | REBASE <- bc = jsREBASE info
1198− | RESERVE n <- bc = jsRESERVE n
1293+ | RESERVE n <- bc = jsRESERVE info n
1199− | MKCON r t rs <- bc = jsMKCON r t rs
1294+ | MKCON r t rs <- bc = jsMKCON info r t rs
1200− | CASE s r c d <- bc = jsCASE s r c d
1295+ | CASE s r c d <- bc = jsCASE info s r c d
1201− | CONSTCASE r c d <- bc = jsCONSTCASE r c d
1296+ | CONSTCASE r c d <- bc = jsCONSTCASE info r c d
1202− | PROJECT r l a <- bc = jsPROJECT r l a
1297+ | PROJECT r l a <- bc = jsPROJECT info r l a
1203− | OP r o a <- bc = jsOP r o a
1298+ | OP r o a <- bc = jsOP info r o a
1204− | ERROR e <- bc = jsERROR e
1299+ | ERROR e <- bc = jsERROR info e
1205 | otherwise = JSRaw $ show bc
1300 | otherwise = JSRaw $ show bc
1206 {-| PROJECTINTO _ _ _ <- bc = undefined-}
1301 {-| PROJECTINTO _ _ _ <- bc = undefined-}