tower_vm/builder/
builder.rs1use std::collections::HashMap;
2
3use super::chunk::Chunk;
4
5use crate::{Instruction, TypeFlag, Value, Machine};
6
7macro_rules! simple_instr {
8 ($fn_name:ident, $instr:ident) => {
9 pub fn $fn_name(&mut self) {
10 self.push_instr(Instruction::$instr);
11 }
12 };
13}
14
15
16
17pub struct Builder {
18 chunks: Vec<Chunk>,
19 funcs: HashMap<String, u64>,}
21
22impl Builder {
23 pub fn new() -> Self {
24 Self {
25 chunks: vec![],
26 funcs: HashMap::new(),
27 }
28 }
29
30 pub fn debug_chunks(&self) {
31 println!("{:?}", self.chunks)
32 }
33 fn get_func(&self, ident: &str) -> Option<u64> {
34 self.funcs.get(ident).copied()
35 }
36
37 fn push_instr(&mut self, instr: Instruction) {
38 self.chunks.push(Chunk::Instr(instr))
39 }
40
41 pub fn push(&mut self, value: Value) {
42 self.push_instr(Instruction::Push);
43 self.chunks.push(Chunk::Literal(value));
44 }
45
46 pub fn push_collect(&mut self, values: &mut Vec<Value>) {
48 while values.len() > 0 {
49 self.push(values.pop().unwrap());
50 }
51 }
52
53 pub fn start_fn(&mut self, id: &str) -> Result<(), u64> {
56 let ident = id.to_string();
57
58 match self.get_func(id) {
59 Some(_) => Err(self.funcs[&ident]),
60 None => {
61 self.funcs.insert(ident, self.chunks.len() as u64);
62 Ok(())
63 },
64 }
65 }
66
67 simple_instr!(ret_fn, Ret);
69
70 simple_instr!(halt, Halt);
72
73 pub fn set_type(&mut self, ty_flag: TypeFlag) {
75 self.push_instr(Instruction::SetType);
76 self.chunks.push(Chunk::Type(ty_flag));
77 }
78
79 simple_instr!(get_type, GetType);
80
81 simple_instr!(add, Add);
82
83 simple_instr!(sub, Sub);
84
85 simple_instr!(div, Div);
86
87 simple_instr!(rem, Rem);
88
89 simple_instr!(neg, Neg);
90
91 simple_instr!(incr, Incr);
92
93 simple_instr!(decr, Decr);
94
95 simple_instr!(eq, Eq);
96
97 simple_instr!(neq, Neq);
98
99 simple_instr!(lt, Lt);
100
101 simple_instr!(gt, Gt);
102
103 simple_instr!(lte, Lte);
104
105 simple_instr!(gte, Gte);
106
107 simple_instr!(and, And);
108
109 simple_instr!(or, Or);
110
111 simple_instr!(xor, Xor);
112
113 simple_instr!(shl, Shl);
114
115 simple_instr!(shr, Shr);
116
117 simple_instr!(not, Not);
118
119 pub fn jmp(&mut self, addr: Option<u64>) {
121 if let Some(idx) = addr {
122 self.push(idx.into());
123 }
124 self.push_instr(Instruction::Jmp);
125 }
126
127 simple_instr!(jmp_if, JmpIf);
128
129 simple_instr!(jmp_if_not, JmpIfNot);
130
131 pub fn call(&mut self, ident: &str) -> Result<(), String> {
132 match self.get_func(ident) {
133 Some(idx) => {
134 self.push(idx.into());
135 Ok(self.push_instr(Instruction::Call))
136 }
137 None => Err(format!("Error: fn {} is undefined", ident)),
138 }
139 }
140
141 simple_instr!(ret, Ret);
142
143 simple_instr!(dup, Dup);
144
145 simple_instr!(drop, Drop);
146
147 simple_instr!(swap, Swap);
148
149 pub fn load(&mut self, ptr: Option<u64>) {
151 if let Some(idx) = ptr {
152 self.push(idx.into());
153 }
154 self.push_instr(Instruction::Load);
155 }
156
157 simple_instr!(store, Store);
158
159 simple_instr!(alloc, Alloc);
160
161 simple_instr!(free, Free);
162
163 simple_instr!(heap_size, HeapSize);
164
165 simple_instr!(stack_size, StackSize);
166
167 simple_instr!(load_code, LoadCode);
168
169 simple_instr!(save_code, SaveCode);
170
171 pub fn write(&mut self, out: Option<&str>) {
172 if let Some(s) = out {
175 let mut values: Vec<Value> = s.chars().into_iter().map(|ch| ch.into()).collect();
176 self.push_collect(&mut values);
177 for _ in 0..(s.len()) {
178 self.push_instr(Instruction::Write);
179 }
180 }else{
181 self.push_instr(Instruction::Write);
182 }
183 }
184
185 simple_instr!(read, Read);
186
187 pub fn print(&mut self, out: Option<&str>) {
188 if let Some(s) = out {
189 self.write(Some(s));
190 }
191 self.push_instr(Instruction::Print);
192 }
193
194 fn to_code(&mut self) -> Vec<u8> {
195 let mut code = vec![];
196
197 for chunk in self.chunks.iter_mut() {
198 code.append(&mut chunk.to_code());
199 }
200
201 code
202 }
203
204 pub fn build_code(&mut self) -> Vec<u8> {
206 self.to_code()
207 }
208
209 pub fn build_machine(&mut self) -> Machine {
210 let mut machine = Machine::new();
211 machine.push_code(&self.build_code());
212 return machine;
213 }
214}