diff --git a/apps/code/app.cpp b/apps/code/app.cpp index 4c017e220..3a54ba988 100644 --- a/apps/code/app.cpp +++ b/apps/code/app.cpp @@ -61,7 +61,7 @@ void App::Snapshot::setOpt(const char * name, const char * value) { const char * scriptContent = separator; Code::ScriptTemplate script(scriptName, scriptContent); m_scriptStore.addScriptFromTemplate(&script); - ScriptStore::ScriptNamed(scriptName).toggleImportationStatus(); // set Importation Status to 1 + ScriptStore::ScriptNamed(scriptName).toggleAutoimportationStatus(); // set Importation Status to 1 return; } if (strcmp(name, "lock-on-console") == 0) { diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index b60f069e8..36456a896 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -54,10 +54,13 @@ bool ConsoleController::loadPythonEnvironment() { m_pythonDelegate->initPythonWithUser(this); MicroPython::registerScriptProvider(m_scriptStore); m_importScriptsWhenViewAppears = m_autoImportScripts; +#if 0 + //TODO LEA /* We load functions and variables names in the variable box before running * any other python code to avoid failling to load functions and variables * due to memory exhaustion. */ App::app()->variableBoxController()->loadFunctionsAndVariables(-1, nullptr, -1); +#endif return true; } @@ -65,6 +68,7 @@ void ConsoleController::unloadPythonEnvironment() { if (!m_pythonDelegate->isPythonUser(nullptr)) { m_consoleStore.startNewSession(); m_pythonDelegate->deinitPython(); + m_scriptStore->clearFetchInformation(); } } @@ -474,7 +478,7 @@ void ConsoleController::autoImportScript(Script script, bool force) { * the sandbox. */ hideAnyDisplayedViewController(); - if (script.importationStatus() || force) { + if (script.autoImportationStatus() || force) { // Step 1 - Create the command "from scriptName import *". assert(strlen(k_importCommand1) + strlen(script.fullName()) - strlen(ScriptStore::k_scriptExtension) - 1 + strlen(k_importCommand2) + 1 <= k_maxImportCommandSize); diff --git a/apps/code/editor_controller.cpp b/apps/code/editor_controller.cpp index 49a9fee8b..2a10bbc50 100644 --- a/apps/code/editor_controller.cpp +++ b/apps/code/editor_controller.cpp @@ -37,7 +37,7 @@ void EditorController::setScript(Script script, int scriptIndex) { * */ size_t newScriptSize = Ion::Storage::sharedStorage()->putAvailableSpaceAtEndOfRecord(m_script); - m_editorView.setText(const_cast(m_script.scriptContent()), newScriptSize - Script::k_importationStatusSize); + m_editorView.setText(const_cast(m_script.scriptContent()), newScriptSize - Script::InformationSize()); } void EditorController::willExitApp() { @@ -154,7 +154,7 @@ void EditorController::cleanStorageEmptySpace() { Ion::Storage::Record::Data scriptValue = m_script.value(); Ion::Storage::sharedStorage()->getAvailableSpaceFromEndOfRecord( m_script, - scriptValue.size - Script::k_importationStatusSize - (strlen(m_script.scriptContent()) + 1)); // TODO optimize number of script fetches + scriptValue.size - Script::InformationSize() - (strlen(m_script.scriptContent()) + 1)); // TODO optimize number of script fetches } diff --git a/apps/code/script.cpp b/apps/code/script.cpp index fb38ad234..15a9419f5 100644 --- a/apps/code/script.cpp +++ b/apps/code/script.cpp @@ -65,31 +65,35 @@ bool Script::nameCompliant(const char * name) { return false; } -bool Script::importationStatus() const { +bool Script::autoImportationStatus() const { assert(!isNull()); Data d = value(); return (((char *)d.buffer)[0] == 1); } -void Script::toggleImportationStatus() { +void Script::toggleAutoimportationStatus() { + assert(!isNull()); Data d = value(); ((char *)d.buffer)[0] = (((char *)d.buffer)[0] == 1 ? 0 : 1); setValue(d); } const char * Script::scriptContent() const { - assert(!isNull()); Data d = value(); - return (const char *)d.buffer + k_autoimportationStatusSize + k_currentImportationStatusSize; + return ((const char *)d.buffer) + InformationSize(); } bool Script::contentFetchedFromConsole() const { - + assert(!isNull()); + Data d = value(); + return (((char *)d.buffer)[k_autoImportationStatusSize] == 1); } -void Script::setContentFetchedFromConsole(bool fetch) const { - -} -//TODO TODO LEA +void Script::setContentFetchedFromConsole(bool fetch) { + assert(!isNull()); + Data d = value(); + ((char *)d.buffer)[k_autoImportationStatusSize] = fetch; + setValue(d); +} } diff --git a/apps/code/script.h b/apps/code/script.h index 040f45a7d..36dbe9ea6 100644 --- a/apps/code/script.h +++ b/apps/code/script.h @@ -9,9 +9,14 @@ namespace Code { * Script: | AutoImportationStatus | Content |*/ class Script : public Ion::Storage::Record { -public: - static constexpr size_t k_autoimportationStatusSize = 1; +private: + // Default script names are chosen between script1 and script99 + static constexpr int k_maxNumberOfDefaultScriptNames = 99; + static constexpr int k_defaultScriptNameNumberMaxSize = 2; // Numbers from 1 to 99 have 2 digits max + + static constexpr size_t k_autoImportationStatusSize = 1; //TODO LEA use only 1 byte for both status flags static constexpr size_t k_currentImportationStatusSize = 1; +public: static constexpr int k_defaultScriptNameMaxSize = 6 + k_defaultScriptNameNumberMaxSize + 1; /* 6 = strlen("script") * k_defaultScriptNameNumberMaxSize = maxLength of integers between 1 and 99 @@ -19,18 +24,14 @@ public: static bool DefaultName(char buffer[], size_t bufferSize); static bool nameCompliant(const char * name); + static constexpr size_t InformationSize() { return k_autoImportationStatusSize + k_currentImportationStatusSize; } Script(Ion::Storage::Record r = Ion::Storage::Record()) : Record(r) {} - bool importationStatus() const; - void toggleImportationStatus(); + bool autoImportationStatus() const; + void toggleAutoimportationStatus(); const char * scriptContent() const; bool contentFetchedFromConsole() const; - void setContentFetchedFromConsole(bool fetch) const; -private: - // Default script names are chosen between script1 and script99 - static constexpr int k_maxNumberOfDefaultScriptNames = 99; - static constexpr int k_defaultScriptNameNumberMaxSize = 2; // Numbers from 1 to 99 have 2 digits max - + void setContentFetchedFromConsole(bool fetch); }; } diff --git a/apps/code/script_parameter_controller.cpp b/apps/code/script_parameter_controller.cpp index ab31e778d..5332fddc3 100644 --- a/apps/code/script_parameter_controller.cpp +++ b/apps/code/script_parameter_controller.cpp @@ -42,7 +42,7 @@ bool ScriptParameterController::handleEvent(Ion::Events::Event event) { m_menuController->renameSelectedScript(); return true; case 2: - m_script.toggleImportationStatus(); + m_script.toggleAutoimportationStatus(); m_selectableTableView.reloadData(); m_menuController->reloadConsole(); Container::activeApp()->setFirstResponder(&m_selectableTableView); @@ -81,7 +81,7 @@ HighlightCell * ScriptParameterController::reusableCell(int index) { void ScriptParameterController::willDisplayCellForIndex(HighlightCell * cell, int index) { if (cell == &m_autoImportScript) { SwitchView * switchView = (SwitchView *)m_autoImportScript.accessoryView(); - switchView->setState(m_script.importationStatus()); + switchView->setState(m_script.autoImportationStatus()); } } diff --git a/apps/code/script_store.cpp b/apps/code/script_store.cpp index c4062a9b6..37fd45cbf 100644 --- a/apps/code/script_store.cpp +++ b/apps/code/script_store.cpp @@ -25,16 +25,27 @@ bool ScriptStore::isFull() { return Ion::Storage::sharedStorage()->availableSize() < k_fullFreeSpaceSizeLimit; } -const char * ScriptStore::contentOfScript(const char * name) { +const char * ScriptStore::contentOfScript(const char * name, bool markAsFetched) { Script script = ScriptNamed(name); if (script.isNull()) { return nullptr; } + if (markAsFetched) { + script.setContentFetchedFromConsole(true); + } return script.scriptContent(); } +void ScriptStore::clearFetchInformation() { + // TODO optimize fetches + const int scriptsCount = numberOfScripts(); + for (int i = 0; i < scriptsCount; i++) { + scriptAtIndex(i).setContentFetchedFromConsole(false); + } +} + Script::ErrorStatus ScriptStore::addScriptFromTemplate(const ScriptTemplate * scriptTemplate) { - size_t valueSize = strlen(scriptTemplate->content())+1+1;// scriptcontent size + 1 char for the importation status + size_t valueSize = Script::InformationSize() + strlen(scriptTemplate->content()) + 1; // (auto importation status + content fetched status) + scriptcontent size + null-terminating char assert(Script::nameCompliant(scriptTemplate->name())); Script::ErrorStatus err = Ion::Storage::sharedStorage()->createRecordWithFullName(scriptTemplate->name(), scriptTemplate->value(), valueSize); assert(err != Script::ErrorStatus::NonCompliantName); diff --git a/apps/code/script_store.h b/apps/code/script_store.h index ae5f7dbf6..3b3cf9a9c 100644 --- a/apps/code/script_store.h +++ b/apps/code/script_store.h @@ -39,7 +39,8 @@ public: bool isFull(); /* MicroPython::ScriptProvider */ - const char * contentOfScript(const char * name) override; + const char * contentOfScript(const char * name, bool markAsFetched) override; + void clearFetchInformation() override; Ion::Storage::Record::ErrorStatus addScriptFromTemplate(const ScriptTemplate * scriptTemplate); private: diff --git a/apps/code/script_template.cpp b/apps/code/script_template.cpp index 488cd362a..df6350040 100644 --- a/apps/code/script_template.cpp +++ b/apps/code/script_template.cpp @@ -2,15 +2,15 @@ namespace Code { -constexpr ScriptTemplate emptyScriptTemplate(".py", "\x01" R"(from math import * +constexpr ScriptTemplate emptyScriptTemplate(".py", "\x01\x00" R"(from math import * )"); -constexpr ScriptTemplate squaresScriptTemplate("squares.py", "\x01" R"( +constexpr ScriptTemplate squaresScriptTemplate("squares.py", "\x01\x00" R"( #from math import sin as stew, cos as cabbage from math import * )"); -/*constexpr ScriptTemplate squaresScriptTemplate("squares.py", "\x01" R"( +/*constexpr ScriptTemplate squaresScriptTemplate("squares.py", "\x01\x00" R"( import math import math as m import math, cmath @@ -31,7 +31,7 @@ from math import sin as stew from math import sin, cos from math import sin as stew, cos as cabbage */ -constexpr ScriptTemplate mandelbrotScriptTemplate("mandelbrot.py", "\x01" R"(# This script draws a Mandelbrot fractal set +constexpr ScriptTemplate mandelbrotScriptTemplate("mandelbrot.py", "\x01\x00" R"(# This script draws a Mandelbrot fractal set # N_iteration: degree of precision import kandinsky def mandelbrot(N_iteration): @@ -51,7 +51,7 @@ def mandelbrot(N_iteration): # Draw a pixel colored in 'col' at position (x,y) kandinsky.set_pixel(x,y,col))"); -constexpr ScriptTemplate polynomialScriptTemplate("polynomial.py", "\x01" R"(from math import * +constexpr ScriptTemplate polynomialScriptTemplate("polynomial.py", "\x01\x00" R"(from math import * # roots(a,b,c) computes the solutions of the equation a*x**2+b*x+c=0 def roots(a,b,c): delta = b*b-4*a*c @@ -64,7 +64,7 @@ def roots(a,b,c): else: return None)"); -constexpr ScriptTemplate parabolaScriptTemplate("parabola.py", "\x01" R"(from matplotlib.pyplot import * +constexpr ScriptTemplate parabolaScriptTemplate("parabola.py", "\x01\x00" R"(from matplotlib.pyplot import * from math import * g=9.81 diff --git a/apps/code/script_template.h b/apps/code/script_template.h index d0d048ab1..02a53f87d 100644 --- a/apps/code/script_template.h +++ b/apps/code/script_template.h @@ -1,6 +1,8 @@ #ifndef CODE_SCRIPT_TEMPLATE_H #define CODE_SCRIPT_TEMPLATE_H +#include "script.h" + namespace Code { class ScriptTemplate { @@ -12,11 +14,11 @@ public: static const ScriptTemplate * Polynomial(); static const ScriptTemplate * Parabola(); const char * name() const { return m_name; } - const char * content() const { return m_value+1; } + const char * content() const { return m_value + Script::InformationSize(); } const char * value() const { return m_value; } private: const char * m_name; - const char * m_value; // hold the 'importation status' flag concatenate with the script content + const char * m_value; // holds the 'importation status' and 'current importation status' flags concatenated with the script content }; } diff --git a/apps/code/variable_box_controller.cpp b/apps/code/variable_box_controller.cpp index 835b9c7e3..87240f40f 100644 --- a/apps/code/variable_box_controller.cpp +++ b/apps/code/variable_box_controller.cpp @@ -385,9 +385,9 @@ void VariableBoxController::insertTextInCaller(const char * text, int textLength void VariableBoxController::loadVariablesImportedFromScripts() { const int scriptsCount = m_scriptStore->numberOfScripts(); for (int i = 0; i < scriptsCount; i++) { - Script * script = m_scriptStore->scriptAtIndex(i); - if (script->contentFetchedFromConsole()) { - loadGlobalAndImportedVariablesInScriptAsImported(script->fullName(), script->scriptContent(), nullptr, -1, false); + Script script = m_scriptStore->scriptAtIndex(i); + if (script.contentFetchedFromConsole()) { + loadGlobalAndImportedVariablesInScriptAsImported(script.fullName(), script.scriptContent(), nullptr, -1, false); // TODO optimize number of script fetches } } } diff --git a/python/port/port.cpp b/python/port/port.cpp index bac7595ca..6ae0c36c9 100644 --- a/python/port/port.cpp +++ b/python/port/port.cpp @@ -288,7 +288,7 @@ void nlr_jump_fail(void *val) { mp_lexer_t * mp_lexer_new_from_file(const char * filename) { if (sScriptProvider != nullptr) { - const char * script = sScriptProvider->contentOfScript(filename); + const char * script = sScriptProvider->contentOfScript(filename, true); if (script != nullptr) { return mp_lexer_new_from_str_len(qstr_from_str(filename), script, strlen(script), 0 /* size_t free_len*/); } else { @@ -300,7 +300,7 @@ mp_lexer_t * mp_lexer_new_from_file(const char * filename) { } mp_import_stat_t mp_import_stat(const char *path) { - if (sScriptProvider && sScriptProvider->contentOfScript(path)) { + if (sScriptProvider && sScriptProvider->contentOfScript(path, false)) { return MP_IMPORT_STAT_FILE; } return MP_IMPORT_STAT_NO_EXIST; diff --git a/python/port/port.h b/python/port/port.h index 3ab3a603f..3cef6ec0a 100644 --- a/python/port/port.h +++ b/python/port/port.h @@ -12,7 +12,8 @@ namespace MicroPython { class ScriptProvider { public: - virtual const char * contentOfScript(const char * name) = 0; + virtual const char * contentOfScript(const char * name, bool markAsFetched) = 0; + virtual void clearFetchInformation() = 0; }; class ExecutionEnvironment {