Add Stmt::FnCall.
This commit is contained in:
parent
cc546fcaab
commit
fe37edd123
28
src/ast.rs
28
src/ast.rs
@ -918,6 +918,11 @@ pub enum Stmt {
|
||||
Const(Expr, Box<Ident>, bool, Position),
|
||||
/// expr op`=` expr
|
||||
Assignment(Box<(Expr, Option<OpAssignment>, Expr)>, Position),
|
||||
/// func `(` expr `,` ... `)`
|
||||
///
|
||||
/// Note - this is a duplicate of [`Expr::FnCall`] to cover the very common pattern of a single
|
||||
/// function call forming one statement.
|
||||
FnCall(Box<FnCallExpr>, Position),
|
||||
/// `{` stmt`;` ... `}`
|
||||
Block(Vec<Stmt>, Position),
|
||||
/// `try` `{` stmt; ... `}` `catch` `(` var `)` `{` stmt; ... `}`
|
||||
@ -983,6 +988,7 @@ impl Stmt {
|
||||
| Self::Break(pos)
|
||||
| Self::Block(_, pos)
|
||||
| Self::Assignment(_, pos)
|
||||
| Self::FnCall(_, pos)
|
||||
| Self::If(_, _, pos)
|
||||
| Self::Switch(_, _, pos)
|
||||
| Self::While(_, _, pos)
|
||||
@ -1012,6 +1018,7 @@ impl Stmt {
|
||||
| Self::Break(pos)
|
||||
| Self::Block(_, pos)
|
||||
| Self::Assignment(_, pos)
|
||||
| Self::FnCall(_, pos)
|
||||
| Self::If(_, _, pos)
|
||||
| Self::Switch(_, _, pos)
|
||||
| Self::While(_, _, pos)
|
||||
@ -1040,7 +1047,11 @@ impl Stmt {
|
||||
/// Does this statement return a value?
|
||||
pub fn returns_value(&self) -> bool {
|
||||
match self {
|
||||
Self::If(_, _, _) | Self::Switch(_, _, _) | Self::Block(_, _) | Self::Expr(_) => true,
|
||||
Self::If(_, _, _)
|
||||
| Self::Switch(_, _, _)
|
||||
| Self::Block(_, _)
|
||||
| Self::Expr(_)
|
||||
| Self::FnCall(_, _) => true,
|
||||
|
||||
Self::Noop(_)
|
||||
| Self::While(_, _, _)
|
||||
@ -1078,6 +1089,7 @@ impl Stmt {
|
||||
Self::Let(_, _, _, _)
|
||||
| Self::Const(_, _, _, _)
|
||||
| Self::Assignment(_, _)
|
||||
| Self::FnCall(_, _)
|
||||
| Self::Expr(_)
|
||||
| Self::Do(_, _, _, _)
|
||||
| Self::Continue(_)
|
||||
@ -1115,7 +1127,10 @@ impl Stmt {
|
||||
condition.is_pure() && block.0.iter().all(Stmt::is_pure)
|
||||
}
|
||||
Self::For(iterable, x, _) => iterable.is_pure() && (x.1).0.iter().all(Stmt::is_pure),
|
||||
Self::Let(_, _, _, _) | Self::Const(_, _, _, _) | Self::Assignment(_, _) => false,
|
||||
Self::Let(_, _, _, _)
|
||||
| Self::Const(_, _, _, _)
|
||||
| Self::Assignment(_, _)
|
||||
| Self::FnCall(_, _) => false,
|
||||
Self::Block(block, _) => block.iter().all(|stmt| stmt.is_pure()),
|
||||
Self::Continue(_) | Self::Break(_) | Self::Return(_, _, _) => false,
|
||||
Self::TryCatch(x, _, _) => {
|
||||
@ -1244,6 +1259,13 @@ impl Stmt {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Self::FnCall(x, _) => {
|
||||
for s in &x.args {
|
||||
if !s.walk(path, on_node) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
Self::Block(x, _) => {
|
||||
for s in x {
|
||||
if !s.walk(path, on_node) {
|
||||
@ -1441,7 +1463,7 @@ impl FnCallHashes {
|
||||
/// # Volatile Data Structure
|
||||
///
|
||||
/// This type is volatile and may change.
|
||||
#[derive(Clone, Default, Hash)]
|
||||
#[derive(Debug, Clone, Default, Hash)]
|
||||
pub struct FnCallExpr {
|
||||
/// Namespace of the function, if any.
|
||||
pub namespace: Option<NamespaceRef>,
|
||||
|
@ -1830,22 +1830,6 @@ impl Engine {
|
||||
Ok(map.into())
|
||||
}
|
||||
|
||||
// Normal function call
|
||||
Expr::FnCall(x, pos) if !x.is_qualified() => {
|
||||
let FnCallExpr {
|
||||
name,
|
||||
capture,
|
||||
hashes,
|
||||
args,
|
||||
constant_args: c_args,
|
||||
..
|
||||
} = x.as_ref();
|
||||
self.make_function_call(
|
||||
scope, mods, state, lib, this_ptr, name, args, c_args, *hashes, *pos, *capture,
|
||||
level,
|
||||
)
|
||||
}
|
||||
|
||||
// Namespace-qualified function call
|
||||
Expr::FnCall(x, pos) if x.is_qualified() => {
|
||||
let FnCallExpr {
|
||||
@ -1864,6 +1848,22 @@ impl Engine {
|
||||
)
|
||||
}
|
||||
|
||||
// Normal function call
|
||||
Expr::FnCall(x, pos) => {
|
||||
let FnCallExpr {
|
||||
name,
|
||||
capture,
|
||||
hashes,
|
||||
args,
|
||||
constant_args: c_args,
|
||||
..
|
||||
} = x.as_ref();
|
||||
self.make_function_call(
|
||||
scope, mods, state, lib, this_ptr, name, args, c_args, *hashes, *pos, *capture,
|
||||
level,
|
||||
)
|
||||
}
|
||||
|
||||
Expr::And(x, _) => {
|
||||
Ok((self
|
||||
.eval_expr(scope, mods, state, lib, this_ptr, &x.lhs, level)?
|
||||
@ -2390,6 +2390,40 @@ impl Engine {
|
||||
// Break statement
|
||||
Stmt::Break(pos) => EvalAltResult::LoopBreak(true, *pos).into(),
|
||||
|
||||
// Namespace-qualified function call
|
||||
Stmt::FnCall(x, pos) if x.is_qualified() => {
|
||||
let FnCallExpr {
|
||||
name,
|
||||
namespace,
|
||||
hashes,
|
||||
args,
|
||||
constant_args: c_args,
|
||||
..
|
||||
} = x.as_ref();
|
||||
let namespace = namespace.as_ref();
|
||||
let hash = hashes.native_hash();
|
||||
self.make_qualified_function_call(
|
||||
scope, mods, state, lib, this_ptr, namespace, name, args, c_args, hash, *pos,
|
||||
level,
|
||||
)
|
||||
}
|
||||
|
||||
// Normal function call
|
||||
Stmt::FnCall(x, pos) => {
|
||||
let FnCallExpr {
|
||||
name,
|
||||
capture,
|
||||
hashes,
|
||||
args,
|
||||
constant_args: c_args,
|
||||
..
|
||||
} = x.as_ref();
|
||||
self.make_function_call(
|
||||
scope, mods, state, lib, this_ptr, name, args, c_args, *hashes, *pos, *capture,
|
||||
level,
|
||||
)
|
||||
}
|
||||
|
||||
// Try/Catch statement
|
||||
Stmt::TryCatch(x, _, _) => {
|
||||
let (try_stmt, err_var, catch_stmt) = x.as_ref();
|
||||
|
@ -628,6 +628,17 @@ fn optimize_stmt(stmt: &mut Stmt, state: &mut State, preserve_result: bool) {
|
||||
let catch_block = mem::take(x.2.statements()).into_vec();
|
||||
*x.2.statements() = optimize_stmt_block(catch_block, state, false, true, false).into();
|
||||
}
|
||||
// func(...)
|
||||
Stmt::Expr(expr @ Expr::FnCall(_, _)) => {
|
||||
optimize_expr(expr, state);
|
||||
match expr {
|
||||
Expr::FnCall(x, pos) => {
|
||||
state.set_dirty();
|
||||
*stmt = Stmt::FnCall(mem::take(x), *pos);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
// {}
|
||||
Stmt::Expr(Expr::Stmt(x)) if x.is_empty() => {
|
||||
state.set_dirty();
|
||||
|
@ -72,7 +72,7 @@ fn test_max_operations_functions() -> Result<(), Box<EvalAltResult>> {
|
||||
fn inc(x) { x + 1 }
|
||||
let x = 0;
|
||||
|
||||
while x < 31 {
|
||||
while x < 36 {
|
||||
print(x);
|
||||
x = inc(x);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user