{-|
Module      : IRTS.JavaScript.Name
Description : The JavaScript name mangler.

License     : BSD3
Maintainer  : The Idris Community.
-}

{-# LANGUAGE OverloadedStrings, PatternGuards #-}

module IRTS.JavaScript.Name
  ( jsName
  , jsNameGenerated
  , Partial(..)
  , jsNamePartial
  , jsTailCallOptimName
  , HiddenClass(..)
  , jsNameHiddenClass
  , dataPartName
  ) where

import Data.Char
import Data.Text (Text)
import qualified Data.Text as T
import Idris.Core.TT

jsEscape :: String -> String
jsEscape :: [Char] -> [Char]
jsEscape = (Char -> [Char]) -> [Char] -> [Char]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> [Char]
jschar
  where
    jschar :: Char -> [Char]
jschar Char
x
      | Char -> Bool
isAlpha Char
x Bool -> Bool -> Bool
|| Char -> Bool
isDigit Char
x = [Char
x]
      | Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.' = [Char]
"__"
      | Bool
otherwise = [Char]
"_" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show (Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
x) [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
"_"

jsName :: Name -> Text
jsName :: Name -> Text
jsName (MN Int
i Text
u) = [Text] -> Text
T.concat [Text
"$_", [Char] -> Text
T.pack (Int -> [Char]
forall a. Show a => a -> [Char]
show Int
i), Text
"_", [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
jsEscape ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Text -> [Char]
T.unpack Text
u]
jsName Name
n = [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char] -> [Char]
jsEscape ([Char] -> [Char]) -> [Char] -> [Char]
forall a b. (a -> b) -> a -> b
$ Name -> [Char]
showCG Name
n

jsNameGenerated :: Int -> Text
jsNameGenerated :: Int -> Text
jsNameGenerated Int
v = [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char]
"$cg$" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
v

data Partial = Partial Name Int Int deriving (Partial -> Partial -> Bool
(Partial -> Partial -> Bool)
-> (Partial -> Partial -> Bool) -> Eq Partial
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: Partial -> Partial -> Bool
== :: Partial -> Partial -> Bool
$c/= :: Partial -> Partial -> Bool
/= :: Partial -> Partial -> Bool
Eq, Eq Partial
Eq Partial =>
(Partial -> Partial -> Ordering)
-> (Partial -> Partial -> Bool)
-> (Partial -> Partial -> Bool)
-> (Partial -> Partial -> Bool)
-> (Partial -> Partial -> Bool)
-> (Partial -> Partial -> Partial)
-> (Partial -> Partial -> Partial)
-> Ord Partial
Partial -> Partial -> Bool
Partial -> Partial -> Ordering
Partial -> Partial -> Partial
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: Partial -> Partial -> Ordering
compare :: Partial -> Partial -> Ordering
$c< :: Partial -> Partial -> Bool
< :: Partial -> Partial -> Bool
$c<= :: Partial -> Partial -> Bool
<= :: Partial -> Partial -> Bool
$c> :: Partial -> Partial -> Bool
> :: Partial -> Partial -> Bool
$c>= :: Partial -> Partial -> Bool
>= :: Partial -> Partial -> Bool
$cmax :: Partial -> Partial -> Partial
max :: Partial -> Partial -> Partial
$cmin :: Partial -> Partial -> Partial
min :: Partial -> Partial -> Partial
Ord)

jsNamePartial :: Partial -> Text
jsNamePartial :: Partial -> Text
jsNamePartial (Partial Name
n Int
i Int
j) = [Text] -> Text
T.concat [Text
"$partial_", [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
i, Text
"_", [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
j, Text
"$" , Name -> Text
jsName Name
n]

jsTailCallOptimName :: Text -> Text
jsTailCallOptimName :: Text -> Text
jsTailCallOptimName Text
x = [Text] -> Text
T.concat [Text
"$tco$", Text
x]


data HiddenClass = HiddenClass Name Int Int deriving (HiddenClass -> HiddenClass -> Bool
(HiddenClass -> HiddenClass -> Bool)
-> (HiddenClass -> HiddenClass -> Bool) -> Eq HiddenClass
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: HiddenClass -> HiddenClass -> Bool
== :: HiddenClass -> HiddenClass -> Bool
$c/= :: HiddenClass -> HiddenClass -> Bool
/= :: HiddenClass -> HiddenClass -> Bool
Eq, Eq HiddenClass
Eq HiddenClass =>
(HiddenClass -> HiddenClass -> Ordering)
-> (HiddenClass -> HiddenClass -> Bool)
-> (HiddenClass -> HiddenClass -> Bool)
-> (HiddenClass -> HiddenClass -> Bool)
-> (HiddenClass -> HiddenClass -> Bool)
-> (HiddenClass -> HiddenClass -> HiddenClass)
-> (HiddenClass -> HiddenClass -> HiddenClass)
-> Ord HiddenClass
HiddenClass -> HiddenClass -> Bool
HiddenClass -> HiddenClass -> Ordering
HiddenClass -> HiddenClass -> HiddenClass
forall a.
Eq a =>
(a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
$ccompare :: HiddenClass -> HiddenClass -> Ordering
compare :: HiddenClass -> HiddenClass -> Ordering
$c< :: HiddenClass -> HiddenClass -> Bool
< :: HiddenClass -> HiddenClass -> Bool
$c<= :: HiddenClass -> HiddenClass -> Bool
<= :: HiddenClass -> HiddenClass -> Bool
$c> :: HiddenClass -> HiddenClass -> Bool
> :: HiddenClass -> HiddenClass -> Bool
$c>= :: HiddenClass -> HiddenClass -> Bool
>= :: HiddenClass -> HiddenClass -> Bool
$cmax :: HiddenClass -> HiddenClass -> HiddenClass
max :: HiddenClass -> HiddenClass -> HiddenClass
$cmin :: HiddenClass -> HiddenClass -> HiddenClass
min :: HiddenClass -> HiddenClass -> HiddenClass
Ord)

jsNameHiddenClass :: HiddenClass -> Text
jsNameHiddenClass :: HiddenClass -> Text
jsNameHiddenClass (HiddenClass Name
n Int
id Int
arity) = [Text] -> Text
T.concat [Text
"$HC_", [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
arity, Text
"_", [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
id,Text
"$", Name -> Text
jsName Name
n]

dataPartName :: Int -> Text
dataPartName :: Int -> Text
dataPartName Int
i = [Char] -> Text
T.pack ([Char] -> Text) -> [Char] -> Text
forall a b. (a -> b) -> a -> b
$ [Char]
"$" [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ Int -> [Char]
forall a. Show a => a -> [Char]
show Int
i