Skip to content

Commit

Permalink
Allow defined identifiers to override math defaults.
Browse files Browse the repository at this point in the history
Closes #51.

Previously we evaluated all math in a special environment that
shadowed any user-defined functions with the same-named functions
from the math or sym modules.

This change gives user-defined identifiers priority over
the math defaults, allowing things like `bb` to be overridden.

API changes:

Typst.Types: EvalState now has two new fields,
`evalMathIdentifiers` and `evalStandardIdentifiers`.
`evalIdentifiers` is now just for user-defined identifiers.
  • Loading branch information
jgm committed Aug 7, 2024
1 parent 9df72ef commit 64e41d8
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 40 deletions.
14 changes: 6 additions & 8 deletions src/Typst/Evaluate.hs
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,10 @@ evaluateTypst operations =

initialEvalState :: EvalState m
initialEvalState =
emptyEvalState { evalIdentifiers = [(BlockScope, standardModule')] }
emptyEvalState { evalIdentifiers = [(BlockScope, mempty)]
, evalMathIdentifiers = [(BlockScope, mathModule <> symModule)]
, evalStandardIdentifiers = [(BlockScope, standardModule')]
}
where
standardModule' = M.insert "eval" evalFunction standardModule
evalFunction = makeFunction $ do
Expand Down Expand Up @@ -239,12 +242,9 @@ pElt = do
[("level", VInteger (fromIntegral level))]
}
Equation display ms -> inBlock BlockScope $ do
importModule mathModule
importModule symModule
oldMath <- evalMath <$> getState
updateState $ \st -> st {evalMath = True}
content <- pInnerContents ms
updateState $ \st -> st {evalMath = oldMath}
element
"equation"
Arguments
Expand All @@ -254,7 +254,7 @@ pElt = do
[ ("block", VBoolean display),
("numbering", VNone)
]
}
} <* updateState (\st -> st {evalMath = oldMath})
MFrac numexp denexp -> do
let handleParens (MGroup (Just "(") (Just ")") xs) = MGroup Nothing Nothing xs
handleParens x = x
Expand Down Expand Up @@ -1098,9 +1098,7 @@ addIdentifier ident val = do
case identifiers of
[] -> fail "Empty evalIdentifiers"
((s, i) : is) -> updateState $ \st ->
st
{ evalIdentifiers = (s, M.insert ident val i) : is
}
st { evalIdentifiers = (s, M.insert ident val i) : is }

updateIdentifier :: Monad m => Identifier -> Val -> MP m ()
updateIdentifier ident val = do
Expand Down
5 changes: 4 additions & 1 deletion src/Typst/Module/Standard.hs
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,10 @@ applyPureFunction (Function f) vals =

initialEvalState :: MonadFail m => EvalState m
initialEvalState =
emptyEvalState { evalIdentifiers = [(BlockScope, standardModule)] }
emptyEvalState { evalIdentifiers = [(BlockScope, mempty)]
, evalMathIdentifiers = [(BlockScope, mathModule <> symModule)]
, evalStandardIdentifiers = [(BlockScope, standardModule)]
}

-- mDigitsRev, mDigits from the unmaintained digits package
-- https://hackage.haskell.org/package/digits-0.3.1
Expand Down
18 changes: 17 additions & 1 deletion src/Typst/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,12 @@ data Operations m =
data EvalState m = EvalState
{ evalIdentifiers :: [(Scope, M.Map Identifier Val)],
-- first item is current block, then superordinate block, etc.
-- The standard identifiers and the identifiers that
-- are imported by default into math contexts are special,
-- since both can be overridden by user-defined identifiers.
-- So, we store them separately.
evalStandardIdentifiers :: [(Scope, M.Map Identifier Val)],
evalMathIdentifiers :: [(Scope, M.Map Identifier Val)],
evalCounters :: M.Map Counter Integer,
evalMath :: Bool,
evalShowRules :: [ShowRule],
Expand All @@ -618,6 +624,8 @@ data EvalState m = EvalState
emptyEvalState :: EvalState m
emptyEvalState = EvalState
{ evalIdentifiers = [],
evalStandardIdentifiers = [],
evalMathIdentifiers = [],
evalCounters = mempty,
evalMath = False,
evalShowRules = [],
Expand Down Expand Up @@ -977,4 +985,12 @@ lookupIdentifier ident = do
go ((_, i) : is) = case M.lookup ident i of
Just v -> pure v
Nothing -> go is
getState >>= go . evalIdentifiers
identifiers <- evalIdentifiers <$> getState
mathIdentifiers <- evalMathIdentifiers <$> getState
standardIdentifiers <- evalStandardIdentifiers <$> getState
math <- evalMath <$> getState
go $ case identifiers of
-- in math mode, we insert the sym and math modules right before
-- the final module (standard module)
(_:_) | math -> identifiers ++ mathIdentifiers ++ standardIdentifiers
_ -> identifiers ++ standardIdentifiers
60 changes: 30 additions & 30 deletions test/out/bugs/math-realize-02.out
Original file line number Diff line number Diff line change
Expand Up @@ -341,21 +341,21 @@ document(body: { text(body: [
text(body: [Inline ]),
math.equation(block: false,
body: { text(body: [2]),
text(body: [|]),
text(body: [(]),
text(body: [α]),
text(body: [,]),
math.lr(body: ({ [(],
text(body: [M]),
text(body: [+]),
math.equation(block: false,
body: { text(body: [a]),
math.attach(b: none,
base: text(body: [b]),
t: text(body: [2])) },
numbering: none),
[)] })),
text(body: [)]) },
math.equation(block: true,
body: { text(body: [α]),
math.attach(b: none,
base: math.lr(body: ({ [(],
text(body: [M]),
text(body: [+]),
math.equation(block: false,
body: { text(body: [a]),
math.attach(b: none,
base: text(body: [b]),
t: text(body: [2])) },
numbering: none),
[)] })),
t: text(body: [2])) },
numbering: none) },
numbering: none),
text(body: [.]),
parbreak(),
Expand Down Expand Up @@ -409,21 +409,21 @@ document(body: { text(body: [
]),
math.equation(block: true,
body: { text(body: [2]),
text(body: [|]),
text(body: [(]),
text(body: [α]),
text(body: [,]),
math.lr(body: ({ [(],
text(body: [M]),
text(body: [+]),
math.equation(block: false,
body: { text(body: [a]),
math.attach(b: none,
base: text(body: [b]),
t: text(body: [2])) },
numbering: none),
[)] })),
text(body: [)]) },
math.equation(block: true,
body: { text(body: [α]),
math.attach(b: none,
base: math.lr(body: ({ [(],
text(body: [M]),
text(body: [+]),
math.equation(block: false,
body: { text(body: [a]),
math.attach(b: none,
base: text(body: [b]),
t: text(body: [2])) },
numbering: none),
[)] })),
t: text(body: [2])) },
numbering: none) },
numbering: none),
text(body: [
]),
Expand Down

0 comments on commit 64e41d8

Please sign in to comment.