mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
REFACTOR: Add a little more abstraction for map and filter.
* Clearer and easier to follow code. * Smaller functions. * Easier to add future functionality.
This commit is contained in:
parent
d40f30dcf9
commit
ef01f166b2
@ -79,8 +79,10 @@ fn test_binary_operator_precedence() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_list_operations() {
|
fn test_functional_processing() {
|
||||||
assert_build(include_str!("../../integration_tests/list_ops_test.ucg"));
|
assert_build(include_str!(
|
||||||
|
"../../integration_tests/functional_processing_test.ucg"
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -1112,49 +1112,65 @@ impl<'a> FileBuilder<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_list_op(&mut self, def: &ListOpDef, scope: &Scope) -> Result<Rc<Val>, Box<dyn Error>> {
|
fn eval_functional_list_processing(
|
||||||
let maybe_list = self.eval_expr(&def.target, scope)?;
|
&mut self,
|
||||||
let l = match maybe_list.as_ref() {
|
elems: &Vec<Rc<Val>>,
|
||||||
&Val::List(ref elems) => elems,
|
def: &MacroDef,
|
||||||
other => {
|
outfield: &PositionedItem<String>,
|
||||||
return Err(Box::new(error::BuildError::new(
|
typ: &ListOpType,
|
||||||
format!("Expected List as target but got {:?}", other.type_name()),
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
error::ErrorType::TypeFail,
|
let mut out = Vec::new();
|
||||||
def.target.pos().clone(),
|
for item in elems.iter() {
|
||||||
)));
|
let argvals = vec![item.clone()];
|
||||||
}
|
let fields = def.eval(self.file.clone(), self, argvals)?;
|
||||||
};
|
if let Some(v) = find_in_fieldlist(&outfield.val, &fields) {
|
||||||
let mac_sym = Value::Symbol(def.mac.clone());
|
match typ {
|
||||||
if let &Val::Macro(ref macdef) = self.eval_value(&mac_sym, &self.scope.clone())?.as_ref() {
|
ListOpType::Map => {
|
||||||
let mut out = Vec::new();
|
out.push(v.clone());
|
||||||
for item in l.iter() {
|
}
|
||||||
let argvals = vec![item.clone()];
|
ListOpType::Filter => {
|
||||||
let fields = macdef.eval(self.file.clone(), self, argvals)?;
|
if let &Val::Empty = v.as_ref() {
|
||||||
if let Some(v) = find_in_fieldlist(&def.field.val, &fields) {
|
// noop
|
||||||
match def.typ {
|
continue;
|
||||||
ListOpType::Map => {
|
} else if let &Val::Boolean(false) = v.as_ref() {
|
||||||
out.push(v.clone());
|
// noop
|
||||||
}
|
continue;
|
||||||
ListOpType::Filter => {
|
|
||||||
if let &Val::Empty = v.as_ref() {
|
|
||||||
// noop
|
|
||||||
continue;
|
|
||||||
} else if let &Val::Boolean(false) = v.as_ref() {
|
|
||||||
// noop
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
out.push(item.clone());
|
|
||||||
}
|
}
|
||||||
|
out.push(item.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Ok(Rc::new(Val::List(out)));
|
|
||||||
}
|
}
|
||||||
return Err(Box::new(error::BuildError::new(
|
return Ok(Rc::new(Val::List(out)));
|
||||||
format!("Expected macro but got {:?}", def.mac),
|
}
|
||||||
error::ErrorType::TypeFail,
|
|
||||||
def.pos.clone(),
|
fn eval_functional_processing(
|
||||||
)));
|
&mut self,
|
||||||
|
def: &ListOpDef,
|
||||||
|
scope: &Scope,
|
||||||
|
) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
|
let maybe_list = self.eval_expr(&def.target, scope)?;
|
||||||
|
let maybe_mac = self.eval_value(&Value::Symbol(def.mac.clone()), &self.scope.clone())?;
|
||||||
|
let macdef = match maybe_mac.as_ref() {
|
||||||
|
&Val::Macro(ref macdef) => macdef,
|
||||||
|
_ => {
|
||||||
|
return Err(Box::new(error::BuildError::new(
|
||||||
|
format!("Expected macro but got {:?}", def.mac),
|
||||||
|
error::ErrorType::TypeFail,
|
||||||
|
def.pos.clone(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return match maybe_list.as_ref() {
|
||||||
|
&Val::List(ref elems) => {
|
||||||
|
self.eval_functional_list_processing(elems, macdef, &def.field, &def.typ)
|
||||||
|
}
|
||||||
|
other => Err(Box::new(error::BuildError::new(
|
||||||
|
format!("Expected List as target but got {:?}", other.type_name()),
|
||||||
|
error::ErrorType::TypeFail,
|
||||||
|
def.target.pos().clone(),
|
||||||
|
))),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_assert(&mut self, tok: &Token) -> Result<Rc<Val>, Box<dyn Error>> {
|
fn build_assert(&mut self, tok: &Token) -> Result<Rc<Val>, Box<dyn Error>> {
|
||||||
@ -1278,7 +1294,7 @@ impl<'a> FileBuilder<'a> {
|
|||||||
&Expression::Macro(ref def) => self.eval_macro_def(def),
|
&Expression::Macro(ref def) => self.eval_macro_def(def),
|
||||||
&Expression::Module(ref def) => self.eval_module_def(def, scope),
|
&Expression::Module(ref def) => self.eval_module_def(def, scope),
|
||||||
&Expression::Select(ref def) => self.eval_select(def, scope),
|
&Expression::Select(ref def) => self.eval_select(def, scope),
|
||||||
&Expression::ListOp(ref def) => self.eval_list_op(def, scope),
|
&Expression::ListOp(ref def) => self.eval_functional_processing(def, scope),
|
||||||
&Expression::Include(ref def) => self.eval_include(def),
|
&Expression::Include(ref def) => self.eval_include(def),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user