use crate::ir::expr::Expr;
#[derive(Debug, Clone, PartialEq)]
pub enum Stmt {
Block(Vec<Stmt>),
ExprStmt(Expr),
LocalDef {
var: u32,
init: Option<Expr>,
is_final: bool,
force_type: bool,
},
Return(Option<Expr>),
Throw(Expr),
If {
cond: Expr,
then_stmt: Box<Stmt>,
else_stmt: Option<Box<Stmt>>,
},
While {
cond: Expr,
body: Box<Stmt>,
},
DoWhile {
body: Box<Stmt>,
cond: Expr,
},
For {
init: Vec<Stmt>,
cond: Option<Expr>,
update: Vec<Expr>,
body: Box<Stmt>,
},
ForEach {
var: u32,
iterable: Expr,
is_array: bool,
body: Box<Stmt>,
},
Switch {
selector: Expr,
cases: Vec<CaseGroup>,
default: Option<Box<Stmt>>,
on_string: bool,
},
Try {
body: Box<Stmt>,
catches: Vec<Catch>,
finally: Option<Box<Stmt>>,
},
TryWithResources {
resources: Vec<Stmt>,
body: Box<Stmt>,
catches: Vec<Catch>,
finally: Option<Box<Stmt>>,
},
Assert {
cond: Expr,
msg: Option<Expr>,
},
Synchronized {
lock: Expr,
body: Box<Stmt>,
},
TernaryValue {
e: Expr,
},
MonitorEnter(Expr),
MonitorExit(Expr),
Label(u32),
Goto(u32),
ClassDecl {
name: String,
header: String,
body: String,
},
Labeled {
label: String,
body: Box<Stmt>,
},
Break(Option<String>),
Continue(Option<String>),
Comment(String),
}
#[derive(Debug, Clone, PartialEq)]
pub struct CaseGroup {
pub labels: Vec<i64>,
pub string_labels: Vec<String>,
pub enum_labels: Vec<String>,
pub raw_labels: Vec<String>,
pub guard: Option<crate::ir::expr::Expr>,
pub body: Vec<Stmt>,
}
#[derive(Debug, Clone, PartialEq)]
pub struct Catch {
pub exc: Vec<std::sync::Arc<str>>,
pub var: u32,
pub var_name: Option<String>,
pub body: Box<Stmt>,
}
impl Stmt {
pub fn is_empty_block(&self) -> bool {
matches!(self, Stmt::Block(b) if b.is_empty())
}
pub fn as_block(self) -> Stmt {
match self {
Stmt::Block(_) => self,
other => Stmt::Block(vec![other]),
}
}
}
pub fn flatten(s: &mut Stmt) {
match s {
Stmt::Block(v) => {
for x in v.iter_mut() {
flatten(x);
}
}
Stmt::If {
then_stmt,
else_stmt,
..
} => {
flatten(then_stmt);
if let Some(e) = else_stmt {
flatten(e);
}
}
Stmt::While { body, .. } | Stmt::DoWhile { body, .. } => flatten(body),
Stmt::For { body, .. } | Stmt::ForEach { body, .. } => flatten(body),
Stmt::Try {
body,
catches,
finally,
} => {
flatten(body);
for c in catches {
flatten(&mut c.body);
}
if let Some(f) = finally {
flatten(f);
}
}
Stmt::TryWithResources {
body,
catches,
finally,
..
} => {
flatten(body);
for c in catches {
flatten(&mut c.body);
}
if let Some(f) = finally {
flatten(f);
}
}
Stmt::Synchronized { body, .. } => flatten(body),
Stmt::Switch { cases, default, .. } => {
for c in cases {
for s in c.body.iter_mut() {
flatten(s);
}
}
if let Some(d) = default {
flatten(d);
}
}
_ => {}
}
}