---------------------------------------------------------
-- |
-- Copyright   : (c) 2023, Henning Thielemann
-- License     : BSD-style
--
-- Maintainer  : haskell@henning-thielemann.de
-- Stability   : experimental
-- Portability : portable
--
-- PDF expressions and functions
---------------------------------------------------------
module Graphics.PDF.Expression (
    PDFExpression (..),
    Function,
    Result,
    Argument,
    serialize,

    (==%), (/=%),
    (<%), (>=%), (>%), (<=%),
    min, max,
    true, false,
    (&&*), (||*), not,
    ifThenElse,

    sqrt,
    sinDeg, cosDeg, log, log10,
    pow, atan2Deg,

    floor, ceiling, round, truncate,
    ) where
     
import qualified Data.ByteString.Lazy.Char8 as CL
import qualified Data.ByteString.Char8 as C
import qualified Data.Ratio as Ratio

import qualified Control.Monad.Trans as MT
import qualified Control.Monad.RWS as MRWS
import qualified Control.Monad.Writer as MW
import qualified Control.Monad.State as MS
import Control.Monad (when)
import Control.Applicative (pure, liftA2, liftA3, (<*>))

import Prelude hiding
        (not, min, max, log, sqrt, floor, ceiling, round, truncate)


data Token = Token C.ByteString | Index Int
    deriving (Int -> Token -> ShowS
[Token] -> ShowS
Token -> String
(Int -> Token -> ShowS)
-> (Token -> String) -> ([Token] -> ShowS) -> Show Token
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> Token -> ShowS
showsPrec :: Int -> Token -> ShowS
$cshow :: Token -> String
show :: Token -> String
$cshowList :: [Token] -> ShowS
showList :: [Token] -> ShowS
Show)

type ExprMonad = MRWS.RWS () [Token] Int

newtype PDFExpression a = PDFExpression (ExprMonad ())


serialize :: (Function f) => f -> CL.ByteString
serialize :: forall f. Function f => f -> ByteString
serialize f
f =
    [ByteString] -> ByteString
CL.unwords ([ByteString] -> ByteString) -> [ByteString] -> ByteString
forall a b. (a -> b) -> a -> b
$
    (\(Int
n,Int
_,[Token]
stream) ->
        (Token -> ByteString) -> [Token] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map (\Token
token ->
                case Token
token of
                    Token ByteString
str -> ByteString -> ByteString
CL.fromStrict ByteString
str
                    Index Int
k -> String -> ByteString
CL.pack (String -> ByteString) -> String -> ByteString
forall a b. (a -> b) -> a -> b
$ Int -> String
forall a. Show a => a -> String
show (Int -> String) -> Int -> String
forall a b. (a -> b) -> a -> b
$ Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
1Int -> Int -> Int
forall a. Num a => a -> a -> a
+Int
k) [Token]
stream) ((Int, Int, [Token]) -> [ByteString])
-> (Int, Int, [Token]) -> [ByteString]
forall a b. (a -> b) -> a -> b
$
    RWS () [Token] Int Int -> () -> Int -> (Int, Int, [Token])
forall r w s a. RWS r w s a -> r -> s -> (a, s, w)
MRWS.runRWS
        (do
            Int
n <- StateT Int (RWST () [Token] Int Identity) ()
-> Int -> RWS () [Token] Int Int
forall (m :: * -> *) s a. Monad m => StateT s m a -> s -> m s
MS.execStateT (f -> StateT Int (RWST () [Token] Int Identity) ()
forall f.
Function f =>
f -> StateT Int (RWST () [Token] Int Identity) ()
serializeFunction f
f) Int
0
            [String] -> ExprMonad ()
tokens ([String] -> ExprMonad ()) -> [String] -> ExprMonad ()
forall a b. (a -> b) -> a -> b
$ Int -> String -> [String]
forall a. Int -> a -> [a]
replicate Int
n String
"pop"
            Int -> RWS () [Token] Int Int
forall a. a -> RWST () [Token] Int Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return Int
n)
        ()
        Int
0


class Function f where
    serializeFunction :: f -> MS.StateT Int ExprMonad ()

instance (Argument a, Function f) => Function (a -> f) where
    serializeFunction :: (a -> f) -> StateT Int (RWST () [Token] Int Identity) ()
serializeFunction a -> f
f = do
        a
arg <- StateT Int (RWST () [Token] Int Identity) a
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m a
argumentExpression
        f -> StateT Int (RWST () [Token] Int Identity) ()
forall f.
Function f =>
f -> StateT Int (RWST () [Token] Int Identity) ()
serializeFunction (f -> StateT Int (RWST () [Token] Int Identity) ())
-> f -> StateT Int (RWST () [Token] Int Identity) ()
forall a b. (a -> b) -> a -> b
$ a -> f
f a
arg

instance Function (PDFExpression a) where
    serializeFunction :: PDFExpression a -> StateT Int (RWST () [Token] Int Identity) ()
serializeFunction = PDFExpression a -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult

instance (Result a, Result b) => Function (a,b) where
    serializeFunction :: (a, b) -> StateT Int (RWST () [Token] Int Identity) ()
serializeFunction = (a, b) -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult

instance (Result a, Result b, Result c) => Function (a,b,c) where
    serializeFunction :: (a, b, c) -> StateT Int (RWST () [Token] Int Identity) ()
serializeFunction = (a, b, c) -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult

instance
    (Result a, Result b, Result c, Result d) =>
        Function (a,b,c,d) where
    serializeFunction :: (a, b, c, d) -> StateT Int (RWST () [Token] Int Identity) ()
serializeFunction = (a, b, c, d) -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult


{-
Extra class is needed in order
to forbid nested functions like (a -> (a, a->a))
-}
class (Function a) => Result a where
    serializeResult :: a -> MS.StateT Int ExprMonad ()

instance Result (PDFExpression a) where
    serializeResult :: PDFExpression a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult (PDFExpression ExprMonad ()
a) = do
        Int
n <- StateT Int (RWST () [Token] Int Identity) Int
forall s (m :: * -> *). MonadState s m => m s
MS.get
        ExprMonad () -> StateT Int (RWST () [Token] Int Identity) ()
forall (m :: * -> *) a. Monad m => m a -> StateT Int m a
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
MT.lift (ExprMonad () -> StateT Int (RWST () [Token] Int Identity) ())
-> ExprMonad () -> StateT Int (RWST () [Token] Int Identity) ()
forall a b. (a -> b) -> a -> b
$ do
            ExprMonad ()
a
            Bool -> ExprMonad () -> ExprMonad ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
nInt -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>Int
0) ([String] -> ExprMonad ()
tokens [Int -> String
forall a. Show a => a -> String
show (Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1), String
"1", String
"roll"])
            (Int -> Int) -> ExprMonad ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
MS.modify Int -> Int
forall a. Enum a => a -> a
pred
            Int
depth <- RWS () [Token] Int Int
forall s (m :: * -> *). MonadState s m => m s
MS.get
            Bool -> ExprMonad () -> ExprMonad ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
depthInt -> Int -> Bool
forall a. Eq a => a -> a -> Bool
/=Int
0) (ExprMonad () -> ExprMonad ()) -> ExprMonad () -> ExprMonad ()
forall a b. (a -> b) -> a -> b
$ String -> ExprMonad ()
forall a. HasCallStack => String -> a
error String
"stack must be empty after evaluation"

instance (Result a, Result b) => Result (a,b) where
    serializeResult :: (a, b) -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult (a
a,b
b) =
        a -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult a
a StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
forall a b.
StateT Int (RWST () [Token] Int Identity) a
-> StateT Int (RWST () [Token] Int Identity) b
-> StateT Int (RWST () [Token] Int Identity) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult b
b

instance (Result a, Result b, Result c) => Result (a,b,c) where
    serializeResult :: (a, b, c) -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult (a
a,b
b,c
c) =
        a -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult a
a StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
forall a b.
StateT Int (RWST () [Token] Int Identity) a
-> StateT Int (RWST () [Token] Int Identity) b
-> StateT Int (RWST () [Token] Int Identity) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult b
b StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
forall a b.
StateT Int (RWST () [Token] Int Identity) a
-> StateT Int (RWST () [Token] Int Identity) b
-> StateT Int (RWST () [Token] Int Identity) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> c -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult c
c

instance
    (Result a, Result b, Result c, Result d) =>
        Result (a,b,c,d) where
    serializeResult :: (a, b, c, d) -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult (a
a,b
b,c
c,d
d) =
        a -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult a
a StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
forall a b.
StateT Int (RWST () [Token] Int Identity) a
-> StateT Int (RWST () [Token] Int Identity) b
-> StateT Int (RWST () [Token] Int Identity) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> b -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult b
b StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
forall a b.
StateT Int (RWST () [Token] Int Identity) a
-> StateT Int (RWST () [Token] Int Identity) b
-> StateT Int (RWST () [Token] Int Identity) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>>
        c -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult c
c StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
-> StateT Int (RWST () [Token] Int Identity) ()
forall a b.
StateT Int (RWST () [Token] Int Identity) a
-> StateT Int (RWST () [Token] Int Identity) b
-> StateT Int (RWST () [Token] Int Identity) b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> d -> StateT Int (RWST () [Token] Int Identity) ()
forall a.
Result a =>
a -> StateT Int (RWST () [Token] Int Identity) ()
serializeResult d
d



class Argument a where
    argumentExpression :: (Monad m) => MS.StateT Int m a

instance Argument (PDFExpression a) where
    argumentExpression :: forall (m :: * -> *). Monad m => StateT Int m (PDFExpression a)
argumentExpression = (Int -> m (PDFExpression a, Int)) -> StateT Int m (PDFExpression a)
forall s (m :: * -> *) a. (s -> m (a, s)) -> StateT s m a
MS.StateT ((Int -> m (PDFExpression a, Int))
 -> StateT Int m (PDFExpression a))
-> (Int -> m (PDFExpression a, Int))
-> StateT Int m (PDFExpression a)
forall a b. (a -> b) -> a -> b
$ \Int
n -> (PDFExpression a, Int) -> m (PDFExpression a, Int)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int -> PDFExpression a
forall a. Int -> PDFExpression a
argument Int
n, Int
nInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1)

instance (Argument a, Argument b) => Argument (a,b) where
    argumentExpression :: forall (m :: * -> *). Monad m => StateT Int m (a, b)
argumentExpression =
        (a -> b -> (a, b))
-> StateT Int m a -> StateT Int m b -> StateT Int m (a, b)
forall a b c.
(a -> b -> c) -> StateT Int m a -> StateT Int m b -> StateT Int m c
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 (,) StateT Int m a
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m a
argumentExpression StateT Int m b
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m b
argumentExpression

instance (Argument a, Argument b, Argument c) => Argument (a,b,c) where
    argumentExpression :: forall (m :: * -> *). Monad m => StateT Int m (a, b, c)
argumentExpression =
        (a -> b -> c -> (a, b, c))
-> StateT Int m a
-> StateT Int m b
-> StateT Int m c
-> StateT Int m (a, b, c)
forall (f :: * -> *) a b c d.
Applicative f =>
(a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 (,,) StateT Int m a
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m a
argumentExpression StateT Int m b
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m b
argumentExpression StateT Int m c
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m c
argumentExpression

instance
    (Argument a, Argument b, Argument c, Argument d) =>
        Argument (a,b,c,d) where
    argumentExpression :: forall (m :: * -> *). Monad m => StateT Int m (a, b, c, d)
argumentExpression =
        (a -> b -> c -> d -> (a, b, c, d))
-> StateT Int m (a -> b -> c -> d -> (a, b, c, d))
forall a. a -> StateT Int m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (,,,)
            StateT Int m (a -> b -> c -> d -> (a, b, c, d))
-> StateT Int m a -> StateT Int m (b -> c -> d -> (a, b, c, d))
forall a b.
StateT Int m (a -> b) -> StateT Int m a -> StateT Int m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> StateT Int m a
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m a
argumentExpression
            StateT Int m (b -> c -> d -> (a, b, c, d))
-> StateT Int m b -> StateT Int m (c -> d -> (a, b, c, d))
forall a b.
StateT Int m (a -> b) -> StateT Int m a -> StateT Int m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> StateT Int m b
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m b
argumentExpression
            StateT Int m (c -> d -> (a, b, c, d))
-> StateT Int m c -> StateT Int m (d -> (a, b, c, d))
forall a b.
StateT Int m (a -> b) -> StateT Int m a -> StateT Int m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> StateT Int m c
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m c
argumentExpression
            StateT Int m (d -> (a, b, c, d))
-> StateT Int m d -> StateT Int m (a, b, c, d)
forall a b.
StateT Int m (a -> b) -> StateT Int m a -> StateT Int m b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> StateT Int m d
forall a (m :: * -> *). (Argument a, Monad m) => StateT Int m a
forall (m :: * -> *). Monad m => StateT Int m d
argumentExpression


tokens :: [String] -> ExprMonad ()
tokens :: [String] -> ExprMonad ()
tokens = [Token] -> ExprMonad ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
MW.tell ([Token] -> ExprMonad ())
-> ([String] -> [Token]) -> [String] -> ExprMonad ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> Token) -> [String] -> [Token]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString -> Token
Token (ByteString -> Token) -> (String -> ByteString) -> String -> Token
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
C.pack)


argument :: Int -> PDFExpression a
argument :: forall a. Int -> PDFExpression a
argument Int
k = ExprMonad () -> PDFExpression a
forall a. ExprMonad () -> PDFExpression a
PDFExpression (ExprMonad () -> PDFExpression a)
-> ExprMonad () -> PDFExpression a
forall a b. (a -> b) -> a -> b
$ do
    Int
depth <- RWS () [Token] Int Int
forall s (m :: * -> *). MonadState s m => m s
MS.get
    [Token] -> ExprMonad ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
MW.tell [Int -> Token
Index (Int
depthInt -> Int -> Int
forall a. Num a => a -> a -> a
-Int
k), ByteString -> Token
Token (ByteString -> Token) -> ByteString -> Token
forall a b. (a -> b) -> a -> b
$ String -> ByteString
C.pack String
"index"]
    (Int -> Int) -> ExprMonad ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
MS.modify Int -> Int
forall a. Enum a => a -> a
succ


constant :: [String] -> PDFExpression b
constant :: forall b. [String] -> PDFExpression b
constant [String]
ts =
    ExprMonad () -> PDFExpression b
forall a. ExprMonad () -> PDFExpression a
PDFExpression (ExprMonad () -> PDFExpression b)
-> ExprMonad () -> PDFExpression b
forall a b. (a -> b) -> a -> b
$ [String] -> ExprMonad ()
tokens [String]
ts ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Int -> Int) -> ExprMonad ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
MS.modify Int -> Int
forall a. Enum a => a -> a
succ

function1 :: String -> PDFExpression a -> PDFExpression b
function1 :: forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
name (PDFExpression ExprMonad ()
a) =
    ExprMonad () -> PDFExpression b
forall a. ExprMonad () -> PDFExpression a
PDFExpression (ExprMonad () -> PDFExpression b)
-> ExprMonad () -> PDFExpression b
forall a b. (a -> b) -> a -> b
$ ExprMonad ()
a ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [String] -> ExprMonad ()
tokens [String
name]

function2 :: String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 :: forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
name (PDFExpression ExprMonad ()
a) (PDFExpression ExprMonad ()
b) =
    ExprMonad () -> PDFExpression c
forall a. ExprMonad () -> PDFExpression a
PDFExpression (ExprMonad () -> PDFExpression c)
-> ExprMonad () -> PDFExpression c
forall a b. (a -> b) -> a -> b
$ ExprMonad ()
a ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ExprMonad ()
b ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [String] -> ExprMonad ()
tokens [String
name] ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Int -> Int) -> ExprMonad ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
MS.modify Int -> Int
forall a. Enum a => a -> a
pred


infix 4 ==%, /=%, <%, <=%, >%, >=%

(==%), (/=%) ::
   (Eq a) => PDFExpression a -> PDFExpression a -> PDFExpression Bool
==% :: forall a.
Eq a =>
PDFExpression a -> PDFExpression a -> PDFExpression Bool
(==%) = String -> PDFExpression a -> PDFExpression a -> PDFExpression Bool
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"eq"
/=% :: forall a.
Eq a =>
PDFExpression a -> PDFExpression a -> PDFExpression Bool
(/=%) = String -> PDFExpression a -> PDFExpression a -> PDFExpression Bool
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"ne"

(<%), (>=%), (>%), (<=%) ::
   (Ord a) => PDFExpression a -> PDFExpression a -> PDFExpression Bool
<% :: forall a.
Ord a =>
PDFExpression a -> PDFExpression a -> PDFExpression Bool
(<%)  = String -> PDFExpression a -> PDFExpression a -> PDFExpression Bool
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"lt"
>=% :: forall a.
Ord a =>
PDFExpression a -> PDFExpression a -> PDFExpression Bool
(>=%) = String -> PDFExpression a -> PDFExpression a -> PDFExpression Bool
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"ge"
>% :: forall a.
Ord a =>
PDFExpression a -> PDFExpression a -> PDFExpression Bool
(>%)  = String -> PDFExpression a -> PDFExpression a -> PDFExpression Bool
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"gt"
<=% :: forall a.
Ord a =>
PDFExpression a -> PDFExpression a -> PDFExpression Bool
(<=%) = String -> PDFExpression a -> PDFExpression a -> PDFExpression Bool
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"le"


minMax ::
    (Ord a) => String -> PDFExpression a -> PDFExpression a -> PDFExpression a
minMax :: forall a.
Ord a =>
String -> PDFExpression a -> PDFExpression a -> PDFExpression a
minMax String
cmp (PDFExpression ExprMonad ()
a) (PDFExpression ExprMonad ()
b) =
    ExprMonad () -> PDFExpression a
forall a. ExprMonad () -> PDFExpression a
PDFExpression (ExprMonad () -> PDFExpression a)
-> ExprMonad () -> PDFExpression a
forall a b. (a -> b) -> a -> b
$ do
        ExprMonad ()
a
        ExprMonad ()
b
        [String] -> ExprMonad ()
tokens [String
"2", String
"copy", String
cmp, String
"{1 pop}", String
"{exch 1 pop}", String
"ifelse"]
        (Int -> Int) -> ExprMonad ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
MS.modify Int -> Int
forall a. Enum a => a -> a
pred

min, max :: (Ord a) => PDFExpression a -> PDFExpression a -> PDFExpression a
min :: forall a.
Ord a =>
PDFExpression a -> PDFExpression a -> PDFExpression a
min = String -> PDFExpression a -> PDFExpression a -> PDFExpression a
forall a.
Ord a =>
String -> PDFExpression a -> PDFExpression a -> PDFExpression a
minMax String
"lt"
max :: forall a.
Ord a =>
PDFExpression a -> PDFExpression a -> PDFExpression a
max = String -> PDFExpression a -> PDFExpression a -> PDFExpression a
forall a.
Ord a =>
String -> PDFExpression a -> PDFExpression a -> PDFExpression a
minMax String
"gt"


true, false :: PDFExpression Bool
true :: PDFExpression Bool
true  = [String] -> PDFExpression Bool
forall b. [String] -> PDFExpression b
constant [String
"true"]
false :: PDFExpression Bool
false = [String] -> PDFExpression Bool
forall b. [String] -> PDFExpression b
constant [String
"false"]

infixr 3 &&*
(&&*) :: PDFExpression Bool -> PDFExpression Bool -> PDFExpression Bool
&&* :: PDFExpression Bool -> PDFExpression Bool -> PDFExpression Bool
(&&*) = String
-> PDFExpression Bool -> PDFExpression Bool -> PDFExpression Bool
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"and"

infixr 2 ||*
(||*) :: PDFExpression Bool -> PDFExpression Bool -> PDFExpression Bool
||* :: PDFExpression Bool -> PDFExpression Bool -> PDFExpression Bool
(||*) = String
-> PDFExpression Bool -> PDFExpression Bool -> PDFExpression Bool
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"or"

not :: PDFExpression Bool -> PDFExpression Bool
not :: PDFExpression Bool -> PDFExpression Bool
not = String -> PDFExpression Bool -> PDFExpression Bool
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"not"



ifThenElse ::
    (Ord a) =>
    PDFExpression Bool -> PDFExpression a -> PDFExpression a -> PDFExpression a
ifThenElse :: forall a.
Ord a =>
PDFExpression Bool
-> PDFExpression a -> PDFExpression a -> PDFExpression a
ifThenElse (PDFExpression ExprMonad ()
cond) (PDFExpression ExprMonad ()
a) (PDFExpression ExprMonad ()
b) =
    ExprMonad () -> PDFExpression a
forall a. ExprMonad () -> PDFExpression a
PDFExpression (ExprMonad () -> PDFExpression a)
-> ExprMonad () -> PDFExpression a
forall a b. (a -> b) -> a -> b
$ do
        ExprMonad ()
cond
        [String] -> ExprMonad ()
tokens [String
"{"] ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ExprMonad ()
a ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [String] -> ExprMonad ()
tokens [String
"}"]
        [String] -> ExprMonad ()
tokens [String
"{"] ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ExprMonad ()
b ExprMonad () -> ExprMonad () -> ExprMonad ()
forall a b.
RWST () [Token] Int Identity a
-> RWST () [Token] Int Identity b -> RWST () [Token] Int Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> [String] -> ExprMonad ()
tokens [String
"}"]
        [String] -> ExprMonad ()
tokens [String
"ifelse"]
        (Int -> Int) -> ExprMonad ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
MS.modify Int -> Int
forall a. Enum a => a -> a
pred
        (Int -> Int) -> ExprMonad ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
MS.modify Int -> Int
forall a. Enum a => a -> a
pred




instance (Num a) => Num (PDFExpression a) where
    fromInteger :: Integer -> PDFExpression a
fromInteger Integer
k = [String] -> PDFExpression a
forall b. [String] -> PDFExpression b
constant [Integer -> String
forall a. Show a => a -> String
show Integer
k]
    negate :: PDFExpression a -> PDFExpression a
negate = String -> PDFExpression a -> PDFExpression a
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"negate"
    abs :: PDFExpression a -> PDFExpression a
abs = String -> PDFExpression a -> PDFExpression a
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"abs"
    + :: PDFExpression a -> PDFExpression a -> PDFExpression a
(+) = String -> PDFExpression a -> PDFExpression a -> PDFExpression a
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"add"
    (-) = String -> PDFExpression a -> PDFExpression a -> PDFExpression a
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"sub"
    * :: PDFExpression a -> PDFExpression a -> PDFExpression a
(*) = String -> PDFExpression a -> PDFExpression a -> PDFExpression a
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"mul"
    signum :: PDFExpression a -> PDFExpression a
signum (PDFExpression ExprMonad ()
a) =
        ExprMonad () -> PDFExpression a
forall a. ExprMonad () -> PDFExpression a
PDFExpression (ExprMonad () -> PDFExpression a)
-> ExprMonad () -> PDFExpression a
forall a b. (a -> b) -> a -> b
$ do
            ExprMonad ()
a
            [String] -> ExprMonad ()
tokens [String
"dup", String
"0", String
"gt"]
            [String] -> ExprMonad ()
tokens   [String
"{", String
"pop", String
"1", String
"}"]
            [String] -> ExprMonad ()
tokens   [String
"{", String
"0", String
"lt", String
"{-1}", String
"{0}", String
"ifelse", String
"}"]
            [String] -> ExprMonad ()
tokens [String
"ifelse"]

instance (Fractional a) => Fractional (PDFExpression a) where
    fromRational :: Rational -> PDFExpression a
fromRational Rational
r =
        [String] -> PDFExpression a
forall b. [String] -> PDFExpression b
constant [Integer -> String
forall a. Show a => a -> String
show (Rational -> Integer
forall a. Ratio a -> a
Ratio.numerator Rational
r), Integer -> String
forall a. Show a => a -> String
show (Rational -> Integer
forall a. Ratio a -> a
Ratio.denominator Rational
r), String
"div"]
    / :: PDFExpression a -> PDFExpression a -> PDFExpression a
(/) = String -> PDFExpression a -> PDFExpression a -> PDFExpression a
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"div"


sqrt, sinDeg, cosDeg, log, log10 ::
    (Floating a) => PDFExpression a -> PDFExpression a
sqrt :: forall a. Floating a => PDFExpression a -> PDFExpression a
sqrt = String -> PDFExpression a -> PDFExpression a
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"sqrt"
sinDeg :: forall a. Floating a => PDFExpression a -> PDFExpression a
sinDeg = String -> PDFExpression a -> PDFExpression a
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"sin"
cosDeg :: forall a. Floating a => PDFExpression a -> PDFExpression a
cosDeg = String -> PDFExpression a -> PDFExpression a
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"cos"
log :: forall a. Floating a => PDFExpression a -> PDFExpression a
log = String -> PDFExpression a -> PDFExpression a
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"ln"
log10 :: forall a. Floating a => PDFExpression a -> PDFExpression a
log10 = String -> PDFExpression a -> PDFExpression a
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"log"

pow, atan2Deg ::
    (Floating a) => PDFExpression a -> PDFExpression a -> PDFExpression a
pow :: forall a.
Floating a =>
PDFExpression a -> PDFExpression a -> PDFExpression a
pow = String -> PDFExpression a -> PDFExpression a -> PDFExpression a
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"exp"
atan2Deg :: forall a.
Floating a =>
PDFExpression a -> PDFExpression a -> PDFExpression a
atan2Deg = String -> PDFExpression a -> PDFExpression a -> PDFExpression a
forall a b c.
String -> PDFExpression a -> PDFExpression b -> PDFExpression c
function2 String
"atan"



floor, ceiling, round, truncate ::
    (RealFrac a) => PDFExpression a -> PDFExpression Int
floor :: forall a. RealFrac a => PDFExpression a -> PDFExpression Int
floor    = String -> PDFExpression a -> PDFExpression Int
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"floor"
ceiling :: forall a. RealFrac a => PDFExpression a -> PDFExpression Int
ceiling  = String -> PDFExpression a -> PDFExpression Int
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"ceiling"
round :: forall a. RealFrac a => PDFExpression a -> PDFExpression Int
round    = String -> PDFExpression a -> PDFExpression Int
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"round"
truncate :: forall a. RealFrac a => PDFExpression a -> PDFExpression Int
truncate = String -> PDFExpression a -> PDFExpression Int
forall a b. String -> PDFExpression a -> PDFExpression b
function1 String
"truncate"