DEV: Maps over lists, strings, and tuples are working

This commit is contained in:
Jeremy Wall 2019-08-17 14:04:02 -05:00
parent 4ba4355d37
commit 8d7ca3d6c1
2 changed files with 78 additions and 27 deletions

View File

@ -21,7 +21,7 @@ use std::rc::Rc;
use regex::Regex; use regex::Regex;
use super::environment::Environment; use super::environment::Environment;
use super::Value::{C, F, P}; use super::Value::{C, F, P, S};
use super::VM; use super::VM;
use super::{Composite, Error, Hook, Primitive, Value}; use super::{Composite, Error, Hook, Primitive, Value};
use crate::ast::Position; use crate::ast::Position;
@ -334,18 +334,6 @@ impl Builtins {
} else { } else {
return Err(dbg!(Error {})); return Err(dbg!(Error {}));
}; };
// TODO(jwall): This can also be tuples or strings.
let elems = match list.as_ref() {
&C(List(ref elems)) => elems,
&C(Tuple(ref _flds)) => {
unimplemented!("TODO Tuple functional operations");
}
&P(Str(ref _s)) => {
unimplemented!("TODO String functional operations");
}
_ => return Err(dbg!(Error {})),
};
// get the func ptr from the stack // get the func ptr from the stack
let fptr = if let Some(ptr) = stack.pop() { let fptr = if let Some(ptr) = stack.pop() {
ptr ptr
@ -359,19 +347,59 @@ impl Builtins {
return Err(dbg!(Error {})); return Err(dbg!(Error {}));
}; };
let mut result_elems = Vec::new(); // TODO(jwall): This can also be tuples or strings.
for e in elems.iter() { match list.as_ref() {
// push function argument on the stack. &C(List(ref elems)) => {
stack.push(e.clone()); let mut result_elems = Vec::new();
// call function and push it's result on the stack. for e in elems.iter() {
result_elems.push(VM::fcall_impl( // push function argument on the stack.
path.as_ref().to_owned(), stack.push(e.clone());
f, // call function and push it's result on the stack.
stack, result_elems.push(VM::fcall_impl(
env.clone(), path.as_ref().to_owned(),
)?); f,
} stack,
stack.push(Rc::new(C(List(result_elems)))); env.clone(),
)?);
}
stack.push(Rc::new(C(List(result_elems))));
}
&C(Tuple(ref _flds)) => {
let mut new_fields = Vec::new();
for (ref name, ref val) in _flds {
stack.push(val.clone());
stack.push(Rc::new(P(Str(name.clone()))));
let result = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
if let &C(List(ref fval)) = result.as_ref() {
// we expect them to be a list of exactly 2 items.
if fval.len() != 2 {
return Err(dbg!(Error {}));
}
let name = match fval[0].as_ref() {
&P(Str(ref name)) => name.clone(),
_ => return Err(dbg!(Error {})),
};
new_fields.push((name, fval[1].clone()));
}
}
stack.push(Rc::new(C(Tuple(dbg!(new_fields)))));
}
&P(Str(ref s)) => {
let mut buf = String::new();
for c in s.chars() {
stack.push(Rc::new(P(Str(c.to_string()))));
// call function and push it's result on the stack.
let result = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
if let &P(Str(ref s)) = result.as_ref() {
buf.push_str(s);
} else {
return Err(dbg!(Error {}));
}
}
stack.push(Rc::new(P(Str(buf))));
}
_ => return Err(dbg!(Error {})),
};
Ok(()) Ok(())
} }

View File

@ -570,7 +570,6 @@ fn scope_stacks() {
} }
use super::translate; use super::translate;
use crate::ast::{Expression, Position, PositionedItem, Statement, Value as ASTValue};
use crate::iter::OffsetStrIter; use crate::iter::OffsetStrIter;
use crate::parse::parse; use crate::parse::parse;
@ -775,3 +774,27 @@ fn simple_trace() {
"TRACE: 1 + 1 = 2 at line: 1 column: 1\n" "TRACE: 1 + 1 = 2 at line: 1 column: 1\n"
); );
} }
#[test]
fn simple_maps() {
assert_parse_cases![
"map(func(el) => el, [1,2,3]);" => C(List(vec![
Rc::new(P(Int(1))),
Rc::new(P(Int(2))),
Rc::new(P(Int(3))),
])),
"map(func(el) => el + 1, [1,2,3]);" => C(List(vec![
Rc::new(P(Int(2))),
Rc::new(P(Int(3))),
Rc::new(P(Int(4))),
])),
"map(func(el) => el, \"foo\");" => P(Str("foo".to_owned())),
"map(func(el) => el + \"-\", \"foo\");" => P(Str("f-o-o-".to_owned())),
"map(func(k, v) => [k, v], {foo = 1});" => C(Tuple(vec![
("foo".to_owned(), Rc::new(P(Int(1)))),
])),
"map(func(k, v) => [k, v + 1], {foo = 1});" => C(Tuple(vec![
("foo".to_owned(), Rc::new(P(Int(2)))),
])),
];
}