1#![allow(clippy::type_complexity)]
2
3mod tree;
6
7mod assembly_source;
10
11mod import;
14
15mod macros;
18
19mod raw;
22
23mod align;
25
26mod label;
28
29mod strings;
31
32mod section;
34
35mod define;
37
38pub mod utils;
40
41use crate::tree::*;
42use crate::tree::AsmNode::*;
43use crate::assembly_source::parse_source;
44use std::collections::HashMap;
45use macros::*;
46
47pub struct Assembler<'a> {
50 root: AsmNode,
53
54 macros: HashMap<MacroID, String>,
57
58 macro_expansion_count: usize,
61
62 defines: HashMap<String, Vec<String>>,
64
65 wordsize: usize,
67
68 pub align_pattern: Vec<u8>,
70
71 pub start_address: usize,
73
74 pub implementation_macro: &'a dyn Fn(&Vec<String>) -> Result<Option<String>, String>,
79
80 pub micro_assembly: &'a dyn Fn(&Vec<String>) -> Result<Vec<u8>, String>,
87}
88
89impl Assembler<'_> {
90 pub fn from_text(text: &str) -> Self {
92 Self::from_named_text(text, "./__asm_init")
93 }
94
95 fn from_named_text(text: &str, name: &str) -> Self {
97 fn default_implementation_macro(_: &Vec<String>) -> Result<Option<String>, String> {
98 Ok(None)
99 }
100 fn default_micro_assembly(_: &Vec<String>) -> Result<Vec<u8>, String> {
101 Err("Micro assembly function should be given by the assembler implementation.".to_string())
102 }
103
104 Assembler {
105 root: parse_source(text, name),
106 macros: HashMap::new(),
107 defines: HashMap::new(),
108 wordsize: 0,
109 align_pattern: vec![0],
110 start_address: 0,
111 implementation_macro: &default_implementation_macro,
112 micro_assembly: &default_micro_assembly,
113 macro_expansion_count: 0,
114 }
115 }
116
117 pub fn from_file(path: &str) -> Self {
119 let mut import_directive = "@import \"".to_string();
120 import_directive.push_str(path);
121 import_directive.push('\"');
122 Self::from_text(&import_directive)
123 }
124
125 pub fn set_word_size(&mut self, wordsize: usize) -> Option<&str> {
128 match wordsize {
129 8 | 16 | 32 | 64 | 128 => {
130 self.wordsize = wordsize / 8;
131 None
132 },
133 x => {
134 if x > 128 {
135 Some("Only word sizes of 128 bits or less are supported. This is not a limitation of the Reflet architecture but one of this assembler.")
136 } else {
137 Some("Valid word sizes should be 8 bits times a power of two such as 8, 16, or 32.")
138 }
139 },
140 }
141 }
142
143 pub fn add_text_before(&mut self, txt: &str, name: &str) {
145 match &mut self.root {
146 Inode(list) => {
147 list.insert(0, parse_source(txt, name));
148 },
149 _ => {
150 panic!("Assembler's root should have been an inode!");
151 },
152 }
153 }
154
155 pub fn add_text_after(&mut self, txt: &str, name: &str) {
157 match &mut self.root {
158 Inode(list) => {
159 list.push(parse_source(txt, name));
160 },
161 _ => {
162 panic!("Assembler's root should have been an inode!");
163 },
164 }
165 }
166
167 fn run_text_adding_passes(&mut self) {
170 const TEXT_ADDING_PASSES: [&dyn Fn(&mut Assembler) -> bool; 5] = [
175 &import::include_source,
176 ¯os::register_macros,
177 &define::handle_define,
178 &run_implementation_macros,
179 ¯os::expand_macros,
180 ];
181
182 let mut pass_index = 0;
183 while pass_index < TEXT_ADDING_PASSES.len() {
184 if TEXT_ADDING_PASSES[pass_index](self) {
185 pass_index = 0;
186 } else {
187 pass_index += 1;
188 }
189 }
190 }
191
192 pub fn assemble(&mut self) -> Result<Vec<u8>, String> {
196 self.run_text_adding_passes();
198 section::handle_sections(self);
199 label::register_labels(self);
200 align::register_align(self);
201 raw::expand_constants(self);
202 raw::decode_raw_bytes(self);
203 strings::register_strings(self);
204
205 self.run_micro_assembler();
207
208 align::expand_align(self);
210 label::expand_labels(self);
211 let ret = self.collect_raw();
212
213 match self.root.check_for_errors() {
215 Some(txt) => Err(txt),
216 None => Ok(ret),
217 }
218 }
219
220 fn run_micro_assembler(&mut self) {
222 let mut running_micro_assembler = | node: &AsmNode | -> Option<AsmNode> {
223 match node {
224 Source{code, meta} => match (self.micro_assembly)(code) {
225 Err(msg) => Some(Error{msg, meta: meta.clone()}),
226 Ok(raw) => Some(Raw(raw)),
227 },
228 _ => None,
229 }
230 };
231
232 self.root.traverse_tree(&mut running_micro_assembler);
233 }
234
235 pub fn label_dump(&mut self) -> String {
237 label::label_dump(self)
238 }
239
240 fn collect_raw(&mut self) -> Vec<u8> {
243 let mut ret: Vec<u8> = vec![];
244 let mut collecting_raw = | node: &AsmNode | -> Option<AsmNode> {
245 match node {
246 Raw(data) => {
247 ret.extend(data);
248 None
249 },
250 Error{msg: _, meta: _} => None,
251 Label{name: _, is_definition: true, meta: _} => None,
252 x => Some(Error{msg: format!("There is a bug in the assembler, the node {} should not be left over in collect_raw.", &x.to_string()), meta: Metadata{line: !0, raw: "!!!".to_string(), source_file: "!!!".to_string()}}),
253 }
254 };
255
256 self.root.traverse_tree(&mut collecting_raw);
257 ret
258 }
259
260 fn format_number(&self, number: u128) -> Option<Vec<u8>> {
264 let mut n = number;
265 let mut ret = vec![];
266 for _i in 0..self.wordsize {
267 ret.push((n & 0xFF) as u8);
268 n >>= 8
269 }
270 if n == 0 {
271 Some(ret)
272 } else {
273 None
274 }
275 }
276
277 fn format_string_into_number(&self, s: &str) -> Option<Vec<u8>> {
280 match utils::format_string_into_number(s) {
281 Some((num, false)) => self.format_number(num),
282 Some((num, true)) => {
283 let mut num_shorten = num;
284 for i in self.wordsize..(128/8) {
285 let mask: u128 = (0xFF << (i * 8)) >> 1;
287 if ((num & mask) << 1) >> (i * 8) != 0xFF {
288 return None
289 }
290 num_shorten &= !(0xFF << (i*8));
292 }
293 self.format_number(num_shorten)
294 },
295 None => None,
296 }
297 }
298}
299
300fn run_implementation_macros(asm: &mut Assembler) -> bool {
303 let mut expanded_macros = false;
304 let mut running_implementation_macros = | node: &AsmNode | -> Option<AsmNode> {
305 match node {
306 Source{code, meta} => match (asm.implementation_macro)(code) {
307 Err(msg) => Some(Error{msg, meta: meta.clone()}),
308 Ok(None) => None,
309 Ok(Some(txt)) => {
310 expanded_macros = true;
311 Some(parse_source(&txt, &format!("Expantion of line {} from file {}, being {}", meta.line, &meta.source_file, &meta.raw)))
312 },
313 },
314 _ => None,
315 }
316 };
317
318 asm.root.traverse_tree(&mut running_implementation_macros);
319 expanded_macros
320}
321
322
323
324#[test]
326fn test_set_word_size() {
327 let mut asm = Assembler::from_text("");
328 assert_eq!(asm.set_word_size(8), None);
329 assert_eq!(asm.set_word_size(128), None);
330 assert_ne!(asm.set_word_size(256), None);
331 assert_ne!(asm.set_word_size(63), None);
332 assert_ne!(asm.set_word_size(0), None);
333}
334
335#[test]
336fn test_format_number() {
337 let mut asm = Assembler::from_text("");
338 assert_eq!(asm.set_word_size(8), None);
339 assert_eq!(asm.format_number(12), Some(vec![12]));
340 assert_eq!(asm.format_number(250), Some(vec![250]));
341 assert_eq!(asm.format_number(260), None);
342 assert_eq!(asm.set_word_size(16), None);
343 assert_eq!(asm.format_number(12), Some(vec![12, 0]));
344 assert_eq!(asm.format_number(250), Some(vec![250, 0]));
345 assert_eq!(asm.format_number(260), Some(vec![4, 1]));
346 assert_eq!(asm.format_number(0x10000), None);
347}
348
349#[test]
350fn format_string_into_number() {
351 let mut asm = Assembler::from_text("");
352 assert_eq!(asm.set_word_size(8), None);
353 assert_eq!(asm.format_string_into_number("12"), Some(vec![12]));
354 assert_eq!(asm.format_string_into_number("250"), Some(vec![250]));
355 assert_eq!(asm.format_string_into_number("260"), None);
356 assert_eq!(asm.format_string_into_number("-129"), None);
357 assert_eq!(asm.format_string_into_number("-10"), Some(vec![0xF6]));
358 assert_eq!(asm.set_word_size(16), None);
359 assert_eq!(asm.format_string_into_number("12"), Some(vec![12, 0]));
360 assert_eq!(asm.format_string_into_number("250"), Some(vec![250, 0]));
361 assert_eq!(asm.format_string_into_number("260"), Some(vec![4, 1]));
362 assert_eq!(asm.format_string_into_number("0x10000"), None);
363 assert_eq!(asm.format_string_into_number("Potate"), None);
364 assert_eq!(asm.format_string_into_number("0xFFF"), Some(vec![0xFF, 0xF]));
365 assert_eq!(asm.format_string_into_number("-10"), Some(vec![0xF6, 0xFF]));
366}
367