1use pest::{error::Error, Parser};
14use std::collections::HashMap;
15
16use crate::instruction::Opcode;
17
18type SymbolTable = HashMap<String, usize>;
19
20#[derive(Parser)]
21#[grammar = "asm.pest"]
22pub struct AsmParser;
23
24#[derive(Debug)]
25pub struct Program {
26 pub data: Vec<DataItem>,
27 pub code: Vec<Instruction>,
28 pub code_tab: SymbolTable,
29 pub data_tab: SymbolTable,
30}
31
32#[derive(Debug)]
33pub enum DataItem {
34 Str(String),
35 Integer(i64),
36 Float(f64)
37}
38
39#[derive(Debug)]
40pub enum Instruction {
41 Halt,
42 Load(u8, [u8; 8]),
43 Add(u8, u8, u8),
44 Sub(u8, u8, u8),
45 Mul(u8, u8, u8),
46 Div(u8, u8, u8, u8),
47 Addf(u8, u8, u8),
48 Subf(u8, u8, u8),
49 Mulf(u8, u8, u8),
50 Divf(u8, u8, u8, u8),
51 Cmp(u8, u8),
52 Cmpf(u8, u8),
53 Jmp(JmpArg),
54 Je(JmpArg),
55 Jne(JmpArg),
56 Jg(JmpArg),
57 Jge(JmpArg),
58 Jl(JmpArg),
59 Jle(JmpArg),
60 Alloc(u8, u8),
61 Dealloc(u8),
62 Read(u8, u8, u8),
63 Readn(u8, u8, u8),
64 Write(u8, u8, u8),
65 Writen(u8, u8, u8),
66 Realloc(u8, u8),
67 Len(u8, u8),
68 Print(JmpArg),
69 Printi(JmpArg),
70 Printri(u8),
71 Printrf(u8),
72 Printf(JmpArg),
73}
74
75#[derive(Debug)]
76pub enum JmpArg {
77 Label(String),
78 Register(u8)
79}
80
81#[derive(Debug)]
82pub enum ParseError {
83 Pest(Error<Rule>),
84 Msg(String),
85}
86
87const HEADER: [u8;8] = [66, 69, 70, 0, 0, 0, 0, 0];
88
89fn parse(source: &str) -> Result<Program, ParseError> {
90 let tree = AsmParser::parse(Rule::program, source);
91 let mut instrs = Vec::new();
92 let mut data = Vec::new();
93 let mut code_tab = HashMap::new();
94 let mut data_tab = HashMap::new();
95 match tree {
96 Ok(mut t) => {
97 let mut pos = 16;
98 let mut dpos = 0;
99 for instr in t.next().unwrap().into_inner() {
100 match instr.as_rule() {
101 Rule::halt => {
102 instrs.push(Instruction::Halt);
103 pos += 1;
104 },
105 Rule::load => {
106 let mut inner_rules = instr.into_inner();
107 let reg: u8 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
108 let npair = inner_rules.next().unwrap();
109 match npair.as_rule() {
110 Rule::integer => {
111 let n: i64 = npair.as_str().parse().unwrap();
112 instrs.push(Instruction::Load(reg, n.to_le_bytes()))
113 },
114 Rule::float => {
115 let n: f64 = npair.as_str().parse().unwrap();
116 instrs.push(Instruction::Load(reg, n.to_le_bytes()))
117
118 },
119 _ => unreachable!()
120 }
121 pos += 10;
122 },
123 Rule::add => {
124 let mut inner_rules = instr.into_inner();
125 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
126 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
127 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
128 instrs.push(Instruction::Add(r1, r2, r3));
129 pos += 4;
130 },
131 Rule::sub => {
132 let mut inner_rules = instr.into_inner();
133 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
134 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
135 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
136 instrs.push(Instruction::Sub(r1, r2, r3))
137 },
138 Rule::mul => {
139 let mut inner_rules = instr.into_inner();
140 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
141 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
142 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
143 pos += 4;
144 instrs.push(Instruction::Mul(r1, r2, r3))
145 },
146 Rule::div => {
147 let mut inner_rules = instr.into_inner();
148 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
149 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
150 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
151 let r4 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
152 pos += 5;
153 instrs.push(Instruction::Div(r1, r2, r3, r4))
154 },
155 Rule::addf => {
156 let mut inner_rules = instr.into_inner();
157 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
158 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
159 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
160 pos += 4;
161 instrs.push(Instruction::Addf(r1, r2, r3))
162 },
163 Rule::subf => {
164 let mut inner_rules = instr.into_inner();
165 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
166 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
167 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
168 pos += 4;
169 instrs.push(Instruction::Subf(r1, r2, r3))
170 },
171 Rule::mulf => {
172 let mut inner_rules = instr.into_inner();
173 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
174 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
175 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
176 pos += 4;
177 instrs.push(Instruction::Mulf(r1, r2, r3))
178 },
179 Rule::divf => {
180 let mut inner_rules = instr.into_inner();
181 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
182 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
183 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
184 let r4 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
185 pos += 5;
186 instrs.push(Instruction::Divf(r1, r2, r3, r4))
187 },
188 Rule::cmp => {
189 let mut inner_rules = instr.into_inner();
190 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
191 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
192 pos += 3;
193 instrs.push(Instruction::Cmp(r1, r2))
194 }
195 Rule::cmpf => {
196 let mut inner_rules = instr.into_inner();
197 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
198 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
199 pos += 3;
200 instrs.push(Instruction::Cmpf(r1, r2))
201 }
202 Rule::jmp => {
203 let mut inner_rules = instr.into_inner();
204 let arg = inner_rules.next().unwrap();
205 match arg.as_rule() {
206 Rule::label => {
207 instrs.push(Instruction::Jmp(JmpArg::Label(arg.as_str().to_owned())));
208 },
209 Rule::register => {
210 instrs.push(Instruction::Jmp(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
211 },
212 _ => unreachable!()
213 }
214 pos += 2;
215 }
216 Rule::je => {
217 let mut inner_rules = instr.into_inner();
218 let arg = inner_rules.next().unwrap();
219 match arg.as_rule() {
220 Rule::label => {
221 instrs.push(Instruction::Je(JmpArg::Label(arg.as_str().to_owned())));
222 },
223 Rule::register => {
224 instrs.push(Instruction::Je(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
225 },
226 _ => unreachable!()
227 }
228 pos += 2;
229 }
230 Rule::jne => {
231 let mut inner_rules = instr.into_inner();
232 let arg = inner_rules.next().unwrap();
233 match arg.as_rule() {
234 Rule::label => {
235 instrs.push(Instruction::Jne(JmpArg::Label(arg.as_str().to_owned())));
236 },
237 Rule::register => {
238 instrs.push(Instruction::Jne(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
239 },
240 _ => unreachable!()
241 }
242 pos += 2;
243 }
244 Rule::jg => {
245 let mut inner_rules = instr.into_inner();
246 let arg = inner_rules.next().unwrap();
247 match arg.as_rule() {
248 Rule::label => {
249 instrs.push(Instruction::Jg(JmpArg::Label(arg.as_str().to_owned())));
250 },
251 Rule::register => {
252 instrs.push(Instruction::Jg(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
253 },
254 _ => unreachable!()
255 }
256 pos += 2;
257 }
258 Rule::jge => {
259 let mut inner_rules = instr.into_inner();
260 let arg = inner_rules.next().unwrap();
261 match arg.as_rule() {
262 Rule::label => {
263 instrs.push(Instruction::Jge(JmpArg::Label(arg.as_str().to_owned())));
264 },
265 Rule::register => {
266 instrs.push(Instruction::Jge(JmpArg::Register(arg.as_str()[1..].parse().unwrap()))) },
267 _ => unreachable!()
268 }
269 pos += 2;
270 }
271 Rule::jl => {
272 let mut inner_rules = instr.into_inner();
273 let arg = inner_rules.next().unwrap();
274 match arg.as_rule() {
275 Rule::label => {
276 instrs.push(Instruction::Jl(JmpArg::Label(arg.as_str().to_owned())));
277 },
278 Rule::register => {
279 instrs.push(Instruction::Jl(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
280 },
281 _ => unreachable!()
282 }
283 pos += 2;
284 }
285 Rule::jle => {
286 let mut inner_rules = instr.into_inner();
287 let arg = inner_rules.next().unwrap();
288 match arg.as_rule() {
289 Rule::label => {
290 instrs.push(Instruction::Jle(JmpArg::Label(arg.as_str().to_owned())));
291 },
292 Rule::register => {
293 instrs.push(Instruction::Jle(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
294 },
295 _ => unreachable!()
296 }
297 pos += 2;
298 },
299 Rule::alloc => {
300 let mut inner_rules = instr.into_inner();
301 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
302 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
303 pos += 3;
304 instrs.push(Instruction::Alloc(r1, r2))
305 },
306 Rule::dealloc => {
307 let mut inner_rules = instr.into_inner();
308 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
309 pos += 2;
310 instrs.push(Instruction::Dealloc(r1))
311 },
312 Rule::read => {
313 let mut inner_rules = instr.into_inner();
314 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
315 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
316 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
317 pos += 4;
318 instrs.push(Instruction::Read(r1, r2, r3))
319 },
320 Rule::readn => {
321 let mut inner_rules = instr.into_inner();
322 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
323 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
324 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
325 pos += 4;
326 instrs.push(Instruction::Readn(r1, r2, r3))
327 },
328 Rule::write => {
329 let mut inner_rules = instr.into_inner();
330 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
331 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
332 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
333 pos += 4;
334 instrs.push(Instruction::Write(r1, r2, r3))
335 },
336 Rule::writen => {
337 let mut inner_rules = instr.into_inner();
338 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
339 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
340 let r3 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
341 pos += 4;
342 instrs.push(Instruction::Writen(r1, r2, r3))
343 },
344 Rule::realloc => {
345 let mut inner_rules = instr.into_inner();
346 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
347 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
348 pos += 3;
349 instrs.push(Instruction::Realloc(r1, r2))
350 },
351 Rule::len => {
352 let mut inner_rules = instr.into_inner();
353 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
354 let r2 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
355 pos += 3;
356 instrs.push(Instruction::Len(r1, r2))
357 },
358 Rule::label_decl => {
359 let mut inner_rules = instr.into_inner();
360 let val = inner_rules.next().unwrap().as_str();
361 if code_tab.insert(val.to_string(), pos).is_some() {
362 return Err(ParseError::Msg(format!("Error: Duplicate label {}", val)));
363 }
364 }
365 Rule::data_item => {
366 let mut inner_rules = instr.into_inner();
367 let tmp = inner_rules.next().unwrap().as_str();
368 let name = tmp[0..tmp.len()-1].to_owned();
369 let val = inner_rules.next().unwrap();
370 match val.as_rule() {
371 Rule::string => {
372 let st = val.into_inner();
373 data.push(DataItem::Str(st.as_str().to_owned()));
374 if data_tab.get(&name).is_some() {
375 return Err(ParseError::Msg(format!("Error: Duplicate data item {}", name)))
376 }
377 },
378 Rule::integer => {
379 data.push(DataItem::Integer(val.as_str().parse().unwrap()));
380 if let Some(_) = data_tab.get(&name) {
381 return Err(ParseError::Msg(format!("Error: Duplicate data item {}", name)))
382 }
383 },
384 Rule::float => {
385 data.push(DataItem::Float(val.as_str().parse().unwrap()));
386 if data_tab.get(&name).is_some() {
387 return Err(ParseError::Msg(format!("Error: Duplicate data item {}", name)))
388 }
389 }
390 _ => unreachable!()
391 }
392 data_tab.insert(name.clone(), dpos);
393 dpos += 1;
394 }
395 Rule::print => {
396 let mut inner_rules = instr.into_inner();
397 let arg = inner_rules.next().unwrap();
398 match arg.as_rule() {
399 Rule::label => {
400 instrs.push(Instruction::Print(JmpArg::Label(arg.as_str().to_owned())));
401 },
402 Rule::register => {
403 instrs.push(Instruction::Print(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
404 },
405 _ => unreachable!()
406 }
407 pos += 2;
408 }
409 Rule::printi => {
410 let mut inner_rules = instr.into_inner();
411 let arg = inner_rules.next().unwrap();
412 match arg.as_rule() {
413 Rule::label => {
414 instrs.push(Instruction::Printi(JmpArg::Label(arg.as_str().to_owned())));
415 },
416 Rule::register => {
417 instrs.push(Instruction::Printi(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
418 },
419 _ => unreachable!()
420 }
421 pos += 2;
422 }
423 Rule::printf => {
424 let mut inner_rules = instr.into_inner();
425 let arg = inner_rules.next().unwrap();
426 match arg.as_rule() {
427 Rule::label => {
428 instrs.push(Instruction::Printf(JmpArg::Label(arg.as_str().to_owned())));
429 },
430 Rule::register => {
431 instrs.push(Instruction::Printf(JmpArg::Register(arg.as_str()[1..].parse().unwrap())))
432 },
433 _ => unreachable!()
434 }
435 pos += 2;
436 }
437 Rule::printri => {
438 let mut inner_rules = instr.into_inner();
439 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
440 pos += 2;
441 instrs.push(Instruction::Printri(r1))
442 },
443 Rule::printrf => {
444 let mut inner_rules = instr.into_inner();
445 let r1 = inner_rules.next().unwrap().as_str()[1..].parse().unwrap();
446 pos += 2;
447 instrs.push(Instruction::Printrf(r1))
448 },
449 Rule::EOI => {}
450 _ => println!("{:?}", instr.as_rule())
451 }
452 }
453 }
454 Err(e) => return Err(ParseError::Pest(e))
455 }
456 let prog = Program {
457 data,
458 code: instrs,
459 code_tab,
460 data_tab,
461 };
462 Ok(prog)
463}
464
465
466pub fn assemble(source: &str) -> Result<Vec<u8>, ParseError> {
467 let prog = match parse(source) {
468 Ok(res) => res,
469 Err(e) => { return Err(e) }
470 };
471 let mut res = Vec::new();
472 for b in HEADER {
473 res.push(b);
474 }
475
476 let mut dlen: usize = 0;
477 let mut data: Vec<u8> = Vec::new();
478 for item in prog.data {
479 match item {
480 DataItem::Str(val) => {
481 dlen += val.len() + 2;
482 data.push(0);
483 data.append(&mut val.into_bytes());
484 data.push(0);
485 }
486 DataItem::Integer(val) => {
487 dlen += 9;
488 data.push(1);
489 data.append(&mut val.to_le_bytes().to_vec());
490 }
491 DataItem::Float(val) => {
492 dlen += 9;
493 data.push(1);
494 data.append(&mut val.to_le_bytes().to_vec());
495 }
496 }
497 }
498
499 res.append(&mut dlen.to_le_bytes().to_vec());
500 res.append(&mut data);
501
502 for instr in prog.code {
503 match instr {
504 Instruction::Load(r, n) => {
505 res.push(Opcode::Load.into());
506 res.push(r);
507 if r == 255 {
508 eprintln!("warning: it is not recomended to use r255")
509 }
510 for byte in n {
511 res.push(byte);
512 }
513 },
514 Instruction::Add(r1, r2, r3) => {
515 res.push(Opcode::Add.into());
516 res.push(r1);
517 res.push(r2);
518 res.push(r3);
519 },
520 Instruction::Sub(r1, r2, r3) => {
521 res.push(Opcode::Sub.into());
522 res.push(r1);
523 res.push(r2);
524 res.push(r3);
525 },
526 Instruction::Mul(r1, r2, r3) => {
527 res.push(Opcode::Mul.into());
528 res.push(r1);
529 res.push(r2);
530 res.push(r3);
531 },
532 Instruction::Div(r1, r2, r3, r4) => {
533 res.push(Opcode::Div.into());
534 res.push(r1);
535 res.push(r2);
536 res.push(r3);
537 res.push(r4);
538 },
539 Instruction::Addf(r1, r2, r3) => {
540 res.push(Opcode::Addf.into());
541 res.push(r1);
542 res.push(r2);
543 res.push(r3);
544 },
545 Instruction::Subf(r1, r2, r3) => {
546 res.push(Opcode::Subf.into());
547 res.push(r1);
548 res.push(r2);
549 res.push(r3);
550 },
551 Instruction::Mulf(r1, r2, r3) => {
552 res.push(Opcode::Mulf.into());
553 res.push(r1);
554 res.push(r2);
555 res.push(r3);
556 },
557 Instruction::Divf(r1, r2, r3, r4) => {
558 res.push(Opcode::Divf.into());
559 res.push(r1);
560 res.push(r2);
561 res.push(r3);
562 res.push(r4);
563 },
564 Instruction::Cmp(r1, r2) => {
565 res.push(Opcode::Cmp.into());
566 res.push(r1);
567 res.push(r2);
568 },
569 Instruction::Cmpf(r1, r2) => {
570 res.push(Opcode::Cmpf.into());
571 res.push(r1);
572 res.push(r2);
573 },
574 Instruction::Jmp(arg) => {
575 match arg {
576 JmpArg::Register(v) => {
577 res.push(Opcode::Jmp.into());
578 res.push(v);
579 },
580 JmpArg::Label(v) => {
581 let addr = prog.code_tab.get(&v);
582 match addr {
583 Some(a) => {
584 res.push(Opcode::Load.into());
585 res.push(255);
586 for byte in a.to_le_bytes() {
587 res.push(byte)
588 }
589 res.push(Opcode::Jmp.into());
590 res.push(255);
591 }
592 None => {
593 return Err(ParseError::Msg(format!("invalid label {}", v)));
594 }
595 }
596 }
597 }
598 },
599 Instruction::Je(arg) => {
600 match arg {
601 JmpArg::Register(v) => {
602 res.push(Opcode::Je.into());
603 res.push(v);
604 },
605 JmpArg::Label(v) => {
606 let addr = prog.code_tab.get(&v);
607 match addr {
608 Some(a) => {
609 res.push(Opcode::Load.into());
610 res.push(255);
611 for byte in a.to_le_bytes() {
612 res.push(byte)
613 }
614 res.push(Opcode::Je.into());
615 res.push(255);
616 }
617 None => {
618 return Err(ParseError::Msg(format!("invalid label {}", v)));
619 }
620 }
621 }
622 }
623 },
624 Instruction::Jne(arg) => {
625 match arg {
626 JmpArg::Register(v) => {
627 res.push(Opcode::Jne.into());
628 res.push(v);
629 },
630 JmpArg::Label(v) => {
631 let addr = prog.code_tab.get(&v);
632 match addr {
633 Some(a) => {
634 res.push(Opcode::Load.into());
635 res.push(255);
636 for byte in a.to_le_bytes() {
637 res.push(byte)
638 }
639 res.push(Opcode::Jne.into());
640 res.push(255);
641 }
642 None => {
643 return Err(ParseError::Msg(format!("invalid label {}", v)));
644 }
645 }
646 }
647 }
648 },
649 Instruction::Jg(arg) => {
650 match arg {
651 JmpArg::Register(v) => {
652 res.push(Opcode::Jg.into());
653 res.push(v);
654 },
655 JmpArg::Label(v) => {
656 let addr = prog.code_tab.get(&v);
657 match addr {
658 Some(a) => {
659 res.push(Opcode::Load.into());
660 res.push(255);
661 for byte in a.to_le_bytes() {
662 res.push(byte)
663 }
664 res.push(Opcode::Jg.into());
665 res.push(255);
666 }
667 None => {
668 return Err(ParseError::Msg(format!("invalid label {}", v)));
669 }
670 }
671 }
672 }
673 },
674 Instruction::Jge(arg) => {
675 match arg {
676 JmpArg::Register(v) => {
677 res.push(Opcode::Jge.into());
678 res.push(v);
679 },
680 JmpArg::Label(v) => {
681 let addr = prog.code_tab.get(&v);
682 match addr {
683 Some(a) => {
684 res.push(Opcode::Load.into());
685 res.push(255);
686 for byte in a.to_le_bytes() {
687 res.push(byte)
688 }
689 res.push(Opcode::Jge.into());
690 res.push(255);
691 }
692 None => {
693 return Err(ParseError::Msg(format!("invalid label {}", v)));
694 }
695 }
696 }
697 }
698 },
699 Instruction::Jl(arg) => {
700 match arg {
701 JmpArg::Register(v) => {
702 res.push(Opcode::Jl.into());
703 res.push(v);
704 },
705 JmpArg::Label(v) => {
706 let addr = prog.code_tab.get(&v);
707 match addr {
708 Some(a) => {
709 res.push(Opcode::Load.into());
710 res.push(255);
711 for byte in a.to_le_bytes() {
712 res.push(byte)
713 }
714 res.push(Opcode::Jl.into());
715 res.push(255);
716 }
717 None => {
718 return Err(ParseError::Msg(format!("invalid label {}", v)));
719 }
720 }
721 }
722 }
723 },
724 Instruction::Jle(arg) => {
725 match arg {
726 JmpArg::Register(v) => {
727 res.push(Opcode::Jle.into());
728 res.push(v);
729 },
730 JmpArg::Label(v) => {
731 let addr = prog.code_tab.get(&v);
732 match addr {
733 Some(a) => {
734 res.push(Opcode::Load.into());
735 res.push(255);
736 for byte in a.to_le_bytes() {
737 res.push(byte)
738 }
739 res.push(Opcode::Jle.into());
740 res.push(255);
741 }
742 None => {
743 return Err(ParseError::Msg(format!("invalid label {}", v)));
744 }
745 }
746 }
747 }
748 },
749 Instruction::Alloc(r1, r2) => {
750 res.push(Opcode::Alloc.into());
751 res.push(r1);
752 res.push(r2);
753 },
754 Instruction::Dealloc(r) => {
755 res.push(Opcode::Dealloc.into());
756 res.push(r);
757 },
758 Instruction::Read(r1, r2, r3) => {
759 res.push(Opcode::Read.into());
760 res.push(r1);
761 res.push(r2);
762 res.push(r3);
763 },
764 Instruction::Readn(r1, r2, r3) => {
765 res.push(Opcode::Readn.into());
766 res.push(r1);
767 res.push(r2);
768 res.push(r3);
769 },
770 Instruction::Write(r1, r2, r3) => {
771 res.push(Opcode::Write.into());
772 res.push(r1);
773 res.push(r2);
774 res.push(r3);
775 },
776 Instruction::Writen(r1, r2, r3) => {
777 res.push(Opcode::Writen.into());
778 res.push(r1);
779 res.push(r2);
780 res.push(r3);
781 },
782 Instruction::Realloc(r1, r2) => {
783 res.push(Opcode::Realloc.into());
784 res.push(r1);
785 res.push(r2)
786 },
787 Instruction::Len(r1, r2) => {
788 res.push(Opcode::Len.into());
789 res.push(r1);
790 res.push(r2)
791 },
792 Instruction::Halt => {
793 res.push(Opcode::Halt.into());
794 },
795 Instruction::Print(arg) => {
796 match arg {
797 JmpArg::Register(v) => {
798 res.push(Opcode::Print.into());
799 res.push(v);
800 },
801 JmpArg::Label(v) => {
802 let addr = prog.data_tab.get(&v);
803 match addr {
804 Some(a) => {
805 res.push(Opcode::Load.into());
806 res.push(255);
807 for byte in a.to_le_bytes() {
808 res.push(byte)
809 }
810 res.push(Opcode::Print.into());
811 res.push(255);
812 }
813 None => {
814 return Err(ParseError::Msg(format!("invalid data item {}", v)));
815 }
816 }
817 }
818 }
819 }
820 Instruction::Printi(arg) => {
821 match arg {
822 JmpArg::Register(v) => {
823 res.push(Opcode::Printi.into());
824 res.push(v);
825 },
826 JmpArg::Label(v) => {
827 let addr = prog.data_tab.get(&v);
828 match addr {
829 Some(a) => {
830 res.push(Opcode::Load.into());
831 res.push(255);
832 for byte in a.to_le_bytes() {
833 res.push(byte)
834 }
835 res.push(Opcode::Printi.into());
836 res.push(255);
837 }
838 None => {
839 return Err(ParseError::Msg(format!("invalid data item {}", v)));
840 }
841 }
842 }
843 }
844 }
845 Instruction::Printf(arg) => {
846 match arg {
847 JmpArg::Register(v) => {
848 res.push(Opcode::Printf.into());
849 res.push(v);
850 },
851 JmpArg::Label(v) => {
852 let addr = prog.data_tab.get(&v);
853 match addr {
854 Some(a) => {
855 res.push(Opcode::Load.into());
856 res.push(255);
857 for byte in a.to_le_bytes() {
858 res.push(byte)
859 }
860 res.push(Opcode::Printf.into());
861 res.push(255);
862 }
863 None => {
864 return Err(ParseError::Msg(format!("invalid data item {}", v)));
865 }
866 }
867 }
868 }
869 }
870 Instruction::Printri(arg) => {
871 res.push(Opcode::Printri.into());
872 res.push(arg);
873 }
874 Instruction::Printrf(arg) => {
875 res.push(Opcode::Printrf.into());
876 res.push(arg);
877 }
878 }
879 }
880
881 Ok(res)
882}