-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy paththreaded_interpreter.cpp
More file actions
113 lines (93 loc) · 2.57 KB
/
threaded_interpreter.cpp
File metadata and controls
113 lines (93 loc) · 2.57 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
#include "threaded_interpreter.hpp"
ThreadedInterpreter::ThreadedInterpreter(InputQueue* iq, OutputQueue* oq): m_iq(iq), m_oq(oq) {
start();
}
// evaluate a stream directly
ThreadedInterpreter::ThreadedInterpreter(OutputQueue* oq, std::istream& stream): m_oq(oq) {
if (!m_thread.joinable()) {
m_thread = std::thread([this, &stream](){
Interpreter interp;
loadStartupFile(interp);
// pop in case there was an error with the startup file
OutputMessage msg;
m_oq->try_pop(msg);
evalStream(interp, stream);
});
}
}
// Be sure to stop and join the thread when falling out of scope
ThreadedInterpreter::~ThreadedInterpreter() {
stop();
}
void ThreadedInterpreter::start() {
active = true;
if (!m_thread.joinable()) {
// Move a new thread into the class' thread
m_thread = std::thread(&ThreadedInterpreter::run, this);
}
}
void ThreadedInterpreter::stop() {
active = false;
if (m_thread.joinable()) {
m_thread.join();
}
}
void ThreadedInterpreter::reset() {
stop();
start();
}
bool ThreadedInterpreter::isActive() const {
return active;
}
void ThreadedInterpreter::error(const std::string& e) {
m_oq->push(OutputMessage(ErrorType, e));
}
void ThreadedInterpreter::evalStream(Interpreter& interp, std::istream& stream) {
if (!interp.parseStream(stream)) {
error("Invalid Expression. Could not parse.");
} else {
// try to evaluate the expression, push the result to the output queue
try {
Expression exp = interp.evaluate();
m_oq->push(OutputMessage(ExpressionType, exp));
} catch(const SemanticError& ex) {
error(std::string(ex.what()));
}
}
}
void ThreadedInterpreter::run() {
Interpreter interp;
loadStartupFile(interp);
while (active) {
// Grab input messages as they populate the queue. If not message is returned, then continue
// iterating
InputMessage msg;
if (m_iq->try_pop(msg)) {
// Attempt to parse the input stream
std::istringstream stream(msg);
evalStream(interp, stream);
}
}
}
void ThreadedInterpreter::loadStartupFile(Interpreter& interp) {
std::ifstream ifs(STARTUP_FILE);
if (!ifs) {
error("Could not open startup file for reading.");
} else {
// Just load the expressions from the startup file into the interpreter. We don't need to do
// anything with them
if (!interp.parseStream(ifs)) {
error("Invalid Program in startup file. Could not parse.");
} else {
try {
interp.evaluate();
} catch (const SemanticError& ex) {
error(std::string(ex.what()) + " [startup]");
}
}
}
startupLoaded = true;
}
bool ThreadedInterpreter::isStartupLoaded() const {
return startupLoaded;
}