fix evaluation behavior mismatch between functions and lambdas
Signed-off-by: Ava Hahn <ava@sunnypup.io>
This commit is contained in:
parent
e0b837cb21
commit
398726568a
4 changed files with 41 additions and 13 deletions
|
|
@ -154,10 +154,8 @@ Note: this section only tracks the state of incomplete TODO items. Having everyt
|
|||
** DONE Beta tasks
|
||||
(See tag: v0.3.0)
|
||||
** TODO v1.0 tasks
|
||||
- Post to relevant channels
|
||||
- Version flag
|
||||
- islist type query
|
||||
- Scripts can use shell functions
|
||||
- Can pass args to relish scripts (via interpreter)
|
||||
- Can pass args to relish scripts (via command line)
|
||||
- File operations
|
||||
|
|
|
|||
|
|
@ -198,12 +198,10 @@ fn launch_command(
|
|||
// glibc says to do this in both parent and child
|
||||
if let Ok(child) = newchld {
|
||||
let pid = child.id();
|
||||
if let Err(e) = unistd::setpgid(
|
||||
_ = unistd::setpgid(
|
||||
Pid::from_raw(pid as i32),
|
||||
Pid::from_raw(pid as i32),
|
||||
) {
|
||||
eprintln!("parent couldnt setpgid on chld: {}", e);
|
||||
}
|
||||
); // ignore result
|
||||
state.children.push(child);
|
||||
if !background {
|
||||
make_foreground(pid, state)
|
||||
|
|
|
|||
28
src/sym.rs
28
src/sym.rs
|
|
@ -143,15 +143,29 @@ impl SymTable {
|
|||
if let ValueType::VarForm(ref val) = symbol.value {
|
||||
match **val {
|
||||
Ctr::Lambda(ref l) if call_func => {
|
||||
call_lambda(
|
||||
return call_lambda(
|
||||
l,
|
||||
&Box::new(Ctr::Seg(args.clone())),
|
||||
self
|
||||
)
|
||||
},
|
||||
_ => Ok(val.clone()),
|
||||
Ctr::Symbol(ref s) if self.is_function_type(s).is_some()
|
||||
&& self.is_function_type(s).unwrap() => {
|
||||
symbol = match self.remove(s) {
|
||||
Some(sym) => sym,
|
||||
None => return Err(
|
||||
Traceback::new().with_trace(
|
||||
(name, format!("(references undefined symbol {})", s))
|
||||
.into())),
|
||||
};
|
||||
symbol.__generation -= 1;
|
||||
self.insert(symbol.name.clone(), symbol.clone());
|
||||
},
|
||||
_ => return Ok(val.clone()),
|
||||
}
|
||||
} else if call_func {
|
||||
}
|
||||
|
||||
if call_func {
|
||||
symbol.call(args, self)
|
||||
} else {
|
||||
// its a function but call_func is off
|
||||
|
|
@ -161,10 +175,10 @@ impl SymTable {
|
|||
|
||||
pub fn is_function_type(&self, name: &String) -> Option<bool> {
|
||||
if let ValueType::VarForm(ref val) = self.get(name)?.value {
|
||||
if let Ctr::Lambda(_) = **val {
|
||||
Some(true)
|
||||
} else {
|
||||
Some(false)
|
||||
match **val {
|
||||
Ctr::Lambda(_) => Some(true),
|
||||
Ctr::Symbol(ref n) => self.is_function_type(n),
|
||||
_ => Some(false),
|
||||
}
|
||||
} else {
|
||||
Some(true)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
mod eval_tests {
|
||||
use relish::ast::{eval, lex, SymTable};
|
||||
use relish::ast::{Args, Ctr, Seg, Symbol, UserFn, ValueType};
|
||||
use relish::stdlib::{dynamic_stdlib, static_stdlib};
|
||||
|
||||
#[test]
|
||||
fn eval_simple() {
|
||||
|
|
@ -92,4 +93,21 @@ mod eval_tests {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn func_lambda_equivalency() {
|
||||
let comparator = "(def apply 'applicator' (fn x) (fn x))";
|
||||
let lh_doc = "(apply car (1 2 3))";
|
||||
let rh_doc = "(apply (lambda (x) (car x)) (1 2 3))";
|
||||
|
||||
let mut syms = SymTable::new();
|
||||
static_stdlib(&mut syms);
|
||||
dynamic_stdlib(&mut syms, None);
|
||||
|
||||
eval(&lex(&comparator.to_string()).unwrap(), &mut syms).unwrap();
|
||||
assert_eq!(
|
||||
eval(&lex(&lh_doc.to_string()).unwrap(), &mut syms).unwrap(),
|
||||
eval(&lex(&rh_doc.to_string()).unwrap(), &mut syms).unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue