-
Notifications
You must be signed in to change notification settings - Fork 0
/
add_goto_pass.rs
40 lines (37 loc) · 1.07 KB
/
add_goto_pass.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
use crate::{fe::ast::*, mw::pass::AstPass};
pub struct AddGotoPass;
impl AstPass for AddGotoPass {
fn apply(&self, nodes: &mut Vec<AstNode>) {
let _ = helper(nodes, 0);
}
fn name(&self) -> String {String::from("add_goto_pass")}
}
fn helper(nodes: &mut Vec<AstNode>, ix: usize) -> bool {
if ix >= nodes.len() {
return false;
}
let add: bool = match &mut nodes[ix] {
AstNode::Function(node) => helper(&mut node.body, 0),
AstNode::Label(node) => match node.body[node.body.len()-1] {
AstNode::Goto(_) => false,
AstNode::Ret(_) => false,
_ => true,
},
AstNode::Goto(_) => false,
_ => if ix+1 < nodes.len() {matches!(nodes[ix+1], AstNode::Label(_))} else {false},
};
if add {
if let Some(AstNode::Label(next_label_node)) = nodes.get(ix + 1) {
let goto_node = AstNode::Goto(GotoAstNode {
name: next_label_node.name.clone(),
loc: next_label_node.loc.clone(),
});
if let AstNode::Label(current_label_node) = &mut nodes[ix] {
current_label_node.body.push(goto_node);
} else {
nodes.insert(ix + 1, goto_node);
}
}
}
helper(nodes, ix+1)
}