# Accumulator

As noted in the overview, one uses an accumulator to collect information about sequentially numbered sections, cross-references, tables of content, etc., then uses a second accumulator to render the source text with these features. Accumulators are made of up of reducers and folds:

```
type alias Reducer a b : a -> b -> b
List.foldl : (a -> b -> b ) -> b -> List a -> b
```

A `Reducer` is a name for the type of the first argument of a fold. Consider a reducer of the form

```
Reducer state a b  = a -> (state, List b) -> (state, List b)
```

It fits into a fold of the form

```
Reducer state a b  -> (state, List b) -> List a -> (state, List b)
```

Let `transform` have type `StateReducer state a b`. Define

```
acc transformer state_ inputList =
  List.foldl transformer (state_, []) inputList
```

The type of this function is

```
Accumulator state a b = state -> List a -> (state, List b)
```

To restate in plainer English, an `Accumulator state a b` takes as input a `State a b` and a `List a` and returns a tuple consisting of an updated `State a b` and another list, one of type `List b`.

## Accumulator.parse

Let us discuss the accumulators used in MiniLatex. The first of these is `Accumulator.parse`. Its function is to take a `LatexState` and a list of paragraphs, i.e., a `List String`, and produce an updated `LatexState` and a `List (List LatexExpression)`. Each element of the latter is a `List LatexExpression` representing the application of the MiniLatex parser to a paragraph.

```
Accumulator.parse :
    LatexState
    -> List String
    -> ( LatexState, List (List LatexExpression) )
Accumulator.parse latexState paragraphs =
    paragraphs
        |> List.foldl parseReducer ( latexState, [] )
```

The `Accumulator.parse` function applies a `List.foldl` to a pair consisting of an initial `LatexState` and an empty list using a `parseReducer`. The latter is defined as follows:

```
parseReducer :
    String
    -> ( LatexState, List (List LatexExpression) )
    -> ( LatexState, List (List LatexExpression) )
parseReducer inputString ( latexState, inputList ) =
    let
        parsedInput =
            Parser.parse inputString

        newLatexState =
            latexStateReducer parsedInput latexState
    in
    ( newLatexState, inputList ++ [ parsedInput ] )
```

The `parseReducer` takes as input a string, representing a logical paragraph of source text, and a pair consisting of a `LatexState` and a `List (List LatexExpression`. It parses the string and computes a new `LatexState` using `latexStateReducer`:

```
latexStateReducer : List LatexExpression -> LatexState -> LatexState
```

We discuss this function later on. The return value of the `parseReducer` is a pair consisting of the new `LatexState` and inputList with the parsedInput appended.

## Accumulator.render

`Accumulator.render renderer` is an accumulator which takes a `LatexState` and a `List (List LatexExpression)` as input, and produces a new `LatexState` and `List a` as output. The nature of `a` depends on the `renderer` function used:

```
Accumulator.render :
    (LatexState -> List LatexExpression -> a)
    -> LatexState
    -> List (List LatexExpression)
    -> ( LatexState, List a )
Accumulator.render renderer latexState paragraphs =
    paragraphs
        |> List.foldl (renderReducer renderer) ( latexState, [] )
```

The expression `renderReducer renderer` is a reducer of type

```
 List LatexExpression  -> ( LatexState, List a ) -> ( LatexState, List a )
```

It operates as follows:

1. Compute a new `LatexState` by applying `latexStateReducer` to (a) the given list of `LatexExpressions` and (b) the `LatexState` coming from the first element of the second argument, a tuple of type `(LatexState, List a)`
2. Apply the `renderer` to the new state computed in the previous step and the `List LatexExpression` given by the first argument.
3. Return a tuple consisting of the updated `LatexState` and the `inputList` with the newly rendered text appended.

```
renderReducer :
    (LatexState -> List LatexExpression -> a)
    -> List LatexExpression
    -> ( LatexState, List a )
    -> ( LatexState, List a )
renderReducer renderer listLatexExpression ( latexState, inputList ) =
    let
        newLatexState =
            latexStateReducer listLatexExpression latexState

        renderedInput =
            renderer newState listLatexExpression
    in
    ( newLatexState, inputList ++ [ renderedInput ] )
```

## LatexStateReducer

The purpose of the `latexStateReducer` is to update a given `LatexState` using the information contained in a `List LatexExpression`, i.e., the parse result of a paragraph.

```
latexStateReducer : List LatexExpression -> LatexState -> LatexState
latexStateReducer parsedParagraph latexState =
    let
        theInfo =
            parsedParagraph
                |> List.head
                |> Maybe.map info
                |> Maybe.withDefault (LatexInfo "null" "null" [] [])
    in
    (latexStateReducerDispatcher  theInfo) theInfo latexState
```

This a fairly complex reducer. In brief, it looks at the first `LatexExpression` in the `List LatexExpression` representing a given paragraph, then uses the function `info` to compute a record, `theInfo`, which extracts certain information from the paragraph. For example, if the paragraph is `\section{Introduction}`, the `theInfo` will contatin fields `name = section` and `typ = macro`. The call `latexStateReducerDispatcher theInfo` uses a dictionary lookup to produce a function of type `LatexInfo -> LatexState -> LatexState` from `theInfo`. Therefore the value of the expression

```
(latexStateReducerDispatcher theInfo) theInfo latexStae
```

is of type `LatexState`, in accord with what one reads from the type annotation of `latexStateReducer parsedParagraph latexState`.

Let's see how this works in a simple example:

```
> import MiniLatex.Parser exposing(..)
> import Parser exposing(run)
> import MiniLatex.Accumulator exposing(info)
> result = run latexExpression "\\section{foo}"
Ok (Macro "section" [] [LatexList [LXString "foo"]])
> expression = Macro "section" [] [LatexList [LXString "foo"]]
> theInfo = info expression
    { name = "section", options = [], typ = "macro", value = [LatexList [LXString "Foo"]] }
    : MiniLatex.Accumulator.LatexInfo
```

Now the dispatcher looks like this

```
latexStateReducerDispatcher : LatexInfo -> (LatexInfo -> LatexState -> LatexState)
latexStateReducerDispatcher theInfo =
    case Dict.get ( theInfo.typ, theInfo.name ) latexStateReducerDict of
        Just f ->
            f

        Nothing ->
            \latexInfo latexState -> latexState
```

where the dictionary has type

```
latexStateReducerDict : Dict.Dict ( String, String ) (LatexInfo -> LatexState -> LatexState)
```

If the key given by `theInfo` is not in the `latexStateReducerDict`, projection of the arguments to `LatexState` is returned. In the case at hand, `theInfo` has fields `name = "section"` and `typ = "macro"`, and the function returned by the dictionary is `SRH.updateSectionNumber x y`. Here `SRH` is an alias of the `StateReducerHelper` module. Referring to that module, we find that

```
updateSectionNumber : LatexInfo -> LatexState -> LatexState
updateSectionNumber info latexState =
    let
        label =
            getCounter "s1" latexState |> (\x -> x + 1) |> String.fromInt
    in
        latexState
            |> incrementCounter "s1"
            |> updateCounter "s2" 0
            |> updateCounter "s3" 0
            |> addSection (PT.unpackString info.value) label 1
```

Thus `updateSectionNumber` increments the "s1" counter in the `latexState` and sets the other section counters to zero. The `addSection` function, listed below, adds the current section to the table of contents field of the `LatexState`:

```
LatexState.addSection : String -> String -> Int -> LatexState -> LatexState
LatexState.addSection sectionName label level latexState =
    let
        newEntry =
            TocEntry sectionName label level

        toc =
            latexState.tableOfContents ++ [ newEntry ]
    in
    { latexState | tableOfContents = toc }
```

We will not go down the rabbit hole any further, but you get the general idea. The `LatexState` holds counters, the table of contents, cross references, and a general-purpose dictionaray. To add new abilities to `MiniLatex`, one can add new entries to `latexStateReducerDict` or new fields to `LatexState`.

```
type alias LatexState =
    { counters : Counters
    , crossReferences : CrossReferences
    , tableOfContents : TableOfContents
    , dictionary : Dictionary
    }
```

### Example: rendering a section

To conclude this discussion, we exhibit the render for sections: s

```
renderSection : LatexState -> List LatexExpression -> Html msg
renderSection latexState args =
    let
        sectionName =
            MiniLatex.Render.renderArg 0 latexState args

        s1 =
            getCounter "s1" latexState

        label =
            if s1 > 0 then
                String.fromInt s1 ++ " "

            else
                ""

        ref =
            idPhrase "section" sectionName
    in
    Html.h2 (headingStyle ref 24) [ Html.text <| label ++ sectionName ]
```

### Appendix: the latexStateReducerDict

```
latexStateReducerDict : Dict.Dict ( String, String ) (LatexInfo -> LatexState -> LatexState)
latexStateReducerDict =
    Dict.fromList
        [ ( ( "macro", "setcounter" ), \x y -> SRH.setSectionCounters x y )
        , ( ( "macro", "section" ), \x y -> SRH.updateSectionNumber x y )
        , ( ( "macro", "subsection" ), \x y -> SRH.updateSubsectionNumber x y )
        , ( ( "macro", "subsubsection" ), \x y -> SRH.updateSubsubsectionNumber x y )
        , ( ( "macro", "title" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "author" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "date" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "email" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "host" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "setclient" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "setdocid" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "macro", "revision" ), \x y -> SRH.setDictionaryItemForMacro x y )
        , ( ( "env", "theorem" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "proposition" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "lemma" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "definition" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "corollary" ), \x y -> SRH.setTheoremNumber x y )
        , ( ( "env", "equation" ), \x y -> SRH.setEquationNumber x y )
        , ( ( "env", "align" ), \x y -> SRH.setEquationNumber x y )
        , ( ( "smacro", "bibitem" ), \x y -> SRH.setBibItemXRef x y )
        ]
```

## Some conclusions

The reliance of `Accumulator.parse` and `Accumulator.render` on the `LatexState` record, as well as the `latexStateReducerDict` for dispatching calls to `latexStateReducer`, makes it very easy to add new features, e.g., new macros and environments whose rendering requires a computed state. Moreover, it is not hard to add fields to `LatexState` in order to add further new features. Indeed, the first version of `LatexInfo` had only a `counters` field. Others were added later as the scope of MiniLatex grew.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://minilatex.gitbook.io/project/accumulator.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
