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::{ use crate::{
Callable, Callable,
convalue::ConValue, convalue::ConValue,
env::{Environment, Place}, env::Environment,
error::{Error, ErrorKind, IResult}, error::{Error, ErrorKind, IResult},
function::collect_upvars::CollectUpvars, function::collect_upvars::CollectUpvars,
interpret::Interpret, interpret::Interpret,
@ -11,11 +11,11 @@ use cl_ast::{Sym, ast_visitor::Visit};
use std::{collections::HashMap, fmt::Display}; use std::{collections::HashMap, fmt::Display};
/// Represents an ad-hoc anonymous function /// Represents an ad-hoc anonymous function
/// which captures surrounding state by reference. /// which captures surrounding state by COPY
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Closure { pub struct Closure {
decl: cl_ast::Closure, decl: cl_ast::Closure,
lift: HashMap<Sym, Place>, lift: HashMap<Sym, Option<ConValue>>,
} }
impl Closure { impl Closure {
@ -24,7 +24,7 @@ impl Closure {
impl Closure { impl Closure {
pub fn new(env: &mut Environment, decl: &cl_ast::Closure) -> Self { 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 } Self { decl: decl.clone(), lift }
} }
} }
@ -42,8 +42,8 @@ impl Callable for Closure {
let mut env = env.frame(Self::NAME); let mut env = env.frame(Self::NAME);
// place lifts in scope // place lifts in scope
for (name, place) in lift { for (name, value) in lift.clone() {
env.insert(*name, Some(ConValue::Ref(*place))); env.insert(name, value);
} }
let mut env = env.frame("args"); let mut env = env.frame("args");

View File

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

View File

@ -7,12 +7,7 @@ use cl_ast::{
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
pub fn collect_upvars(f: &Function, env: &Environment) -> super::Upvars { pub fn collect_upvars(f: &Function, env: &Environment) -> super::Upvars {
CollectUpvars::new(env) CollectUpvars::new(env).visit(f).finish_copied()
.visit(f)
.finish()
.into_iter()
.map(|(k, v)| (k, env.get_id(v).cloned()))
.collect()
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -31,6 +26,14 @@ impl<'env> CollectUpvars<'env> {
std::mem::take(&mut self.upvars) 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) { pub fn add_upvar(&mut self, name: &Sym) {
let Self { env, upvars, blacklist } = self; let Self { env, upvars, blacklist } = self;
if blacklist.contains(name) || upvars.contains_key(name) { if blacklist.contains(name) || upvars.contains_key(name) {