-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrustrepl.rs
More file actions
171 lines (154 loc) · 5.6 KB
/
Copy pathrustrepl.rs
File metadata and controls
171 lines (154 loc) · 5.6 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#[link(name = "rustrepl", vers = "0.2", author = "dbp")];
extern mod std;
use std::tempfile;
use io::WriterUtil;
struct AbstrSession {mut view_items: ~[~str], mut definitions: ~[~str], mut stmt: ~str}
fn write_session(s: AbstrSession, path: path::Path) {
if os::path_exists(&path) {
os::remove_file(&path);
}
let w = result::get(&(io::file_writer(&path, ~[io::Create])));
for vec::each(s.view_items) |i| {
w.write_line(i+~";");
}
w.write_line(~"fn main() {");
for vec::each(s.definitions) |d| {
w.write_line(d+~";");
}
if s.stmt != ~"" {
w.write_line(~"io::println(fmt!(\"%?\","+s.stmt+~"));");
}
w.write_line(~"\n}\n")
}
fn check_session(s: AbstrSession, tmppath: path::Path) -> bool {
let path = tmppath.push("sess.rs");
write_session(s, copy path);
let out = run::program_output(~"rustc", ~[path.to_str()]);
match out.status {
0 => { return true; }
_ => {
let fst = copy str::split_char(out.err, '\n')[0];
let err_indx = option::get(&(str::find_str(fst, ~"error:")));
io::println(str::slice(fst, err_indx, str::len(fst)));
return false;
}
}
}
fn handle_command(c: char, rest: ~str, tmppath: path::Path) {
match c {
'w' => {
let new_path = path::from_str(str::trim(rest));
// pretty print the output
let out = run::program_output(~"rustc",
~[~"--pretty", ~"normal",
tmppath.push("sess.rs").to_str()]);
let out_path = tmppath.push("out.rs");
if os::path_exists(&out_path) {
os::remove_file(&out_path);
}
let w = result::get(&(io::file_writer(&out_path, ~[io::Create])));
w.write_str(out.out);
if !os::copy_file(&out_path, &new_path) {
io::println(fmt!("could not write to %s.", new_path.to_str()));
}
}
'l' => {
io::println(~"not implemented yet.");
}
'h' => {
io::println("about:");
io::println("this is a very simple repl for rust. type in \
expressions to evaluate,");
io::println("let statements to make local definitions, import \
and use statements, and ");
io::println("fn statements to define functions. don't add \
trailing semis!");
io::println("commands:");
io::println(":w filename.rs - write current session to file.");
io::println(":l filename.rs - load session from file - will erase \
current session. (not yet implemented)");
io::println(":h - this message.");
}
_ => {
io::println("unknown command. :h for help.");
}
}
}
fn main() {
// set up working directory
let p = tempfile::mkdtemp(&(os::tmpdir()), ~"repl");
if option::is_none(&p) {
fail ~"could not create temporary directory";
}
let tmppath = option::unwrap(p);
io::println("repl for rust, 0.2.");
io::println("don't use trailing semicolons. :h for help, Ctrl-D to quit.");
let mut session = AbstrSession {view_items: ~[], definitions: ~[], stmt: ~""};
loop {
let stdin = io::stdin();
io::print("rust> ");
let raw_input = (stdin as io::ReaderUtil).read_line();
if str::is_empty(raw_input) {
if stdin.eof() {
io::println("");
break;
}
loop;
}
let input = str::trim(raw_input);
if input[0] == ':' as u8 {
handle_command(input[1] as char, if str::len(input) > 3 {
str::slice(input, 3, str::len(input))
} else {~""}, copy tmppath);
} else {
let view_pop;
let def_pop;
let stmt_pop;
let mut run = false; // should we run, ie, has stmt changed
if str::starts_with(input, ~"use ") ||
str::starts_with(input, ~"extern mod ") {
session.view_items.push(input);
view_pop = true;
def_pop = false;
stmt_pop = ~"";
} else if str::starts_with(input, ~"fn ") ||
str::starts_with(input, ~"let ") {
session.definitions.push(input);
view_pop = false;
def_pop = true;
stmt_pop = ~"";
} else {
view_pop = false;
def_pop = false;
stmt_pop = copy session.stmt;
run = true;
session.stmt = input;
}
if check_session(copy session, copy tmppath) {
if run {
let sess = tmppath.push("sess");
let res = run::program_output(sess.to_str(), ~[]);
io::print(res.out);
}
} else {
if view_pop {
session.view_items.pop();
}
if def_pop {
session.definitions.pop();
}
session.stmt = stmt_pop;
}
}
}
// clean up tmp stuff. we want recursive, so call out to system.
remove_tmpdir(tmppath);
}
#[cfg(unix)]
fn remove_tmpdir(tmppath: Path) {
run::program_output(~"rm", ~[~"-R", tmppath.to_str()]);
}
#[cfg(windows)]
fn remove_tmpdir(tmppath: Path) {
run::program_output(~"rd", ~[~"/S", ~"/Q", tmppath.to_str()]);
}