Support scope argument for eval

This commit is contained in:
Laurenz 2023-07-18 21:53:42 +02:00
parent f52c39c388
commit 803ae9309f
5 changed files with 45 additions and 5 deletions

View File

@ -218,9 +218,30 @@ pub fn eval(
#[named] #[named]
#[default(EvalMode::Code)] #[default(EvalMode::Code)]
mode: EvalMode, 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. /// The virtual machine.
vm: &mut Vm, vm: &mut Vm,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
let Spanned { v: text, span } = source; 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)
} }

View File

@ -145,8 +145,9 @@ pub fn eval(
pub fn eval_string( pub fn eval_string(
world: Tracked<dyn World + '_>, world: Tracked<dyn World + '_>,
string: &str, string: &str,
mode: EvalMode,
span: Span, span: Span,
mode: EvalMode,
scope: Scope,
) -> SourceResult<Value> { ) -> SourceResult<Value> {
let mut root = match mode { let mut root = match mode {
EvalMode::Code => parse_code(string), EvalMode::Code => parse_code(string),
@ -179,6 +180,7 @@ pub fn eval_string(
let id = FileId::detached(); let id = FileId::detached();
let scopes = Scopes::new(Some(world.library())); let scopes = Scopes::new(Some(world.library()));
let mut vm = Vm::new(vt, route.track(), id, scopes); let mut vm = Vm::new(vt, route.track(), id, scopes);
vm.scopes.scopes.push(scope);
// Evaluate the code. // Evaluate the code.
let result = match mode { let result = match mode {

View File

@ -72,7 +72,11 @@ impl<'a> Scopes<'a> {
#[cold] #[cold]
fn unknown_variable(var: &str) -> EcoString { fn unknown_variable(var: &str) -> EcoString {
if var.contains('-') { 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 { } else {
eco_format!("unknown variable: {}", var) eco_format!("unknown variable: {}", var)
} }
@ -171,7 +175,10 @@ impl Slot {
match self.kind { match self.kind {
Kind::Normal => Ok(&mut self.value), Kind::Normal => Ok(&mut self.value),
Kind::Captured => { 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"
)
} }
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -73,7 +73,17 @@
#test(type(10 / 3), "float") #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 // Error: 7-12 expected identifier