diff options
Diffstat (limited to 'src/model/eval.rs')
| -rw-r--r-- | src/model/eval.rs | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/src/model/eval.rs b/src/model/eval.rs index 1fbf4125..6e118f8a 100644 --- a/src/model/eval.rs +++ b/src/model/eval.rs @@ -16,7 +16,9 @@ use crate::diag::{ bail, error, At, SourceError, SourceResult, StrResult, Trace, Tracepoint, }; use crate::syntax::ast::AstNode; -use crate::syntax::{ast, Source, SourceId, Span, Spanned, SyntaxKind, SyntaxNode}; +use crate::syntax::{ + ast, parse_code, Source, SourceId, Span, Spanned, SyntaxKind, SyntaxNode, +}; use crate::util::PathExt; use crate::World; @@ -63,6 +65,40 @@ pub fn eval( Ok(Module::new(name).with_scope(vm.scopes.top).with_content(result?)) } +/// Evaluate a string as code and return the resulting value. +/// +/// Everything in the output is associated with the given `span`. +#[comemo::memoize] +pub fn eval_code_str( + world: Tracked<dyn World>, + text: &str, + span: Span, +) -> SourceResult<Value> { + let mut root = parse_code(text); + root.synthesize(span); + + let errors = root.errors(); + if !errors.is_empty() { + return Err(Box::new(errors)); + } + + let id = SourceId::detached(); + let library = world.library(); + let scopes = Scopes::new(Some(library)); + let route = Route::default(); + let mut tracer = Tracer::default(); + let mut vm = Vm::new(world, route.track(), tracer.track_mut(), id, scopes, 0); + let code = root.cast::<ast::Code>().unwrap(); + let result = code.eval(&mut vm); + + // Handle control flow. + if let Some(flow) = vm.flow { + bail!(flow.forbidden()); + } + + result +} + /// A virtual machine. /// /// Holds the state needed to [evaluate](eval) Typst sources. A new |
