1use comemo::Tracked;
2use ecow::eco_format;
3use typst_library::World;
4use typst_library::diag::{HintedString, warning};
5use typst_library::engine::Engine;
6use typst_library::foundations::{Binding, Context, IntoValue, Scopes, Value};
7use typst_syntax::Span;
8use typst_syntax::ast::{self, AstNode};
9
10use crate::FlowEvent;
11
12pub struct Vm<'a> {
17 pub engine: Engine<'a>,
19 pub flow: Option<FlowEvent>,
21 pub scopes: Scopes<'a>,
23 pub inspected: Option<Span>,
26 pub context: Tracked<'a, Context<'a>>,
28}
29
30impl<'a> Vm<'a> {
31 pub fn new(
33 engine: Engine<'a>,
34 context: Tracked<'a, Context<'a>>,
35 scopes: Scopes<'a>,
36 target: Span,
37 ) -> Self {
38 let inspected = target.id().and_then(|id| engine.traced.get(id));
39 Self { engine, context, flow: None, scopes, inspected }
40 }
41
42 pub fn world(&self) -> Tracked<'a, dyn World + 'a> {
44 self.engine.world
45 }
46
47 pub fn define(&mut self, var: ast::Ident, value: impl IntoValue) {
51 self.bind(var, Binding::new(value, var.span()));
52 }
53
54 pub fn bind(&mut self, var: ast::Ident, binding: Binding) {
59 self.trace_at(var.span(), binding.read());
60
61 if var.get() == "is" {
63 self.engine.sink.warn(warning!(
64 var.span(),
65 "`is` will likely become a keyword in future versions and will \
66 not be allowed as an identifier";
67 hint: "rename this variable to avoid future errors";
68 hint: "try `is_` instead";
69 ));
70 }
71
72 self.scopes.top.bind(var.get().clone(), binding);
73 }
74
75 pub fn trace_at(&mut self, span: Span, value: &Value) {
79 if self.inspected == Some(span) {
80 self.trace(value.clone());
81 }
82 }
83
84 #[cold]
87 pub fn trace(&mut self, value: Value) {
88 self.engine
89 .sink
90 .value(value, self.context.styles().ok().map(|s| s.to_map()));
91 }
92}
93
94pub fn hint_if_shadowed_std(
96 vm: &mut Vm,
97 callee: &ast::Expr,
98 mut err: HintedString,
99) -> HintedString {
100 if let ast::Expr::Ident(ident) = callee {
101 let ident = ident.get();
102 if vm.scopes.check_std_shadowed(ident) {
103 err.hint(eco_format!(
104 "use `std.{ident}` to access the shadowed standard library function",
105 ));
106 }
107 }
108 err
109}