@@ -27,7 +27,9 @@
28-- * Inlining variables
28-- * Inlining variables
30−-- * Inline Prelude.($)
30+-- * Inline Prelude.($), Prelude.(++), Prelude.(!!)
32+-- * Inlining primitive Javascript operators
32-----------------------------------------------------------------------------
34-----------------------------------------------------------------------------
@@ -45,13 +47,14 @@ import Language.PureScript.Options
45import Language.PureScript.CodeGen.Common (identToJs)
47import Language.PureScript.CodeGen.Common (identToJs)
46import Language.PureScript.Sugar.TypeClasses
48import Language.PureScript.Sugar.TypeClasses
47 (mkDictionaryValueName)
49 (mkDictionaryValueName)
48−import Language.PureScript.Types (Type(..))
50+import Language.PureScript.Types
51-- Apply a series of optimizer passes to simplified Javascript code
53-- Apply a series of optimizer passes to simplified Javascript code
53optimize :: Options -> JS -> JS
55optimize :: Options -> JS -> JS
56+optimize opts | optionsNoOptimizations opts = id
54−optimize opts = untilFixedPoint $ applyAll
57+ | otherwise = untilFixedPoint $ applyAll
55 [ collapseNestedBlocks
58 [ collapseNestedBlocks
56 , tco opts
59 , tco opts
57 , magicDo opts
60 , magicDo opts
@@ -59,7 +62,10 @@ optimize opts = untilFixedPoint $ applyAll
60 , etaConvert
63 , etaConvert
61 , inlineVariables
64 , inlineVariables
62− , inlineDollar ]
65+ , inlineOperator "$" $ \f x -> JSApp f [x]
66+ , inlineOperator "!!" $ flip JSIndexer
67+ , inlineOperator "++" $ JSBinary Add
68+ , inlineCommonOperators ]
64applyAll :: [a -> a] -> a -> a
70applyAll :: [a -> a] -> a -> a
65applyAll = foldl1 (.)
71applyAll = foldl1 (.)
@@ -293,12 +299,71 @@ collapseNestedBlocks = everywhere (mkT collapse)
293 go (JSBlock sts) = sts
299 go (JSBlock sts) = sts
294 go s = [s]
300 go s = [s]
296−inlineDollar :: JS -> JS
302+inlineOperator :: String -> (JS -> JS -> JS) -> JS -> JS
297−inlineDollar = everywhere (mkT convert)
303+inlineOperator op f = everywhere (mkT convert)
299 convert :: JS -> JS
305 convert :: JS -> JS
300− convert (JSApp (JSApp dollar [f]) [x]) | isDollar dollar = JSApp f [x]
306+ convert (JSApp (JSApp op [x]) [y]) | isOp op = f x y
301 convert other = other
307 convert other = other
302− isDollar (JSAccessor "$dollar" (JSVar "Prelude")) = True
308+ isOp (JSAccessor longForm (JSVar "Prelude")) | longForm == identToJs (Op op) = True
309+ isOp (JSIndexer (JSStringLiteral op') (JSVar "Prelude")) | op == op' = True
312+inlineCommonOperators :: JS -> JS
313+inlineCommonOperators = applyAll
314+ [ binary "+" "Num" tyNumber Add
315+ , binary "-" "Num" tyNumber Subtract
316+ , binary "*" "Num" tyNumber Multiply
317+ , binary "/" "Num" tyNumber Divide
318+ , binary "%" "Num" tyNumber Modulus
319+ , unary "negate" "Num" tyNumber Negate
321+ , binary "<" "Ord" tyNumber LessThan
322+ , binary ">" "Ord" tyNumber GreaterThan
323+ , binary "<=" "Ord" tyNumber LessThanOrEqualTo
324+ , binary ">=" "Ord" tyNumber GreaterThanOrEqualTo
326+ , binary "==" "Eq" tyNumber EqualTo
327+ , binary "/=" "Eq" tyNumber NotEqualTo
328+ , binary "==" "Eq" tyString EqualTo
329+ , binary "/=" "Eq" tyString NotEqualTo
330+ , binary "==" "Eq" tyBoolean EqualTo
331+ , binary "/=" "Eq" tyBoolean NotEqualTo
333+ , binary "<<" "Bits" tyNumber ShiftLeft
334+ , binary ">>" "Bits" tyNumber ShiftRight
335+ , binary ">>>" "Bits" tyNumber ZeroFillShiftRight
336+ , binary "&" "Bits" tyNumber BitwiseAnd
337+ , binary "|" "Bits" tyNumber BitwiseOr
338+ , binary "^" "Bits" tyNumber BitwiseXor
339+ , unary "complement" "Bits" tyNumber BitwiseNot
341+ , binary "&&" "BoolLike" tyBoolean And
342+ , binary "||" "BoolLike" tyBoolean Or
343+ , unary "not" "BoolLike" tyBoolean Not
346+ binary :: String -> String -> Type -> BinaryOperator -> JS -> JS
347+ binary opString className classTy op = everywhere (mkT convert)
350+ convert (JSApp (JSApp (JSApp fn [dict]) [x]) [y]) | isOp fn && isOpDict className classTy dict = JSBinary op x y
351+ convert other = other
352+ isOp (JSAccessor longForm (JSVar "Prelude")) | longForm == identToJs (Op opString) = True
303− isDollar (JSIndexer (JSStringLiteral "$") (JSVar "Prelude")) = True
353+ isOp (JSIndexer (JSStringLiteral op') (JSVar "Prelude")) | opString == op' = True
355+ unary :: String -> String -> Type -> UnaryOperator -> JS -> JS
356+ unary fnName className classTy op = everywhere (mkT convert)
359+ convert (JSApp (JSApp fn [dict]) [x]) | isOp fn && isOpDict className classTy dict = JSUnary op x
360+ convert other = other
361+ isOp (JSAccessor fnName' (JSVar "Prelude")) | fnName' == fnName = True
363+ isOpDict className ty (JSAccessor prop (JSVar "Prelude")) | prop == dictName = True
365+ Right (Ident dictName) = mkDictionaryValueName
366+ (ModuleName (ProperName "Prelude"))
367+ (Qualified (Just (ModuleName (ProperName "Prelude"))) (ProperName className))
304− isDollar _ = False
369+ isOpDict _ _ _ = False