    {-# 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
    "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
    "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
    "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
    TString)],
          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")
      ]

    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"
          ]
          [(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]
    "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]
    "sin",
              Text
    Item [Text]
    "sinc",
              Text
    Item [Text]
    "sinh",
              Text
    Item [Text]
    "tan",
              Text
    Item [Text]
    "tg",
              Text
    Item [Text]
    "tanh"
            ]