mirror of
https://github.com/zaphar/ucg.git
synced 2025-07-22 18:19:54 -04:00
BUGFIX: Regression tests for our list operators and bugfixes.
This commit is contained in:
parent
523e2db483
commit
f9cdd4f3f6
17
integration_tests/list_ops_test.ucg
Normal file
17
integration_tests/list_ops_test.ucg
Normal file
@ -0,0 +1,17 @@
|
||||
let list1 = [1, 2, 3, 4];
|
||||
let list2 = ["foo", "bar", "foo", "bar"];
|
||||
|
||||
let mapper = macro(item) => { result = item + 1 };
|
||||
let filtrator = macro(item) => {
|
||||
result = select item, NULL, {
|
||||
foo = item,
|
||||
},
|
||||
};
|
||||
|
||||
assert |map mapper.result list1 == [2, 3, 4, 5]|;
|
||||
assert |(map mapper.result [1, 2, 3, 4]) == [2, 3, 4, 5]|;
|
||||
assert |map mapper.result [1, 2, 3, 4] == [2, 3, 4, 5]|;
|
||||
|
||||
assert |filter filtrator.result list2 == ["foo", "foo"]|;
|
||||
assert |(filter filtrator.result ["foo", "bar", "foo", "bar"]) == ["foo", "foo"]|;
|
||||
assert |filter filtrator.result ["foo", "bar", "foo", "bar"] == ["foo", "foo"]|;
|
@ -691,7 +691,7 @@ pub struct ListOpDef {
|
||||
pub typ: ListOpType,
|
||||
pub mac: SelectorDef,
|
||||
pub field: String,
|
||||
pub target: ListDef,
|
||||
pub target: Box<Expression>,
|
||||
pub pos: Position,
|
||||
}
|
||||
|
||||
|
@ -61,3 +61,8 @@ fn test_binary_operator_precedence() {
|
||||
"../../integration_tests/operator_precedence_test.ucg"
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_list_operations() {
|
||||
assert_build(include_str!("../../integration_tests/list_ops_test.ucg"));
|
||||
}
|
||||
|
@ -1137,12 +1137,22 @@ impl<'a> Builder<'a> {
|
||||
}
|
||||
|
||||
fn eval_list_op(&self, def: &ListOpDef) -> Result<Rc<Val>, Box<Error>> {
|
||||
let l = &def.target.elems;
|
||||
let maybe_list = try!(self.eval_expr(&def.target));
|
||||
let l = match maybe_list.as_ref() {
|
||||
&Val::List(ref elems) => elems,
|
||||
other => {
|
||||
return Err(Box::new(error::Error::new(
|
||||
format!("Expected List as target but got {:?}", other.type_name()),
|
||||
error::ErrorType::TypeFail,
|
||||
def.target.pos().clone(),
|
||||
)));
|
||||
}
|
||||
};
|
||||
let mac = &def.mac;
|
||||
if let &Val::Macro(ref macdef) = try!(self.lookup_selector(&mac.sel)).as_ref() {
|
||||
let mut out = Vec::new();
|
||||
for expr in l.iter() {
|
||||
let argvals = vec![try!(self.eval_expr(expr))];
|
||||
let argvals = vec![expr.clone()];
|
||||
let fields = try!(macdef.eval(
|
||||
self.root.clone(),
|
||||
self.assets.clone(),
|
||||
|
@ -43,7 +43,7 @@ macro_rules! trace_nom {
|
||||
}
|
||||
let result = $rule($i, $($args)* );
|
||||
if ENABLE_TRACE {
|
||||
eprintln!("Exiting Rule: {:?}", stringify!($rule));
|
||||
eprintln!("Exiting Rule: {:?} with {:?}", stringify!($rule), result);
|
||||
}
|
||||
result
|
||||
}
|
||||
@ -57,7 +57,7 @@ macro_rules! trace_nom {
|
||||
}
|
||||
let result = call!($i, $rule);
|
||||
if ENABLE_TRACE {
|
||||
eprintln!("Exiting Rule: {:?}", stringify!($rule));
|
||||
eprintln!("Exiting Rule: {:?} with {:?}", stringify!($rule), result);
|
||||
}
|
||||
result
|
||||
}
|
||||
@ -636,31 +636,7 @@ named!(call_expression<TokenIter, Expression, error::Error>,
|
||||
)
|
||||
);
|
||||
|
||||
fn symbol_or_list(input: TokenIter) -> NomResult<Value> {
|
||||
let sym = do_parse!(input, sym: symbol >> (sym));
|
||||
|
||||
match sym {
|
||||
IResult::Incomplete(i) => {
|
||||
return IResult::Incomplete(i);
|
||||
}
|
||||
IResult::Error(_) => match list_value(input) {
|
||||
IResult::Incomplete(i) => {
|
||||
return IResult::Incomplete(i);
|
||||
}
|
||||
IResult::Error(e) => {
|
||||
return IResult::Error(e);
|
||||
}
|
||||
IResult::Done(i, val) => {
|
||||
return IResult::Done(i, val);
|
||||
}
|
||||
},
|
||||
IResult::Done(rest, val) => {
|
||||
return IResult::Done(rest, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tuple_to_list_op(tpl: (Position, Token, Value, Value)) -> ParseResult<Expression> {
|
||||
fn tuple_to_list_op(tpl: (Position, Token, Value, Expression)) -> ParseResult<Expression> {
|
||||
let pos = tpl.0;
|
||||
let t = if &tpl.1.fragment == "map" {
|
||||
ListOpType::Map
|
||||
@ -683,6 +659,12 @@ fn tuple_to_list_op(tpl: (Position, Token, Value, Value)) -> ParseResult<Express
|
||||
// two sections.
|
||||
let fieldname: String = match &mut def.sel.tail {
|
||||
&mut None => {
|
||||
if ENABLE_TRACE {
|
||||
eprintln!(
|
||||
"tuple_to_list_op had error {}",
|
||||
"Missing a result field for the macro"
|
||||
);
|
||||
}
|
||||
return Err(error::Error::new(
|
||||
format!("Missing a result field for the macro"),
|
||||
error::ErrorType::IncompleteParsing,
|
||||
@ -691,6 +673,12 @@ fn tuple_to_list_op(tpl: (Position, Token, Value, Value)) -> ParseResult<Express
|
||||
}
|
||||
&mut Some(ref mut tl) => {
|
||||
if tl.len() < 1 {
|
||||
if ENABLE_TRACE {
|
||||
eprintln!(
|
||||
"tuple_to_list_op had error {}",
|
||||
"Missing a result field for the macro"
|
||||
);
|
||||
}
|
||||
return Err(error::Error::new(
|
||||
format!("Missing a result field for the macro"),
|
||||
error::ErrorType::IncompleteParsing,
|
||||
@ -701,20 +689,19 @@ fn tuple_to_list_op(tpl: (Position, Token, Value, Value)) -> ParseResult<Express
|
||||
fname.unwrap().fragment
|
||||
}
|
||||
};
|
||||
if let Value::List(ldef) = list {
|
||||
return Ok(Expression::ListOp(ListOpDef {
|
||||
typ: t,
|
||||
mac: def,
|
||||
field: fieldname,
|
||||
target: ldef,
|
||||
pos: pos,
|
||||
}));
|
||||
}
|
||||
return Err(error::Error::new(
|
||||
format!("Expected a list but got {}", list.type_name()),
|
||||
error::ErrorType::UnexpectedToken,
|
||||
pos,
|
||||
));
|
||||
return Ok(Expression::ListOp(ListOpDef {
|
||||
typ: t,
|
||||
mac: def,
|
||||
field: fieldname,
|
||||
target: Box::new(list),
|
||||
pos: pos,
|
||||
}));
|
||||
}
|
||||
if ENABLE_TRACE {
|
||||
eprintln!(
|
||||
"tuple_to_list_op had error {}",
|
||||
format!("Expected a selector but got {}", macroname.type_name())
|
||||
);
|
||||
}
|
||||
return Err(error::Error::new(
|
||||
format!("Expected a selector but got {}", macroname.type_name()),
|
||||
@ -729,7 +716,7 @@ named!(list_op_expression<TokenIter, Expression, error::Error>,
|
||||
pos: pos >>
|
||||
optype: alt!(word!("map") | word!("filter")) >>
|
||||
macroname: trace_nom!(selector_value) >>
|
||||
list: trace_nom!(symbol_or_list) >>
|
||||
list: trace_nom!(non_op_expression) >>
|
||||
(pos, optype, macroname, list)
|
||||
),
|
||||
tuple_to_list_op
|
||||
@ -785,12 +772,7 @@ named!(let_statement<TokenIter, Statement, error::Error>,
|
||||
do_parse!(
|
||||
word!("let") >>
|
||||
pos: pos >>
|
||||
stmt: add_return_error!(
|
||||
nom::ErrorKind::Custom(
|
||||
error::Error::new(
|
||||
"Invalid syntax for let binding",
|
||||
error::ErrorType::ParseError, pos)),
|
||||
trace_nom!(let_stmt_body)) >>
|
||||
stmt: trace_nom!(let_stmt_body) >>
|
||||
(stmt)
|
||||
)
|
||||
);
|
||||
@ -819,12 +801,7 @@ named!(import_statement<TokenIter, Statement, error::Error>,
|
||||
word!("import") >>
|
||||
// past this point we know this is supposed to be an import statement.
|
||||
pos: pos >>
|
||||
stmt: add_return_error!(
|
||||
nom::ErrorKind::Custom(
|
||||
error::Error::new(
|
||||
"Invalid syntax for import",
|
||||
error::ErrorType::ParseError, pos)),
|
||||
trace_nom!(import_stmt_body)) >>
|
||||
stmt: trace_nom!(import_stmt_body) >>
|
||||
(stmt)
|
||||
)
|
||||
);
|
||||
@ -833,12 +810,7 @@ named!(assert_statement<TokenIter, Statement, error::Error>,
|
||||
do_parse!(
|
||||
word!("assert") >>
|
||||
pos: pos >>
|
||||
tok: add_return_error!(
|
||||
nom::ErrorKind::Custom(
|
||||
error::Error::new(
|
||||
"Invalid syntax for assert",
|
||||
error::ErrorType::ParseError, pos)),
|
||||
match_type!(PIPEQUOTE)) >>
|
||||
tok: match_type!(PIPEQUOTE) >>
|
||||
punct!(";") >>
|
||||
(Statement::Assert(tok.clone()))
|
||||
)
|
||||
@ -849,12 +821,7 @@ named!(out_statement<TokenIter, Statement, error::Error>,
|
||||
word!("out") >>
|
||||
pos: pos >>
|
||||
typ: match_type!(BAREWORD) >>
|
||||
expr: add_return_error!(
|
||||
nom::ErrorKind::Custom(
|
||||
error::Error::new(
|
||||
"Invalid syntax for assert",
|
||||
error::ErrorType::ParseError, pos)),
|
||||
expression) >>
|
||||
expr: expression >>
|
||||
punct!(";") >>
|
||||
(Statement::Output(typ.clone(), expr.clone()))
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user