This repository has been archived by the owner on Jan 16, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 12
/
002main.cc
177 lines (150 loc) · 4.21 KB
/
002main.cc
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
172
173
174
175
176
177
//// run unit tests or interactive interpreter
bool Interactive = false;
string Last_file = "";
int main(int argc, const char* argv[]) {
// Stop loading Wart files early for faster startup.
Last_file = flag_value("--until", argc, argv);
if (flag("test", argc, argv))
return run_tests();
//// Interactive loop: parse commands from user, evaluate them, print the results
setup();
cerr << time_string() << " loading wart files (takes ~15 seconds)\n";
load_files(".wart");
cerr << time_string() << " ready! type in an expression, then hit enter twice. ctrl-d exits.\n";
Interactive = true; // stop run on two enters
while (!cin.eof()) {
cell* curr = run(cin);
cout << "=> " << curr << '\n';
rmref(curr);
}
}
//// read: tokenize, parenthesize, parse, transform infix, build cells, transform $vars
// simply returns nil on eof
cell* read(indent_sensitive_stream& in) {
return mkref(transform_dollar_vars(next_cell(in)));
}
// parenthesize requires input stream to know when it's at start of line
struct indent_sensitive_stream {
istream& fd;
bool at_start_of_line;
explicit indent_sensitive_stream(istream& in) :fd(in), at_start_of_line(true) { fd >> std::noskipws; }
// leaky version just for convenient tests
explicit indent_sensitive_stream(string s) :fd(*new stringstream(s)), at_start_of_line(true) { fd >> std::noskipws; }
bool eof() { return fd.eof(); }
};
extern cell* nil;
cell* run(istream& i) {
indent_sensitive_stream in(i);
cell* result = nil;
while (true) {
cell* form = read(in);
update(result, eval(form));
rmref(form);
if (in.eof()) break;
if (Interactive && at_end_of_line(in))
// 'in' has no state left; destroy and print
break;
}
return result;
}
bool at_end_of_line(indent_sensitive_stream& in) {
if (in.at_start_of_line) return true;
skip_whitespace(in.fd);
if (in.fd.peek() == '#')
skip_comment(in.fd);
return in.fd.peek() == '\n';
}
bool flag(const string& flag, int argc, const char* argv[]) {
for (int i = 1; i < argc; ++i)
if (string(argv[i]) == flag)
return true;
return false;
}
string flag_value(const string& flag, int argc, const char* argv[]) {
for (int i = 1; i < argc-1; ++i)
if (string(argv[i]) == flag)
return argv[i+1];
return "";
}
//// test harness
int run_tests() {
cerr << time_string() << " C tests\n";
for (unsigned long i=0; i < sizeof(Tests)/sizeof(Tests[0]); ++i) {
START_TRACING_UNTIL_END_OF_SCOPE;
setup();
CLEAR_TRACE;
//? Trace_stream->dump_layer = "test"; // uncomment to segment test output
(*Tests[i])();
verify();
}
setup();
cerr << "\n" << time_string() << " loading wart files (takes ~15 seconds)\n";
load_files(".wart"); // after GC tests
cerr << time_string() << " wart tests\n";
load_files(".test");
cerr << '\n';
if (Num_failures > 0)
cerr << Num_failures << " failure"
<< (Num_failures > 1 ? "s" : "")
<< '\n';
return Num_failures;
}
void verify() {
Hide_warnings = false;
teardown_streams();
teardown_compiledfns();
teardown_cells();
if (!Passed)
;
else if (num_unfreed() > 0)
dump_unfreed();
else
cerr << ".";
}
void setup() {
grow_stack();
setup_cells();
setup_common_syms();
setup_scopes();
setup_compiledfns();
setup_streams();
Interactive = false;
Hide_warnings = false;
Passed = true;
}
#include <sys/resource.h>
void grow_stack() {
static bool already_called = false;
if (already_called) return;
already_called = true;
// Modern machines have gigabytes of memory; spare one for the stack.
rlimit limit;
getrlimit(RLIMIT_STACK, &limit);
limit.rlim_cur = 1024*1024*1024;
setrlimit(RLIMIT_STACK, &limit);
}
//// helpers for tests
void read_all(string s) {
stringstream ss(s);
indent_sensitive_stream in(ss);
do {
rmref(read(in));
} while (!in.eof());
// return nothing; we'll just verify the trace
}
void run(string s) {
stringstream in(s);
rmref(run(in));
// return nothing; we'll just verify the trace
}
cell* read(string s) {
return read(*new stringstream(s));
}
string time_string() {
time_t t;
time(&t);
char buffer[10];
if (!strftime(buffer, 10, "%H:%M:%S", localtime(&t)))
return "";
return buffer;
}