HAL
python_context.h
Go to the documentation of this file.
1 // MIT License
2 //
3 // Copyright (c) 2019 Ruhr University Bochum, Chair for Embedded Security. All Rights reserved.
4 // Copyright (c) 2019 Marc Fyrbiak, Sebastian Wallat, Max Hoffmann ("ORIGINAL AUTHORS"). All rights reserved.
5 // Copyright (c) 2021 Max Planck Institute for Security and Privacy. All Rights reserved.
6 // Copyright (c) 2021 Jörn Langheinrich, Julian Speith, Nils Albartus, René Walendy, Simon Klix ("ORIGINAL AUTHORS"). All Rights reserved.
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in all
16 // copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 // SOFTWARE.
25 
26 #pragma once
27 
32 
33 #include <QString>
34 #include <QObject>
35 
36 #pragma GCC diagnostic push
37 #pragma GCC diagnostic ignored "-Wshadow"
38 #include "pybind11/embed.h"
39 #include "pybind11/eval.h"
40 #include "pybind11/functional.h"
41 #include "pybind11/operators.h"
42 #include "pybind11/stl.h"
43 #include "pybind11/stl_bind.h"
44 #pragma GCC diagnostic pop
45 
46 namespace hal
47 {
48  class PythonContextSubscriber;
49  class PythonEditor;
50  class PythonThread;
51  class LayoutLocker;
52 
54  {
55  Q_OBJECT
56  PythonThread* mThread;
57  public Q_SLOTS:
58  void handleGatesPicked(const QSet<u32>& gats) override;
59  public:
61  : GateSelectReceiver(parent), mThread(thread) {;}
62  };
63 
65  {
66  Q_OBJECT
67  PythonThread* mThread;
68  public Q_SLOTS:
69  void handleModulesPicked(const QSet<u32>& gats) override;
70  public:
72  : ModuleSelectReceiver(parent), mThread(thread) {;}
73  };
74 
75  namespace py = pybind11;
83  class __attribute__((visibility("default"))) PythonContext : public QObject
84  {
85  Q_OBJECT
86  public:
90  PythonContext(QObject* parent=nullptr);
91 
95  ~PythonContext();
96 
102  void interpretForeground(const QString& input);
103 
112  void interpretBackground(QObject* caller, const QString& input, bool multiple_expressions = false);
113 
120  void interpretScript(QObject* caller, const QString& input);
121 
127  void forwardStdout(const QString& output);
128 
134  void forwardError(const QString& output);
135 
140  void scheduleClear();
141 
145  void scheduleReset();
146 
152  void setConsole(PythonConsole* console);
153 
164  std::vector<std::tuple<std::string, std::string>> complete(const QString& text, bool use_console_context);
165 
171  int checkCompleteStatement(const QString& text);
172 
173  // void set_history_length();
174 
175  // void read_history_file(const QString& file);
176  // void write_history_file(const QString& file);
180  void initPython();
181 
185  void closePython();
186 
190  void updateNetlist();
191 
192  PythonThread* pythonThread() const;
193 
194  static void initializeContext(py::dict* context);
195  static void initializeScript(py::dict* context);
196 
197  void abortThread();
198  void abortThreadAndWait();
199  bool isThreadRunning() const { return mThread != nullptr; }
200 
201  private Q_SLOTS:
202  void handleThreadFinished();
203  void handleScriptOutput(const QString& txt);
204  void handleScriptError(const QString& txt);
205  void handleInputRequired(int type, const QString& prompt, const QVariant& defaultValue);
206  void handleConsoleInputReceived(const QString& input);
207 
208  private:
209 
210  void handleReset();
211  void handleClear();
212 
213  // these have to be pointers, otherwise they are destructed after py::finalize_interpreter and segfault
214  // only one object for global and local is needed, as for the console we run it always in global scope wher globals() == locals()
215  py::dict* mContext;
216 
217  PythonContextSubscriber* mSender;
218 
219  std::string mHistoryFile;
220 
221  PythonConsole* mConsole;
222  bool mTriggerReset;
223  bool mTriggerClear;
224  LayoutLocker* mLayoutLocker;
225  PythonThread* mThread;
226  bool mThreadAborted;
227  PyThreadState* mMainThreadState;
228  QObject* mInterpreterCaller;
229 
230  void startThread(const QString& input, bool singleStatement);
231  };
232 } // namespace hal
PythonGateSelectionReceiver(PythonThread *thread, QObject *parent=nullptr)
void handleGatesPicked(const QSet< u32 > &gats) override
PythonModuleSelectionReceiver(PythonThread *thread, QObject *parent=nullptr)
void handleModulesPicked(const QSet< u32 > &gats) override
PinType type
Q_OBJECTQ_OBJECT
Q_SLOTSQ_SLOTS
QObject * parent() const const
QThread * thread() const const