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

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

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

-- | 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]