blob: debda5bea3fd3ea1cdaaeeadb605b1fb7800d29a [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
swissChilia44bf722022-04-16 18:41:54 -070013void NbRuntime::reset()
14{
15 _eval.reset();
16 _ctx = {};
17}
18
swissChilid85daa92022-02-24 15:29:02 -080019void NbRuntime::queueCell(Cell *cell)
20{
21 if (!_cells.contains(cell))
22 {
23 qInfo() << "Queueing cell";
24
25 _cells.append(cell);
26
27 emit cellWaiting(cell);
28
29 if (!_running)
30 evalRemaining();
31 }
32}
33
34void NbRuntime::unqueueCell(Cell *cell)
35{
36 if (cell == _running)
37 {
38 // Exception should propagate back up to evalRemaining()
39 _eval.quit();
40 }
41 else
42 {
43 _cells.removeOne(cell);
44 }
45}
46
47void NbRuntime::evalRemaining()
48{
49 qInfo() << "evalRemaining";
50
51 while (!_cells.empty())
52 {
53 QCoreApplication::processEvents();
54
55 Cell *cell = _cells.first();
56 _cells.removeFirst();
57
58 _running = cell;
59
60 Parser parser(cell->code());
61 RuntimeResult result;
62
63 emit cellRunning(cell);
64
65 try
66 {
67 // Allow this cell to be quit
68 QCoreApplication::processEvents();
69
70 while (true)
71 {
72 ParseResult ret;
73 Function func;
swissChili732628e2022-02-25 10:35:56 -080074 QList<AstNode> ast;
swissChilid85daa92022-02-24 15:29:02 -080075
76 if ((ret = parser.parseFunctionDefinition(&func)))
77 {
78 _eval.addFunction(func);
79 }
80 else if (ret.status() == ParseResult::INCOMPLETE)
81 {
swissChiliece1ac82022-02-25 11:20:42 -080082 emit cellFailedToParse(cell, ret, parser);
swissChilid85daa92022-02-24 15:29:02 -080083 goto endOfCell; // JANK!
84 }
swissChili732628e2022-02-25 10:35:56 -080085 else if ((ret = parser.parseMany(&ast)) && !ast.empty())
swissChilid85daa92022-02-24 15:29:02 -080086 {
swissChili732628e2022-02-25 10:35:56 -080087 for (const AstNode &node : ast)
swissChilid85daa92022-02-24 15:29:02 -080088 {
swissChili732628e2022-02-25 10:35:56 -080089 RuntimeResult nodeRes = _eval.evaluate(node, _ctx);
90 result += nodeRes;
91
92 if (!nodeRes.success())
93 {
94 goto endOfParseLoop;
95 }
swissChilid85daa92022-02-24 15:29:02 -080096 }
97 }
98 else if (ret.status() == ParseResult::INCOMPLETE)
99 {
swissChiliece1ac82022-02-25 11:20:42 -0800100 emit cellFailedToParse(cell, ret, parser);
swissChilid85daa92022-02-24 15:29:02 -0800101 break;
102 }
103 else
104 {
105 parser.skip();
106
107 if (!parser.atEnd())
108 {
swissChiliece1ac82022-02-25 11:20:42 -0800109 emit cellFailedToParse(cell, ParseResult(ParseResult::NO_MATCH, "Garbage at end of input", parser.save()), parser);
swissChilid85daa92022-02-24 15:29:02 -0800110 goto endOfCell;
111 }
112
113 break;
114 }
115 }
116
swissChili732628e2022-02-25 10:35:56 -0800117 endOfParseLoop:
swissChilid85daa92022-02-24 15:29:02 -0800118 emit cellFinishedRunning(cell, result);
119
120 endOfCell:
121 _running = nullptr;
122 }
123 catch (EvalQuitException &ex)
124 {
125 _running = nullptr;
126 emit cellQuit(cell);
127 }
128 catch (StackOverflowException &ex)
129 {
130 _running = nullptr;
131 emit cellFinishedRunning(cell, RuntimeResult(ex));
132 }
swissChili5d3e5562022-02-24 16:49:19 -0800133 catch (AssertionException &ex)
134 {
135 _running = nullptr;
136 emit cellFinishedRunning(cell, RuntimeResult(ex));
137 }
swissChilid85daa92022-02-24 15:29:02 -0800138 }
139}