{-|
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 :: String -> String
jsEscape = (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
jschar
  where
    jschar :: Char -> String
jschar x :: 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
== '.' = "__"
      | Bool
otherwise = "_" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show (Char -> Int
forall a. Enum a => a -> Int
fromEnum Char
x) String -> String -> String
forall a. [a] -> [a] -> [a]
++ "_"

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

jsNameGenerated :: Int -> Text
jsNameGenerated :: Int -> Text
jsNameGenerated v :: Int
v = String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$ "$cg$" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
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
/= :: Partial -> Partial -> Bool
$c/= :: Partial -> Partial -> Bool
== :: Partial -> Partial -> Bool
$c== :: 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
min :: Partial -> Partial -> Partial
$cmin :: Partial -> Partial -> Partial
max :: Partial -> Partial -> Partial
$cmax :: Partial -> Partial -> Partial
>= :: Partial -> Partial -> Bool
$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
compare :: Partial -> Partial -> Ordering
$ccompare :: Partial -> Partial -> Ordering
$cp1Ord :: Eq Partial
Ord)

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

jsTailCallOptimName :: Text -> Text
jsTailCallOptimName :: Text -> Text
jsTailCallOptimName x :: Text
x = [Text] -> Text
T.concat ["$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
/= :: HiddenClass -> HiddenClass -> Bool
$c/= :: HiddenClass -> HiddenClass -> Bool
== :: HiddenClass -> HiddenClass -> Bool
$c== :: 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
min :: HiddenClass -> HiddenClass -> HiddenClass
$cmin :: HiddenClass -> HiddenClass -> HiddenClass
max :: HiddenClass -> HiddenClass -> HiddenClass
$cmax :: HiddenClass -> HiddenClass -> HiddenClass
>= :: HiddenClass -> HiddenClass -> Bool
$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
compare :: HiddenClass -> HiddenClass -> Ordering
$ccompare :: HiddenClass -> HiddenClass -> Ordering
$cp1Ord :: Eq HiddenClass
Ord)

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

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