bedrock_vm/
assembler.rs

1// Copyright 2022 Devin Rockwell
2
3/*
4     This file is part of Bedrock.
5
6    Bedrock is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
7
8    Bedrock is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9
10    You should have received a copy of the GNU General Public License along with Bedrock. If not, see <https://www.gnu.org/licenses/>.
11*/
12
13use 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}