{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE OverloadedStrings #-}
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)
import Graphics.Implicit.ExtOpenScad.Parser.Lexer (whiteSpace, matchLet, matchTok, matchColon, matchComma, surroundedBy, matchIdentifier, matchEQ, matchNE, matchLE, matchLT, matchGE, matchGT, matchCAT, matchAND, matchOR, matchEXP, matchComma)
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)
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)
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
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 ->
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 ->
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 ->
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 ->
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 ->
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 ->
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 ->
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 ->
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 ->
do
Char
op <- forall st. Char -> GenParser Char st Char
matchTok Char
'!'
Expr
right <- GenParser Char st Expr
self
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 ->
forall a. (a -> a) -> a
fix forall a b. (a -> b) -> a -> b
$ \GenParser Char st Expr
self ->
do
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
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 ->
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
]
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
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)
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
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
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
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]
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]
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]
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