diff --git a/.github/workflows/benchmarks.yml b/.github/workflows/benchmarks.yml index 3a5858ba..44767669 100644 --- a/.github/workflows/benchmarks.yml +++ b/.github/workflows/benchmarks.yml @@ -43,7 +43,7 @@ jobs: with: python-version: '3.11' - - uses: leafo/gh-actions-lua@v10 + - uses: leafo/gh-actions-lua@8aace3457a2fcf3f3c4e9007ecc6b869ff6d74d6 # v11 with: luaVersion: "5.4.1" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c1fa7144..c520923d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -40,7 +40,7 @@ jobs: steps: - uses: actions/checkout@v4 - name: Run clang-format style check for C/C++/Protobuf programs. - uses: jidicula/clang-format-action@v4.11.0 + uses: jidicula/clang-format-action@4726374d1aa3c6aecf132e5197e498979588ebc8 # v4.15.0 with: clang-format-version: '13' check-path: ${{ matrix.path }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 59abf441..bfce32a5 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -15,7 +15,7 @@ jobs: if: ${{ contains(github.event.head_commit.message, '[skip ci]') != true }} - name: Build and push stable Docker image - uses: docker/build-push-action@v1.1.0 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} @@ -28,7 +28,7 @@ jobs: push: ${{ startsWith(github.ref, 'refs/tags/') }} - name: Build and push nightly Docker image - uses: docker/build-push-action@v1.1.0 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} @@ -39,7 +39,7 @@ jobs: tags: latest - name: Build and push harden Docker image - uses: docker/build-push-action@v1.1.0 + uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c0727274..d2c31c69 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -140,10 +140,10 @@ jobs: - name: Extract release notes id: extract-release-notes - uses: ffurrer2/extract-release-notes@v1 + uses: ffurrer2/extract-release-notes@cae32133495112d23e3569ad04fef240ba4e7bc8 # v2.3.0 - name: Create release - uses: softprops/action-gh-release@v2 + uses: softprops/action-gh-release@da05d552573ad5aba039eaac05058a918a7bf631 # v2.2.2 id: create_release env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -154,17 +154,6 @@ jobs: prerelease: false body: ${{ steps.extract-release-notes.outputs.release_notes }} - - uses: sarisia/actions-status-discord@v1 - with: - webhook: ${{ secrets.DISCORD_WEBHOOK }} - title: "A new release (${{ env.RELEASE_VERSION }}) has been drafted" - description: | - Please review it **before publishing it**, as this action would trigger workflows and GitHub webhooks, - notifying everyone of a new release! You want to be sure **everything** is correct - [Release draft URL](${{ steps.create_release.outputs.url }}) - nodetail: true - username: GitHub Actions - - name: Upload artifact uses: actions/upload-release-asset@v1 env: diff --git a/.github/workflows/setup-compilers/action.yaml b/.github/workflows/setup-compilers/action.yaml index 78e2f910..0c7adeb2 100644 --- a/.github/workflows/setup-compilers/action.yaml +++ b/.github/workflows/setup-compilers/action.yaml @@ -62,7 +62,7 @@ runs: brew install llvm@${{ inputs.compiler_version }} - name: Setup Windows environment - uses: ilammy/msvc-dev-cmd@v1 + uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0 if: startsWith(inputs.os_name, 'windows') - name: Install MacOS dependencies diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index f344643a..8b888946 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -47,7 +47,7 @@ jobs: echo "EOF" >> $GITHUB_ENV - name: Find Comment - uses: peter-evans/find-comment@v3 + uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e # v3.1.0 id: fc with: issue-number: ${{ github.event.pull_request.number }} @@ -55,7 +55,7 @@ jobs: body-includes: Static analysis report - name: Create or update comment - uses: peter-evans/create-or-update-comment@v4 + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0 with: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 61104ebe..1f962d57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -129,6 +129,7 @@ - removed `and` and `or` instructions in favor of a better implementation to support short-circuiting - removed `LET` and `MUT` instructions in favor of a single new `STORE` instruction - removed `SAVE_ENV` instruction +- removed `Value VM::resolve(const Value* val, Args&&... args)`, which has been deprecated in ArkScript v3.4.0 ## [3.5.0] - 2023-02-19 ### Added diff --git a/include/Ark/Compiler/Instructions.hpp b/include/Ark/Compiler/Instructions.hpp index d1d4ad72..9ed41589 100644 --- a/include/Ark/Compiler/Instructions.hpp +++ b/include/Ark/Compiler/Instructions.hpp @@ -40,7 +40,7 @@ namespace Ark::internal LOAD_SYMBOL = 0x01, // @args stack index - // @role Load a symbol from the locals stack by its index + // @role Load a symbol from the locals stack by its index (starting from the end of the current scope) LOAD_SYMBOL_BY_INDEX = 0x02, // @args symbol id diff --git a/include/Ark/VM/VM.hpp b/include/Ark/VM/VM.hpp index efb79d4e..df885d82 100644 --- a/include/Ark/VM/VM.hpp +++ b/include/Ark/VM/VM.hpp @@ -82,17 +82,6 @@ namespace Ark // function calling from plugins // ================================================ - /** - * @brief Resolving a function call (called by plugins and builtins) - * - * @tparam Args - * @param val the ArkScript function object - * @param args C++ argument list - * @return Value - */ - template - [[deprecated("Use resolve(ExecutionContext*, vector&) instead")]] Value resolve(const Value* val, Args&&... args); - /** * @brief Resolves a function call (called by plugins and builtins) * @@ -100,7 +89,7 @@ namespace Ark * @param n the function and its arguments * @return Value */ - inline Value resolve(internal::ExecutionContext* context, std::vector& n); + inline Value resolve(internal::ExecutionContext* context, const std::vector& n); /** * @brief Ask the VM to exit with a given exit code @@ -109,6 +98,15 @@ namespace Ark */ void exit(int code) noexcept; + /** + * @brief Return a pointer to the first execution context, for the main thread of the app + * @return internal::ExecutionContext* + */ + inline internal::ExecutionContext* getDefaultContext() + { + return m_execution_contexts.front().get(); + } + /** * @brief Create an execution context and returns it * @details This method is thread-safe VM wise. @@ -187,10 +185,48 @@ namespace Ark // instruction helpers // ================================================ + /** + * @brief Load a symbol by its id in the current context. Performs a lookup in the scope stack, in reverse order. + * + * @param id symbol id + * @param context + * @return Value* nullptr if the symbol could not be loaded + */ [[nodiscard]] inline Value* loadSymbol(uint16_t id, internal::ExecutionContext& context); + + /** + * @brief Load a symbol by its (reversed) index in the current scope + * + * @param index index of the symbol to load, starting from the end + * @param context + * @return Value* + */ [[nodiscard]] inline Value* loadSymbolFromIndex(uint16_t index, internal::ExecutionContext& context); + + /** + * @brief Load a constant from the constant table by its id + * + * @param id + * @return Value* + */ [[nodiscard]] inline Value* loadConstAsPtr(uint16_t id) const; + + /** + * @brief Create a new symbol with an associated value in the current scope + * + * @param id + * @param val + * @param context + */ inline void store(uint16_t id, const Value* val, internal::ExecutionContext& context); + + /** + * @brief Change the value of a symbol given its identifier + * + * @param id + * @param val + * @param context + */ inline void setVal(uint16_t id, const Value* val, internal::ExecutionContext& context); // ================================================ diff --git a/include/Ark/VM/VM.inl b/include/Ark/VM/VM.inl index 36c326d7..ce5d8a2a 100644 --- a/include/Ark/VM/VM.inl +++ b/include/Ark/VM/VM.inl @@ -47,47 +47,7 @@ Value VM::call(const std::string& name, Args&&... args) return *popAndResolveAsPtr(context); } -template -Value VM::resolve(const Value* val, Args&&... args) -{ - using namespace internal; - - // TODO: deprecate resolve(const Value*, Args&&...) and add a resolve(ExecutionContext*, const Value*, Args&&...) - ExecutionContext& context = *m_execution_contexts.front().get(); - - if (!val->isFunction()) - throw TypeError("Value::resolve couldn't resolve a non-function"); - - const std::size_t ip = context.ip; - const std::size_t pp = context.pp; - - // convert and push arguments in reverse order - std::vector fnargs { { Value(std::forward(args))... } }; - for (auto it = fnargs.rbegin(), it_end = fnargs.rend(); it != it_end; ++it) - push(*it, context); - // push function - push(*val, context); - - const std::size_t frames_count = context.fc; - // call it - call(context, static_cast(sizeof...(Args))); - // reset instruction pointer, otherwise the safeRun method will start at ip = -1 - // without doing context.ip++ as intended (done right after the call() in the loop, but here - // we start outside this loop) - context.ip = 0; - - // run until the function returns - safeRun(context, /* untilFrameCount */ frames_count); - - // restore VM state - context.ip = ip; - context.pp = pp; - - // get result - return *popAndResolveAsPtr(context); -} - -inline Value VM::resolve(internal::ExecutionContext* context, std::vector& n) +inline Value VM::resolve(internal::ExecutionContext* context, const std::vector& n) { if (!n[0].isFunction()) throw TypeError(fmt::format("VM::resolve couldn't resolve a non-function ({})", types_to_str[static_cast(n[0].valueType())])); @@ -138,6 +98,9 @@ inline Value* VM::loadSymbol(const uint16_t id, internal::ExecutionContext& cont inline Value* VM::loadSymbolFromIndex(const uint16_t index, internal::ExecutionContext& context) { + // we need to load symbols from the end, because function calls add a reference to the current function + // upon calling it. Which changes the index by 1, making it less clear, because it needs special + // treatment only for function calls. auto& [id, value] = context.locals.back().atPosReverse(index); context.last_symbol = id; return &value; diff --git a/lib/modules b/lib/modules index ab5b3b35..b8e1058b 160000 --- a/lib/modules +++ b/lib/modules @@ -1 +1 @@ -Subproject commit ab5b3b3592153a301f463c41f7334eae8c16d8e8 +Subproject commit b8e1058b424d078aa2e173443f406fdca81070d8