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
use log::info;
use std::{
env,
fs::File,
io::{self, Read, Write},
path::Path,
process::exit,
};
use umpl::{cli, error, eval::Eval, lexer::Lexer, parser::Parser};
fn main() {
let args: Vec<String> = env::args().collect(); // get the args
let (index, mut parsed_args): (usize, cli::ParsedArgs) = cli::get_string_args(&args); // get the ile name args and the index of the firrst flag
if index != 0 {
// if there are any args after the program name parse them
cli::get_dash_args(&args, index, &mut parsed_args);
}
if parsed_args.log {
simple_file_logger::init_logger!("UMPL", simple_file_logger::LogLevel::Debug)
.expect("couldn't initialize logger");
}
let mut full_repl: Vec<String> = Vec::new(); // create a vector to hold the lines of the repl just in case we need to write it to a file
if parsed_args.repl {
// if we are in repl mode
let mut current_repl: String = String::new(); // create a string to hold the current line of the repl
'l: loop {
let mut input = String::new();
print!(">> "); // print the prompt
io::stdout()
.flush()
.unwrap_or_else(|_| panic!("Failed to flush stdout"));
io::stdin()
.read_line(&mut input)
.unwrap_or_else(|_| panic!("Failed to read stdin"));
if input.trim() == "exit" {
// if the input is exit, then exit
info!("Exiting...");
if !parsed_args.file.is_empty() {
// if we are in repl mode and we have a file to write to
if Path::new(&parsed_args.file).exists() && !parsed_args.force {
// if the file exists and we are not forcing it to overwrite
print!("Do you want to overwrite the {}? (y/n): ", parsed_args.file); // ask the user if they want to overwrite the file
io::stdout()
.flush()
.unwrap_or_else(|_| panic!("Failed to flush stdout"));
let mut y_or_n: String = String::new();
io::stdin()
.read_line(&mut y_or_n)
.unwrap_or_else(|_| panic!("Failed to read stdin")); // read the input
if y_or_n == "n" {
// if the user does not want to overwrite the file exit
exit(0);
}
}
let mut file: File = File::create(parsed_args.file)
.expect("Error encountered while creating file!"); // create/open the file
for line in full_repl {
file.write_all(line.as_bytes())
.expect("Error encountered while writing to file!");
}
}
break 'l;
} else if input.trim() == "run" {
run(current_repl.to_string()); // run the current repl
input.clear();
} else {
current_repl.push_str(&input); // add the input to the current line of the repl
full_repl.push(input.to_string());
}
}
} else {
// if we are not in repl mode ie we are reading a file
let mut file: File = File::open(&parsed_args.file).unwrap_or_else(|_| {
error::error(0, "Error encountered while opening file!");
}); // open the file
let mut contents: String = String::new(); // create a string to hold the contents of the file
match file.read_to_string(&mut contents) {
Ok(contents) => contents,
Err(_) => {
error::error(0, "could not read file");
}
}; // read the file into the string
run(contents); // run the file
}
}
fn run(line: String) {
let lexer: Lexer = Lexer::new(line);
let mut parsed: Parser = Parser::new(lexer.scan_tokens());
Eval::new(parsed.parse());
}