1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use std::io::{self, BufRead, Write};

use crate::{lexer::Lexer, parser::Parser, token::Kind};

use super::{bytecode::compiler::Compiler, vm::VM};
const PROMPT: &str = "-> ";

pub fn start() {
    let mut buf = String::new();
    let mut stdin = io::stdin().lock(); // We get `Stdin` here.

    let debug_lexer = false;
    let debug_parser = false;
    let show_error = true;

    loop {
        io::stdout().lock().write_all(PROMPT.as_bytes()).unwrap();
        io::stdout().flush().unwrap();
        match stdin.read_line(&mut buf) {
            Ok(_) => {
                let lexer = Lexer::new(buf.clone());

                let mut cloned_lexer = lexer.clone();

                if debug_lexer {
                    loop {
                        let cur_token = cloned_lexer.next_token();

                        println!("Debug Output (Lexer) >> {:?}", cur_token);

                        if cur_token.kind == Kind::EOF {
                            break;
                        }
                    }
                }

                let mut parser = Parser::new(lexer);
                let program = parser.parse();

                if debug_parser {
                    println!("Debug Output (Parser) >> {:?}", program);
                }

                if let Ok(program) = program {
                    let comp_rst = Compiler::create();
                    if comp_rst.is_err() {
                        println!(
                            "Error while compiler creation {:?}",
                            comp_rst
                        );
                        continue;
                    }
                    let mut compiler = comp_rst.unwrap();

                    let comp = compiler.compile(program);

                    if comp.is_err() {
                        println!("Error while compiler creation {:?}", comp);
                        continue;
                    }

                    let bytecode_rst = compiler.bytecode();
                    match bytecode_rst {
                        Ok(_) => (),
                        Err(err) => {
                            println!("Error while taking bytecode {:?}", err);
                            continue;
                        }
                    }

                    let mut vm =
                        unsafe { VM::new(bytecode_rst.unwrap_unchecked()) };
                    buf.clear();
                    println!("Intitial state:{}", vm);

                    println!("Commands:");
                    println!("\tpressing enter: excute next cycle.");
                    println!("\t          exit: terminate");

                    loop {
                        match stdin.read_line(&mut buf) {
                            Ok(_) => {
                                // HACK: clear screen
                                println!("\n\n\n\n\n\n\n\n\n");
                                println!("\n\n\n\n\n\n\n\n\n");
                                println!("\n\n\n\n\n\n\n\n\n");
                                println!("\n\n\n\n\n\n\n\n\n");
                                if buf == "exit" {
                                    break;
                                }
                                if !vm.is_runable() {
                                    break;
                                }
                                if let Err(e) = vm.run_single() {
                                    eprintln!("{:?}", e);
                                }

                                println!("{}", vm);
                            }
                            Err(err) => {
                                println!("Error occured during reading stdin");
                                println!("{:?}", err);
                            }
                        }
                    }

                    println!("VM Terminated.");
                    println!("Please give new input.");
                } else if show_error {
                    println!("!!!> ERROR OCCURED <!!!");
                    for errs in program.err().unwrap() {
                        println!(">> ERROR DETAIL ");
                        for err in errs {
                            println!("Pos>> {:?}", err.as_ref().position());
                            println!("Detail>> {} ", err.as_ref().detail());
                        }
                    }
                }
                buf.clear();
            }
            Err(err) => {
                println!("Error occured during reading stdin");
                println!("{:?}", err);
                return;
            }
        }
    }
}