summaryrefslogtreecommitdiff
path: root/src/eval
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2021-11-07 22:05:48 +0100
committerLaurenz <laurmaedje@gmail.com>2021-11-08 01:37:49 +0100
commit95866d5fc9ae89a23c5754193c7de5d4fe4873b1 (patch)
treeae408006c29ba31aa62dab7e48e9326316f89fed /src/eval
parent8117ca9950a2027efae133f811a26a4a7bf86a8e (diff)
Tidy up AST
Diffstat (limited to 'src/eval')
-rw-r--r--src/eval/capture.rs80
-rw-r--r--src/eval/mod.rs33
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"),