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
use std::io::{self, BufRead, Write};

use crate::{
    ast::Nodetrait,
    heap::Heap,
    lexer::Lexer,
    object::{environment::Environment, ObjectTrait},
    parser::Parser,
    token::Kind,
    treewalker::eval::evaluate,
};
const PROMPT: &str = "-> ";

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

    let mut env = Environment::new();
    let mut heap = Heap::new();

    let debug_lexer = false;
    let debug_parser = false;
    let debug_evaluator = 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(_) => {
                if buf == "$env\n" {
                    dbg!(&env);
                    buf.clear();
                    continue;
                }
                if buf == "$heap\n" {
                    dbg!(&heap);
                    buf.clear();
                    continue;
                }
                if buf == "$rungc\n" {
                    heap.run_gc(&mut env);
                    buf.clear();
                    continue;
                }
                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 program.is_ok() {
                    let program = program.unwrap();
                    let result =
                        evaluate(program.to_node(), &mut heap, &mut env);

                    if debug_evaluator {
                        println!("Debug Output (Eval) >> {:?}", result);
                    }

                    if result.is_ok() {
                        let eval = result.unwrap();
                        if eval.is_some() {
                            let val = eval.unwrap();
                            println!("{}", val.to_str());
                        }
                    } else if show_error {
                        println!("!!!> ERROR OCCURED <!!!");
                        println!(">> ERROR DETAIL ");
                        println!("{:?}", result.err().unwrap());
                    }
                } 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;
            }
        }
    }
}