{-# 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
"underparen" [(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
"undershell" [(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
"overparen" [(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
"overshell" [(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
"stretch" [(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
  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 (VArray {}) = Bool
True
      isArray Val
_ = Bool
False
  let (as, bs) = span isArray (positional args)
  let 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
  fields <- M.insert "rows" (VArray (V.fromList rows)) <$> argsToFields [] args
  pure $ VContent . Seq.singleton $ Elt "math.mat" (Just pos) 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)]
          )
      )
      [ Item [Text]
Text
"limsup",
        Item [Text]
Text
"liminf",
        Item [Text]
Text
"det",
        Item [Text]
Text
"gcd",
        Item [Text]
Text
"inf",
        Item [Text]
Text
"lim",
        Item [Text]
Text
"max",
        Item [Text]
Text
"min",
        Item [Text]
Text
"Pr",
        Item [Text]
Text
"sup",
        Item [Text]
Text
"id",
        Item [Text]
Text
"im",
        Item [Text]
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)]
            )
        )
        [ Item [Text]
Text
"arccos",
          Item [Text]
Text
"arcsin",
          Item [Text]
Text
"arctan",
          Item [Text]
Text
"arg",
          Item [Text]
Text
"cos",
          Item [Text]
Text
"cosh",
          Item [Text]
Text
"cot",
          Item [Text]
Text
"csch",
          Item [Text]
Text
"ctg",
          Item [Text]
Text
"coth",
          Item [Text]
Text
"csc",
          Item [Text]
Text
"deg",
          Item [Text]
Text
"dim",
          Item [Text]
Text
"exp",
          Item [Text]
Text
"hom",
          Item [Text]
Text
"mod",
          Item [Text]
Text
"ker",
          Item [Text]
Text
"lcm",
          Item [Text]
Text
"lg",
          Item [Text]
Text
"ln",
          Item [Text]
Text
"log",
          Item [Text]
Text
"sec",
          Item [Text]
Text
"sech",
          Item [Text]
Text
"sin",
          Item [Text]
Text
"sinc",
          Item [Text]
Text
"sinh",
          Item [Text]
Text
"tan",
          Item [Text]
Text
"tg",
          Item [Text]
Text
"tanh"
        ]