{-# LANGUAGE OverloadedStrings, PatternGuards #-}
module IRTS.JavaScript.Specialize
( SCtor
, STest
, SProj
, specialCased
, specialCall
, qualifyN
) where
import qualified Data.Map.Strict as Map
import qualified Data.Text as T
import Idris.Core.TT
import IRTS.JavaScript.AST
split :: Char -> String -> [String]
split c "" = [""]
split c (x:xs)
| c == x = "" : split c xs
| otherwise =
let ~(h:t) = split c xs
in ((x : h) : t)
qualify :: String -> Name -> Name
qualify "" n = n
qualify ns n = sNS n (reverse $ split '.' ns)
qualifyN :: String -> String -> Name
qualifyN ns n = qualify ns $ sUN n
type SCtor = [JsExpr] -> JsExpr
type STest = JsExpr -> JsExpr
type SProj = JsExpr -> Int -> JsExpr
constructorOptimizeDB :: Map.Map Name (SCtor, STest, SProj)
constructorOptimizeDB =
Map.fromList
[ item "Prelude.Bool" "True" (const $ JsBool True) trueTest cantProj
, item "Prelude.Bool" "False" (const $ JsBool False) falseTest cantProj
, item "Prelude.Interfaces" "LT" (const $ JsInt (0-1)) ltTest cantProj
, item "Prelude.Interfaces" "EQ" (const $ JsInt 0) eqTest cantProj
, item "Prelude.Interfaces" "GT" (const $ JsInt 1) gtTest cantProj
]
where
trueTest = id
falseTest e = JsUniOp (T.pack "!") e
ltTest e = JsBinOp "<" e (JsInt 0)
eqTest e = JsBinOp "===" e (JsInt 0)
gtTest e = JsBinOp ">" e (JsInt 0)
cantProj x j = error $ "This type should be projected"
item :: String
-> String
-> SCtor
-> STest
-> SProj
-> (Name, (SCtor, STest, SProj))
item ns n ctor test match = (qualifyN ns n, (ctor, test, match))
specialCased :: Name -> Maybe (SCtor, STest, SProj)
specialCased n = Map.lookup n constructorOptimizeDB
type SSig = (Int, [JsExpr] -> JsExpr)
callSpecializeDB :: Map.Map Name (SSig)
callSpecializeDB =
Map.fromList
[ qb "Eq" "Int" "==" "==="
, qb "Ord" "Int" "<" "<"
, qb "Ord" "Int" ">" ">"
, qb "Ord" "Int" "<=" "<="
, qb "Ord" "Int" ">=" ">="
, qb "Eq" "Double" "==" "==="
, qb "Ord" "Double" "<" "<"
, qb "Ord" "Double" ">" ">"
, qb "Ord" "Double" "<=" "<="
, qb "Ord" "Double" ">=" ">="
]
where
qb intf ty op jsop =
( qualify "Prelude.Interfaces" $
SN $
WhereN
0
(qualify "Prelude.Interfaces" $
SN $ ImplementationN (qualifyN "Prelude.Interfaces" intf) [ty])
(SN $ MethodN $ UN op)
, (2, \[x, y] -> JsBinOp jsop x y))
specialCall :: Name -> Maybe SSig
specialCall n = Map.lookup n callSpecializeDB