-- | Defines functions for printing symbols and units.
module Language.Drasil.Printing.Import.Symbol (symbol, pUnit) where

import Language.Drasil (USymb(..))
import Language.Drasil.ShortHands (cDelta)
import Language.Drasil.Display (Decoration(..), Symbol(..))
import qualified Language.Drasil.Printing.AST as P

import Data.List (partition)
import Data.Bifunctor (second)

-- | Converts a symbol into an expression.
symbol :: Symbol -> P.Expr
symbol :: Symbol -> Expr
symbol (Variable String
s) = String -> Expr
P.Ident String
s
symbol (Label    String
s) = String -> Expr
P.Label String
s
symbol (Integ    Int
n) = Integer -> Expr
P.Int (Int -> Integer
forall a. Integral a => a -> Integer
toInteger Int
n)
symbol (Special  Special
s) = Special -> Expr
P.Spec Special
s
--symbol (Greek g)    = P.Gr g
symbol (Concat  [Symbol]
sl) = [Expr] -> Expr
P.Row ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ (Symbol -> Expr) -> [Symbol] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map Symbol -> Expr
symbol [Symbol]
sl
--
-- Handle the special cases first, then general case
symbol (Corners [] [] [Symbol
x] [] Symbol
s) = [Expr] -> Expr
P.Row [[Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
s, Expr -> Expr
P.Sup (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Symbol -> Expr
symbol Symbol
x]]
symbol (Corners [] [] [] [Symbol
x] Symbol
s) = [Expr] -> Expr
P.Row [[Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
s, Expr -> Expr
P.Sub (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Symbol -> Expr
symbol Symbol
x]]
symbol (Corners [Symbol
_] [] [] [] Symbol
_) = String -> Expr
forall a. HasCallStack => String -> a
error String
"rendering of ul prescript"
symbol (Corners [] [Symbol
_] [] [] Symbol
_) = String -> Expr
forall a. HasCallStack => String -> a
error String
"rendering of ll prescript"
symbol Corners{}                = String -> Expr
forall a. HasCallStack => String -> a
error String
"rendering of Corners (general)"
symbol (Atop Decoration
f Symbol
s)               = Decoration -> Symbol -> Expr
sFormat Decoration
f Symbol
s
symbol Symbol
Empty                    = [Expr] -> Expr
P.Row []

-- | Helper that adds decoration to symbols (for vectors, derivatives, etc.).
sFormat :: Decoration -> Symbol -> P.Expr
sFormat :: Decoration -> Symbol -> Expr
sFormat Decoration
Hat        Symbol
s = OverSymb -> Expr -> Expr
P.Over OverSymb
P.Hat (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Symbol -> Expr
symbol Symbol
s
sFormat Decoration
Vector     Symbol
s = Fonts -> Expr -> Expr
P.Font Fonts
P.Bold (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Symbol -> Expr
symbol Symbol
s
sFormat Decoration
Prime      Symbol
s = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
s, Ops -> Expr
P.MO Ops
P.Prime]
sFormat Decoration
Delta      Symbol
s = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
cDelta, Symbol -> Expr
symbol Symbol
s]
sFormat Decoration
Magnitude  Symbol
s = Fence -> Fence -> Expr -> Expr
P.Fenced Fence
P.Norm Fence
P.Norm (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Symbol -> Expr
symbol Symbol
s

-- | Renders a unit symbol as a printable expression.
pUnit :: USymb -> P.Expr
pUnit :: USymb -> Expr
pUnit (US [(Symbol, Integer)]
ls) = [(Symbol, Integer)] -> [(Symbol, Integer)] -> Expr
formatu [(Symbol, Integer)]
t [(Symbol, Integer)]
b
  where
    ([(Symbol, Integer)]
t, [(Symbol, Integer)]
b) = ((Symbol, Integer) -> Bool)
-> [(Symbol, Integer)]
-> ([(Symbol, Integer)], [(Symbol, Integer)])
forall a. (a -> Bool) -> [a] -> ([a], [a])
partition ((Integer -> Integer -> Bool
forall a. Ord a => a -> a -> Bool
> Integer
0) (Integer -> Bool)
-> ((Symbol, Integer) -> Integer) -> (Symbol, Integer) -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Symbol, Integer) -> Integer
forall a b. (a, b) -> b
snd) [(Symbol, Integer)]
ls
    formatu :: [(Symbol, Integer)] -> [(Symbol, Integer)] -> P.Expr
    formatu :: [(Symbol, Integer)] -> [(Symbol, Integer)] -> Expr
formatu [] [(Symbol, Integer)]
l = [(Symbol, Integer)] -> Expr
line [(Symbol, Integer)]
l
    formatu [(Symbol, Integer)]
l [] = [Expr] -> Expr
P.Row ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ ((Symbol, Integer) -> Expr) -> [(Symbol, Integer)] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Symbol, Integer) -> Expr
powu [(Symbol, Integer)]
l
    formatu [(Symbol, Integer)]
nu [(Symbol, Integer)]
de = Expr -> Expr -> Expr
P.Div ([(Symbol, Integer)] -> Expr
line [(Symbol, Integer)]
nu) (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ [(Symbol, Integer)] -> Expr
line ([(Symbol, Integer)] -> Expr) -> [(Symbol, Integer)] -> Expr
forall a b. (a -> b) -> a -> b
$ ((Symbol, Integer) -> (Symbol, Integer))
-> [(Symbol, Integer)] -> [(Symbol, Integer)]
forall a b. (a -> b) -> [a] -> [b]
map ((Integer -> Integer) -> (Symbol, Integer) -> (Symbol, Integer)
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second Integer -> Integer
forall a. Num a => a -> a
negate) [(Symbol, Integer)]
de
    line :: [(Symbol, Integer)] -> P.Expr
    line :: [(Symbol, Integer)] -> Expr
line []  = [Expr] -> Expr
P.Row [] -- should not happen ?
    line [(Symbol, Integer)
n] = (Symbol, Integer) -> Expr
powu (Symbol, Integer)
n
    line [(Symbol, Integer)]
l   = [Expr] -> Expr
P.Row ([Expr] -> Expr) -> [Expr] -> Expr
forall a b. (a -> b) -> a -> b
$ ((Symbol, Integer) -> Expr) -> [(Symbol, Integer)] -> [Expr]
forall a b. (a -> b) -> [a] -> [b]
map (Symbol, Integer) -> Expr
powu [(Symbol, Integer)]
l
    powu :: (Symbol, Integer) -> P.Expr
    powu :: (Symbol, Integer) -> Expr
powu (Symbol
n, Integer
1) = Symbol -> Expr
symbol Symbol
n
    powu (Symbol
n, Integer
p) = [Expr] -> Expr
P.Row [Symbol -> Expr
symbol Symbol
n, Expr -> Expr
P.Sup (Expr -> Expr) -> Expr -> Expr
forall a b. (a -> b) -> a -> b
$ Integer -> Expr
P.Int Integer
p]