diff --git a/crates/typst-library/src/compute/foundations.rs b/crates/typst-library/src/compute/foundations.rs index ecac3ffad..b76631138 100644 --- a/crates/typst-library/src/compute/foundations.rs +++ b/crates/typst-library/src/compute/foundations.rs @@ -218,9 +218,30 @@ pub fn eval( #[named] #[default(EvalMode::Code)] mode: EvalMode, + /// A scope of definitions that are made available. + /// + /// ```example + /// #eval("x + 1", scope: (x: 2)) \ + /// #eval( + /// "abc/xyz", + /// mode: "math", + /// scope: ( + /// abc: $a + b + c$, + /// xyz: $x + y + z$, + /// ), + /// ) + /// ``` + #[named] + #[default] + scope: Dict, /// The virtual machine. vm: &mut Vm, ) -> SourceResult { let Spanned { v: text, span } = source; - typst::eval::eval_string(vm.world(), &text, mode, span) + let dict = scope; + let mut scope = Scope::new(); + for (key, value) in dict { + scope.define(key, value); + } + typst::eval::eval_string(vm.world(), &text, span, mode, scope) } diff --git a/crates/typst/src/eval/mod.rs b/crates/typst/src/eval/mod.rs index 6f684a7bd..f72eeaa4f 100644 --- a/crates/typst/src/eval/mod.rs +++ b/crates/typst/src/eval/mod.rs @@ -145,8 +145,9 @@ pub fn eval( pub fn eval_string( world: Tracked, string: &str, - mode: EvalMode, span: Span, + mode: EvalMode, + scope: Scope, ) -> SourceResult { let mut root = match mode { EvalMode::Code => parse_code(string), @@ -179,6 +180,7 @@ pub fn eval_string( let id = FileId::detached(); let scopes = Scopes::new(Some(world.library())); let mut vm = Vm::new(vt, route.track(), id, scopes); + vm.scopes.scopes.push(scope); // Evaluate the code. let result = match mode { diff --git a/crates/typst/src/eval/scope.rs b/crates/typst/src/eval/scope.rs index f3e137151..b8d5b75a0 100644 --- a/crates/typst/src/eval/scope.rs +++ b/crates/typst/src/eval/scope.rs @@ -72,7 +72,11 @@ impl<'a> Scopes<'a> { #[cold] fn unknown_variable(var: &str) -> EcoString { if var.contains('-') { - eco_format!("unknown variable: {} - if you meant to use subtraction, try adding spaces around the minus sign.", var) + eco_format!( + "unknown variable: {} - if you meant to use subtraction, \ + try adding spaces around the minus sign.", + var + ) } else { eco_format!("unknown variable: {}", var) } @@ -171,7 +175,10 @@ impl Slot { match self.kind { Kind::Normal => Ok(&mut self.value), Kind::Captured => { - bail!("variables from outside the function are read-only and cannot be modified") + bail!( + "variables from outside the function are \ + read-only and cannot be modified" + ) } } } diff --git a/tests/ref/compute/foundations.png b/tests/ref/compute/foundations.png new file mode 100644 index 000000000..5d6ba7441 Binary files /dev/null and b/tests/ref/compute/foundations.png differ diff --git a/tests/typ/compute/foundations.typ b/tests/typ/compute/foundations.typ index 9c7b13cab..3da2e6019 100644 --- a/tests/typ/compute/foundations.typ +++ b/tests/typ/compute/foundations.typ @@ -73,7 +73,17 @@ #test(type(10 / 3), "float") --- -#eval("[_Hello" + " World!_]") +// Test the eval function. +#test(eval("1 + 2"), 3) +#test(eval("1 + x", scope: (x: 3)), 4) +#test(eval("let x = x + 1; x + 1", scope: (x: 1)), 3) + +--- +// Test evaluation in other modes. +// Ref: true +#eval("[_Hello" + " World!_]") \ +#eval("_Hello" + " World!_", mode: "markup") \ +#eval("RR_1^NN", mode: "math", scope: (RR: math.NN, NN: math.RR)) --- // Error: 7-12 expected identifier