Simplify match.
This commit is contained in:
parent
5eaa4c5240
commit
df05f43460
@ -288,8 +288,8 @@ pub enum Expr {
|
|||||||
Unit(Position),
|
Unit(Position),
|
||||||
/// Variable access - (optional long index, namespace, namespace hash, variable name), optional short index, position
|
/// Variable access - (optional long index, namespace, namespace hash, variable name), optional short index, position
|
||||||
///
|
///
|
||||||
/// The short index is [`u8`] which is used when the index is <= 255, which should be the vast
|
/// The short index is [`u8`] which is used when the index is <= 255, which should be
|
||||||
/// majority of cases (unless there are more than 255 variables defined!).
|
/// the vast majority of cases (unless there are more than 255 variables defined!).
|
||||||
/// This is to avoid reading a pointer redirection during each variable access.
|
/// This is to avoid reading a pointer redirection during each variable access.
|
||||||
Variable(
|
Variable(
|
||||||
Box<(Option<NonZeroUsize>, Namespace, u64, ImmutableString)>,
|
Box<(Option<NonZeroUsize>, Namespace, u64, ImmutableString)>,
|
||||||
@ -315,15 +315,15 @@ pub enum Expr {
|
|||||||
///
|
///
|
||||||
/// ### Flags
|
/// ### Flags
|
||||||
///
|
///
|
||||||
/// [`NEGATED`][ASTFlags::NEGATED] = `?.` (`.` if unset)
|
/// * [`NEGATED`][ASTFlags::NEGATED] = `?.` (`.` if unset)
|
||||||
/// [`BREAK`][ASTFlags::BREAK] = terminate the chain (recurse into the chain if unset)
|
/// * [`BREAK`][ASTFlags::BREAK] = terminate the chain (recurse into the chain if unset)
|
||||||
Dot(Box<BinaryExpr>, ASTFlags, Position),
|
Dot(Box<BinaryExpr>, ASTFlags, Position),
|
||||||
/// lhs `[` rhs `]`
|
/// lhs `[` rhs `]`
|
||||||
///
|
///
|
||||||
/// ### Flags
|
/// ### Flags
|
||||||
///
|
///
|
||||||
/// [`NEGATED`][ASTFlags::NEGATED] = `?[` ... `]` (`[` ... `]` if unset)
|
/// * [`NEGATED`][ASTFlags::NEGATED] = `?[` ... `]` (`[` ... `]` if unset)
|
||||||
/// [`BREAK`][ASTFlags::BREAK] = terminate the chain (recurse into the chain if unset)
|
/// * [`BREAK`][ASTFlags::BREAK] = terminate the chain (recurse into the chain if unset)
|
||||||
Index(Box<BinaryExpr>, ASTFlags, Position),
|
Index(Box<BinaryExpr>, ASTFlags, Position),
|
||||||
/// lhs `&&` rhs
|
/// lhs `&&` rhs
|
||||||
And(Box<BinaryExpr>, Position),
|
And(Box<BinaryExpr>, Position),
|
||||||
|
14
src/defer.rs
14
src/defer.rs
@ -65,8 +65,8 @@ macro_rules! defer {
|
|||||||
/// Run custom restoration logic upon the end of scope.
|
/// Run custom restoration logic upon the end of scope.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub struct Deferred<'a, T: ?Sized, R: FnOnce(&mut T)> {
|
pub struct Deferred<'a, T: ?Sized, R: FnOnce(&mut T)> {
|
||||||
value: &'a mut T,
|
lock: &'a mut T,
|
||||||
restore: Option<R>,
|
defer: Option<R>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized, R: FnOnce(&mut T)> Deferred<'a, T, R> {
|
impl<'a, T: ?Sized, R: FnOnce(&mut T)> Deferred<'a, T, R> {
|
||||||
@ -78,8 +78,8 @@ impl<'a, T: ?Sized, R: FnOnce(&mut T)> Deferred<'a, T, R> {
|
|||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn lock(value: &'a mut T, restore: R) -> Self {
|
pub fn lock(value: &'a mut T, restore: R) -> Self {
|
||||||
Self {
|
Self {
|
||||||
value,
|
lock: value,
|
||||||
restore: Some(restore),
|
defer: Some(restore),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,7 +87,7 @@ impl<'a, T: ?Sized, R: FnOnce(&mut T)> Deferred<'a, T, R> {
|
|||||||
impl<'a, T: ?Sized, R: FnOnce(&mut T)> Drop for Deferred<'a, T, R> {
|
impl<'a, T: ?Sized, R: FnOnce(&mut T)> Drop for Deferred<'a, T, R> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
self.restore.take().unwrap()(self.value);
|
self.defer.take().unwrap()(self.lock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,13 +96,13 @@ impl<'a, T: ?Sized, R: FnOnce(&mut T)> Deref for Deferred<'a, T, R> {
|
|||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
self.value
|
self.lock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized, R: FnOnce(&mut T)> DerefMut for Deferred<'a, T, R> {
|
impl<'a, T: ?Sized, R: FnOnce(&mut T)> DerefMut for Deferred<'a, T, R> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
self.value
|
self.lock
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -362,21 +362,14 @@ impl Engine {
|
|||||||
Expr::Property(..) if chain_type == ChainType::Dotting => (),
|
Expr::Property(..) if chain_type == ChainType::Dotting => (),
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Property(..) => unreachable!("unexpected Expr::Property for indexing"),
|
Expr::Property(..) => unreachable!("unexpected Expr::Property for indexing"),
|
||||||
// Short-circuit for simple method call: {expr}.func()
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
Expr::FnCall(x, ..) if chain_type == ChainType::Dotting && x.args.is_empty() => (),
|
|
||||||
// Short-circuit for method call with all literal arguments: {expr}.func(1, 2, 3)
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
Expr::FnCall(x, ..)
|
|
||||||
if chain_type == ChainType::Dotting && x.args.iter().all(Expr::is_constant) =>
|
|
||||||
{
|
|
||||||
idx_values.extend(x.args.iter().map(|expr| expr.get_literal_value().unwrap()))
|
|
||||||
}
|
|
||||||
// Short-circuit for indexing with literal: {expr}[1]
|
// Short-circuit for indexing with literal: {expr}[1]
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
_ if chain_type == ChainType::Indexing && rhs.is_constant() => {
|
_ if chain_type == ChainType::Indexing && rhs.is_constant() => {
|
||||||
idx_values.push(rhs.get_literal_value().unwrap())
|
idx_values.push(rhs.get_literal_value().unwrap())
|
||||||
}
|
}
|
||||||
|
// Short-circuit for simple method call: {expr}.func()
|
||||||
|
#[cfg(not(feature = "no_object"))]
|
||||||
|
Expr::MethodCall(x, ..) if chain_type == ChainType::Dotting && x.args.is_empty() => (),
|
||||||
// All other patterns - evaluate the arguments chain
|
// All other patterns - evaluate the arguments chain
|
||||||
_ => self.eval_dot_index_chain_arguments(
|
_ => self.eval_dot_index_chain_arguments(
|
||||||
global,
|
global,
|
||||||
@ -439,27 +432,25 @@ impl Engine {
|
|||||||
) -> RhaiResultOf<()> {
|
) -> RhaiResultOf<()> {
|
||||||
self.track_operation(global, expr.position())?;
|
self.track_operation(global, expr.position())?;
|
||||||
|
|
||||||
let chain_type = ChainType::from(parent);
|
match (expr, ChainType::from(parent)) {
|
||||||
|
|
||||||
match expr {
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::MethodCall(x, ..) if chain_type == ChainType::Dotting && !x.is_qualified() => {
|
(Expr::MethodCall(x, ..), ChainType::Dotting) => {
|
||||||
|
debug_assert!(
|
||||||
|
!x.is_qualified(),
|
||||||
|
"function call in dot chain should not be namespace-qualified"
|
||||||
|
);
|
||||||
|
|
||||||
for expr in &x.args {
|
for expr in &x.args {
|
||||||
let arg_value =
|
let arg_value =
|
||||||
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
|
self.get_arg_value(global, caches, scope, this_ptr.as_deref_mut(), expr)?;
|
||||||
idx_values.push(arg_value.0.flatten());
|
idx_values.push(arg_value.0.flatten());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
Expr::MethodCall(..) if chain_type == ChainType::Dotting => {
|
|
||||||
unreachable!("function call in dot chain should not be namespace-qualified")
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Property(..) if chain_type == ChainType::Dotting => (),
|
(Expr::Property(..), ChainType::Dotting) => (),
|
||||||
Expr::Property(..) => unreachable!("unexpected Expr::Property for indexing"),
|
|
||||||
|
|
||||||
Expr::Index(x, ..) | Expr::Dot(x, ..)
|
(Expr::Index(x, ..), chain_type) | (Expr::Dot(x, ..), chain_type)
|
||||||
if !parent.options().contains(ASTFlags::BREAK) =>
|
if !parent.options().contains(ASTFlags::BREAK) =>
|
||||||
{
|
{
|
||||||
let BinaryExpr { lhs, rhs, .. } = &**x;
|
let BinaryExpr { lhs, rhs, .. } = &**x;
|
||||||
@ -467,37 +458,34 @@ impl Engine {
|
|||||||
let mut _arg_values = FnArgsVec::new_const();
|
let mut _arg_values = FnArgsVec::new_const();
|
||||||
|
|
||||||
// Evaluate in left-to-right order
|
// Evaluate in left-to-right order
|
||||||
match lhs {
|
match (lhs, chain_type) {
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::Property(..) if chain_type == ChainType::Dotting => (),
|
(Expr::Property(..), ChainType::Dotting) => (),
|
||||||
Expr::Property(..) => unreachable!("unexpected Expr::Property for indexing"),
|
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
#[cfg(not(feature = "no_object"))]
|
||||||
Expr::MethodCall(x, ..)
|
(Expr::MethodCall(x, ..), ChainType::Dotting) => {
|
||||||
if chain_type == ChainType::Dotting && !x.is_qualified() =>
|
debug_assert!(
|
||||||
{
|
!x.is_qualified(),
|
||||||
|
"function call in dot chain should not be namespace-qualified"
|
||||||
|
);
|
||||||
|
|
||||||
for expr in &x.args {
|
for expr in &x.args {
|
||||||
let tp = this_ptr.as_deref_mut();
|
let tp = this_ptr.as_deref_mut();
|
||||||
let arg_value = self.get_arg_value(global, caches, scope, tp, expr)?;
|
let arg_value = self.get_arg_value(global, caches, scope, tp, expr)?;
|
||||||
_arg_values.push(arg_value.0.flatten());
|
_arg_values.push(arg_value.0.flatten());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
Expr::MethodCall(..) if chain_type == ChainType::Dotting => {
|
|
||||||
unreachable!("function call in dot chain should not be namespace-qualified")
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
expr if chain_type == ChainType::Dotting => {
|
|
||||||
unreachable!("invalid dot expression: {:?}", expr);
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
_ if chain_type == ChainType::Indexing => {
|
(_, ChainType::Indexing) => {
|
||||||
_arg_values.push(
|
_arg_values.push(
|
||||||
self.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), lhs)?
|
self.eval_expr(global, caches, scope, this_ptr.as_deref_mut(), lhs)?
|
||||||
.flatten(),
|
.flatten(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
expr => unreachable!("unknown chained expression: {:?}", expr),
|
#[allow(unreachable_patterns)]
|
||||||
|
(expr, chain_type) => {
|
||||||
|
unreachable!("unknown {:?} expression: {:?}", chain_type, expr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push in reverse order
|
// Push in reverse order
|
||||||
@ -508,16 +496,13 @@ impl Engine {
|
|||||||
idx_values.extend(_arg_values);
|
idx_values.extend(_arg_values);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(feature = "no_object"))]
|
|
||||||
_ if chain_type == ChainType::Dotting => {
|
|
||||||
unreachable!("invalid dot expression: {:?}", expr);
|
|
||||||
}
|
|
||||||
#[cfg(not(feature = "no_index"))]
|
#[cfg(not(feature = "no_index"))]
|
||||||
_ if chain_type == ChainType::Indexing => idx_values.push(
|
(_, ChainType::Indexing) => idx_values.push(
|
||||||
self.eval_expr(global, caches, scope, this_ptr, expr)?
|
self.eval_expr(global, caches, scope, this_ptr, expr)?
|
||||||
.flatten(),
|
.flatten(),
|
||||||
),
|
),
|
||||||
_ => unreachable!("unknown chained expression: {:?}", expr),
|
#[allow(unreachable_patterns)]
|
||||||
|
(expr, chain_type) => unreachable!("unknown {:?} expression: {:?}", chain_type, expr),
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -259,17 +259,18 @@ impl Engine {
|
|||||||
self.eval_fn_call_expr(global, caches, scope, this_ptr, x, *pos)
|
self.eval_fn_call_expr(global, caches, scope, this_ptr, x, *pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr::Variable(x, index, var_pos) => {
|
Expr::Variable(x, index, var_pos)
|
||||||
if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS {
|
if index.is_none() && x.0.is_none() && x.3 == KEYWORD_THIS =>
|
||||||
|
{
|
||||||
this_ptr
|
this_ptr
|
||||||
.ok_or_else(|| ERR::ErrorUnboundThis(*var_pos).into())
|
.ok_or_else(|| ERR::ErrorUnboundThis(*var_pos).into())
|
||||||
.cloned()
|
.cloned()
|
||||||
} else {
|
|
||||||
self.search_namespace(global, caches, scope, this_ptr, expr)
|
|
||||||
.map(Target::take_or_clone)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Expr::Variable(..) => self
|
||||||
|
.search_namespace(global, caches, scope, this_ptr, expr)
|
||||||
|
.map(Target::take_or_clone),
|
||||||
|
|
||||||
Expr::InterpolatedString(x, _) => {
|
Expr::InterpolatedString(x, _) => {
|
||||||
let mut concat = SmartString::new_const();
|
let mut concat = SmartString::new_const();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user