Improve if statement and top-level jump handling

This commit is contained in:
Rerumu 2021-11-23 17:46:12 -05:00
parent 704060703b
commit 2a9c03249c
3 changed files with 28 additions and 20 deletions

View File

@ -212,8 +212,8 @@ impl Backward {
pub struct If { pub struct If {
pub cond: Expression, pub cond: Expression,
pub body: Vec<Statement>, pub truthy: Vec<Statement>,
pub other: Option<Vec<Statement>>, pub falsey: Option<Vec<Statement>>,
} }
impl If { impl If {
@ -222,11 +222,11 @@ impl If {
self.cond.accept(visitor); self.cond.accept(visitor);
for v in &self.body { for v in &self.truthy {
v.accept(visitor); v.accept(visitor);
} }
if let Some(v) = &self.other { if let Some(v) = &self.falsey {
for v in v { for v in v {
v.accept(visitor); v.accept(visitor);
} }
@ -403,13 +403,11 @@ pub struct Function {
pub num_param: u32, pub num_param: u32,
pub num_local: u32, pub num_local: u32,
pub num_stack: u32, pub num_stack: u32,
pub body: Vec<Statement>, pub body: Forward,
} }
impl Function { impl Function {
pub fn accept<V: Visitor>(&self, visitor: &mut V) { pub fn accept<V: Visitor>(&self, visitor: &mut V) {
for v in &self.body { self.body.accept(visitor);
v.accept(visitor);
}
} }
} }

View File

@ -31,8 +31,8 @@ fn local_sum(list: &[Local]) -> u32 {
list.iter().map(Local::count).sum() list.iter().map(Local::count).sum()
} }
fn is_else_stat(list: &[Instruction]) -> bool { fn is_else_stat(inst: &Instruction) -> bool {
list.get(0) == Some(&Instruction::Else) inst == &Instruction::Else
} }
impl<'a> Transformer<'a> { impl<'a> Transformer<'a> {
@ -51,7 +51,7 @@ impl<'a> Transformer<'a> {
debug_assert!(self.name != usize::MAX, "Not an indexed value"); debug_assert!(self.name != usize::MAX, "Not an indexed value");
let func = &self.wasm.code_section().unwrap().bodies()[self.name]; let func = &self.wasm.code_section().unwrap().bodies()[self.name];
let body = self.new_stored_body(&mut func.code().elements()); let body = self.new_forward(&mut func.code().elements());
Function { Function {
num_param: self.arity.in_arity[self.name].num_param, num_param: self.arity.in_arity[self.name].num_param,
@ -205,7 +205,9 @@ impl<'a> Transformer<'a> {
let mut stat = Vec::new(); let mut stat = Vec::new();
while let Some(inst) = list.get(0) { loop {
let inst = &list[0];
*list = &list[1..]; *list = &list[1..];
if let Ok(op) = UnOp::try_from(inst) { if let Ok(op) = UnOp::try_from(inst) {
@ -384,13 +386,17 @@ impl<'a> Transformer<'a> {
} }
fn new_if(&mut self, cond: Expression, list: &mut &[Instruction]) -> If { fn new_if(&mut self, cond: Expression, list: &mut &[Instruction]) -> If {
let body = self.new_stored_body(list); let copied = list.clone();
let other = is_else_stat(list).then(|| { let truthy = self.new_stored_body(list);
*list = &list[1..];
self.new_stored_body(list)
});
If { cond, body, other } let last = copied.len() - list.len() - 1;
let falsey = is_else_stat(&copied[last]).then(|| self.new_stored_body(list));
If {
cond,
truthy,
falsey,
}
} }
fn new_backward(&mut self, list: &mut &[Instruction]) -> Backward { fn new_backward(&mut self, list: &mut &[Instruction]) -> Backward {

View File

@ -271,7 +271,11 @@ impl If {
d.edition.start_if(&var, w)?; d.edition.start_if(&var, w)?;
self.body.iter().try_for_each(|s| s.output(d, w))?; self.truthy.iter().try_for_each(|s| s.output(d, w))?;
if let Some(v) = &self.falsey {
v.iter().try_for_each(|s| s.output(d, w))?;
}
d.edition.end_if(rem, w)?; d.edition.end_if(rem, w)?;
d.label_list.pop().unwrap(); d.label_list.pop().unwrap();
@ -478,7 +482,7 @@ impl Function {
self.write_visitor_list(w)?; self.write_visitor_list(w)?;
self.write_variable_list(w)?; self.write_variable_list(w)?;
self.body.iter().try_for_each(|s| s.output(d, w))?; self.body.output(d, w)?;
write!(w, "end ") write!(w, "end ")
} }