Simplify using ..
This commit is contained in:
@@ -53,7 +53,7 @@ impl fmt::Debug for AST {
|
||||
|
||||
#[cfg(not(feature = "no_function"))]
|
||||
if !self.lib.is_empty() {
|
||||
for (_, _, _, _, ref fn_def) in self.lib.iter_script_fn() {
|
||||
for (.., ref fn_def) in self.lib.iter_script_fn() {
|
||||
let sig = fn_def.to_string();
|
||||
fp.field(&sig, &fn_def.body.as_slice());
|
||||
}
|
||||
@@ -640,7 +640,7 @@ impl AST {
|
||||
pub fn iter_fn_def(&self) -> impl Iterator<Item = &super::ScriptFnDef> {
|
||||
self.lib
|
||||
.iter_script_fn()
|
||||
.map(|(_, _, _, _, fn_def)| fn_def.as_ref())
|
||||
.map(|(.., fn_def)| fn_def.as_ref())
|
||||
}
|
||||
/// Iterate through all function definitions.
|
||||
///
|
||||
@@ -652,7 +652,7 @@ impl AST {
|
||||
pub(crate) fn iter_fn_def(&self) -> impl Iterator<Item = &super::ScriptFnDef> {
|
||||
self.lib
|
||||
.iter_script_fn()
|
||||
.map(|(_, _, _, _, fn_def)| fn_def.as_ref())
|
||||
.map(|(.., fn_def)| fn_def.as_ref())
|
||||
}
|
||||
/// Iterate through all function definitions.
|
||||
///
|
||||
@@ -662,7 +662,7 @@ impl AST {
|
||||
pub fn iter_functions<'a>(&'a self) -> impl Iterator<Item = super::ScriptFnMetadata> + 'a {
|
||||
self.lib
|
||||
.iter_script_fn()
|
||||
.map(|(_, _, _, _, fn_def)| fn_def.as_ref().into())
|
||||
.map(|(.., fn_def)| fn_def.as_ref().into())
|
||||
}
|
||||
/// Clear all function definitions in the [`AST`].
|
||||
///
|
||||
@@ -744,7 +744,7 @@ impl AST {
|
||||
include_variables: bool,
|
||||
) -> impl Iterator<Item = (&str, bool, Dynamic)> {
|
||||
self.statements().iter().filter_map(move |stmt| match stmt {
|
||||
Stmt::Var(expr, name, options, _)
|
||||
Stmt::Var(expr, name, options, ..)
|
||||
if options.contains(AST_OPTION_CONSTANT) && include_constants
|
||||
|| !options.contains(AST_OPTION_CONSTANT) && include_variables =>
|
||||
{
|
||||
|
270
src/ast/expr.rs
270
src/ast/expr.rs
@@ -443,24 +443,24 @@ impl fmt::Debug for Expr {
|
||||
let mut display_pos = self.start_position();
|
||||
|
||||
match self {
|
||||
Self::DynamicConstant(value, _) => write!(f, "{:?}", value),
|
||||
Self::BoolConstant(value, _) => write!(f, "{:?}", value),
|
||||
Self::IntegerConstant(value, _) => write!(f, "{:?}", value),
|
||||
Self::DynamicConstant(value, ..) => write!(f, "{:?}", value),
|
||||
Self::BoolConstant(value, ..) => write!(f, "{:?}", value),
|
||||
Self::IntegerConstant(value, ..) => write!(f, "{:?}", value),
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Self::FloatConstant(value, _) => write!(f, "{:?}", value),
|
||||
Self::CharConstant(value, _) => write!(f, "{:?}", value),
|
||||
Self::StringConstant(value, _) => write!(f, "{:?}", value),
|
||||
Self::FloatConstant(value, ..) => write!(f, "{:?}", value),
|
||||
Self::CharConstant(value, ..) => write!(f, "{:?}", value),
|
||||
Self::StringConstant(value, ..) => write!(f, "{:?}", value),
|
||||
Self::Unit(_) => f.write_str("()"),
|
||||
|
||||
Self::InterpolatedString(x, _) => {
|
||||
Self::InterpolatedString(x, ..) => {
|
||||
f.write_str("InterpolatedString")?;
|
||||
return f.debug_list().entries(x.iter()).finish();
|
||||
}
|
||||
Self::Array(x, _) => {
|
||||
Self::Array(x, ..) => {
|
||||
f.write_str("Array")?;
|
||||
f.debug_list().entries(x.iter()).finish()
|
||||
}
|
||||
Self::Map(x, _) => {
|
||||
Self::Map(x, ..) => {
|
||||
f.write_str("Map")?;
|
||||
f.debug_map()
|
||||
.entries(x.0.iter().map(|(k, v)| (k, v)))
|
||||
@@ -470,7 +470,7 @@ impl fmt::Debug for Expr {
|
||||
f.write_str("Variable(")?;
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
if let Some((_, ref namespace)) = x.1 {
|
||||
if let Some((.., ref namespace)) = x.1 {
|
||||
write!(f, "{}{}", namespace, Token::DoubleColon.literal_syntax())?
|
||||
}
|
||||
f.write_str(&x.2)?;
|
||||
@@ -479,13 +479,13 @@ impl fmt::Debug for Expr {
|
||||
}
|
||||
f.write_str(")")
|
||||
}
|
||||
Self::Property(x, _) => write!(f, "Property({})", x.2),
|
||||
Self::Stack(x, _) => write!(f, "ConstantArg#{}", x),
|
||||
Self::Property(x, ..) => write!(f, "Property({})", x.2),
|
||||
Self::Stack(x, ..) => write!(f, "ConstantArg#{}", x),
|
||||
Self::Stmt(x) => {
|
||||
f.write_str("ExprStmtBlock")?;
|
||||
f.debug_list().entries(x.iter()).finish()
|
||||
}
|
||||
Self::FnCall(x, _) => fmt::Debug::fmt(x, f),
|
||||
Self::FnCall(x, ..) => fmt::Debug::fmt(x, f),
|
||||
Self::Index(x, term, pos) => {
|
||||
display_pos = *pos;
|
||||
|
||||
@@ -497,9 +497,9 @@ impl fmt::Debug for Expr {
|
||||
}
|
||||
Self::Dot(x, _, pos) | Self::And(x, pos) | Self::Or(x, pos) => {
|
||||
let op_name = match self {
|
||||
Self::Dot(_, _, _) => "Dot",
|
||||
Self::And(_, _) => "And",
|
||||
Self::Or(_, _) => "Or",
|
||||
Self::Dot(..) => "Dot",
|
||||
Self::And(..) => "And",
|
||||
Self::Or(..) => "Or",
|
||||
expr => unreachable!(
|
||||
"Self::Dot or Self::And or Self::Or expected but gets {:?}",
|
||||
expr
|
||||
@@ -513,7 +513,7 @@ impl fmt::Debug for Expr {
|
||||
.field("rhs", &x.rhs)
|
||||
.finish()
|
||||
}
|
||||
Self::Custom(x, _) => f.debug_tuple("Custom").field(x).finish(),
|
||||
Self::Custom(x, ..) => f.debug_tuple("Custom").field(x).finish(),
|
||||
}?;
|
||||
|
||||
display_pos.debug_print(f)
|
||||
@@ -528,24 +528,24 @@ impl Expr {
|
||||
#[must_use]
|
||||
pub fn get_literal_value(&self) -> Option<Dynamic> {
|
||||
Some(match self {
|
||||
Self::DynamicConstant(x, _) => x.as_ref().clone(),
|
||||
Self::IntegerConstant(x, _) => (*x).into(),
|
||||
Self::DynamicConstant(x, ..) => x.as_ref().clone(),
|
||||
Self::IntegerConstant(x, ..) => (*x).into(),
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Self::FloatConstant(x, _) => (*x).into(),
|
||||
Self::CharConstant(x, _) => (*x).into(),
|
||||
Self::StringConstant(x, _) => x.clone().into(),
|
||||
Self::BoolConstant(x, _) => (*x).into(),
|
||||
Self::FloatConstant(x, ..) => (*x).into(),
|
||||
Self::CharConstant(x, ..) => (*x).into(),
|
||||
Self::StringConstant(x, ..) => x.clone().into(),
|
||||
Self::BoolConstant(x, ..) => (*x).into(),
|
||||
Self::Unit(_) => Dynamic::UNIT,
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Self::Array(x, _) if self.is_constant() => {
|
||||
Self::Array(x, ..) if self.is_constant() => {
|
||||
let mut arr = crate::Array::with_capacity(x.len());
|
||||
arr.extend(x.iter().map(|v| v.get_literal_value().unwrap()));
|
||||
Dynamic::from_array(arr)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Self::Map(x, _) if self.is_constant() => {
|
||||
Self::Map(x, ..) if self.is_constant() => {
|
||||
Dynamic::from_map(x.0.iter().fold(x.1.clone(), |mut map, (k, v)| {
|
||||
let value_ref = map.get_mut(k.name.as_str()).unwrap();
|
||||
*value_ref = v.get_literal_value().unwrap();
|
||||
@@ -554,10 +554,10 @@ impl Expr {
|
||||
}
|
||||
|
||||
// Fn
|
||||
Self::FnCall(ref x, _)
|
||||
Self::FnCall(ref x, ..)
|
||||
if !x.is_qualified() && x.args.len() == 1 && x.name == KEYWORD_FN_PTR =>
|
||||
{
|
||||
if let Expr::StringConstant(ref s, _) = x.args[0] {
|
||||
if let Expr::StringConstant(ref s, ..) = x.args[0] {
|
||||
if let Ok(fn_ptr) = FnPtr::new(s) {
|
||||
fn_ptr.into()
|
||||
} else {
|
||||
@@ -569,33 +569,35 @@ impl Expr {
|
||||
}
|
||||
|
||||
// Binary operators
|
||||
Self::FnCall(x, _) if !x.is_qualified() && x.args.len() == 2 => match x.name.as_str() {
|
||||
// x..y
|
||||
OP_EXCLUSIVE_RANGE => {
|
||||
if let Expr::IntegerConstant(ref start, _) = x.args[0] {
|
||||
if let Expr::IntegerConstant(ref end, _) = x.args[1] {
|
||||
(*start..*end).into()
|
||||
Self::FnCall(x, ..) if !x.is_qualified() && x.args.len() == 2 => {
|
||||
match x.name.as_str() {
|
||||
// x..y
|
||||
OP_EXCLUSIVE_RANGE => {
|
||||
if let Expr::IntegerConstant(ref start, ..) = x.args[0] {
|
||||
if let Expr::IntegerConstant(ref end, ..) = x.args[1] {
|
||||
(*start..*end).into()
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
// x..=y
|
||||
OP_INCLUSIVE_RANGE => {
|
||||
if let Expr::IntegerConstant(ref start, _) = x.args[0] {
|
||||
if let Expr::IntegerConstant(ref end, _) = x.args[1] {
|
||||
(*start..=*end).into()
|
||||
// x..=y
|
||||
OP_INCLUSIVE_RANGE => {
|
||||
if let Expr::IntegerConstant(ref start, ..) = x.args[0] {
|
||||
if let Expr::IntegerConstant(ref end, ..) = x.args[1] {
|
||||
(*start..=*end).into()
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
_ => return None,
|
||||
}
|
||||
_ => return None,
|
||||
},
|
||||
}
|
||||
|
||||
_ => return None,
|
||||
})
|
||||
@@ -605,25 +607,25 @@ impl Expr {
|
||||
#[must_use]
|
||||
pub fn from_dynamic(value: Dynamic, pos: Position) -> Self {
|
||||
match value.0 {
|
||||
Union::Unit(_, _, _) => Self::Unit(pos),
|
||||
Union::Bool(b, _, _) => Self::BoolConstant(b, pos),
|
||||
Union::Str(s, _, _) => Self::StringConstant(s, pos),
|
||||
Union::Char(c, _, _) => Self::CharConstant(c, pos),
|
||||
Union::Int(i, _, _) => Self::IntegerConstant(i, pos),
|
||||
Union::Unit(..) => Self::Unit(pos),
|
||||
Union::Bool(b, ..) => Self::BoolConstant(b, pos),
|
||||
Union::Str(s, ..) => Self::StringConstant(s, pos),
|
||||
Union::Char(c, ..) => Self::CharConstant(c, pos),
|
||||
Union::Int(i, ..) => Self::IntegerConstant(i, pos),
|
||||
|
||||
#[cfg(feature = "decimal")]
|
||||
Union::Decimal(value, _, _) => Self::DynamicConstant(Box::new((*value).into()), pos),
|
||||
Union::Decimal(value, ..) => Self::DynamicConstant(Box::new((*value).into()), pos),
|
||||
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Union::Float(f, _, _) => Self::FloatConstant(f, pos),
|
||||
Union::Float(f, ..) => Self::FloatConstant(f, pos),
|
||||
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Union::Array(a, _, _) => Self::DynamicConstant(Box::new((*a).into()), pos),
|
||||
Union::Array(a, ..) => Self::DynamicConstant(Box::new((*a).into()), pos),
|
||||
|
||||
#[cfg(not(feature = "no_object"))]
|
||||
Union::Map(m, _, _) => Self::DynamicConstant(Box::new((*m).into()), pos),
|
||||
Union::Map(m, ..) => Self::DynamicConstant(Box::new((*m).into()), pos),
|
||||
|
||||
Union::FnPtr(f, _, _) if !f.is_curried() => Self::FnCall(
|
||||
Union::FnPtr(f, ..) if !f.is_curried() => Self::FnCall(
|
||||
FnCallExpr {
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
namespace: None,
|
||||
@@ -651,8 +653,8 @@ impl Expr {
|
||||
|
||||
match self {
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Variable(_, _, x) if _non_qualified && x.1.is_some() => false,
|
||||
Self::Variable(_, _, _) => true,
|
||||
Self::Variable(.., x) if _non_qualified && x.1.is_some() => false,
|
||||
Self::Variable(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -666,8 +668,8 @@ impl Expr {
|
||||
|
||||
match self {
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Variable(_, _, x) if _non_qualified && x.1.is_some() => None,
|
||||
Self::Variable(_, _, x) => Some(x.2.as_str()),
|
||||
Self::Variable(.., x) if _non_qualified && x.1.is_some() => None,
|
||||
Self::Variable(.., x) => Some(x.2.as_str()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -677,27 +679,27 @@ impl Expr {
|
||||
pub const fn position(&self) -> Position {
|
||||
match self {
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Self::FloatConstant(_, pos) => *pos,
|
||||
Self::FloatConstant(.., pos) => *pos,
|
||||
|
||||
Self::DynamicConstant(_, pos)
|
||||
| Self::BoolConstant(_, pos)
|
||||
| Self::IntegerConstant(_, pos)
|
||||
| Self::CharConstant(_, pos)
|
||||
Self::DynamicConstant(.., pos)
|
||||
| Self::BoolConstant(.., pos)
|
||||
| Self::IntegerConstant(.., pos)
|
||||
| Self::CharConstant(.., pos)
|
||||
| Self::Unit(pos)
|
||||
| Self::StringConstant(_, pos)
|
||||
| Self::Array(_, pos)
|
||||
| Self::Map(_, pos)
|
||||
| Self::Variable(_, pos, _)
|
||||
| Self::Stack(_, pos)
|
||||
| Self::And(_, pos)
|
||||
| Self::Or(_, pos)
|
||||
| Self::Index(_, _, pos)
|
||||
| Self::Dot(_, _, pos)
|
||||
| Self::Custom(_, pos)
|
||||
| Self::InterpolatedString(_, pos)
|
||||
| Self::Property(_, pos) => *pos,
|
||||
| Self::StringConstant(.., pos)
|
||||
| Self::Array(.., pos)
|
||||
| Self::Map(.., pos)
|
||||
| Self::Variable(.., pos, _)
|
||||
| Self::Stack(.., pos)
|
||||
| Self::And(.., pos)
|
||||
| Self::Or(.., pos)
|
||||
| Self::Index(.., pos)
|
||||
| Self::Dot(.., pos)
|
||||
| Self::Custom(.., pos)
|
||||
| Self::InterpolatedString(.., pos)
|
||||
| Self::Property(.., pos) => *pos,
|
||||
|
||||
Self::FnCall(x, _) => x.pos,
|
||||
Self::FnCall(x, ..) => x.pos,
|
||||
|
||||
Self::Stmt(x) => x.position(),
|
||||
}
|
||||
@@ -708,10 +710,10 @@ impl Expr {
|
||||
#[must_use]
|
||||
pub const fn start_position(&self) -> Position {
|
||||
match self {
|
||||
Self::And(x, _) | Self::Or(x, _) | Self::Index(x, _, _) | Self::Dot(x, _, _) => {
|
||||
Self::And(x, ..) | Self::Or(x, ..) | Self::Index(x, ..) | Self::Dot(x, ..) => {
|
||||
x.lhs.start_position()
|
||||
}
|
||||
Self::FnCall(_, pos) => *pos,
|
||||
Self::FnCall(.., pos) => *pos,
|
||||
_ => self.position(),
|
||||
}
|
||||
}
|
||||
@@ -720,26 +722,26 @@ impl Expr {
|
||||
pub fn set_position(&mut self, new_pos: Position) -> &mut Self {
|
||||
match self {
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Self::FloatConstant(_, pos) => *pos = new_pos,
|
||||
Self::FloatConstant(.., pos) => *pos = new_pos,
|
||||
|
||||
Self::DynamicConstant(_, pos)
|
||||
| Self::BoolConstant(_, pos)
|
||||
| Self::IntegerConstant(_, pos)
|
||||
| Self::CharConstant(_, pos)
|
||||
Self::DynamicConstant(.., pos)
|
||||
| Self::BoolConstant(.., pos)
|
||||
| Self::IntegerConstant(.., pos)
|
||||
| Self::CharConstant(.., pos)
|
||||
| Self::Unit(pos)
|
||||
| Self::StringConstant(_, pos)
|
||||
| Self::Array(_, pos)
|
||||
| Self::Map(_, pos)
|
||||
| Self::And(_, pos)
|
||||
| Self::Or(_, pos)
|
||||
| Self::Dot(_, _, pos)
|
||||
| Self::Index(_, _, pos)
|
||||
| Self::Variable(_, pos, _)
|
||||
| Self::Stack(_, pos)
|
||||
| Self::FnCall(_, pos)
|
||||
| Self::Custom(_, pos)
|
||||
| Self::InterpolatedString(_, pos)
|
||||
| Self::Property(_, pos) => *pos = new_pos,
|
||||
| Self::StringConstant(.., pos)
|
||||
| Self::Array(.., pos)
|
||||
| Self::Map(.., pos)
|
||||
| Self::And(.., pos)
|
||||
| Self::Or(.., pos)
|
||||
| Self::Dot(.., pos)
|
||||
| Self::Index(.., pos)
|
||||
| Self::Variable(.., pos, _)
|
||||
| Self::Stack(.., pos)
|
||||
| Self::FnCall(.., pos)
|
||||
| Self::Custom(.., pos)
|
||||
| Self::InterpolatedString(.., pos)
|
||||
| Self::Property(.., pos) => *pos = new_pos,
|
||||
|
||||
Self::Stmt(x) => x.set_position(new_pos, Position::NONE),
|
||||
}
|
||||
@@ -753,15 +755,15 @@ impl Expr {
|
||||
#[must_use]
|
||||
pub fn is_pure(&self) -> bool {
|
||||
match self {
|
||||
Self::InterpolatedString(x, _) | Self::Array(x, _) => x.iter().all(Self::is_pure),
|
||||
Self::InterpolatedString(x, ..) | Self::Array(x, ..) => x.iter().all(Self::is_pure),
|
||||
|
||||
Self::Map(x, _) => x.0.iter().map(|(_, v)| v).all(Self::is_pure),
|
||||
Self::Map(x, ..) => x.0.iter().map(|(.., v)| v).all(Self::is_pure),
|
||||
|
||||
Self::And(x, _) | Self::Or(x, _) => x.lhs.is_pure() && x.rhs.is_pure(),
|
||||
Self::And(x, ..) | Self::Or(x, ..) => x.lhs.is_pure() && x.rhs.is_pure(),
|
||||
|
||||
Self::Stmt(x) => x.iter().all(Stmt::is_pure),
|
||||
|
||||
Self::Variable(_, _, _) | Self::Stack(_, _) => true,
|
||||
Self::Variable(..) | Self::Stack(..) => true,
|
||||
|
||||
_ => self.is_constant(),
|
||||
}
|
||||
@@ -778,19 +780,19 @@ impl Expr {
|
||||
pub fn is_constant(&self) -> bool {
|
||||
match self {
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Self::FloatConstant(_, _) => true,
|
||||
Self::FloatConstant(..) => true,
|
||||
|
||||
Self::DynamicConstant(_, _)
|
||||
| Self::BoolConstant(_, _)
|
||||
| Self::IntegerConstant(_, _)
|
||||
| Self::CharConstant(_, _)
|
||||
| Self::StringConstant(_, _)
|
||||
Self::DynamicConstant(..)
|
||||
| Self::BoolConstant(..)
|
||||
| Self::IntegerConstant(..)
|
||||
| Self::CharConstant(..)
|
||||
| Self::StringConstant(..)
|
||||
| Self::Unit(_)
|
||||
| Self::Stack(_, _) => true,
|
||||
| Self::Stack(..) => true,
|
||||
|
||||
Self::InterpolatedString(x, _) | Self::Array(x, _) => x.iter().all(Self::is_constant),
|
||||
Self::InterpolatedString(x, ..) | Self::Array(x, ..) => x.iter().all(Self::is_constant),
|
||||
|
||||
Self::Map(x, _) => x.0.iter().map(|(_, expr)| expr).all(Self::is_constant),
|
||||
Self::Map(x, ..) => x.0.iter().map(|(.., expr)| expr).all(Self::is_constant),
|
||||
|
||||
_ => false,
|
||||
}
|
||||
@@ -807,31 +809,31 @@ impl Expr {
|
||||
|
||||
match self {
|
||||
#[cfg(not(feature = "no_float"))]
|
||||
Self::FloatConstant(_, _) => false,
|
||||
Self::FloatConstant(..) => false,
|
||||
|
||||
Self::DynamicConstant(_, _)
|
||||
| Self::BoolConstant(_, _)
|
||||
| Self::CharConstant(_, _)
|
||||
| Self::And(_, _)
|
||||
| Self::Or(_, _)
|
||||
Self::DynamicConstant(..)
|
||||
| Self::BoolConstant(..)
|
||||
| Self::CharConstant(..)
|
||||
| Self::And(..)
|
||||
| Self::Or(..)
|
||||
| Self::Unit(_) => false,
|
||||
|
||||
Self::IntegerConstant(_, _)
|
||||
| Self::StringConstant(_, _)
|
||||
| Self::InterpolatedString(_, _)
|
||||
| Self::FnCall(_, _)
|
||||
Self::IntegerConstant(..)
|
||||
| Self::StringConstant(..)
|
||||
| Self::InterpolatedString(..)
|
||||
| Self::FnCall(..)
|
||||
| Self::Stmt(_)
|
||||
| Self::Dot(_, _, _)
|
||||
| Self::Index(_, _, _)
|
||||
| Self::Array(_, _)
|
||||
| Self::Map(_, _)
|
||||
| Self::Custom(_, _) => match token {
|
||||
| Self::Dot(..)
|
||||
| Self::Index(..)
|
||||
| Self::Array(..)
|
||||
| Self::Map(..)
|
||||
| Self::Custom(..) => match token {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Token::LeftBracket => true,
|
||||
_ => false,
|
||||
},
|
||||
|
||||
Self::Variable(_, _, _) => match token {
|
||||
Self::Variable(..) => match token {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Token::LeftBracket => true,
|
||||
Token::LeftParen => true,
|
||||
@@ -840,14 +842,14 @@ impl Expr {
|
||||
_ => false,
|
||||
},
|
||||
|
||||
Self::Property(_, _) => match token {
|
||||
Self::Property(..) => match token {
|
||||
#[cfg(not(feature = "no_index"))]
|
||||
Token::LeftBracket => true,
|
||||
Token::LeftParen => true,
|
||||
_ => false,
|
||||
},
|
||||
|
||||
Self::Stack(_, _) => false,
|
||||
Self::Stack(..) => false,
|
||||
}
|
||||
}
|
||||
/// Recursively walk this expression.
|
||||
@@ -872,21 +874,21 @@ impl Expr {
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::InterpolatedString(x, _) | Self::Array(x, _) => {
|
||||
Self::InterpolatedString(x, ..) | Self::Array(x, ..) => {
|
||||
for e in x.as_ref() {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Map(x, _) => {
|
||||
for (_, e) in &x.0 {
|
||||
Self::Map(x, ..) => {
|
||||
for (.., e) in &x.0 {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Index(x, _, _) | Self::Dot(x, _, _) | Expr::And(x, _) | Expr::Or(x, _) => {
|
||||
Self::Index(x, ..) | Self::Dot(x, ..) | Expr::And(x, ..) | Expr::Or(x, ..) => {
|
||||
if !x.lhs.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
@@ -894,14 +896,14 @@ impl Expr {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Self::FnCall(x, _) => {
|
||||
Self::FnCall(x, ..) => {
|
||||
for e in &x.args {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Custom(x, _) => {
|
||||
Self::Custom(x, ..) => {
|
||||
for e in &x.inputs {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
|
169
src/ast/stmt.rs
169
src/ast/stmt.rs
@@ -411,25 +411,25 @@ impl Stmt {
|
||||
pub const fn position(&self) -> Position {
|
||||
match self {
|
||||
Self::Noop(pos)
|
||||
| Self::BreakLoop(_, pos)
|
||||
| Self::Block(_, (pos, _))
|
||||
| Self::Assignment(_, pos)
|
||||
| Self::FnCall(_, pos)
|
||||
| Self::If(_, _, pos)
|
||||
| Self::Switch(_, _, pos)
|
||||
| Self::While(_, _, pos)
|
||||
| Self::Do(_, _, _, pos)
|
||||
| Self::For(_, _, pos)
|
||||
| Self::Return(_, _, pos)
|
||||
| Self::Var(_, _, _, pos)
|
||||
| Self::TryCatch(_, pos) => *pos,
|
||||
| Self::BreakLoop(.., pos)
|
||||
| Self::Block(.., (pos, ..))
|
||||
| Self::Assignment(.., pos)
|
||||
| Self::FnCall(.., pos)
|
||||
| Self::If(.., pos)
|
||||
| Self::Switch(.., pos)
|
||||
| Self::While(.., pos)
|
||||
| Self::Do(.., pos)
|
||||
| Self::For(.., pos)
|
||||
| Self::Return(.., pos)
|
||||
| Self::Var(.., pos)
|
||||
| Self::TryCatch(.., pos) => *pos,
|
||||
|
||||
Self::Expr(x) => x.start_position(),
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Import(_, _, pos) => *pos,
|
||||
Self::Import(.., pos) => *pos,
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Export(_, pos) => *pos,
|
||||
Self::Export(.., pos) => *pos,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Self::Share(_) => Position::NONE,
|
||||
@@ -439,27 +439,27 @@ impl Stmt {
|
||||
pub fn set_position(&mut self, new_pos: Position) -> &mut Self {
|
||||
match self {
|
||||
Self::Noop(pos)
|
||||
| Self::BreakLoop(_, pos)
|
||||
| Self::Block(_, (pos, _))
|
||||
| Self::Assignment(_, pos)
|
||||
| Self::FnCall(_, pos)
|
||||
| Self::If(_, _, pos)
|
||||
| Self::Switch(_, _, pos)
|
||||
| Self::While(_, _, pos)
|
||||
| Self::Do(_, _, _, pos)
|
||||
| Self::For(_, _, pos)
|
||||
| Self::Return(_, _, pos)
|
||||
| Self::Var(_, _, _, pos)
|
||||
| Self::TryCatch(_, pos) => *pos = new_pos,
|
||||
| Self::BreakLoop(.., pos)
|
||||
| Self::Block(.., (pos, ..))
|
||||
| Self::Assignment(.., pos)
|
||||
| Self::FnCall(.., pos)
|
||||
| Self::If(.., pos)
|
||||
| Self::Switch(.., pos)
|
||||
| Self::While(.., pos)
|
||||
| Self::Do(.., pos)
|
||||
| Self::For(.., pos)
|
||||
| Self::Return(.., pos)
|
||||
| Self::Var(.., pos)
|
||||
| Self::TryCatch(.., pos) => *pos = new_pos,
|
||||
|
||||
Self::Expr(x) => {
|
||||
x.set_position(new_pos);
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Import(_, _, pos) => *pos = new_pos,
|
||||
Self::Import(.., pos) => *pos = new_pos,
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Export(_, pos) => *pos = new_pos,
|
||||
Self::Export(.., pos) => *pos = new_pos,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Self::Share(_) => (),
|
||||
@@ -471,25 +471,20 @@ impl Stmt {
|
||||
#[must_use]
|
||||
pub const fn returns_value(&self) -> bool {
|
||||
match self {
|
||||
Self::If(_, _, _)
|
||||
| Self::Switch(_, _, _)
|
||||
| Self::Block(_, _)
|
||||
Self::If(..)
|
||||
| Self::Switch(..)
|
||||
| Self::Block(..)
|
||||
| Self::Expr(_)
|
||||
| Self::FnCall(_, _) => true,
|
||||
| Self::FnCall(..) => true,
|
||||
|
||||
Self::Noop(_)
|
||||
| Self::While(_, _, _)
|
||||
| Self::Do(_, _, _, _)
|
||||
| Self::For(_, _, _)
|
||||
| Self::TryCatch(_, _) => false,
|
||||
Self::Noop(_) | Self::While(..) | Self::Do(..) | Self::For(..) | Self::TryCatch(..) => {
|
||||
false
|
||||
}
|
||||
|
||||
Self::Var(_, _, _, _)
|
||||
| Self::Assignment(_, _)
|
||||
| Self::BreakLoop(_, _)
|
||||
| Self::Return(_, _, _) => false,
|
||||
Self::Var(..) | Self::Assignment(..) | Self::BreakLoop(..) | Self::Return(..) => false,
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Import(_, _, _) | Self::Export(_, _) => false,
|
||||
Self::Import(..) | Self::Export(..) => false,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Self::Share(_) => false,
|
||||
@@ -499,28 +494,28 @@ impl Stmt {
|
||||
#[must_use]
|
||||
pub const fn is_self_terminated(&self) -> bool {
|
||||
match self {
|
||||
Self::If(_, _, _)
|
||||
| Self::Switch(_, _, _)
|
||||
| Self::While(_, _, _)
|
||||
| Self::For(_, _, _)
|
||||
| Self::Block(_, _)
|
||||
| Self::TryCatch(_, _) => true,
|
||||
Self::If(..)
|
||||
| Self::Switch(..)
|
||||
| Self::While(..)
|
||||
| Self::For(..)
|
||||
| Self::Block(..)
|
||||
| Self::TryCatch(..) => true,
|
||||
|
||||
// A No-op requires a semicolon in order to know it is an empty statement!
|
||||
Self::Noop(_) => false,
|
||||
|
||||
Self::Expr(Expr::Custom(x, _)) if x.is_self_terminated() => true,
|
||||
Self::Expr(Expr::Custom(x, ..)) if x.is_self_terminated() => true,
|
||||
|
||||
Self::Var(_, _, _, _)
|
||||
| Self::Assignment(_, _)
|
||||
Self::Var(..)
|
||||
| Self::Assignment(..)
|
||||
| Self::Expr(_)
|
||||
| Self::FnCall(_, _)
|
||||
| Self::Do(_, _, _, _)
|
||||
| Self::BreakLoop(_, _)
|
||||
| Self::Return(_, _, _) => false,
|
||||
| Self::FnCall(..)
|
||||
| Self::Do(..)
|
||||
| Self::BreakLoop(..)
|
||||
| Self::Return(..) => false,
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Import(_, _, _) | Self::Export(_, _) => false,
|
||||
Self::Import(..) | Self::Export(..) => false,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Self::Share(_) => false,
|
||||
@@ -534,18 +529,18 @@ impl Stmt {
|
||||
match self {
|
||||
Self::Noop(_) => true,
|
||||
Self::Expr(expr) => expr.is_pure(),
|
||||
Self::If(condition, x, _) => {
|
||||
Self::If(condition, x, ..) => {
|
||||
condition.is_pure()
|
||||
&& x.0.iter().all(Stmt::is_pure)
|
||||
&& x.1.iter().all(Stmt::is_pure)
|
||||
}
|
||||
Self::Switch(expr, x, _) => {
|
||||
Self::Switch(expr, x, ..) => {
|
||||
expr.is_pure()
|
||||
&& x.cases.values().all(|block| {
|
||||
block.condition.as_ref().map(Expr::is_pure).unwrap_or(true)
|
||||
&& block.statements.iter().all(Stmt::is_pure)
|
||||
})
|
||||
&& x.ranges.iter().all(|(_, _, _, block)| {
|
||||
&& x.ranges.iter().all(|(.., block)| {
|
||||
block.condition.as_ref().map(Expr::is_pure).unwrap_or(true)
|
||||
&& block.statements.iter().all(Stmt::is_pure)
|
||||
})
|
||||
@@ -553,31 +548,31 @@ impl Stmt {
|
||||
}
|
||||
|
||||
// Loops that exit can be pure because it can never be infinite.
|
||||
Self::While(Expr::BoolConstant(false, _), _, _) => true,
|
||||
Self::Do(body, Expr::BoolConstant(x, _), options, _)
|
||||
Self::While(Expr::BoolConstant(false, ..), ..) => true,
|
||||
Self::Do(body, Expr::BoolConstant(x, ..), options, ..)
|
||||
if *x == options.contains(AST_OPTION_NEGATED) =>
|
||||
{
|
||||
body.iter().all(Stmt::is_pure)
|
||||
}
|
||||
|
||||
// Loops are never pure since they can be infinite - and that's a side effect.
|
||||
Self::While(_, _, _) | Self::Do(_, _, _, _) => false,
|
||||
Self::While(..) | Self::Do(..) => false,
|
||||
|
||||
// For loops can be pure because if the iterable is pure, it is finite,
|
||||
// so infinite loops can never occur.
|
||||
Self::For(iterable, x, _) => iterable.is_pure() && x.2.iter().all(Stmt::is_pure),
|
||||
Self::For(iterable, x, ..) => iterable.is_pure() && x.2.iter().all(Stmt::is_pure),
|
||||
|
||||
Self::Var(_, _, _, _) | Self::Assignment(_, _) | Self::FnCall(_, _) => false,
|
||||
Self::Block(block, _) => block.iter().all(|stmt| stmt.is_pure()),
|
||||
Self::BreakLoop(_, _) | Self::Return(_, _, _) => false,
|
||||
Self::TryCatch(x, _) => {
|
||||
Self::Var(..) | Self::Assignment(..) | Self::FnCall(..) => false,
|
||||
Self::Block(block, ..) => block.iter().all(|stmt| stmt.is_pure()),
|
||||
Self::BreakLoop(..) | Self::Return(..) => false,
|
||||
Self::TryCatch(x, ..) => {
|
||||
x.try_block.iter().all(Stmt::is_pure) && x.catch_block.iter().all(Stmt::is_pure)
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Import(_, _, _) => false,
|
||||
Self::Import(..) => false,
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Export(_, _) => false,
|
||||
Self::Export(..) => false,
|
||||
|
||||
#[cfg(not(feature = "no_closure"))]
|
||||
Self::Share(_) => false,
|
||||
@@ -594,16 +589,16 @@ impl Stmt {
|
||||
#[must_use]
|
||||
pub fn is_block_dependent(&self) -> bool {
|
||||
match self {
|
||||
Self::Var(_, _, _, _) => true,
|
||||
Self::Var(..) => true,
|
||||
|
||||
Self::Expr(Expr::Stmt(s)) => s.iter().all(Stmt::is_block_dependent),
|
||||
|
||||
Self::FnCall(x, _) | Self::Expr(Expr::FnCall(x, _)) => {
|
||||
Self::FnCall(x, ..) | Self::Expr(Expr::FnCall(x, ..)) => {
|
||||
!x.is_qualified() && x.name == KEYWORD_EVAL
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Import(_, _, _) | Self::Export(_, _) => true,
|
||||
Self::Import(..) | Self::Export(..) => true,
|
||||
|
||||
_ => false,
|
||||
}
|
||||
@@ -618,14 +613,14 @@ impl Stmt {
|
||||
#[must_use]
|
||||
pub fn is_internally_pure(&self) -> bool {
|
||||
match self {
|
||||
Self::Var(expr, _, _, _) => expr.is_pure(),
|
||||
Self::Var(expr, _, ..) => expr.is_pure(),
|
||||
|
||||
Self::Expr(Expr::Stmt(s)) => s.iter().all(Stmt::is_internally_pure),
|
||||
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Import(expr, _, _) => expr.is_pure(),
|
||||
Self::Import(expr, ..) => expr.is_pure(),
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Export(_, _) => true,
|
||||
Self::Export(..) => true,
|
||||
|
||||
_ => self.is_pure(),
|
||||
}
|
||||
@@ -639,7 +634,7 @@ impl Stmt {
|
||||
#[must_use]
|
||||
pub const fn is_control_flow_break(&self) -> bool {
|
||||
match self {
|
||||
Self::Return(_, _, _) | Self::BreakLoop(_, _) => true,
|
||||
Self::Return(..) | Self::BreakLoop(..) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
@@ -658,12 +653,12 @@ impl Stmt {
|
||||
}
|
||||
|
||||
match self {
|
||||
Self::Var(e, _, _, _) => {
|
||||
Self::Var(e, _, ..) => {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Self::If(e, x, _) => {
|
||||
Self::If(e, x, ..) => {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
@@ -678,7 +673,7 @@ impl Stmt {
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Switch(e, x, _) => {
|
||||
Self::Switch(e, x, ..) => {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
@@ -697,7 +692,7 @@ impl Stmt {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (_, _, _, b) in &x.ranges {
|
||||
for (.., b) in &x.ranges {
|
||||
if !b
|
||||
.condition
|
||||
.as_ref()
|
||||
@@ -718,7 +713,7 @@ impl Stmt {
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::While(e, s, _) | Self::Do(s, e, _, _) => {
|
||||
Self::While(e, s, ..) | Self::Do(s, e, ..) => {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
@@ -728,7 +723,7 @@ impl Stmt {
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::For(e, x, _) => {
|
||||
Self::For(e, x, ..) => {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
@@ -738,7 +733,7 @@ impl Stmt {
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Assignment(x, _) => {
|
||||
Self::Assignment(x, ..) => {
|
||||
if !x.1.lhs.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
@@ -746,21 +741,21 @@ impl Stmt {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Self::FnCall(x, _) => {
|
||||
Self::FnCall(x, ..) => {
|
||||
for s in &x.args {
|
||||
if !s.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Block(x, _) => {
|
||||
Self::Block(x, ..) => {
|
||||
for s in x.iter() {
|
||||
if !s.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::TryCatch(x, _) => {
|
||||
Self::TryCatch(x, ..) => {
|
||||
for s in x.try_block.iter() {
|
||||
if !s.walk(path, on_node) {
|
||||
return false;
|
||||
@@ -778,7 +773,7 @@ impl Stmt {
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "no_module"))]
|
||||
Self::Import(e, _, _) => {
|
||||
Self::Import(e, ..) => {
|
||||
if !e.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
|
Reference in New Issue
Block a user