vm_translator/
lib.rs

1//! VM TRanslator
2//!
3//! Does the job of translating using the other modules
4
5pub mod code_writer;
6mod constants;
7pub mod parser;
8
9use glob::glob;
10use std::   path::Path;
11
12use code_writer::CodeWriter;
13use parser::{CommandType, Parser};
14
15fn vm_functionality(parser: &mut Parser, code_writer: &mut CodeWriter) {
16    while parser.has_more_lines() {
17        parser.advance();
18        match parser.command_type() {
19            CommandType::C_PUSH(_) | CommandType::C_POP(_) => code_writer.write_push_pop(
20                Some(parser.current_command.as_str()),
21                parser.command_type(),
22                parser.arg1().as_str(),
23                parser.arg2(),
24            ),
25            CommandType::C_LABEL(_) => code_writer.write_label(&parser.arg1()),
26            CommandType::C_GOTO(_) => code_writer.write_goto(&parser.arg1()),
27            CommandType::C_IF(_) => code_writer.write_if(&parser.arg1()),
28            CommandType::C_FUNCTION(_) => code_writer.write_function(&parser.arg1(), parser.arg2()),
29            CommandType::C_ARITHMETIC(_) => code_writer
30                .write_arithmetic(Some(parser.current_command.as_str()), parser.command_type()),
31            CommandType::C_RETURN => code_writer.write_return(),
32            CommandType::C_CALL(_) => code_writer.write_call(&parser.arg1(), parser.arg2()),
33        };
34    }
35}
36
37pub fn vm_translator(mut args: impl Iterator<Item = String>) {
38    args.next(); // Enter next value
39
40    let filepath = args.next().expect("Filepath is required!");
41    let filepath = Path::new(&filepath);
42    let output_filepath = if !filepath.is_dir() {
43        filepath.with_extension("asm")
44    } else {
45        filepath
46            .join(filepath.file_name().unwrap())
47            .with_extension("asm")
48    };
49    let mut code_writer = CodeWriter::new(&output_filepath);
50
51    if filepath.is_dir() {
52        let file_pattern = filepath.join("**").join("*.vm");
53        for entry in glob(file_pattern.to_str().unwrap()).unwrap() {
54            match entry {
55                Ok(file_path) => {
56                    let mut parser = Parser::new(&file_path);
57                    // set the new file name here
58                    code_writer.set_file_name(
59                        file_path.as_path()
60                            .file_stem().unwrap().to_str().expect("Invalid file encountered in dir")
61                    );
62                    vm_functionality(&mut parser, &mut code_writer);
63                }
64                Err(e) => println!("Invalid path dir provided {:?}", e),
65            }
66        }
67    } else {
68        let mut parser = Parser::new(filepath);
69        vm_functionality(&mut parser, &mut code_writer);
70    }
71}