cl-interpret: copy-capture closures
This commit is contained in:
parent
d3e20e53d0
commit
ccfa4c7723
@ -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");
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user