[code] The Python console compiles and executes commands entered.

It stores and displays the result in the console store.
An empty line returned at the end of the execution is deleted.

Change-Id: Ic90e02e2d91d0a0033413da0588032d9450aefd0
This commit is contained in:
Léa Saviot
2017-10-12 14:00:18 +02:00
committed by Romain Goyet
parent 493cef0d4d
commit c57f9cf8b1
18 changed files with 165 additions and 171 deletions

View File

@@ -1,13 +1,61 @@
#include "console_controller.h"
#include <apps/i18n.h>
extern "C" {
#include <stdlib.h>
#include "port.h"
#include "py/mphal.h"
#include "py/compile.h"
#include "py/runtime.h"
#include "py/gc.h"
#include "py/stackctrl.h"
}
namespace Code {
/* mp_hal_stdout_tx_strn_cooked symbol required by micropython at printing
* needs to access information about where to print. This 'context' is provided
* by the global sCurrentConsoleStore that points to the console store. */
static ConsoleStore * sCurrentConsoleStore = nullptr;
extern "C"
void mp_hal_stdout_tx_strn_cooked(const char * str, size_t len) {
assert(sCurrentConsoleStore != nullptr);
sCurrentConsoleStore->pushResult(str, len);
}
mp_obj_t execute_from_str(const char *str) {
nlr_buf_t nlr;
if (nlr_push(&nlr) == 0) {
mp_lexer_t *lex = mp_lexer_new_from_str_len(0, str, strlen(str), false);
mp_parse_tree_t pt = mp_parse(lex, MP_PARSE_SINGLE_INPUT);
mp_obj_t module_fun = mp_compile(&pt, lex->source_name, MP_EMIT_OPT_NONE, true);
mp_hal_set_interrupt_char((int)Ion::Keyboard::Key::A6);
mp_call_function_0(module_fun);
mp_hal_set_interrupt_char(-1); // Disable interrupt
nlr_pop();
return 0;
} else {
// Uncaught exception
return (mp_obj_t) nlr.ret_val;
}
}
ConsoleController::ConsoleController(Responder * parentResponder) :
ViewController(parentResponder),
TextFieldDelegate(),
m_rowHeight(KDText::charSize(k_fontSize).height()),
m_tableView(this, this, 0, 0),
m_editCell(this, this)
{
assert(sCurrentConsoleStore == nullptr);
sCurrentConsoleStore = &m_consoleStore;
initPython();
}
ConsoleController::~ConsoleController() {
stopPython();
}
void ConsoleController::viewWillAppear() {
@@ -23,7 +71,7 @@ int ConsoleController::numberOfRows() {
}
KDCoordinate ConsoleController::rowHeight(int j) {
return k_rowHeight;
return m_rowHeight;
}
KDCoordinate ConsoleController::cumulatedHeightFromIndex(int j) {
@@ -82,9 +130,11 @@ bool ConsoleController::textFieldDidReceiveEvent(TextField * textField, Ion::Eve
bool ConsoleController::textFieldDidFinishEditing(TextField * textField, const char * text, Ion::Events::Event event) {
m_consoleStore.pushCommand(text, strlen(text));
executePython(text);
textField->setText("");
m_tableView.reloadData();
m_tableView.scrollToCell(0, m_consoleStore.numberOfLines());
m_editCell.setEditing(true);
return true;
}
@@ -92,4 +142,26 @@ Toolbox * ConsoleController::toolboxForTextField(TextField * textFied) {
return nullptr;
}
void ConsoleController::initPython() {
mp_stack_set_limit(40000);
mp_port_init_stack_top();
m_pythonHeap = (char *)malloc(16384);
gc_init(m_pythonHeap, m_pythonHeap + 16384);
mp_init();
}
void ConsoleController::executePython(const char * str) {
if (execute_from_str(str)) {
mp_hal_stdout_tx_strn_cooked(I18n::translate(I18n::Message::ConsoleError), 5);
}
m_consoleStore.deleteLastLineIfEmpty();
}
void ConsoleController::stopPython() {
free(m_pythonHeap);
sCurrentConsoleStore = nullptr;
}
}