Fix bug in dotting-indexing.

This commit is contained in:
Stephen Chung 2021-08-17 15:32:48 +08:00
parent 8a8bc2adfb
commit 224a2dfb60
2 changed files with 40 additions and 38 deletions

View File

@ -1697,52 +1697,51 @@ fn make_dot_expr(
(lhs, prop @ Expr::Property(_)) => {
Expr::Dot(BinaryExpr { lhs, rhs: prop }.into(), false, op_pos)
}
// lhs.dot_lhs.dot_rhs
(lhs, Expr::Dot(x, _, pos)) => match x.lhs {
Expr::Variable(_, _, _) | Expr::Property(_) => {
let rhs = Expr::Dot(
BinaryExpr {
// lhs.dot_lhs.dot_rhs or lhs.dot_lhs[idx_rhs]
(lhs, rhs @ Expr::Dot(_, _, _)) | (lhs, rhs @ Expr::Index(_, _, _)) => {
let (x, term, pos, is_dot) = match rhs {
Expr::Dot(x, term, pos) => (x, term, pos, true),
Expr::Index(x, term, pos) => (x, term, pos, false),
_ => unreachable!(),
};
match x.lhs {
Expr::Variable(_, _, _) | Expr::Property(_) => {
let new_lhs = BinaryExpr {
lhs: x.lhs.into_property(state),
rhs: x.rhs,
}
.into(),
false,
pos,
);
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
}
Expr::FnCall(mut func, func_pos) => {
// Recalculate hash
func.hashes = FnCallHashes::from_script_and_native(
calc_fn_hash(&func.name, func.args.len()),
calc_fn_hash(&func.name, func.args.len() + 1),
);
.into();
let rhs = Expr::Dot(
BinaryExpr {
let rhs = if is_dot {
Expr::Dot(new_lhs, term, pos)
} else {
Expr::Index(new_lhs, term, pos)
};
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
}
Expr::FnCall(mut func, func_pos) => {
// Recalculate hash
func.hashes = FnCallHashes::from_script_and_native(
calc_fn_hash(&func.name, func.args.len()),
calc_fn_hash(&func.name, func.args.len() + 1),
);
let new_lhs = BinaryExpr {
lhs: Expr::FnCall(func, func_pos),
rhs: x.rhs,
}
.into(),
false,
pos,
);
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
}
_ => unreachable!("invalid dot expression: {:?}", x.lhs),
},
// lhs.idx_lhs[idx_rhs]
(lhs, Expr::Index(x, term, pos)) => {
let rhs = Expr::Index(
BinaryExpr {
lhs: x.lhs.into_property(state),
rhs: x.rhs,
.into();
let rhs = if is_dot {
Expr::Dot(new_lhs, term, pos)
} else {
Expr::Index(new_lhs, term, pos)
};
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
}
.into(),
term,
pos,
);
Expr::Dot(BinaryExpr { lhs, rhs }.into(), false, op_pos)
_ => unreachable!("invalid dot expression: {:?}", x.lhs),
}
}
// lhs.nnn::func(...)
(_, Expr::FnCall(x, _)) if x.is_qualified() => {

View File

@ -168,6 +168,9 @@ fn test_array_with_structs() -> Result<(), Box<EvalAltResult>> {
fn test_arrays_map_reduce() -> Result<(), Box<EvalAltResult>> {
let engine = Engine::new();
assert_eq!(engine.eval::<INT>("[1].map(|x| x + 41)[0]")?, 42);
assert_eq!(engine.eval::<INT>("([1].map(|x| x + 41))[0]")?, 42);
assert_eq!(
convert_to_vec::<INT>(engine.eval(
"