diff --git a/src/eval/chaining.rs b/src/eval/chaining.rs index a6184061..cda741a5 100644 --- a/src/eval/chaining.rs +++ b/src/eval/chaining.rs @@ -397,9 +397,10 @@ impl Engine { match lhs { // id.??? or id[???] Expr::Variable(.., var_pos) => { + self.track_operation(global, *var_pos)?; + #[cfg(feature = "debugging")] self.run_debugger(global, caches, scope, this_ptr.as_deref_mut(), lhs)?; - self.track_operation(global, *var_pos)?; let target = &mut self.search_namespace(global, caches, scope, this_ptr, lhs)?; diff --git a/src/eval/expr.rs b/src/eval/expr.rs index 540eb7a7..e728249e 100644 --- a/src/eval/expr.rs +++ b/src/eval/expr.rs @@ -236,8 +236,7 @@ impl Engine { mut this_ptr: Option<&mut Dynamic>, expr: &Expr, ) -> RhaiResult { - // Coded this way for better branch prediction. - // Popular branches are lifted out of the `match` statement into their own branches. + self.track_operation(global, expr.position())?; #[cfg(feature = "debugging")] let reset = @@ -245,8 +244,6 @@ impl Engine { #[cfg(feature = "debugging")] auto_restore! { global if Some(reset) => move |g| g.debugger_mut().reset_status(reset) } - self.track_operation(global, expr.position())?; - match expr { // Constants Expr::IntegerConstant(x, ..) => Ok((*x).into()), diff --git a/src/eval/stmt.rs b/src/eval/stmt.rs index 2410d036..2fdd5cec 100644 --- a/src/eval/stmt.rs +++ b/src/eval/stmt.rs @@ -267,14 +267,14 @@ impl Engine { stmt: &Stmt, rewind_scope: bool, ) -> RhaiResult { + self.track_operation(global, stmt.position())?; + #[cfg(feature = "debugging")] let reset = self.run_debugger_with_reset(global, caches, scope, this_ptr.as_deref_mut(), stmt)?; #[cfg(feature = "debugging")] auto_restore! { global if Some(reset) => move |g| g.debugger_mut().reset_status(reset) } - self.track_operation(global, stmt.position())?; - match stmt { // No-op Stmt::Noop(..) => Ok(Dynamic::UNIT), @@ -307,6 +307,8 @@ impl Engine { .eval_expr(global, caches, scope, this_ptr.as_deref_mut(), rhs)? .flatten(); + self.track_operation(global, lhs.position())?; + let mut target = self.search_namespace(global, caches, scope, this_ptr, lhs)?; let is_temp_result = !target.is_ref(); @@ -326,8 +328,6 @@ impl Engine { .into()); } - self.track_operation(global, lhs.position())?; - self.eval_op_assignment(global, caches, op_info, lhs, &mut target, rhs_val)?; } else { #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] @@ -715,8 +715,6 @@ impl Engine { *scope.get_mut_by_index(index).write_lock().unwrap() = value; // Run block - self.track_operation(global, body.position())?; - if body.is_empty() { continue; } diff --git a/src/func/call.rs b/src/func/call.rs index e5fa0507..e834b750 100644 --- a/src/func/call.rs +++ b/src/func/call.rs @@ -488,7 +488,7 @@ impl Engine { // index getter function not found? #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] crate::engine::FN_IDX_GET => { - assert!(args.len() == 2); + debug_assert_eq!(args.len(), 2); let t0 = self.map_type_name(args[0].type_name()); let t1 = self.map_type_name(args[1].type_name()); @@ -499,7 +499,7 @@ impl Engine { // index setter function not found? #[cfg(any(not(feature = "no_index"), not(feature = "no_object")))] crate::engine::FN_IDX_SET => { - assert!(args.len() == 3); + debug_assert_eq!(args.len(), 3); let t0 = self.map_type_name(args[0].type_name()); let t1 = self.map_type_name(args[1].type_name()); @@ -511,7 +511,7 @@ impl Engine { // Getter function not found? #[cfg(not(feature = "no_object"))] _ if name.starts_with(crate::engine::FN_GET) => { - assert!(args.len() == 1); + debug_assert_eq!(args.len(), 1); let prop = &name[crate::engine::FN_GET.len()..]; let t0 = self.map_type_name(args[0].type_name()); @@ -528,7 +528,7 @@ impl Engine { // Setter function not found? #[cfg(not(feature = "no_object"))] _ if name.starts_with(crate::engine::FN_SET) => { - assert!(args.len() == 2); + debug_assert_eq!(args.len(), 2); let prop = &name[crate::engine::FN_SET.len()..]; let t0 = self.map_type_name(args[0].type_name()); @@ -1365,10 +1365,11 @@ impl Engine { // Get target reference to first argument let first_arg = &args_expr[0]; - let target = self.search_scope_only(global, caches, scope, this_ptr, first_arg)?; self.track_operation(global, first_arg.position())?; + let target = self.search_scope_only(global, caches, scope, this_ptr, first_arg)?; + #[cfg(not(feature = "no_closure"))] let target_is_shared = target.is_shared(); #[cfg(feature = "no_closure")] @@ -1433,8 +1434,6 @@ impl Engine { }), ); - self.track_operation(global, pos)?; - if let Some(f) = module.get_qualified_fn(hash_qualified_fn) { func = Some(f); break; diff --git a/src/func/script.rs b/src/func/script.rs index 4d119cfc..d385f389 100644 --- a/src/func/script.rs +++ b/src/func/script.rs @@ -35,7 +35,7 @@ impl Engine { rewind_scope: bool, pos: Position, ) -> RhaiResult { - assert_eq!(fn_def.params.len(), args.len()); + debug_assert_eq!(fn_def.params.len(), args.len()); self.track_operation(global, pos)?; diff --git a/src/parser.rs b/src/parser.rs index 4209b6b5..64f5731e 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -3929,7 +3929,7 @@ impl Engine { let expr = self.parse_expr(&mut input, state, &mut functions, settings)?; #[cfg(feature = "no_function")] - assert!(functions.is_empty()); + debug_assert!(functions.is_empty()); match input.peek().expect(NEVER_ENDS) { (Token::EOF, ..) => (), diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 27d0cf6b..d82075fe 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -1219,12 +1219,12 @@ pub fn parse_string_literal( ch } None if verbatim => { - assert_eq!(escape, "", "verbatim strings should not have any escapes"); + debug_assert_eq!(escape, "", "verbatim strings should not have any escapes"); pos.advance(); break; } None if allow_line_continuation && !escape.is_empty() => { - assert_eq!(escape, "\\", "unexpected escape {escape} at end of line"); + debug_assert_eq!(escape, "\\", "unexpected escape {} at end of line", escape); pos.advance(); break; } @@ -1343,14 +1343,14 @@ pub fn parse_string_literal( // Verbatim '\n' if verbatim => { - assert_eq!(escape, "", "verbatim strings should not have any escapes"); + debug_assert_eq!(escape, "", "verbatim strings should not have any escapes"); pos.new_line(); result.push(next_char); } // Line continuation '\n' if allow_line_continuation && !escape.is_empty() => { - assert_eq!(escape, "\\", "unexpected escape {escape} at end of line"); + debug_assert_eq!(escape, "\\", "unexpected escape {} at end of line", escape); escape.clear(); pos.new_line();