diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index aa777be8..00000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,34 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve.
-title: ''
-labels: ["bug", "process/needs triage"]
-assignees: ''
-
----
-
-**Describe the bug**
-Describe the issue you are experiencing here.
-Tell us what you were trying to do and what happened.
-
-**Expected behavior**
-Describe clearly and concisely what you expected to happen.
-
-**Actual behavior**
-Describe clearly and concisely what actually happened.
-
-**To Reproduce**
-Link to a small reproducer or attach an archive containing the reproducer to the issue.
-Alternatively, provide clear and concise steps to reproduce the behavior.
-
-## Environment
-
-**Timefold Solver Version or Git ref**:
-
-**Python version used:**
-
-**Output of `uname -a` or `ver`:**
-
-## Additional information
-
-Provide any and all other information which might be relevant to the issue.
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
deleted file mode 100644
index ffed6958..00000000
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ /dev/null
@@ -1,8 +0,0 @@
-blank_issues_enabled: true
-contact_links:
- - name: Question
- url: https://stackoverflow.com/questions/ask?tags=timefold
- about: Ask a question about how to use Timefold Solver.
- - name: Discussions
- url: https://github.com/TimefoldAI/timefold-solver/discussions/new?category=general
- about: Open Community discussions related to Timefold Solver.
\ No newline at end of file
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index faa1a6da..00000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,20 +0,0 @@
----
-name: Feature request
-about: Suggest an idea for this project.
-title: 'Feat: '
-labels: ["enhancement", "process/needs triage"]
-assignees: ''
-
----
-
-**Is your feature request related to a problem? Please describe.**
-A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
-
-**Describe the solution you'd like**
-A clear and concise description of what you want to happen.
-
-**Describe alternatives you've considered**
-A clear and concise description of any alternative solutions or features you've considered.
-
-**Additional context**
-Add any other context or screenshots about the feature request here.
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index a13bd381..00000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,27 +0,0 @@
-version: 2
-updates:
-- package-ecosystem: maven
- directory: "/"
- schedule:
- interval: weekly
- time: '05:00'
- open-pull-requests-limit: 10
- target-branch: "main"
- commit-message:
- prefix: "deps: "
-
-- package-ecosystem: pip
- directory: "/"
- schedule:
- interval: weekly
- time: '05:00'
- open-pull-requests-limit: 10
- target-branch: "main"
- commit-message:
- prefix: "deps: "
-
-- package-ecosystem: "github-actions"
- directory: "/"
- schedule:
- interval: weekly
- time: '05:00' # Otherwise it picks a random time.
diff --git a/.github/scripts/change_versions.sh b/.github/scripts/change_versions.sh
deleted file mode 100755
index 1bd274c6..00000000
--- a/.github/scripts/change_versions.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-# Expects the following environment variables to be set:
-# $NEW_VERSION (Example: "1.2.0")
-# $NEW_VERSION_PYTHON (Example: "1.2.0a0")
-
-# This will fail the Maven build if the version is not available.
-# Thankfully, this is not the case (yet) in this project.
-# If/when it happens, this needs to be replaced by a manually provided version,
-# as scanning the text of the POM would be unreliable.
-echo " New version: $NEW_VERSION"
-echo " New Python Version: $NEW_VERSION_PYTHON"
-mvn clean install -Dquickly
-mvn versions:update-parent "-DparentVersion=$NEW_VERSION" -DskipResolution=true -DallowSnapshots=true -DgenerateBackupPoms=false
-mvn versions:update-child-modules -DallowSnapshots=true -DgenerateBackupPoms=false
-sed -i "s/^timefold_solver_python_version.*=.*/timefold_solver_python_version = '$NEW_VERSION_PYTHON'/" setup.py
-git commit -am "build: switch to version $NEW_VERSION_PYTHON"
\ No newline at end of file
diff --git a/.github/workflows/downstream_python_enterprise.yml b/.github/workflows/downstream_python_enterprise.yml
deleted file mode 100644
index 417bd544..00000000
--- a/.github/workflows/downstream_python_enterprise.yml
+++ /dev/null
@@ -1,161 +0,0 @@
-# Tests PRs on multiple operating systems and Python/Java versions
-name: Downstream - Timefold Solver Enterprise for Python
-
-on:
- # Enables the workflow to run on PRs from forks;
- # token sharing is safe here, because enterprise is a private repo and therefore fully under our control.
- pull_request_target:
- branches: [ main, '*.x' ]
- types:
- - opened
- - reopened
- - synchronize
- paths-ignore:
- - 'LICENSE*'
- - '.gitignore'
- - '**.md'
- - '**.adoc'
- - '*.txt'
-
-defaults:
- run:
- shell: bash
-
-jobs:
- build:
- concurrency:
- group: downstream-enterprise-python-${{ github.event_name }}-${{ github.head_ref }}
- cancel-in-progress: true
- timeout-minutes: 120
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out repository code
- uses: actions/checkout@v4
- with:
- path: './timefold-solver-python'
-
- # Need to check for stale repo, since Github is not aware of the build chain and therefore doesn't automate it.
- - name: Checkout timefold-solver (PR) # Checkout the PR branch first, if it exists
- id: checkout-solver
- uses: actions/checkout@v4
- continue-on-error: true
- with:
- repository: ${{ github.actor }}/timefold-solver
- ref: ${{ github.head_ref }}
- path: ./timefold-solver
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Checkout timefold-solver (main) # Checkout the main branch if the PR branch does not exist
- if: steps.checkout-solver.outcome != 'success'
- uses: actions/checkout@v4
- with:
- repository: TimefoldAI/timefold-solver
- ref: main
- path: ./timefold-solver
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Prevent stale fork of timefold-solver
- env:
- BLESSED_REPO: "timefold-solver"
- BLESSED_BRANCH: ${{ endsWith(github.head_ref, '.x') && github.head_ref || 'main' }}
- shell: bash
- working-directory: ./timefold-solver
- run: .github/scripts/prevent_stale_fork.sh
-
- # Clone timefold-solver-enterprise
- # Need to check for stale repo, since Github is not aware of the build chain and therefore doesn't automate it.
- - name: Checkout timefold-solver-enterprise (PR) # Checkout the PR branch first, if it exists
- id: checkout-solver-enterprise
- uses: actions/checkout@v4
- continue-on-error: true
- with:
- repository: TimefoldAI/timefold-solver-enterprise
- ref: ${{ github.head_ref }}
- token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork.
- path: ./timefold-solver-enterprise
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Checkout timefold-solver-enterprise (main) # Checkout the main branch if the PR branch does not exist
- if: steps.checkout-solver-enterprise.outcome != 'success'
- uses: actions/checkout@v4
- with:
- repository: TimefoldAI/timefold-solver-enterprise
- ref: main
- token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork.
- path: ./timefold-solver-enterprise
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Prevent stale fork of timefold-solver-enterprise
- env:
- BLESSED_REPO: "timefold-solver-enterprise"
- BLESSED_BRANCH: ${{ endsWith(github.head_ref, '.x') && github.head_ref || 'main' }}
- shell: bash
- working-directory: ./timefold-solver-enterprise
- run: ../timefold-solver/.github/scripts/prevent_stale_fork.sh
-
- # Clone timefold-solver-python-enterprise
- # Need to check for stale repo, since Github is not aware of the build chain and therefore doesn't automate it.
- - name: Checkout timefold-solver-enterprise-python (PR) # Checkout the PR branch first, if it exists
- id: checkout-solver-enterprise-python
- uses: actions/checkout@v4
- continue-on-error: true
- with:
- repository: TimefoldAI/timefold-solver-enterprise-python
- ref: ${{ github.head_ref }}
- token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork.
- path: ./timefold-solver-enterprise-python
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Checkout timefold-solver-python-enterprise-python (main) # Checkout the main branch if the PR branch does not exist
- if: steps.checkout-solver-enterprise-python.outcome != 'success'
- uses: actions/checkout@v4
- with:
- repository: TimefoldAI/timefold-solver-enterprise-python
- ref: main
- token: ${{ secrets.JRELEASER_GITHUB_TOKEN }} # Safe; only used to clone the repo and not stored in the fork.
- path: ./timefold-solver-enterprise-python
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Prevent stale fork of timefold-solver-enterprise-python
- env:
- BLESSED_REPO: "timefold-solver-enterprise-python"
- BLESSED_BRANCH: ${{ endsWith(github.head_ref, '.x') && github.head_ref || 'main' }}
- shell: bash
- working-directory: ./timefold-solver-enterprise-python
- run: ../timefold-solver/.github/scripts/prevent_stale_fork.sh
-
- # Build and test
- - name: Set up JDK 17
- uses: actions/setup-java@v4
- with:
- java-version: 17
- distribution: 'temurin'
- cache: 'maven'
- # Need to install all Python versions in the same run for tox
- - name: Python 3.10, Python 3.11, Python 3.12 Setup
- uses: actions/setup-python@v5
- with:
- python-version: |
- 3.10
- 3.11
- 3.12
- cache: 'pip'
- cache-dependency-path: |
- **/setup.py
- - name: Install tox
- run:
- python -m pip install --upgrade pip
- pip install tox build
- - name: Quickly build timefold-solver
- working-directory: ./timefold-solver
- run: mvn -B -Dquickly clean install
- - name: Quickly Build timefold-solver-enterprise
- working-directory: ./timefold-solver-enterprise
- shell: bash
- run: mvn -B -Dquickly clean install
- - name: Build with Maven to install parent poms for python build
- working-directory: ./timefold-solver-python
- run: mvn -B --fail-at-end clean install
- - name: Build timefold solver python
- working-directory: ./timefold-solver-python
- run: python -m build
- - name: Run tox on timefold solver enterprise python test suite
- working-directory: ./timefold-solver-enterprise-python
- env:
- PIP_FIND_LINKS: ${{ github.workspace }}/timefold-solver-python/dist
- run: tox
diff --git a/.github/workflows/downstream_python_quickstarts.yml b/.github/workflows/downstream_python_quickstarts.yml
deleted file mode 100644
index af22fe6f..00000000
--- a/.github/workflows/downstream_python_quickstarts.yml
+++ /dev/null
@@ -1,121 +0,0 @@
-# Tests PRs on multiple operating systems and Python/Java versions
-name: Downstream - Timefold Solver for Python Quickstarts
-
-on:
- pull_request:
- types: [opened, synchronize, reopened, labeled]
- branches:
- - main
- paths-ignore:
- - 'LICENSE*'
- - '.gitignore'
- - '**.md'
- - '**.adoc'
- - '*.txt'
- - '.ci/**'
-
-defaults:
- run:
- shell: bash
-
-jobs:
- test-build:
- concurrency:
- group: pull_request_python_quickstarts-${{ github.event_name }}-${{ github.head_ref }}-${{ matrix.os }}-${{ matrix.java-version }}-${{ matrix.python-version }}
- cancel-in-progress: true
- strategy:
- matrix:
- os: [ ubuntu-latest ]
- java-version: [ 17 ] # Only the first supported LTS; already too many jobs here.
- # TODO: Add Python 3.10 once employee scheduling and school timetabling support it
- python-version: ['3.11', '3.12']
- fail-fast: false
- runs-on: ${{ matrix.os }}
-
- steps:
- # Need to check for stale repo, since Github is not aware of the build chain and therefore doesn't automate it.
- - name: Checkout timefold-solver (PR) # Checkout the PR branch first, if it exists
- id: checkout-solver
- uses: actions/checkout@v4
- continue-on-error: true
- with:
- repository: ${{ github.actor }}/timefold-solver
- ref: ${{ github.head_ref }}
- path: ./timefold-solver
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Checkout timefold-solver (main) # Checkout the main branch if the PR branch does not exist
- if: steps.checkout-solver.outcome != 'success'
- uses: actions/checkout@v4
- with:
- repository: TimefoldAI/timefold-solver
- ref: main
- path: ./timefold-solver
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Prevent stale fork of timefold-solver
- env:
- BLESSED_REPO: "timefold-solver"
- BLESSED_BRANCH: ${{ endsWith(github.head_ref, '.x') && github.head_ref || 'main' }}
- shell: bash
- working-directory: ./timefold-solver
- run: .github/scripts/prevent_stale_fork.sh
-
- - name: Check out repository code
- uses: actions/checkout@v4
- with:
- path: './timefold-solver-python'
-
- # Need to check for stale repo, since Github is not aware of the build chain and therefore doesn't automate it.
- - name: Checkout timefold-quickstarts (PR) # Checkout the PR branch first, if it exists
- id: checkout-quickstarts
- uses: actions/checkout@v4
- continue-on-error: true
- with:
- repository: ${{ github.actor }}/timefold-quickstarts
- ref: ${{ github.head_ref }}
- path: ./timefold-quickstarts
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Checkout timefold-quickstarts (development) # Checkout the development branch if the PR branch does not exist
- if: steps.checkout-solver-quickstarts.outcome != 'success'
- uses: actions/checkout@v4
- with:
- repository: TimefoldAI/timefold-quickstarts
- ref: development
- path: ./timefold-quickstarts
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Prevent stale fork of timefold-quickstarts
- env:
- BLESSED_REPO: "timefold-quickstarts"
- BLESSED_BRANCH: ${{ endsWith(github.head_ref, '.x') && github.head_ref || 'development' }}
- shell: bash
- working-directory: ./timefold-quickstarts
- run: ../timefold-solver/.github/scripts/prevent_stale_fork.sh
-
- # Build and test
- - name: "Setup Java and Maven"
- uses: actions/setup-java@v4
- with:
- java-version: ${{matrix.java-version}}
- distribution: 'temurin'
- cache: 'maven'
- - name: Python Setup
- uses: actions/setup-python@v5
- with:
- python-version: ${{matrix.python-version}}
- cache: 'pip'
- cache-dependency-path: |
- **/setup.py
- - name: Install build
- run:
- python -m pip install --upgrade pip
- pip install build
- - name: Quickly build timefold-solver
- working-directory: ./timefold-solver
- run: mvn -B -Dquickly -DskipTests clean install
- - name: Build timefold-solver-python
- working-directory: ./timefold-solver-python
- run: python -m build
- - name: Build and test timefold-quickstarts
- working-directory: ./timefold-quickstarts
- env:
- TIMEFOLD_SOLVER_PYTHON_DIST: "${{ github.workspace }}/timefold-solver-python/dist"
- run: .github/scripts/run_python_tests.sh
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
deleted file mode 100644
index dfebc757..00000000
--- a/.github/workflows/pull_request.yml
+++ /dev/null
@@ -1,95 +0,0 @@
-# Tests PRs on multiple operating systems and Python/Java versions
-name: Test Build
-
-on:
- pull_request:
- types: [opened, synchronize, reopened, labeled]
- branches:
- - main
- paths-ignore:
- - 'LICENSE*'
- - '.gitignore'
- - '**.md'
- - '**.adoc'
- - '*.txt'
- - '.ci/**'
-
-defaults:
- run:
- shell: bash
-
-jobs:
- test-build:
- strategy:
- matrix:
- os: [ ubuntu-latest ]
- java-version: [ 17, 21, 22 ]
- fail-fast: false
- runs-on: ${{ matrix.os }}
-
- steps:
- # Need to check for stale repo, since Github is not aware of the build chain and therefore doesn't automate it.
- - name: Checkout timefold-solver (PR) # Checkout the PR branch first, if it exists
- id: checkout-solver
- uses: actions/checkout@v4
- continue-on-error: true
- with:
- repository: ${{ github.actor }}/timefold-solver
- ref: ${{ github.head_ref }}
- path: ./timefold-solver
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Checkout timefold-solver (main) # Checkout the main branch if the PR branch does not exist
- if: steps.checkout-solver.outcome != 'success'
- uses: actions/checkout@v4
- with:
- repository: TimefoldAI/timefold-solver
- ref: main
- path: ./timefold-solver
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Prevent stale fork of timefold-solver
- env:
- BLESSED_REPO: "timefold-solver"
- BLESSED_BRANCH: ${{ endsWith(github.head_ref, '.x') && github.head_ref || 'main' }}
- shell: bash
- working-directory: ./timefold-solver
- run: .github/scripts/prevent_stale_fork.sh
-
- - name: Check out repository code
- uses: actions/checkout@v4
- with:
- path: './timefold-solver-python'
-
- # Build and test
- - name: Set up JDK 17
- uses: actions/setup-java@v4
- with:
- java-version: ${{ matrix.java-version }}
- distribution: 'temurin'
- cache: 'maven'
- # Need to install all Python versions in the same run for tox
- - name: Python 3.10, Python 3.11, Python 3.12 Setup
- uses: actions/setup-python@v5
- with:
- python-version: |
- 3.10
- 3.11
- 3.12
- cache: 'pip'
- cache-dependency-path: |
- **/setup.py
- - name: Install tox
- run:
- python -m pip install --upgrade pip
- pip install tox pytest
- - name: Quickly build timefold-solver
- working-directory: ./timefold-solver
- run: mvn -B -Dquickly clean install
- - name: Build with Maven to install parent poms for python build
- working-directory: ./timefold-solver-python
- run: mvn -B --fail-at-end clean install
- - name: Run tox on timefold solver python test suite
- working-directory: ./timefold-solver-python
- run: python -m tox
- - name: Run tox on jpyinterpreter test suite
- working-directory: ./timefold-solver-python/jpyinterpreter
- run: python -m tox
diff --git a/.github/workflows/release-changelog-template.md b/.github/workflows/release-changelog-template.md
deleted file mode 100644
index 9ab8260c..00000000
--- a/.github/workflows/release-changelog-template.md
+++ /dev/null
@@ -1,28 +0,0 @@
-**!!! REMOVE THIS !!!**
-
-**!!! SUMMARIZE THE RELEASE HERE !!!**
-
-**!!! REMOVE THIS !!!**
-
-# Changelog
-
-{{changelogChanges}}
-{{changelogContributors}}
-
-_Timefold Solver Community Edition_ is an open source project, and you are more than welcome to contribute as well!
-For more, see [Contributing](https://github.com/TimefoldAI/timefold-solver/blob/main/CONTRIBUTING.adoc).
-
-Should your business need to scale to truly massive data sets or require enterprise-grade support,
-check out [_Timefold Solver Enterprise Edition_](https://timefold.ai/pricing).
-
-# How to use Timefold Solver in Python
-
-To see Timefold Solver in action, check out [the quickstarts](https://github.com/TimefoldAI/timefold-quickstarts).
-
-Add `timefold=={{projectVersion}}` to your `requirements.txt` or `pip install timefold=={{projectVersion}}` file to get started.
-
-# Additional notes
-
-The changelog and the list of contributors above are automatically generated.
-It excludes contributions to certain areas of the repository, such as CI and build automation.
-This is done for the sake of brevity and to make the user-facing changes stand out more.
diff --git a/.github/workflows/release-pr-body.md b/.github/workflows/release-pr-body.md
deleted file mode 100644
index fa0844c1..00000000
--- a/.github/workflows/release-pr-body.md
+++ /dev/null
@@ -1,13 +0,0 @@
-At this point, the release of _Timefold Solver Community Edition_ for Python is ready to be published.
-Artifacts have been uploaded to PyPI.
-Release branch has been created.
-
-To finish the release of _Timefold Solver Community Edition_ for Python,
-please follow the steps below in the given order:
-
-1. [ ] [Undraft the release](https://github.com/TimefoldAI/timefold-solver-python/releases) on Github.
-2. [ ] Merge this PR.
-3. [ ] Delete the branch that this PR is based on. (Typically a button appears on this page once the PR is merged.)
-
-Note: If this is a dry run,
-none of the above applies and this PR should not be merged.
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 7e9b700b..00000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,143 +0,0 @@
-name: Release
-on:
- workflow_dispatch:
- inputs:
- version:
- description: 'Community Edition version (e.g. 1.0.0)'
- required: true
- pythonVersionSuffix:
- description: 'What suffix to append to the Python version (ex: b0 for beta release)'
- required: true
- default: b0
- sourceBranch:
- description: 'Branch to cut the release from'
- default: main
- required: true
- releaseBranch:
- description: 'Release branch to create (e.g. 1.0.x for version 1.0.0; once created, branch protection rules apply)'
- default: dry_run
- required: true
- dryRun:
- description: 'Do a dry run? (true or false)'
- default: true
- required: true
-jobs:
- build:
- env:
- MAVEN_ARGS: "--no-transfer-progress --batch-mode"
- runs-on: ubuntu-latest
- environment:
- name: pypi
- url: https://pypi.org/p/timefold
- permissions:
- contents: write # IMPORTANT: required for action to create release branch
- pull-requests: write # IMPORTANT: so release PR can be created
- id-token: write # IMPORTANT: mandatory for trusted publishing
- steps:
- - name: Print inputs to the release workflow
- run: echo "${{ toJSON(github.event.inputs) }}"
- - name: Checkout the relevant timefold-solver tag
- uses: actions/checkout@v4
- with:
- repository: "TimefoldAI/timefold-solver"
- path: "./timefold-solver"
- fetch-depth: 0
- ref: v${{ github.event.inputs.version }}
-
- - uses: actions/setup-java@v4
- with:
- java-version: '17'
- distribution: 'temurin'
- cache: 'maven'
-
- - name: Set up Maven
- uses: stCarolas/setup-maven@v5
- with:
- maven-version: 3.9.3
-
- - name: Python 3.12 Setup
- uses: actions/setup-python@v5
- with:
- python-version: 3.12
-
- - name: Install Pip and build
- run:
- python -m pip install --upgrade pip
- pip install build
-
- # Needed so mvn versions:set in the Python repo can update
- # the version in its pom.xml
- - name: Build the upstream release tag as 999-SNAPSHOT
- working-directory: "./timefold-solver"
- run: |
- mvn versions:set -DnewVersion=999-SNAPSHOT
- mvn -Dquickly install
- cd ..
- rm -rf timefold-solver
-
- - name: Checkout timefold-solver-python
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
- ref: ${{ github.event.inputs.sourceBranch }}
-
- - name: Create release branch and switch to it
- run: |
- git config user.name "Timefold Release Bot"
- git config user.email "release@timefold.ai"
- git checkout -b ${{ github.event.inputs.releaseBranch }}
-
- # We skip tests in dry run, to make the process faster.
- # Technically, this goes against the main reason for doing a dry run; to eliminate potential problems.
- # But unless something catastrophic happened, PR checks on source branch already ensured that all tests pass.
- # We also do not use versions:set, because we'd have to have the SNAPSHOT version built from somewhere,
- # and at this point in the release, there is no upstream branch anywhere that would have this version anymore.
- - name: Set release version and build release
- run: |
- export NEW_VERSION=${{ github.event.inputs.version }}
- export NEW_VERSION_PYTHON=${{ github.event.inputs.version }}${{ github.event.inputs.pythonVersionSuffix }}
- .github/scripts/change_versions.sh
- python -m build
-
- # JReleaser requires the release branch to exist, so we need to push it before releasing.
- # Once this is pushed, branch protection rules apply.
- # So if any of the subsequent steps should fail, the release branch is there to stay; cannot be deleted.
- # To minimize that chance, do a dry run first, with a branch named in a way that the protection rules don't apply.
- - name: Push release branch to Git
- run: |
- git push origin ${{ github.event.inputs.releaseBranch }}
-
- - name: Run JReleaser
- uses: jreleaser/release-action@v2
- env:
- JRELEASER_DRY_RUN: ${{ github.event.inputs.dryRun }}
- JRELEASER_PROJECT_VERSION: ${{ github.event.inputs.version }}-beta
- JRELEASER_GITHUB_TOKEN: ${{ secrets.JRELEASER_GITHUB_TOKEN }}
- JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }}
- JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.JRELEASER_GPG_PUBLIC_KEY }}
- JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }}
-
- - name: JReleaser release output
- uses: actions/upload-artifact@v4
- if: always()
- with:
- name: jreleaser-release
- path: |
- out/jreleaser/trace.log
- out/jreleaser/output.properties
-
- - name: Publish distribution to PyPI
- uses: pypa/gh-action-pypi-publish@release/v1
- if: ${{ github.event.inputs.dryRun == 'false' }}
-
- # Pull Request will be created with the changes and a summary of next steps.
- - name: Put back the 999-SNAPSHOT version on the release branch
- run: |
- git checkout -B ${{ github.event.inputs.releaseBranch }}-put-back-999-snapshot
- export NEW_VERSION="999-SNAPSHOT"
- export NEW_VERSION_PYTHON="999-dev0"
- .github/scripts/change_versions.sh
- git push origin ${{ github.event.inputs.releaseBranch }}-put-back-999-snapshot
- gh pr create --reviewer triceo,Christopher-Chianelli --base ${{ github.event.inputs.releaseBranch }} --head ${{ github.event.inputs.releaseBranch }}-put-back-999-snapshot --title "build: move back to 999-SNAPSHOT" --body-file .github/workflows/release-pr-body.md
- env:
- GITHUB_TOKEN: ${{ secrets.JRELEASER_GITHUB_TOKEN }}
diff --git a/.github/workflows/sonarcloud.yml b/.github/workflows/sonarcloud.yml
deleted file mode 100644
index 827ad885..00000000
--- a/.github/workflows/sonarcloud.yml
+++ /dev/null
@@ -1,114 +0,0 @@
-# Runs the SonarCloud analysis of the Timefold Solver Python main branch after a PR is merged.
-name: SonarCloud Analysis
-
-on:
- push:
- branches:
- - main
- paths-ignore:
- - 'LICENSE*'
- - '.gitignore'
- - '**.md'
- - '**.adoc'
- - '*.txt'
- - '.ci/**'
- pull_request_target: # This workflow will be triggered by the opening, reopening, or updating of a PR, and the first run will not require approval.
- types:
- - opened
- - reopened
- - synchronize
-
-defaults:
- run:
- shell: bash
-
-jobs:
- sonarcloud-analysis:
- runs-on: ubuntu-latest
-
- steps:
- # Need to check for stale repo, since Github is not aware of the build chain and therefore doesn't automate it.
- - name: Checkout timefold-solver (PR) # Checkout the PR branch first, if it exists
- id: checkout-solver
- uses: actions/checkout@v4
- continue-on-error: true
- with:
- repository: ${{ github.actor }}/timefold-solver
- ref: ${{ github.head_ref }}
- path: ./timefold-solver
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Checkout timefold-solver (main) # Checkout the main branch if the PR branch does not exist
- if: steps.checkout-solver.outcome != 'success'
- uses: actions/checkout@v4
- with:
- repository: TimefoldAI/timefold-solver
- ref: main
- path: ./timefold-solver
- fetch-depth: 0 # Otherwise merge will fail on account of not having history.
- - name: Prevent stale fork of timefold-solver
- env:
- BLESSED_REPO: "timefold-solver"
- BLESSED_BRANCH: ${{ endsWith(github.head_ref, '.x') && github.head_ref || 'main' }}
- shell: bash
- working-directory: ./timefold-solver
- run: .github/scripts/prevent_stale_fork.sh
- - uses: actions/checkout@v4
- with:
- fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
- ref: ${{ github.event.pull_request.head.sha }} # The GHA event will pull the main branch by default, and we must specify the PR reference version
- path: './timefold-solver-python'
-
- # Build and test
- - name: Set up JDK 17
- uses: actions/setup-java@v4
- with:
- java-version: 17
- distribution: 'temurin'
- - name: Cache SonarCloud packages
- uses: actions/cache@v4
- with:
- path: ~/.sonar/cache
- key: ${{ runner.os }}-sonar
- restore-keys: ${{ runner.os }}-sonar
- - name: Cache Maven packages
- uses: actions/cache@v4
- with:
- path: ~/.m2
- key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
- restore-keys: ${{ runner.os }}-m2
- # Need to install all Python versions in the same run for tox
- - name: Python 3.10, Python 3.11, Python 3.12 Setup
- uses: actions/setup-python@v5
- with:
- python-version: |
- 3.10
- 3.11
- 3.12
- cache: 'pip'
- cache-dependency-path: |
- **/setup.py
- - name: Install tox
- run:
- python -m pip install --upgrade pip
- pip install tox coverage pytest pytest-cov
- - name: Quickly build timefold-solver
- working-directory: ./timefold-solver
- run: mvn -B -Dquickly clean install
- - name: Build with Maven to measure code coverage
- working-directory: ./timefold-solver-python
- run: mvn -B --fail-at-end clean install -Prun-code-coverage
- - name: Get JaCoCo Agent
- working-directory: ./timefold-solver-python
- run: mvn org.apache.maven.plugins:maven-dependency-plugin:2.8:get -Dartifact=org.jacoco:org.jacoco.agent:0.8.11:jar:runtime -Ddest=target/jacocoagent.jar
- - name: Run tox to measure timefold solver python code coverage from Python tests
- working-directory: ./timefold-solver-python
- run: python -m tox -- --cov=timefold --cov-report=xml:target/coverage.xml --cov-config=tox.ini --cov-branch --cov-append --jacoco-agent=./target/jacocoagent.jar
- - name: Run tox to measure jpyinterpreter code coverage from Python tests
- working-directory: ./timefold-solver-python/jpyinterpreter
- run: python -m tox -- --cov=jpyinterpreter --cov-report=xml:target/coverage.xml --cov-config=tox.ini --cov-branch --cov-append --jacoco-agent=../target/jacocoagent.jar --jacoco-output=../target/jacoco.exec
- - name: Run SonarCloud analysis
- working-directory: ./timefold-solver-python
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
- run: mvn -B -Psonarcloud-analysis validate org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Dsonar.organization=timefold -Dsonar.projectKey=TimefoldAI_timefold-solver-python -Dsonar.host.url=https://sonarcloud.io -Dsonar.pullrequest.key=${{ github.event.pull_request.number }} -Dsonar.pullrequest.branch=${{ github.event.pull_request.head.ref }} -Dsonar.scm.revision=${{ github.event.pull_request.head.sha }}
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
deleted file mode 100644
index d8b2495a..00000000
--- a/.mvn/wrapper/maven-wrapper.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.1/apache-maven-3.9.1-bin.zip
-wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/MANIFEST.in b/MANIFEST.in
deleted file mode 100644
index 9dc78b3f..00000000
--- a/MANIFEST.in
+++ /dev/null
@@ -1,12 +0,0 @@
-graft .mvn
-include mvnw mvnw.cmd pom.xml create-stubs.py
-
-include timefold-solver-python-core/pom.xml
-graft timefold-solver-python-core/src/main/java
-graft timefold-solver-python-core/src/main/resources
-graft timefold-solver-python-core/src/test/java
-
-include jpyinterpreter/pom.xml
-graft jpyinterpreter/src/main/java
-graft jpyinterpreter/src/main/resources
-graft jpyinterpreter/src/test/java
diff --git a/README.adoc b/README.adoc
new file mode 100644
index 00000000..dc9ce5f6
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1,4 @@
+= PROJECT MOVED
+
+This project has been merged into the https://github.com/TimefoldAI/timefold-solver[Timefold Solver repo].
+All future development will be done there.
diff --git a/README.md b/README.md
deleted file mode 100644
index a984b9a6..00000000
--- a/README.md
+++ /dev/null
@@ -1,186 +0,0 @@
-![Timefold Logo](https://raw.githubusercontent.com/TimefoldAI/timefold-solver/main/docs/src/modules/ROOT/images/shared/timefold-logo.png)
-
-# Timefold Solver for Python
-
-[![PyPI](https://img.shields.io/pypi/v/timefold?style=for-the-badge& "PyPI")](https://pypi.org/project/timefold/)
-[![License](https://img.shields.io/github/license/TimefoldAI/timefold-solver-python?style=for-the-badge&logo=apache)](https://www.apache.org/licenses/LICENSE-2.0)
-[![JVM support](https://img.shields.io/badge/Java-17+-brightgreen.svg?style=for-the-badge)](https://sdkman.io)
-[![Python support](https://img.shields.io/badge/Python-3.10+-brightgreen.svg?style=for-the-badge)](https://www.python.org/downloads)
-[![Commit Activity](https://img.shields.io/github/commit-activity/m/TimefoldAI/timefold-solver-python?label=commits&style=for-the-badge)](https://github.com/TimefoldAI/timefold-solver-python/pulse)
-
-[![Stackoverflow](https://img.shields.io/badge/stackoverflow-ask_question-orange.svg?logo=stackoverflow&style=for-the-badge)](https://stackoverflow.com/questions/tagged/timefold)
-[![GitHub Discussions](https://img.shields.io/github/discussions/TimefoldAI/timefold-solver?style=for-the-badge&logo=github)](https://github.com/TimefoldAI/timefold-solver/discussions)
-[![GitHub Issues](https://img.shields.io/github/issues/TimefoldAI/timefold-solver-python?style=for-the-badge&logo=github)](https://github.com/TimefoldAI/timefold-solver-python/issues)
-
-[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=TimefoldAI_timefold-solver-python&metric=reliability_rating)](https://sonarcloud.io/summary/new_code?id=TimefoldAI_timefold-solver-python)
-[![Security Rating](https://sonarcloud.io/api/project_badges/measure?project=TimefoldAI_timefold-solver-python&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=TimefoldAI_timefold-solver-python)
-[![Maintainability Rating](https://sonarcloud.io/api/project_badges/measure?project=TimefoldAI_timefold-solver-python&metric=sqale_rating)](https://sonarcloud.io/summary/new_code?id=TimefoldAI_timefold-solver-python)
-[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=TimefoldAI_timefold-solver-python&metric=coverage)](https://sonarcloud.io/summary/new_code?id=TimefoldAI_timefold-solver-python)
-
-Timefold Solver is *an AI constraint solver for Python* to optimize
-the Vehicle Routing Problem, Employee Rostering, Maintenance Scheduling, Task Assignment, School Timetabling,
-Cloud Optimization, Conference Scheduling, Job Shop Scheduling, Bin Packing and many more planning problems.
-
-Using Timefold Solver in Python is significantly slower than using Timefold Solver in [Java](https://github.com/TimefoldAI/timefold-solver) or Kotlin.
-
-## Get started with Timefold Solver for Python
-
-* [Read a Getting Started guide](https://timefold.ai/docs)
-* [Clone the Quickstarts repository](https://github.com/TimefoldAI/timefold-quickstarts)
-
-## Requirements
-
-- [Install Python 3.10 or later.](https://www.python.org)
-- [Install JDK 17 or later](https://adoptium.net) with the environment variable `JAVA_HOME` configured to the JDK installation directory.
- For example, with [Sdkman](https://sdkman.io/):
- ```shell
- $ sdk install java
- ```
-
-## Build from source
-
-1. [Build the main branch of Timefold Solver for Java from source](https://github.com/TimefoldAI/timefold-solver?tab=readme-ov-file#build-from-source)
-2. Install the repo
- ```shell
- $ pip install git+https://github.com/TimefoldAI/timefold-solver-python.git
- ```
-
-## Source code overview
-
-### Domain
-
-In Timefold Solver, the domain has three parts:
-
-- Problem Facts, which do not change.
-- Planning Entities, which have one or more planning variables.
-- Planning Solution, which define the facts and entities of the problem.
-
-#### Problem Facts
-
-Problem facts can be any Python class, which are used to describe unchanging facts in your problem:
-
-```python
-from dataclasses import dataclass
-from datetime import time
-
-@dataclass
-class Timeslot:
- id: int
- day_of_week: str
- start_time: time
- end_time: time
-```
-
-#### Planning Entities
-
-To declare Planning Entities, use the `@planning_entity` decorator along with annotations:
-
-```python
-from dataclasses import dataclass, field
-from typing import Annotated
-from timefold.solver.domain import planning_entity, PlanningId, PlanningVariable
-
-@planning_entity
-@dataclass
-class Lesson:
- id: Annotated[int, PlanningId]
- subject: str
- teacher: str
- student_group: str
- timeslot: Annotated[Timeslot, PlanningVariable] = field(default=None)
- room: Annotated[Room, PlanningVariable] = field(default=None)
-```
-
-- The `PlanningVariable` annotation is used to mark what fields the solver is allowed to change.
-
-- The `PlanningId` annotation is used to uniquely identify an entity object of a particular class. The same Planning Id can be used on entities of different classes, but the ids of all entities in the same class must be different.
-
-#### Planning Solution
-
-To declare the Planning Solution, use the `@planning_solution` decorator:
-
-```python
-from dataclasses import dataclass, field
-from typing import Annotated
-from timefold.solver.domain import (planning_solution, ProblemFactCollectionProperty, ValueRangeProvider,
- PlanningEntityCollectionProperty, PlanningScore)
-from timefold.solver.score import HardSoftScore
-
-@planning_solution
-@dataclass
-class TimeTable:
- timeslots: Annotated[list[Timeslot], ProblemFactCollectionProperty, ValueRangeProvider]
- rooms: Annotated[list[Room], ProblemFactCollectionProperty, ValueRangeProvider]
- lessons: Annotated[list[Lesson], PlanningEntityCollectionProperty]
- score: Annotated[HardSoftScore, PlanningScore] = field(default=None)
-```
-
-- The `ValueRangeProvider` annotation is used to denote a field that contains possible planning values for a `PlanningVariable`.
-
-- The`ProblemFactCollection` annotation is used to denote a field that contains problem facts. This allows these facts to be queried in your constraints.
-
-- The `PlanningEntityCollection` annotation is used to denote a field that contains planning entities. The planning variables of these entities will be modified during solving.
-
-- The `PlanningScore` annotation is used to denote the field that holds the score of the current solution. The solver will set this field during solving.
-
-### Constraints
-
-You define your constraints by using the ConstraintFactory:
-
-```python
-from domain import Lesson
-from timefold.solver.score import (Joiners, HardSoftScore, ConstraintFactory,
- Constraint, constraint_provider)
-
-@constraint_provider
-def define_constraints(constraint_factory: ConstraintFactory) -> list[Constraint]:
- return [
- # Hard constraints
- room_conflict(constraint_factory),
- # Other constraints here...
- ]
-
-def room_conflict(constraint_factory: ConstraintFactory) -> Constraint:
- # A room can accommodate at most one lesson at the same time.
- return (
- constraint_factory.for_each_unique_pair(Lesson,
- # ... in the same timeslot ...
- Joiners.equal(lambda lesson: lesson.timeslot),
- # ... in the same room ...
- Joiners.equal(lambda lesson: lesson.room))
- .penalize(HardSoftScore.ONE_HARD)
- .as_constraint("Room conflict")
- )
-```
-for more details on Constraint Streams,
-see https://timefold.ai/docs/timefold-solver/latest/constraints-and-score/score-calculation.
-
-### Solve
-
-```python
-from timefold.solver import SolverFactory
-from timefold.solver.config import SolverConfig, TerminationConfig, ScoreDirectorFactoryConfig, Duration
-from constraints import define_constraints
-from domain import TimeTable, Lesson, generate_problem
-
-solver_config = SolverConfig(
- solution_class=TimeTable,
- entity_class_list=[Lesson],
- score_director_factory_config=ScoreDirectorFactoryConfig(
- constraint_provider_function=define_constraints
- ),
- termination_config=TerminationConfig(
- spent_limit=Duration(seconds=30)
- )
-)
-
-solver = SolverFactory.create(solver_config).build_solver()
-solution = solver.solve(generate_problem())
-```
-
-`solution` will be a `TimeTable` instance with planning
-variables set to the final best solution found.
-
-## More information
-
-For a full API spec, visit [the Timefold Documentation](https://timefold.ai/docs/timefold-solver/latest).
diff --git a/create-stubs.py b/create-stubs.py
deleted file mode 100644
index 888d7d22..00000000
--- a/create-stubs.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import pathlib
-import jpype
-import stubgenj
-
-jars = list(map(str, pathlib.Path('target/dependency').glob('**/*.jar')))
-
-jpype.startJVM(classpath=jars, convertStrings=True)
-
-import jpype.imports # noqa
-import ai.timefold.solver.core.api # noqa
-import ai.timefold.solver.core.config # noqa
-import ai.timefold.jpyinterpreter # noqa
-import java.lang # noqa
-import java.time # noqa
-import java.util # noqa
-
-stubgenj.generateJavaStubs([java.lang, java.time, java.util, ai.timefold.solver.core.api,
- ai.timefold.solver.core.config, ai.timefold.jpyinterpreter],
- useStubsSuffix=True)
-
diff --git a/jpyinterpreter/.gitignore b/jpyinterpreter/.gitignore
deleted file mode 100644
index cc3c0ab1..00000000
--- a/jpyinterpreter/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
-/dist
-/*.egg-info
-/target
-/*-stubs
-
-# Eclipse, Netbeans and IntelliJ files
-/.*
-!.gitignore
-!.dockerignore
-!.mvn
-/nbproject
-/*.ipr
-/*.iws
-/*.iml
diff --git a/jpyinterpreter/.mvn/wrapper/maven-wrapper.properties b/jpyinterpreter/.mvn/wrapper/maven-wrapper.properties
deleted file mode 100644
index d8b2495a..00000000
--- a/jpyinterpreter/.mvn/wrapper/maven-wrapper.properties
+++ /dev/null
@@ -1,18 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.1/apache-maven-3.9.1-bin.zip
-wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/jpyinterpreter/MANIFEST.in b/jpyinterpreter/MANIFEST.in
deleted file mode 100644
index 5b1a72ba..00000000
--- a/jpyinterpreter/MANIFEST.in
+++ /dev/null
@@ -1,4 +0,0 @@
-graft .mvn
-graft src/main/java
-graft src/main/resources
-include mvnw mvnw.cmd pom.xml
\ No newline at end of file
diff --git a/jpyinterpreter/README.adoc b/jpyinterpreter/README.adoc
deleted file mode 100644
index 14635231..00000000
--- a/jpyinterpreter/README.adoc
+++ /dev/null
@@ -1,66 +0,0 @@
-= Python to Java Translator
-
-This module contains the code needed to translate Python's
-bytecode into equivalent Java bytecode. This allows Java
-functions to use Python functions without incurring a large
-overhead cost on each function call for changing context from
-Java to Python (and then Python to Java). This is mostly relevant
-for small functions, such as those that simply return an attribute
-or perform a small calculation. For small functions, the
-performance increase is around 600%. As functions get larger,
-the overhead cost matters less, causing CPython to outperform
-the Java version.
-
-== Building
-
-Install the python build module, then run the following command:
-
-```bash
-python -m build
-```
-
-== Running
-
-. Install the built `javapython` package into a virtual
-environment:
-+
-```bash
-python -m venv venv
-. venv/bin/activate
-pip install dist/jpyinterpreter-*-py3-none-any.whl
-```
-
-. Initialize the translator:
-+
-```python
-import jpype.imports
-import jpyinterpreter
-
-jpyinterpreter.init(path=['my-java-jar.jar'])
-```
-+
-This will start the JVM used by the Java translator and load jars
-specified by the `path` parameter.
-
-. Translate a Python function to Java:
-+
-```python
-from java.util.function import Function
-
-def my_function(arg):
- return arg + 1
-
-translated_function = javapython.translate_python_bytecode_to_java_bytecode(my_function, Function)
-```
-+
-The first parameter is the Python function you want to translate,
-the second parameter is the Java class the function implements.
-+
-. Use the translated function like a normal Python function:
-+
-```python
-from org.acme import MyClass # A class defined in a Java jar
-
-translated_function(10) # 11
-MyClass.performALongOperation(translated_function)
-```
\ No newline at end of file
diff --git a/jpyinterpreter/developer-docs/.gitignore b/jpyinterpreter/developer-docs/.gitignore
deleted file mode 100644
index 45f84210..00000000
--- a/jpyinterpreter/developer-docs/.gitignore
+++ /dev/null
@@ -1,16 +0,0 @@
-/node_modules
-/build
-/dist
-/*.egg-info
-/target
-/*-stubs
-
-# Eclipse, Netbeans and IntelliJ files
-/.*
-!.gitignore
-!.dockerignore
-!.mvn
-/nbproject
-/*.ipr
-/*.iws
-/*.iml
diff --git a/jpyinterpreter/developer-docs/src/antora-template.yml b/jpyinterpreter/developer-docs/src/antora-template.yml
deleted file mode 100644
index 92f12126..00000000
--- a/jpyinterpreter/developer-docs/src/antora-template.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is a template for antora.yml, which is created during a release by:
-# 1. running maven that substitutes the properties into this file
-# 2. running update_antora_yml.sh that copies the result of the previous step to src/antora.yml
-#
-# The goal is to have the antora.yml containing correct attributes available in the release branch before
-# the optapy-website is refreshed.
-name: docs
-title: JPyInterpreter Developer Guide ${version.jpyinterpreter}
-version: latest
-asciidoc:
- attributes:
- jpyinterpreter-version: ${version.jpyinterpreter}
- java-version: ${maven.compiler.release}
-nav:
- - modules/ROOT/nav.adoc
\ No newline at end of file
diff --git a/jpyinterpreter/developer-docs/src/antora.yml b/jpyinterpreter/developer-docs/src/antora.yml
deleted file mode 100644
index 008895c1..00000000
--- a/jpyinterpreter/developer-docs/src/antora.yml
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file is a placeholder that is replaced by antora-template.yml during a release.
-# Please note that some AsciiDoc attributes might be missing if you build the docs from this branch.
-name: docs
-title: JPyInterpreter Developer Guide
-version: latest
-nav:
- - modules/ROOT/nav.adoc
\ No newline at end of file
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/images/jpyinterpreter-architecture/jpyinterpreter-architecture.png b/jpyinterpreter/developer-docs/src/modules/ROOT/images/jpyinterpreter-architecture/jpyinterpreter-architecture.png
deleted file mode 100644
index 71b234d5..00000000
Binary files a/jpyinterpreter/developer-docs/src/modules/ROOT/images/jpyinterpreter-architecture/jpyinterpreter-architecture.png and /dev/null differ
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/images/jpyinterpreter-architecture/jpyinterpreter-architecture.svg b/jpyinterpreter/developer-docs/src/modules/ROOT/images/jpyinterpreter-architecture/jpyinterpreter-architecture.svg
deleted file mode 100644
index 0f8293cb..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/images/jpyinterpreter-architecture/jpyinterpreter-architecture.svg
+++ /dev/null
@@ -1,685 +0,0 @@
-
-
-
-
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/nav.adoc b/jpyinterpreter/developer-docs/src/modules/ROOT/nav.adoc
deleted file mode 100644
index 411bd914..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/nav.adoc
+++ /dev/null
@@ -1,6 +0,0 @@
-* xref:jpyinterpreter-introduction/jpyinterpreter-introduction.adoc[leveloffset=+1]
-* xref:stack-machines/stack-machines.adoc[leveloffset=+1]
-* xref:python-function-structure/python-function-structure.adoc[leveloffset=+1]
-* xref:opcodes/opcodes.adoc[leveloffset=+1]
-* xref:java-bytecode/java-bytecode.adoc[leveloffset=+1]
-* xref:jpyinterpreter-architecture/jpyinterpreter-architecture.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/.index.adoc b/jpyinterpreter/developer-docs/src/modules/ROOT/pages/.index.adoc
deleted file mode 100644
index 541b06c0..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/.index.adoc
+++ /dev/null
@@ -1,18 +0,0 @@
-= JPyInterpreter Developer Guide
-:doctype: book
-:imagesdir: .
-:toc: left
-:toclevels: 3
-:sectnums:
-:sectanchors:
-:sectlinks:
-:sectnumlevels: 5
-:icons: font
-:docinfo:
-
-include::jpyinterpreter-introduction/jpyinterpreter-introduction.adoc[leveloffset=+1]
-include::stack-machines/stack-machines.adoc[leveloffset=+1]
-include::python-function-structure/python-function-structure.adoc[leveloffset=+1]
-include::opcodes/opcodes.adoc[leveloffset=+1]
-include::java-bytecode/java-bytecode.adoc[leveloffset=+1]
-include::jpyinterpreter-architecture/jpyinterpreter-architecture.adoc[leveloffset=+1]
\ No newline at end of file
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/java-bytecode/java-bytecode.adoc b/jpyinterpreter/developer-docs/src/modules/ROOT/pages/java-bytecode/java-bytecode.adoc
deleted file mode 100644
index d3111c92..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/java-bytecode/java-bytecode.adoc
+++ /dev/null
@@ -1,137 +0,0 @@
-[[javaBytecode]]
-= Java Bytecode
-
-== Java Virtual Machine Basic Properties
-
-The Java Virtual Machine is a stack based virtual machine.
-It has the following properties:
-
-- Parameters and local variables are stored in slots, with parameters being first.
-This also includes the `this` parameter, which is always in the first slot for instance methods.
-Compilers can also introduce synthetic local variables that do not correspond to any variable in the source.
-
-- On exception, the current stack is cleared and the thrown exception is pushed to the stack.
-
-- Each instruction must have a consistent prior stack size.
-This means if an instruction is the target of multiple instructions, each instruction that have it as a target must have the same post stack size.
-For instance, this is invalid:
-+
-```
-LDC 1
-ILOAD 1
-if_icmpeq [if-equal]
-ILOAD 2
-[if-equal]
-RETURN
-```
-+
-Because RETURN have an inconsistent prior stack size: if the `if_icmpeq` branch is taken, the expected stack size is 0; otherwise, the expected stack size is 1 (because `ILOAD 2` push an `int` to the stack).
-The bytecode below is valid:
-+
-```
-LDC 1
-ILOAD 1
-if_icmpeq [if-equal]
-ILOAD 2
-POP
-[if-equal]
-RETURN
-```
-+
-since the expected stack size prior to RETURN is 0 for both branches of `if_icmpeq`.
-
-- The stack is typed, and will cause verification errors if we were to try to call a method with invalid types on the stack.
-For instance, this is invalid:
-+
-```
-ILOAD 1
-INVOKESTATIC [MyClass.method(float) -> float]
-```
-+
-since we are calling a method that expects a `float` with an `int`.
-This is also invalid:
-+
-```
-ALOAD 1 [Object]
-INVOKEVIRTUAL [MyClass.method() -> void]
-```
-+
-Since we are trying to call a `MyClass` method on `Object` (which may or may not be a `MyClass` instance).
-To fix it, we need to cast it first:
-+
-```
-ALOAD 1 [Object]
-CHECKCAST [MyClass]
-INVOKEVIRTUAL [MyClass.method() -> void]
-```
-
-== Java Virtual Machine instruction listing
-
-A full explanation of the Java Virtual Machine's instruction set can be viewed at the https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-6.html[Oracle JVM Documentation] and a summary can be read on the https://en.wikipedia.org/wiki/List_of_Java_bytecode_instructions[List of Java bytecode instruction wikipedia article].
-
-== Generating Java bytecode instructions
-
-Java bytecode instructions are generated with the https://asm.ow2.io/[ASM library].
-Functions are created by creating a `JavaPythonClassWriter` (which is a `ClassWriter` that overrides `getCommonSuperClass` to prevent `TypeNotPresent` errors) instance,
-getting the MethodVisitor for its https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.8[functional interface method],
-adapting the method visitor with `MethodVisitorAdapters.adapt` (which sorts try blocks for us and gives us better error messages),
-and then generating the Java bytecode using that method visitor.
-It looks like this in the code:
-
-```java
-ClassWriter classWriter = new JavaPythonClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
-classWriter.visit(Opcodes.V11, Modifier.PUBLIC, internalClassName, null, Type.getInternalName(Object.class),
- new String[] { methodDescriptor.getDeclaringClassInternalName() });
-
-// ... Create fields and constructor ...
-
-MethodVisitor methodVisitor = classWriter.visitMethod(Modifier.PUBLIC,
- methodDescriptor.getMethodName(),
- methodDescriptor.getMethodDescriptor(),
- null,
- null);
-
-MethodVisitorAdapters.adapt(methodVisitor, methodDescriptor);
-
-// ... Visit parameters ...
-
-methodVisitor.visitCode();
-
-// ... Create bytecode ...
-
-methodVisitor.visitMaxs(0, 0);
-methodVisitor.visitEnd();
-```
-
-To generate a particular opcode instruction, identify what kind of instruction it is:
-
-- Instructions that either conditionally or unconditionally jump to a label are created with `visitJumpInsn`, which take the label to either conditionally or unconditionally jump to.
-
-- Instructions that load parameters or local variables are created with `visitVarInsn`, which take an `int` to identify which slot to load the parameter/local variable from.
-We can use the `LocalVariableHelper` on `StackMetadata` to obtain the slot number of parameters and local variables.
-
-- Instructions that operate on the stack are created with `visitInsn` (for instance, popping a value or adding the top two `int` on the stack). No parameter (beside the opcode to generate) is needed for these opcodes.
-
-- Instructions that call methods are created with `visitMethodInsn`, which takes.
-
-** The internal name of the declaring class.
-This can be retrieved with `Type.getInternalName`.
-
-** The method name.
-
-** The method descriptor string that describe the parameter and return types of the method.
-This can be received with `Type.getMethodDescriptor(Type returnType, Type... parameterTypes)` (the `Type` object of a class can be received with `Type.getType`).
-
-** A boolean that is true if the method is defined on an interface, false otherwise.
-
-- Instructions that read or set fields are created with `visitFieldInsn`, which takes
-
-** The internal name of the class this field belongs to. This can be retrieved with `Type.getInternalName`.
-
-** The field's name.
-
-** The field's type descriptor string. This can be received with `Type.getDescriptor`.
-
-- Instructions that operate on types (i.e. `CHECKCAST`, `INSTANCEOF` and `NEW`) are generated with `visitTypeInsn`. It takes the internal name of the class to cast/instanceof/new as an argument (this can be retrieved with `Type.getInternalName`).
-
-- The instruction that load constants onto the stack can be generated with `visitLDC`; it takes the constant to load (which *must* be a primitive type, Type object, or a String) as its only argument.
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/jpyinterpreter-architecture/jpyinterpreter-architecture.adoc b/jpyinterpreter/developer-docs/src/modules/ROOT/pages/jpyinterpreter-architecture/jpyinterpreter-architecture.adoc
deleted file mode 100644
index 6ac731c7..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/jpyinterpreter-architecture/jpyinterpreter-architecture.adoc
+++ /dev/null
@@ -1,125 +0,0 @@
-[[jpyinterpreterArchitecture]]
-= JPyInterpreter Architecture
-
-The architecture of JPyInterpreter is composed of several components spread across Python and Java.
-The Python components are:
-
-- `jvm_setup.py`, which sets up the JVM and the hooks JPyInterpreter uses to communicate with CPython (to look up packages, call native methods, and converting CPython object to Java object and vice-versa).
-
-- `python_to_java_bytecode_translator.py`, which acts as the Python's frontend to JPyInterpreter.
-Users supply a CPython function to translate (and an optional Java functional interface it implements) to `translate_python_bytecode_to_java_bytecode`, which firsts converts that function to a `PythonCompiledFunction`, and then passes it to `PythonBytecodeToJavaBytecodeTranslator` to translate the function.
-It also provides the `translate_python_class_to_java_class` function, which is given a user supplied CPython class, converts it to a `PythonCompiledClass`, and passes it to `PythonClassTranslator` to translate the class.
-
-The Java components are:
-
-- `PythonBytecodeToJavaBytecodeTranslator`, which acts as the entrypoint for function translation.
-It is responsible for:
-
-** Setting up the `JavaPythonClassWriter` and `MethodVisitor` used for bytecode generation.
-
-** Creating and setting fields on the generated class objects (See <<_pythonbytecodetojavabytecodetranslator>> for details).
-
-** Do the leg work of moving/translating Java parameters (ex: `int`) into `PythonLikeObject`.
-
-** Setup cells variables.
-
-** Delegating to `PythonGeneratorTranslator` when it detects the function being translated is a generator.
-
-** Using `FlowGraph` to calculate the `StackMetadata` of each instruction.
-
-** Calling the `implement` method on every opcode in the `Opcode` list with the `StackMetadata` for the opcode and the `FunctionMetadata` for the overall function.
-
-- `PythonGeneratorTranslator` is like `PythonBytecodeToJavaBytecodeTranslator` but for generators.
-It breaks a single generator function into multiple `advance` functions, and generates each `advance` function bytecode independently.
-
-- `FlowGraph`, which calculates the `StackMetadata` that corresponds to each `Opcode`.
-It is responsible for unifying the `StackMetadata` from all jump sources for each `Opcode` that is a jump target.
-For instance, if two sources with the same target have post `StackMetadata` of `... int` and `... bool` respectively, `FlowGraph` will unify that to `... int` (since `bool` is a subclass of `int`, for better or worse).
-
-- `StackMetadata` stores metadata about the stack and local variables.
-Each `Opcode` get its own `StackMetadata` instance.
-It is mostly used to perform optimizations; for instance, if we detect the top two items on the stack are `int` and `int` for the `BINARY_ADD` instruction, we can change the (normally complex due to Python semantics) `BINARY_ADD` bytecode into a single method call.
-
-- `FunctionMetadata` stores metadata about the function (for instance, the `MethodVisitor` to use to generate bytecode). Each `Opcode` gets the same `FunctionMetadata` instance.
-
-- `Opcode` are the interface between CPython opcodes and the `Implementors`.
-Each describe a particular operation, and usually (but not always) correspond to a CPython opcode.
-Some CPython opcodes map to the same `Opcode` implementation.
-
-- `Implementors` are responsible for generating the Java bytecode corresponding to CPython bytecode.
-They can be found in the `implementors` package.
-
-The overall process of compiling a function looks like this:
-
-image::jpyinterpreter-architecture/jpyinterpreter-architecture.png[A diagram showing how JPyInterpreter classes interact]
-
-
-== Types
-
-The builtin types for JPyInterpreter can be found in the `types` package.
-They all implement `PythonLikeObject`, the interface the bytecode uses to represent arbitrary objects.
-If type flow analysis determines a more specific type can be used (via `StackMetadata`), the more specific type is used directly instead.
-`PythonLikeObject` have several methods:
-
-- `\\__getAttributeOrNull`: returns the attribute with the given name if it exists, otherwise returns null.
-This is NOT `__getattribute\__` (which is implemented by `$method$\__getattribute\__` instead).
-This is more akin to `self.\__dict\__[attribute]`.
-The default `$method$\__getattribute__` uses it to get the attribute (with additional magic to handle descriptors, see https://docs.python.org/3.11/howto/descriptor.html#invocation-from-an-instance[the Python descriptor tutorial] for more detail).
-
-- `__getAttributeOrError`: returns the attribute with the given name if it exists, otherwise raises `AttributeError`.
-Used in bytecode generation to lookup methods on types.
-
-- `\\__setAttribute`: sets the attribute with the given name to the given value.
-This is NOT `__setattr\__` (which is implemented by `$method$\__setattr\__` instead).
-This is more akin to `self.\__dict\__[attribute] = value`.
-The default `$method$\__setattr__` uses it to set the attribute.
-
-- `\\__deleteAttribute`: deletes the attribute with the given name.
-This is NOT `__delattr\__` (which is implemented by `$method$\__delattr\__` instead).
-This is more akin to `del self.\__dict\__[attribute]`.
-The default `$method$\__delattr__` uses it to delete the attribute.
-
-- `__getType`: returns the type of the object.
-Used to implement `type(object)`.
-
-- `__getGenericType`: returns the generic type of the object (ex: `list[int]`).
-Used for typeflow analysis.
-
-- `$method$`: the builtin methods on every object in Python.
-The `$method$` naming is to allow custom classes to override them (custom classes prefix method names with `$method$` to not clash with Java method names).
-
-== PythonBytecodeToJavaBytecodeTranslator
-
-The entrypoint for function translation, and the glue code for the many subsystems of the translator.
-It is responsible for setting up the `JavaPythonClassWriter`, `MethodVisitor` and configuring the class' fields.
-The fields it configures are:
-
-- `co_consts`: Static; a `List` that stores constants used in the bytecode.
-
-- `co_names`: Static; a `List` that stores names used in the bytecode.
-
-- `co_varnames`: Static; a `List` that stores variable names used in the bytecode.
-
-- `\\__globals__`: Static; a `Map` used to read and store globals.
-
-- `\\__spec_getter__`: Static; a `BiFunction>` that maps default arguments (which are per function) to an `ArgumentSpec` that can be used to set parameters.
-
-- `\\__defaults__`: Instance; a `PythonLikeTuple` that stores default positional arguments.
-
-- `\\__kwdefaults__`: Instance; a `PythonLikeDict` that stores default keyword arguments.
-
-- `\\__annotations__`: Instance; a `PythonLikeDict` that stores type annotations on the function.
-
-- `\\__closure__`: Instance; a `PythonLikeTuple` that stores the function's closure (i.e. the free variable cells).
-
-- `\\__qualname__`: Instance; a `PythonString` that stores the qualified name of the function.
-
-- `\\__spec__`: Instance; an `ArgumentSpec` that can be used to receive parameter (and correctly handle default arguments).
-
-- `\\__interpreter__`: Instance; the `PythonInterpreter` this function runs in (used to perform imports and lookup unknown globals).
-
-If a Python function cannot be translated for any reason (ex: native code), the following fields are also added:
-
-- `\\__code__`: Static; an opaque pointer to the function's CPython code object (used in the construct to make the wrapped CPython function).
-
-- `\\__function__`: Instance; a `PythonObjectWrapper` that wraps the CPython function (used to call the CPython function).
\ No newline at end of file
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/jpyinterpreter-introduction/jpyinterpreter-introduction.adoc b/jpyinterpreter/developer-docs/src/modules/ROOT/pages/jpyinterpreter-introduction/jpyinterpreter-introduction.adoc
deleted file mode 100644
index 5c26314f..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/jpyinterpreter-introduction/jpyinterpreter-introduction.adoc
+++ /dev/null
@@ -1,38 +0,0 @@
-[[jpyinterpreterIntroduction]]
-= JPyInterpreter Introduction
-// Redirect to this page from .../docs/jpyinterpreter/latest.
-:page-aliases: ../index.adoc
-:doctype: book
-:sectnums:
-:icons: font
-
-[[whatIsJpyinterpreter]]
-== What is JPyInterpreter
-
-JPyInterpreter is a Python interpreter that runs in
-the JVM that can be embedded in CPython to remove overhead
-of calling Python code frequently from Java. This is mostly
-relevant for small functions, where the overhead decreases
-performance by as much as 100 times.
-
-It accomplishes this by creating Java class files from the
-https://docs.python.org/3/glossary.html#term-bytecode[CPython bytecode], accessible https://docs.python.org/3/library/dis.html[via the dis module]. Both CPython Virtual Machine and the JVM are
-https://en.wikipedia.org/wiki/Stack_machine[stack machines], meaning each opcode reads it parameters
-and writes its results to a stack. As such, JPyInterpreter can also be thought of as a translator of CPython bytecode to Java bytecode.
-
-[[jpyinterpreterStructure]]
-== JPyInterpreter's Structure
-
-JPyInterpreter's structure can be broken into several
-components:
-
-- The Python frontend, which is given Python function and classes and returns their corresponding Java versions.
- The Python frontend has minimal code, and is mostly responsible for passing the Python bytecode to Java and converting Python constants into Java constants.
-
-- The Java opcode parser, which is given Python bytecode instructions and needs to convert them to intermediary opcodes.
-
-- A typeflow analyzer, which is given the Python function signature and the intermediary opcodes, and returns the stack metadata associated with each opcode. The stack metadata is useful for optimizing opcodes, such as `GET_ATTR` (which typically need to go through a complicated dict lookup process, but if it is a known field, it can be implemented by a single `getfield` java bytecode instruction)
-
-- Implementors, which write the java bytecode instructions
-to implement a given intermediary opcode with the given stack metadata and function metadata.
-
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/opcodes/opcodes.adoc b/jpyinterpreter/developer-docs/src/modules/ROOT/pages/opcodes/opcodes.adoc
deleted file mode 100644
index 1ab75f85..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/opcodes/opcodes.adoc
+++ /dev/null
@@ -1,3843 +0,0 @@
-[[cpythonOpcodes]]
-= CPython Opcode Instructions
-
-CPython compiles function into bytecode.
-The opcodes for this bytecode are listed here and can also be found in `OpcodeIdentifier`.
-CPython bytecode structure in not stable, and opcode behaviour may change between releases.
-
-== General Format
-
-Each opcode will be listed in the following format:
-
-```
-Opcode Name
-
-Python Versions
-
-Stack Prior: ... [expected stack state]
-Stack After: ... [new stack state]
-
-Description of Opcode
-
-Example sources that generate the opcode
-```
-
-For instance, the `POP_TOP` opcode, which pop a single item off the top of the stack, would look like this:
-
-```
-POP_TOP
-
-Python Versions: ALL
-
-Stack Prior: ... item
-Stack After: ...
-
-Pops a single item off the stack.
-Used to discard return value of functions and to manipulate the stack.
-
-Example Sources:
-my_fun() # POP_TOP is generated after the function call
- # since the result of my_fun is unused.
-```
-
-
-== Instruction Addressing
-
-Prior to 3.10, instructions are addressed by byte offsets.
-So the first instruction would have address 0, the second instruction would have address 2, and the third instruction would have address 4.
-After 3.10, instructions are addressed by instruction offsets.
-So the first instruction would have address 0, the second instruction would have address 1, and the third instruction would have address 2.
-
-Absolute jumps go to the instruction with the address given by the argument.
-So an absolute jump with argument 2 will go to the instruction at address 2 regardless of the jump's address.
-
-Relative jumps go to the instruction that are argument addresses away from it.
-So a relative jump with argument 2 will go to the instruction at address 3 if the jump is at address 1, or 4 if the jump is at address 2.
-
-
-[#_cell_variable_index]
-== Cell Variable Index
-
-In Python 3.10 and below, the argument for `LOAD_CLOSURE`, `LOAD_CLASSDEREF`, `LOAD_DEREF`, `STORE_DEREF` and `DELETE_DEREF` correspond to the index of the variable name in the combined list `co_cellvars + co_freevars`.
-For instance, if `co_cellvars = ['a', 'b']` and `co_freevars = ['c', 'd']`, the argument to read/modify/delete the variable corresponding to each name would be:
-
-- 'a': 0
-- 'b': 1
-- 'c': 2
-- 'd': 3
-
-In Python 3.11, the indices for cell variables that do not correspond to parameters are offset by `co_varnames`. If a cell variable corresponds to a parameter, it uses the parameter index in `co_varnames` as its cell index. For instance, if `co_varnames = ['a', 'x', 'y']`, `co_cellvars = ['a', 'b']` and `co_freevars = ['c', 'd']`, the argument to read/modify/delete the variable corresponding to each name would be:
-
-- 'a': 0
-- 'b': 3
-- 'c': 4
-- 'd': 5
-
-== Opcode Listing
-
-=== NOP
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Does absolutely nothing.
-Exists purely to simplify bytecode generation.
-
-Example Sources:
-
-```python
-pass # `pass` represent a NOP in Python
-```
-
-=== RESUME
-
-Python Versions: 3.11+
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-A NOP opcode that CPython uses to perform internal tracing, debugging and optimization checks.
-Generally put into places where the CPython interpreter enters a function (the start of every function and after yield statements).
-
-Example Sources:
-
-```python
-def function():
- # A RESUME opcode is placed at the start of every
- # function.
- return None
-```
-
-```python
-yield 10 # A RESUME opcode is placed after
- # each YIELD_VALUE opcode
-```
-
-=== CACHE
-
-Python Versions: 3.11+
-
-A NOP opcode that CPython uses to record runtime conditions for the https://peps.python.org/pep-0659/[specializing adaptive interpreter].
-For instance, if CPython detects a BINARY_OP opcode is usually performed on two `int`,
-the CPython interpreter writes that information into the CACHE opcodes that precede the BINARY_OP to specialize the BINARY_OP into `INT_BINARY_ADD`.
-JPyIntepreter does specialization at compile time using information from type annotation and typeflow analysis.
-
-Example Sources:
-
-```python
-# Several CACHE instruction precede the
-# BINARY_OP
-x + y
-```
-
-=== POP_TOP
-
-Python Versions: ALL
-
-```
-Stack Prior: ... item
-Stack After: ...
-```
-
-Pops a single item off the stack.
-Used to discard return value of functions and to manipulate the stack.
-
-Example Sources:
-
-```python
-my_fun() # POP_TOP is generated after the function call
- # since the result of my_fun is unused.
-```
-
-=== ROT_TWO
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... second, first
-Stack After: ... first, second
-```
-
-Swaps the top two elements of the stack.
-Used for stack manipulation.
-
-Example Sources:
-
-```python
-# Swap in Python 3.10 and below can be implemented as
-# LOAD[y], LOAD[x], ROT_TWO, STORE[x], STORE[y]
-x, y = y, x
-```
-
-=== ROT_THREE
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... third, second, first
-Stack After: ... first, third, second
-```
-
-Move the top of stack down by two, raising the two items immediately below it up by one.
-Used for stack manipulation.
-
-Example Sources:
-
-```python
-# FLIP_3 in Python 3.10 and below can be implemented as
-# LOAD[z], LOAD[y], LOAD[x], (stack is z, y, x)
-# ROT_THREE, (stack is x, z, y)
-# ROT_TWO, (stack is x, y, z)
-# STORE[x], STORE[y], STORE[z]
-x, y, z = z, y, x
-```
-
-=== ROT_FOUR
-
-Python Versions: >= 3.8 and \<= 3.10
-
-```
-Stack Prior: ... fourth, third, second, first
-Stack After: ... first, fourth, third, second
-```
-
-Move the top of stack down by three, raising the three items immediately below it up by one.
-Used for stack manipulation.
-
-Example Sources:
-
-```python
-# FLIP_3 in Python 3.10 and below can be implemented as
-# LOAD[w], LOAD[z], LOAD[y], LOAD[x], (stack is z, y, x, w)
-# ROT_FOUR, (stack is w, z, y, x)
-# ROT_THREE, (stack is w, x, z, y)
-# ROT_TWO (stack is w, x, y, z)
-# STORE[w], STORE[x], STORE[y], STORE[z]
-w, x, y, z = z, y, x, w
-```
-
-=== DUP_TOP
-
-Python Versions: >= 3.2, \<= 3.10
-
-```
-Stack Prior: ... top
-Stack After: ... top, top
-```
-
-Duplicates the top of stack.
-Used to preserve a stack value that is used in multiple operations.
-
-Example Sources:
-
-```python
-# Python 3.10 and below
-a == b == c
-```
-
-=== DUP_TOP_TWO
-
-Python Versions: >= 3.2, \<= 3.10
-
-```
-Stack Prior: ... a, b
-Stack After: ... a, b, a, b
-```
-
-Duplicates the top two elements of the stack.
-
-Example Sources:
-
-```python
-a[b] += a[c]
-```
-
-=== COPY(i)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... item_i, ..., item_2, item_1
-Stack After: ... item_i, ..., item_2, item_1, item_i
-```
-
-Copies the item at the given 1-based index in the stack to the top of stack.
-The item is not removed from its original position.
-
-Example Sources:
-
-```python
-# Python 3.11 and above
-a == b == c
-```
-
-=== SWAP(i)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... item_i, ..., item_2, item_1
-Stack After: ... item_1, ..., item_2, item_i
-```
-
-Swaps the item at the given 1-based index in the stack with the top of stack.
-
-Example Sources:
-
-```python
-# Python 3.11 and above
-a == b == c
-```
-
-=== UNARY_POSITIVE
-
-Python Versions: ALL
-
-```
-Stack Prior: ... operand
-Stack After: ... result
-```
-
-Implements `+x`.
-Pops the operand off the stack, call its `\\__pos__` method, and push the result.
-
-Example Sources:
-
-```python
-+x
-```
-
-=== UNARY_NEGATIVE
-
-Python Versions: ALL
-
-```
-Stack Prior: ... operand
-Stack After: ... result
-```
-
-Implements `-x`.
-Pops the operand off the stack, call its `\\__neg__` method, and push the result.
-
-Example Sources:
-
-```python
--x
-```
-
-=== UNARY_INVERT
-
-Python Versions: ALL
-
-```
-Stack Prior: ... operand
-Stack After: ... result
-```
-
-Implements `~x`.
-Pops the operand off the stack, call its `\\__invert__` method, and push the result.
-
-Example Sources:
-
-```python
-~x
-```
-
-=== GET_ITER
-
-Python Versions: ALL
-
-```
-Stack Prior: ... iterable
-Stack After: ... iterator
-```
-
-Pops the iterable off the stack, call its `\\__iter__` method, and push the result. Used to implement for loops.
-
-Example Sources:
-
-```python
-# The for loop performs GET_ITER on iterable to get the iterator,
-# which is then used by FOR_ITER to loops through iterable items.
-for item in iterable:
- ...
-```
-
-=== GET_YIELD_FROM_ITER
-
-Python Versions: >= 3.5
-
-```
-Stack Prior: ... iterable
-Stack After: ... iterator
-```
-
-If the iterable is a generator iterator or a coroutine, leave it on the stack.
-Otherwise, call its `\\__iter__` method.
-Used in `yield from` expressions.
-
-Example Sources:
-
-```python
-# GET_YIELD_FROM_ITER is used to get the
-# iterator for [1, 2, 3].
-yield from [1, 2, 3]
-```
-
-=== BINARY_OP(op)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... left_operand, right_operand
-Stack After: ... result
-```
-
-Perform the binary operator indicated by the opcode's argument on the top two items on the stack (popping them), and push the result to the top of stack.
-An binary op can either be inplace or not in place.
-Inplace opcodes try the binary op's inplace method first,
-then fall back to the standard binary op handling.
-The argument to binary operator mapping can be found in https://github.com/python/cpython/blob/0faa0ba240e815614e5a2900e48007acac41b214/Python/ceval.c#L299[CPython source code].
-In general, first are the non-inplace opcodes in alphabetical order, followed by the inplace opcodes in alphabetical order.
-
-The left operand is always the first element below the top of stack, and the right operand is always the top of stack. The binary operation is performed as followed:
-
-* Get the method for the binary operation from the left operand's type.
-
-* If the method is present:
-
-** Call the resolved method with the left and right operands.
-** If the result is not `NotImplemented`, then it the result of this `BINARY_OP` and go to the next bytecode instruction.
-** If the result is `NotImplemented`, treat it as if the left operand's type did not have the method.
-** If the left operand a builtin type and the method raises a `TypeError`, treat it as if the left operand's type did not have the method.
-
-* If the method is not present:
-
-** Get the method for the reflected version of the binary operation from the right operand's type.
-
-** If the reflected method is present:
-
-*** Call the reflected resolved method with the right and left operands.
-*** If the result is not `NotImplemented`, then it the result of this `BINARY_OP` and go to the next bytecode instruction.
-*** If the result is `NotImplemented`, treat it as if the right operand's type did not have the reflected method.
-
-** If the reflected method is not present, raise a `TypeError` with the message `f"unsupported operand type(s) for {symbol(BINARY_OP)}: '{type(left_operand)}' and '{type(right_operand)}'"`
-
-In Python, it would look like this:
-
-```python
-def binary_op(BINARY_OP, left_operand, right_operand):
- UNSUPPORTED_OP_MSG = f"unsupported operand type(s) for {symbol(BINARY_OP)}: '{type(left_operand)}' and '{type(right_operand)}'"
- def reflected_binary_op():
- right_method = getattr(type(right_operand), reflected(BINARY_OP), None)
- if right_method is not None:
- reflected_out = right_method(right_operand, left_operand)
- if reflected_out is NotImplemented:
- raise TypeError(UNSUPPORTED_OP_MSG)
- else:
- return reflected_out
-
- if is_in_place(BINARY_OP):
- inplace_method = getattr(type(left_operand), BINARY_OP, None)
- if inplace_method is not None:
- out = inplace_method(left_operand, right_operand)
- if out is not NotImplemented:
- return out
- BINARY_OP = get_standard_binary_op(BINARY_OP)
- left_method = getattr(type(left_operand), BINARY_OP, None)
- if left_method is not None:
- try:
- out = left_method(left_operand, right_operand)
- if out is not NotImplemented:
- return out
- except TypeError:
- if type(left_operand) in BUILTIN_TYPES:
- return reflected_binary_op()
- raise
- return reflected_binary_op()
-
-```
-
-Example Sources:
-
-```python
-x + 1
-```
-
-```python
-x -= y
-```
-
-=== BINARY_POWER
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... base, exponent
-Stack After: ... result
-```
-
-<> corresponding to `\\__pow__` and `\\__rpow__`. Implements `**`.
-
-Example Sources:
-
-```python
-base ** expotent
-```
-
-=== BINARY_MULTIPLY
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... left_factor, right_factor
-Stack After: ... product
-```
-
-<> corresponding to `\\__mul__` and `\\__rmul__`. Implements `*`.
-
-Example Sources:
-
-```python
-left_factor * right_factor
-```
-
-=== BINARY_MATRIX_MULTIPLY
-
-Python Versions: >= 3.5 and \<= 3.10
-
-```
-Stack Prior: ... left_factor, right_factor
-Stack After: ... product
-```
-
-<> corresponding to `\\__matmul__` and `\\__rmatmul__`. Implements `@`.
-
-Example Sources:
-
-```python
-left_factor @ right_factor
-```
-
-=== BINARY_FLOOR_DIVIDE
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... dividend, divisor
-Stack After: ... quotient
-```
-
-<> corresponding to `\\__floordiv__` and `\\__rfloordiv__`. Implements `//`.
-
-Example Sources:
-
-```python
-dividend // divisor
-```
-
-=== BINARY_TRUE_DIVIDE
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... dividend, divisor
-Stack After: ... quotient
-```
-
-<> corresponding to `\\__truediv__` and `\\__rtruediv__`. Implements `/`.
-
-Example Sources:
-
-```python
-dividend / divisor
-```
-
-=== BINARY_MODULO
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... dividend, divisor
-Stack After: ... modulus
-```
-
-<> corresponding to `\\__mod__` and `\\__rmod__`. Implements `%`.
-
-Example Sources:
-
-```python
-dividend % divisor
-```
-
-=== BINARY_ADD
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... augend, addend
-Stack After: ... sum
-```
-
-<> corresponding to `\\__add__` and `\\__radd__`. Implements `+`.
-
-Example Sources:
-
-```python
-augend + addend
-```
-
-=== BINARY_SUBTRACT
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... minuend, subtrahend
-Stack After: ... difference
-```
-
-<> corresponding to `\\__sub__` and `\\__rsub__`. Implements `-`.
-
-Example Sources:
-
-```python
-minuend - subtrahend
-```
-
-
-=== BINARY_LSHIFT
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... to_shift, shift
-Stack After: ... result
-```
-
-<> corresponding to `\\__lshift__` and `\\__rlshift__`. Implements `<<`.
-
-Example Sources:
-
-```python
-to_shift << shift
-```
-
-=== BINARY_RSHIFT
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... to_shift, shift
-Stack After: ... result
-```
-
-<> corresponding to `\\__rshift__` and `\\__rrshift__`. Implements `>>`.
-
-Example Sources:
-
-```python
-to_shift >> shift
-```
-
-=== BINARY_AND
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... left_conjunct, right_conjunct
-Stack After: ... conjunction
-```
-
-<> corresponding to `\\__and__` and `\\__rand__`. Implements `&`.
-
-Example Sources:
-
-```python
-left_conjunct & right_conjunct
-```
-
-
-=== BINARY_OR
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... left_disjunct, right_disjunct
-Stack After: ... disjunction
-```
-
-<> corresponding to `\\__or__` and `\\__ror__`. Implements `|`.
-
-Example Sources:
-
-```python
-left_disjunct | right_disjunct
-```
-
-
-=== BINARY_XOR
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... left_disjunct, right_disjunct
-Stack After: ... disjunction
-```
-
-<> corresponding to `\\__xor__` and `\\__rxor__`. Implements `^`.
-
-Example Sources:
-
-```python
-left_disjunct ^ right_disjunct
-```
-
-
-=== INPLACE_POWER
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... base, exponent
-Stack After: ... result
-```
-
-<> corresponding to `\\__ipow__`, `\\__pow__` and `\\__rpow__`. Implements `**=`.
-
-Example Sources:
-
-```python
-base **= expotent
-```
-
-=== INPLACE_MULTIPLY
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... left_factor, right_factor
-Stack After: ... product
-```
-
-<> corresponding to `\\__imul__`, `\\__mul__` and `\\__rmul__`. Implements `*`.
-
-Example Sources:
-
-```python
-left_factor *= right_factor
-```
-
-=== INPLACE_MATRIX_MULTIPLY
-
-Python Versions: >= 3.5 and \<= 3.10
-
-```
-Stack Prior: ... left_factor, right_factor
-Stack After: ... product
-```
-
-<> corresponding to `\\__imatmul__`, `\\__matmul__` and `\\__rmatmul__`. Implements `@=`.
-
-Example Sources:
-
-```python
-left_factor @= right_factor
-```
-
-=== INPLACE_FLOOR_DIVIDE
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... dividend, divisor
-Stack After: ... quotient
-```
-
-<> corresponding to `\\__ifloordiv__`, `\\__floordiv__` and `\\__rfloordiv__`. Implements `//=`.
-
-Example Sources:
-
-```python
-dividend //= divisor
-```
-
-=== INPLACE_TRUE_DIVIDE
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... dividend, divisor
-Stack After: ... quotient
-```
-
-<> corresponding to `\\__itruediv__`, `\\__truediv__` and `\\__rtruediv__`. Implements `/=`.
-
-Example Sources:
-
-```python
-dividend /= divisor
-```
-
-=== INPLACE_MODULO
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... dividend, divisor
-Stack After: ... modulus
-```
-
-<> corresponding to `\\__imod__`, `\\__mod__` and `\\__rmod__`. Implements `%=`.
-
-Example Sources:
-
-```python
-dividend %= divisor
-```
-
-=== INPLACE_ADD
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... augend, addend
-Stack After: ... sum
-```
-
-<> corresponding to `\\__iadd__`, `\\__add__` and `\\__radd__`. Implements `+=`.
-
-Example Sources:
-
-```python
-augend += addend
-```
-
-=== INPLACE_SUBTRACT
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... minuend, subtrahend
-Stack After: ... difference
-```
-
-<> corresponding to `\\__isub__`, `\\__sub__` and `\\__rsub__`. Implements `-=`.
-
-Example Sources:
-
-```python
-minuend -= subtrahend
-```
-
-
-=== INPLACE_LSHIFT
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... to_shift, shift
-Stack After: ... result
-```
-
-<> corresponding to `\\__ilshift__`, `\\__lshift__` and `\\__rlshift__`. Implements `<\<=`.
-
-Example Sources:
-
-```python
-to_shift <<= shift
-```
-
-=== INPLACE_RSHIFT
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... to_shift, shift
-Stack After: ... result
-```
-
-<> corresponding to `\\__irshift__` , `\\__rshift__` and `\\__rrshift__`. Implements `>>=`.
-
-Example Sources:
-
-```python
-to_shift >>= shift
-```
-
-=== INPLACE_AND
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... left_conjunct, right_conjunct
-Stack After: ... conjunction
-```
-
-<> corresponding to `\\__iand__` , `\\__and__` and `\\__rand__`. Implements `&=`.
-
-Example Sources:
-
-```python
-left_conjunct &= right_conjunct
-```
-
-
-=== INPLACE_OR
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... left_disjunct, right_disjunct
-Stack After: ... disjunction
-```
-
-<> corresponding to `\\__ior__`, `\\__or__` and `\\__ror__`. Implements `|=`.
-
-Example Sources:
-
-```python
-left_disjunct |= right_disjunct
-```
-
-
-=== INPLACE_XOR
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... left_disjunct, right_disjunct
-Stack After: ... disjunction
-```
-
-<> corresponding to `\\__ixor__`, `\\__xor__` and `\\__rxor__`. Implements `^=`.
-
-Example Sources:
-
-```python
-left_disjunct ^= right_disjunct
-```
-
-
-=== BINARY_SUBSCR
-
-Python Versions: ALL
-
-```
-Stack Prior: ... collection, key
-Stack After: ... item
-```
-
-Implements `collection[key]`. Acts like a <>, but does not have a reflective method. Pop the two top items off the stack, calls the `\\__getitem__` method on `type(collection)` with the arguments `collection` and `key`, and push the method result to the top of the stack.
-
-Example Sources:
-
-```python
-collection[key]
-```
-
-
-=== STORE_SUBSCR
-
-Python Versions: ALL
-
-```
-Stack Prior: ... value, collection, key
-Stack After: ...
-```
-
-Implements `collection[key] = value`. Pop the three top items off the stack, calls the `\\__setitem__` method on `type(collection)` with the arguments `collection`, `key` and `value`. Does not push the result onto the stack.
-
-Example Sources:
-
-```python
-collection[key] = value
-```
-
-
-=== DELETE_SUBSCR
-
-Python Versions: ALL
-
-```
-Stack Prior: ... collection, key
-Stack After: ...
-```
-
-Implements `del collection[key]`. Pop the two top items off the stack, calls the `\\__delitem__` method on `type(collection)` with the arguments `collection` and `key`. Does not push the result onto the stack.
-
-Example Sources:
-
-```python
-del collection[key]
-```
-
-
-=== GET_AWAITABLE(where)
-
-Python Versions: >= 3.5
-
-```
-Stack Prior: ... awaitable
-Stack After: ... awaitable_iterator
-```
-
-If awaitable is a coroutine or a generator coroutine, leave it as is on the stack. Otherwise, replace `awaitable` with the result of calling its `\\__await__` method.
-
-Before Python 3.11, this opcode did not have an argument.
-
-After Python 3.11, this opcode has an argument, which indicates where the instruction occurs if non-zero:
-
-- `1` if after a call to `\\__aenter__`
-- `2` if after a call to `\\__aexit__`
-
-Example Sources:
-
-```python
-await awaitable
-```
-
-
-=== GET_AITER
-
-Python Versions: >= 3.5
-
-```
-Stack Prior: ... async_iterable
-Stack After: ... async_iterator
-```
-
-Pops the async iterable off the stack, call its `\\__aiter__` method, and push the result. Used to implement async for loops.
-
-Example Sources:
-
-```python
-# The for loop performs GET_AITER on async_iterable to get the async iterator.
-# GET_ANEXT is then called on the async iterator.
-# The object returned by GET_ANEXT is sent None,
-# and the object returned from the send operation is the next item in the async for loop.
-async for item in iterable:
- print(item)
-```
-The bytecode in 3.11 looks like this:
-```
- 6 LOAD_FAST 0 (iterable)
- 8 GET_AITER
-================= begin try block =====================
->> 10 GET_ANEXT <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<+
- 12 LOAD_CONST 0 (None) ^
->> 14 SEND 3 (to 22) ------+>>+ ^
- 16 YIELD_VALUE ^ v ^
- 18 RESUME 3 ^ v ^
- 20 JUMP_BACKWARD_NO_INTERRUPT 4 (to 14)-+ v ^
-================== end try block ===================v=^>v
->> 22 STORE_FAST 1 (item) <<<<<<<<<<+ ^ v
- 24 LOAD_GLOBAL 1 (NULL + print) ^ v
- 36 LOAD_FAST 1 (item) ^ v
- 38 PRECALL 1 ^ v
- 42 CALL 1 ^ v
- 52 POP_TOP ^ v
- 54 JUMP_BACKWARD 23 (to 10)>>>>>>>>>>>>+ v
-================== begin finally ======================<+
->> 56 END_ASYNC_FOR
-================== end finally ========================
-```
-
-
-=== GET_ANEXT
-
-Python Versions: >= 3.5
-
-```
-Stack Prior: ... awaitable_iterator
-Stack After: ... awaitable_item
-```
-
-Pops `awaitable_iterator` off the stack.
-Calls `\\__anext__` on `awaitable_iterator`.
-If the result is a coroutine or a generator coroutine, push it as is on the stack.
-Otherwise, call the result's `\\__await__` method and push that to the stack.
-Used to implement async for loops.
-
-
-Example Sources:
-
-See <> for an example.
-
-
-=== END_ASYNC_FOR
-
-Python Versions: >= 3.5, \<= 3.10
-
-```
-Stack Prior: ... async_iterable, tb1, ex1, ex_type1, tb2, ex2, ex_type2
-Stack After: ...
-```
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... async_iterable, exception
-Stack After: ...
-```
-
-Terminates an async for loop.
-
-Behavior prior to 3.11:
-
-If `ex_type2` is `StopAsyncIteration`, pop 7 values from the stack, restoring exception state from `tb1`, `ex1` and `ex_type1`.
-Otherwise, re-raise `ex2`.
-
-Behavior after 3.11:
-
-If `exception` is an instance of `StopAsyncIteration`, pop both `async_iterable` and `exception` off the stack.
-Otherwise, re-raise `exception`.
-
-Example Sources:
-
-See <> for an example.
-
-
-=== BEFORE_ASYNC_WITH
-
-Python Versions: >= 3.5
-
-```
-Stack Prior: ... async_context_manager
-Stack After: ... async_exit_function, async_enter_result
-```
-
-Pops `async_context_manager` off the stack and resolve its `\\__aexit__` and `\\__aenter__` methods.
-The `\\__aexit__` function is pushed to the stack,
-followed by the object return by calling `\\__aenter__`.
-Used to implement asynchronous context managers
-
-Example Sources:
-
-```python
-async with async_context_manager as async_context:
- pass
-```
-
-
-=== SETUP_ASYNC_WITH
-
-Python Versions: >= 3.5, \<= 3.10
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Create the `try...finally` block used for asynchronous context managers.
-
-Example Sources:
-
-```python
-async with async_context_manager as async_context:
- pass
-```
-
-
-=== PRINT_EXPR
-
-Python Versions: ALL
-
-```
-Stack Prior: ... to_print
-Stack After: ...
-```
-
-Pops off the top of the stack, calls its `\\__repr__` method, and prints the result.
-Used by the CPython interactive interpreter to print an entered expression.
-It is never emitted as an opcode in a function.
-
-Example Sources:
-
-It cannot be emitted in a function, and thus has no example sources.
-It is emitted as the final opcode when the CPython interactive interpreter compiles an expression outside a block.
-
-=== SET_ADD(i)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... s_i, ..., s_1, s_0
-Stack After: ... s_i, ..., s_1
-```
-
-Pops off the top of the stack and call `s_i.add(s_0)`.
-`s_i` remains on the stack so it can be reused.
-Used to implement set comprehensions.
-
-Example Sources:
-
-```python
-{point for point in point_list}
-```
-
-
-=== LIST_APPEND(i)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... s_i, ..., s_1, s_0
-Stack After: ... s_i, ..., s_1
-```
-
-Pops off the top of the stack and call `s_i.append(s_0)`.
-`s_i` remains on the stack so it can be reused.
-Used to implement list comprehensions.
-
-Example Sources:
-
-```python
-[point for point in point_list]
-```
-
-
-=== MAP_ADD(i)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... s_i, ..., s_1, s_0, value
-Stack After: ... s_i, ..., s_1
-```
-
-Pops off the top two items on the stack and call `s_i.\\__setitem__(s_0, value)`.
-`s_i` remains on the stack so it can be reused.
-Used to implement dict comprehensions.
-
-Example Sources:
-
-```python
-{key: value for key, value in item_list}
-```
-
-=== RETURN_VALUE
-
-Python Versions: ALL
-
-```
-Stack Prior: ... return_value
-Stack After: N/A
-```
-
-Returns the item at the top of the stack.
-
-Example Sources:
-
-```python
-def function():
- pass # A `return None` is placed at the end of the function
-```
-
-```python
-return # This is actually `return None` in disguise
-```
-
-```python
-return value
-```
-
-=== RETURN_GENERATOR
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Creates a new generator from the current frame.
-Used to implement generators.
-
-Generators basically act as two separate functions:
-
-* One outer function that just set locals and return a generator object that wraps the inner function.
-* One inner function that yield values.
-
-In this way, it is similar to returning a new anonymous class in a Java function, where we need to pass the function locals to the anonymous class.
-
-However, unlike Java, the outer function and the inner function share the same bytecode. So a generator will start with the `RETURN_GENERATOR` opcode (which returns the generator object), followed by the bytecode for the generator.
-
-JPyInterpreter treats this opcode as a no-op, since we use separate classes for the outer function and the inner functions.
-
-Example Sources:
-
-```python
-def function():
- # A RETURN_GENERATOR will be placed at the start
- # of the generator
- yield
-```
-
-
-=== GEN_START(kind)
-
-Python Versions: == 3.10
-
-```
-Stack Prior: ... top
-Stack After: ...
-```
-
-Pops off the top of stack.
-This is the first opcode for generators in 3.10.
-The stack is not empty, since calling a generator is the same as sending the generator `None`, which push `None` to the top of the stack.
-The `kind` argument indicates what kind of generator it is:
-
-- 0 is a normal generator.
-- 1 is a coroutine.
-- 2 is an async generator.
-
-Example Sources:
-
-```python
-def function():
- # A GEN_START(0) will be placed at the start
- # of the generator
- yield
-```
-
-
-=== SEND(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... subgenerator, sent_value
-Stack if subgenerator is not exhausted: ... subgenerator, yielded_value
-Stack if subgenerator is exhausted: ... subgenerator
-```
-
-Pops off the top of stack, and sends it to the sub-generator of this generator.
-If the sub-generator is not exhausted, the yielded value is pushed to the top of the stack.
-Otherwise, jump forward by `target_delta`, leaving `subgenerator` on the stack.
-Used to implement `yield from` and `await` statements.
-
-Example Sources:
-
-```python
-# yield from subgenerator is implemented as the following loop
-# (with None initially at the top of the stack)
-#
-# SEND (sends the top of stack to the subgenerator)
-# YIELD_VALUE (returns the yielded value to the caller)
-# JUMP_BACKWARDS (to SEND)
-#
-# Before the loop, GET_YIELD_FROM_ITER is used to get the generator
-# that will act as the subgenerator
-yield from subgenerator
-```
-
-```python
-# await is a yield from in disguise,
-# and is implemented by the same loop
-#
-# Before the loop, GET_AWAITABLE is used to get the awaitable
-# that will act as the subgenerator
-await awaitable
-```
-
-
-=== YIELD_VALUE
-
-Python Versions: ALL
-
-```
-Stack Prior: ... yielded_value
-Stack After: ... sent_value
-```
-
-Pops off the top of the stack and yields it to the calling function.
-The function is then paused, and is resumed by either a `.send(sent_value)` or `.throw(raised_exception)` call.
-If `.send(sent_value)` is used, that value is pushed to the top of the stack.
-Otherwise, the exception passed to `.throw(raised_exception)` is raised at this opcode position.
-Calling `next` on a generator acts as `generator.send(None)`.
-
-Example Sources:
-
-```python
-# the sent value is ignored here
-yield 10
-```
-
-```python
-# the sent value is stored in sent_value here
-sent_value = yield 10
-```
-
-
-=== YIELD_FROM
-
-Python Versions: >= 3.3, \<= 3.10
-
-```
-Stack Prior: ... subgenerator, sent_value
-Stack After: ... final_yielded_value
-```
-
-Pops off the top of the stack, and set this generator subgenerator to the element immediately below it.
-Control is then passed to the subgenerator.
-If the subgenerator is not a generator but an iterable, it is treated as the following pseudo-generator:
-
-```python
-def iterable_generator(iterable):
- for item in iterable:
- sent_value = yield item
- if sent_value is not None:
- raise AttributeError(f"'{type(iter(iterable))}' object has no attribute 'send'")
-
-```
-
-When the subgenerator is not exhausted, `send` and `throw` calls are proxied to it.
-When the subgenerator is exhausted, its final yielded value is pushed to the top of the stack and this generator resumes.
-
-In Python 3.11 and above, the YIELD_FROM opcode is replaced by a SEND + YIELD_VALUE while loop, as documented in the <>.
-
-Example Sources:
-
-```python
-yield from subgenerator
-```
-
-=== SETUP_ANNOTATIONS
-
-Python Versions: >= 3.6
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Checks if the variable `\\__annotations__` is defined.
-If `\\__annotations__` is not defined, it is initialized to an empty `dict`.
-Otherwise, `\\__annotations__` keep it current value.
-It is emitted for a class and module bodies which contain static variable annotations.
-This opcode is not emitted for function bodies.
-
-Example Sources:
-
-```python
-class MyClass:
- # SETUP_ANNOTATIONS is emitted here,
- # for a later __annotations__['x'] = int
- # call
- x: int
-```
-
-
-=== IMPORT_STAR
-
-Python Versions: ALL
-
-```
-Stack Prior: ... modulevalue
-Stack After: ...
-```
-
-Loads all symbols not starting with '_' directly from the module located at the top of the stack to the local namespace.
-The module is popped after loading all names, whose values are copied to the module's local variables.
-This opcode implements `from module import *`.
-It is illegal to use `from module import *` in a function.
-
-Example Sources:
-
-```python
-from module import *
-```
-
-
-=== POP_BLOCK
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Pops the block that store exception handler information off the stack.
-Since the JVM store the exception table separate from the bytecode, this is a no-op for JPyInterpreter.
-In CPython 3.11, the CPython interpreter also stores the exception table separate from the bytecode, removing the need for this opcode.
-
-Example Sources:
-
-```python
-try:
- something()
- # A POP_BLOCK opcode is placed
- # at the end of a try block.
-except:
- pass
-```
-
-
-=== POP_EXCEPT
-
-Python Versions: ALL
-
-Python 3.10 and below
-```
-Stack Prior: ... traceback, exception, exception_type
-Stack After: ...
-```
-
-Python 3.11 and above
-```
-Stack Prior: ... exception
-Stack After: ...
-```
-
-Pop off exception data off the stack, which is used to restore the exception state.
-Before Python 3.11, this pop off three values (traceback, exception and type(exception)).
-After Python 3.11, this pop off one value (exception).
-This is placed at the beginning of every except block
-
-Example Sources:
-
-```python
-try:
- something()
-except:
- # A POP_EXCEPT opcode is placed
- # at the beginning of an except block.
- pass
-```
-
-
-=== PUSH_EXC_INFO
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... top
-Stack After: ... exception, top
-```
-
-Inserts the currently active exception behind the item currently at the top of stack.
-Used to allow the current exception to be stored if an except block uses it.
-
-Example Sources:
-
-```python
-try:
- pass
-
-# A PUSH_EXC_INFO is emitted at the start of the
-# try block exception handler, which goes through
-# a series of conditional jumps to determine which
-# except block to enter.
-# The except block then decide if they should store
-# the current exception, or pop it off the stack.
-except ValueError as e:
- pass
-except Exception:
- pass
-```
-
-
-=== CHECK_EXC_MATCH
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... exception, exception_type
-Stack After: ... exception, test_result
-```
-
-Test if `exception` is an instance of `exception_type`.
-If so, it pushes `True` to the top of stack; otherwise, it pushes `False`.
-`exception_type` is popped off the stack; `exception` remains on the stack.
-Used to implement `except` blocks that catch particular types of exceptions.
-
-Example Sources:
-
-```python
-try:
- pass
-except ValueError: # CHECK_EXC_MATCH is used here with
- # exception and ValueError
- # on the stack.
- pass
-```
-
-
-=== RERAISE(set_f_lasti)
-
-Python Versions: >= 3.9
-
-If `set_f_lasti` is not set
-```
-Stack Prior: ... exception_or_type
-Stack After: N/A
-```
-
-If `set_f_lasti` is set
-```
-Stack Prior: ... index, exception_or_type
-Stack After: N/A
-```
-
-The item at the top of the stack is either an exception or type.
-If it is an exception, throw it.
-If it is a type, construct and throw a new instance of that type.
-Used to implement a bare `raise` in an except block.
-
-Note: CPython uses the `index` below the exception/type to set the last index if the bytecode argument not 0.
-JPyInterpreter can ignore the argument, since the JVM keep track of frames for us.
-
-Example Sources:
-
-```python
-try:
- pass
-except:
- raise # this emits RERAISE
-```
-
-
-=== WITH_EXCEPT_START
-
-Python Versions: >= 3.9
-
-Before 3.11
-```
-Stack Prior: ... exit_function, instruction, stack_size, label, traceback, exception, exception_type
-Stack After: N/A
-```
-
-After 3.11
-```
-Stack Prior: ... exit_function, traceback, exception, exception_type
-Stack After: N/A
-```
-
-Calls `exit_function` with arguments `exception_type, exception, traceback`, and push the returned value to the top of the stack.
-The returned value should be a boolean.
-If the returned value is Truthy, the context manager handled the exception and execution continue.
-If the returned value is Falsy, the exception is propagated.
-If no exception occurred, exception_type, exception, traceback are all None.
-
-
-Example Sources:
-
-```python
-with context:
- pass
-```
-
-
-=== LOAD_ASSERTION_ERROR
-
-Python Versions: >= 3.9
-
-```
-Stack Prior: ...
-Stack After: ... AssertionError
-```
-
-Pushes the type `AssertionError` onto the stack.
-Used in `assert` statements.
-
-Example Sources:
-
-```python
-assert False
-```
-
-
-=== LOAD_BUILD_CLASS
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ... __build_class__
-```
-
-Pushes the function `builtins.\\__build_class__` onto the stack.
-Used to construct classes.
-The function signature for `\\__build_class__` is:
-
-```python
-def __build_class__(class_body: function,
- class_name: str,
- *bases: List[Type],
- metaclass: Type,
- **metaclass_parameters: Dict[str, Any]) \
- -> Type
-```
-
-Example Sources:
-
-```python
-class C:
- pass
-
-# this translates roughly to:
-# __build_class__(, 'C')
-```
-
-```python
-class C(A, B):
- pass
-
-# this translates roughly to:
-# __build_class__(, 'C', A, B)
-```
-
-```python
-class C(A, metaclass=M, metaclass_arg=1):
- pass
-
-# this translates roughly to:
-# __build_class__(, 'C', A, metaclass=M, metaclass_arg=1)
-```
-
-
-=== SETUP_WITH(except_delta)
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... context_manager
-Stack After: ... exit_function, start_function_result
-Stack On Exception: ... instruction, stack_size, label, traceback, exception, exception_type
-```
-
-Pops off the top of the stack, and push its `\\__exit__` function and the result of calling its `\\__enter__` function to the top of the stack.
-`except_delta` points to the exception handler for the which block.
-If an exception occurs, the follow items will be pushed to the stack:
-
-. The bytecode instruction index that was executing when the exception happened.
-
-. The size of the stack before the with block.
-
-. The exception handler label.
-
-. The traceback for the exception.
-
-. The actual exception.
-
-. The type of the exception.
-
-Example Sources:
-
-```python
-with context_manager:
- pass
-```
-
-
-=== STORE_NAME(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... value
-Stack After: ...
-```
-
-Sets either the global or local variable with the name `co_names[namei]` to the item currently at the top of stack.
-The top of stack is then popped.
-This opcode is only emitted for module bodies and classes.
-
-Example Sources:
-
-```python
-class C:
- x = 10 # this emits a STORE_NAME('x') opcode
- # with 10 on the top of the stack
-```
-
-
-=== DELETE_NAME(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Deletes either the global or local variable with the name `co_names[namei]`.
-This opcode is only emitted for module bodies and classes.
-
-Example Sources:
-
-```python
-class C:
- x = 10
- del x # this emits a DELETE_NAME('x') opcode
-```
-
-=== UNPACK_SEQUENCE(count)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... iterable
-Stack After: ... item_{count - 1}, ..., item_1, item_0
-```
-
-Top of stack is an iterable.
-In reverse order, push its items to the stack (making the new item at the top of stack the first item in the iterable).
-The iterable is then popped off the stack.
-If the iterable does not have exactly `count` items, a `ValueError` is raised.
-The items are received using an iterator loop:
-
-```python
-iterator = iter(iterable)
-items = []
-while True:
- try:
- items.append(next(iterator))
- except StopIteration:
- break
-
-```
-
-Example Sources:
-
-```python
-# This is compiled as:
-# UNPACK_SEQUENCE(2)
-# STORE_FAST('x') (1)
-# STORE_FAST('y') (2)
-x, y = (1, 2)
-```
-
-
-=== UNPACK_EX((high byte) end_index | (low byte) start_index)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... iterable
-Stack After: ... after_0, after_1, ..., after_{end_index - 1}, extra, before_{start_index - 1}, ..., before_1, before_0
-```
-
-Top of stack is an iterable.
-Collect its item into a list.
-Push each item in the slice [-end_index:] to the stack in forward order (empty if end_index == 0).
-Push a list containing the slice [start_index:end_index] to the stack as a single item.
-Push each item in the slice [:start_index] in reverse order (empty if start_index == 0).
-The iterable is then popped off the stack.
-If the iterable does not have at least `start_index + end_index` items, a `ValueError` is raised.
-The items are received using an iterator loop:
-
-```python
-iterator = iter(iterable)
-items = []
-while True:
- try:
- items.append(next(iterator))
- except StopIteration:
- break
-
-before = items[:start_index]
-after = items[-end_index:]
-extra = items[start_index:end_index]
-```
-
-Example Sources:
-
-```python
-# This is compiled as:
-# UNPACK_EX((2 << 8) | 1) (= 513)
-# STORE_FAST('b_0') (1)
-# STORE_FAST('extra') ([2, 3])
-# STORE_FAST('a_0') (4)
-# STORE_FAST('a_1') (5)
-b_0, *extra, a_0, a_1 = (1, 2, 3, 4, 5)
-```
-
-
-=== STORE_ATTR(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... value, object
-Stack After: ...
-```
-
-Sets the attribute with the name `co_names[namei]` on the object at the top of the stack to the value immediately below it.
-Both the object and the value are popped.
-The value is set by calling the `\\__setattr__(self, name: str, value: Any)` method on the type of object with `object`, `co_names[namei]` and `value` as the arguments.
-
-Example Sources:
-
-```python
-# equivalent to
-# type(my_object).__setattr__(my_object, 'attribute', value)
-my_object.attribute = value
-```
-
-
-=== DELETE_ATTR(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... object
-Stack After: ...
-```
-
-Deletes the attribute with the name `co_names[namei]` on the object at the top of the stack.
-The object is then popped off the stack.
-The value is deleted by calling the `\\__delattr__(self, name: str)` method on the type of object with `object` and `co_names[namei]` as the arguments.
-
-Example Sources:
-
-```python
-# equivalent to
-# type(my_object).__delattr__(my_object, 'attribute')
-del my_object.attribute
-```
-
-
-=== STORE_GLOBAL(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... value
-Stack After: ...
-```
-
-Sets the global variable with the name `co_names[namei]` to the value currently at the top of the stack.
-The value is then popped from the stack.
-Each module has a unique global namespace used to store global variables.
-Functions in the same module use the same namespace.
-
-Example Sources:
-
-```python
-# required, otherwise it be a STORE_FAST
-global variable
-variable = 5
-```
-
-
-=== DELETE_GLOBAL(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Deletes the global variable with the name `co_names[namei]`.
-Each module has a unique global namespace used to store global variables.
-Functions in the same module use the same namespace.
-
-Example Sources:
-
-```python
-# required, otherwise it be a DELETE_FAST
-global variable
-del variable
-```
-
-
-=== LOAD_CONST(consti)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ... constant
-```
-
-Loads the constant `co_constants[consti]`.
-
-Example Sources:
-
-```python
-'A string constant'
-```
-
-```python
-1 # an int constant
-```
-
-```python
-(1, 2, 3) # a tuple constant
-```
-
-
-=== LOAD_NAME(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ... value
-```
-
-Pushes either the global or local variable with the name `co_names[namei]` to the top of stack.
-This opcode is only emitted for module bodies and classes.
-
-Example Sources:
-
-```python
-class C:
- x # this emits a LOAD_NAME('x') opcode
-```
-
-
-=== BUILD_TUPLE(count)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... item_0, item_1, ..., item_{count - 1}
-Stack After: ... item_tuple
-```
-
-Construct a tuple from the top `count` items on the stack.
-The items are placed in the reverse order that they are encountered from the top of stack (making the top of stack the last element).
-The top `count` items are then popped from the stack, and the newly constructed tuple is pushed to the stack.
-
-Example Sources:
-
-```python
-x = 1
-y = 2
-z = (x, y) # This creates a BUILD_TUPLE opcode:
-# LOAD_FAST('x')
-# LOAD_FAST('y')
-# BUILD_TUPLE(2)
-```
-
-
-=== BUILD_LIST(count)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... item_0, item_1, ..., item_{count - 1}
-Stack After: ... item_tuple
-```
-
-Construct a list from the top `count` items on the stack.
-The items are placed in the reverse order that they are encountered from the top of stack (making the top of stack the last element).
-The top `count` items are then popped from the stack, and the newly constructed list is pushed to the stack.
-
-Example Sources:
-
-```python
-x = 1
-y = 2
-z = [x, y] # This creates a BUILD_LIST opcode:
-# LOAD_FAST('x')
-# LOAD_FAST('y')
-# BUILD_LIST(2)
-```
-
-
-=== BUILD_SET(count)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... item_0, item_1, ..., item_{count - 1}
-Stack After: ... item_tuple
-```
-
-Construct a set from the top `count` items on the stack.
-The items are placed in the reverse order that they are encountered from the top of stack (making the top of stack the last element).
-The top `count` items are then popped from the stack, and the newly constructed set is pushed to the stack.
-The items lower in the stack are prioritized over items higher in stack (i.e. if `item_0 == item_1`, then `item_0` be added to the set, not `item_1`).
-
-Example Sources:
-
-```python
-x = 1
-y = 2
-z = {x, y} # This creates a BUILD_SET opcode:
-# LOAD_FAST('x')
-# LOAD_FAST('y')
-# BUILD_SET(2)
-```
-
-
-=== BUILD_MAP(count)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... , key_0, value_0, key_1, value_1, ..., key_{count - 1}, value_{count - 1}
-Stack After: ... item_map
-```
-
-Construct a dict from the top `2 * count` items on the stack.
-The items are put in the reverse order that they are encountered from the top of stack (making the top two items on the stack the last key-value pair).
-The top `2 * count` items are then popped from the stack, and the newly constructed dict is pushed to the stack.
-The items higher in the stack are prioritized over items higher in stack (i.e. if `key_0 == key_1`, then `key_1 = value_1` be put in the dict, not `key_0 = value_0`).
-
-Example Sources:
-
-```python
-key_0 = 1
-value_0 = 2
-key_1 = 3
-value_1 = 4
-z = {
- key_0: value_0,
- key_1: value_1
-}
-# This creates a BUILD_MAP opcode:
-# LOAD_FAST('key_0')
-# LOAD_FAST('value_0')
-# LOAD_FAST('key_1')
-# LOAD_FAST('value_1')
-# BUILD_MAP(2)
-```
-
-
-=== BUILD_CONST_KEY_MAP(count)
-
-Python Versions: >= 3.6
-
-```
-Stack Prior: ... , value_0, value_1, ..., value_{count - 1}, key_tuple
-Stack After: ... item_map
-```
-
-Construct a dict from the top `count + 1` items on the stack.
-The item at the top of the stack is a tuple of constants of length count, which stores the dict's keys.
-There are `count` items below it representing each key's corresponding value.
-The key-value pairs are put in the reverse order that they are encountered from the top of stack (making `key_tuple[-1], value_{count - 1}` the last key-value pair to be added to the dict).
-The top `count + 1` items are then popped from the stack, and the newly constructed dict is pushed to the stack.
-The items higher in the stack are prioritized over items higher in stack (i.e. if `tuple[0] == tuple[1]`, then `tuple[1] = value_1` be put in the dict, not `tuple[0] = value_0`).
-
-Example Sources:
-
-```python
-value_0 = 1
-value_1 = 2
-z = {
- 'a': value_0,
- 'b': value_1
-}
-# This creates a BUILD_CONST_KEY_MAP opcode:
-# LOAD_FAST('value_0')
-# LOAD_FAST('value_1')
-# LOAD_CONSTANT (('a', 'b'))
-# BUILD_CONST_KEY_MAP(2)
-```
-
-
-=== BUILD_STRING(count)
-
-Python Versions: >= 3.6
-
-```
-Stack Prior: ... string_0, string_1, ..., string_{count - 1}
-Stack After: ... result
-```
-
-Concatenate the top `count` items on the stack into a single string.
-Each of the top `count` items on the stack must be a string.
-The strings are concatenated from the lowest item up
-(i.e. `string_0 + string_1 + ... + string_{count - 1}`).
-Used to implement f-strings.
-
-Example Sources:
-
-```python
-a = 'before'
-b = 'after'
-f'{a} {b}'
-# Bytecode:
-# LOAD_FAST(a)
-# FORMAT_VALUE(str)
-# LOAD_CONST(' ')
-# LOAD_FAST(b)
-# FORMAT_VALUE(str)
-# BUILD_STRING(3)
-```
-
-
-=== LIST_TO_TUPLE
-
-Python Versions: >= 3.9
-
-```
-Stack Prior: ... list
-Stack After: ... tuple
-```
-
-The top of the stack is a list.
-Pop off the top of the stack, and replace it with a tuple with the same values in the same order.
-Used to unpack a list into a tuple.
-
-Example Sources:
-
-```python
-(*[1, 2, 3],)
-#
-# BUILD_LIST(0) # Construct an empty list
-# to store the final result
-#
-# BUILD_LIST(0) # Construct an empty list
-# # to store the immediate [1, 2, 3]
-# # since lists cannot be constants
-#
-# LOAD_CONST((1, 2, 3)) # Load the constant (1, 2, 3)
-#
-# LIST_EXTEND(1) # Convert the constant (1, 2, 3)
-# to [1, 2, 3]
-#
-# LIST_EXTEND(1) # Unpacks [1, 2, 3] into the
-# # final result
-#
-# LIST_TO_TUPLE # Convert the final result into a tuple
-```
-
-
-=== LIST_EXTEND(i)
-
-Python Versions: >= 3.9
-
-```
-Stack Prior: ... s_i, ..., s_1, s_0
-Stack After: ... s_i, ..., s_1
-```
-
-The top of the stack is an iterable and `s_i` is a list.
-Pop off the top of the stack, and add its contents to `s_i`.
-`s_i` remains on the stack so it can be reused.
-Used to implement list unpacking.
-
-Example Sources:
-
-See <>.
-
-
-=== SET_UPDATE(i)
-
-Python Versions: >= 3.9
-
-```
-Stack Prior: ... s_i, ..., s_1, s_0
-Stack After: ... s_i, ..., s_1
-```
-
-The top of the stack is an iterable and `s_i` is a set.
-Pop off the top of the stack, and add its contents to `s_i`.
-The added content will not replace items already in the `set`.
-`s_i` remains on the stack so it can be reused.
-Used to implement set unpacking.
-
-
-Example Sources:
-
-```python
-{*(1, 2, 3)}
-# BUILD_SET(0) # Create an empty set to
-# # store the result
-#
-# LOAD_CONST((1, 2, 3)) # Load the constant (1, 2, 3)
-#
-# SET_UPDATE(1) # Unpacks (1, 2, 3) into the result
-```
-
-
-=== DICT_UPDATE(i)
-
-Python Versions: >= 3.9
-
-```
-Stack Prior: ... s_i, ..., s_1, s_0
-Stack After: ... s_i, ..., s_1
-```
-
-The top of the stack is an mapping and `s_i` is a dict.
-Pop off the top of the stack, and add its contents to `s_i`.
-The added content will replace the value assigned to keys already in the `dict`.
-`s_i` remains on the stack so it can be reused.
-Used to implement dict unpacking.
-
-
-Example Sources:
-
-```python
-{
- 'a': 1,
- **b
-}
-# LOAD_CONSTANT('a')
-# LOAD_CONSTANT(1)
-#
-# BUILD_MAP(1) # Create a dict with items
-# # ('a', 1)
-#
-# LOAD_FAST(n) # Load b
-#
-# DICT_UPDATE(1) # Unpacks b into the result dict
-```
-
-
-=== DICT_MERGE(i)
-
-Python Versions: >= 3.9
-
-```
-Stack Prior: ... s_i, ..., s_1, s_0
-Stack After: ... s_i, ..., s_1
-```
-
-The top of the stack is an mapping and `s_i` is a dict.
-Pop off the top of the stack, and add its contents to `s_i`.
-If the mapping at the top of the stack share any keys with `s_i`, a `TypeError` is raised.
-`s_i` remains on the stack so it can be reused.
-Used to implement dict unpacking in function calls.
-
-
-Example Sources:
-
-```python
-my_function(a=1, **b)
-# LOAD_CONSTANT('a')
-# LOAD_CONSTANT(1)
-#
-# BUILD_MAP(1) # Create a dict with items
-# # ('a', 1)
-#
-# LOAD_FAST(n) # Load b
-#
-# DICT_MERGE(1) # Unpacks b into the result dict,
- # raise an exception if b has a value
- # for the key 'a'
-```
-
-
-=== LOAD_ATTR(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... object
-Stack After: ... attribute
-```
-
-Loads the attribute with the name `co_names[namei]` on the object at the top of the stack; the top of stack is popped.
-The value is retrieved by calling the `\\__getattribute__(self, name: str)` method on the type of object with `object` and `co_names[namei]` as the arguments.
-
-Example Sources:
-
-```python
-# equivalent to
-# type(my_object).__getattribute__(my_object, 'attribute')
-my_object.attribute
-```
-
-
-=== COMPARE_OP(op)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... left_comparable, right_comparable
-Stack After: ... comparison_result
-```
-
-A <> that correspond to the comparison operation indicated by the `op` argument.
-The comparison operation that `op` refers to is `cmp_op[op]` (where `cmp_op` is https://github.com/python/cpython/blob/174c4bfd0fee4622657a604af7a2e7d20a3f0dbc/Lib/opcode.py#L24[defined here]). In particular:
-
-- 0 corresponds to `\\__lt__` (normal) and `\\__gt__` (reflected)
-- 1 corresponds to `\\__le__` (normal) and `\\__ge__` (reflected)
-- 2 corresponds to `\\__eq__` (normal) and `\\__eq__` (reflected)
-- 3 corresponds to `\\__ne__` (normal) and `\\__ne__` (reflected)
-- 4 corresponds to `\\__gt__` (normal) and `\\__lt__` (reflected)
-- 5 corresponds to `\\__ge__` (normal) and `\\__le__` (reflected)
-
-The top two items on the top of the stack are popped, the comparison operation is performed, and the result (not necessary a boolean) is pushed to the top of the stack.
-
-Example Sources:
-
-```python
-left_comparable < right_comparable
-```
-
-```python
-left_comparable == right_comparable
-```
-
-
-=== IS_OP(invert)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... left, right
-Stack After: ... is_same
-```
-
-Pop off the top two items on the stack.
-Push `True` if the two items refer to the same reference, `False` otherwise.
-If `invert == 1`, then the result is negated.
-
-
-Example Sources:
-
-```python
-left = []
-right = []
-left is right # False
-```
-
-```python
-left = []
-right = left
-left is right # True
-```
-
-```python
-left is not right
-```
-
-=== CONTAINS_OP(invert)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... query, container
-Stack After: ... is_contained
-```
-
-Pop the two top items off the stack.
-The top item is the `container`, and the item immediately below it is the `query`.
-If `container` has a `\\__contain__(self, object)` method, it is called, and its result is converted to a boolean value (i.e. `None` is converted to `True`).
-Otherwise, an iterator is obtained by calling the `\\__iter__` method on `container`.
-If the iterator returns an object equal to `query`, `True` is pushed to the stack.
-If the iterator get exhausted before that, `False` is pushed to the stack.
-If the iterator is infinite and does not contain `query`, an infinite loop occurs.
-If `invert == 1`, then the result is negated.
-
-Example Sources:
-
-```python
-1 in (1, 2, 3)
-```
-
-```python
-1 not in (1, 2, 3)
-```
-
-
-=== IMPORT_NAME(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... level, from_list
-Stack After: ... module
-```
-
-Calls the https://docs.python.org/3/library/functions.html#import__[\_import_] builtin function with the arguments `co_names[namei]`, `globals()`, `locals()`, `from_list` and `level`.
-The top two elements of the stack are popped, and the imported module is pushed.
-`from_list` can either be `None` or a list of strings containing names to import from the module.
-`level` indicates if the import is absolute or relative.
-If `level` is `0`, then it is an absolute import (the default).
-Otherwise, `level` indicates how many parents directories need to be navigated to perform the relative import (for instance, `1` is same directory as the current module, `2` is parent directory of the current module, `3` is the parent of the parent directory).
-The namespace is not modified; that is done by a subsequent <> instruction(s).
-
-Example Sources:
-
-```python
-import module
-```
-
-```python
-from module import a, b, c
-```
-
-
-
-=== IMPORT_FROM(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... module
-Stack After: ... module, attribute
-```
-
-Loads the attribute with the name `co_names[namei]` from the module that is on the top of the stack.
-The top of stack is not popped, and the loaded attribute is pushed to the top of the stack.
-The namespace is not modified; that is done by a subsequent <> instruction(s).
-
-Example Sources:
-
-```python
-from module import a, b, c
-```
-
-
-=== JUMP_FORWARD(target_delta)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Performs a forced relative jump forward by `target_delta` addresses (see <> for details).
-Used to implement skipping unentered blocks in `if...elif...else` blocks and skipping exception handlers in `try...except...finally` blocks.
-
-Example Sources:
-
-```python
-if cond:
- x = 1
- # a JUMP_FORWARD is put here
- # to skip the else
-else:
- x = 2
-return x * 2
-```
-
-
-=== JUMP_BACKWARD(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Performs a forced relative jump backwards by `target_delta` addresses (see <> for details).
-CPython checks for interrupts during this instruction.
-Used to implement `for` and `while True` loops.
-
-Example Sources:
-
-```python
-for item in iterable:
- pass
- # a JUMP_BACKWARD is put here
- # to jump back to the start of
- # the FOR_ITER instruction
- # (which ends the loop if the
- # iterator is exhausted)
-```
-
-```python
-while True:
- pass
- # a JUMP_BACKWARD is put here
- # to jump back to the start of
- # the while block
-```
-
-
-=== JUMP_BACKWARD_NO_INTERRUPT(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Performs a forced relative jump backwards by `target_delta` addresses (see <> for details).
-CPython does not checks for interrupts during this instruction.
-Used to implement `yield from` statements.
-
-Example Sources:
-
-```python
-yield from generator
-# A JUMP_BACKWARD_NO_INTERRUPT is used to
-# jump back to the SEND opcode (which will
-# break out of the loop when the generator
-# is exhausted).
-```
-
-
-=== POP_JUMP_IF_TRUE(target)
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... condition
-Stack After: ...
-```
-
-If `condition` is truthy, jump to `target`, which represents an absolute address (see <> for details).
-Used to implement going to the next block when there a negated condition in an `if...elif...else` chain or start of a `while` loop.
-
-Example Sources:
-
-```python
-if not cond: # A POP_JUMP_IF_TRUE
- # is put here to jump
- # to else if cond is truthy
- print('case 1')
-else:
- print('case 2')
-```
-
-```python
-while not cond: # A POP_JUMP_IF_TRUE
- # is put here to skip
- # the loop if cond is
- # truthy
- pass
-```
-
-
-=== POP_JUMP_FORWARD_IF_TRUE(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... condition
-Stack After: ...
-```
-
-If `condition` is truthy, jump forward by `target_delta`, which represents a relative addresses (see <> for details).
-Used to implement going to the next block when there a negated condition in an `if...elif...else` chain.
-
-Example Sources:
-
-```python
-if not cond: # A POP_JUMP_FORWARD_IF_TRUE
- # is put here to jump to else
- # if cond is truthy
- print('case 1')
-else:
- print('case 2')
-```
-
-```python
-while not cond: # A POP_JUMP_FORWARD_IF_TRUE
- # is put here to skip
- # the loop if cond is
- # truthy
- pass
-```
-
-
-=== POP_JUMP_BACKWARD_IF_TRUE(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... condition
-Stack After: ...
-```
-
-If `condition` is truthy, jump backward by `target_delta`, which represents a relative addresses (see <> for details).
-Used to implement looping in a `while` loop.
-
-Example Sources:
-
-```python
-while cond:
- pass
- # A POP_JUMP_BACKWARD_IF_TRUE is put here
- # with a test on cond
-```
-
-
-=== POP_JUMP_IF_FALSE(target)
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... condition
-Stack After: ...
-```
-
-If `condition` is falsely, jump to `target`, which represents an absolute addresses (see <> for details).
-Used to implement going to the next block when there a positive condition in an `if...elif...else` chain.
-
-Example Sources:
-
-```python
-if cond: # A POP_JUMP_IF_FALSE is
- # put here to jump to else
- # else if cond is falsely
- print('case 1')
-else:
- print('case 2')
-```
-
-```python
-while cond: # A POP_JUMP_IF_FALSE
- # is put here to skip
- # the loop if cond is
- # falsely
- pass
-```
-
-=== POP_JUMP_FORWARD_IF_FALSE(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... condition
-Stack After: ...
-```
-
-If `condition` is falsely, jump forward by `target_delta`, which represents a relative addresses (see <> for details).
-Used to implement going to the next block when there a positive condition in an `if...elif...else` chain.
-
-Example Sources:
-
-```python
-if cond: # A POP_JUMP_IF_FALSE is
- # put here to jump to else
- # else if cond is falsely
- print('case 1')
-else:
- print('case 2')
-```
-
-```python
-while cond: # A POP_JUMP_IF_FALSE
- # is put here to skip
- # the loop if cond is
- # falsely
- pass
-```
-
-
-=== POP_JUMP_BACKWARD_IF_FALSE(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... condition
-Stack After: ...
-```
-
-If `condition` is falsely, jump backward by `target_delta`, which represents a relative addresses (see <> for details).
-Used to implement looping in a negated `while` loop.
-
-Example Sources:
-
-```python
-while not cond:
- pass
- # A POP_JUMP_BACKWARD_IF_FALSE is put here
- # with a test on cond
-```
-
-
-=== POP_JUMP_FORWARD_IF_NOT_NONE(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... item
-Stack After: ...
-```
-
-If `item` is not None, jump forward by `target_delta`, which represents a relative addresses (see <> for details).
-Used to implement going to the next block when there a `is None` condition in an `if...elif...else` chain.
-
-Example Sources:
-
-```python
-if item is None: # POP_JUMP_FORWARD_IF_NOT_NONE
- # is put here to jump to else
- # if item is not None
- print('case 1')
-else:
- print('case 2')
-```
-
-```python
-# POP_JUMP_FORWARD_IF_NOT_NONE
-# is put here to skip
-# the loop if cond is
-# truthy
-while item is None:
-
- pass
-```
-
-
-=== POP_JUMP_BACKWARD_IF_NOT_NONE(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... item
-Stack After: ...
-```
-
-If `condition` is falsely, jump backward by `target_delta`, which represents a relative addresses (see <> for details).
-Used to implement looping in a `while item is not None` loop.
-
-Example Sources:
-
-```python
-while item is not None:
- pass
- # A POP_JUMP_BACKWARD_IF_NOT_NONE
- # is put here with a test on item
-```
-
-
-=== POP_JUMP_FORWARD_IF_NONE(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... item
-Stack After: ...
-```
-
-If `item` is None, jump forward by `target_delta`, which represents a relative addresses (see <> for details).
-Used to implement going to the next block when there a `is not None` condition in an `if...elif...else` chain.
-
-Example Sources:
-
-```python
-if item is not None: # POP_JUMP_FORWARD_IF_NONE
- # is put here to jump to else
- # if item is not None
- print('case 1')
-else:
- print('case 2')
-```
-
-```python
-# POP_JUMP_FORWARD_IF_NONE
-# is put here to skip
-# the loop if cond is
-# truthy
-while item is not None:
-
- pass
-```
-
-
-=== POP_JUMP_BACKWARD_IF_NONE(target_delta)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ... item
-Stack After: ...
-```
-
-If `condition` is falsely, jump backward by `target_delta`, which represents a relative addresses (see <> for details).
-Used to implement looping in a `while item is None` loop.
-
-Example Sources:
-
-```python
-while item is None:
- pass
- # A POP_JUMP_BACKWARD_IF_NONE
- # is put here with a test on item
-```
-
-
-=== JUMP_IF_NOT_EXC_MATCH(target)
-
-Python Versions: >= 3.9, \<= 3.10
-
-```
-Stack Prior: ... exception_type, test_type
-Stack After: ...
-```
-
-If `exception_type` is not a subclass of `test_type`, jump to `target`, which represents an absolute address (see <> for details).
-Used to determine which except block to enter.
-
-Example Sources:
-
-```python
-try:
- pass
-except ValueError as e:
- # JUMP_IF_NOT_EXC_MATCH is used here
- # with type(e), ValueError on the stack
- pass
-```
-
-
-=== JUMP_IF_TRUE_OR_POP(target)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... item
-Stack After if truthy: ... item
-Stack After if falsely: ...
-```
-
-If `item` is truthy, jump to `target` and keep `item` on the stack.
-Otherwise, pop `item` from the stack.
-
-IMPORTANT: In Python 3.10 and below, `target` is an absolute address. In Python 3.11 and above, `target` is a relative address (see <> for details).
-
-Used to implement `or`.
-
-Example Sources:
-
-```python
-# if a is truthy, b is not evaluated at all
-# since JUMP_IF_TRUE_OR_POP jumps past it
-# as such, after this statement,
-# the stack is either:
-# a, if a is truthy
-# b, if a is falsely
-a or b
-```
-
-
-=== JUMP_IF_FALSE_OR_POP(target)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... item
-Stack After if truthy: ... item
-Stack After if falsely: ...
-```
-
-If `item` is falsely, jump to `target` and keep `item` on the stack.
-Otherwise, pop `item` from the stack.
-
-IMPORTANT: In Python 3.10 and below, `target` is an absolute address. In Python 3.11 and above, `target` is a relative address (see <> for details).
-
-Used to implement `and`.
-
-Example Sources:
-
-```python
-# if a is falsely, b is not evaluated at all
-# since JUMP_IF_FALSE_OR_POP jumps past it
-# as such, after this statement,
-# the stack is either:
-# a, if a is falsely
-# b, if a is truthy
-a and b
-```
-
-
-=== JUMP_ABSOLUTE(target)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Jump to `target`, which represents an absolute address (see <> for details).
-Used to implement looping in `for` and `while` loops.
-
-Example Sources:
-
-```python
-for item in iterable:
- pass
- # a JUMP_ABSOLUTE to FOR_ITER is placed here
-```
-
-```python
-while True:
- pass
- # a JUMP_ABSOLUTE to place here
-```
-
-
-=== FOR_ITER(target_delta)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... iterator
-Stack After if not exhausted: ... iterator item
-Stack After if exhausted: ...
-```
-
-If the iterator at the top of the stack is exhausted, jump forward by `target_delta`, which represents a relative addresses (see <> for details) and pop iterator off the stack.
-Otherwise, keep iterator on the stack, and push its next item (obtained by calling `iterator.\\__next__()`) to the top of the stack.
-
-In Python code, it looks like this:
-
-```python
-while True:
- try:
- item = next(iterator)
- except StopIteration:
- break
- # ... The for block
-```
-
-Used to implement `for` loops.
-
-Example Sources:
-
-```python
-for item in iterable:
- pass
-```
-
-
-=== LOAD_GLOBAL(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After (1): ... global
-Stack After (2): ... NULL, global
-```
-
-Prior 3.11:
-
-Push the global variable with the name `co_names[namei]` to the top of the stack.
-
-After 3.11:
-
-Push the global variable with the name `co_names[namei >> 1]` to the top of the stack. If `namei & 1` is set, push `NULL` before the global variable.
-
-Used to read global variables.
-
-Example Sources:
-
-```python
-global variable
-# NULL will not be pushed here after 3.11
-variable
-```
-
-```python
-global function
-# NULL will be pushed here after 3.11
-function(1,2,3)
-```
-
-
-=== SETUP_FINALLY(target_delta)
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ...
-Stack After: ...
-Stack On Exception: ... instruction, stack_size, label, traceback, exception, exception_type
-```
-
-Creates a try block whose handler is at the given `target_delta` relative address (see <> for details).
-The try block starts at this instruction, and ends at the start of its handler.
-When an exception occurs, the stack prior to the `SETUP_FINALLY` is restored, and the following is pushed to the stack:
-
-- The instruction index that created the block (i.e. this `SETUP_FINALLY` address)
-- The stack depth at the time the block was created
-- The exception handler start address
-- The traceback for the exception
-- The exception itself
-- The type of the exception
-
-Used to implement try blocks.
-
-Example Sources:
-
-```python
-try:
- # A SETUP_FINALLY is emitted here, which
- # points to the except block
- pass
-except:
- pass
-```
-
-
-=== LOAD_FAST(var_num)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ... local
-```
-
-Push the local variable with the name `co_varnames[var_num]` to the top of the stack.
-Used to read local variables.
-
-Example Sources:
-
-```python
-variable
-```
-
-
-=== STORE_FAST(var_num)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... value
-Stack After: ...
-```
-
-Pops off the top item on the stack and sets the local variable with the name `co_varnames[var_num]` to it.
-Used to set local variables.
-
-Example Sources:
-
-```python
-variable = value
-```
-
-
-=== DELETE_FAST(var_num)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Deletes the local variable with the name `co_varnames[var_num]`.
-Used to implement `del variable`.
-
-Example Sources:
-
-```python
-del variable
-```
-
-
-=== MAKE_CELL(i)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Creates a new cell in slot `i`. If that slot is not empty then that value is stored into the new cell.
-Used to initialize cell variables.
-This is a NOP for JPyInterpreter, which initializes cell variables at function definition.
-
-Example Sources:
-
-```python
-def outer_function():
- # MAKE_CELL will be emitted here for a,
- # since it is used in inner_function
- a = 10
- def inner_function():
- nonlocal a
- print(a)
-```
-
-```python
-def outer_function(a):
- # MAKE_CELL will be emitted here for a,
- # since it is used in inner_function
- def inner_function():
- nonlocal a
- print(a)
-```
-
-
-=== COPY_FREE_VARS(n)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Copies the `n` free variables from the closure into the frame.
-Removes the need for special code on the caller’s side when calling closures.
-This is a NOP for JPyInterpreter, which initializes free variables at function definition.
-
-Example Sources:
-
-```python
-def outer_function():
- a = 10
- def inner_function():
- # COPY_FREE_VARS(1) is emitted here
- nonlocal a
- print(a)
-```
-
-```python
-def outer_function(a):
- def inner_function():
- # COPY_FREE_VARS(1) is emitted here
- nonlocal a
- print(a)
-```
-
-
-=== LOAD_CLOSURE(i)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ... cell
-```
-
-Loads the cell (not its value) in slot `i` as described by <<_cell_variable_index>>.
-A cell corresponds to either a shared or free variable.
-Used to pass shared variables from an outer function to an inner function (where they be free variables).
-
-Example Sources:
-
-```python
-def outer():
- x = 10
- # LOAD_CLOSURE(x) is generated here
- # so x's cell can be put into a tuple
- # that is passed to inner's MAKE_FUNCTION
- # (allowing inner to access it).
- def inner():
- nonlocal x
- return x
-```
-
-
-=== LOAD_DEREF(i)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ... cell_value
-```
-
-Loads the value contained in the cell at slot `i` as described by <<_cell_variable_index>>.
-A cell corresponds to either a shared or free variable.
-Used to read shared and free variables.
-
-Example Sources:
-
-```python
-def outer():
- x = 10
- print(x) # LOAD_DEREF(x) is used here
- # since x is used in inner
- def inner():
- nonlocal x
- # ...
-```
-
-```python
-def outer():
- x = 10
- def inner():
- nonlocal x
- print(x) # LOAD_DEREF(x) is used here
- # since x is a free variable
-```
-
-
-=== LOAD_CLASSDEREF(i)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ... cell_value
-```
-
-If locals has a variable corresponding to the name of slot `i`, push its value.
-Otherwise, push the value contained in the cell at slot `i` as described by <<_cell_variable_index>>.
-A cell corresponds to either a shared or free variable.
-Used to read shared and free variables in class bodies.
-
-Example Sources:
-
-```python
-def outer():
- x = 10
- class InnerClass:
- my_value = x # LOAD_CLASSDEREF(x) is
- # used here since x is a
- # free variable in a class
- # body.
-```
-
-
-=== STORE_DEREF(i)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... cell_value
-Stack After: ...
-```
-
-Pop off the top of the stack and sets the value contained in the cell at slot `i` as described by <<_cell_variable_index>> to the popped value.
-A cell corresponds to either a shared or free variable.
-Used to set shared and free variables.
-
-Example Sources:
-
-```python
-def outer():
- x = 10 # STORE_DEREF(x) is used here
- # since x is used in inner
- print(x)
- def inner():
- nonlocal x
- # ...
-```
-
-```python
-def outer():
- x = 10
- def inner():
- nonlocal x
- x = 20 # STORE_DEREF(x) is used here
- # since x is a free variable
- inner()
- print(x) # 20
-```
-
-
-=== DELETE_DEREF(i)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Deletes the value contained in the cell at slot `i` as described by <<_cell_variable_index>>.
-The actual cell is NOT deleted, but has no associated
-value.
-A cell corresponds to either a shared or free variable.
-Used to delete shared and free variables.
-
-Example Sources:
-
-```python
-def outer():
- x = 10
- del x # DELETE_DEREF(x) is used here
- # since x is used in inner
- def inner():
- nonlocal x
- # ...
-```
-
-```python
-def outer():
- x = 10
- def inner():
- nonlocal x
- del x # DELETE_DEREF(x) is used here
- # since x is a free variable
-```
-
-
-=== RAISE_VARARGS(argc)
-
-Python Versions: ALL
-
-```
-Stack Prior (argc = 0): ...
-Stack Prior (argc = 1): ... exception
-Stack Prior (argc = 2): ... exception cause
-Stack After: N/A
-```
-
-Does one of three things depends on `argc`:
-
-- If `argc = 0`, reraise the last raised exception. Used to implement a bare `raise` in an except block.
-
-- If `argc = 1`, the top of stack is either an exception or an exception type.
-If it is an exception instance, raise it; otherwise, create a new instance of the exception type.
-Used to implement `raise Exception` and `raise Exception()`
-
-- If `argc = 2`, the top of stack is an exception and the item immediately below it is an exception or an exception type.
-If `exception` is an exception instance, set its `\\__cause__` to `cause` and raise it. Otherwise, construct a new instance of `exception`, set its `\\__cause__` to `cause` and raise it.
-Used to implement `raise Exception from cause` and `raise Exception() from cause`.
-
-Example Sources:
-
-```python
-try:
- # ...
-except:
- raise # argc = 0
-```
-
-```python
-raise Exception # argc = 1
-```
-
-```python
-raise Exception() # argc = 1
-```
-
-```python
-raise Exception from cause # argc = 2
-```
-
-```python
-raise Exception() from cause # argc = 2
-```
-
-
-=== KW_NAMES(consti)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-Sets the keyword names for the next <> opcode to the tuple of strings stored in `co_consts[consti]`.
-Used to implement calling a function with keyword arguments
-
-Example Sources:
-
-```python
-# Assume co_const[3] = ('a', 'b'),
-# then KW_NAMES(3) would be emitted here
-my_function(a=1, b=2)
-```
-
-
-=== PRECALL(argc)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-A NOP.
-CPython uses it to allow the specialization of function calls. `argc` is the number of arguments as described in <>.
-Used when calling a function.
-
-Example Sources:
-
-```python
-# A PRECALL(3) is put here
-my_function(1, 2, a=3)
-```
-
-
-=== PUSH_NULL
-
-Python Versions: >= 3.11
-
-```
-Stack Prior: ...
-Stack After: ... NULL
-```
-
-Pushes `NULL` to the top of the stack.
-Used in the call sequence to match the NULL pushed by <> for non-method calls.
-
-Example Sources:
-
-```python
-# 3
-# A PUSH_NULL is used here
-my_function(1, 2, a=3)
-```
-
-
-=== CALL(argc)
-
-Python Versions: >= 3.11
-
-```
-Stack Prior (1): ... NULL, callable, arg_1, arg_2, ..., arg_{argc}
-Stack Prior (2): ... method, object, arg_1, arg_2, ..., arg_{argc}
-Stack After: ... return_value
-```
-
-Calls a function from the top `argc + 2` items on the stack.
-The first `argc` items on the stack are the arguments to the function.
-For the arguments, the keyword names internal variable length is checked, and the top `len(keyword names)` items are keyword arguments, and the bottom `argc - len(keyword names)` items are positional arguments.
-The two items below the arguments are either:
-
-- An unbound method object and an object
-- NULL and an arbitrary callable
-
-If it is NULL and an arbitrary callable, the given positional and keyword arguments are used.
-If it is an unbound method object and an object, object is inserted as the first item in the positional argument list.
-All the arguments and the two items below the arguments are popped, and the result of the function call is pushed to the top of the stack.
-The keyword names are reset to an empty list after this call.
-Used to implement function calls that do not unpack an iterable or mapping.
-
-Example Sources:
-
-```python
-# This is a CALL in NULL, CALLABLE form
-my_function(1, 2, a=3)
-```
-
-```python
-# This is a CALL in METHOD, OBJECT form
-my_object.my_function(1, 2, a=3)
-```
-
-
-=== CALL_FUNCTION(argc)
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... callable, arg_1, arg_2, ..., arg_{argc}
-Stack After: ... return_value
-```
-
-Calls a function from the top `argc + 1` items on the stack.
-The first `argc` items on the stack are the positional arguments to the function (there are no keyword arguments).
-The item below the arguments is the callable to call.
-All the arguments and the item below them are popped, and the result of the function call is pushed to the top of the stack.
-Used to implement function calls without keyword arguments.
-
-Example Sources:
-
-```python
-# This is CALL_FUNCTION(3)
-function(1, 2, 3)
-```
-
-
-=== CALL_FUNCTION_KW(argc)
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior: ... callable, arg_1, arg_2, ..., arg_{argc}, kw_names
-Stack After: ... return_value
-```
-
-Calls a function from the top `argc + 2` items on the stack.
-The item on the top of the stack is a tuple containing the names of keyword arguments.
-The `argc` items below that are the arguments to the function.
-For the arguments, the tuple at the top of the stack length is checked, and the top `len(keyword names)` items are keyword arguments, and the bottom `argc - len(keyword names)` items are positional arguments.
-The item below the arguments is the callable to call.
-The keyword argument name tuple, arguments and the callable are popped and the result of the function call is pushed to the top of the stack.
-Used to implement function calls with keyword arguments.
-
-Example Sources:
-
-```python
-# This is CALL_FUNCTION_KW(3) with
-# the tuple ('arg_1',) at the top of the stack
-function(1, 2, arg_1=3)
-```
-
-
-=== CALL_FUNCTION_EX(flags)
-
-Python Versions: ALL
-
-```
-Stack Prior (1): ... function, iterable
-Stack Prior (2): ... function, iterable, mapping
-Stack Prior (3): ... NULL, function, iterable
-Stack Prior (4): ... NULL, function, iterable, mapping
-Stack After: ... return_value
-```
-
-There are two modes for this function, controlled by its flags:
-
-- If `flags & 1` is set, this is a function call with both positional and keyword arguments, and the stack contains `callable`, `iterable`, `mapping`.
-The items in the iterable and mapping are unpacked, and are used to make the function call.
-Used to implement `function(*iterable, **mapping)`
-
-- If `flags & 1` is unset, this is a function call with only positional arguments, and the stack contains `callable`, `iterable`.
-The items in the iterable are unpacked and are used to make the function call.
-Used to implement `function(*iterable)`
-
-If the Python version is at least 3.11, a `NULL` is put beneath callable.
-In all cases, the argument containers, callable (and possibly `NULL`) are popped and the returned value is pushed to the top of the stack.
-
-
-Used to implement function calls that unpack arguments.
-
-Example Sources:
-
-```python
-# CALL_FUNCTION_EX(0)
-function(*iterable)
-```
-
-```python
-# CALL_FUNCTION_EX(0)
-function(1, 2, 3, *iterable)
-```
-
-```python
-# CALL_FUNCTION_EX(1)
-function(*iterable, **mapping)
-```
-
-```python
-# CALL_FUNCTION_EX(1)
-function(**mapping)
-```
-
-```python
-# CALL_FUNCTION_EX(1)
-function(1, arg=1, *iterable)
-```
-
-
-=== LOAD_METHOD(namei)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... object
-Stack After (1): ... unbound_method, object
-Stack After (2): ... function, NULL
-Stack After (3): ... NULL, function
-```
-
-Load the method with the name `co_names[namei]` from the object at the top of the stack.
-If the method exists (and is an instance method, not a class method, static method or a callable), the unbounded method is put beneath the object at the top of the stack.
-Otherwise, the object at the top of the stack is popped, attribute lookup is performed, and the result of the lookup is pushed to the stack (with a NULL either before or after the lookup result depending on the Python version).
-Used to implement attribute lookups for function calls.
-
-Example Sources:
-
-```python
-# This emits LOAD_METHOD
-my_object.function()
-
-# This DOES NOT emit LOAD_METHOD
-my_onject.function
-```
-
-
-=== CALL_METHOD(argc)
-
-Python Versions: \<= 3.10
-
-```
-Stack Prior (1): ... method, object, arg_1, ..., arg_{argc}
-Stack Prior (2): ... callable, NULL, arg_1, ..., arg_{argc}
-Stack After: ... return_value
-```
-
-Calls a method with `argc` positional arguments (and no keyword arguments).
-The top `argc` items on the stack are the positional arguments.
-The item immediately below the argument is either an object (which will be used as the self parameter) or NULL.
-The item below that is either an unbound method or a callable to call.
-All the arguments, the object/NULL, and the method/callable are all popped, and the return value is pushed to the top of the stack.
-Used to implement method calls.
-
-Example Sources:
-
-```python
-# This emits CALL_METHOD
-my_object.function()
-```
-
-
-=== MAKE_FUNCTION(flags)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... [default_positional_args], [default_keyword_args], [annotation_directory_or_tuple], [cell_tuple], function_code, [function_name]
-Stack After: ... function
-```
-
-Creates a function from the code object.
-Expected stack varies depending on `flags` and Python version.
-
-- If the Python version is prior to 3.11, at the top of the stack is the qualified name of the function, with the code object for the function below it.
-Otherwise, at the top of the stack is the code object (and the qualified name of the function is received via the code object).
-
-- If `flags & 8` is set, the next item below is a tuple containing the closure for the created function.
-The closure is a tuple that consists of the cells the inner function shares with the outer function.
-
-- If `flags & 4` is set, the next item below are the annotations for the created function.
-Prior to 3.10, this is a `tuple` containing `(key, value)` pairs.
-After 3.10, this is a `dict`.
-
-- If `flags & 2` is set, the next item below are the default values for keyword-only arguments (as a `dict`).
-
-- Finally, if `flags & 1` is set, the next item below are the default values for allow-positional arguments (as a `tuple`).
-
-All these items are popped off the stack and are used to create a new function object, which is pushed to the top of the stack.
-Used to create inner functions.
-
-Example Sources:
-
-```python
-def outer():
- fun_list = []
- for i in range(10):
- # MAKE_FUNCTION(1)
- def inner(value=i):
- return value
- fun_list.append(inner)
- fun_list[0]() # 0 because it
- # the default parameter
- # for fun_list[0]
-```
-
-```python
-def outer():
- for i in range(10):
- # MAKE_FUNCTION(8)
- def inner():
- return i
- fun_list.append(inner)
- fun_list[0]() # 9 because
- # it the current value of i
-```
-
-```python
-def outer():
- # MAKE_FUNCTION(4)
- # on the stack is either
- # (('a', str),) or {'a': str}
- # depending on Python version
- def inner(a: str):
- return a
-```
-
-```python
-def outer():
- # MAKE_FUNCTION(2)
- def inner(*, keyword_arg=1):
- return keyword_arg
-```
-
-
-=== BUILD_SLICE(argc)
-
-Python Versions: ALL
-
-```
-Stack Prior (argc=2): ... start, end
-Stack Prior (argc=3): ... start, end, step
-Stack After: ... function
-```
-
-At the top of the stack is either two or three items depending on `argc`:
-
-- If `argc = 2`, at the top of the stack are two objects to use as the start and end index of a slice.
-- If `argc = 3`, at the top of the stack are three objects to use as the start, end and step of a slice.
-
-Any items on the stack that are not `int` or `None` are converted to `int` by calling their `\\__index__()` method.
-The arguments are popped, and the created slice is pushed to the top of the stack.
-Used to implement https://docs.python.org/3/library/functions.html#slice[slice indexing].
-
-Example Sources:
-
-```python
-# BUILD_SLICE(2)
-my_list[:]
-my_list[1:]
-my_list[:2]
-my_list[1:-1]
-
-# BUILD_SLICE(3)
-my_list[::]
-my_list[1::]
-my_list[:2:]
-my_list[::3]
-my_list[1:2:]
-my_list[:2:3]
-my_list[1:2:3]
-```
-
-
-=== EXTENDED_ARG(ext)
-
-Python Versions: ALL
-
-```
-Stack Prior: ...
-Stack After: ...
-```
-
-A NOP.
-Used to extend an opcode argument range beyond one byte by prefixing up to three EXTENDED_ARG opcodes before it.
-
-Example Sources:
-
-```python
-# Dynamic list of length 260,
-# which is too large to fit into a byte (256)
-# So EXTENDED_ARG is used to extend
-# BUILD_LIST argument like so:
-# EXTENDED_ARG(0x01) BUILD_LIST(0x04)
-# = BUILD_LIST(0x0104 = 260)
-[
- a[0x00], a[0x01], a[0x02], a[0x03],
- a[0x04], a[0x05], a[0x06], a[0x07],
- # ...
- a[0xFC], a[0xFD], a[0xFE], a[0xFF],
- a[0x100], a[0x101], a[0x102], a[0x103]
-]
-```
-
-
-=== FORMAT_VALUE(flags)
-
-Python Versions: ALL
-
-```
-Stack Prior: ... object, [format_spec]
-Stack After: ... formatted_string
-```
-
-Formats an object with an optional format specifier string.
-Acts different depending on `flags`:
-
-- If `flags & 4` is set, there is a format specifier on the top of the stack, with the object to format below it.
-Otherwise, the object to format is at the top of the stack (and `None` will be used as the format specifier).
-
-- If `(flags & 3) == 0`, the object is formatted as is.
-
-- If `(flags & 3) == 1`, the object is converted via `str()` before formatting.
-
-- If `(flags & 3) == 2`, the object is converted via `repr()` before formatting.
-
-- If `(flags & 3) == 3`, the object is converted via `ascii()` before formatting.
-
-
-Example Sources:
-
-```python
-f'{my_object}' # FORMAT_VALUE(0)
-f'{my_object!s}' # FORMAT_VALUE(1)
-f'{my_object!r}' # FORMAT_VALUE(2)
-f'{my_object!a}' # FORMAT_VALUE(3)
-f'{my_object:my_spec}' # FORMAT_VALUE(4)
-f'{my_object!s:my_spec}' # FORMAT_VALUE(5)
-```
\ No newline at end of file
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/python-function-structure/python-function-structure.adoc b/jpyinterpreter/developer-docs/src/modules/ROOT/pages/python-function-structure/python-function-structure.adoc
deleted file mode 100644
index 95cc589d..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/python-function-structure/python-function-structure.adoc
+++ /dev/null
@@ -1,191 +0,0 @@
-[[pythonFunctionStructure]]
-= Python Function Structure
-
-In Python, the details about a function, including
-its implementation and argument spec, are accessible
-from the https://docs.python.org/3.11/reference/datamodel.html#index-33[function object].
-In `jpyinterpreter`, this information is stored in the class `PythonCompiledFunction`.
-It has several attributes. In particular, we are interested in:
-
-- `\\__globals__`: The globals dict that is used by the function. All classes defined in the same file share the same globals. Classes defined in different files have different globals. All globals variables are stored in this dict.
-
-- `\\__closure__`: Variables used by the function that were declared in an outer scope. for instance:
-+
-```python
-def outer():
- x = 10
- def inner():
- return x
- return inner
-```
-+
-the function `inner.\\__closure__` would be `[Cell(value=10)]`. Cells are used because changes in the outer function affects the inner function. For instance:
-+
-```python
-def outer():
- x = 10
- def inner():
- return x
- x = 20
- return inner() # returns 20
-```
-
-- `\\__defaults__`: contains default values for "allow-positional" arguments. For example, for the function:
-+
-```python
-def my_function(a, pos_only=1, / , allow_pos=2, * , keyword_only=3):
- pass
-```
-+
-`\\__defaults__` would be `(1, 2)`. Keyword-only default arguments are instead stored in `\\__kwdefaults__`, which for the above function would be `{'keyword_only': 3}`.
-
-- `\\__qualname__`: the https://docs.python.org/3.11/glossary.html#term-qualified-name[qualified name] of the function.
-
-- `\\__annotations__`: the type annotations of the function. For example, for the function:
-+
-```python
-def typed_function(a: int, b: str) -> 'A':
- return A(a, b)
-```
-+
-`\\__annotations__` would be `{'a': int, 'b': str, 'return': 'A'}`. Values in the `\\__annotations__` dict should be a type or a string. If it is a string, it represents the type that has the same name as that string.
-
-- `\\__code__`: The code object of the function, containing the function bytecode and argument spec. Code objects are described below.
-
-== Code Objects
-
-https://docs.python.org/3.11/reference/datamodel.html#index-55[Code objects] is the byte-compiled Python function. The primary difference between function objects and code objects is that function objects contain context (i.e. globals, defaults, closure) whereas code objects are context-free. Of its attributes, we are interested in:
-
-- `co_names`: A tuple of names used by the bytecode. For instance, the function
-+
-```python
-def my_function():
- a = 1
- b = 2
- return max(a, b)
-```
-+
-has `('a', 'b', 'max')` in its `co_names` attribute. It is referenced by the bytecode to load and store globals. For example, `LOAD_GLOBAL 2` means "load the global with the name given by the entry in co_names at index 2" (i.e. `max`).
-
-- `co_varnames`: a tuple of variable names used by the bytecode (including parameters). For instance, the function:
-+
-```python
-def outer_function(outer_parameter):
- def inner_function(inner_parameter):
- my_local = outer_parameter + inner_parameter
- return my_local * 2
- return inner_function
-```
-+
-`inner_function's` `co_varnames` would be `('inner_parameter', 'my_local', 'outer_parameters')`. `co_varnames` always starts with the function's parameter, followed by local variables used in the function, followed by cell variables used in the function. Cell variables are variables that are stored in a cell. There are two types: free variables, which is a cell from an outer function (in this case, `outer_parameter` is a free variable of `inner_function`), and bound variables, which is a cell that is used in an inner function (in this case, `outer_parameter` is a bound variable of `outer_function`).
-
-- `co_cellvars`: a tuple of strings representing bound variable.
-
-- `co_freevars`: a tuple of strings representing free variable.
-
-- `co_constants`: a tuple of constants used in the function. For instance, the function:
-+
-```python
-def my_function():
- a = 1
- b = 2
- return a + b
-```
-+
-`co_constants` would be `(1, 2)`. In CPython, objects
-eligible to be constants are:
-+
-** `int` objects (ex: `1`, `42`)
-** `float` objects (ex: `1.5`, `NaN`)
-** `bool` objects (`True` and `False`)
-** `str` objects (ex: `'hello world'`)
-** `bytes` objects (ex: `b'hello world'`)
-** `None` (`None`)
-** `Ellipsis` (`...`)
-+
-The following objects are not eligible to be used as constants, and are loaded with `LOAD_GLOBAL` instead:
-+
-** `class` objects (ex: `int`, `str`, user defined classes)
-** `function` objects (ex: `max`, `range`, user defined functions)
-** Instances of user defined classes
-
-- `co_exceptiontable`: a mapping from bytecode instruction ranges to their exception handler.
- The exception handler have the following properties:
-+
-** `targetInstruction`: the bytecode index to jump to
-** `stackDepth`: the stack depth prior to the try block (required for restoring the stack state)
-** `pushLastIndex`: A boolean, that if true, indicates the handler should push the bytecode index that raised the exception prior to pushing the exception (otherwise, only the exception is pushed).
-+
-This attribute is only present in Python 3.11 and above; previous versions of Python use bytecode instruction to push and pop exception blocks.
- For example, the function:
-+
-```python
-def my_function():
- for x in range(10):
- try:
- y = other_function_1(x)
- try:
- other_function_2(x, y)
- except:
- print('other 2 exception')
- except:
- print('other 1 exception')
-```
-+
-would have (simplified) bytecode looking like this:
-+
-```
-0 LOAD_GLOBAL 0 (range)
-1 LOAD_CONSTANT 1 (10)
-2 CALL 1
-3 GET_ITER
-4 FOR_ITER 19 (23 LOAD_CONSTANT)
-5 STORE_LOCAL 0 (x)
-6 LOAD_GLOBAL 1 (other_function_1)
-7 LOAD_LOCAL 0 (x)
-8 CALL 1
-9 STORE_LOCAL 1 (y)
-10 LOAD_GLOBAL 2 (other_function_2)
-11 LOAD_LOCAL 0 (x)
-12 LOAD_LOCAL 1 (y)
-13 CALL 2
-14 JUMP_BACKWARDS 10 (4 FOR_ITER)
-15 POP_TOP
-16 LOAD_GLOBAL 3 (print)
-17 LOAD_CONSTANT 2 ('other 2 exception')
-18 JUMP_BACKWARDS 14 (4 FOR_ITER)
-19 POP_TOP
-20 LOAD_GLOBAL 3 (print)
-21 LOAD_CONSTANT 2 ('other 1 exception')
-22 JUMP_BACKWARDS 18 (4 FOR_ITER)
-23 LOAD_CONSTANT 0 (None)
-24 RETURN
-```
-+
-For simplicity, the code that handles exceptions in exception handlers has been excluded. The above bytecode would have the corresponding exception table below:
-+
-```
-Exception Table:
-[12, 14) -> 15 (stack-depth: 1)
-[5, 18) -> 19 (stack-depth: 1)
-```
-+
-Stack depth is 1 because the iterator was on the stack prior to the try block.
-
-- `co_argcount` the number of allow-positional arguments the function takes. For example, for the function below:
-+
-```python
-def my_function(a, b, /, c, d=10, *, e=20):
- pass
-```
-+
-`co_argcount` would be `4`, since `a`, `b`, `c`, and `d` can be specified as a positional argument (`a`, `b` are required positional only arguments,
-`c` is a positional-or-keyword required argument,
-`d` is a positional-or-keyword optional argument,
-`e` is a keyword-only optional argument).
-
-- `co_kwonlyargcount` is the number of keyword-only arguments.
-For the example given in `co_argcount`, it would be `1`, since `e` is the only keyword-only argument.
-
-- `co_posonlyargcount` is the number of positional-only arguments.
-For the example given in `co_argcount`, it would be `2`, since `a` and `b` are the only positional-only arguments.
\ No newline at end of file
diff --git a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/stack-machines/stack-machines.adoc b/jpyinterpreter/developer-docs/src/modules/ROOT/pages/stack-machines/stack-machines.adoc
deleted file mode 100644
index 84b80bca..00000000
--- a/jpyinterpreter/developer-docs/src/modules/ROOT/pages/stack-machines/stack-machines.adoc
+++ /dev/null
@@ -1,570 +0,0 @@
-[[stackMachineIntroduction]]
-= Stack Machines Introduction
-:doctype: book
-:sectnums:
-:icons: font
-
-NOTE: This section uses a fake stack machine language for educational purposes, and is unrelated to both the Java bytecode machine language and the CPython bytecode machine language.
-
-[[whatIsAStackMachine]]
-== What is a Stack Machine?
-
-A Stack Machine is a type of virtual machine that uses a stack to store intermediary inputs and results.
-For instance, this program:
-
-```python
-def my_fun(x: int):
- return x + 1
-```
-
-when compiled to a stack machine language, may look like this:
-
-```
-LOAD_LOCAL 0 (x)
-LOAD_CONSTANT 0 (1)
-ADD
-RETURN
-```
-
-The stack starts initially empty, and each operation modifies it:
-
-```
-// []
-LOAD_LOCAL 0 (x) // push x to the stack
-
-// [x]
-LOAD_CONSTANT 0 (1) // push 1 to the stack
-
-// [x, 1]
-ADD // pop top two elements (x, 1) and push their sum
-
-// [(x+1)]
-RETURN // returns TOS (x+1) to the caller
-```
-
-The stack is often not the only means of storage. Usually, there are local variables that can also be read and written to. For instance, this function:
-
-```python
-def test(x):
- a = x + x
- b = x * x
- return a + b
-```
-
-when compiled to a stack machine language, may look like this:
-
-```
-// stack: [] locals: {}
-LOAD_LOCAL 0 (x)
-
-// stack: [x] locals: {}
-DUP_TOP
-
-// stack: [x, x] locals: {}
-ADD
-
-// stack: [(x + x)] locals: {}
-STORE_LOCAL 1 (a)
-
-// stack: [], locals: {a: x+x}
-LOAD_LOCAL 0 (x)
-
-// stack: [x], locals: {a: x+x}
-DUP_TOP
-
-// stack: [x, x], locals: {a: x+x}
-MULTIPLY
-
-// stack: [(x*x)], locals: {a: x+x}
-STORE_LOCAL 2 (b)
-
-// stack: [], locals: {a: x+x, b: x*x}
-LOAD_LOCAL 1 (a)
-
-// stack: [x+x], locals: {a: x+x, b: x*x}
-LOAD_LOCAL 2 (b)
-
-// stack: [x+x, x*x], locals: {a: x+x, b: x*x}
-ADD
-
-// stack: [(x+x) + (x*x)] locals: {a: x+x, b: x*x}
-RETURN
-```
-
-[[jumpsInAStackMachine]]
-== Jumps in a Stack Machine
-
-A stack machine opcode could conditionally jump to a different location. For instance:
-
-```python
-def test(x):
- a = 0
- if x < 10:
- a += x
- return a
-```
-
-when compiled to a stack machine language, may look like this:
-
-```
-// stack: [] locals: {}
-LOAD_CONSTANT 0 (0)
-
-// stack: [0] locals: {}
-STORE_LOCAL 1 (a)
-
-// stack: [] locals: {a: 0}
-LOAD_LOCAL 0 (x)
-
-// stack: [x] locals: {a: 0}
-LOAD_CONSTANT 1 (10)
-
-// stack: [x, 1] locals: {a: 0}
-LESS_THAN
-
-// stack: [Type] locals: {a: 0}
-POP_JUMP_IF_FALSE skip_if >---------------|
- |
-// stack: [] locals: {a: 0} |
-LOAD_LOCAL 1 (a) |
- |
-// stack: [a] locals: {a: 0} |
-LOAD_LOCAL 0 (x) |
- |
-// stack: [a, x] locals: {a: 0} |
-ADD |
- |
-// stack: [(a+x)] locals: {a: 0} |
-STORE_LOCAL 1 (a) |
- |
-[label skip_if] |
-// stack: [] locals: {a: 0 or (0 + x)} |
-LOAD_LOCAL 1 (a) <------------------------|
-
-// stack: [a] locals: {a: 0 or (0 + x)}
-RETURN
-```
-
-In particular, the instruction after `POP_JUMP_IF_FALSE` will be the instruction after `skip_if` if TOS is False. If TOS is True, it will be the instruction after `POP_JUMP_IF_FALSE` instead. We call the possible next instruction(s) for a given instruction that instruction's target(s).
-
-This means the instruction after the label `skip_if` has
-two possible predecessors:
-
-- `POP_JUMP_IF_FALSE` if TOS was False
-- `STORE_LOCAL (a + x)` if TOS was True
-
-In most stack based languages, stack state must be consistent.
-This means, among other things, the number of elements in the stack for a given opcode must be the same for all possible predecessors. For example, the following stack machine program is invalid:
-
-```
-// stack: []
-LOAD_LOCAL 0 (x)
-
-// stack: [x]
-LOAD_CONSTANT 0 (10)
-
-// stack: [x, 10]
-LESS_THAN
-
-// stack: [Type]
-POP_JUMP_IF_TRUE skip_if >-----------------------------------------|
- |
-// stack: [] |
-LOAD_CONSTANT 0 (10) |
- |
-[label skip_if] |
-// Cannot compute stack; stack size mismatch [10] (1) vs [] (0) |
-LOAD_CONSTANT 0 (10)<----------------------------------------------|
-
-// ???
-RETURN
-```
-
-The `if` block pushed an extra element to the stack, but did not pop it, causing an inconsistent stack size after the if
-(either 1, if the branch was taken, or 0, if it was not).
-
-== Differences between Java and the CPython Virtual Machines
-
-The Java and CPython virtual machines have a number of differences:
-
-- In Java, the compiler is allowed to introduce "extra"
- local variables not declared in the source program. This
- is because local variables in the JVM are stored in slots,
- and the number of slots does not need to match the number
- of local variables. In contrast, every local variable
- in the CPython virtual machine correlates to a declared
- local variable in the function, which is stored in a
- dictionary. This leads to CPython using the stack as
- storage for compiler local variables. For instance,
-+
-```python
-def my_fun(iterable):
- total = 0
- for item in iterable:
- total += item
- return total
-```
-+
-translates roughly to
-+
-```
-// [], locals: {}
-LOAD_CONSTANT 1 (0)
-
-// [0], locals: {}
-STORE_LOCAL 1 (total)
-
-// [], locals: {total: 0}
-LOAD_LOCAL 0 (iterable)
-
-// [iterable], locals: {total: 0}
-GET_ITER
-
-[forStart]<---------------------------------------------------------|
-// [iter(iterable)], locals: {total: int} |
-FOR_ITER afterFor >-------------------------------------------------+--|
- | |
-// [iter(iterable), int], locals: {total: int} | |
-STORE_LOCAL 2 (item) | |
- | |
-// [iter(iterable)], locals: {total: int, item: int} | |
-LOAD_LOCAL 1 (total) | |
- | |
-// [iter(iterable), total], locals: {total: int, item: int} | |
-LOAD_LOCAL 2 (item) | |
- | |
-// [iter(iterable), total, item], locals: {total: int, item: int} | |
-BINARY_OP 13 (+=) | |
- | |
-// [iter(iterable), (total += item)] | |
-STORE_LOCAL 1 (total) | |
- | |
-// [iter(iterable)], locals: {total: int, item: int} | |
-GOTO forStart>------------------------------------------------------| |
- |
-[afterFor]<------------------------------------------------------------|
-// [], locals: {total: int, item: int}
-LOAD_LOCAL 1 (total)
-
-// [total], locals: {total: int, item: int}
-RETURN_VALUE
-```
-+
-Note that despite the fact `iter(iterable)` is not used inside
-the for block, it remains on the stack for the entire duration of the for block so it can be reused by `FOR_ITER`.
-In Java, the above code instead would roughly translate to
-+
-```
-// [], locals: {}
-LOAD_CONSTANT 0 (0)
-
-// [0], locals: {}
-STORE_LOCAL 1 (total)
-
-// [], locals: {total: 0}
-LOAD_LOCAL 0 (iterable)
-
-// [iterable], locals: {total: 0}
-INVOKE iterator()
-
-// [iterable.iterator()], locals: {total: 0}
-STORE_LOCAL 2 (iterator)
-
-[forStart]<---------------------------------------------------------|
-// [], locals: {total: 0, iterator: iterator} |
-LOAD_LOCAL 2 (iterator) |
- |
-// [iterator], locals: {total: 0, iterator: iterator} |
-INVOKE hasNext() |
- |
-// [boolean], locals: {total: 0, iterator: iterator} |
-JUMP_IF_FALSE afterFor >--------------------------------------------+--|
- | |
-// [], locals: {total: int} | |
-LOAD_LOCAL 2 (iterator) | |
- | |
-// [iterator], locals: {total: int} | |
-INVOKE next | | |
- | |
-// [int], locals: {total: int} | |
-STORE_LOCAL 3 (item) | |
- | |
-// [], locals: {total: int, item: int} | |
-LOAD_LOCAL 1 (total) | |
- | |
-// [total], locals: {total: int, item: int} | |
-LOAD_LOCAL 3 (item) | |
- | |
-// [total, item], locals: {total: int, item: int} | |
-INT_ADD | |
- | |
-// [total + item] | |
-STORE_LOCAL 1 (total) | |
- | |
-// [], locals: {total: int, item: int} | |
-GOTO forStart>------------------------------------------------------| |
- |
-[afterFor]<------------------------------------------------------------|
-// [], locals: {total: int, item: int}
-LOAD_LOCAL 1 (total)
-
-// [total], locals: {total: int, item: int}
-RETURN_VALUE
-```
-+
-That is, instead of the iterator remaining on the stack, it got stored in a compiler local variable.
-
-- The stack state is before a try-block is preserved in Python, so it can
- be restored when an exception occurs. Thus, when an exception occurs in
- CPython, the stack state is `, `
- (where `` is either `, traceback, exception, exception_type` if the Python version is before Python 3.11, `exception`
- otherwise). In contrast, after an exception occurs in Java, the stack state is
- `exception`. For example, this code:
-+
-```python
-def my_fun(session_list):
- for session in session_list:
- try:
- session.start()
- except IOError as e:
- print('Could not start session: ' + str(e))
-```
-+
-translates roughly in python (3.11) to:
-+
-```
-// [], {}
-LOAD_LOCAL 0 (session_list)
-
-// [session_list], {}
-GET_ITER
-
-[forStart]
-// [iter], {}
-FOR_ITER after_for
-
-[tryStart]
-// [iter, any], {}
-STORE_LOCAL 1 (session)
-
-// [iter], {session: any}
-LOAD_LOCAL 1 (session)
-
-// [iter, session], {session: any}
-LOAD_METHOD 'start'
-
-// [iter, session, method], {session: any}
-CALL 1
-
-// [iter], {session: any}
-GOTO forStart
-
-[except]
-// [iter, exception], {}
-PUSH_EXC_INFO
-
-// [iter, exception, exception], {}
-LOAD_GLOBAL 2 (IOERROR)
-
-// [iter, exception, exception, IOError], {}
-CHECK_EXC_MATCH
-
-// [iter, exception, bool], {}
-POP_JUMP_FORWARD_IF_FALSE finally
-
-[ioError]
-// [iter, exception], {}
-STORE_LOCAL 2 (e)
-
-// [iter], {e: Error}
-LOAD_GLOBAL 5 (print)
-
-// [iter, print], {e: Error}
-LOAD_CONST 1 ('Could not start session: ')
-
-// [iter, print, msg], {e: Error}
-LOAD_GLOBAL 7 (str)
-
-// [iter, print, msg, str], {e: Error}
-LOAD_LOCAL 2 (e)
-
-// [iter, print, msg, str, e], {e: Error}
-CALL 1
-
-// [iter, print, msg, str(e)], {e: Error}
-BINARY_OP 0 (+)
-
-// [iter, print, msg + str(e)], {e: Error}
-CALL 1
-
-// [iter, None], {e: Error}
-POP_TOP
-
-// [iter], {e: Error}
-POP_EXCEPT
-
-// [iter], {e: Error}
-LOAD_CONST 0 (None)
-
-// [iter, None], {e: Error}
-STORE_LOCAL 2 (e)
-
-// [iter], {e: None}
-DELETE_LOCAL 2 (e)
-
-// [iter], {}
-GOTO forStart
-
-[exceptionInExceptFinally]
-// [iter, exception], {}
-LOAD_CONST 0 (None)
-
-// [iter, exception, None], {}
-STORE_FAST 2 (e)
-
-// [iter, exception], {e: None}
-DELETE_FAST 2 (e)
-
-// [iter, exception], {}
-RERAISE
-
-[unmatchExceptionTypeFinally]
-// [iter, exception], {}
-RERAISE
-
-[exceptionInSetupCleanupFinally]
-// [iter, exception], {}
-POP_EXCEPT
-
-// [iter, exception], {}
-RERAISE
-
-[forEnd]
-// [], {}
-LOAD_CONST 0 (None)
-
-// [None], {}
-RETURN_VALUE
-
-ExceptionHandlers:
- Any: (tryStart, except) -> except
- Any: (except, ioError) -> exceptionInSetupCleanupFinally
- Any: (ioError, exceptionInExceptFinally) -> exceptionInExceptFinally
- Any: (exceptionInExceptFinally, unmatchExceptionTypeFinally) -> exceptionInSetupCleanupFinally
-```
-+
-(In 3.10 and below, the ExceptionHandlers are done via the SETUP_FINALLY opcode which create the corresponding try/except blocks). In Java, the above code would instead roughly translate to:
-+
-```
-// [], {}
-LOAD_LOCAL 0 (session_list)
-
-// [session_list], {}
-INVOKE iterator()
-
-// [iterator], {}
-STORE_LOCAL 3 (iterator)
-
-[forStart]
-// [], {iterator: iterator}
-LOAD_LOCAL 3 (iterator)
-
-// [iterator], {iterator: iterator}
-INVOKE hasNext()
-
-// [bool], {iterator: iterator}
-JUMP_IF_FALSE afterFor
-
-// [], {iterator: iterator}
-LOAD_LOCAL 3 (iterator)
-
-// [iterator], {iterator: iterator}
-INVOKE next()
-
-[tryStart]
-
-// [item], {iterator: iterator}
-STORE_LOCAL 1 (session)
-
-// [], {iterator: iterator, session: item}
-LOAD_LOCAL 1 (session)
-
-// [item], {iterator: iterator, session: item}
-INVOKE start()
-
-// [], {iterator: iterator, session: item}
-GOTO forStart
-
-[except]
-// [exception], {iterator: iterator}
-STORE_LOCAL 2 (e)
-
-// [], {iterator: iterator, e: exception}
-LOAD_CONST 1 ('Could not start session: ')
-
-// [message], {iterator: iterator, e: exception}
-LOAD_LOCAL 2 (e)
-
-// [message, e], {iterator: iterator, e: exception}
-INVOKE toString()
-
-// [message, e.toString()], {iterator: iterator, e: exception}
-INVOKE concat(String)
-
-// [message + e.toString()], {iterator: iterator, e: exception}
-INVOKESTATIC print(String)
-
-// [], {iterator: iterator, e: exception}
-GOTO forStart
-
-[exceptionInExceptFinally]
-// [exception], {iterator: iterator}
-THROW
-
-[forEnd]
-// [], {iterator: iterator}
-LOAD_CONST 0 (None)
-
-// [None], {iterator: iterator}
-RETURN_VALUE
-
-ExceptionHandlers:
- IOError: (tryStart, except) -> except
- Any: (tryStart, exceptionInExceptFinally) -> exceptionInSetupCleanupFinally
-```
-
-- Methods and types are objects on the stack in CPython. In contrast, methods and types are arguments to opcodes in Java. For example, this Python code:
-+
-```python
-def my_function(obj):
- return obj.my_function()
-```
-+
-roughly translates to this bytecode in CPython
-+
-```
-// []
-LOAD_LOCAL 0 (obj)
-
-// [obj]
-LOAD_METHOD 'my_function'
-
-// [obj, my_function]
-CALL 1
-
-// [value]
-RETURN_VALUE
-```
-+
-In Java, it would roughly translate to this instead:
-+
-```
-// []
-LOAD_LOCAL 0 (obj)
-
-// [obj]
-INVOKE ObjectType::my_function()
-
-// [value]
-RETURN_VALUE
-```
diff --git a/jpyinterpreter/examples/.gitignore b/jpyinterpreter/examples/.gitignore
deleted file mode 100644
index cc3c0ab1..00000000
--- a/jpyinterpreter/examples/.gitignore
+++ /dev/null
@@ -1,14 +0,0 @@
-/dist
-/*.egg-info
-/target
-/*-stubs
-
-# Eclipse, Netbeans and IntelliJ files
-/.*
-!.gitignore
-!.dockerignore
-!.mvn
-/nbproject
-/*.ipr
-/*.iws
-/*.iml
diff --git a/jpyinterpreter/examples/example.py b/jpyinterpreter/examples/example.py
deleted file mode 100644
index 111a8596..00000000
--- a/jpyinterpreter/examples/example.py
+++ /dev/null
@@ -1,51 +0,0 @@
-import jpype.imports
-import jpyinterpreter
-
-jpyinterpreter.init(path=['target/example-1.0.0.jar'])
-
-from java.util.function import Function
-
-from org.acme import MyClass
-
-
-def time(iterations, function, argument):
- from timeit import default_timer as timer
- java_function = jpyinterpreter.translate_python_bytecode_to_java_bytecode(function, Function)
-
- start = timer()
-
- result = MyClass.iterate(iterations, argument, function)
-
- end = timer()
-
- print(f"Python Result: {result}")
- print(f"Time for Python: {end - start}s")
-
- start = timer()
-
- result = MyClass.iterate(iterations, argument, java_function)
-
- end = timer()
-
- print(f"Java Result (translated from Python bytecode): {result}")
- print(f"Time for Java (translated from Python bytecode): {end - start}s")
-
-
-def test1(arg):
- return arg + 1
-
-def test2(arg):
- index = 0
- while index <= 10:
- index += 1
- return arg + 1
-
-def test3(arg):
- index = 0
- while index <= 100:
- index += 1
- return arg + 1
-
-time(100000, test1, 0)
-time(100000, test2, 0)
-time(100000, test3, 0)
diff --git a/jpyinterpreter/examples/pom.xml b/jpyinterpreter/examples/pom.xml
deleted file mode 100644
index 6a7b3f60..00000000
--- a/jpyinterpreter/examples/pom.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-
-
- 4.0.0
-
- ai.timefold.solver
- timefold-solver-build-parent
- 1.7.0
-
-
- org.acme
- example
- Example
- 1.0.0
-
-
- acme
-
-
-
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- analyze-only
- none
-
-
-
-
- org.apache.maven.plugins
- maven-surefire-plugin
-
-
- org.jboss.logmanager.LogManager
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
-
-
diff --git a/jpyinterpreter/examples/src/main/java/org/acme/MyClass.java b/jpyinterpreter/examples/src/main/java/org/acme/MyClass.java
deleted file mode 100644
index 47d91a62..00000000
--- a/jpyinterpreter/examples/src/main/java/org/acme/MyClass.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package org.acme;
-
-import java.util.function.Function;
-
-public class MyClass {
- public static T iterate(int times, T start, Function reducer) {
- T current = start;
- for (int i = 0; i < times; i++) {
- current = reducer.apply(current);
- }
- return current;
- }
-}
diff --git a/jpyinterpreter/mvnw b/jpyinterpreter/mvnw
deleted file mode 100755
index 633bbb74..00000000
--- a/jpyinterpreter/mvnw
+++ /dev/null
@@ -1,239 +0,0 @@
-#!/bin/sh
-# ----------------------------------------------------------------------------
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-# ----------------------------------------------------------------------------
-
-# ----------------------------------------------------------------------------
-# Apache Maven Wrapper startup batch script, version 3.2.0
-#
-# Optional ENV vars
-# -----------------
-# JAVA_HOME - location of a JDK home dir, required when download maven via java source
-# MVNW_REPOURL - repo url base for downloading maven distribution
-# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
-# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
-# ----------------------------------------------------------------------------
-
-set -euf
-[ "${MVNW_VERBOSE-}" != debug ] || set -x
-
-# OS specific support.
-native_path() { printf %s\\n "$1"; }
-case "$(uname)" in
-(CYGWIN*|MINGW*) [ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
- native_path() { cygpath --path --windows "$1"; } ;;
-esac
-
-# set JAVACMD and JAVACCMD
-set_java_home() {
- # For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
- if [ -n "${JAVA_HOME-}" ] ; then
- if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
- # IBM's JDK on AIX uses strange locations for the executables
- JAVACMD="$JAVA_HOME/jre/sh/java"
- JAVACCMD="$JAVA_HOME/jre/sh/javac"
- else
- JAVACMD="$JAVA_HOME/bin/java"
- JAVACCMD="$JAVA_HOME/bin/javac"
-
- if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ] ; then
- echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
- echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
- return 1
- fi
- fi
- else
- JAVACMD="$('set' +e; 'unset' -f command 2>/dev/null; 'command' -v java)" || :
- JAVACCMD="$('set' +e; 'unset' -f command 2>/dev/null; 'command' -v javac)" || :
-
- if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ] ; then
- echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
- return 1
- fi
- fi
-}
-
-# hash string like Java String::hashCode
-hash_string() {
- str="${1:-}" h=0
- while [ -n "$str" ]; do
- h=$(( ( h * 31 + $(LC_CTYPE=C printf %d "'$str") ) % 4294967296 ))
- str="${str#?}"
- done
- printf %x\\n $h
-}
-
-verbose() { :; }
-[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
-
-die() {
- printf %s\\n "$1" >&2
- exit 1
-}
-
-# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
-while IFS="=" read -r key value; do
- case "${key-}" in
- distributionUrl) distributionUrl="${value-}" ;;
- distributionSha256Sum) distributionSha256Sum="${value-}" ;;
- esac
-done < "${0%/*}/.mvn/wrapper/maven-wrapper.properties"
-[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
-
-
-case "${distributionUrl##*/}" in
-(maven-mvnd-*bin.*)
- MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
- case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
- (*AMD64:CYGWIN*|*AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
- (:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
- (:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
- (:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
- (*) echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
- distributionPlatform=linux-amd64
- ;;
- esac
- distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
- ;;
-(maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
-(*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
-esac
-
-# apply MVNW_REPOURL and calculate MAVEN_HOME
-# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
-[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
-distributionUrlName="${distributionUrl##*/}"
-distributionUrlNameMain="${distributionUrlName%.*}"
-distributionUrlNameMain="${distributionUrlNameMain%-bin}"
-MAVEN_HOME="$HOME/.m2/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
-
-exec_maven() {
- unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
- exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
-}
-
-if [ -d "$MAVEN_HOME" ]; then
- verbose "found existing MAVEN_HOME at $MAVEN_HOME"
- exec_maven "$@"
-fi
-
-case "${distributionUrl-}" in
-(*?-bin.zip|*?maven-mvnd-?*-?*.zip) ;;
-(*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
-esac
-
-# prepare tmp dir
-if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
- clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
- trap clean HUP INT TERM EXIT
-else
- die "cannot create temp dir"
-fi
-
-mkdir -p -- "${MAVEN_HOME%/*}"
-
-# Download and Install Apache Maven
-verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
-verbose "Downloading from: $distributionUrl"
-verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
-
-# select .zip or .tar.gz
-if ! command -v unzip >/dev/null; then
- distributionUrl="${distributionUrl%.zip}.tar.gz"
- distributionUrlName="${distributionUrl##*/}"
-fi
-
-# verbose opt
-__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
-[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
-
-# normalize http auth
-case "${MVNW_PASSWORD:+has-password}" in
-'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
-has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
-esac
-
-if [ -z "${MVNW_USERNAME-}" ] && command -v wget > /dev/null; then
- verbose "Found wget ... using wget"
- wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName"
-elif [ -z "${MVNW_USERNAME-}" ] && command -v curl > /dev/null; then
- verbose "Found curl ... using curl"
- curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl"
-elif set_java_home; then
- verbose "Falling back to use Java to download"
- javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
- targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
- cat > "$javaSource" <<-END
- public class Downloader extends java.net.Authenticator
- {
- protected java.net.PasswordAuthentication getPasswordAuthentication()
- {
- return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
- }
- public static void main( String[] args ) throws Exception
- {
- setDefault( new Downloader() );
- java.nio.file.Files.copy( new java.net.URL( args[0] ).openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
- }
- }
- END
- # For Cygwin/MinGW, switch paths to Windows format before running javac and java
- verbose " - Compiling Downloader.java ..."
- "$(native_path "$JAVACCMD")" "$(native_path "$javaSource")"
- verbose " - Running Downloader.java ..."
- "$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
-fi
-
-# If specified, validate the SHA-256 sum of the Maven distribution zip file
-if [ -n "${distributionSha256Sum-}" ]; then
- distributionSha256Result=false
- if [ "$MVN_CMD" = mvnd.sh ]; then
- echo "Checksum validation is not supported for maven-mvnd." >&2
- echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
- exit 1
- elif command -v sha256sum > /dev/null; then
- if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c > /dev/null 2>&1; then
- distributionSha256Result=true
- fi
- elif command -v shasum > /dev/null; then
- if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c > /dev/null 2>&1; then
- distributionSha256Result=true
- fi
- else
- echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
- echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
- exit 1
- fi
- if [ $distributionSha256Result = false ]; then
- echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
- echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
- exit 1
- fi
-fi
-
-# unzip and move
-if command -v unzip > /dev/null; then
- unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR"
-else
- tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR"
-fi
-printf %s\\n "$distributionUrl" > "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
-mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
-
-clean || :
-exec_maven "$@"
diff --git a/jpyinterpreter/mvnw.cmd b/jpyinterpreter/mvnw.cmd
deleted file mode 100644
index dd02e16f..00000000
--- a/jpyinterpreter/mvnw.cmd
+++ /dev/null
@@ -1,145 +0,0 @@
-<# : batch portion
-@REM ----------------------------------------------------------------------------
-@REM Licensed to the Apache Software Foundation (ASF) under one
-@REM or more contributor license agreements. See the NOTICE file
-@REM distributed with this work for additional information
-@REM regarding copyright ownership. The ASF licenses this file
-@REM to you under the Apache License, Version 2.0 (the
-@REM "License"); you may not use this file except in compliance
-@REM with the License. You may obtain a copy of the License at
-@REM
-@REM http://www.apache.org/licenses/LICENSE-2.0
-@REM
-@REM Unless required by applicable law or agreed to in writing,
-@REM software distributed under the License is distributed on an
-@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-@REM KIND, either express or implied. See the License for the
-@REM specific language governing permissions and limitations
-@REM under the License.
-@REM ----------------------------------------------------------------------------
-
-@REM ----------------------------------------------------------------------------
-@REM Apache Maven Wrapper startup batch script, version 3.2.0
-@REM
-@REM Optional ENV vars
-@REM MVNW_REPOURL - repo url base for downloading maven distribution
-@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
-@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
-@REM ----------------------------------------------------------------------------
-
-@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
-@SET __MVNW_CMD__=
-@SET __MVNW_ERROR__=
-@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
-@SET PSModulePath=
-@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
- IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
-)
-@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
-@SET __MVNW_PSMODULEP_SAVE=
-@SET __MVNW_ARG0_NAME__=
-@SET MVNW_USERNAME=
-@SET MVNW_PASSWORD=
-@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
-@echo Cannot start maven from wrapper >&2 && exit /b 1
-@GOTO :EOF
-: end batch / begin powershell #>
-
-$ErrorActionPreference = "Stop"
-if ($env:MVNW_VERBOSE -eq "true") {
- $VerbosePreference = "Continue"
-}
-
-# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
-$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
-if (!$distributionUrl) {
- Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
-}
-
-switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
- "maven-mvnd-*" {
- $USE_MVND = $true
- $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
- $MVN_CMD = "mvnd.cmd"
- break
- }
- default {
- $USE_MVND = $false
- $MVN_CMD = $script -replace '^mvnw','mvn'
- break
- }
-}
-
-# apply MVNW_REPOURL and calculate MAVEN_HOME
-# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/
-if ($env:MVNW_REPOURL) {
- $MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
- $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
-}
-$distributionUrlName = $distributionUrl -replace '^.*/',''
-$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
-$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
-$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
-$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
-
-if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
- Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
- Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
- exit $?
-}
-
-if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
- Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
-}
-
-# prepare tmp dir
-$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
-$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
-$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
-trap {
- if ($TMP_DOWNLOAD_DIR.Exists) {
- try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
- catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
- }
-}
-
-New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
-
-# Download and Install Apache Maven
-Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
-Write-Verbose "Downloading from: $distributionUrl"
-Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
-
-$webclient = New-Object System.Net.WebClient
-if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
- $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
-}
-[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
-$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
-
-# If specified, validate the SHA-256 sum of the Maven distribution zip file
-$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
-if ($distributionSha256Sum) {
- if ($USE_MVND) {
- Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
- }
- if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
- Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
- }
-}
-
-# unzip and move
-Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
-Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
-try {
- Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
-} catch {
- if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
- Write-Error "fail to move MAVEN_HOME"
- }
-} finally {
- try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
- catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
-}
-
-Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
diff --git a/jpyinterpreter/pom.xml b/jpyinterpreter/pom.xml
deleted file mode 100644
index 5b6bcca9..00000000
--- a/jpyinterpreter/pom.xml
+++ /dev/null
@@ -1,126 +0,0 @@
-
-
-
- ai.timefold.solver
- timefold-solver-python-parent
- 999-SNAPSHOT
- ../pom.xml
-
- 4.0.0
- jpyinterpreter
-
-
- ai.timefold.jpyinterpreter
- 9.7
-
-
-
-
-
- org.ow2.asm
- asm-util
- ${version.ow2.asm}
-
-
- org.ow2.asm
- asm-tree
- ${version.ow2.asm}
-
-
-
-
-
-
- ai.timefold.solver
- timefold-solver-core
-
-
-
- org.ow2.asm
- asm
-
-
- org.ow2.asm
- asm-util
-
-
- org.ow2.asm
- asm-tree
-
-
-
-
- org.apache.commons
- commons-collections4
-
-
-
-
- org.slf4j
- slf4j-api
-
-
- ch.qos.logback
- logback-classic
- runtime
-
-
-
-
- org.junit.jupiter
- junit-jupiter-api
- test
-
-
- org.junit.jupiter
- junit-jupiter-engine
- test
-
-
- org.junit.jupiter
- junit-jupiter-params
- test
-
-
- org.assertj
- assertj-core
- test
-
-
- org.mockito
- mockito-core
- test
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-compiler-plugin
-
-
- org.apache.maven.plugins
- maven-dependency-plugin
-
-
- copy-dependencies
-
- copy-dependencies
-
-
-
- dependency-classpath
-
- build-classpath
-
-
- target/classpath.txt
-
-
-
-
-
-
-
diff --git a/jpyinterpreter/pyproject.toml b/jpyinterpreter/pyproject.toml
deleted file mode 100644
index 3228d3a0..00000000
--- a/jpyinterpreter/pyproject.toml
+++ /dev/null
@@ -1,8 +0,0 @@
-[build-system]
-requires = [
- "setuptools>=69.1.1",
- "stubgenj>=0.2.5",
- "JPype1>=1.4.1",
- "wheel"
-]
-build-backend = "setuptools.build_meta"
diff --git a/jpyinterpreter/setup.py b/jpyinterpreter/setup.py
deleted file mode 100644
index 0f1b6359..00000000
--- a/jpyinterpreter/setup.py
+++ /dev/null
@@ -1,88 +0,0 @@
-try:
- from setuptools import setup
-except ImportError:
- from distutils.core import setup
-from distutils.command.build_py import build_py
-import glob
-import os
-import platform
-import subprocess
-from pathlib import Path
-from shutil import copyfile
-import sys
-
-class FetchDependencies(build_py):
- """
- A command class that fetch Java Dependencies and
- add them as files within a python package
- """
- def create_stubs(self, project_root, command):
- subprocess.run([str((project_root / command).absolute()), 'dependency:copy-dependencies'],
- cwd=project_root, check=True)
- subprocess.run([str((project_root / command).absolute()), 'dependency:copy-dependencies',
- '-Dclassifier=javadoc'], cwd=project_root, check=True)
-
-
- def run(self):
- if not self.dry_run:
- project_root = Path(__file__).parent
- # Do a mvn clean install
- # which is configured to add dependency jars to 'target/dependency'
- command = 'mvnw'
- if platform.system() == 'Windows':
- command = 'mvnw.cmd'
- self.create_stubs(project_root, command)
- subprocess.run([str((project_root / command).absolute()), 'clean', 'install'], cwd=project_root, check=True)
- classpath_jars = []
- # Add the main artifact
- classpath_jars.extend(glob.glob(os.path.join(project_root, 'target', '*.jar')))
- # Add the main artifact's dependencies
- classpath_jars.extend(glob.glob(os.path.join(project_root, 'target', 'dependency', '*.jar')))
- self.mkpath(os.path.join(self.build_lib, 'jpyinterpreter', 'jars'))
-
- # Copy classpath jars to jpyinterpreter.jars
- for file in classpath_jars:
- copyfile(file, os.path.join(self.build_lib, 'jpyinterpreter', 'jars', os.path.basename(file)))
-
- # Make jpyinterpreter.jars a Python module
- fp = open(os.path.join(self.build_lib, 'jpyinterpreter', 'jars', '__init__.py'), 'w')
- fp.close()
- build_py.run(self)
-
-this_directory = Path(__file__).parent
-
-setup(
- name='jpyinterpreter',
- version='0.0.0a0',
- license='Apache License Version 2.0',
- license_file='LICENSE',
- description='A Python bytecode to Java bytecode translator',
- classifiers=[
- 'Development Status :: 1 - Planning',
- 'Programming Language :: Python :: 3',
- 'Topic :: Software Development :: Libraries :: Java Libraries',
- 'License :: OSI Approved :: Apache Software License',
- 'Operating System :: OS Independent'
- ],
- packages=['jpyinterpreter', 'java-stubs', 'jpype-stubs', 'org-stubs'],
- package_dir={
- 'jpyinterpreter': 'src/main/python',
- # Setup tools need a non-empty directory to use as base
- # Since these packages are generated during the build,
- # we use the src/main/resources package, which does
- # not contain any python files and is already included
- # in the build
- 'java-stubs': 'src/main/resources',
- 'jpype-stubs': 'src/main/resources',
- 'org-stubs': 'src/main/resources',
- },
- test_suite='tests',
- python_requires='>=3.10',
- install_requires=[
- 'JPype1>=1.5.0',
- ],
- cmdclass={'build_py': FetchDependencies},
- package_data={
- 'jpyinterpreter.jars': ['*.jar'],
- },
-)
diff --git a/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/AnnotationMetadata.java b/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/AnnotationMetadata.java
deleted file mode 100644
index f3593da0..00000000
--- a/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/AnnotationMetadata.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package ai.timefold.jpyinterpreter;
-
-import java.lang.annotation.Annotation;
-import java.lang.annotation.Repeatable;
-import java.lang.reflect.Array;
-import java.util.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.objectweb.asm.AnnotationVisitor;
-import org.objectweb.asm.ClassVisitor;
-import org.objectweb.asm.FieldVisitor;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Type;
-
-public record AnnotationMetadata(Class extends Annotation> annotationType, Map annotationValueMap) {
- public void addAnnotationTo(ClassVisitor classVisitor) {
- visitAnnotation(classVisitor.visitAnnotation(Type.getDescriptor(annotationType), true));
- }
-
- public void addAnnotationTo(FieldVisitor fieldVisitor) {
- visitAnnotation(fieldVisitor.visitAnnotation(Type.getDescriptor(annotationType), true));
- }
-
- public void addAnnotationTo(MethodVisitor methodVisitor) {
- visitAnnotation(methodVisitor.visitAnnotation(Type.getDescriptor(annotationType), true));
- }
-
- public static List getAnnotationListWithoutRepeatable(List metadata) {
- List out = new ArrayList<>();
- Map, List> repeatableAnnotationMap = new LinkedHashMap<>();
- for (AnnotationMetadata annotation : metadata) {
- Repeatable repeatable = annotation.annotationType().getAnnotation(Repeatable.class);
- if (repeatable == null) {
- out.add(annotation);
- continue;
- }
- var annotationContainer = repeatable.value();
- repeatableAnnotationMap.computeIfAbsent(annotationContainer,
- ignored -> new ArrayList<>()).add(annotation);
- }
- for (var entry : repeatableAnnotationMap.entrySet()) {
- out.add(new AnnotationMetadata(entry.getKey(),
- Map.of("value", entry.getValue().toArray(AnnotationMetadata[]::new))));
- }
- return out;
- }
-
- public static Type getValueAsType(String className) {
- return Type.getType("L" + className.replace('.', '/') + ";");
- }
-
- private void visitAnnotation(AnnotationVisitor annotationVisitor) {
- for (var entry : annotationValueMap.entrySet()) {
- var annotationAttributeName = entry.getKey();
- var annotationAttributeValue = entry.getValue();
-
- visitAnnotationAttribute(annotationVisitor, annotationAttributeName, annotationAttributeValue);
- }
- annotationVisitor.visitEnd();
- }
-
- private void visitAnnotationAttribute(AnnotationVisitor annotationVisitor, String attributeName, Object attributeValue) {
- if (attributeValue instanceof Number
- || attributeValue instanceof Boolean
- || attributeValue instanceof Character
- || attributeValue instanceof String) {
- annotationVisitor.visit(attributeName, attributeValue);
- return;
- }
-
- if (attributeValue instanceof Type type) {
- annotationVisitor.visit(attributeName, type);
- return;
- }
-
- if (attributeValue instanceof AnnotationMetadata annotationMetadata) {
- annotationMetadata.visitAnnotation(
- annotationVisitor.visitAnnotation(attributeName, Type.getDescriptor(annotationMetadata.annotationType)));
- return;
- }
-
- if (attributeValue instanceof Enum> enumValue) {
- annotationVisitor.visitEnum(attributeName, Type.getDescriptor(enumValue.getClass()),
- enumValue.name());
- return;
- }
-
- if (attributeValue.getClass().isArray()) {
- var arrayAnnotationVisitor = annotationVisitor.visitArray(attributeName);
- var arrayLength = Array.getLength(attributeValue);
- for (int i = 0; i < arrayLength; i++) {
- visitAnnotationAttribute(arrayAnnotationVisitor, attributeName, Array.get(attributeValue, i));
- }
- arrayAnnotationVisitor.visitEnd();
- return;
- }
- throw new IllegalArgumentException("Annotation of type %s has an illegal value %s for attribute %s."
- .formatted(annotationType, attributeValue, attributeName));
- }
-}
diff --git a/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/BytecodeSwitchImplementor.java b/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/BytecodeSwitchImplementor.java
deleted file mode 100644
index 5fc60ed6..00000000
--- a/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/BytecodeSwitchImplementor.java
+++ /dev/null
@@ -1,164 +0,0 @@
-package ai.timefold.jpyinterpreter;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
-import java.util.function.Consumer;
-import java.util.stream.Collectors;
-
-import org.objectweb.asm.Label;
-import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
-import org.objectweb.asm.Type;
-
-public class BytecodeSwitchImplementor {
-
- public static void createStringSwitch(MethodVisitor methodVisitor, Collection keyNames,
- int switchVariable, Consumer caseWriter, Runnable defaultCase, boolean doesEachCaseReturnEarly) {
- if (keyNames.isEmpty()) {
- defaultCase.run();
- return;
- }
-
- // keys in lookup switch MUST be sorted
- SortedMap> hashCodeToMatchingFieldList = new TreeMap<>();
- for (String fieldName : keyNames) {
- hashCodeToMatchingFieldList.computeIfAbsent(fieldName.hashCode(), hash -> new ArrayList<>()).add(fieldName);
- }
-
- int[] keys = new int[hashCodeToMatchingFieldList.size()];
- Label[] hashCodeLabels = new Label[keys.length];
-
- { // Scoped to hide keyIndex
- int keyIndex = 0;
- for (Integer key : hashCodeToMatchingFieldList.keySet()) {
- keys[keyIndex] = key;
- hashCodeLabels[keyIndex] = new Label();
- keyIndex++;
- }
- }
-
- final int TOS_VARIABLE = switchVariable;
- final int CASE_VARIABLE = TOS_VARIABLE + 1;
-
- methodVisitor.visitInsn(Opcodes.DUP);
- methodVisitor.visitVarInsn(Opcodes.ASTORE, TOS_VARIABLE);
- methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(String.class), "hashCode",
- Type.getMethodDescriptor(Type.INT_TYPE), false);
- Map switchVariableValueToField = new HashMap<>();
-
- Label endOfKeySwitch = new Label();
-
- methodVisitor.visitLdcInsn(-1);
- methodVisitor.visitVarInsn(Opcodes.ISTORE, CASE_VARIABLE);
-
- methodVisitor.visitLookupSwitchInsn(endOfKeySwitch, keys, hashCodeLabels);
-
- int totalEntries = 0;
- for (int i = 0; i < keys.length; i++) {
- methodVisitor.visitLabel(hashCodeLabels[i]);
- List matchingFields = hashCodeToMatchingFieldList.get(keys[i]);
-
- for (int fieldIndex = 0; fieldIndex < matchingFields.size(); fieldIndex++) {
- String field = matchingFields.get(fieldIndex);
- Label ifDoesNotMatchLabel = new Label();
-
- methodVisitor.visitVarInsn(Opcodes.ALOAD, TOS_VARIABLE);
- methodVisitor.visitLdcInsn(field);
- methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, Type.getInternalName(String.class), "equals",
- Type.getMethodDescriptor(Type.BOOLEAN_TYPE, Type.getType(Object.class)), false);
- if (fieldIndex != matchingFields.size() - 1) {
- methodVisitor.visitJumpInsn(Opcodes.IFEQ, ifDoesNotMatchLabel);
- } else {
- methodVisitor.visitJumpInsn(Opcodes.IFEQ, endOfKeySwitch);
- }
- methodVisitor.visitLdcInsn(totalEntries);
- methodVisitor.visitVarInsn(Opcodes.ISTORE, CASE_VARIABLE);
- if (fieldIndex != matchingFields.size() - 1) {
- methodVisitor.visitJumpInsn(Opcodes.GOTO, endOfKeySwitch);
- methodVisitor.visitLabel(ifDoesNotMatchLabel);
- }
-
- switchVariableValueToField.put(totalEntries, field);
- totalEntries++;
- }
- if (totalEntries != keyNames.size()) {
- methodVisitor.visitJumpInsn(Opcodes.GOTO, endOfKeySwitch);
- }
- }
- methodVisitor.visitLabel(endOfKeySwitch);
-
- Label missingField = new Label();
- Label endOfFieldsSwitch = new Label();
- Label[] fieldHandlerLabels = new Label[totalEntries];
- for (int i = 0; i < fieldHandlerLabels.length; i++) {
- fieldHandlerLabels[i] = new Label();
- }
-
- methodVisitor.visitVarInsn(Opcodes.ILOAD, CASE_VARIABLE);
- methodVisitor.visitTableSwitchInsn(0, totalEntries - 1, missingField, fieldHandlerLabels);
-
- for (int i = 0; i < totalEntries; i++) {
- methodVisitor.visitLabel(fieldHandlerLabels[i]);
- String field = switchVariableValueToField.get(i);
- caseWriter.accept(field);
- if (!doesEachCaseReturnEarly) {
- methodVisitor.visitJumpInsn(Opcodes.GOTO, endOfFieldsSwitch);
- }
- }
- methodVisitor.visitLabel(missingField);
- defaultCase.run();
- if (!doesEachCaseReturnEarly) {
- methodVisitor.visitLabel(endOfFieldsSwitch);
- }
- }
-
- public static void createIntSwitch(MethodVisitor methodVisitor, Collection keySet,
- Consumer caseWriter, Runnable defaultCase,
- boolean doesEachCaseReturnEarly) {
- if (keySet.isEmpty()) {
- defaultCase.run();
- return;
- }
-
- List sortedKeyList = keySet.stream().sorted().collect(Collectors.toList());
-
- int[] keys = new int[sortedKeyList.size()];
- Label[] keyLabels = new Label[keys.length];
-
- { // Scoped to hide keyIndex
- int keyIndex = 0;
- for (Integer key : sortedKeyList) {
- keys[keyIndex] = key;
- keyLabels[keyIndex] = new Label();
- keyIndex++;
- }
- }
-
- Label endOfKeySwitch = new Label();
- Label missingKey = new Label();
-
- methodVisitor.visitLookupSwitchInsn(missingKey, keys, keyLabels);
-
- for (int i = 0; i < keys.length; i++) {
- methodVisitor.visitLabel(keyLabels[i]);
- Integer matchingKey = sortedKeyList.get(i);
-
- caseWriter.accept(matchingKey);
- if (!doesEachCaseReturnEarly) {
- methodVisitor.visitJumpInsn(Opcodes.GOTO, endOfKeySwitch);
- }
- }
- methodVisitor.visitLabel(missingKey);
-
- defaultCase.run();
-
- if (!doesEachCaseReturnEarly) {
- methodVisitor.visitLabel(endOfKeySwitch);
- }
- }
-}
diff --git a/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/CPythonBackedPythonInterpreter.java b/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/CPythonBackedPythonInterpreter.java
deleted file mode 100644
index 90f08c83..00000000
--- a/jpyinterpreter/src/main/java/ai/timefold/jpyinterpreter/CPythonBackedPythonInterpreter.java
+++ /dev/null
@@ -1,213 +0,0 @@
-package ai.timefold.jpyinterpreter;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.Set;
-import java.util.function.BiConsumer;
-import java.util.function.BiFunction;
-import java.util.function.Function;
-
-import ai.timefold.jpyinterpreter.builtins.GlobalBuiltins;
-import ai.timefold.jpyinterpreter.types.CPythonBackedPythonLikeObject;
-import ai.timefold.jpyinterpreter.types.PythonModule;
-import ai.timefold.jpyinterpreter.types.PythonString;
-import ai.timefold.jpyinterpreter.types.collections.PythonLikeTuple;
-import ai.timefold.jpyinterpreter.types.errors.PythonTraceback;
-import ai.timefold.jpyinterpreter.types.numeric.PythonInteger;
-import ai.timefold.jpyinterpreter.types.wrappers.OpaquePythonReference;
-import ai.timefold.jpyinterpreter.types.wrappers.PythonObjectWrapper;
-import ai.timefold.jpyinterpreter.util.ConcurrentWeakIdentityHashMap;
-import ai.timefold.jpyinterpreter.util.function.PentaFunction;
-import ai.timefold.jpyinterpreter.util.function.QuadConsumer;
-import ai.timefold.jpyinterpreter.util.function.QuadFunction;
-import ai.timefold.jpyinterpreter.util.function.TriFunction;
-
-public class CPythonBackedPythonInterpreter implements PythonInterpreter {
- InputStream standardInput;
- PrintStream standardOutput;
- Scanner inputScanner;
-
- Map moduleSpecToModuleMap = new HashMap<>();
-
- final Set hasReferenceSet =
- Collections.newSetFromMap(new ConcurrentWeakIdentityHashMap<>());
-
- public static Map pythonObjectIdToConvertedObjectMap = new HashMap<>();
-
- public static Function lookupPythonReferenceIdPythonFunction;
-
- public static Function lookupPythonReferenceTypePythonFunction;
- public static BiFunction lookupAttributeOnPythonReferencePythonFunction;
- public static BiFunction lookupPointerForAttributeOnPythonReferencePythonFunction;
- public static BiFunction lookupPointerArrayForAttributeOnPythonReferencePythonFunction;
- public static BiConsumer