{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE OverloadedStrings #-}

module Typst.Module.Math
  ( mathModule,
  )
where

import qualified Data.Map as M
import qualified Data.Sequence as Seq
import qualified Data.Vector as V
import Text.Parsec (getPosition)
import Typst.Types
import Typst.Util

mathModule :: M.Map Identifier Val
mathModule :: Map Identifier Val
mathModule =
  forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
    [ Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (forall a. a -> Maybe a
Just Identifier
"math")
        Identifier
"frac"
        [ (Identifier
"num", ValType -> TypeSpec
One ValType
TContent),
          (Identifier
"denom", ValType -> TypeSpec
One ValType
TContent)
        ],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (forall a. a -> Maybe a
Just Identifier
"math")
        Identifier
"accent"
        [ (Identifier
"base", ValType -> TypeSpec
One ValType
TContent),
          (Identifier
"accent", ValType -> TypeSpec
One (ValType
TContent ValType -> ValType -> ValType
:|: ValType
TString ValType -> ValType -> ValType
:|: ValType
TSymbol))
        ],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"attach" [(Identifier
"base", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"scripts" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"limits" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (forall a. a -> Maybe a
Just Identifier
"math")
        Identifier
"binom"
        [ (Identifier
"upper", ValType -> TypeSpec
One ValType
TContent),
          (Identifier
"lower", ValType -> TypeSpec
One ValType
TContent)
        ],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"cancel" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"equation" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (forall a. a -> Maybe a
Just Identifier
"math")
        Identifier
"root"
        [ (Identifier
"index", ValType -> TypeSpec
One (ValType
TNone ValType -> ValType -> ValType
:|: ValType
TContent ValType -> ValType -> ValType
:|: ValType
TInteger ValType -> ValType -> ValType
:|: ValType
TRatio)),
          (Identifier
"radicand", ValType -> TypeSpec
One ValType
TContent)
        ],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"sqrt" [(Identifier
"radicand", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"cases" [(Identifier
"children", ValType -> TypeSpec
Many ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"lr" [(Identifier
"body", ValType -> TypeSpec
Many ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"abs" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"norm" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"floor" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"ceil" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      (Identifier
"mat", Val
matrixElement),
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"round" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"serif" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"sans" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"frak" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"mono" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"bb" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"cal" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"cal" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"upright" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"italic" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"bold" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"op" [(Identifier
"text", ValType -> TypeSpec
One ValType
TString)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"underline" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"overline" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (forall a. a -> Maybe a
Just Identifier
"math")
        Identifier
"underbrace"
        [ (Identifier
"body", ValType -> TypeSpec
One ValType
TContent),
          (Identifier
"annotation", ValType -> TypeSpec
One (ValType
TNone ValType -> ValType -> ValType
:|: ValType
TContent))
        ],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (forall a. a -> Maybe a
Just Identifier
"math")
        Identifier
"overbrace"
        [ (Identifier
"body", ValType -> TypeSpec
One ValType
TContent),
          (Identifier
"annotation", ValType -> TypeSpec
One (ValType
TNone ValType -> ValType -> ValType
:|: ValType
TContent))
        ],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (forall a. a -> Maybe a
Just Identifier
"math")
        Identifier
"underbracket"
        [ (Identifier
"body", ValType -> TypeSpec
One ValType
TContent),
          (Identifier
"annotation", ValType -> TypeSpec
One (ValType
TNone ValType -> ValType -> ValType
:|: ValType
TContent))
        ],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (forall a. a -> Maybe a
Just Identifier
"math")
        Identifier
"overbracket"
        [ (Identifier
"body", ValType -> TypeSpec
One ValType
TContent),
          (Identifier
"annotation", ValType -> TypeSpec
One (ValType
TNone ValType -> ValType -> ValType
:|: ValType
TContent))
        ],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"vec" [(Identifier
"children", ValType -> TypeSpec
Many ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (forall a. a -> Maybe a
Just Identifier
"math") Identifier
"alignpoint" [] -- not a real element, but needed internally
    ]
    forall a. Semigroup a => a -> a -> a
<> forall a b k. (a -> b) -> Map k a -> Map k b
M.map (Seq Content -> Val
VContent forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Seq a
Seq.singleton) Map Identifier Content
predefinedOperators
    forall a. Semigroup a => a -> a -> a
<> forall a b k. (a -> b) -> Map k a -> Map k b
M.map (Seq Content -> Val
VContent forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Seq a
Seq.singleton) Map Identifier Content
spaceConstants
    forall a. Semigroup a => a -> a -> a
<> [ (Identifier
"dif", Symbol -> Val
VSymbol (Text -> Bool -> [(Set Text, Text)] -> Symbol
Symbol Text
"d" Bool
False forall a. Monoid a => a
mempty)),
         (Identifier
"Dif", Symbol -> Val
VSymbol (Text -> Bool -> [(Set Text, Text)] -> Symbol
Symbol Text
"D" Bool
False forall a. Monoid a => a
mempty))
       ]

matrixElement :: Val
matrixElement :: Val
matrixElement = Maybe Identifier -> Map Identifier Val -> Function -> Val
VFunction (forall a. a -> Maybe a
Just Identifier
"mat") forall a. Monoid a => a
mempty forall a b. (a -> b) -> a -> b
$ (forall (m :: * -> *). Monad m => Arguments -> MP m Val)
-> Function
Function forall a b. (a -> b) -> a -> b
$ \Arguments
args -> do
  SourcePos
pos <- forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  -- get array args first
  let isArray :: Val -> Bool
isArray (VArray {}) = Bool
True
      isArray Val
_ = Bool
False
  let ([Val]
as, [Val]
bs) = forall a. (a -> Bool) -> [a] -> ([a], [a])
span Val -> Bool
isArray (Arguments -> [Val]
positional Arguments
args)
  let rows :: [Val]
rows =
        if forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Val]
bs
          then [Val]
as
          else [Val]
as forall a. [a] -> [a] -> [a]
++ [Vector Val -> Val
VArray (forall a. [a] -> Vector a
V.fromList [Val]
bs)]
  -- then any leftovers
  let fields :: Map Identifier Val
fields = forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(Identifier
"rows", Vector Val -> Val
VArray (forall a. [a] -> Vector a
V.fromList [Val]
rows))]
  forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a b. (a -> b) -> a -> b
$ Seq Content -> Val
VContent forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Seq a
Seq.singleton forall a b. (a -> b) -> a -> b
$ Identifier -> Maybe SourcePos -> Map Identifier Val -> Content
Elt Identifier
"math.mat" (forall a. a -> Maybe a
Just SourcePos
pos) Map Identifier Val
fields

spaceConstants :: M.Map Identifier Content
spaceConstants :: Map Identifier Content
spaceConstants =
  [ (Identifier
"thin", Text -> Content
Txt Text
"\8201"),
    (Identifier
"thick", Text -> Content
Txt Text
"\8197"),
    (Identifier
"med", Text -> Content
Txt Text
"\8287"),
    (Identifier
"quad", Text -> Content
Txt Text
"\8195")
  ]

predefinedOperators :: M.Map Identifier Content
predefinedOperators :: Map Identifier Content
predefinedOperators =
  forall k a. Ord k => [(k, a)] -> Map k a
M.fromList forall a b. (a -> b) -> a -> b
$
    forall a b. (a -> b) -> [a] -> [b]
map
      ( \Text
t ->
          ( Text -> Identifier
Identifier Text
t,
            Identifier -> Maybe SourcePos -> Map Identifier Val -> Content
Elt
              Identifier
"math.op"
              forall a. Maybe a
Nothing
              [(Identifier
"text", Text -> Val
VString Text
t), (Identifier
"limits", Bool -> Val
VBoolean Bool
True)]
          )
      )
      [ Text
"limsup",
        Text
"liminf",
        Text
"det",
        Text
"gcd",
        Text
"inf",
        Text
"lim",
        Text
"max",
        Text
"min",
        Text
"Pr",
        Text
"sup"
      ]
      forall a. [a] -> [a] -> [a]
++ forall a b. (a -> b) -> [a] -> [b]
map
        ( \Text
t ->
            ( Text -> Identifier
Identifier Text
t,
              Identifier -> Maybe SourcePos -> Map Identifier Val -> Content
Elt
                Identifier
"math.op"
                forall a. Maybe a
Nothing
                [(Identifier
"text", Text -> Val
VString Text
t), (Identifier
"limits", Bool -> Val
VBoolean Bool
False)]
            )
        )
        [ Text
"arccos",
          Text
"arcsin",
          Text
"arctan",
          Text
"arg",
          Text
"cos",
          Text
"cosh",
          Text
"cot",
          Text
"ctg",
          Text
"coth",
          Text
"csc",
          Text
"deg",
          Text
"dim",
          Text
"exp",
          Text
"hom",
          Text
"mod",
          Text
"ker",
          Text
"lg",
          Text
"ln",
          Text
"log",
          Text
"sec",
          Text
"sin",
          Text
"sinc",
          Text
"sinh",
          Text
"tan",
          Text
"tg",
          Text
"tanh"
        ]