{-# LANGUAGE GADTs #-}

-- | Defines functions to render 'CodeExpr's as printable 'P.Expr's.
module Language.Drasil.Printing.Import.CodeExpr (codeExpr) where

import Language.Drasil (DomainDesc(..), Inclusive(..),
  RTopology(..), RealInterval(..), UID, LiteralC (int))
import Language.Drasil.Display (Symbol(..))
import Language.Drasil.CodeExpr.Development
import Language.Drasil.Literal.Development

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

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

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


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

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

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

-- | Helper for properly rendering negation of expressions.
neg' :: CodeExpr -> Bool
neg' :: CodeExpr -> 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
MulI [CodeExpr]
_)        = Bool
True
neg' (AssocA AssocArithOper
MulRe [CodeExpr]
_)       = Bool
True
neg' (LABinaryOp LABinOp
Index CodeExpr
_ CodeExpr
_) = Bool
True
neg' (UnaryOp UFunc
_ CodeExpr
_)          = Bool
True
neg' (UnaryOpB UFuncB
_ CodeExpr
_)         = Bool
True
neg' (UnaryOpVV UFuncVV
_ CodeExpr
_)        = Bool
True
neg' (C UID
_)                  = Bool
True
neg' CodeExpr
_                      = Bool
False

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

-- | For printing indexes.
indx :: PrintingInformation -> CodeExpr -> CodeExpr -> P.Expr
indx :: PrintingInformation -> CodeExpr -> CodeExpr -> Expr
indx PrintingInformation
sm (C UID
c) CodeExpr
i = Symbol -> Expr
f Symbol
s
  where
    i' :: Expr
i' = CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
i PrintingInformation
sm
    s :: Symbol
s = Stage -> ChunkDB -> UID -> Symbol
lookupC (PrintingInformation
sm forall s a. s -> Getting a s a -> a
^. Lens' PrintingInformation Stage
stg) (PrintingInformation
sm forall s a. s -> Getting a s a -> a
^. Lens' PrintingInformation ChunkDB
ckdb) UID
c
    f :: Symbol -> Expr
f (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@(Variable String
_) = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
a, Expr -> Expr
P.Sub Expr
i']
    f a :: Symbol
a@(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 CodeExpr
a CodeExpr
i = [Expr] -> Expr
P.Row [[Expr] -> Expr
P.Row [CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
a PrintingInformation
sm], Expr -> Expr
P.Sub forall a b. (a -> b) -> a -> b
$ CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
i PrintingInformation
sm]

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

-- | Helper function for addition 'EOperator's.
eopAdds :: PrintingInformation -> DomainDesc t CodeExpr CodeExpr -> CodeExpr -> P.Expr
eopAdds :: forall (t :: RTopology).
PrintingInformation
-> DomainDesc t CodeExpr CodeExpr -> CodeExpr -> Expr
eopAdds PrintingInformation
sm (BoundedDD Symbol
v RTopology
Continuous CodeExpr
l CodeExpr
h) CodeExpr
e =
  [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Inte, Expr -> Expr
P.Sub (CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
l PrintingInformation
sm), Expr -> Expr
P.Sup (CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
h PrintingInformation
sm),
         [Expr] -> Expr
P.Row [CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
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) CodeExpr
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 [CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
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 CodeExpr
l CodeExpr
h) CodeExpr
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, CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
l PrintingInformation
sm]), Expr -> Expr
P.Sup (CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
h PrintingInformation
sm),
         [Expr] -> Expr
P.Row [CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
e PrintingInformation
sm]]
eopAdds PrintingInformation
sm (AllDD Symbol
_ RTopology
Discrete) CodeExpr
e = [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Summ, [Expr] -> Expr
P.Row [CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
e PrintingInformation
sm]]

-- | Helper function for multiplicative 'EOperator's.
eopMuls :: PrintingInformation -> DomainDesc t CodeExpr CodeExpr -> CodeExpr -> P.Expr
eopMuls :: forall (t :: RTopology).
PrintingInformation
-> DomainDesc t CodeExpr CodeExpr -> CodeExpr -> Expr
eopMuls PrintingInformation
sm (BoundedDD Symbol
v RTopology
Discrete CodeExpr
l CodeExpr
h) CodeExpr
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, CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
l PrintingInformation
sm]), Expr -> Expr
P.Sup (CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
h PrintingInformation
sm),
         [Expr] -> Expr
P.Row [CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
e PrintingInformation
sm]]
eopMuls PrintingInformation
sm (AllDD Symbol
_ RTopology
Discrete) CodeExpr
e = [Expr] -> Expr
P.Row [Ops -> Expr
P.MO Ops
P.Prod, [Expr] -> Expr
P.Row [CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
e PrintingInformation
sm]]
eopMuls PrintingInformation
_ (AllDD Symbol
_ RTopology
Continuous) CodeExpr
_ = forall a. HasCallStack => String -> a
error String
"Printing/Import.hs Product-Integral not implemented."
eopMuls PrintingInformation
_ (BoundedDD Symbol
_ RTopology
Continuous CodeExpr
_ CodeExpr
_) CodeExpr
_ = 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 CodeExpr CodeExpr -> CodeExpr -> P.Expr
eop :: forall (t :: RTopology).
PrintingInformation
-> AssocArithOper
-> DomainDesc t CodeExpr CodeExpr
-> CodeExpr
-> Expr
eop PrintingInformation
sm AssocArithOper
AddI = forall (t :: RTopology).
PrintingInformation
-> DomainDesc t CodeExpr CodeExpr -> CodeExpr -> Expr
eopAdds PrintingInformation
sm
eop PrintingInformation
sm AssocArithOper
AddRe = forall (t :: RTopology).
PrintingInformation
-> DomainDesc t CodeExpr CodeExpr -> CodeExpr -> Expr
eopAdds PrintingInformation
sm
eop PrintingInformation
sm AssocArithOper
MulI = forall (t :: RTopology).
PrintingInformation
-> DomainDesc t CodeExpr CodeExpr -> CodeExpr -> Expr
eopMuls PrintingInformation
sm
eop PrintingInformation
sm AssocArithOper
MulRe = forall (t :: RTopology).
PrintingInformation
-> DomainDesc t CodeExpr CodeExpr -> CodeExpr -> Expr
eopMuls PrintingInformation
sm

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

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

-- | Helper for rendering printable expressions.
addExpr :: [CodeExpr] -> AssocArithOper -> PrintingInformation -> [P.Expr]
addExpr :: [CodeExpr] -> AssocArithOper -> PrintingInformation -> [Expr]
addExpr [CodeExpr]
exprs AssocArithOper
o PrintingInformation
sm = [Expr] -> [Expr]
addExprFilter (forall a b. (a -> b) -> [a] -> [b]
map (PrintingInformation -> Int -> CodeExpr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o)) [CodeExpr]
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 forall a. a -> [a] -> [a]
: [Expr] -> [Expr]
addExprFilter ([Expr] -> Expr
P.Row[Ops -> Expr
P.MO Ops
P.Neg, Expr
x2] forall a. a -> [a] -> [a]
: [Expr]
xs)
addExprFilter (Expr
x:[Expr]
xs) = Expr
x forall a. a -> [a] -> [a]
: Ops -> Expr
P.MO Ops
P.Add forall a. a -> [a] -> [a]
: [Expr] -> [Expr]
addExprFilter [Expr]
xs

-- | Helper for rendering printable expressions.
mulExpr ::  [CodeExpr] -> AssocArithOper -> PrintingInformation -> [P.Expr]
mulExpr :: [CodeExpr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (CodeExpr
hd1:CodeExpr
hd2:[CodeExpr]
tl) AssocArithOper
o PrintingInformation
sm = case (CodeExpr
hd1, CodeExpr
hd2) of
  (CodeExpr
a, Lit (Int Integer
_))      ->  [PrintingInformation -> Int -> CodeExpr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) CodeExpr
a, Ops -> Expr
P.MO Ops
P.Dot] forall a. [a] -> [a] -> [a]
++ [CodeExpr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (CodeExpr
hd2 forall a. a -> [a] -> [a]
: [CodeExpr]
tl) AssocArithOper
o PrintingInformation
sm
  (CodeExpr
a, Lit (ExactDbl Integer
_)) ->  [PrintingInformation -> Int -> CodeExpr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) CodeExpr
a, Ops -> Expr
P.MO Ops
P.Dot] forall a. [a] -> [a] -> [a]
++ [CodeExpr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (CodeExpr
hd2 forall a. a -> [a] -> [a]
: [CodeExpr]
tl) AssocArithOper
o PrintingInformation
sm
  (CodeExpr
a, Lit (Dbl Double
_))      ->  [PrintingInformation -> Int -> CodeExpr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) CodeExpr
a, Ops -> Expr
P.MO Ops
P.Dot] forall a. [a] -> [a] -> [a]
++ [CodeExpr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (CodeExpr
hd2 forall a. a -> [a] -> [a]
: [CodeExpr]
tl) AssocArithOper
o PrintingInformation
sm
  (CodeExpr
a, CodeExpr
_)                ->  [PrintingInformation -> Int -> CodeExpr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) CodeExpr
a, Ops -> Expr
P.MO Ops
P.Mul] forall a. [a] -> [a] -> [a]
++ [CodeExpr] -> AssocArithOper -> PrintingInformation -> [Expr]
mulExpr (CodeExpr
hd2 forall a. a -> [a] -> [a]
: [CodeExpr]
tl) AssocArithOper
o PrintingInformation
sm
mulExpr [CodeExpr
hd]         AssocArithOper
o PrintingInformation
sm = [PrintingInformation -> Int -> CodeExpr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) CodeExpr
hd]
mulExpr []           AssocArithOper
o PrintingInformation
sm = [PrintingInformation -> Int -> CodeExpr -> Expr
expr' PrintingInformation
sm (AssocArithOper -> Int
precA AssocArithOper
o) (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 -> CodeExpr -> CodeExpr -> P.Expr
withParens :: PrintingInformation -> CodeExpr -> CodeExpr -> Expr
withParens PrintingInformation
prI CodeExpr
a CodeExpr
b = [Expr] -> Expr
P.Row [Expr -> Expr
parens (CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
a PrintingInformation
prI), Expr -> Expr
P.Sup (CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
b PrintingInformation
prI)]

-- | Helper for properly rendering exponents.
pow :: PrintingInformation -> CodeExpr -> CodeExpr -> P.Expr
pow :: PrintingInformation -> CodeExpr -> CodeExpr -> Expr
pow PrintingInformation
prI a :: CodeExpr
a@(AssocA AssocArithOper
AddI [CodeExpr]
_)          CodeExpr
b = PrintingInformation -> CodeExpr -> CodeExpr -> Expr
withParens PrintingInformation
prI CodeExpr
a CodeExpr
b
pow PrintingInformation
prI a :: CodeExpr
a@(AssocA AssocArithOper
AddRe [CodeExpr]
_)         CodeExpr
b = PrintingInformation -> CodeExpr -> CodeExpr -> Expr
withParens PrintingInformation
prI CodeExpr
a CodeExpr
b
pow PrintingInformation
prI a :: CodeExpr
a@(AssocA AssocArithOper
MulI [CodeExpr]
_)          CodeExpr
b = PrintingInformation -> CodeExpr -> CodeExpr -> Expr
withParens PrintingInformation
prI CodeExpr
a CodeExpr
b
pow PrintingInformation
prI a :: CodeExpr
a@(AssocA AssocArithOper
MulRe [CodeExpr]
_)         CodeExpr
b = PrintingInformation -> CodeExpr -> CodeExpr -> Expr
withParens PrintingInformation
prI CodeExpr
a CodeExpr
b
pow PrintingInformation
prI a :: CodeExpr
a@(ArithBinaryOp ArithBinOp
Subt CodeExpr
_ CodeExpr
_) CodeExpr
b = PrintingInformation -> CodeExpr -> CodeExpr -> Expr
withParens PrintingInformation
prI CodeExpr
a CodeExpr
b
pow PrintingInformation
prI a :: CodeExpr
a@(ArithBinaryOp ArithBinOp
Frac CodeExpr
_ CodeExpr
_) CodeExpr
b = PrintingInformation -> CodeExpr -> CodeExpr -> Expr
withParens PrintingInformation
prI CodeExpr
a CodeExpr
b
pow PrintingInformation
prI a :: CodeExpr
a@(ArithBinaryOp ArithBinOp
Pow CodeExpr
_ CodeExpr
_)  CodeExpr
b = PrintingInformation -> CodeExpr -> CodeExpr -> Expr
withParens PrintingInformation
prI CodeExpr
a CodeExpr
b
pow PrintingInformation
prI CodeExpr
a                          CodeExpr
b = [Expr] -> Expr
P.Row [CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
a PrintingInformation
prI, Expr -> Expr
P.Sup (CodeExpr -> PrintingInformation -> Expr
codeExpr CodeExpr
b PrintingInformation
prI)]

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