iridium/assembler/
program_parsers.rs

1use assembler::directive_parsers::directive;
2use assembler::instruction_parsers::{instruction, AssemblerInstruction};
3use assembler::SymbolTable;
4use nom::types::CompleteStr;
5
6#[derive(Debug, PartialEq)]
7pub struct Program {
8    pub instructions: Vec<AssemblerInstruction>,
9}
10
11impl Program {
12    pub fn to_bytes(&self, symbols: &SymbolTable) -> Vec<u8> {
13        let mut program = vec![];
14        for instruction in &self.instructions {
15            program.append(&mut instruction.to_bytes(symbols));
16        }
17        program
18    }
19}
20
21named!(pub program<CompleteStr, Program>,
22    do_parse!(
23        instructions: many1!(alt!(instruction | directive)) >>
24        (
25            Program {
26                instructions
27            }
28        )
29    )
30);
31
32#[cfg(test)]
33mod tests {
34    use super::*;
35    use assembler::Assembler;
36    use vm::VM;
37
38    #[test]
39    fn test_parse_program() {
40        let result = program(CompleteStr("load $0 #100\n"));
41        assert_eq!(result.is_ok(), true);
42        let (leftover, p) = result.unwrap();
43        assert_eq!(leftover, CompleteStr(""));
44        assert_eq!(1, p.instructions.len());
45        // TODO: Figure out an ergonomic way to test the AssemblerInstruction returned
46    }
47
48    #[test]
49    fn test_program_to_bytes() {
50        let result = program(CompleteStr("load $0 #100\n"));
51        assert_eq!(result.is_ok(), true);
52        let (_, program) = result.unwrap();
53        let symbols = SymbolTable::new();
54        let bytecode = program.to_bytes(&symbols);
55        assert_eq!(bytecode.len(), 4);
56    }
57
58    #[test]
59    fn test_complete_program() {
60        let test_program = CompleteStr(".data\nhello: .asciiz 'Hello everyone!'\n.code\nhlt");
61        let result = program(test_program);
62        assert_eq!(result.is_ok(), true);
63    }
64
65    #[test]
66    fn test_parse_load_greater_than_i16() {
67        let mut test_assembler = Assembler::new();
68        let mut test_vm = VM::new();
69        let result = test_assembler.assemble(".data\n.code\nload $0 #-50000");
70        assert!(result.is_ok());
71        let result = result.unwrap();
72        test_vm.program = result;
73        test_vm.run();
74    }
75
76    #[test]
77    fn test_parse_cloop() {
78        let mut test_assembler = Assembler::new();
79        let mut test_vm = VM::new();
80        let result = test_assembler.assemble(".data\n.code\ncloop #10");
81        assert!(result.is_ok());
82        let result = result.unwrap();
83        test_vm.program = result;
84        test_vm.run();
85    }
86}