-- | Desugar 'ListExpr' nodes into 'App' nodes
module Front.DesugarLists (desugarLists) where

import qualified Common.Compiler as Compiler
import Common.Identifiers
import Data.Generics (everywhere, mkT)
import qualified Front.Ast as A


-- | Desugar ListExpr nodes inside of an AST 'A.Program'.
desugarLists :: A.Program -> Compiler.Pass A.Program
desugarLists :: Program -> Pass Program
desugarLists (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 'ListExpr' into a node of 'App'.

For example,
@@
(ListExpr [1, 2, 3])
@@

turns into

@@
App (App (Id "Cons") (Lit (LitInt 1) ))
  (App (App (Id "Cons") (Lit (LitInt 2)))
       (App (App (Id "Cons") (Lit (LitInt 3))) (id "Nil")))
@@
-}
desugarExpr :: A.Expr -> A.Expr
desugarExpr :: Expr -> Expr
desugarExpr (A.ListExpr [Expr]
es) = [Expr] -> Expr
helper [Expr]
es
 where
  helper :: [A.Expr] -> A.Expr
  helper :: [Expr] -> Expr
helper [] = Identifier -> Expr
A.Id Identifier
nil
  helper (Expr
h : [Expr]
t) = Expr -> Expr -> Expr
A.Apply (Expr -> Expr -> Expr
A.Apply (Identifier -> Expr
A.Id Identifier
cons) Expr
h) ([Expr] -> Expr
helper [Expr]
t)
desugarExpr Expr
e = Expr
e