{-# LANGUAGE GADTs #-}

-- | Defines functions for printing expressions.
module Language.Drasil.Printing.Import.Expr (expr) where

import Language.Drasil hiding (neg, sec, symbol, isIn, Matrix, Set)
import qualified Language.Drasil.Display as S (Symbol(..))
import Language.Drasil.Expr.Development (ArithBinOp(..), AssocArithOper(..),
  AssocBoolOper(..), BoolBinOp(..), EqBinOp(..), Expr(..),
  LABinOp(..), OrdBinOp(..), UFunc(..), UFuncB(..), UFuncVN(..), UFuncVV(..),
  VVNBinOp(..), VVVBinOp(..), NVVBinOp(..), ESSBinOp(..), ESBBinOp(..), AssocConcatOper(..), eprec, precA, precB, precC)
import Language.Drasil.Literal.Development (Literal(..))

import qualified Language.Drasil.Printing.AST as P
import Language.Drasil.Printing.PrintingInformation (PrintingInformation, ckdb, stg)

import Control.Lens ((^.))
import Data.List (intersperse)

import Language.Drasil.Printing.Import.Literal (literal)
import Language.Drasil.Printing.Import.Symbol (symbol)
import Language.Drasil.Printing.Import.Helpers (lookupC, parens)


-- | Helper that creates an expression row given printing information, an operator, and an expression.
mkCall :: PrintingInformation -> P.Ops -> Expr -> P.Expr
mkCall :: PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
s Ops
o Expr
e = [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
o, Expr -> Expr
parens (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
e PrintingInformation
s]

-- | Helper that creates a binary expression row given printing information, an operator, and two expressions.
mkBOp :: PrintingInformation -> P.Ops -> Expr -> Expr -> P.Expr
mkBOp :: PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
o Expr
a Expr
b = [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
sm, Ops -> Expr
P.MO Ops
o, Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
sm]

-- | Helper that adds parenthesis to an expression where appropriate.
expr' :: PrintingInformation -> Int -> Expr -> P.Expr
expr' :: PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
s Int
p Expr
e = Expr -> Expr
fence (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
e PrintingInformation
s
  where fence :: Expr -> Expr
fence = if Expr -> Int
eprec Expr
e Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
p then Expr -> Expr
parens else Expr -> Expr
forall a. a -> a
id

-- | Helper for properly rendering negation of expressions.
neg' :: Expr -> Bool
neg' :: Expr -> Bool
neg' (Lit (Dbl Double
_))          = Bool
True
neg' (Lit (Int Integer
_))          = Bool
True
neg' (Lit (ExactDbl Integer
_))     = Bool
True
neg' Operator{}             = Bool
True
neg' (AssocA AssocArithOper
Mul [Expr]
_)       = Bool
True
neg' (LABinaryOp LABinOp
Index Expr
_ Expr
_) = Bool
True
neg' (UnaryOp UFunc
_ Expr
_)          = Bool
True
neg' (UnaryOpB UFuncB
_ Expr
_)         = Bool
True
neg' (UnaryOpVV UFuncVV
_ Expr
_)        = Bool
True
neg' (C UID
_)                  = Bool
True
neg' Expr
_                      = Bool
False

-- | Render negated expressions.
neg :: PrintingInformation -> Expr -> P.Expr
neg :: PrintingInformation -> Expr -> Expr
neg PrintingInformation
sm Expr
a = [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Neg, (if Expr -> Bool
neg' Expr
a then Expr -> Expr
forall a. a -> a
id else Expr -> Expr
parens) (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
sm]

-- | For printing indexes.
indx :: PrintingInformation -> Expr -> Expr -> P.Expr
indx :: PrintingInformation -> Expr -> Expr -> Expr
indx PrintingInformation
sm (C UID
c) Expr
i = Symbol -> Expr
f Symbol
s
  where
    i' :: Expr
i' = Expr -> PrintingInformation -> Expr
expr Expr
i PrintingInformation
sm
    s :: Symbol
s = Stage -> ChunkDB -> UID -> Symbol
lookupC (PrintingInformation
sm PrintingInformation
-> Getting Stage PrintingInformation Stage -> Stage
forall s a. s -> Getting a s a -> a
^. Getting Stage PrintingInformation Stage
Lens' PrintingInformation Stage
stg) (PrintingInformation
sm PrintingInformation
-> Getting ChunkDB PrintingInformation ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB PrintingInformation ChunkDB
Lens' PrintingInformation ChunkDB
ckdb) UID
c
    f :: Symbol -> Expr
f (S.Corners [] [] [] [Symbol
b] Symbol
e) =
      let e' :: Expr
e' = Symbol -> Expr
symbol Symbol
e
          b' :: Expr
b' = Symbol -> Expr
symbol Symbol
b in
      [Expr] -> Expr
P.Row [[Expr] -> Expr
P.Row [Expr
e', Expr -> Expr
P.Sub ([Expr] -> Expr
P.Row [Expr
b', Ops -> Expr
P.MO Ops
P.Comma, Expr
i'])]] -- FIXME, extra Row
    f a :: Symbol
a@(S.Variable String
_) = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
a, Expr -> Expr
P.Sub Expr
i']
    f a :: Symbol
a@(S.Label String
_)    = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
a, Expr -> Expr
P.Sub Expr
i']
--    f a@(Greek _)  = P.Row [symbol a, P.Sub i']
    f   Symbol
e          = let e' :: Expr
e' = Symbol -> Expr
symbol Symbol
e in [Expr] -> Expr
P.Row [[Expr] -> Expr
P.Row [Expr
e'], Expr -> Expr
P.Sub Expr
i']
indx PrintingInformation
sm Expr
a Expr
i = [Expr] -> Expr
P.Row [[Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
sm], Expr -> Expr
P.Sub (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
i PrintingInformation
sm]

-- | For printing expressions that call something.
call :: PrintingInformation -> UID -> [Expr] -> P.Expr
call :: PrintingInformation -> UID -> [Expr] -> Expr
call PrintingInformation
sm UID
f [Expr]
ps = [Expr] -> Expr
P.Row [
    Symbol -> Expr
symbol (Symbol -> Expr) -> Symbol -> Expr
forall a b. (a -> b) -> a -> b
$ Stage -> ChunkDB -> UID -> Symbol
lookupC (PrintingInformation
sm PrintingInformation
-> Getting Stage PrintingInformation Stage -> Stage
forall s a. s -> Getting a s a -> a
^. Getting Stage PrintingInformation Stage
Lens' PrintingInformation Stage
stg) (PrintingInformation
sm PrintingInformation
-> Getting ChunkDB PrintingInformation ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB PrintingInformation ChunkDB
Lens' PrintingInformation ChunkDB
ckdb) UID
f,
    Expr -> Expr
parens (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ [Expr] -> Expr
P.Row ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
intersperse (Ops -> Expr
P.MO Ops
P.Comma) ([Expr] -> [Expr]) -> [Expr] -> [Expr]
forall a b. (a -> b) -> a -> b
$ (Expr -> Expr) -> [Expr] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Expr -> PrintingInformation -> Expr
`expr` PrintingInformation
sm) [Expr]
ps
  ]

-- | Helper function for addition 'EOperator's.
eopAdds :: PrintingInformation -> DomainDesc t Expr Expr -> Expr -> P.Expr
eopAdds :: forall (t :: RTopology).
PrintingInformation -> DomainDesc t Expr Expr -> Expr -> Expr
eopAdds PrintingInformation
sm (BoundedDD Symbol
v RTopology
Continuous Expr
l Expr
h) Expr
e =
  [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Inte, Expr -> Expr
P.Sub (Expr -> PrintingInformation -> Expr
expr Expr
l PrintingInformation
sm), Expr -> Expr
P.Sup (Expr -> PrintingInformation -> Expr
expr Expr
h PrintingInformation
sm),
         [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
e PrintingInformation
sm], Spacing -> Expr
P.Spc Spacing
P.Thin, String -> Expr
P.Ident String
"d", Symbol -> Expr
symbol Symbol
v]
eopAdds PrintingInformation
sm (AllDD Symbol
v RTopology
Continuous) Expr
e =
  [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Inte, Expr -> Expr
P.Sub (Symbol -> Expr
symbol Symbol
v), [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
e PrintingInformation
sm], Spacing -> Expr
P.Spc Spacing
P.Thin,
         String -> Expr
P.Ident String
"d", Symbol -> Expr
symbol Symbol
v]
eopAdds PrintingInformation
sm (BoundedDD Symbol
v RTopology
Discrete Expr
l Expr
h) Expr
e =
  [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Summ, Expr -> Expr
P.Sub ([Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
v, Ops -> Expr
P.MO Ops
P.Eq, Expr -> PrintingInformation -> Expr
expr Expr
l PrintingInformation
sm]), Expr -> Expr
P.Sup (Expr -> PrintingInformation -> Expr
expr Expr
h PrintingInformation
sm),
         [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
e PrintingInformation
sm]]
eopAdds PrintingInformation
sm (AllDD Symbol
_ RTopology
Discrete) Expr
e = [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Summ, [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
e PrintingInformation
sm]]

-- | Helper function for multiplicative 'EOperator's.
eopMuls :: PrintingInformation -> DomainDesc t Expr Expr -> Expr -> P.Expr
eopMuls :: forall (t :: RTopology).
PrintingInformation -> DomainDesc t Expr Expr -> Expr -> Expr
eopMuls PrintingInformation
sm (BoundedDD Symbol
v RTopology
Discrete Expr
l Expr
h) Expr
e =
  [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Prod, Expr -> Expr
P.Sub ([Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
v, Ops -> Expr
P.MO Ops
P.Eq, Expr -> PrintingInformation -> Expr
expr Expr
l PrintingInformation
sm]), Expr -> Expr
P.Sup (Expr -> PrintingInformation -> Expr
expr Expr
h PrintingInformation
sm),
         [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
e PrintingInformation
sm]]
eopMuls PrintingInformation
sm (AllDD Symbol
_ RTopology
Discrete) Expr
e = [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Prod, [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
e PrintingInformation
sm]]
eopMuls PrintingInformation
_ (AllDD Symbol
_ RTopology
Continuous) Expr
_ = String -> Expr
forall a. HasCallStack => String -> a
error String
"Printing/Import.hs Product-Integral not implemented."
eopMuls PrintingInformation
_ (BoundedDD Symbol
_ RTopology
Continuous Expr
_ Expr
_) Expr
_ = String -> Expr
forall a. HasCallStack => String -> a
error String
"Printing/Import.hs Product-Integral not implemented."


-- | Helper function for translating 'EOperator's.
eop :: PrintingInformation -> AssocArithOper -> DomainDesc t Expr Expr -> Expr -> P.Expr
eop :: forall (t :: RTopology).
PrintingInformation
-> AssocArithOper -> DomainDesc t Expr Expr -> Expr -> Expr
eop PrintingInformation
sm AssocArithOper
Add = PrintingInformation -> DomainDesc t Expr Expr -> Expr -> Expr
forall (t :: RTopology).
PrintingInformation -> DomainDesc t Expr Expr -> Expr -> Expr
eopAdds PrintingInformation
sm
eop PrintingInformation
sm AssocArithOper
Mul = PrintingInformation -> DomainDesc t Expr Expr -> Expr -> Expr
forall (t :: RTopology).
PrintingInformation -> DomainDesc t Expr Expr -> Expr -> Expr
eopMuls PrintingInformation
sm


-- | Translate Exprs to printable layout AST.
expr :: Expr -> PrintingInformation -> P.Expr
expr :: Expr -> PrintingInformation -> Expr
expr (Lit Literal
l)                  PrintingInformation
sm = Literal -> PrintingInformation -> Expr
literal Literal
l PrintingInformation
sm
expr (AssocB AssocBoolOper
And [Expr]
l)           PrintingInformation
sm = Ops -> Int -> [Expr] -> PrintingInformation -> Expr
assocExpr Ops
P.And (AssocBoolOper -> Int
precB AssocBoolOper
And) [Expr]
l PrintingInformation
sm
expr (AssocB AssocBoolOper
Or [Expr]
l)            PrintingInformation
sm = Ops -> Int -> [Expr] -> PrintingInformation -> Expr
assocExpr Ops
P.Or (AssocBoolOper -> Int
precB AssocBoolOper
Or) [Expr]
l PrintingInformation
sm
expr (AssocA AssocArithOper
Add [Expr]
l)           PrintingInformation
sm = [Expr] -> Expr
P.Row ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ [Expr] -> AssocArithOper -> PrintingInformation -> [Expr]
addExpr [Expr]
l AssocArithOper
Add PrintingInformation
sm
expr (AssocA AssocArithOper
Mul [Expr]
l)           PrintingInformation
sm = [Expr] -> Expr
P.Row ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ [Expr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr [Expr]
l AssocArithOper
Mul PrintingInformation
sm
expr (AssocC AssocConcatOper
SUnion [Expr]
l)        PrintingInformation
sm = Ops -> Int -> [Expr] -> PrintingInformation -> Expr
assocExpr Ops
P.SUnion (AssocConcatOper -> Int
precC AssocConcatOper
SUnion) [Expr]
l PrintingInformation
sm
expr (C UID
c)                    PrintingInformation
sm = Symbol -> Expr
symbol (Symbol -> Expr) -> Symbol -> Expr
forall a b. (a -> b) -> a -> b
$ Stage -> ChunkDB -> UID -> Symbol
lookupC (PrintingInformation
sm PrintingInformation
-> Getting Stage PrintingInformation Stage -> Stage
forall s a. s -> Getting a s a -> a
^. Getting Stage PrintingInformation Stage
Lens' PrintingInformation Stage
stg) (PrintingInformation
sm PrintingInformation
-> Getting ChunkDB PrintingInformation ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB PrintingInformation ChunkDB
Lens' PrintingInformation ChunkDB
ckdb) UID
c
expr (FCall UID
f [Expr
x])            PrintingInformation
sm =
  [Expr] -> Expr
P.Row [Symbol -> Expr
symbol (Symbol -> Expr) -> Symbol -> Expr
forall a b. (a -> b) -> a -> b
$ Stage -> ChunkDB -> UID -> Symbol
lookupC (PrintingInformation
sm PrintingInformation
-> Getting Stage PrintingInformation Stage -> Stage
forall s a. s -> Getting a s a -> a
^. Getting Stage PrintingInformation Stage
Lens' PrintingInformation Stage
stg) (PrintingInformation
sm PrintingInformation
-> Getting ChunkDB PrintingInformation ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB PrintingInformation ChunkDB
Lens' PrintingInformation ChunkDB
ckdb) UID
f, Expr -> Expr
parens (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
x PrintingInformation
sm]
expr (FCall UID
f [Expr]
l)              PrintingInformation
sm = PrintingInformation -> UID -> [Expr] -> Expr
call PrintingInformation
sm UID
f [Expr]
l
expr (Case Completeness
_ [(Expr, Expr)]
ps)              PrintingInformation
sm =
  if [(Expr, Expr)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Expr, Expr)]
ps Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2
    then String -> Expr
forall a. HasCallStack => String -> a
error String
"Attempting to use multi-case expr incorrectly"
    else [(Expr, Expr)] -> Expr
P.Case ([Expr] -> [Expr] -> [(Expr, Expr)]
forall a b. [a] -> [b] -> [(a, b)]
zip (((Expr, Expr) -> Expr) -> [(Expr, Expr)] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map ((Expr -> PrintingInformation -> Expr)
-> PrintingInformation -> Expr -> Expr
forall a b c. (a -> b -> c) -> b -> a -> c
flip Expr -> PrintingInformation -> Expr
expr PrintingInformation
sm (Expr -> Expr) -> ((Expr, Expr) -> Expr) -> (Expr, Expr) -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Expr, Expr) -> Expr
forall a b. (a, b) -> a
fst) [(Expr, Expr)]
ps) (((Expr, Expr) -> Expr) -> [(Expr, Expr)] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map ((Expr -> PrintingInformation -> Expr)
-> PrintingInformation -> Expr -> Expr
forall a b c. (a -> b -> c) -> b -> a -> c
flip Expr -> PrintingInformation -> Expr
expr PrintingInformation
sm (Expr -> Expr) -> ((Expr, Expr) -> Expr) -> (Expr, Expr) -> Expr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Expr, Expr) -> Expr
forall a b. (a, b) -> b
snd) [(Expr, Expr)]
ps))
expr (Matrix [[Expr]]
a)               PrintingInformation
sm = [[Expr]] -> Expr
P.Mtx ([[Expr]] -> Expr) -> [[Expr]] -> Expr
forall a b. (a -> b) -> a -> b
$ ([Expr] -> [Expr]) -> [[Expr]] -> [[Expr]]
forall a b. (a -> b) -> [a] -> [b]
map ((Expr -> Expr) -> [Expr] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Expr -> PrintingInformation -> Expr
`expr` PrintingInformation
sm)) [[Expr]]
a
expr (Set Space
_ [Expr]
a)                PrintingInformation
sm = [Expr] -> Expr
P.Set ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ (Expr -> Expr) -> [Expr] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Expr -> PrintingInformation -> Expr
`expr` PrintingInformation
sm) [Expr]
a
expr (Variable String
_ Expr
l)           PrintingInformation
sm = Expr -> PrintingInformation -> Expr
expr Expr
l PrintingInformation
sm
expr (UnaryOp UFunc
Log Expr
u)          PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Log Expr
u
expr (UnaryOp UFunc
Ln Expr
u)           PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Ln Expr
u
expr (UnaryOp UFunc
Sin Expr
u)          PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Sin Expr
u
expr (UnaryOp UFunc
Cos Expr
u)          PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Cos Expr
u
expr (UnaryOp UFunc
Tan Expr
u)          PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Tan Expr
u
expr (UnaryOp UFunc
Sec Expr
u)          PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Sec Expr
u
expr (UnaryOp UFunc
Csc Expr
u)          PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Csc Expr
u
expr (UnaryOp UFunc
Cot Expr
u)          PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Cot Expr
u
expr (UnaryOp UFunc
Arcsin Expr
u)       PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Arcsin Expr
u
expr (UnaryOp UFunc
Arccos Expr
u)       PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Arccos Expr
u
expr (UnaryOp UFunc
Arctan Expr
u)       PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Arctan Expr
u
expr (UnaryOp UFunc
Exp Expr
u)          PrintingInformation
sm = [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Exp, Expr -> Expr
P.Sup (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
u PrintingInformation
sm]
expr (UnaryOp UFunc
Abs Expr
u)          PrintingInformation
sm = Fence -> Fence -> Expr -> Expr
P.Fenced Fence
P.Abs Fence
P.Abs (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
u PrintingInformation
sm
expr (UnaryOpB UFuncB
Not Expr
u)         PrintingInformation
sm = [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Not, Expr -> PrintingInformation -> Expr
expr Expr
u PrintingInformation
sm]
expr (UnaryOpVN UFuncVN
Norm Expr
u)       PrintingInformation
sm = Fence -> Fence -> Expr -> Expr
P.Fenced Fence
P.Norm Fence
P.Norm (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
u PrintingInformation
sm
expr (UnaryOpVN UFuncVN
Dim Expr
u)        PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr
mkCall PrintingInformation
sm Ops
P.Dim Expr
u
expr (UnaryOp UFunc
Sqrt Expr
u)         PrintingInformation
sm = Expr -> Expr
P.Sqrt (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> PrintingInformation -> Expr
expr Expr
u PrintingInformation
sm
expr (UnaryOp UFunc
Neg Expr
u)          PrintingInformation
sm = PrintingInformation -> Expr -> Expr
neg PrintingInformation
sm Expr
u
expr (UnaryOpVV UFuncVV
NegV Expr
u)       PrintingInformation
sm = PrintingInformation -> Expr -> Expr
neg PrintingInformation
sm Expr
u
expr (ArithBinaryOp ArithBinOp
Frac Expr
a Expr
b) PrintingInformation
sm = Expr -> Expr -> Expr
P.Div (Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
sm) (Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
sm)
expr (ArithBinaryOp ArithBinOp
Pow Expr
a Expr
b)  PrintingInformation
sm = PrintingInformation -> Expr -> Expr -> Expr
pow PrintingInformation
sm Expr
a Expr
b
expr (ArithBinaryOp ArithBinOp
Subt Expr
a Expr
b) PrintingInformation
sm = [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
sm, Ops -> Expr
P.MO Ops
P.Subt, Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
sm]
expr (BoolBinaryOp BoolBinOp
Impl Expr
a Expr
b)  PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.Impl Expr
a Expr
b
expr (BoolBinaryOp BoolBinOp
Iff Expr
a Expr
b)   PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.Iff Expr
a Expr
b
expr (EqBinaryOp EqBinOp
Eq Expr
a Expr
b)      PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.Eq Expr
a Expr
b
expr (EqBinaryOp EqBinOp
NEq Expr
a Expr
b)     PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.NEq Expr
a Expr
b
expr (LABinaryOp LABinOp
Index Expr
a Expr
b)   PrintingInformation
sm = PrintingInformation -> Expr -> Expr -> Expr
indx PrintingInformation
sm Expr
a Expr
b
expr (LABinaryOp LABinOp
IndexOf Expr
a Expr
b) PrintingInformation
sm = PrintingInformation -> Expr -> Expr -> Expr
indx PrintingInformation
sm Expr
a Expr
b
expr (OrdBinaryOp OrdBinOp
Lt Expr
a Expr
b)     PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.Lt Expr
a Expr
b
expr (OrdBinaryOp OrdBinOp
Gt Expr
a Expr
b)     PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.Gt Expr
a Expr
b
expr (OrdBinaryOp OrdBinOp
LEq Expr
a Expr
b)    PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.LEq Expr
a Expr
b
expr (OrdBinaryOp OrdBinOp
GEq Expr
a Expr
b)    PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.GEq Expr
a Expr
b
expr (VVVBinaryOp VVVBinOp
Cross Expr
a Expr
b)  PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.Cross Expr
a Expr
b
expr (VVVBinaryOp VVVBinOp
VAdd Expr
a Expr
b)   PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.VAdd Expr
a Expr
b
expr (VVVBinaryOp VVVBinOp
VSub Expr
a Expr
b)   PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.VSub Expr
a Expr
b
expr (VVNBinaryOp VVNBinOp
Dot Expr
a Expr
b)    PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.Dot Expr
a Expr
b
expr (NVVBinaryOp NVVBinOp
Scale Expr
a Expr
b)  PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.Scale Expr
a Expr
b
expr (ESSBinaryOp ESSBinOp
SAdd Expr
a Expr
b)   PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.SAdd Expr
a Expr
b
expr (ESSBinaryOp ESSBinOp
SRemove Expr
a Expr
b)    PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.SRemove Expr
a Expr
b
expr (ESBBinaryOp ESBBinOp
SContains Expr
a Expr
b)  PrintingInformation
sm = PrintingInformation -> Ops -> Expr -> Expr -> Expr
mkBOp PrintingInformation
sm Ops
P.SContains Expr
a Expr
b
expr (Operator AssocArithOper
o DiscreteDomainDesc Expr Expr
d Expr
e)         PrintingInformation
sm = PrintingInformation
-> AssocArithOper -> DiscreteDomainDesc Expr Expr -> Expr -> Expr
forall (t :: RTopology).
PrintingInformation
-> AssocArithOper -> DomainDesc t Expr Expr -> Expr -> Expr
eop PrintingInformation
sm AssocArithOper
o DiscreteDomainDesc Expr Expr
d Expr
e
expr (RealI UID
c RealInterval Expr Expr
ri)             PrintingInformation
sm = PrintingInformation -> Symbol -> RealInterval Expr Expr -> Expr
renderRealInt PrintingInformation
sm (Stage -> ChunkDB -> UID -> Symbol
lookupC (PrintingInformation
sm PrintingInformation
-> Getting Stage PrintingInformation Stage -> Stage
forall s a. s -> Getting a s a -> a
^. Getting Stage PrintingInformation Stage
Lens' PrintingInformation Stage
stg)
  (PrintingInformation
sm PrintingInformation
-> Getting ChunkDB PrintingInformation ChunkDB -> ChunkDB
forall s a. s -> Getting a s a -> a
^. Getting ChunkDB PrintingInformation ChunkDB
Lens' PrintingInformation ChunkDB
ckdb) UID
c) RealInterval Expr Expr
ri

-- | Common method of converting associative operations into printable layout AST.
assocExpr :: P.Ops -> Int -> [Expr] -> PrintingInformation -> P.Expr
assocExpr :: Ops -> Int -> [Expr] -> PrintingInformation -> Expr
assocExpr Ops
op Int
prec [Expr]
exprs PrintingInformation
sm = [Expr] -> Expr
P.Row ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
intersperse (Ops -> Expr
P.MO Ops
op) ([Expr] -> [Expr]) -> [Expr] -> [Expr]
forall a b. (a -> b) -> a -> b
$ (Expr -> Expr) -> [Expr] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
sm Int
prec) [Expr]
exprs

-- | Helper for rendering printable expressions.
addExpr :: [Expr] -> AssocArithOper -> PrintingInformation -> [P.Expr]
addExpr :: [Expr] -> AssocArithOper -> PrintingInformation -> [Expr]
addExpr [Expr]
exprs AssocArithOper
o PrintingInformation
sm = [Expr] -> [Expr]
addExprFilter ((Expr -> Expr) -> [Expr] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o)) [Expr]
exprs)

-- | Add add symbol only when the second Expr is not negation 
addExprFilter :: [P.Expr] -> [P.Expr]
addExprFilter :: [Expr] -> [Expr]
addExprFilter [] = []
addExprFilter [Expr
x] = [Expr
x]
addExprFilter (Expr
x1:P.Row[P.MO Ops
P.Neg, Expr
x2]:[Expr]
xs) = Expr
x1 Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: [Expr] -> [Expr]
addExprFilter ([Expr] -> Expr
P.Row[Ops -> Expr
P.MO Ops
P.Neg, Expr
x2] Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: [Expr]
xs)
addExprFilter (Expr
x:[Expr]
xs) = Expr
x Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: Ops -> Expr
P.MO Ops
P.Add Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: [Expr] -> [Expr]
addExprFilter [Expr]
xs

-- | Helper for rendering printable expressions.
mulExpr ::  [Expr] -> AssocArithOper -> PrintingInformation -> [P.Expr]
mulExpr :: [Expr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (Expr
hd1:Expr
hd2:[Expr]
tl) AssocArithOper
o PrintingInformation
sm = case (Expr
hd1, Expr
hd2) of
  (Expr
a, Lit (Int Integer
_))      ->  [PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) Expr
a, Ops -> Expr
P.MO Ops
P.Dot] [Expr] -> [Expr] -> [Expr]
forall a. [a] -> [a] -> [a]
++ [Expr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (Expr
hd2 Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: [Expr]
tl) AssocArithOper
o PrintingInformation
sm
  (Expr
a, Lit (ExactDbl Integer
_)) ->  [PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) Expr
a, Ops -> Expr
P.MO Ops
P.Dot] [Expr] -> [Expr] -> [Expr]
forall a. [a] -> [a] -> [a]
++ [Expr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (Expr
hd2 Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: [Expr]
tl) AssocArithOper
o PrintingInformation
sm
  (Expr
a, Lit (Dbl Double
_))      ->  [PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) Expr
a, Ops -> Expr
P.MO Ops
P.Dot] [Expr] -> [Expr] -> [Expr]
forall a. [a] -> [a] -> [a]
++ [Expr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (Expr
hd2 Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: [Expr]
tl) AssocArithOper
o PrintingInformation
sm
  (Expr
a, Expr
_)                ->  [PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) Expr
a, Ops -> Expr
P.MO Ops
P.Mul] [Expr] -> [Expr] -> [Expr]
forall a. [a] -> [a] -> [a]
++ [Expr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (Expr
hd2 Expr -> [Expr] -> [Expr]
forall a. a -> [a] -> [a]
: [Expr]
tl) AssocArithOper
o PrintingInformation
sm
mulExpr [Expr
hd]         AssocArithOper
o PrintingInformation
sm = [PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) Expr
hd]
mulExpr []           AssocArithOper
o PrintingInformation
sm = [PrintingInformation -> Int -> Expr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) (Integer -> Expr
forall r. LiteralC r => Integer -> r
int Integer
1)]


-- | Helper that adds parenthesis to the first expression. The second expression
-- is written as a superscript attached to the first.
withParens :: PrintingInformation -> Expr -> Expr -> P.Expr
withParens :: PrintingInformation -> Expr -> Expr -> Expr
withParens PrintingInformation
prI Expr
a Expr
b = [Expr] -> Expr
P.Row [Expr -> Expr
parens (Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
prI), Expr -> Expr
P.Sup (Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
prI)]

-- | Helper for properly rendering exponents.
pow :: PrintingInformation -> Expr -> Expr -> P.Expr
pow :: PrintingInformation -> Expr -> Expr -> Expr
pow PrintingInformation
prI a :: Expr
a@(AssocA AssocArithOper
Add [Expr]
_)          Expr
b = PrintingInformation -> Expr -> Expr -> Expr
withParens PrintingInformation
prI Expr
a Expr
b
pow PrintingInformation
prI a :: Expr
a@(AssocA AssocArithOper
Mul [Expr]
_)         Expr
b = PrintingInformation -> Expr -> Expr -> Expr
withParens PrintingInformation
prI Expr
a Expr
b
pow PrintingInformation
prI a :: Expr
a@(ArithBinaryOp ArithBinOp
Subt Expr
_ Expr
_) Expr
b = PrintingInformation -> Expr -> Expr -> Expr
withParens PrintingInformation
prI Expr
a Expr
b
pow PrintingInformation
prI a :: Expr
a@(ArithBinaryOp ArithBinOp
Frac Expr
_ Expr
_) Expr
b = PrintingInformation -> Expr -> Expr -> Expr
withParens PrintingInformation
prI Expr
a Expr
b
pow PrintingInformation
prI a :: Expr
a@(ArithBinaryOp ArithBinOp
Pow Expr
_ Expr
_)  Expr
b = PrintingInformation -> Expr -> Expr -> Expr
withParens PrintingInformation
prI Expr
a Expr
b
pow PrintingInformation
prI Expr
a                          Expr
b = [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
prI, Expr -> Expr
P.Sup (Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
prI)]

-- | Print a 'RealInterval'.
renderRealInt :: PrintingInformation -> Symbol -> RealInterval Expr Expr -> P.Expr
renderRealInt :: PrintingInformation -> Symbol -> RealInterval Expr Expr -> Expr
renderRealInt PrintingInformation
st Symbol
s (Bounded (Inclusive
Inc,Expr
a) (Inclusive
Inc,Expr
b)) =
  [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
st, Ops -> Expr
P.MO Ops
P.LEq, Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.LEq, Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
st]
renderRealInt PrintingInformation
st Symbol
s (Bounded (Inclusive
Inc,Expr
a) (Inclusive
Exc,Expr
b)) =
  [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
st, Ops -> Expr
P.MO Ops
P.LEq, Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.Lt, Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
st]
renderRealInt PrintingInformation
st Symbol
s (Bounded (Inclusive
Exc,Expr
a) (Inclusive
Inc,Expr
b)) =
  [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
st, Ops -> Expr
P.MO Ops
P.Lt, Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.LEq, Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
st]
renderRealInt PrintingInformation
st Symbol
s (Bounded (Inclusive
Exc,Expr
a) (Inclusive
Exc,Expr
b)) =
  [Expr] -> Expr
P.Row [Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
st, Ops -> Expr
P.MO Ops
P.Lt, Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.Lt, Expr -> PrintingInformation -> Expr
expr Expr
b PrintingInformation
st]
renderRealInt PrintingInformation
st Symbol
s (UpTo (Inclusive
Inc,Expr
a))   = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.LEq, Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
st]
renderRealInt PrintingInformation
st Symbol
s (UpTo (Inclusive
Exc,Expr
a))   = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.Lt,  Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
st]
renderRealInt PrintingInformation
st Symbol
s (UpFrom (Inclusive
Inc,Expr
a)) = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.GEq, Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
st]
renderRealInt PrintingInformation
st Symbol
s (UpFrom (Inclusive
Exc,Expr
a)) = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.Gt,  Expr -> PrintingInformation -> Expr
expr Expr
a PrintingInformation
st]