diff options
| author | Laurenz <laurmaedje@gmail.com> | 2021-11-07 22:05:48 +0100 |
|---|---|---|
| committer | Laurenz <laurmaedje@gmail.com> | 2021-11-08 01:37:49 +0100 |
| commit | 95866d5fc9ae89a23c5754193c7de5d4fe4873b1 (patch) | |
| tree | ae408006c29ba31aa62dab7e48e9326316f89fed /src/eval | |
| parent | 8117ca9950a2027efae133f811a26a4a7bf86a8e (diff) | |
Tidy up AST
Diffstat (limited to 'src/eval')
| -rw-r--r-- | src/eval/capture.rs | 80 | ||||
| -rw-r--r-- | src/eval/mod.rs | 33 |
2 files changed, 23 insertions, 90 deletions
diff --git a/src/eval/capture.rs b/src/eval/capture.rs index e46103c8..786da36e 100644 --- a/src/eval/capture.rs +++ b/src/eval/capture.rs @@ -1,93 +1,27 @@ use std::rc::Rc; -use super::{Scope, Scopes, Value}; -use crate::syntax::ast::{ClosureParam, Expr, Imports}; -use crate::syntax::RedRef; +use super::{Scope, Scopes}; +use crate::syntax::{NodeKind, RedRef}; /// A visitor that captures variable slots. 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(), - } + Self { external, captures: Scope::new() } } pub fn visit(&mut self, node: RedRef) { - let expr: Option<Expr> = node.cast(); - - match expr.as_ref() { - Some(Expr::Let(expr)) => { - self.visit(expr.init_ref()); - let ident = expr.binding(); - self.internal.def_mut(ident.as_str(), Value::None); - } - Some(Expr::Closure(closure)) => { - for arg in closure.params() { - match arg { - ClosureParam::Pos(ident) | ClosureParam::Sink(ident) => { - self.internal.def_mut(ident.as_str(), Value::None); - } - ClosureParam::Named(name) => { - self.internal.def_mut(name.name().as_str(), Value::None); - } - } - } - self.visit(closure.body_ref()); - } - Some(Expr::For(forloop)) => { - let pattern = forloop.pattern(); - self.internal.def_mut(pattern.value().as_str(), Value::None); - - if let Some(key) = pattern.key() { - self.internal.def_mut(key.as_str(), Value::None); + match node.kind() { + NodeKind::Ident(ident) => { + if let Some(slot) = self.external.get(ident.as_str()) { + self.captures.def_slot(ident.as_str(), Rc::clone(slot)); } - self.visit(forloop.body_ref()); } - Some(Expr::Import(import)) => { - if let Imports::Idents(idents) = import.imports() { - for ident in idents { - self.internal.def_mut(ident.as_str(), Value::None); - } - } - } - Some(Expr::Ident(ident)) => { - if self.internal.get(ident.as_str()).is_none() { - if let Some(slot) = self.external.get(ident.as_str()) { - self.captures.def_slot(ident.as_str(), Rc::clone(slot)); - } - } - } - _ => {} - } - - match expr.as_ref() { - Some(Expr::Let(_)) | Some(Expr::For(_)) | Some(Expr::Closure(_)) => {} - - Some(Expr::Block(_)) => { - self.internal.enter(); - for child in node.children() { - self.visit(child); - } - self.internal.exit(); - } - - Some(Expr::Template(_)) => { - self.internal.enter(); - for child in node.children() { - self.visit(child); - } - self.internal.exit(); - } - _ => { for child in node.children() { self.visit(child); diff --git a/src/eval/mod.rs b/src/eval/mod.rs index 809209f4..7c984691 100644 --- a/src/eval/mod.rs +++ b/src/eval/mod.rs @@ -219,7 +219,7 @@ impl Eval for Ident { type Output = Value; fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> { - match ctx.scopes.get(self) { + match ctx.scopes.get(&self.string) { Some(slot) => Ok(slot.borrow().clone()), None => bail!(self.span, "unknown variable"), } @@ -401,7 +401,7 @@ impl Eval for CallArgs { CallArg::Named(x) => { items.push(Arg { span, - name: Some((&x.name().string).into()), + name: Some(x.name().string.into()), value: Spanned::new(x.expr().eval(ctx)?, x.expr().span()), }); } @@ -443,12 +443,10 @@ impl Eval for ClosureExpr { type Output = Value; fn eval(&self, ctx: &mut EvalContext) -> TypResult<Self::Output> { - let name = self.name().as_ref().map(|name| name.string.clone()); - // Collect captured variables. let captured = { let mut visitor = CapturesVisitor::new(&ctx.scopes); - visitor.visit(self.underlying()); + visitor.visit(self.as_red()); visitor.finish() }; @@ -459,23 +457,24 @@ impl Eval for ClosureExpr { for param in self.params() { match param { ClosureParam::Pos(name) => { - params.push((name.string.clone(), None)); + params.push((name.string, None)); } - ClosureParam::Named(x) => { - params.push((x.name().string.clone(), Some(x.expr().eval(ctx)?))); + ClosureParam::Named(named) => { + params.push((named.name().string, Some(named.expr().eval(ctx)?))); } ClosureParam::Sink(name) => { if sink.is_some() { bail!(name.span, "only one argument sink is allowed"); } - sink = Some(name.string.clone()); + sink = Some(name.string); } } } // Clone the body expression so that we don't have a lifetime // dependence on the AST. - let body = self.body().clone(); + let name = self.name().map(|name| name.string); + let body = self.body(); // Define the actual function. let func = Function::new(name, move |ctx, args| { @@ -534,7 +533,7 @@ impl Eval for LetExpr { Some(expr) => expr.eval(ctx)?, None => Value::None, }; - ctx.scopes.def_mut(self.binding().as_str(), value); + ctx.scopes.def_mut(self.binding().string, value); Ok(Value::None) } } @@ -590,7 +589,7 @@ impl Eval for ForExpr { #[allow(unused_parens)] for ($($value),*) in $iter { - $(ctx.scopes.def_mut($binding.as_str(), $value);)* + $(ctx.scopes.def_mut(&$binding.string, $value);)* let value = self.body().eval(ctx)?; output = ops::join(output, value) @@ -637,16 +636,16 @@ impl Eval for ImportExpr { let file = ctx.import(&path, self.path().span())?; let module = &ctx.modules[&file]; - match &self.imports() { + match self.imports() { Imports::Wildcard => { for (var, slot) in module.scope.iter() { ctx.scopes.def_mut(var, slot.borrow().clone()); } } - Imports::Idents(idents) => { + Imports::Items(idents) => { for ident in idents { - if let Some(slot) = module.scope.get(&ident) { - ctx.scopes.def_mut(ident.as_str(), slot.borrow().clone()); + if let Some(slot) = module.scope.get(&ident.string) { + ctx.scopes.def_mut(ident.string, slot.borrow().clone()); } else { bail!(ident.span, "unresolved import"); } @@ -692,7 +691,7 @@ impl Access for Expr { impl Access for Ident { fn access<'a>(&self, ctx: &'a mut EvalContext) -> TypResult<RefMut<'a, Value>> { - match ctx.scopes.get(self) { + match ctx.scopes.get(&self.string) { Some(slot) => match slot.try_borrow_mut() { Ok(guard) => Ok(guard), Err(_) => bail!(self.span, "cannot mutate a constant"), |
