summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2023-07-18 21:18:35 +0200
committerLaurenz <laurmaedje@gmail.com>2023-07-18 21:53:39 +0200
commitf52c39c388c2e3e38be0022fda6d78b12f0a9544 (patch)
tree27d25df5cab59031a8d9d9eb4a26731de2f71bc2
parentf5953887c9ae0b40a0c3e0ab516daf425c5a598c (diff)
Support different modes for `eval`
-rw-r--r--crates/typst-library/src/compute/foundations.rs15
-rw-r--r--crates/typst/src/eval/mod.rs36
2 files changed, 43 insertions, 8 deletions
diff --git a/crates/typst-library/src/compute/foundations.rs b/crates/typst-library/src/compute/foundations.rs
index f83d71a0..ecac3ffa 100644
--- a/crates/typst-library/src/compute/foundations.rs
+++ b/crates/typst-library/src/compute/foundations.rs
@@ -1,3 +1,5 @@
+use typst::eval::EvalMode;
+
use crate::prelude::*;
/// Determines the type of a value.
@@ -196,7 +198,7 @@ pub fn assert_ne(
/// ```example
/// #eval("1 + 1") \
/// #eval("(1, 2, 3, 4)").len() \
-/// #eval("[*Strong text*]")
+/// #eval("*Markup!*", mode: "markup") \
/// ```
///
/// Display: Evaluate
@@ -207,9 +209,18 @@ pub fn eval(
///
/// The code in the string cannot interact with the file system.
source: Spanned<String>,
+ /// The syntactical mode in which the string is parsed.
+ ///
+ /// ```example
+ /// #eval("= Heading", mode: "markup")
+ /// #eval("1_2^3", mode: "math")
+ /// ```
+ #[named]
+ #[default(EvalMode::Code)]
+ mode: EvalMode,
/// The virtual machine.
vm: &mut Vm,
) -> SourceResult<Value> {
let Spanned { v: text, span } = source;
- typst::eval::eval_string(vm.world(), &text, span)
+ typst::eval::eval_string(vm.world(), &text, mode, span)
}
diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs
index 33c5f1a2..6f684a7b 100644
--- a/crates/typst/src/eval/mod.rs
+++ b/crates/typst/src/eval/mod.rs
@@ -74,8 +74,8 @@ use crate::model::{
};
use crate::syntax::ast::{self, AstNode};
use crate::syntax::{
- parse_code, FileId, PackageSpec, PackageVersion, Source, Span, Spanned, SyntaxKind,
- SyntaxNode,
+ parse, parse_code, parse_math, FileId, PackageSpec, PackageVersion, Source, Span,
+ Spanned, SyntaxKind, SyntaxNode,
};
use crate::World;
@@ -144,10 +144,16 @@ pub fn eval(
#[comemo::memoize]
pub fn eval_string(
world: Tracked<dyn World + '_>,
- code: &str,
+ string: &str,
+ mode: EvalMode,
span: Span,
) -> SourceResult<Value> {
- let mut root = parse_code(code);
+ let mut root = match mode {
+ EvalMode::Code => parse_code(string),
+ EvalMode::Markup => parse(string),
+ EvalMode::Math => parse_math(string),
+ };
+
root.synthesize(span);
let errors = root.errors();
@@ -175,8 +181,15 @@ pub fn eval_string(
let mut vm = Vm::new(vt, route.track(), id, scopes);
// Evaluate the code.
- let code = root.cast::<ast::Code>().unwrap();
- let result = code.eval(&mut vm);
+ let result = match mode {
+ EvalMode::Code => root.cast::<ast::Code>().unwrap().eval(&mut vm),
+ EvalMode::Markup => {
+ root.cast::<ast::Markup>().unwrap().eval(&mut vm).map(Value::Content)
+ }
+ EvalMode::Math => {
+ root.cast::<ast::Math>().unwrap().eval(&mut vm).map(Value::Content)
+ }
+ };
// Handle control flow.
if let Some(flow) = vm.flow {
@@ -186,6 +199,17 @@ pub fn eval_string(
result
}
+/// In which mode to evaluate a string.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, Cast)]
+pub enum EvalMode {
+ /// Evaluate as code, as after a hashtag.
+ Code,
+ /// Evaluate as markup, like in a Typst file.
+ Markup,
+ /// Evaluate as math, as in an equation.
+ Math,
+}
+
/// A virtual machine.
///
/// Holds the state needed to [evaluate](eval) Typst sources. A new