optimize closures, refactoring
This commit is contained in:
parent
8a62d46bcf
commit
749a404a90
9 changed files with 133 additions and 143 deletions
|
@ -61,6 +61,7 @@ fn repl() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
rl.set_helper(Some(h));
|
rl.set_helper(Some(h));
|
||||||
println!("Press {}Ctrl+D{} to exit.", C_BLUE, C_RESET);
|
println!("Press {}Ctrl+D{} to exit.", C_BLUE, C_RESET);
|
||||||
stdlib::load(&mut env.borrow_mut());
|
stdlib::load(&mut env.borrow_mut());
|
||||||
|
stdlib::io::load(&mut env.borrow_mut());
|
||||||
stdlib::iter::load(&mut env.borrow_mut());
|
stdlib::iter::load(&mut env.borrow_mut());
|
||||||
stdlib::math::load(&mut env.borrow_mut());
|
stdlib::math::load(&mut env.borrow_mut());
|
||||||
loop {
|
loop {
|
||||||
|
|
|
@ -331,24 +331,30 @@ pub fn eval_comp(lhs: &Expr, rhs: &Expr, op: &Token, env: EnvRef) -> Result<Valu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pipecolon_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, iter_data: Rc<RefCell<Vec<CIterator>>>) -> Result<Value, RuntimeError> {
|
fn mk_pipecolon_inner(f: Func, it: CIterator) -> Func {
|
||||||
let f = &data.borrow()[0];
|
let it = RefCell::new(it);
|
||||||
if let Some(next) = iter_data.borrow_mut()[0].next() {
|
return Func::BuiltinClosure{
|
||||||
let func = f.as_func()?;
|
arg_count: 0,
|
||||||
func.call(vec![next?])
|
func: Rc::new(move |_| {
|
||||||
|
if let Some(next) = it.borrow_mut().next() {
|
||||||
|
f.call(vec![next?])
|
||||||
} else {
|
} else {
|
||||||
Ok(Value::Nil)
|
Ok(Value::Nil)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pipequestion_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, iter_data: Rc<RefCell<Vec<CIterator>>>) -> Result<Value, RuntimeError> {
|
fn mk_pipequestion_inner(f: Func, it: CIterator) -> Func {
|
||||||
let f = &data.borrow()[0];
|
let it = RefCell::new(it);
|
||||||
|
return Func::BuiltinClosure {
|
||||||
|
arg_count: 0,
|
||||||
|
func: Rc::new(move |_| {
|
||||||
loop {
|
loop {
|
||||||
let next = iter_data.borrow_mut()[0].next();
|
let next = it.borrow_mut().next();
|
||||||
if let Some(next) = next {
|
if let Some(next) = next {
|
||||||
let next = next?;
|
let next = next?;
|
||||||
let func = f.as_func()?;
|
let success = f.call(vec![next.clone()])?.truthy();
|
||||||
let success = func.call(vec![next.clone()])?.truthy();
|
|
||||||
if success {
|
if success {
|
||||||
return Ok(next)
|
return Ok(next)
|
||||||
}
|
}
|
||||||
|
@ -356,6 +362,8 @@ fn pipequestion_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, iter_data: R
|
||||||
return Ok(Value::Nil)
|
return Ok(Value::Nil)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -370,22 +378,8 @@ pub fn eval_pipeline(lhs: &Expr, rhs: &Expr, op: &Token, env: EnvRef) -> Result<
|
||||||
fn eval_pipeline_inner(l: Value, r: &Func, op: &Token) -> Result<Value, RuntimeError> {
|
fn eval_pipeline_inner(l: Value, r: &Func, op: &Token) -> Result<Value, RuntimeError> {
|
||||||
match op.ty {
|
match op.ty {
|
||||||
TokenType::PipePoint => r.call(vec![l]),
|
TokenType::PipePoint => r.call(vec![l]),
|
||||||
TokenType::PipeColon => {
|
TokenType::PipeColon => Ok(Value::Func(mk_pipecolon_inner(r.clone(), l.iter()?))),
|
||||||
Ok(Value::Func(Func::BuiltinClosure {
|
TokenType::PipeQuestion => Ok(Value::Func(mk_pipequestion_inner(r.clone(), l.iter()?))),
|
||||||
arg_count: 0,
|
|
||||||
data: Rc::new(RefCell::new(vec![Value::Func(r.clone())])),
|
|
||||||
iter_data: Rc::new(RefCell::new(vec![l.iter()?])),
|
|
||||||
func: pipecolon_inner,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
TokenType::PipeQuestion => {
|
|
||||||
Ok(Value::Func(Func::BuiltinClosure {
|
|
||||||
arg_count: 0,
|
|
||||||
data: Rc::new(RefCell::new(vec![Value::Func(r.clone())])),
|
|
||||||
iter_data: Rc::new(RefCell::new(vec![l.iter()?])),
|
|
||||||
func: pipequestion_inner,
|
|
||||||
}))
|
|
||||||
},
|
|
||||||
TokenType::PipeDoubleSlash => {
|
TokenType::PipeDoubleSlash => {
|
||||||
let mut result = Value::Nil;
|
let mut result = Value::Nil;
|
||||||
let mut first_iter = true;
|
let mut first_iter = true;
|
||||||
|
|
|
@ -14,6 +14,7 @@ pub fn interpret(src: &str, fname: Option<String>, env: Option<EnvRef>, repl: bo
|
||||||
} else {
|
} else {
|
||||||
environ = Rc::new(RefCell::new(Environment::new()));
|
environ = Rc::new(RefCell::new(Environment::new()));
|
||||||
stdlib::load(&mut environ.borrow_mut());
|
stdlib::load(&mut environ.borrow_mut());
|
||||||
|
stdlib::io::load(&mut environ.borrow_mut());
|
||||||
stdlib::iter::load(&mut environ.borrow_mut());
|
stdlib::iter::load(&mut environ.borrow_mut());
|
||||||
stdlib::math::load(&mut environ.borrow_mut());
|
stdlib::math::load(&mut environ.borrow_mut());
|
||||||
}
|
}
|
||||||
|
|
30
complexpr/src/stdlib/io.rs
Normal file
30
complexpr/src/stdlib/io.rs
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
use crate::{env::Environment, declare_fn, value::Value, RuntimeError};
|
||||||
|
|
||||||
|
pub fn load(env: &mut Environment) {
|
||||||
|
declare_fn!(env, print, 1);
|
||||||
|
declare_fn!(env, println, 1);
|
||||||
|
declare_fn!(env, input, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_print(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
print!("{}", args[0].to_string());
|
||||||
|
std::io::stdout().flush().map_err(|e| e.to_string())?;
|
||||||
|
Ok(Value::Nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_println(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
println!("{}", args[0].to_string());
|
||||||
|
Ok(Value::Nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fn_input(_: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
let mut buffer = String::new();
|
||||||
|
let stdin = std::io::stdin();
|
||||||
|
stdin.read_line(&mut buffer).map_err(|e| e.to_string())?;
|
||||||
|
if buffer.ends_with('\n') {
|
||||||
|
buffer.pop();
|
||||||
|
}
|
||||||
|
Ok(Value::from(buffer))
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{rc::Rc, cell::RefCell};
|
use std::{rc::Rc, cell::RefCell};
|
||||||
|
|
||||||
use crate::{value::{Value, func::{Func, CIterator}}, RuntimeError, env::Environment, declare_fn};
|
use crate::{value::{Value, func::Func}, RuntimeError, env::Environment, declare_fn};
|
||||||
|
|
||||||
pub fn load(env: &mut Environment) {
|
pub fn load(env: &mut Environment) {
|
||||||
declare_fn!(env, take, 2);
|
declare_fn!(env, take, 2);
|
||||||
|
@ -9,44 +9,27 @@ pub fn load(env: &mut Environment) {
|
||||||
declare_fn!(env, exists, 2);
|
declare_fn!(env, exists, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn take_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, iter_data: Rc<RefCell<Vec<CIterator>>>) -> Result<Value, RuntimeError> {
|
|
||||||
// 0: current index
|
|
||||||
// 1: target index
|
|
||||||
let mut d = data.borrow_mut();
|
|
||||||
if d[0] >= d[1] {
|
|
||||||
Ok(Value::Nil)
|
|
||||||
} else {
|
|
||||||
d[0] = (&d[0] + &Value::Int(1))?;
|
|
||||||
match iter_data.borrow_mut()[0].next() {
|
|
||||||
None => Ok(Value::Nil),
|
|
||||||
Some(x) => x
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fn_take(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn fn_take(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
let idx = RefCell::new(0);
|
||||||
|
let limit = match args[0] {
|
||||||
|
Value::Int(n) => n,
|
||||||
|
_ => return Err("Argument to take must be an integer".into()),
|
||||||
|
};
|
||||||
|
let it = RefCell::new(args[1].iter()?);
|
||||||
Ok(Value::Func(Func::BuiltinClosure {
|
Ok(Value::Func(Func::BuiltinClosure {
|
||||||
arg_count: 0,
|
arg_count: 0,
|
||||||
data: Rc::new(RefCell::new(vec![Value::Int(0), args[0].clone()])),
|
func: Rc::new(move |_| {
|
||||||
iter_data: Rc::new(RefCell::new(vec![args[1].iter()?])),
|
if *idx.borrow() >= limit {
|
||||||
func: take_inner
|
Ok(Value::Nil)
|
||||||
}))
|
} else {
|
||||||
}
|
*idx.borrow_mut() += 1;
|
||||||
|
match it.borrow_mut().next() {
|
||||||
fn skip_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, iter_data: Rc<RefCell<Vec<CIterator>>>) -> Result<Value, RuntimeError> {
|
|
||||||
let mut d = if let Value::Int(d) = data.borrow()[0] { d } else {
|
|
||||||
unreachable!() // checked by fn_skip()
|
|
||||||
};
|
|
||||||
while d > 0 {
|
|
||||||
iter_data.borrow_mut()[0].next();
|
|
||||||
d -= 1;
|
|
||||||
}
|
|
||||||
data.borrow_mut()[0] = Value::Int(d);
|
|
||||||
match iter_data.borrow_mut()[0].next() {
|
|
||||||
None => Ok(Value::Nil),
|
None => Ok(Value::Nil),
|
||||||
Some(x) => x
|
Some(x) => x
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_skip(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn fn_skip(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
@ -55,12 +38,20 @@ fn fn_skip(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
Value::Int(n) => n,
|
Value::Int(n) => n,
|
||||||
_ => return Err(RuntimeError::new_no_pos("First argument to skip must be an integer"))
|
_ => return Err(RuntimeError::new_no_pos("First argument to skip must be an integer"))
|
||||||
};
|
};
|
||||||
let it = args[1].iter()?;
|
let it = RefCell::new(args[1].iter()?);
|
||||||
|
let idx = RefCell::new(0);
|
||||||
Ok(Value::Func(Func::BuiltinClosure {
|
Ok(Value::Func(Func::BuiltinClosure {
|
||||||
arg_count: 0,
|
arg_count: 0,
|
||||||
data: Rc::new(RefCell::new(vec![Value::Int(n)])),
|
func: Rc::new(move |_| {
|
||||||
iter_data: Rc::new(RefCell::new(vec![it])),
|
while *idx.borrow() < n {
|
||||||
func: skip_inner
|
it.borrow_mut().next();
|
||||||
|
*idx.borrow_mut() += 1;
|
||||||
|
}
|
||||||
|
match it.borrow_mut().next() {
|
||||||
|
None => Ok(Value::Nil),
|
||||||
|
Some(x) => x
|
||||||
|
}
|
||||||
|
})
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use std::{rc::Rc, cmp::Ordering};
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use num_traits::{ToPrimitive, Pow};
|
use num_traits::{ToPrimitive, Pow};
|
||||||
|
|
||||||
use crate::{value::{Value, func::Func, Complex, Rational}, RuntimeError, env::Environment, declare_fn};
|
use crate::{value::{Value, Complex, Rational}, RuntimeError, env::Environment, declare_fn};
|
||||||
|
|
||||||
enum Floaty {
|
enum Floaty {
|
||||||
Real(f64), Complex(Complex)
|
Real(f64), Complex(Complex)
|
||||||
|
|
|
@ -1,19 +1,20 @@
|
||||||
pub mod math;
|
pub mod io;
|
||||||
pub mod iter;
|
pub mod iter;
|
||||||
|
pub mod math;
|
||||||
|
|
||||||
use std::{rc::Rc, io::Write, cmp::Ordering, time::{SystemTime, UNIX_EPOCH}, cell::RefCell};
|
use std::{rc::Rc, cmp::Ordering, time::{SystemTime, UNIX_EPOCH}, cell::RefCell};
|
||||||
|
|
||||||
use crate::{value::{Value, func::{Func, CIterator}}, RuntimeError, env::Environment};
|
use crate::{value::{Value, func::Func}, RuntimeError, env::Environment};
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! declare_fn {
|
macro_rules! declare_fn {
|
||||||
($env:ident, $name:ident, $arg_count:literal) => {paste::paste!{{
|
($env:ident, $name:ident, $arg_count:literal) => {::paste::paste!{{
|
||||||
let s: Rc<str> = Rc::from(stringify!($name));
|
let s: ::std::rc::Rc<str> = ::std::rc::Rc::from(stringify!($name));
|
||||||
$env.declare(s.clone(), Value::Func(Func::Builtin { func: [<fn_ $name>], arg_count: $arg_count, name: s }));
|
$env.declare(s.clone(), $crate::value::Value::Func($crate::value::func::Func::Builtin { func: [<fn_ $name>], arg_count: $arg_count, name: s }));
|
||||||
}}};
|
}}};
|
||||||
($env:ident, $name:literal, $rust_name:ident, $arg_count:literal) => {{
|
($env:ident, $name:literal, $rust_name:ident, $arg_count:literal) => {{
|
||||||
let s: Rc<str> = Rc::from($name);
|
let s: ::std::rc::Rc<str> = ::std::rc::Rc::from($name);
|
||||||
$env.declare(s.clone(), Value::Func(Func::Builtin { func: $rust_name, arg_count: $arg_count, name: s }));
|
$env.declare(s.clone(), $crate::value::Value::Func($crate::value::func::Func::Builtin { func: $rust_name, arg_count: $arg_count, name: s }));
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,9 +23,6 @@ pub fn load(env: &mut Environment) {
|
||||||
declare_fn!(env, type_eq, 1);
|
declare_fn!(env, type_eq, 1);
|
||||||
declare_fn!(env, str, 1);
|
declare_fn!(env, str, 1);
|
||||||
declare_fn!(env, repr, 1);
|
declare_fn!(env, repr, 1);
|
||||||
declare_fn!(env, print, 1);
|
|
||||||
declare_fn!(env, println, 1);
|
|
||||||
declare_fn!(env, input, 0);
|
|
||||||
declare_fn!(env, ord, 1);
|
declare_fn!(env, ord, 1);
|
||||||
declare_fn!(env, chr, 1);
|
declare_fn!(env, chr, 1);
|
||||||
declare_fn!(env, range, 2);
|
declare_fn!(env, range, 2);
|
||||||
|
@ -54,27 +52,6 @@ fn fn_repr(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
Ok(Value::String(args[0].repr()))
|
Ok(Value::String(args[0].repr()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_print(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
||||||
print!("{}", args[0].to_string());
|
|
||||||
std::io::stdout().flush().map_err(|e| e.to_string())?;
|
|
||||||
Ok(Value::Nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fn_println(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
||||||
println!("{}", args[0].to_string());
|
|
||||||
Ok(Value::Nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fn_input(_: Vec<Value>) -> Result<Value, RuntimeError> {
|
|
||||||
let mut buffer = String::new();
|
|
||||||
let stdin = std::io::stdin();
|
|
||||||
stdin.read_line(&mut buffer).map_err(|e| e.to_string())?;
|
|
||||||
if buffer.ends_with('\n') {
|
|
||||||
buffer.pop();
|
|
||||||
}
|
|
||||||
Ok(Value::from(buffer))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn fn_ord(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn fn_ord(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
if let Value::Char(c) = args[0] {
|
if let Value::Char(c) = args[0] {
|
||||||
Ok(Value::from(c as u32))
|
Ok(Value::from(c as u32))
|
||||||
|
@ -96,36 +73,36 @@ fn fn_chr(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn range_inner(_: Vec<Value>, data: Rc<RefCell<Vec<Value>>>, _: Rc<RefCell<Vec<CIterator>>>) -> Result<Value, RuntimeError> {
|
fn mk_range_inner(start: i64, end: i64, delta: i64) -> Func {
|
||||||
const ZERO: Value = Value::Int(0);
|
let counter = RefCell::new(start);
|
||||||
let mut d = data.borrow_mut();
|
Func::BuiltinClosure {
|
||||||
if d[2] >= ZERO && d[0] >= d[1]
|
arg_count: 0,
|
||||||
|| d[2] <= ZERO && d[0] <= d[1] {
|
func: Rc::new(move |_| {
|
||||||
|
let c_value = *counter.borrow();
|
||||||
|
if delta >= 0 && c_value >= end
|
||||||
|
|| delta <= 0 && c_value <= end {
|
||||||
Ok(Value::Nil)
|
Ok(Value::Nil)
|
||||||
} else {
|
} else {
|
||||||
let res = d[0].clone();
|
let res = *counter.borrow();
|
||||||
d[0] = (&d[0] + &d[2])?;
|
*counter.borrow_mut() += delta;
|
||||||
Ok(res)
|
Ok(Value::Int(res))
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_range(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn fn_range(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
let start = &args[0];
|
let (start, end, delta) = match (&args[0], &args[1]) {
|
||||||
let end = &args[1];
|
(Value::Int(a), Value::Int(b)) => (a, b,
|
||||||
let delta = match (start, end) {
|
match a.cmp(&b) {
|
||||||
(Value::Int(a), Value::Int(b)) => match a.cmp(b) {
|
|
||||||
Ordering::Equal => 0,
|
Ordering::Equal => 0,
|
||||||
Ordering::Less => 1,
|
Ordering::Less => 1,
|
||||||
Ordering::Greater => -1,
|
Ordering::Greater => -1,
|
||||||
},
|
}
|
||||||
|
),
|
||||||
_ => return Err("Both arguments to range must be integers".into())
|
_ => return Err("Both arguments to range must be integers".into())
|
||||||
};
|
};
|
||||||
Ok(Value::Func(Func::BuiltinClosure {
|
Ok(Value::Func(mk_range_inner(*start, *end, delta)))
|
||||||
arg_count: 0,
|
|
||||||
data: Rc::new(RefCell::new(vec![start.clone(), end.clone(), Value::Int(delta)])),
|
|
||||||
iter_data: Rc::new(RefCell::new(vec![])),
|
|
||||||
func: range_inner
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fn_len(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
fn fn_len(args: Vec<Value>) -> Result<Value, RuntimeError> {
|
||||||
|
|
|
@ -21,9 +21,7 @@ pub enum Func {
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
},
|
},
|
||||||
BuiltinClosure {
|
BuiltinClosure {
|
||||||
func: fn(Vec<Value>, ClosureData, ClosureIterData) -> Result<Value, RuntimeError>,
|
func: Rc<dyn Fn(Vec<Value>) -> Result<Value, RuntimeError>>,
|
||||||
data: ClosureData,
|
|
||||||
iter_data: ClosureIterData,
|
|
||||||
arg_count: usize,
|
arg_count: usize,
|
||||||
},
|
},
|
||||||
Partial {
|
Partial {
|
||||||
|
@ -45,10 +43,9 @@ impl fmt::Debug for Func {
|
||||||
.field("name", name)
|
.field("name", name)
|
||||||
.field("arg_count", arg_count)
|
.field("arg_count", arg_count)
|
||||||
.finish_non_exhaustive(),
|
.finish_non_exhaustive(),
|
||||||
Self::BuiltinClosure { arg_count, data, .. }
|
Self::BuiltinClosure { arg_count, .. }
|
||||||
=> f.debug_struct("Func::BuiltinClosure")
|
=> f.debug_struct("Func::BuiltinClosure")
|
||||||
.field("arg_count", arg_count)
|
.field("arg_count", arg_count)
|
||||||
.field("data", data)
|
|
||||||
.finish_non_exhaustive(),
|
.finish_non_exhaustive(),
|
||||||
Self::Partial { inner, filled_args }
|
Self::Partial { inner, filled_args }
|
||||||
=> f.debug_struct("Func::Partial")
|
=> f.debug_struct("Func::Partial")
|
||||||
|
@ -84,8 +81,8 @@ impl Func {
|
||||||
Ordering::Equal => match self {
|
Ordering::Equal => match self {
|
||||||
Self::Builtin { func, .. }
|
Self::Builtin { func, .. }
|
||||||
=> func(arg_values),
|
=> func(arg_values),
|
||||||
Self::BuiltinClosure { func, data, iter_data, .. }
|
Self::BuiltinClosure { func, .. }
|
||||||
=> func(arg_values, data.clone(), iter_data.clone()),
|
=> func(arg_values),
|
||||||
Self::Func { args, func, env, .. } => {
|
Self::Func { args, func, env, .. } => {
|
||||||
let mut env = Environment::extend(env.clone());
|
let mut env = Environment::extend(env.clone());
|
||||||
for (k, v) in args.iter().zip(arg_values.iter()) {
|
for (k, v) in args.iter().zip(arg_values.iter()) {
|
||||||
|
@ -137,9 +134,8 @@ impl Hash for Func {
|
||||||
name.hash(state);
|
name.hash(state);
|
||||||
args.hash(state);
|
args.hash(state);
|
||||||
},
|
},
|
||||||
Self::BuiltinClosure { arg_count, data, .. } => {
|
Self::BuiltinClosure { arg_count, .. } => {
|
||||||
arg_count.hash(state);
|
arg_count.hash(state);
|
||||||
data.borrow().hash(state);
|
|
||||||
},
|
},
|
||||||
Self::Partial { inner, filled_args } => {
|
Self::Partial { inner, filled_args } => {
|
||||||
filled_args.hash(state);
|
filled_args.hash(state);
|
||||||
|
|
|
@ -116,7 +116,7 @@ impl Value {
|
||||||
Self::Map(m) => Rc::from(format!("{:?}", m)), // TODO fix
|
Self::Map(m) => Rc::from(format!("{:?}", m)), // TODO fix
|
||||||
Self::Type(t) => Rc::from(format!("<type {}>", t.name)),
|
Self::Type(t) => Rc::from(format!("<type {}>", t.name)),
|
||||||
Self::Func(Func::Builtin { name, func, .. }) => Rc::from(format!("<builtin fn {} at {:?}>", name, *func as *const ())),
|
Self::Func(Func::Builtin { name, func, .. }) => Rc::from(format!("<builtin fn {} at {:?}>", name, *func as *const ())),
|
||||||
Self::Func(Func::BuiltinClosure { func, .. }) => Rc::from(format!("<builtin anonymous fn at {:?}>", *func as *const ())),
|
Self::Func(Func::BuiltinClosure { .. }) => Rc::from(format!("<builtin anonymous fn>")),
|
||||||
Self::Func(f @ Func::Partial { .. }) => match f.name() {
|
Self::Func(f @ Func::Partial { .. }) => match f.name() {
|
||||||
Some(name) => Rc::from(format!("<partial of fn {}>", name)),
|
Some(name) => Rc::from(format!("<partial of fn {}>", name)),
|
||||||
None => Rc::from("<partial of anonymous fn>"),
|
None => Rc::from("<partial of anonymous fn>"),
|
||||||
|
|
Loading…
Reference in a new issue