mirror of https://github.com/stelzo/typst.git
75 lines
2.0 KiB
Rust
75 lines
2.0 KiB
Rust
use std::rc::Rc;
|
|
|
|
use super::{Scope, Scopes, Value};
|
|
use crate::syntax::visit::{visit_expr, Visit};
|
|
use crate::syntax::{Expr, Ident, Node};
|
|
|
|
/// A visitor that captures variable slots.
|
|
#[derive(Debug)]
|
|
pub struct CapturesVisitor<'a> {
|
|
external: &'a Scopes<'a>,
|
|
internal: Scopes<'a>,
|
|
captures: Scope,
|
|
}
|
|
|
|
impl<'a> CapturesVisitor<'a> {
|
|
/// Create a new visitor for the given external scopes.
|
|
pub fn new(external: &'a Scopes) -> Self {
|
|
Self {
|
|
external,
|
|
internal: Scopes::new(None),
|
|
captures: Scope::new(),
|
|
}
|
|
}
|
|
|
|
/// Return the scope of captured variables.
|
|
pub fn finish(self) -> Scope {
|
|
self.captures
|
|
}
|
|
|
|
/// Find out whether the name is not locally defined and if so if it can be
|
|
/// captured.
|
|
fn process(&mut self, name: &str) {
|
|
if self.internal.get(name).is_none() {
|
|
if let Some(slot) = self.external.get(name) {
|
|
self.captures.def_slot(name, Rc::clone(slot));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'ast> Visit<'ast> for CapturesVisitor<'_> {
|
|
fn visit_node(&mut self, node: &'ast Node) {
|
|
match node {
|
|
Node::Text(_) => {}
|
|
Node::Space => {}
|
|
Node::Linebreak(_) => self.process(Node::LINEBREAK),
|
|
Node::Parbreak(_) => self.process(Node::PARBREAK),
|
|
Node::Strong(_) => self.process(Node::STRONG),
|
|
Node::Emph(_) => self.process(Node::EMPH),
|
|
Node::Heading(_) => self.process(Node::HEADING),
|
|
Node::Raw(_) => self.process(Node::RAW),
|
|
Node::Expr(expr) => self.visit_expr(expr),
|
|
}
|
|
}
|
|
|
|
fn visit_expr(&mut self, node: &'ast Expr) {
|
|
match node {
|
|
Expr::Ident(ident) => self.process(ident),
|
|
expr => visit_expr(self, expr),
|
|
}
|
|
}
|
|
|
|
fn visit_binding(&mut self, id: &'ast Ident) {
|
|
self.internal.def_mut(id.as_str(), Value::None);
|
|
}
|
|
|
|
fn visit_enter(&mut self) {
|
|
self.internal.enter();
|
|
}
|
|
|
|
fn visit_exit(&mut self) {
|
|
self.internal.exit();
|
|
}
|
|
}
|