cl-interpret: copy-capture closures

This commit is contained in:
John 2025-05-18 11:30:17 -04:00
parent d3e20e53d0
commit ccfa4c7723
3 changed files with 20 additions and 12 deletions

View File

@ -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<Sym, Place>,
lift: HashMap<Sym, Option<ConValue>>,
}
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");

View File

@ -99,6 +99,11 @@ impl Environment {
function.call(self, args)
}
/// Gets all registered globals, bound or unbound.
pub fn globals(&self) -> &HashMap<Sym, Option<ConValue>> {
&self.global
}
/// Adds builtins
///
/// # Panics

View File

@ -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) {