#pragma once #include #include #include "machine.h" class Eval_python { public: static std::regex statement_delimiter; explicit Eval_python(Machine& machine, const Locator& loc); Eval_python(const Eval_python&) = delete; Eval_python& operator=(const Eval_python&) = delete; ~Eval_python(); void add_module_path(const std::string& path); std::vector parse_modules(std::string code); void import_module(const std::string& module_name, bool verify = true); std::string get_result(PyObject* result_object); // The Python exception currently raised (there must be one): clear it, // return the formatted traceback, and keep the exception object in the // slot below. ktext puts the text into the Error it throws; the Python // binding (kpy/) additionally chains the object as the Error's __cause__, // so a script sees the ZeroDivisionError its @eval raised, with its // traceback, and not only a description of it. std::string fetch_python_exception(); // Take ownership of the exception kept by the last fetch (nullptr if // none); the slot is cleared. ktext never calls this: it terminates on // the Error, and the interpreter is torn down with the process. static PyObject* take_last_exception(); std::string eval_expression(const std::string& expression, bool import_modules = true); std::string eval_statements(const std::string& script); std::string eval(std::string code); //std::string eval_katom_list(const katom_iter& begin, const katom_iter& end); std::string eval_katom_list( std::vector& katoms, const std::vector::iterator& begin, const std::vector::iterator& end); Machine m_machine; Locator m_loc; PyObject* m_globals; PyObject* m_locals; static PyObject* s_last_exception; };