{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE NoImplicitPrelude #-}

-- | Nix expression types and auxiliary functions.
-- Since 'Expr' is actually a fixpoint over the 'ExprF' base functor, this
-- module also exposes auxiliary functions that serve as constructors.
module PureNix.Expr where

import Data.List.NonEmpty (NonEmpty (..))
import PureNix.Identifiers
import PureNix.Prelude

-- | The fixpoint over 'ExprF', see haddocks there for more information.
newtype Expr = Expr {Expr -> ExprF Expr
unExpr :: ExprF Expr}
  -- Explicitly using the @newtype@ strategy here makes the 'Show' instance
  -- much nicer, since it makes it so you don't get all the @Expr@
  -- constructors.
  deriving newtype (Int -> Expr -> ShowS
[Expr] -> ShowS
Expr -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Expr] -> ShowS
$cshowList :: [Expr] -> ShowS
show :: Expr -> String
$cshow :: Expr -> String
showsPrec :: Int -> Expr -> ShowS
$cshowsPrec :: Int -> Expr -> ShowS
Show)

-- | Base functor for a Nix expression.
-- We don't aim to be able to represent every valid Nix expression, just the
-- ones that are relevant for PureNix.
--
-- 'ExprF' is the base functor for the 'Expr' fixpoint.
-- This allows us to easily annotate and consume it during pretty-printing.
--
-- Note that 'String', unlike 'Key' and 'Var', is a raw representation of the intended string, completely unquoted and unescaped.
-- That means that it might consist of, for example, a single '"'.
-- It is the job of the printer to figure out how to correctly escape those.
data ExprF f
  = Var Var
  | Lam Var f
  | App f f
  | Attrs [Var] [(f, [Key])] [(Key, f)]
  | Cond f f f
  | List [f]
  | Bin Op f f
  | Not f
  | Sel f Key
  | Let (NonEmpty (Var, f)) f
  | Int Integer
  | Double Double
  | String Text
  | Path Text
  deriving stock (forall a b. a -> ExprF b -> ExprF a
forall a b. (a -> b) -> ExprF a -> ExprF b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> ExprF b -> ExprF a
$c<$ :: forall a b. a -> ExprF b -> ExprF a
fmap :: forall a b. (a -> b) -> ExprF a -> ExprF b
$cfmap :: forall a b. (a -> b) -> ExprF a -> ExprF b
Functor, forall a. Eq a => a -> ExprF a -> Bool
forall a. Num a => ExprF a -> a
forall a. Ord a => ExprF a -> a
forall m. Monoid m => ExprF m -> m
forall a. ExprF a -> Bool
forall a. ExprF a -> Int
forall a. ExprF a -> [a]
forall a. (a -> a -> a) -> ExprF a -> a
forall m a. Monoid m => (a -> m) -> ExprF a -> m
forall b a. (b -> a -> b) -> b -> ExprF a -> b
forall a b. (a -> b -> b) -> b -> ExprF a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: forall a. Num a => ExprF a -> a
$cproduct :: forall a. Num a => ExprF a -> a
sum :: forall a. Num a => ExprF a -> a
$csum :: forall a. Num a => ExprF a -> a
minimum :: forall a. Ord a => ExprF a -> a
$cminimum :: forall a. Ord a => ExprF a -> a
maximum :: forall a. Ord a => ExprF a -> a
$cmaximum :: forall a. Ord a => ExprF a -> a
elem :: forall a. Eq a => a -> ExprF a -> Bool
$celem :: forall a. Eq a => a -> ExprF a -> Bool
length :: forall a. ExprF a -> Int
$clength :: forall a. ExprF a -> Int
null :: forall a. ExprF a -> Bool
$cnull :: forall a. ExprF a -> Bool
toList :: forall a. ExprF a -> [a]
$ctoList :: forall a. ExprF a -> [a]
foldl1 :: forall a. (a -> a -> a) -> ExprF a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> ExprF a -> a
foldr1 :: forall a. (a -> a -> a) -> ExprF a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> ExprF a -> a
foldl' :: forall b a. (b -> a -> b) -> b -> ExprF a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> ExprF a -> b
foldl :: forall b a. (b -> a -> b) -> b -> ExprF a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> ExprF a -> b
foldr' :: forall a b. (a -> b -> b) -> b -> ExprF a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> ExprF a -> b
foldr :: forall a b. (a -> b -> b) -> b -> ExprF a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> ExprF a -> b
foldMap' :: forall m a. Monoid m => (a -> m) -> ExprF a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> ExprF a -> m
foldMap :: forall m a. Monoid m => (a -> m) -> ExprF a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> ExprF a -> m
fold :: forall m. Monoid m => ExprF m -> m
$cfold :: forall m. Monoid m => ExprF m -> m
Foldable, Functor ExprF
Foldable ExprF
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a. Monad m => ExprF (m a) -> m (ExprF a)
forall (f :: * -> *) a. Applicative f => ExprF (f a) -> f (ExprF a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> ExprF a -> m (ExprF b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> ExprF a -> f (ExprF b)
sequence :: forall (m :: * -> *) a. Monad m => ExprF (m a) -> m (ExprF a)
$csequence :: forall (m :: * -> *) a. Monad m => ExprF (m a) -> m (ExprF a)
mapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> ExprF a -> m (ExprF b)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> ExprF a -> m (ExprF b)
sequenceA :: forall (f :: * -> *) a. Applicative f => ExprF (f a) -> f (ExprF a)
$csequenceA :: forall (f :: * -> *) a. Applicative f => ExprF (f a) -> f (ExprF a)
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> ExprF a -> f (ExprF b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> ExprF a -> f (ExprF b)
Traversable, Int -> ExprF f -> ShowS
forall f. Show f => Int -> ExprF f -> ShowS
forall f. Show f => [ExprF f] -> ShowS
forall f. Show f => ExprF f -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [ExprF f] -> ShowS
$cshowList :: forall f. Show f => [ExprF f] -> ShowS
show :: ExprF f -> String
$cshow :: forall f. Show f => ExprF f -> String
showsPrec :: Int -> ExprF f -> ShowS
$cshowsPrec :: forall f. Show f => Int -> ExprF f -> ShowS
Show)

data Op = Update | Equals | And
  deriving (Op -> Op -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Op -> Op -> Bool
$c/= :: Op -> Op -> Bool
== :: Op -> Op -> Bool
$c== :: Op -> Op -> Bool
Eq, Int -> Op -> ShowS
[Op] -> ShowS
Op -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Op] -> ShowS
$cshowList :: [Op] -> ShowS
show :: Op -> String
$cshow :: Op -> String
showsPrec :: Int -> Op -> ShowS
$cshowsPrec :: Int -> Op -> ShowS
Show)

foldExpr :: (ExprF r -> r) -> Expr -> r
foldExpr :: forall r. (ExprF r -> r) -> Expr -> r
foldExpr ExprF r -> r
f = Expr -> r
go where go :: Expr -> r
go = ExprF r -> r
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Expr -> r
go forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expr -> ExprF Expr
unExpr

var :: Var -> Expr
var :: Var -> Expr
var = ExprF Expr -> Expr
Expr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall f. Var -> ExprF f
Var

lam :: Var -> Expr -> Expr
lam :: Var -> Expr -> Expr
lam Var
arg Expr
body = ExprF Expr -> Expr
Expr forall a b. (a -> b) -> a -> b
$ forall f. Var -> f -> ExprF f
Lam Var
arg Expr
body

app :: Expr -> Expr -> Expr
app :: Expr -> Expr -> Expr
app Expr
f Expr
x = ExprF Expr -> Expr
Expr forall a b. (a -> b) -> a -> b
$ forall f. f -> f -> ExprF f
App Expr
f Expr
x

cond :: Expr -> Expr -> Expr -> Expr
cond :: Expr -> Expr -> Expr -> Expr
cond Expr
c Expr
true Expr
false = ExprF Expr -> Expr
Expr forall a b. (a -> b) -> a -> b
$ forall f. f -> f -> f -> ExprF f
Cond Expr
c Expr
true Expr
false

attrs ::
  [Var] ->
  [(Expr, [Key])] ->
  [(Key, Expr)] ->
  Expr
attrs :: [Var] -> [(Expr, [Key])] -> [(Key, Expr)] -> Expr
attrs [Var]
inherits [(Expr, [Key])]
inheritFroms [(Key, Expr)]
binds = ExprF Expr -> Expr
Expr forall a b. (a -> b) -> a -> b
$ forall f. [Var] -> [(f, [Key])] -> [(Key, f)] -> ExprF f
Attrs [Var]
inherits [(Expr, [Key])]
inheritFroms [(Key, Expr)]
binds

sel :: Expr -> Key -> Expr
sel :: Expr -> Key -> Expr
sel Expr
e Key
s = ExprF Expr -> Expr
Expr forall a b. (a -> b) -> a -> b
$ forall f. f -> Key -> ExprF f
Sel Expr
e Key
s

let' :: [(Var, Expr)] -> Expr -> Expr
let' :: [(Var, Expr)] -> Expr -> Expr
let' [] Expr
body = Expr
body
let' ((Var, Expr)
h : [(Var, Expr)]
t) Expr
body = ExprF Expr -> Expr
Expr forall a b. (a -> b) -> a -> b
$ forall f. NonEmpty (Var, f) -> f -> ExprF f
Let ((Var, Expr)
h forall a. a -> [a] -> NonEmpty a
:| [(Var, Expr)]
t) Expr
body

int :: Integer -> Expr
int :: Integer -> Expr
int = ExprF Expr -> Expr
Expr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall f. Integer -> ExprF f
Int

double :: Double -> Expr
double :: Double -> Expr
double = ExprF Expr -> Expr
Expr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall f. Double -> ExprF f
Double

string :: Text -> Expr
string :: Text -> Expr
string = ExprF Expr -> Expr
Expr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall f. Text -> ExprF f
String

list :: [Expr] -> Expr
list :: [Expr] -> Expr
list = ExprF Expr -> Expr
Expr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall f. [f] -> ExprF f
List

bin :: Op -> Expr -> Expr -> Expr
bin :: Op -> Expr -> Expr -> Expr
bin Op
op Expr
a Expr
b = ExprF Expr -> Expr
Expr forall a b. (a -> b) -> a -> b
$ forall f. Op -> f -> f -> ExprF f
Bin Op
op Expr
a Expr
b

path :: Text -> Expr
path :: Text -> Expr
path = ExprF Expr -> Expr
Expr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall f. Text -> ExprF f
Path

constructorFieldNames :: [Var]
constructorFieldNames :: [Var]
constructorFieldNames = Text -> [Var]
numberedVars Text
"__field"

not' :: Expr -> Expr
not' :: Expr -> Expr
not' = ExprF Expr -> Expr
Expr forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall f. f -> ExprF f
Not

-- | Convenience constructor for builtins.
-- Takes a Key, and gives you @builtins.key@
builtin :: Key -> Expr
builtin :: Key -> Expr
builtin = Expr -> Key -> Expr
sel (Var -> Expr
var Var
"builtins")

--   Just
-- becomes
--   (a: { __tag = "Just"; __field0 = a; })
constructor :: Text -> [Var] -> Expr
constructor :: Text -> [Var] -> Expr
constructor Text
conName [Var]
fields =
  forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr
    Var -> Expr -> Expr
lam
    ( [Var] -> [(Expr, [Key])] -> [(Key, Expr)] -> Expr
attrs
        []
        []
        ((Key
"__tag", Text -> Expr
string Text
conName) forall a. a -> [a] -> [a]
: forall a b c. (a -> b -> c) -> [a] -> [b] -> [c]
zipWith (\Var
arg (UnsafeVar Text
name) -> (Text -> Key
UnsafeKey Text
name, Var -> Expr
var Var
arg)) [Var]
fields [Var]
constructorFieldNames)
    )
    [Var]
fields