From 224a2dfb6045031961c922f92e53afb316071cc8 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 17 Aug 2021 15:32:48 +0800 Subject: [PATCH] Fix bug in dotting-indexing. --- src/parse.rs | 75 ++++++++++++++++++++++++------------------------- tests/arrays.rs | 3 ++ 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/src/parse.rs b/src/parse.rs index 7162081d..a98154cc 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -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() => { diff --git a/tests/arrays.rs b/tests/arrays.rs index 486bfbe8..a230e561 100644 --- a/tests/arrays.rs +++ b/tests/arrays.rs @@ -168,6 +168,9 @@ fn test_array_with_structs() -> Result<(), Box> { fn test_arrays_map_reduce() -> Result<(), Box> { let engine = Engine::new(); + assert_eq!(engine.eval::("[1].map(|x| x + 41)[0]")?, 42); + assert_eq!(engine.eval::("([1].map(|x| x + 41))[0]")?, 42); + assert_eq!( convert_to_vec::(engine.eval( "