-- | Desugar String Literal nodes into ListExpr nodes
module Front.DesugarStrings (
  desugarStrings,
) where

import qualified Common.Compiler as Compiler
import qualified Front.Ast as A

import Data.Char (ord)
import Data.Generics (everywhere, mkT)


-- | Desugar 'A.LitString' nodes inside of an AST 'A.Program'.
desugarStrings :: A.Program -> Compiler.Pass A.Program
desugarStrings :: Program -> Pass Program
desugarStrings (A.Program [TopDef]
decls) = Program -> Pass Program
forall (m :: * -> *) a. Monad m => a -> m a
return (Program -> Pass Program) -> Program -> Pass Program
forall a b. (a -> b) -> a -> b
$ [TopDef] -> Program
A.Program ([TopDef] -> Program) -> [TopDef] -> Program
forall a b. (a -> b) -> a -> b
$ TopDef -> TopDef
desugarTop (TopDef -> TopDef) -> [TopDef] -> [TopDef]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TopDef]
decls
 where
  desugarTop :: TopDef -> TopDef
desugarTop (A.TopDef Definition
d) = Definition -> TopDef
A.TopDef (Definition -> TopDef) -> Definition -> TopDef
forall a b. (a -> b) -> a -> b
$ Definition -> Definition
desugarDef Definition
d
  desugarTop TopDef
t = TopDef
t

  desugarDef :: Definition -> Definition
desugarDef (A.DefFn Identifier
v [Pat]
bs TypFn
t Expr
e) = Identifier -> [Pat] -> TypFn -> Expr -> Definition
A.DefFn Identifier
v [Pat]
bs TypFn
t (Expr -> Definition) -> Expr -> Definition
forall a b. (a -> b) -> a -> b
$ (forall a. Data a => a -> a) -> Expr -> Expr
(forall a. Data a => a -> a) -> forall a. Data a => a -> a
everywhere ((Expr -> Expr) -> a -> a
forall a b. (Typeable a, Typeable b) => (b -> b) -> a -> a
mkT Expr -> Expr
desugarExpr) Expr
e
  desugarDef (A.DefPat Pat
b Expr
e) = Pat -> Expr -> Definition
A.DefPat Pat
b (Expr -> Definition) -> Expr -> Definition
forall a b. (a -> b) -> a -> b
$ (forall a. Data a => a -> a) -> Expr -> Expr
(forall a. Data a => a -> a) -> forall a. Data a => a -> a
everywhere ((Expr -> Expr) -> a -> a
forall a b. (Typeable a, Typeable b) => (b -> b) -> a -> a
mkT Expr -> Expr
desugarExpr) Expr
e


{- | Transform a node of 'A.LitString' into a node of type 'A.ListExpr'.

For example:

@@
  (Lit (LitString "abc"))
@@

turns into

@@
  (ListExpr [97, 98, 99])
@@
-}
desugarExpr :: A.Expr -> A.Expr
desugarExpr :: Expr -> Expr
desugarExpr (A.Lit (A.LitString String
s)) = [Expr] -> Expr
A.ListExpr ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ String -> [Expr]
convertList String
s
 where
  convertList :: String -> [Expr]
convertList String
ls = [Literal -> Expr
A.Lit (Literal -> Expr) -> Literal -> Expr
forall a b. (a -> b) -> a -> b
$ Integer -> Literal
A.LitInt (Integer -> Literal) -> Integer -> Literal
forall a b. (a -> b) -> a -> b
$ Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
i | Int
i <- (Char -> Int) -> String -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map Char -> Int
ord String
ls]
desugarExpr Expr
e = Expr
e