diff --git a/apps/code/console_controller.cpp b/apps/code/console_controller.cpp index 16a5e4400..2169cb0ba 100644 --- a/apps/code/console_controller.cpp +++ b/apps/code/console_controller.cpp @@ -52,7 +52,7 @@ bool ConsoleController::loadPythonEnvironment() { m_pythonDelegate->initPythonWithUser(this); MicroPython::registerScriptProvider(m_scriptStore); m_importScriptsWhenViewAppears = m_autoImportScripts; - m_scriptStore->clearFetchInformation(); + m_scriptStore->clearConsoleFetchInformation(); } return true; } diff --git a/apps/code/script.cpp b/apps/code/script.cpp index bee1db59f..4b39b3452 100644 --- a/apps/code/script.cpp +++ b/apps/code/script.cpp @@ -65,16 +65,18 @@ bool Script::nameCompliant(const char * name) { return false; } +uint8_t * StatusFromData(Script::Data d) { + return const_cast(static_cast(d.buffer)); +} + bool Script::autoImportationStatus() const { - assert(!isNull()); - Data d = value(); - return (*statusFromData(d) & k_autoImportationStatusMask) == 1; + return getStatutBit(k_autoImportationStatusMask); } void Script::toggleAutoimportationStatus() { assert(!isNull()); Data d = value(); - *statusFromData(d) ^= k_autoImportationStatusMask; + *StatusFromData(d) ^= k_autoImportationStatusMask; setValue(d); } @@ -83,46 +85,34 @@ const char * Script::content() const { return ((const char *)d.buffer) + StatusSize(); } -bool Script::contentFetchedFromConsole() const { - return fetchedStatus() == FetchedStatus::FromConsole; +bool Script::fetchedFromConsole() const { + return getStatutBit(k_fetchedFromConsoleMask); } -bool Script::contentFetchedForVariableBox() const { - return fetchedStatus() == FetchedStatus::ForVariableBox; +void Script::setFetchedFromConsole(bool fetched) { + setStatutBit(k_fetchedFromConsoleMask, k_fetchedFromConsoleOffset, fetched); } -void Script::setContentFetchedFromConsole() { - setFetchedStatus(FetchedStatus::FromConsole); +bool Script::fetchedForVariableBox() const { + return getStatutBit(k_fetchedForVariableBoxMask); } -void Script::setContentFetchedForVariableBox() { - setFetchedStatus(FetchedStatus::ForVariableBox); +void Script::setFetchedForVariableBox(bool fetched) { + setStatutBit(k_fetchedForVariableBoxMask, k_fetchedForVariableBoxOffset, fetched); } -void Script::resetContentFetchedStatus() { - setFetchedStatus(FetchedStatus::None); -} - -Script::FetchedStatus Script::fetchedStatus() const { +bool Script::getStatutBit(uint8_t mask) const { assert(!isNull()); Data d = value(); - uint8_t status = (*statusFromData(d)) >> k_fetchedStatusOffset; - assert(status == static_cast(FetchedStatus::None) - || status == static_cast(FetchedStatus::FromConsole) - || status == static_cast(FetchedStatus::ForVariableBox)); - return static_cast(status); + return ((*StatusFromData(d)) & mask) != 0; } -void Script::setFetchedStatus(FetchedStatus fetchedStatus) { +void Script::setStatutBit(uint8_t mask, uint8_t offset, bool statusBit) { assert(!isNull()); Data d = value(); - uint8_t * status = statusFromData(d); - *status = ((*status) & ~k_fetchedStatusMask) | (static_cast(fetchedStatus) << k_fetchedStatusOffset); //TODO Create and use a bit operations library + uint8_t * status = StatusFromData(d); + *status = ((*status) & ~mask) | (static_cast(statusBit) << offset); //TODO Create and use a bit operations library setValue(d); } -uint8_t * Script::statusFromData(Data d) const { - return const_cast(static_cast(d.buffer)); -} - } diff --git a/apps/code/script.h b/apps/code/script.h index fbbb66267..9d2df78c6 100644 --- a/apps/code/script.h +++ b/apps/code/script.h @@ -8,22 +8,22 @@ namespace Code { /* Record: | Size | Name | Body | * Script: | | | Status | Content | * - * Status is a byte long: xxxxxxxx - * ^^ ^ - * FetchedStatus AutoImportationStatus * - * AutoImportationStatus is 1 if the script should be auto imported when the + * |FetchedForVariableBoxBit + * Status is one byte long: xxxxxxxx + * ^ ^ + * FetchedFromConsoleBit AutoImportationBit + * + * AutoImportationBit is 1 if the script should be auto imported when the * console opens. * - * FetchedStatus has two purposes: - * - It is used to detect which scripts are imported in the console, so we can - * retrieve the correct variables afterwards in the variable box. When a - * script has been imported, its fetchedStatus value is - * FetchedStatus::FromConsole. - * - It is used to prevent circular importation problems, such as scriptA - * importing scriptB, which imports scriptA. Once we get the variables from a - * script to put them in the variable box, we switch the status to - * FetchedStatus::ForVariableBox and won't reload it afterwards. */ + * FetchedFromConsoleBit is 1 if its content has been fetched from the console, + * so we can retrieve the correct variables afterwards in the variable box. + * + * FetchedForVariableBoxBit is used to prevent circular importation problems, + * such as scriptA importing scriptB, which imports scriptA. Once we get the + * variables from a script to put them in the variable box, we switch the bit to + * 1 and won't reload it afterwards. */ class Script : public Ion::Storage::Record { private: @@ -49,25 +49,22 @@ public: bool autoImportationStatus() const; void toggleAutoimportationStatus(); const char * content() const; - bool contentFetchedFromConsole() const; - bool contentFetchedForVariableBox() const; - void setContentFetchedFromConsole(); - void setContentFetchedForVariableBox(); - void resetContentFetchedStatus(); + + /* Fetched status */ + bool fetchedFromConsole() const; + void setFetchedFromConsole(bool fetched); + bool fetchedForVariableBox() const; + void setFetchedForVariableBox(bool fetched); + private: static constexpr uint8_t k_autoImportationStatusMask = 0b1; - static constexpr uint8_t k_fetchedStatusBits = 0b11; - static constexpr uint8_t k_fetchedStatusOffset = 6; - static constexpr uint8_t k_fetchedStatusMask = k_fetchedStatusBits << k_fetchedStatusOffset; - /* Fetched status */ - enum class FetchedStatus : uint8_t { - None = 0, - FromConsole = 1, - ForVariableBox = 2 - }; - FetchedStatus fetchedStatus() const; - void setFetchedStatus(FetchedStatus status); - uint8_t * statusFromData(Data d) const; + static constexpr uint8_t k_fetchedForVariableBoxOffset = 7; + static constexpr uint8_t k_fetchedFromConsoleOffset = 6; + static constexpr uint8_t k_fetchedForVariableBoxMask = 0b1 << k_fetchedForVariableBoxOffset; + static constexpr uint8_t k_fetchedFromConsoleMask = 0b1 << k_fetchedFromConsoleOffset; + + bool getStatutBit(uint8_t offset) const; + void setStatutBit(uint8_t mask, uint8_t offset, bool value); }; } diff --git a/apps/code/script_store.cpp b/apps/code/script_store.cpp index 3062eb01c..ebc358827 100644 --- a/apps/code/script_store.cpp +++ b/apps/code/script_store.cpp @@ -31,16 +31,24 @@ const char * ScriptStore::contentOfScript(const char * name, bool markAsFetched) return nullptr; } if (markAsFetched) { - script.setContentFetchedFromConsole(); + script.setFetchedFromConsole(true); } return script.content(); } -void ScriptStore::clearFetchInformation() { +void ScriptStore::clearVariableBoxFetchInformation() { // TODO optimize fetches const int scriptsCount = numberOfScripts(); for (int i = 0; i < scriptsCount; i++) { - scriptAtIndex(i).resetContentFetchedStatus(); + scriptAtIndex(i).setFetchedForVariableBox(false); + } +} + +void ScriptStore::clearConsoleFetchInformation() { + // TODO optimize fetches + const int scriptsCount = numberOfScripts(); + for (int i = 0; i < scriptsCount; i++) { + scriptAtIndex(i).setFetchedFromConsole(false); } } diff --git a/apps/code/script_store.h b/apps/code/script_store.h index 3b3cf9a9c..ad9b59ff7 100644 --- a/apps/code/script_store.h +++ b/apps/code/script_store.h @@ -40,7 +40,8 @@ public: /* MicroPython::ScriptProvider */ const char * contentOfScript(const char * name, bool markAsFetched) override; - void clearFetchInformation() override; + void clearVariableBoxFetchInformation(); + void clearConsoleFetchInformation(); Ion::Storage::Record::ErrorStatus addScriptFromTemplate(const ScriptTemplate * scriptTemplate); private: diff --git a/apps/code/variable_box_controller.cpp b/apps/code/variable_box_controller.cpp index d884abe32..57fa989e6 100644 --- a/apps/code/variable_box_controller.cpp +++ b/apps/code/variable_box_controller.cpp @@ -158,7 +158,7 @@ void VariableBoxController::loadFunctionsAndVariables(int scriptIndex, const cha // Reset the node counts empty(); - m_scriptStore->clearFetchInformation(); + if (textToAutocomplete != nullptr && textToAutocompleteLength < 0) { textToAutocompleteLength = strlen(textToAutocomplete); } @@ -180,8 +180,8 @@ void VariableBoxController::loadFunctionsAndVariables(int scriptIndex, const cha /* Handle the FetchedStatus: we will import the current script variables in * loadCurrentVariablesInScript, so we do not want to import those variables * before, if any imported script also imported the current script. */ - assert(!script.contentFetchedFromConsole() && !script.contentFetchedForVariableBox()); - script.setContentFetchedForVariableBox(); + assert(!script.fetchedFromConsole() && !script.fetchedForVariableBox()); + script.setFetchedForVariableBox(true); // Load the imported and current variables const char * scriptContent = script.content(); @@ -229,7 +229,7 @@ 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()) { + if (script.fetchedFromConsole()) { loadGlobalAndImportedVariablesInScriptAsImported(script, nullptr, -1, false); } } @@ -240,6 +240,7 @@ void VariableBoxController::empty() { m_currentScriptNodesCount = 0; m_importedNodesCount = 0; m_shortenResultCharCount = 0; + m_scriptStore->clearVariableBoxFetchInformation(); } void VariableBoxController::insertAutocompletionResultAtIndex(int index) { @@ -628,7 +629,7 @@ void VariableBoxController::loadCurrentVariablesInScript(const char * scriptCont } void VariableBoxController::loadGlobalAndImportedVariablesInScriptAsImported(Script script, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules) { - if (script.contentFetchedForVariableBox()) { + if (script.fetchedForVariableBox()) { // We already fetched these script variables return; } @@ -674,7 +675,7 @@ void VariableBoxController::loadGlobalAndImportedVariablesInScriptAsImported(Scr nlr_pop(); } // Mark that we already fetched these script variables - script.setContentFetchedForVariableBox(); + script.setFetchedForVariableBox(true); } bool VariableBoxController::addNodesFromImportMaybe(mp_parse_node_struct_t * parseNode, const char * textToAutocomplete, int textToAutocompleteLength, bool importFromModules) { diff --git a/python/port/port.h b/python/port/port.h index 24a7524bd..75a973887 100644 --- a/python/port/port.h +++ b/python/port/port.h @@ -13,7 +13,6 @@ namespace MicroPython { class ScriptProvider { public: virtual const char * contentOfScript(const char * name, bool markAsFetched) = 0; - virtual void clearFetchInformation() = 0; }; class ExecutionEnvironment {