Ian Wrzesinski dcb130bd71
Add a warning for is to anticipate using it as a keyword (#5229)
Co-authored-by: Malo <57839069+MDLC01@users.noreply.github.com>
2024-10-31 11:55:31 +00:00

72 lines
2.3 KiB
Rust

use comemo::Tracked;
use typst_library::diag::warning;
use typst_library::engine::Engine;
use typst_library::foundations::{Context, IntoValue, Scopes, Value};
use typst_library::World;
use typst_syntax::ast::{self, AstNode};
use typst_syntax::Span;
use crate::FlowEvent;
/// A virtual machine.
///
/// Holds the state needed to [evaluate](crate::eval()) Typst sources. A
/// new virtual machine is created for each module evaluation and function call.
pub struct Vm<'a> {
/// The underlying virtual typesetter.
pub(crate) engine: Engine<'a>,
/// A control flow event that is currently happening.
pub(crate) flow: Option<FlowEvent>,
/// The stack of scopes.
pub(crate) scopes: Scopes<'a>,
/// A span that is currently under inspection.
pub(crate) inspected: Option<Span>,
/// Data that is contextually made accessible to code behind the scenes.
pub(crate) context: Tracked<'a, Context<'a>>,
}
impl<'a> Vm<'a> {
/// Create a new virtual machine.
pub fn new(
engine: Engine<'a>,
context: Tracked<'a, Context<'a>>,
scopes: Scopes<'a>,
target: Span,
) -> Self {
let inspected = target.id().and_then(|id| engine.traced.get(id));
Self { engine, context, flow: None, scopes, inspected }
}
/// Access the underlying world.
pub fn world(&self) -> Tracked<'a, dyn World + 'a> {
self.engine.world
}
/// Define a variable in the current scope.
pub fn define(&mut self, var: ast::Ident, value: impl IntoValue) {
let value = value.into_value();
if self.inspected == Some(var.span()) {
self.trace(value.clone());
}
// This will become an error in the parser if 'is' becomes a keyword.
if var.get() == "is" {
self.engine.sink.warn(warning!(
var.span(),
"`is` will likely become a keyword in future versions and will \
not be allowed as an identifier";
hint: "rename this variable to avoid future errors";
hint: "try `is_` instead"
));
}
self.scopes.top.define_ident(var, value);
}
/// Trace a value.
#[cold]
pub fn trace(&mut self, value: Value) {
self.engine
.sink
.value(value.clone(), self.context.styles().ok().map(|s| s.to_map()));
}
}