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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
mod byte_code;
mod byte_expr;
mod first_pass;
mod second_pass;
mod third_pass;
use std::fmt;
use crate::program::CompilableFn;
pub use byte_code::{
Arg, FieldAccess, Instruction, InstructionPointerType, JumpTarget,
Location, RelJumpTarget,
};
pub use byte_expr::fn_id as to_fn_id;
use crate::analysis::Traverser;
#[derive(Debug, Clone)]
pub struct ByteCodeFunction {
instructions: Vec<Instruction>,
validated_flag: bool,
}
impl ByteCodeFunction {
pub fn new_not_validated(
instructions: Vec<Instruction>,
) -> ByteCodeFunction {
ByteCodeFunction {
instructions: instructions,
validated_flag: false,
}
}
pub fn new_pre_validated(
instructions: Vec<Instruction>,
) -> ByteCodeFunction {
ByteCodeFunction {
instructions: instructions,
validated_flag: true,
}
}
pub fn validate(mut self) -> ByteCodeFunction {
self.validated_flag = true;
self
}
pub fn is_validated(&self) -> bool {
self.validated_flag
}
pub fn instructions(&self) -> &[Instruction] {
&self.instructions
}
}
impl fmt::Display for ByteCodeFunction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for instr in self.instructions.iter() {
writeln!(f, "{}", instr)?;
}
Ok(())
}
}
pub fn compile_to_byte_code(function: &CompilableFn) -> ByteCodeFunction {
let cfg = function.cfg();
let cfg = cfg.borrow();
let typing_context = function.typing_context();
let mut first_pass = first_pass::FirstPass::new(typing_context);
{
let traverser = Traverser::new(&*cfg, &mut first_pass);
traverser.traverse().unwrap();
}
let second_pass: second_pass::SecondPass = first_pass.into();
let third_pass = third_pass::ThirdPass::new(second_pass.pass());
ByteCodeFunction::new_pre_validated(third_pass.pass())
}