@@ -246,14 +246,17 @@ jsLet name value body =
246 ) [value]
246 ) [value]
249−jsSubst :: String -> JS -> JS -> JS
249+jsSubst :: JS -> JS -> JS -> JS
250−jsSubst var new (JSVar old)
250+jsSubst var new old
253+jsSubst (JSIdent var) new (JSVar old)
251 | var == translateVariableName old = new
254 | var == translateVariableName old = new
252− | otherwise = JSVar old
255+ | otherwise = JSVar old
254−jsSubst var new (JSIdent old)
257+jsSubst var new old@(JSIdent _)
255 | var == old = new
258 | var == old = new
256− | otherwise = JSIdent old
259+ | otherwise = old
258jsSubst var new (JSArray fields) =
261jsSubst var new (JSArray fields) =
259 JSArray (map (jsSubst var new) fields)
262 JSArray (map (jsSubst var new) fields)
@@ -261,25 +264,25 @@ jsSubst var new (JSArray fields) =
261jsSubst var new (JSNew con vals) =
264jsSubst var new (JSNew con vals) =
262 JSNew con $ map (jsSubst var new) vals
265 JSNew con $ map (jsSubst var new) vals
264−jsSubst var new (JSApp (JSProj (JSFunction args body) "apply") vals)
267+jsSubst (JSIdent var) new (JSApp (JSProj (JSFunction args body) "apply") vals)
265 | var `notElem` args =
268 | var `notElem` args =
266− JSApp (JSProj (JSFunction args (jsSubst var new body)) "apply") (
269+ JSApp (JSProj (JSFunction args (jsSubst (JSIdent var) new body)) "apply") (
267− map (jsSubst var new) vals
270+ map (jsSubst (JSIdent var) new) vals
269 | otherwise =
272 | otherwise =
270 JSApp (JSProj (JSFunction args body) "apply") (
273 JSApp (JSProj (JSFunction args body) "apply") (
271− map (jsSubst var new) vals
274+ map (jsSubst (JSIdent var) new) vals
274−jsSubst var new (JSApp (JSFunction [arg] body) vals)
277+jsSubst (JSIdent var) new (JSApp (JSFunction [arg] body) vals)
275 | var /= arg =
278 | var /= arg =
276 JSApp (JSFunction [arg] (
279 JSApp (JSFunction [arg] (
277− jsSubst var new body
280+ jsSubst (JSIdent var) new body
278− )) $ map (jsSubst var new) vals
281+ )) $ map (jsSubst (JSIdent var) new) vals
279 | otherwise =
282 | otherwise =
280 JSApp (JSFunction [arg] (
283 JSApp (JSFunction [arg] (
282− )) $ map (jsSubst var new) vals
285+ )) $ map (jsSubst (JSIdent var) new) vals
284jsSubst var new (JSApp lhs rhs) =
287jsSubst var new (JSApp lhs rhs) =
285 JSApp (jsSubst var new lhs) (map (jsSubst var new) rhs)
288 JSApp (jsSubst var new lhs) (map (jsSubst var new) rhs)
@@ -324,7 +327,7 @@ removeAllocations (JSSeq body) =
324 removeHelper :: [JS] -> [JS]
327 removeHelper :: [JS] -> [JS]
325 removeHelper [js] = [js]
328 removeHelper [js] = [js]
326 removeHelper ((JSAlloc name (Just val@(JSIdent _))):js) =
329 removeHelper ((JSAlloc name (Just val@(JSIdent _))):js) =
327− map (jsSubst name val) (removeHelper js)
330+ map (jsSubst (JSIdent name) val) (removeHelper js)
328 removeHelper (j:js) = j : removeHelper js
331 removeHelper (j:js) = j : removeHelper js
330removeAllocations (JSFunction args body) =
333removeAllocations (JSFunction args body) =
@@ -378,7 +381,7 @@ isJSConstant js
379inlineJS :: JS -> JS
382inlineJS :: JS -> JS
380inlineJS (JSReturn (JSApp (JSFunction ["cse"] body) [val@(JSVar _)])) =
383inlineJS (JSReturn (JSApp (JSFunction ["cse"] body) [val@(JSVar _)])) =
381− inlineJS $ jsSubst "cse" val body
384+ inlineJS $ jsSubst (JSIdent "cse") val body
383inlineJS (JSReturn (JSApp (JSFunction [arg] cond@(JSCond _)) [val])) =
386inlineJS (JSReturn (JSApp (JSFunction [arg] cond@(JSCond _)) [val])) =
384 JSSeq [ JSAlloc arg (Just (inlineJS val))
387 JSSeq [ JSAlloc arg (Just (inlineJS val))
@@ -394,7 +397,7 @@ inlineJS (JSApp (JSProj (JSFunction args (JSReturn body)) "apply") [
394 inlineApply [] body _ = inlineJS body
397 inlineApply [] body _ = inlineJS body
395 inlineApply (a:as) body n =
398 inlineApply (a:as) body n =
396 inlineApply as (
399 inlineApply as (
397− jsSubst a (JSIndex (JSProj var "vars") (JSNum (JSInt n))) body
400+ jsSubst (JSIdent a) (JSIndex (JSProj var "vars") (JSNum (JSInt n))) body
398 ) (n + 1)
401 ) (n + 1)
400inlineJS (JSApp (JSIdent "__IDR__mEVAL0") [val])
403inlineJS (JSApp (JSIdent "__IDR__mEVAL0") [val])
@@ -408,33 +411,43 @@ inlineJS (JSApp (JSIdent "__IDRRT__tailcall") [
408inlineJS (JSApp (JSFunction [arg] (JSReturn ret)) [val])
411inlineJS (JSApp (JSFunction [arg] (JSReturn ret)) [val])
409 | JSNew con [tag, vals] <- ret
412 | JSNew con [tag, vals] <- ret
410 , opt <- inlineJS val =
413 , opt <- inlineJS val =
411− JSNew con [tag, jsSubst arg opt vals]
414+ JSNew con [tag, jsSubst (JSIdent arg) opt vals]
413 | JSNew con [JSFunction [] (JSReturn (JSApp fun vars))] <- ret
416 | JSNew con [JSFunction [] (JSReturn (JSApp fun vars))] <- ret
414 , opt <- inlineJS val =
417 , opt <- inlineJS val =
415 JSNew con [JSFunction [] (
418 JSNew con [JSFunction [] (
421+ jsSubst (JSIdent arg) opt fun
416− JSReturn $ JSApp (jsSubst arg opt fun) (map (jsSubst arg opt) vars)
423+ map (jsSubst (JSIdent arg) opt) vars
419 | JSApp (JSProj obj field) args <- ret
428 | JSApp (JSProj obj field) args <- ret
420 , opt <- inlineJS val =
429 , opt <- inlineJS val =
421− JSApp (JSProj (jsSubst arg opt obj) field) $ map (jsSubst arg opt) args
431+ JSProj (jsSubst (JSIdent arg) opt obj) field
433+ map (jsSubst (JSIdent arg) opt) args
423 | JSIndex (JSProj obj field) idx <- ret
436 | JSIndex (JSProj obj field) idx <- ret
424 , opt <- inlineJS val =
437 , opt <- inlineJS val =
425 JSIndex (JSProj (
438 JSIndex (JSProj (
426− jsSubst arg opt obj
439+ jsSubst (JSIdent arg) opt obj
428− ) (jsSubst arg opt idx)
441+ ) (jsSubst (JSIdent arg) opt idx)
430 | JSOp op lhs rhs <- ret
443 | JSOp op lhs rhs <- ret
431 , opt <- inlineJS val =
444 , opt <- inlineJS val =
432− JSOp op (jsSubst arg opt lhs) $
445+ JSOp op (jsSubst (JSIdent arg) opt lhs) $
433− (jsSubst arg opt rhs)
446+ (jsSubst (JSIdent arg) opt rhs)
435 | JSApp (JSIdent fun) args <- ret
448 | JSApp (JSIdent fun) args <- ret
436 , opt <- inlineJS val =
449 , opt <- inlineJS val =
437− JSApp (JSIdent fun) $ map (jsSubst arg opt) args
450+ JSApp (JSIdent fun) $ map (jsSubst (JSIdent arg) opt) args
439inlineJS (JSApp fun args) =
452inlineJS (JSApp fun args) =
440 JSApp (inlineJS fun) (map inlineJS args)
453 JSApp (inlineJS fun) (map inlineJS args)
@@ -480,6 +493,11 @@ reduceJS js = reduceLoop [] ([], js)
480funName :: JS -> String
493funName :: JS -> String
481funName (JSAlloc fun _) = fun
494funName (JSAlloc fun _) = fun
496+elimDeadLoop :: [JS] -> [JS]
498+ | ret <- deadEvalApplyCases js
499+ , ret /= js = elimDeadLoop ret
484deadEvalApplyCases :: [JS] -> [JS]
502deadEvalApplyCases :: [JS] -> [JS]
485deadEvalApplyCases js =
503deadEvalApplyCases js =
@@ -816,6 +834,131 @@ reduceConstants js
816 , ret /= js = reduceConstants ret
834 , ret /= js = reduceConstants ret
817 | otherwise = js
835 | otherwise = js
838+elimDuplicateEvals :: JS -> JS
839+elimDuplicateEvals (JSAlloc fun (Just (JSFunction args (JSSeq seq)))) =
840+ JSAlloc fun $ Just (JSFunction args $ JSSeq (elimHelper seq))
842+ elimHelper :: [JS] -> [JS]
843+ elimHelper (j@(JSAlloc var (Just val)):js) =
844+ j : map (jsSubst val (JSIdent var)) (elimHelper js)
849+elimDuplicateEvals js = js
851+optimizeEvalTailcalls :: (String, String) -> JS -> JS
852+optimizeEvalTailcalls (fun, tc) js =
855+ optHelper :: JS -> JS
856+ optHelper (JSApp (JSIdent "__IDRRT__tailcall") [
857+ JSFunction [] (JSReturn (JSApp (JSIdent n) args))
859+ | n == fun = JSApp (JSIdent tc) $ map optHelper args
861+ optHelper (JSFunction args body) =
862+ JSFunction args $ optHelper body
864+ optHelper (JSSeq seq) =
865+ JSSeq $ map optHelper seq
867+ optHelper (JSReturn ret) =
868+ JSReturn $ optHelper ret
870+ optHelper (JSApp lhs rhs) =
871+ JSApp (optHelper lhs) (map optHelper rhs)
873+ optHelper (JSNew con args) =
874+ JSNew con $ map optHelper args
876+ optHelper (JSOp op lhs rhs) =
877+ JSOp op (optHelper lhs) (optHelper rhs)
879+ optHelper (JSProj obj field) =
880+ JSProj (optHelper obj) field
882+ optHelper (JSArray vals) =
883+ JSArray $ map optHelper vals
885+ optHelper (JSAssign lhs rhs) =
886+ JSAssign (optHelper lhs) (optHelper rhs)
888+ optHelper (JSAlloc var (Just val)) =
889+ JSAlloc var (Just $ optHelper val)
891+ optHelper (JSIndex lhs rhs) =
892+ JSIndex (optHelper lhs) (optHelper rhs)
894+ optHelper (JSCond conds) =
895+ JSCond $ map (optHelper *** optHelper) conds
897+ optHelper (JSTernary c t f) =
909+removeInstanceChecks :: JS -> JS
910+removeInstanceChecks (JSCond conds) =
911+ JSCond $ map (removeHelper *** removeInstanceChecks) conds
914+ JSOp "&&" (JSOp "instanceof" _ (JSIdent "__IDRRT__Con")) check
915+ ) = removeHelper check
916+ removeHelper js = js
918+removeInstanceChecks (JSFunction args body) =
919+ JSFunction args $ removeInstanceChecks body
921+removeInstanceChecks (JSSeq seq) =
922+ JSSeq $ map removeInstanceChecks seq
924+removeInstanceChecks (JSReturn ret) =
925+ JSReturn $ removeInstanceChecks ret
927+removeInstanceChecks (JSApp lhs rhs) =
928+ JSApp (removeInstanceChecks lhs) $ map removeInstanceChecks rhs
930+removeInstanceChecks (JSNew con args) =
931+ JSNew con $ map removeInstanceChecks args
933+removeInstanceChecks (JSOp op lhs rhs) =
934+ JSOp op (removeInstanceChecks lhs) (removeInstanceChecks rhs)
936+removeInstanceChecks (JSProj obj field) =
937+ JSProj (removeInstanceChecks obj) field
939+removeInstanceChecks (JSArray vals) =
940+ JSArray $ map removeInstanceChecks vals
942+removeInstanceChecks (JSAssign lhs rhs) =
943+ JSAssign (removeInstanceChecks lhs) (removeInstanceChecks rhs)
945+removeInstanceChecks (JSAlloc var (Just val)) =
946+ JSAlloc var (Just $ removeInstanceChecks val)
948+removeInstanceChecks (JSIndex lhs rhs) =
949+ JSIndex (removeInstanceChecks lhs) (removeInstanceChecks rhs)
951+removeInstanceChecks (JSTernary c t f) =
953+ removeInstanceChecks c
955+ removeInstanceChecks t
957+ removeInstanceChecks f
960+removeInstanceChecks js = js
819reduceLoop :: [String] -> ([JS], [JS]) -> [JS]
962reduceLoop :: [String] -> ([JS], [JS]) -> [JS]
820reduceLoop reduced (cons, program) =
963reduceLoop reduced (cons, program) =
821 case partition findConstructors program of
964 case partition findConstructors program of
@@ -942,8 +1085,13 @@ codegenJavaScript target definitions filename outputType = do
942 constRemoved = map reduceConstants reduced
1085 constRemoved = map reduceConstants reduced
943 constrInit = initConstructors constRemoved
1086 constrInit = initConstructors constRemoved
944 removeAlloc = map removeAllocations constrInit
1087 removeAlloc = map removeAllocations constrInit
945− deadElim = deadEvalApplyCases removeAlloc
1088+ deadElim = elimDeadLoop removeAlloc
946− js = inlineFunctions deadElim in
1089+ inlined = inlineFunctions deadElim
1090+ elimDup = map elimDuplicateEvals inlined
1091+ evalTC = map (optimizeEvalTailcalls ("__IDR__mEVAL0", "__IDRRT__EVALTC")) elimDup
1092+ applyTC = map (optimizeEvalTailcalls ("__IDR__mAPPLY0", "__IDRRT__APPLYTC")) evalTC
1093+ remChecks = map removeInstanceChecks applyTC
947 map compileJS js
1095 map compileJS js
949 mainLoop :: JS
1097 mainLoop :: JS