{- ORMOLU_DISABLE -}
-- Implicit CAD. Copyright (C) 2011, Christopher Olah (chris@colah.ca)
-- Copyright (C) 2014-2019 , Julia Longtin (julial@turinglace.com)
-- Copyright (C) 2016, Kelvin Cookshaw (kelvin@cookshaw.com)
-- Released under the GNU AGPLV3+, see LICENSE

-- Allow us to use shorter forms of Var and Name.
{-# LANGUAGE PatternSynonyms #-}

-- Allow us to use string literals for Text
{-# LANGUAGE OverloadedStrings #-}

-- A parser for a numeric expressions.
module Graphics.Implicit.ExtOpenScad.Parser.Expr(expr0) where

import Prelude (Char, Maybe(Nothing, Just), ($), (<>), id, foldl, foldr, (==), length, head, (&&), (<$>), (<*>), (*>), (<*), flip, (.), pure)

import Graphics.Implicit.ExtOpenScad.Definitions (Expr(LamE, LitE, ListE, (:$)), OVal(ONum, OUndefined), Symbol(Symbol))

import qualified Graphics.Implicit.ExtOpenScad.Definitions as GIED (Expr(Var), Pattern(Name))

import Graphics.Implicit.ExtOpenScad.Parser.Util ((?:), (*<|>), number, boolean, scadString, scadUndefined, variable)

-- The lexer.
import Graphics.Implicit.ExtOpenScad.Parser.Lexer (whiteSpace, matchLet, matchTok, matchColon, matchComma, surroundedBy, matchIdentifier, matchEQ, matchNE, matchLE, matchLT, matchGE, matchGT, matchCAT, matchAND, matchOR, matchEXP, matchComma)

-- The parsec parsing library.
import Text.Parsec (oneOf, many, sepBy, optionMaybe, option, (<|>), chainl1, chainr1)

import Text.Parsec.String (GenParser)

import Data.Text.Lazy (Text, pack, singleton)

import Control.Monad.Fix (fix)

-- Let us use the old syntax when defining Vars and Names.
pattern Var :: Text -> Expr
pattern $bVar :: Text -> Expr
$mVar :: forall {r}. Expr -> (Text -> r) -> ((# #) -> r) -> r
Var  s = GIED.Var  (Symbol s)
pattern Name :: Text -> GIED.Pattern
pattern $bName :: Text -> Pattern
$mName :: forall {r}. Pattern -> (Text -> r) -> ((# #) -> r) -> r
Name n = GIED.Name (Symbol n)

-- Borrowed the pattern from http://compgroups.net/comp.lang.functional/parsing-ternary-operator-with-parsec/1052460
-- In the levels list, the first element is the lowest precedent, and the last is the highest.
-- "higher" represents the higher precedence parser, ie. the next one in the levels list.
-- "fix $ \self ->..." is used to consume all expressions in the same level, "self" being the current level.
expr0 :: GenParser Char st Expr
expr0 :: forall st. GenParser Char st Expr
expr0 = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr forall a b. (a -> b) -> a -> b
($) forall st. GenParser Char st Expr
nonAssociativeExpr forall st. [GenParser Char st Expr -> GenParser Char st Expr]
levels
  where
    levels :: [GenParser Char st Expr -> GenParser Char st Expr]
    levels :: forall st. [GenParser Char st Expr -> GenParser Char st Expr]
levels =
      [ forall a. a -> a
id
      , \GenParser Char st Expr
higher -> forall a. (a -> a) -> a
fix forall a b. (a -> b) -> a -> b
$ \GenParser Char st Expr
self -> do -- ?: ternary operator.
          Expr
condition <- GenParser Char st Expr
higher
          do
            Expr
trueExpr  <- forall st. Char -> GenParser Char st Char
matchTok Char
'?' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> GenParser Char st Expr
self
            Expr
falseExpr <- forall st. GenParser Char st Text
matchColon   forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> GenParser Char st Expr
self
            forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Text -> Expr
Var Text
"?" Expr -> [Expr] -> Expr
:$ [Expr
condition, Expr
trueExpr, Expr
falseExpr]
           forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
            forall (f :: * -> *) a. Applicative f => a -> f a
pure Expr
condition
      , \GenParser Char st Expr
higher -> -- boolean OR operator (||)
          forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a
chainl1 GenParser Char st Expr
higher forall a b. (a -> b) -> a -> b
$ Text -> Expr -> Expr -> Expr
binaryOperation forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall st. GenParser Char st Text
matchOR
      , \GenParser Char st Expr
higher -> -- boolean AND operator (&&)
          forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a
chainl1 GenParser Char st Expr
higher forall a b. (a -> b) -> a -> b
$ Text -> Expr -> Expr -> Expr
binaryOperation forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall st. GenParser Char st Text
matchAND
      , \GenParser Char st Expr
higher -> -- == and != operators
          forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a
chainl1 GenParser Char st Expr
higher forall a b. (a -> b) -> a -> b
$ Text -> Expr -> Expr -> Expr
binaryOperation forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall st. GenParser Char st Text
matchEQ forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Text
matchNE)
      , \GenParser Char st Expr
higher -> -- <, <=, >= and > operators
          forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a
chainl1 GenParser Char st Expr
higher forall a b. (a -> b) -> a -> b
$ Text -> Expr -> Expr -> Expr
binaryOperation forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall st. GenParser Char st Text
matchLE forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Text
matchLT forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Text
matchGE forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Text
matchGT)
      , \GenParser Char st Expr
higher -> -- + and - operators
          forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a
chainl1 GenParser Char st Expr
higher forall a b. (a -> b) -> a -> b
$ Text -> Expr -> Expr -> Expr
binaryOperation forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Text
singleton forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m Char
oneOf [Char]
"+-" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall st. GenParser Char st ()
whiteSpace
      , \GenParser Char st Expr
higher -> -- string/list concatenation operator (++). This is not available in OpenSCAD.
          forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a
chainl1 GenParser Char st Expr
higher forall a b. (a -> b) -> a -> b
$ Text -> Expr -> Expr -> Expr
binaryOperation forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall st. GenParser Char st Text
matchCAT
      , \GenParser Char st Expr
higher -> -- multiplication (*), division (/), and modulus (%) operators
          forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a
chainl1 GenParser Char st Expr
higher forall a b. (a -> b) -> a -> b
$ Text -> Expr -> Expr -> Expr
binaryOperation forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Text
singleton forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m Char
oneOf [Char]
"*/%" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall st. GenParser Char st ()
whiteSpace
      , \GenParser Char st Expr
higher -> -- exponent operator (^). This is not available in OpenSCAD.
          forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (a -> a -> a) -> ParsecT s u m a
chainr1 GenParser Char st Expr
higher forall a b. (a -> b) -> a -> b
$ Text -> Expr -> Expr -> Expr
binaryOperation forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Text
singleton forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall st. GenParser Char st Char
matchEXP
      , \GenParser Char st Expr
higher ->
          forall a. (a -> a) -> a
fix forall a b. (a -> b) -> a -> b
$ \GenParser Char st Expr
self -> -- unary ! operator. OpenSCAD's YACC parser puts '!' at the same level of precedence as '-' and '+'.
                  do
                    Char
op <- forall st. Char -> GenParser Char st Char
matchTok Char
'!'
                    Expr
right <- GenParser Char st Expr
self
                    -- when noting a not, just skip both of them.
                    forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ case Expr
right of
                      Var Text
"!" :$ [Expr
deepright] -> Expr
deepright
                      Expr
_                      -> Text -> Expr
Var (Char -> Text
singleton Char
op) Expr -> [Expr] -> Expr
:$ [Expr
right]
        forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
          GenParser Char st Expr
higher
      , \GenParser Char st Expr
higher -> -- leading positive or negative sign.
          forall a. (a -> a) -> a
fix forall a b. (a -> b) -> a -> b
$ \GenParser Char st Expr
self ->
              do -- Unary -. applied to strings is undefined, but handle that in the interpreter.
                Expr
right <- forall st. Char -> GenParser Char st Char
matchTok Char
'-' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> GenParser Char st Expr
self
                forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Text -> Expr
Var Text
"negate" Expr -> [Expr] -> Expr
:$ [Expr
right]
          forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> do -- Unary +. Handle this by ignoring the +.
                forall st. Char -> GenParser Char st Char
matchTok Char
'+' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> GenParser Char st Expr
self
        forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
          GenParser Char st Expr
higher
      , \GenParser Char st Expr
higher -> -- "let" expression
          forall a b c. (a -> b -> c) -> b -> a -> c
flip (forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Expr -> Expr -> Expr
bindLets) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (forall st. GenParser Char st ()
matchLet forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall st a.
Char -> GenParser Char st a -> Char -> GenParser Char st a
surroundedBy Char
'(' (forall st. GenParser Char st Expr
assignment forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepBy` forall st. GenParser Char st Text
matchComma) Char
')') forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall st. GenParser Char st Expr
expr0
        forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
          GenParser Char st Expr
higher
      ]

-- | parse expressions that don't associate, either because they are not operators or because they are operators
--   that contain the expressions they operate on in start and end tokens, like parentheses, and no other operator can associate with their expressions.
nonAssociativeExpr :: GenParser Char st Expr
nonAssociativeExpr :: forall st. GenParser Char st Expr
nonAssociativeExpr =
       forall st. GenParser Char st Expr
number
   forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Expr
vectorListParentheses
   forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Expr
variableish
   forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Expr
scadString
   forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Expr
boolean
   forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> forall st. GenParser Char st Expr
scadUndefined

-- | parse operations that start with a variable name,
-- including variable reference, function calling, variable list indexing, and variable list splicing.
variableish :: GenParser Char st Expr
variableish :: forall st. GenParser Char st Expr
variableish = [Char]
"variable" forall s u (m :: * -> *) a.
[Char] -> ParsecT s u m a -> ParsecT s u m a
?:
    do
        Expr
obj <- forall st. GenParser Char st Expr
variable
        [Expr -> Expr]
args <- forall s (m :: * -> *) t a u.
Stream s m t =>
a -> ParsecT s u m a -> ParsecT s u m a
option [] (
          [Char]
"function application" forall s u (m :: * -> *) a.
[Char] -> ParsecT s u m a -> ParsecT s u m a
?: do
              [Expr]
args <- forall st a.
Char -> GenParser Char st a -> Char -> GenParser Char st a
surroundedBy Char
'(' (forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy forall st. GenParser Char st Expr
expr0 forall st. GenParser Char st Text
matchComma) Char
')'
              forall (f :: * -> *) a. Applicative f => a -> f a
pure [(Expr -> [Expr] -> Expr
:$ [Expr]
args)]
          )
        [Expr -> Expr]
mods <- forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (
               [Char]
"list indexing" forall s u (m :: * -> *) a.
[Char] -> ParsecT s u m a -> ParsecT s u m a
?: do
                   Expr
i <- forall st a.
Char -> GenParser Char st a -> Char -> GenParser Char st a
surroundedBy Char
'[' forall st. GenParser Char st Expr
expr0 Char
']'
                   forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ \Expr
l -> Text -> Expr
Var Text
"index" Expr -> [Expr] -> Expr
:$ [Expr
l, Expr
i]
          forall tok u a.
GenParser tok u a -> GenParser tok u a -> GenParser tok u a
*<|> [Char]
"list splicing" forall s u (m :: * -> *) a.
[Char] -> ParsecT s u m a -> ParsecT s u m a
?: do
                   Maybe Expr
start <- forall st. Char -> GenParser Char st Char
matchTok Char
'[' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
optionMaybe forall st. GenParser Char st Expr
expr0
                   Maybe Expr
end   <- forall st. GenParser Char st Text
matchColon forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
optionMaybe forall st. GenParser Char st Expr
expr0 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall st. Char -> GenParser Char st Char
matchTok Char
']'
                   forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ case (Maybe Expr
start, Maybe Expr
end) of
                              (Maybe Expr
Nothing, Maybe Expr
Nothing) -> forall a. a -> a
id
                              (Just Expr
s,  Maybe Expr
Nothing)  -> \Expr
l -> Text -> Expr
Var Text
"splice" Expr -> [Expr] -> Expr
:$ [Expr
l, Expr
s, OVal -> Expr
LitE OVal
OUndefined]
                              (Maybe Expr
Nothing, Just Expr
e )  -> \Expr
l -> Text -> Expr
Var Text
"splice" Expr -> [Expr] -> Expr
:$ [Expr
l, OVal -> Expr
LitE forall a b. (a -> b) -> a -> b
$ ℝ -> OVal
ONum 0, Expr
e]
                              (Just Expr
s,  Just Expr
e )  -> \Expr
l -> Text -> Expr
Var Text
"splice" Expr -> [Expr] -> Expr
:$ [Expr
l, Expr
s, Expr
e]
                 )
        forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl (\Expr
a Expr -> Expr
b -> Expr -> Expr
b Expr
a) Expr
obj ([Expr -> Expr]
args forall a. Semigroup a => a -> a -> a
<> [Expr -> Expr]
mods)

-- | Parse parentheses, lists, vectors, and vector/list generators.
vectorListParentheses :: GenParser Char st Expr
vectorListParentheses :: forall st. GenParser Char st Expr
vectorListParentheses =
         [Char]
"vector/list/parentheses" forall s u (m :: * -> *) a.
[Char] -> ParsecT s u m a -> ParsecT s u m a
?: do
            -- eg. [ 3, a, a+1, b, a*b] - list
            --     ( 1, 2, 3) - list
            --     (a+1) - parenthesized expression.
            Char
o <- forall s (m :: * -> *) u.
Stream s m Char =>
[Char] -> ParsecT s u m Char
oneOf [Char]
"[(" forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall st. GenParser Char st ()
whiteSpace
            [Expr]
exprs <- forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
sepBy forall st. GenParser Char st Expr
expr0 forall st. GenParser Char st Text
matchComma
              forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* if Char
o forall a. Eq a => a -> a -> Bool
== Char
'['
                 then forall st. Char -> GenParser Char st Char
matchTok Char
']'
                 else forall st. Char -> GenParser Char st Char
matchTok Char
')'
            forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ if Char
o forall a. Eq a => a -> a -> Bool
== Char
'(' Bool -> Bool -> Bool
&& forall (t :: * -> *) a. Foldable t => t a -> Int
length [Expr]
exprs forall a. Eq a => a -> a -> Bool
== Int
1
                     then forall a. [a] -> a
head [Expr]
exprs
                     else [Expr] -> Expr
ListE [Expr]
exprs
    forall tok u a.
GenParser tok u a -> GenParser tok u a -> GenParser tok u a
*<|> [Char]
"vector/list generator" forall s u (m :: * -> *) a.
[Char] -> ParsecT s u m a -> ParsecT s u m a
?: do
        -- eg.  [ a : 1 : a + 10 ]
        --      [ a : a + 10 ]
        -- FIXME: clearly, these have a numeric context, and should fail to parse for non-numeric contents.
        Expr
expr1 <- forall st. Char -> GenParser Char st Char
matchTok Char
'[' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall st. GenParser Char st Expr
expr0 forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall st. GenParser Char st Text
matchColon
        [Expr]
exprs <- do
                   Expr
expr2 <- forall st. GenParser Char st Expr
expr0
                   Maybe Expr
expr3 <- forall s (m :: * -> *) t u a.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m (Maybe a)
optionMaybe (forall st. GenParser Char st Text
matchColon forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall st. GenParser Char st Expr
expr0)
                   forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ case Maybe Expr
expr3 of
                      Just Expr
n  -> [Expr
expr1, Expr
expr2, Expr
n]
                      Maybe Expr
Nothing -> [Expr
expr1, OVal -> Expr
LitE forall a b. (a -> b) -> a -> b
$ ℝ -> OVal
ONum 1.0, Expr
expr2]
          forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall st. Char -> GenParser Char st Char
matchTok Char
']'
        forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Text -> [Expr] -> Expr
collector Text
"list_gen" [Expr]
exprs

-- | Apply a symbolic operator to a list of expressions, pureing one big expression.
--   Accepts a string for the operator, to simplify callers.
collector :: Text -> [Expr] -> Expr
collector :: Text -> [Expr] -> Expr
collector Text
_ [Expr
x] = Expr
x
collector Text
s  [Expr]
l  = Text -> Expr
Var Text
s Expr -> [Expr] -> Expr
:$ [[Expr] -> Expr
ListE [Expr]
l]

-- | Apply a symbolic operator to two expressions, combining left and right operands with an binary operator
binaryOperation :: Text -> Expr -> Expr -> Expr
binaryOperation :: Text -> Expr -> Expr -> Expr
binaryOperation Text
symbol Expr
left Expr
right = Text -> Expr
Var Text
symbol Expr -> [Expr] -> Expr
:$ [Expr
left, Expr
right]

-- | An assignment expression within a let's bindings list
assignment :: GenParser Char st Expr
assignment :: forall st. GenParser Char st Expr
assignment = do
    [Char]
ident       <- forall st. GenParser Char st [Char]
matchIdentifier
    Expr
expression  <- forall st. Char -> GenParser Char st Char
matchTok Char
'=' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall st. GenParser Char st Expr
expr0
    forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ [Expr] -> Expr
ListE [Text -> Expr
Var ([Char] -> Text
pack [Char]
ident), Expr
expression]

-- | build nested let statements when foldr'd.
bindLets :: Expr -> Expr -> Expr
bindLets :: Expr -> Expr -> Expr
bindLets (ListE [Var Text
boundName, Expr
boundExpr]) Expr
nestedExpr = [Pattern] -> Expr -> Expr
LamE [Text -> Pattern
Name Text
boundName] Expr
nestedExpr Expr -> [Expr] -> Expr
:$ [Expr
boundExpr]
bindLets Expr
_ Expr
e = Expr
e