{-# 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 =
  [(Identifier, Val)] -> Map Identifier Val
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
    [ Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement
        (Identifier -> Maybe Identifier
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
        (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"math") Identifier
"class" [(Identifier
"class", ValType -> TypeSpec
One ValType
TString),
                                         (Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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
        (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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
        (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"math") Identifier
"display" [(Identifier
"content", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"math") Identifier
"inline" [(Identifier
"content", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"math") Identifier
"script" [(Identifier
"content", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"math") Identifier
"sscript" [(Identifier
"content", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"math") Identifier
"mid" [(Identifier
"body", ValType -> TypeSpec
One ValType
TContent)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"math") Identifier
"op" [(Identifier
"text", ValType -> TypeSpec
One ValType
TAny)],
      Maybe Identifier
-> Identifier -> [(Identifier, TypeSpec)] -> (Identifier, Val)
makeElement (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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
        (Identifier -> Maybe Identifier
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
        (Identifier -> Maybe Identifier
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
        (Identifier -> Maybe Identifier
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
        (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
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 (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"math") Identifier
"alignpoint" [] -- not a real element, but needed internally
    ]
    Map Identifier Val -> Map Identifier Val -> Map Identifier Val
forall a. Semigroup a => a -> a -> a
<> (Content -> Val) -> Map Identifier Content -> Map Identifier Val
forall a b k. (a -> b) -> Map k a -> Map k b
M.map (Seq Content -> Val
VContent (Seq Content -> Val) -> (Content -> Seq Content) -> Content -> Val
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Content -> Seq Content
forall a. a -> Seq a
Seq.singleton) Map Identifier Content
predefinedOperators
    Map Identifier Val -> Map Identifier Val -> Map Identifier Val
forall a. Semigroup a => a -> a -> a
<> (Content -> Val) -> Map Identifier Content -> Map Identifier Val
forall a b k. (a -> b) -> Map k a -> Map k b
M.map (Seq Content -> Val
VContent (Seq Content -> Val) -> (Content -> Seq Content) -> Content -> Val
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Content -> Seq Content
forall a. a -> Seq a
Seq.singleton) Map Identifier Content
spaceConstants
    Map Identifier Val -> Map Identifier Val -> Map Identifier Val
forall a. Semigroup a => a -> a -> a
<> [ (Identifier
"dif", Symbol -> Val
VSymbol (Text -> Bool -> [(Set Text, Text)] -> Symbol
Symbol Text
"d" Bool
False [(Set Text, Text)]
forall a. Monoid a => a
mempty)),
         (Identifier
"Dif", Symbol -> Val
VSymbol (Text -> Bool -> [(Set Text, Text)] -> Symbol
Symbol Text
"D" Bool
False [(Set Text, Text)]
forall a. Monoid a => a
mempty))
       ]

matrixElement :: Val
matrixElement :: Val
matrixElement = Maybe Identifier -> Map Identifier Val -> Function -> Val
VFunction (Identifier -> Maybe Identifier
forall a. a -> Maybe a
Just Identifier
"mat") Map Identifier Val
forall a. Monoid a => a
mempty (Function -> Val) -> Function -> Val
forall a b. (a -> b) -> a -> b
$ (forall (m :: * -> *). Monad m => Arguments -> MP m Val)
-> Function
Function ((forall (m :: * -> *). Monad m => Arguments -> MP m Val)
 -> Function)
-> (forall (m :: * -> *). Monad m => Arguments -> MP m Val)
-> Function
forall a b. (a -> b) -> a -> b
$ \Arguments
args -> do
  SourcePos
pos <- ParsecT [Markup] (EvalState m) m SourcePos
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) = (Val -> Bool) -> [Val] -> ([Val], [Val])
forall a. (a -> Bool) -> [a] -> ([a], [a])
span Val -> Bool
isArray (Arguments -> [Val]
positional Arguments
args)
  let rows :: [Val]
rows =
        if [Val] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Val]
bs
          then [Val]
as
          else [Val]
as [Val] -> [Val] -> [Val]
forall a. [a] -> [a] -> [a]
++ [Vector Val -> Val
VArray ([Val] -> Vector Val
forall a. [a] -> Vector a
V.fromList [Val]
bs)]
  -- then any leftovers
  let fields :: Map Identifier Val
fields = [(Identifier, Val)] -> Map Identifier Val
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList [(Identifier
"rows", Vector Val -> Val
VArray ([Val] -> Vector Val
forall a. [a] -> Vector a
V.fromList [Val]
rows))]
  Val -> MP m Val
forall a. a -> ParsecT [Markup] (EvalState m) m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Val -> MP m Val) -> Val -> MP m Val
forall a b. (a -> b) -> a -> b
$ Seq Content -> Val
VContent (Seq Content -> Val) -> (Content -> Seq Content) -> Content -> Val
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Content -> Seq Content
forall a. a -> Seq a
Seq.singleton (Content -> Val) -> Content -> Val
forall a b. (a -> b) -> a -> b
$ Identifier -> Maybe SourcePos -> Map Identifier Val -> Content
Elt Identifier
"math.mat" (SourcePos -> Maybe SourcePos
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"),
    (Identifier
"wide", Text -> Content
Txt Text
"\8195\8195")
  ]

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