blob: a2111a7412e533d2e33bbf23948b51482f7e8136 [file] [log] [blame]
swissChilid85daa92022-02-24 15:29:02 -08001#include <QCoreApplication>
2
3#include "NbRuntime.h"
4#include "../Parser.h"
swissChili5d3e5562022-02-24 16:49:19 -08005#include "../StdLib.h"
swissChilid85daa92022-02-24 15:29:02 -08006
7NbRuntime::NbRuntime(QObject *parent)
swissChili732628e2022-02-25 10:35:56 -08008 : QObject(parent)
swissChilid85daa92022-02-24 15:29:02 -08009{
swissChili5d3e5562022-02-24 16:49:19 -080010 StdLib().load(_eval);
swissChilid85daa92022-02-24 15:29:02 -080011}
12
13void NbRuntime::queueCell(Cell *cell)
14{
15 if (!_cells.contains(cell))
16 {
17 qInfo() << "Queueing cell";
18
19 _cells.append(cell);
20
21 emit cellWaiting(cell);
22
23 if (!_running)
24 evalRemaining();
25 }
26}
27
28void NbRuntime::unqueueCell(Cell *cell)
29{
30 if (cell == _running)
31 {
32 // Exception should propagate back up to evalRemaining()
33 _eval.quit();
34 }
35 else
36 {
37 _cells.removeOne(cell);
38 }
39}
40
41void NbRuntime::evalRemaining()
42{
43 qInfo() << "evalRemaining";
44
45 while (!_cells.empty())
46 {
47 QCoreApplication::processEvents();
48
49 Cell *cell = _cells.first();
50 _cells.removeFirst();
51
52 _running = cell;
53
54 Parser parser(cell->code());
55 RuntimeResult result;
56
57 emit cellRunning(cell);
58
59 try
60 {
61 // Allow this cell to be quit
62 QCoreApplication::processEvents();
63
64 while (true)
65 {
66 ParseResult ret;
67 Function func;
swissChili732628e2022-02-25 10:35:56 -080068 QList<AstNode> ast;
swissChilid85daa92022-02-24 15:29:02 -080069
70 if ((ret = parser.parseFunctionDefinition(&func)))
71 {
72 _eval.addFunction(func);
73 }
74 else if (ret.status() == ParseResult::INCOMPLETE)
75 {
swissChiliece1ac82022-02-25 11:20:42 -080076 emit cellFailedToParse(cell, ret, parser);
swissChilid85daa92022-02-24 15:29:02 -080077 goto endOfCell; // JANK!
78 }
swissChili732628e2022-02-25 10:35:56 -080079 else if ((ret = parser.parseMany(&ast)) && !ast.empty())
swissChilid85daa92022-02-24 15:29:02 -080080 {
swissChili732628e2022-02-25 10:35:56 -080081 for (const AstNode &node : ast)
swissChilid85daa92022-02-24 15:29:02 -080082 {
swissChili732628e2022-02-25 10:35:56 -080083 RuntimeResult nodeRes = _eval.evaluate(node, _ctx);
84 result += nodeRes;
85
86 if (!nodeRes.success())
87 {
88 goto endOfParseLoop;
89 }
swissChilid85daa92022-02-24 15:29:02 -080090 }
91 }
92 else if (ret.status() == ParseResult::INCOMPLETE)
93 {
swissChiliece1ac82022-02-25 11:20:42 -080094 emit cellFailedToParse(cell, ret, parser);
swissChilid85daa92022-02-24 15:29:02 -080095 break;
96 }
97 else
98 {
99 parser.skip();
100
101 if (!parser.atEnd())
102 {
swissChiliece1ac82022-02-25 11:20:42 -0800103 emit cellFailedToParse(cell, ParseResult(ParseResult::NO_MATCH, "Garbage at end of input", parser.save()), parser);
swissChilid85daa92022-02-24 15:29:02 -0800104 goto endOfCell;
105 }
106
107 break;
108 }
109 }
110
swissChili732628e2022-02-25 10:35:56 -0800111 endOfParseLoop:
swissChilid85daa92022-02-24 15:29:02 -0800112 emit cellFinishedRunning(cell, result);
113
114 endOfCell:
115 _running = nullptr;
116 }
117 catch (EvalQuitException &ex)
118 {
119 _running = nullptr;
120 emit cellQuit(cell);
121 }
122 catch (StackOverflowException &ex)
123 {
124 _running = nullptr;
125 emit cellFinishedRunning(cell, RuntimeResult(ex));
126 }
swissChili5d3e5562022-02-24 16:49:19 -0800127 catch (AssertionException &ex)
128 {
129 _running = nullptr;
130 emit cellFinishedRunning(cell, RuntimeResult(ex));
131 }
swissChilid85daa92022-02-24 15:29:02 -0800132 }
133}