From ccfa4c7723364580bfa21b4a271a2af8dbffaa31 Mon Sep 17 00:00:00 2001 From: John Date: Sun, 18 May 2025 11:30:17 -0400 Subject: [PATCH] cl-interpret: copy-capture closures --- compiler/cl-interpret/src/closure.rs | 12 ++++++------ compiler/cl-interpret/src/env.rs | 5 +++++ .../cl-interpret/src/function/collect_upvars.rs | 15 +++++++++------ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/compiler/cl-interpret/src/closure.rs b/compiler/cl-interpret/src/closure.rs index 7f4be74..368c2ec 100644 --- a/compiler/cl-interpret/src/closure.rs +++ b/compiler/cl-interpret/src/closure.rs @@ -1,7 +1,7 @@ use crate::{ Callable, convalue::ConValue, - env::{Environment, Place}, + env::Environment, error::{Error, ErrorKind, IResult}, function::collect_upvars::CollectUpvars, interpret::Interpret, @@ -11,11 +11,11 @@ use cl_ast::{Sym, ast_visitor::Visit}; use std::{collections::HashMap, fmt::Display}; /// Represents an ad-hoc anonymous function -/// which captures surrounding state by reference. +/// which captures surrounding state by COPY #[derive(Clone, Debug)] pub struct Closure { decl: cl_ast::Closure, - lift: HashMap, + lift: HashMap>, } impl Closure { @@ -24,7 +24,7 @@ impl Closure { impl Closure { pub fn new(env: &mut Environment, decl: &cl_ast::Closure) -> Self { - let lift = CollectUpvars::new(env).visit(decl).finish(); + let lift = CollectUpvars::new(env).visit(decl).finish_copied(); Self { decl: decl.clone(), lift } } } @@ -42,8 +42,8 @@ impl Callable for Closure { let mut env = env.frame(Self::NAME); // place lifts in scope - for (name, place) in lift { - env.insert(*name, Some(ConValue::Ref(*place))); + for (name, value) in lift.clone() { + env.insert(name, value); } let mut env = env.frame("args"); diff --git a/compiler/cl-interpret/src/env.rs b/compiler/cl-interpret/src/env.rs index 5010d56..89d7bd4 100644 --- a/compiler/cl-interpret/src/env.rs +++ b/compiler/cl-interpret/src/env.rs @@ -99,6 +99,11 @@ impl Environment { function.call(self, args) } + /// Gets all registered globals, bound or unbound. + pub fn globals(&self) -> &HashMap> { + &self.global + } + /// Adds builtins /// /// # Panics diff --git a/compiler/cl-interpret/src/function/collect_upvars.rs b/compiler/cl-interpret/src/function/collect_upvars.rs index 76a4778..a762471 100644 --- a/compiler/cl-interpret/src/function/collect_upvars.rs +++ b/compiler/cl-interpret/src/function/collect_upvars.rs @@ -7,12 +7,7 @@ use cl_ast::{ use std::collections::{HashMap, HashSet}; pub fn collect_upvars(f: &Function, env: &Environment) -> super::Upvars { - CollectUpvars::new(env) - .visit(f) - .finish() - .into_iter() - .map(|(k, v)| (k, env.get_id(v).cloned())) - .collect() + CollectUpvars::new(env).visit(f).finish_copied() } #[derive(Clone, Debug)] @@ -31,6 +26,14 @@ impl<'env> CollectUpvars<'env> { std::mem::take(&mut self.upvars) } + pub fn finish_copied(&mut self) -> super::Upvars { + let Self { env, upvars, blacklist: _ } = self; + std::mem::take(upvars) + .into_iter() + .map(|(k, v)| (k, env.get_id(v).cloned())) + .collect() + } + pub fn add_upvar(&mut self, name: &Sym) { let Self { env, upvars, blacklist } = self; if blacklist.contains(name) || upvars.contains_key(name) {