Unroll switch range case if range has only one number.
This commit is contained in:
parent
7ff50451cc
commit
1c50efbac8
@ -144,10 +144,17 @@ impl fmt::Debug for StmtBlock {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StmtBlock> for Stmt {
|
impl From<Stmt> for StmtBlock {
|
||||||
#[inline(always)]
|
#[inline]
|
||||||
fn from(block: StmtBlock) -> Self {
|
fn from(stmt: Stmt) -> Self {
|
||||||
Self::Block(block.0.into_boxed_slice(), block.1)
|
match stmt {
|
||||||
|
Stmt::Block(mut block, pos) => Self(block.iter_mut().map(mem::take).collect(), pos),
|
||||||
|
Stmt::Noop(pos) => Self(StaticVec::new_const(), pos),
|
||||||
|
_ => {
|
||||||
|
let pos = stmt.position();
|
||||||
|
Self(vec![stmt].into(), pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,7 +183,13 @@ pub enum Stmt {
|
|||||||
Noop(Position),
|
Noop(Position),
|
||||||
/// `if` expr `{` stmt `}` `else` `{` stmt `}`
|
/// `if` expr `{` stmt `}` `else` `{` stmt `}`
|
||||||
If(Expr, Box<(StmtBlock, StmtBlock)>, Position),
|
If(Expr, Box<(StmtBlock, StmtBlock)>, Position),
|
||||||
/// `switch` expr `if` condition `{` literal or _ `=>` stmt `,` ... `}`
|
/// `switch` expr `{` literal or range or _ `if` condition `=>` stmt `,` ... `}`
|
||||||
|
///
|
||||||
|
/// ### Data Structure
|
||||||
|
///
|
||||||
|
/// 0) Hash table for (condition, block)
|
||||||
|
/// 1) Default block
|
||||||
|
/// 2) List of ranges: (start, end, inclusive, condition, statement)
|
||||||
Switch(
|
Switch(
|
||||||
Expr,
|
Expr,
|
||||||
Box<(
|
Box<(
|
||||||
@ -262,17 +275,10 @@ impl Default for Stmt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Stmt> for StmtBlock {
|
impl From<StmtBlock> for Stmt {
|
||||||
#[inline]
|
#[inline(always)]
|
||||||
fn from(stmt: Stmt) -> Self {
|
fn from(block: StmtBlock) -> Self {
|
||||||
match stmt {
|
Self::Block(block.0.into_boxed_slice(), block.1)
|
||||||
Stmt::Block(mut block, pos) => Self(block.iter_mut().map(mem::take).collect(), pos),
|
|
||||||
Stmt::Noop(pos) => Self(StaticVec::new_const(), pos),
|
|
||||||
_ => {
|
|
||||||
let pos = stmt.position();
|
|
||||||
Self(vec![stmt].into(), pos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ use crate::tokenizer::{
|
|||||||
};
|
};
|
||||||
use crate::types::dynamic::AccessMode;
|
use crate::types::dynamic::AccessMode;
|
||||||
use crate::{
|
use crate::{
|
||||||
calc_fn_hash, calc_qualified_fn_hash, calc_qualified_var_hash, Engine, ExclusiveRange,
|
calc_fn_hash, calc_qualified_fn_hash, calc_qualified_var_hash, Dynamic, Engine, ExclusiveRange,
|
||||||
Identifier, ImmutableString, InclusiveRange, LexError, ParseError, ParseErrorType, Position,
|
Identifier, ImmutableString, InclusiveRange, LexError, ParseError, ParseErrorType, Position,
|
||||||
Scope, Shared, StaticVec, AST, INT,
|
Scope, Shared, StaticVec, AST, INT,
|
||||||
};
|
};
|
||||||
@ -1095,7 +1095,29 @@ fn parse_switch(
|
|||||||
|
|
||||||
def_stmt = match (hash, range) {
|
def_stmt = match (hash, range) {
|
||||||
(None, Some(range)) => {
|
(None, Some(range)) => {
|
||||||
ranges.push((range.0, range.1, range.2, condition, stmt.into()));
|
let is_empty = if range.2 {
|
||||||
|
(range.0..=range.1).is_empty()
|
||||||
|
} else {
|
||||||
|
(range.0..range.1).is_empty()
|
||||||
|
};
|
||||||
|
|
||||||
|
if !is_empty {
|
||||||
|
match (range.1.checked_sub(range.0), range.2) {
|
||||||
|
// Unroll single range
|
||||||
|
(Some(1), false) | (Some(0), true) => {
|
||||||
|
let value = Dynamic::from_int(range.0);
|
||||||
|
let hasher = &mut get_hasher();
|
||||||
|
value.hash(hasher);
|
||||||
|
let hash = hasher.finish();
|
||||||
|
|
||||||
|
if !table.contains_key(&hash) {
|
||||||
|
table.insert(hash, (condition.clone(), stmt.into()).into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Other range
|
||||||
|
_ => ranges.push((range.0, range.1, range.2, condition, stmt.into())),
|
||||||
|
}
|
||||||
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
(Some(hash), None) => {
|
(Some(hash), None) => {
|
||||||
@ -1103,9 +1125,7 @@ fn parse_switch(
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
(None, None) => Some(stmt.into()),
|
(None, None) => Some(stmt.into()),
|
||||||
(Some(_), Some(_)) => {
|
_ => unreachable!("both hash and range in `switch` statement case"),
|
||||||
unreachable!("cannot have both a hash and a range in a `switch` statement")
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
match input.peek().expect(NEVER_ENDS) {
|
match input.peek().expect(NEVER_ENDS) {
|
||||||
|
Loading…
Reference in New Issue
Block a user