From abbfa3777d649bfe8fc8a40b9b9a3a52c4c8dd1e Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Wed, 15 Dec 2021 22:12:51 +0800 Subject: [PATCH] Add more range API's. --- CHANGELOG.md | 1 + src/ast.rs | 6 ++++++ src/optimizer.rs | 41 +++++++++++++------------------------- src/packages/iter_basic.rs | 12 ++++++++++- src/tokenizer.rs | 10 ++++++++++ 5 files changed, 42 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64a35df2..ac70de93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Version 1.4.0 ============= This version adds support for integer _ranges_ via the `..` and `..=` operators. +Many standard API's are extended with range parameters where appropriate. New features ------------ diff --git a/src/ast.rs b/src/ast.rs index dc87ec79..8d7e19f1 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1057,6 +1057,12 @@ impl StmtBlock { pub fn len(&self) -> usize { self.0.len() } + /// Get the statements of this statements block. + #[inline(always)] + #[must_use] + pub fn statements(&self) -> &[Stmt] { + &self.0 + } /// Get the position (location of the beginning `{`) of this statements block. #[inline(always)] #[must_use] diff --git a/src/optimizer.rs b/src/optimizer.rs index c1170a35..304d4cbd 100644 --- a/src/optimizer.rs +++ b/src/optimizer.rs @@ -471,11 +471,6 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // switch const { case if condition => stmt, _ => def } => if condition { stmt } else { def } optimize_expr(&mut condition, state, false); - let def_pos = if x.1.position().is_none() { - *pos - } else { - x.1.position() - }; let def_stmt = optimize_stmt_block(mem::take(&mut *x.1), state, true, true, false); @@ -483,16 +478,16 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b condition, Box::new(( mem::take(&mut block.1), - Stmt::Block(def_stmt.into_boxed_slice(), def_pos).into(), + Stmt::Block(def_stmt.into_boxed_slice(), x.1.position().or_else(*pos)) + .into(), )), match_expr.position(), ); } else { // Promote the matched case - let new_pos = block.1.position(); let statements = optimize_stmt_block(mem::take(&mut *block.1), state, true, true, false); - *stmt = Stmt::Block(statements.into_boxed_slice(), new_pos); + *stmt = Stmt::Block(statements.into_boxed_slice(), block.1.position()); } state.set_dirty(); @@ -519,29 +514,27 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // switch const { range if condition => stmt, _ => def } => if condition { stmt } else { def } optimize_expr(&mut condition, state, false); - let def_block = mem::take(&mut *x.1); - let def_stmt = optimize_stmt_block(def_block, state, true, true, false); - let def_pos = if x.1.position().is_none() { - *pos - } else { - x.1.position() - }; - + let def_stmt = + optimize_stmt_block(mem::take(&mut *x.1), state, true, true, false); *stmt = Stmt::If( condition, Box::new(( mem::take(stmt_block), - Stmt::Block(def_stmt.into_boxed_slice(), def_pos).into(), + Stmt::Block( + def_stmt.into_boxed_slice(), + x.1.position().or_else(*pos), + ) + .into(), )), match_expr.position(), ); } else { // Promote the matched case - let new_pos = stmt_block.position(); let statements = mem::take(&mut **stmt_block); let statements = optimize_stmt_block(statements, state, true, true, false); - *stmt = Stmt::Block(statements.into_boxed_slice(), new_pos); + *stmt = + Stmt::Block(statements.into_boxed_slice(), stmt_block.position()); } state.set_dirty(); @@ -551,10 +544,9 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // Multiple ranges - clear the table and just keep the right ranges if !table.is_empty() { state.set_dirty(); + table.clear(); } - table.clear(); - let old_ranges_len = ranges.len(); ranges.retain(|&mut (start, end, inclusive, _, _)| { @@ -585,13 +577,8 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut OptimizerState, preserve_result: b // Promote the default case state.set_dirty(); - let def_pos = if x.1.position().is_none() { - *pos - } else { - x.1.position() - }; let def_stmt = optimize_stmt_block(mem::take(&mut *x.1), state, true, true, false); - *stmt = Stmt::Block(def_stmt.into_boxed_slice(), def_pos); + *stmt = Stmt::Block(def_stmt.into_boxed_slice(), x.1.position().or_else(*pos)); } // switch Stmt::Switch(match_expr, x, _) => { diff --git a/src/packages/iter_basic.rs b/src/packages/iter_basic.rs index c5a0941b..75538f63 100644 --- a/src/packages/iter_basic.rs +++ b/src/packages/iter_basic.rs @@ -542,10 +542,15 @@ mod range_functions { range.contains(&value) } #[rhai_fn(get = "is_inclusive", name = "is_inclusive", pure)] - pub fn range_is_inclusive(range: &mut ExclusiveRange) -> bool { + pub fn is_inclusive(range: &mut ExclusiveRange) -> bool { let _range = range; false } + #[rhai_fn(get = "is_exclusive", name = "is_exclusive", pure)] + pub fn is_exclusive(range: &mut ExclusiveRange) -> bool { + let _range = range; + true + } #[rhai_fn(get = "is_empty", name = "is_empty", pure)] pub fn is_empty(range: &mut ExclusiveRange) -> bool { range.is_empty() @@ -571,4 +576,9 @@ mod range_functions { let _range = range; true } + #[rhai_fn(get = "is_exclusive", name = "is_exclusive", pure)] + pub fn is_exclusive_inclusive(range: &mut InclusiveRange) -> bool { + let _range = range; + false + } } diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 4a3ab161..b49cbd68 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -213,6 +213,16 @@ impl Position { #[cfg(feature = "no_position")] return true; } + /// Returns an fallback [`Position`] if it is [`NONE`][Position::NONE]? + #[inline] + #[must_use] + pub const fn or_else(self, pos: Self) -> Self { + if self.is_none() { + pos + } else { + self + } + } /// Print this [`Position`] for debug purposes. #[inline] pub(crate) fn debug_print(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {