mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-25 18:49:50 -04:00
DEV: Reduce works over lists, tuples, and string
This commit is contained in:
parent
b016b9294b
commit
d09bd13f42
@ -539,18 +539,6 @@ impl Builtins {
|
|||||||
} else {
|
} else {
|
||||||
return dbg!(Err(Error {}));
|
return dbg!(Err(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 accumulator from the stack
|
// Get the accumulator from the stack
|
||||||
let mut acc = if let Some(acc) = stack.pop() {
|
let mut acc = if let Some(acc) = stack.pop() {
|
||||||
acc
|
acc
|
||||||
@ -570,17 +558,41 @@ impl Builtins {
|
|||||||
return dbg!(Err(Error {}));
|
return dbg!(Err(Error {}));
|
||||||
};
|
};
|
||||||
|
|
||||||
for e in elems.iter() {
|
// TODO(jwall): This can also be tuples or strings.
|
||||||
// push function arguments on the stack.
|
match list.as_ref() {
|
||||||
stack.push(e.clone());
|
&C(List(ref elems)) => {
|
||||||
stack.push(acc.clone());
|
for e in dbg!(elems).iter() {
|
||||||
// call function and push it's result on the stack.
|
// push function arguments on the stack.
|
||||||
acc = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
|
stack.push(dbg!(e.clone()));
|
||||||
// Check for empty or boolean results and only push e back in
|
stack.push(dbg!(acc.clone()));
|
||||||
// if they are non empty and true
|
// call function and push it's result on the stack.
|
||||||
}
|
acc = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&C(Tuple(ref _flds)) => {
|
||||||
|
for (ref name, ref val) in _flds.iter() {
|
||||||
|
// push function arguments on the stack.
|
||||||
|
stack.push(val.clone());
|
||||||
|
stack.push(Rc::new(P(Str(name.clone()))));
|
||||||
|
stack.push(dbg!(acc.clone()));
|
||||||
|
// call function and push it's result on the stack.
|
||||||
|
acc = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&P(Str(ref _s)) => {
|
||||||
|
for c in _s.chars() {
|
||||||
|
// push function arguments on the stack.
|
||||||
|
stack.push(dbg!(Rc::new(P(Str(c.to_string())))));
|
||||||
|
stack.push(dbg!(acc.clone()));
|
||||||
|
// call function and push it's result on the stack.
|
||||||
|
acc = VM::fcall_impl(path.as_ref().to_owned(), f, stack, env.clone())?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(dbg!(Error {})),
|
||||||
|
};
|
||||||
|
|
||||||
// push the acc on the stack as our result
|
// push the acc on the stack as our result
|
||||||
stack.push(acc);
|
stack.push(dbg!(acc));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -827,3 +827,26 @@ fn simple_filters() {
|
|||||||
])),
|
])),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn simple_reduces() {
|
||||||
|
assert_parse_cases![
|
||||||
|
"reduce(func(acc, el) => acc + [el], [], [1,2,3]);" => C(List(vec![
|
||||||
|
Rc::new(P(Int(1))),
|
||||||
|
Rc::new(P(Int(2))),
|
||||||
|
Rc::new(P(Int(3))),
|
||||||
|
])),
|
||||||
|
"reduce(func(acc, el) => acc + [el+1], [], [1,2,3]);" => C(List(vec![
|
||||||
|
Rc::new(P(Int(2))),
|
||||||
|
Rc::new(P(Int(3))),
|
||||||
|
Rc::new(P(Int(4))),
|
||||||
|
])),
|
||||||
|
"reduce(func(acc, s) => acc + s, \"\", \"foo\");" => P(Str("foo".to_owned())),
|
||||||
|
"reduce(func(acc, k, v) => acc + [[k, v]], [], {foo = 1});" => C(List(vec![
|
||||||
|
Rc::new(C(List(vec![
|
||||||
|
Rc::new(P(Str("foo".to_owned()))),
|
||||||
|
Rc::new(P(Int(1))),
|
||||||
|
]))),
|
||||||
|
])),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
@ -456,7 +456,7 @@ where
|
|||||||
let left = self.pop()?;
|
let left = self.pop()?;
|
||||||
let right = self.pop()?;
|
let right = self.pop()?;
|
||||||
// Then pushes the result onto the stack.
|
// Then pushes the result onto the stack.
|
||||||
self.push(Rc::new(P(self.add(&left, &right)?)))?;
|
self.push(Rc::new(self.add(&left, &right)?))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -757,15 +757,25 @@ where
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&self, left: &Value, right: &Value) -> Result<Primitive, Error> {
|
fn add(&self, left: &Value, right: &Value) -> Result<Value, Error> {
|
||||||
Ok(match (left, right) {
|
Ok(match (left, right) {
|
||||||
(P(Int(i)), Value::P(Int(ii))) => Int(i + ii),
|
(P(Int(i)), Value::P(Int(ii))) => P(Int(i + ii)),
|
||||||
(P(Float(f)), Value::P(Float(ff))) => Float(f + ff),
|
(P(Float(f)), Value::P(Float(ff))) => P(Float(f + ff)),
|
||||||
(P(Str(s)), Value::P(Str(ss))) => {
|
(P(Str(s)), Value::P(Str(ss))) => {
|
||||||
let mut ns = String::new();
|
let mut ns = String::new();
|
||||||
ns.push_str(&s);
|
ns.push_str(&s);
|
||||||
ns.push_str(&ss);
|
ns.push_str(&ss);
|
||||||
Str(ns)
|
P(Str(ns))
|
||||||
|
}
|
||||||
|
(C(List(ref left_list)), C(List(ref right_list))) => {
|
||||||
|
let mut new_list = Vec::with_capacity(left_list.len() + right_list.len());
|
||||||
|
for v in left_list.iter() {
|
||||||
|
new_list.push(v.clone());
|
||||||
|
}
|
||||||
|
for v in right_list.iter() {
|
||||||
|
new_list.push(v.clone());
|
||||||
|
}
|
||||||
|
C(List(new_list))
|
||||||
}
|
}
|
||||||
_ => return Err(dbg!(Error {})),
|
_ => return Err(dbg!(Error {})),
|
||||||
})
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user