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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
use crate::{asm, Error, Result};
use alloc::{
string::{String, ToString},
vec::Vec,
};
use core::fmt::Display;
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub struct Ast {
procs: Vec<Procedure>,
}
impl Ast {
pub(crate) fn new(procs: Vec<Procedure>) -> Self {
Self { procs }
}
pub fn lower(self) -> Result<Vec<asm::Instruct>> {
let mut entry_proc = Procedure::new(Procedure::ENTRY_POINT, Vec::new());
for prc in &self.procs {
if prc.is_entry_point() {
entry_proc = prc.clone();
}
}
entry_proc.lower(&self.procs)
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub(crate) enum Exec {
Nop,
Call(String),
Assembly(asm::Instruct),
}
impl Exec {
pub fn call(name: impl Display) -> Self {
Self::Call(name.to_string())
}
pub fn asm(i: asm::Instruct) -> Self {
Self::Assembly(i)
}
}
#[derive(Clone, Debug, PartialEq, PartialOrd)]
pub(crate) struct Procedure {
name: String,
code: Vec<Exec>,
}
impl Procedure {
const ENTRY_POINT: &'static str = "start";
pub fn new(name: impl Display, code: Vec<Exec>) -> Self {
Self {
name: name.to_string(),
code,
}
}
pub fn get_name(&self) -> String {
self.name.clone()
}
pub fn is_entry_point(&self) -> bool {
self.get_name() == Self::ENTRY_POINT
}
pub fn is_proc(&self, name: impl Display) -> bool {
self.get_name() == name.to_string()
}
pub fn lower(&self, procs: &[Self]) -> Result<Vec<asm::Instruct>> {
let mut result = Vec::new();
for expr in &self.code {
match expr {
Exec::Nop => {}
Exec::Call(name) => {
let mut proc_exists = false;
for prc in procs {
if prc.is_proc(&name) {
proc_exists = true;
result.extend(prc.lower(procs)?);
break;
}
}
if !proc_exists {
return Err(Error::ProcedureNotDefined(name.clone()));
}
}
Exec::Assembly(i) => result.push(i.clone()),
}
}
Ok(result)
}
}