Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
M  src/Nix/Builtins.hs
M  src/Nix/Expr/Shorthands.hs
M  src/Nix/Utils.hs
M  tests/ParserTests.hs
M  tests/PrettyParseTests.hs
M  tests/ReduceExprTests.hs
  • Loading branch information
Anton-Latukha committed Jul 10, 2021
1 parent 66590da commit adc62c9
Show file tree
Hide file tree
Showing 6 changed files with 420 additions and 250 deletions.
2 changes: 1 addition & 1 deletion src/Nix/Builtins.hs
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ headNix :: forall e t f m. MonadNix e t f m => NValue t f m -> m (NValue t f m)
headNix =
maybe
(throwError $ ErrorCall "builtins.head: empty list")
(pure)
pure
. viaNonEmpty head <=< fromValue @[NValue t f m]

tailNix :: forall e t f m. MonadNix e t f m => NValue t f m -> m (NValue t f m)
Expand Down
178 changes: 120 additions & 58 deletions src/Nix/Expr/Shorthands.hs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module Nix.Expr.Shorthands where
import Data.Fix
import Nix.Atoms
import Nix.Expr.Types
import Nix.Utils

-- * Basic expression builders

Expand All @@ -33,15 +34,17 @@ mkFloat = Fix . mkFloatF

-- | Put a regular (double-quoted) string.
mkStr :: Text -> NExpr
mkStr = Fix . NStr . DoubleQuoted . \case
"" -> mempty
x -> [Plain x]
mkStr = Fix . NStr . DoubleQuoted .
whenText
mempty
(one . Plain)

-- | Put an indented string.
mkIndentedStr :: Int -> Text -> NExpr
mkIndentedStr w = Fix . NStr . Indented w . \case
"" -> mempty
x -> [Plain x]
mkIndentedStr w = Fix . NStr . Indented w .
whenText
mempty
(one . Plain)

-- | Put a path. Use @True@ if the path should be read from the environment, else use @False@.
mkPath :: Bool -> FilePath -> NExpr
Expand Down Expand Up @@ -79,6 +82,7 @@ mkNot = mkOp NNot
-- Language allows negate integers & floats.
mkNeg :: NExpr -> NExpr
mkNeg = mkOp NNeg
infix 8 `mkNeg`

-- | Put a binary operator.
mkOp2 :: NBinaryOp -> NExpr -> NExpr -> NExpr
Expand All @@ -93,20 +97,34 @@ mkParamset params variadic = ParamSet params variadic mempty
mkRecSet :: [Binding NExpr] -> NExpr
mkRecSet = mkSet Recursive

($#~#) = mkRecSet

-- | Put a non-recursive set.
--
-- > { .. }
mkNonRecSet :: [Binding NExpr] -> NExpr
mkNonRecSet = mkSet NonRecursive

($###) = mkNonRecSet


-- | General set builder function.
mkSet :: Recursivity -> [Binding NExpr] -> NExpr
mkSet r = Fix . NSet r

-- | Empty set.
--
-- Monoid. Use @//@ operation (shorthand $//) to extend the set.
emptySet :: NExpr
emptySet = mkNonRecSet mempty

-- | Put a list.
mkList :: [NExpr] -> NExpr
mkList = Fix . NList

emptyList :: NExpr
emptyList = mkList mempty

-- | Wrap in a @let@.
--
-- (Evaluate the second argument after introducing the bindings.)
Expand Down Expand Up @@ -162,26 +180,9 @@ mkIf e1 e2 = Fix . NIf e1 e2
mkFunction :: Params NExpr -> NExpr -> NExpr
mkFunction params = Fix . NAbs params

-- | Lambda function, analog of Haskell's @\\ x -> x@:
--
-- +---------------+-----------+
-- | Haskell | Nix |
-- +===============+===========+
-- | @x ==> expr @ | @x: expr@ |
-- +---------------+-----------+
(==>) :: Params NExpr -> NExpr -> NExpr
(==>) = mkFunction
infixr 1 ==>

-- | Dot-reference into an attribute set: @attrSet.k@
(@.) :: NExpr -> Text -> NExpr
(@.) obj name = getRefOrDefault obj name Nothing
infixl 2 @.


-- | General dot-reference with optional alternative if the jey does not exist.
getRefOrDefault :: NExpr -> VarName -> Maybe NExpr -> NExpr
getRefOrDefault obj name alt = Fix $ NSelect obj (StaticKey name :| mempty) alt
getRefOrDefault obj name alt = Fix $ NSelect obj (mkSelector name) alt

-- ** Base functor builders for basic expressions builders *sic

Expand Down Expand Up @@ -293,55 +294,116 @@ recAttrsE pairs = mkRecSet $ uncurry ($=) <$> pairs

-- * Nix binary operators

-- | Nix binary operator builder.
mkBinop :: NBinaryOp -> NExpr -> NExpr -> NExpr
mkBinop = mkOp2

(@@), ($==), ($!=), ($<), ($<=), ($>), ($>=), ($&&), ($||), ($->), ($//), ($+), ($-), ($*), ($/), ($++)
:: NExpr -> NExpr -> NExpr
-- 2021-07-10: NOTE: Probably the presedence of some operators is still needs to be tweaked.

-- | Dot-reference into an attribute set: @attrSet.k@
(@.) :: NExpr -> Text -> NExpr
(@.) obj name = getRefOrDefault obj name Nothing
infix 9 @.

-- | Dot-reference into an attribute set with alternative if the key does not exist.
--
-- > s.x or y
(@./) :: NExpr -> VarName -> NExpr -> NExpr
(@./) obj name alt = getRefOrDefault obj name $ pure alt
infix 9 @./

-- | Function application (@' '@ in @f x@)
(@@) = mkOp2 NApp
infixl 1 @@
-- | Equality: @==@
($==) = mkOp2 NEq
-- | Inequality: @!=@
($!=) = mkOp2 NNEq
-- | Less than: @<@
($<) = mkOp2 NLt
-- | Less than OR equal: @<=@
($<=) = mkOp2 NLte
infixl 8 @@

-- | List concatenation: @++@
($++) = mkOp2 NConcat
infixr 7 $++

-- | Multiplication: @*@
($*) = mkOp2 NMult
infixl 6 $*

-- | Division: @/@
($/) = mkOp2 NDiv
infixl 6 $/

-- | Addition: @+@
($+) = mkOp2 NPlus
infixl 5 $+

-- | Subtraction: @-@
($-) = mkOp2 NMinus
infixl 5 $-

-- | Logical negation: @!e@
($!) :: NExpr -> NExpr
($!) = mkNot
infix 5 $!

-- | Extend/override the left attr set, with the right one: @//@
($//) = mkOp2 NUpdate
infixr 5 $//

-- | Greater than: @>@
($>) = mkOp2 NGt
infix 4 $>

-- | Greater than OR equal: @>=@
infix 4 $>=
($>=) = mkOp2 NGte

-- | Less than OR equal: @<=@
($<=) = mkOp2 NLte
infix 4 $<=

-- | Less than: @<@
($<) = mkOp2 NLt
infix 4 $<

-- | Equality: @==@
($==) = mkOp2 NEq
infix 3 $==

-- | Inequality: @!=@
($!=) = mkOp2 NNEq
infix 3 $!=

-- | AND: @&&@
($&&) = mkOp2 NAnd
infixl 2 $&&

-- | OR: @||@
($||) = mkOp2 NOr
infixl 2 $||

-- | Logical implication: @->@
($->) = mkOp2 NImpl
-- | Extend/override the left attr set, with the right one: @//@
($//) = mkOp2 NUpdate
-- | Addition: @+@
($+) = mkOp2 NPlus
-- | Subtraction: @-@
($-) = mkOp2 NMinus
-- | Multiplication: @*@
($*) = mkOp2 NMult
-- | Division: @/@
($/) = mkOp2 NDiv
-- | List concatenation: @++@
($++) = mkOp2 NConcat
infix 1 $->

-- | Lambda function, analog of Haskell's @\\ x -> x@:
--
-- +---------------+-----------+
-- | Haskell | Nix |
-- +===============+===========+
-- | @x ==> expr @ | @x: expr@ |
-- +---------------+-----------+
(==>) :: Params NExpr -> NExpr -> NExpr
(==>) = mkFunction
infixr 1 ==>

-- * Under deprecation

-- NOTE: Remove after 2023-07
-- | Put an unary operator.
mkOper :: NUnaryOp -> NExpr -> NExpr
mkOper op = Fix . NUnary op
-- -- * Under deprecation

-- NOTE: Remove after 2023-07
-- | Put a binary operator.
mkOper2 :: NBinaryOp -> NExpr -> NExpr -> NExpr
mkOper2 op a = Fix . NBinary op a
-- -- NOTE: Remove after 2023-07
-- -- | Put an unary operator.
-- mkOper :: NUnaryOp -> NExpr -> NExpr
-- mkOper op = Fix . NUnary op

-- -- NOTE: Remove after 2023-07
-- -- | Put a binary operator.
-- mkOper2 :: NBinaryOp -> NExpr -> NExpr -> NExpr
-- mkOper2 op a = Fix . NBinary op a

-- -- NOTE: Remove after 2023-07
-- | Nix binary operator builder.
-- mkBinop :: NBinaryOp -> NExpr -> NExpr -> NExpr
-- mkBinop = mkOp2
8 changes: 8 additions & 0 deletions src/Nix/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,14 @@ list e f l =
(null l)
{-# inline list #-}

whenText
:: a -> (Text -> a) -> Text -> a
whenText e f t =
bool
(f t)
e
(Text.null t)

-- | Lambda analog of @maybe@ or @either@ for Free monad.
free :: (a -> b) -> (f (Free f a) -> b) -> Free f a -> b
free fP fF fr =
Expand Down
Loading

0 comments on commit adc62c9

Please sign in to comment.