use super::super::common::{AstExpr, AstNameRef, AstTableField, AstTableKey};
pub(super) fn expr_complexity(expr: &AstExpr) -> usize {
match expr {
AstExpr::Nil
| AstExpr::Boolean(_)
| AstExpr::Integer(_)
| AstExpr::Number(_)
| AstExpr::String(_)
| AstExpr::Int64(_)
| AstExpr::UInt64(_)
| AstExpr::Complex { .. }
| AstExpr::Var(_)
| AstExpr::VarArg | AstExpr::Error(_) => 1,
AstExpr::Unary(unary) => 1 + expr_complexity(&unary.expr),
AstExpr::Binary(binary) => 1 + expr_complexity(&binary.lhs) + expr_complexity(&binary.rhs),
AstExpr::LogicalAnd(logical) | AstExpr::LogicalOr(logical) => {
1 + expr_complexity(&logical.lhs) + expr_complexity(&logical.rhs)
}
AstExpr::FieldAccess(access) => 1 + expr_complexity(&access.base),
AstExpr::IndexAccess(access) => {
1 + expr_complexity(&access.base) + expr_complexity(&access.index)
}
AstExpr::Call(call) => {
1 + expr_complexity(&call.callee) + call.args.iter().map(expr_complexity).sum::<usize>()
}
AstExpr::MethodCall(call) => {
1 + expr_complexity(&call.receiver)
+ call.args.iter().map(expr_complexity).sum::<usize>()
}
AstExpr::SingleValue(expr) => 1 + expr_complexity(expr),
AstExpr::TableConstructor(table) => {
1 + table
.fields
.iter()
.map(|field| match field {
AstTableField::Array(value) => expr_complexity(value),
AstTableField::Record(record) => {
let key_cost = match &record.key {
AstTableKey::Name(_) => 1,
AstTableKey::Expr(key) => expr_complexity(key),
};
key_cost + expr_complexity(&record.value)
}
})
.sum::<usize>()
}
AstExpr::FunctionExpr(function) => 1 + function.body.stmts.len(),
}
}
pub(super) fn is_context_safe_expr(expr: &AstExpr) -> bool {
match expr {
AstExpr::Nil
| AstExpr::Boolean(_)
| AstExpr::Integer(_)
| AstExpr::Number(_)
| AstExpr::String(_)
| AstExpr::Int64(_)
| AstExpr::UInt64(_)
| AstExpr::Complex { .. } => true,
AstExpr::Var(
AstNameRef::Param(_)
| AstNameRef::Local(_)
| AstNameRef::SyntheticLocal(_)
| AstNameRef::Temp(_)
| AstNameRef::Upvalue(_),
) => true,
AstExpr::Unary(unary) => {
matches!(unary.op, super::super::common::AstUnaryOpKind::Not)
&& is_context_safe_expr(&unary.expr)
}
AstExpr::SingleValue(expr) => is_context_safe_expr(expr),
AstExpr::LogicalAnd(logical) | AstExpr::LogicalOr(logical) => {
is_context_safe_expr(&logical.lhs) && is_context_safe_expr(&logical.rhs)
}
AstExpr::Var(AstNameRef::Global(_))
| AstExpr::FieldAccess(_)
| AstExpr::IndexAccess(_)
| AstExpr::Binary(_)
| AstExpr::Call(_)
| AstExpr::MethodCall(_)
| AstExpr::VarArg
| AstExpr::TableConstructor(_)
| AstExpr::FunctionExpr(_)
| AstExpr::Error(_) => false,
}
}
pub(super) fn is_access_base_inline_expr(expr: &AstExpr) -> bool {
is_atomic_access_base_expr(expr) || is_named_field_chain_expr(expr)
}
pub(super) fn is_raw_global_alias_expr(expr: &AstExpr) -> bool {
matches!(expr, AstExpr::Var(AstNameRef::Global(_)))
}
pub(super) fn is_lookup_inline_expr(expr: &AstExpr) -> bool {
match expr {
AstExpr::FieldAccess(access) => {
is_atomic_access_base_expr(&access.base) || is_lookup_inline_expr(&access.base)
}
AstExpr::IndexAccess(access) => {
(is_atomic_access_base_expr(&access.base) || is_lookup_inline_expr(&access.base))
&& is_context_safe_expr(&access.index)
}
_ => false,
}
}
pub(super) fn is_copy_like_expr(expr: &AstExpr) -> bool {
match expr {
AstExpr::Nil
| AstExpr::Boolean(_)
| AstExpr::Integer(_)
| AstExpr::Number(_)
| AstExpr::String(_)
| AstExpr::Int64(_)
| AstExpr::UInt64(_)
| AstExpr::Complex { .. }
| AstExpr::Var(_) => true,
AstExpr::SingleValue(expr) => is_copy_like_expr(expr),
AstExpr::FieldAccess(access) => is_copy_like_expr(&access.base),
AstExpr::IndexAccess(access) => {
is_copy_like_expr(&access.base) && is_copy_like_expr(&access.index)
}
AstExpr::Unary(_)
| AstExpr::Binary(_)
| AstExpr::LogicalAnd(_)
| AstExpr::LogicalOr(_)
| AstExpr::Call(_)
| AstExpr::MethodCall(_)
| AstExpr::VarArg
| AstExpr::TableConstructor(_)
| AstExpr::FunctionExpr(_)
| AstExpr::Error(_) => false,
}
}
pub(super) fn is_mechanical_run_inline_expr(expr: &AstExpr) -> bool {
match expr {
AstExpr::Nil
| AstExpr::Boolean(_)
| AstExpr::Integer(_)
| AstExpr::Number(_)
| AstExpr::String(_)
| AstExpr::Int64(_)
| AstExpr::UInt64(_)
| AstExpr::Complex { .. }
| AstExpr::Var(_) => true,
AstExpr::SingleValue(expr) => is_mechanical_run_inline_expr(expr),
AstExpr::FieldAccess(access) => is_mechanical_run_inline_expr(&access.base),
AstExpr::IndexAccess(access) => {
is_mechanical_run_inline_expr(&access.base)
&& is_mechanical_run_inline_expr(&access.index)
}
AstExpr::Unary(unary) => is_mechanical_run_inline_expr(&unary.expr),
AstExpr::Binary(binary) => {
is_mechanical_run_inline_expr(&binary.lhs) && is_mechanical_run_inline_expr(&binary.rhs)
}
AstExpr::LogicalAnd(logical) | AstExpr::LogicalOr(logical) => {
is_mechanical_run_inline_expr(&logical.lhs)
&& is_mechanical_run_inline_expr(&logical.rhs)
}
AstExpr::Call(_)
| AstExpr::MethodCall(_)
| AstExpr::VarArg
| AstExpr::TableConstructor(_)
| AstExpr::FunctionExpr(_)
| AstExpr::Error(_) => false,
}
}
pub(super) fn is_direct_return_constructor_inline_expr(expr: &AstExpr) -> bool {
matches!(expr, AstExpr::TableConstructor(_))
}
pub(super) fn is_always_truthy_expr(expr: &AstExpr) -> bool {
match expr {
AstExpr::Boolean(true)
| AstExpr::Integer(_)
| AstExpr::Number(_)
| AstExpr::String(_)
| AstExpr::Int64(_)
| AstExpr::UInt64(_)
| AstExpr::Complex { .. }
| AstExpr::TableConstructor(_)
| AstExpr::FunctionExpr(_) => true,
AstExpr::Nil
| AstExpr::Boolean(false)
| AstExpr::Var(_)
| AstExpr::FieldAccess(_)
| AstExpr::IndexAccess(_)
| AstExpr::Unary(_)
| AstExpr::Binary(_)
| AstExpr::LogicalAnd(_)
| AstExpr::LogicalOr(_)
| AstExpr::Call(_)
| AstExpr::MethodCall(_)
| AstExpr::SingleValue(_)
| AstExpr::VarArg | AstExpr::Error(_) => false,
}
}
fn is_named_field_chain_expr(expr: &AstExpr) -> bool {
let AstExpr::FieldAccess(access) = expr else {
return false;
};
is_atomic_access_base_expr(&access.base) || is_named_field_chain_expr(&access.base)
}
fn is_atomic_access_base_expr(expr: &AstExpr) -> bool {
matches!(
expr,
AstExpr::Nil
| AstExpr::Boolean(_)
| AstExpr::Integer(_)
| AstExpr::Number(_)
| AstExpr::String(_)
| AstExpr::Int64(_)
| AstExpr::UInt64(_)
| AstExpr::Complex { .. }
| AstExpr::Var(_)
)
}