| #include <QCoreApplication> |
| |
| #include "NbRuntime.h" |
| #include "../Parser.h" |
| #include "../StdLib.h" |
| |
| NbRuntime::NbRuntime(QObject *parent) |
| : QObject(parent) |
| { |
| StdLib().load(_eval); |
| } |
| |
| void NbRuntime::queueCell(Cell *cell) |
| { |
| if (!_cells.contains(cell)) |
| { |
| qInfo() << "Queueing cell"; |
| |
| _cells.append(cell); |
| |
| emit cellWaiting(cell); |
| |
| if (!_running) |
| evalRemaining(); |
| } |
| } |
| |
| void NbRuntime::unqueueCell(Cell *cell) |
| { |
| if (cell == _running) |
| { |
| // Exception should propagate back up to evalRemaining() |
| _eval.quit(); |
| } |
| else |
| { |
| _cells.removeOne(cell); |
| } |
| } |
| |
| void NbRuntime::evalRemaining() |
| { |
| qInfo() << "evalRemaining"; |
| |
| while (!_cells.empty()) |
| { |
| QCoreApplication::processEvents(); |
| |
| Cell *cell = _cells.first(); |
| _cells.removeFirst(); |
| |
| _running = cell; |
| |
| Parser parser(cell->code()); |
| RuntimeResult result; |
| |
| emit cellRunning(cell); |
| |
| try |
| { |
| // Allow this cell to be quit |
| QCoreApplication::processEvents(); |
| |
| while (true) |
| { |
| ParseResult ret; |
| Function func; |
| QList<AstNode> ast; |
| |
| if ((ret = parser.parseFunctionDefinition(&func))) |
| { |
| _eval.addFunction(func); |
| } |
| else if (ret.status() == ParseResult::INCOMPLETE) |
| { |
| emit cellFailedToParse(cell, ret, parser); |
| goto endOfCell; // JANK! |
| } |
| else if ((ret = parser.parseMany(&ast)) && !ast.empty()) |
| { |
| for (const AstNode &node : ast) |
| { |
| RuntimeResult nodeRes = _eval.evaluate(node, _ctx); |
| result += nodeRes; |
| |
| if (!nodeRes.success()) |
| { |
| goto endOfParseLoop; |
| } |
| } |
| } |
| else if (ret.status() == ParseResult::INCOMPLETE) |
| { |
| emit cellFailedToParse(cell, ret, parser); |
| break; |
| } |
| else |
| { |
| parser.skip(); |
| |
| if (!parser.atEnd()) |
| { |
| emit cellFailedToParse(cell, ParseResult(ParseResult::NO_MATCH, "Garbage at end of input", parser.save()), parser); |
| goto endOfCell; |
| } |
| |
| break; |
| } |
| } |
| |
| endOfParseLoop: |
| emit cellFinishedRunning(cell, result); |
| |
| endOfCell: |
| _running = nullptr; |
| } |
| catch (EvalQuitException &ex) |
| { |
| _running = nullptr; |
| emit cellQuit(cell); |
| } |
| catch (StackOverflowException &ex) |
| { |
| _running = nullptr; |
| emit cellFinishedRunning(cell, RuntimeResult(ex)); |
| } |
| catch (AssertionException &ex) |
| { |
| _running = nullptr; |
| emit cellFinishedRunning(cell, RuntimeResult(ex)); |
| } |
| } |
| } |