From ac24075469f171fe83a976b9a97b9b1ea078a7e3 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Sat, 30 Jan 2021 10:24:51 +0100 Subject: =?UTF-8?q?Moves=20captures=20visitor=20into=20separate=20file=20?= =?UTF-8?q?=F0=9F=9A=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/eval/capture.rs | 44 +++++++++++++++++++++++++++++++++++++++++ src/eval/mod.rs | 14 ++++++++++++- src/eval/template.rs | 56 ---------------------------------------------------- 3 files changed, 57 insertions(+), 57 deletions(-) create mode 100644 src/eval/capture.rs delete mode 100644 src/eval/template.rs (limited to 'src/eval') diff --git a/src/eval/capture.rs b/src/eval/capture.rs new file mode 100644 index 00000000..b7052c70 --- /dev/null +++ b/src/eval/capture.rs @@ -0,0 +1,44 @@ +use super::*; +use crate::syntax::visit::*; + +/// A visitor that replaces all captured variables with their values. +#[derive(Debug)] +pub struct CapturesVisitor<'a> { + external: &'a Scopes<'a>, + internal: Scopes<'a>, +} + +impl<'a> CapturesVisitor<'a> { + /// Create a new visitor for the given external scopes. + pub fn new(external: &'a Scopes) -> Self { + Self { external, internal: Scopes::default() } + } +} + +impl<'a> Visitor<'a> for CapturesVisitor<'a> { + fn visit_scope_pre(&mut self) { + self.internal.push(); + } + + fn visit_scope_post(&mut self) { + self.internal.pop(); + } + + fn visit_def(&mut self, id: &mut Ident) { + self.internal.define(id.as_str(), Value::None); + } + + fn visit_expr(&mut self, expr: &'a mut Expr) { + if let Expr::Ident(ident) = expr { + // Find out whether the identifier is not locally defined, but + // captured, and if so, replace it with its value. + if self.internal.get(ident).is_none() { + if let Some(value) = self.external.get(ident) { + *expr = Expr::CapturedValue(value.clone()); + } + } + } else { + walk_expr(self, expr); + } + } +} diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 9e45a67b..af3303af 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -3,13 +3,14 @@ #[macro_use] mod value; mod call; +mod capture; mod context; mod ops; mod scope; mod state; -mod template; pub use call::*; +pub use capture::*; pub use context::*; pub use scope::*; pub use state::*; @@ -208,6 +209,17 @@ impl Eval for Spanned<&ExprDict> { } } +impl Eval for Spanned<&ExprTemplate> { + type Output = Value; + + fn eval(self, ctx: &mut EvalContext) -> Self::Output { + let mut template = self.v.clone(); + let mut visitor = CapturesVisitor::new(&ctx.scopes); + visitor.visit_template(&mut template); + Value::Template(template) + } +} + impl Eval for Spanned<&ExprBlock> { type Output = Value; diff --git a/src/eval/template.rs b/src/eval/template.rs deleted file mode 100644 index 040685f8..00000000 --- a/src/eval/template.rs +++ /dev/null @@ -1,56 +0,0 @@ -use super::*; -use crate::syntax::visit::*; - -impl Eval for Spanned<&ExprTemplate> { - type Output = Value; - - fn eval(self, ctx: &mut EvalContext) -> Self::Output { - let mut template = self.v.clone(); - let mut visitor = CapturesVisitor::new(ctx); - visitor.visit_template(&mut template); - Value::Template(template) - } -} - -/// A visitor that replaces all captured variables with their values. -struct CapturesVisitor<'a> { - external: &'a Scopes<'a>, - internal: Scopes<'a>, -} - -impl<'a> CapturesVisitor<'a> { - fn new(ctx: &'a EvalContext) -> Self { - Self { - external: &ctx.scopes, - internal: Scopes::default(), - } - } -} - -impl<'a> Visitor<'a> for CapturesVisitor<'a> { - fn visit_scope_pre(&mut self) { - self.internal.push(); - } - - fn visit_scope_post(&mut self) { - self.internal.pop(); - } - - fn visit_def(&mut self, id: &mut Ident) { - self.internal.define(id.as_str(), Value::None); - } - - fn visit_expr(&mut self, expr: &'a mut Expr) { - if let Expr::Ident(ident) = expr { - // Find out whether the identifier is not locally defined, but - // captured, and if so, replace it with it's value. - if self.internal.get(ident).is_none() { - if let Some(value) = self.external.get(ident) { - *expr = Expr::CapturedValue(value.clone()); - } - } - } else { - walk_expr(self, expr); - } - } -} -- cgit v1.2.3