Add more range API's.

This commit is contained in:
Stephen Chung 2021-12-15 22:12:51 +08:00
parent 59a9ff0b0f
commit abbfa3777d
5 changed files with 42 additions and 28 deletions

View File

@ -5,6 +5,7 @@ Version 1.4.0
============= =============
This version adds support for integer _ranges_ via the `..` and `..=` operators. This version adds support for integer _ranges_ via the `..` and `..=` operators.
Many standard API's are extended with range parameters where appropriate.
New features New features
------------ ------------

View File

@ -1057,6 +1057,12 @@ impl StmtBlock {
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.0.len() 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. /// Get the position (location of the beginning `{`) of this statements block.
#[inline(always)] #[inline(always)]
#[must_use] #[must_use]

View File

@ -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 } // switch const { case if condition => stmt, _ => def } => if condition { stmt } else { def }
optimize_expr(&mut condition, state, false); optimize_expr(&mut condition, state, false);
let def_pos = if x.1.position().is_none() {
*pos
} else {
x.1.position()
};
let def_stmt = let def_stmt =
optimize_stmt_block(mem::take(&mut *x.1), state, true, true, false); 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, condition,
Box::new(( Box::new((
mem::take(&mut block.1), 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(), match_expr.position(),
); );
} else { } else {
// Promote the matched case // Promote the matched case
let new_pos = block.1.position();
let statements = let statements =
optimize_stmt_block(mem::take(&mut *block.1), state, true, true, false); 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(); 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 } // switch const { range if condition => stmt, _ => def } => if condition { stmt } else { def }
optimize_expr(&mut condition, state, false); optimize_expr(&mut condition, state, false);
let def_block = mem::take(&mut *x.1); let def_stmt =
let def_stmt = optimize_stmt_block(def_block, state, true, true, false); optimize_stmt_block(mem::take(&mut *x.1), state, true, true, false);
let def_pos = if x.1.position().is_none() {
*pos
} else {
x.1.position()
};
*stmt = Stmt::If( *stmt = Stmt::If(
condition, condition,
Box::new(( Box::new((
mem::take(stmt_block), 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(), match_expr.position(),
); );
} else { } else {
// Promote the matched case // Promote the matched case
let new_pos = stmt_block.position();
let statements = mem::take(&mut **stmt_block); let statements = mem::take(&mut **stmt_block);
let statements = let statements =
optimize_stmt_block(statements, state, true, true, false); 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(); 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 // Multiple ranges - clear the table and just keep the right ranges
if !table.is_empty() { if !table.is_empty() {
state.set_dirty(); state.set_dirty();
table.clear();
} }
table.clear();
let old_ranges_len = ranges.len(); let old_ranges_len = ranges.len();
ranges.retain(|&mut (start, end, inclusive, _, _)| { 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 // Promote the default case
state.set_dirty(); 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); 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 // switch
Stmt::Switch(match_expr, x, _) => { Stmt::Switch(match_expr, x, _) => {

View File

@ -542,10 +542,15 @@ mod range_functions {
range.contains(&value) range.contains(&value)
} }
#[rhai_fn(get = "is_inclusive", name = "is_inclusive", pure)] #[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; let _range = range;
false 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)] #[rhai_fn(get = "is_empty", name = "is_empty", pure)]
pub fn is_empty(range: &mut ExclusiveRange) -> bool { pub fn is_empty(range: &mut ExclusiveRange) -> bool {
range.is_empty() range.is_empty()
@ -571,4 +576,9 @@ mod range_functions {
let _range = range; let _range = range;
true true
} }
#[rhai_fn(get = "is_exclusive", name = "is_exclusive", pure)]
pub fn is_exclusive_inclusive(range: &mut InclusiveRange) -> bool {
let _range = range;
false
}
} }

View File

@ -213,6 +213,16 @@ impl Position {
#[cfg(feature = "no_position")] #[cfg(feature = "no_position")]
return true; 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. /// Print this [`Position`] for debug purposes.
#[inline] #[inline]
pub(crate) fn debug_print(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result { pub(crate) fn debug_print(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {