├── .eslintignore ├── .eslintrc.json ├── .gitignore ├── .prettierrc.json ├── CNAME ├── LICENSE ├── README.md ├── dist ├── bundle.js └── bundle.js.map ├── index.html ├── package-lock.json ├── package.json ├── rollup.config.js └── src ├── dis-table-element.js ├── highlightable-editor.js ├── links.json ├── main.js ├── opcode_links_gen.py └── permalink-element.js /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules/* 2 | docs/* 3 | docs-src/* 4 | dist/* 5 | rollup-config.js 6 | custom-elements.json 7 | package-lock.json 8 | web-dev-server.config.js 9 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": ["eslint:recommended"], 4 | "parser": "@babel/eslint-parser", 5 | "parserOptions": { 6 | "requireConfigFile": false, 7 | "sourceType": "module" 8 | }, 9 | "env": { 10 | "browser": true 11 | }, 12 | "rules": { 13 | "no-unexpected-multiline": "off" 14 | }, 15 | "overrides": [ 16 | { 17 | "files": ["rollup.config.js", "web-test-runner.config.js"], 18 | "env": { 19 | "node": true 20 | } 21 | } 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "singleQuote": true, 5 | "bracketSpacing": false, 6 | "arrowParens": "always", 7 | "bracketSameLine": true, 8 | "printWidth": 127 9 | } 10 | -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | www.dis-this.com -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dis-this 2 | 3 | An online tool to disassemble Python code 4 | 5 | ## Development 6 | 7 | Install packages: 8 | 9 | ``` 10 | npm install 11 | ``` 12 | 13 | Run the development server (with hot reloading): 14 | 15 | ``` 16 | npm run dev 17 | ``` 18 | 19 | Lint the code: 20 | 21 | ``` 22 | npm run lint 23 | ``` 24 | 25 | Format the code: 26 | 27 | ``` 28 | npm run format 29 | ``` 30 | 31 | Build the production version: 32 | 33 | ``` 34 | npm run build 35 | ``` -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Dis This: Online Python Disassembler 8 | 11 | 44 | 45 | 46 | 47 |
48 |

Disassemble Python code

49 |
50 |
51 | 59 |
60 | 63 |
64 |
68 | 72 |
73 | 76 | Loading Pyodide... 77 | 78 | 80 | 81 |
82 | 83 | 88 | 89 |
104 | 105 | 106 | 107 | 108 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dis-this", 3 | "repository": "https://github.com/pamelafox/dis-this", 4 | "license": "Apache-2.0", 5 | "devDependencies": { 6 | "@babel/eslint-parser": "^7.17.0", 7 | "@babel/core": "^7.11.0", 8 | "@rollup/plugin-node-resolve": "^11.1.0", 9 | "@rollup/plugin-terser": "^0.4.0", 10 | "@rollup/plugin-json": "^6.0.0", 11 | "npm-run-all": "^4.1.5", 12 | "rollup": "^2.36.2", 13 | "serve": "^11.3.2", 14 | "eslint": "^8.15.0", 15 | "prettier": "^2.6.2", 16 | "lit-analyzer": "^1.2.1" 17 | }, 18 | "dependencies": { 19 | "@codemirror/lang-python": "^6.0.0", 20 | "codemirror": "^6.0.0", 21 | "lit": "^2.2.4" 22 | }, 23 | "scripts": { 24 | "lint": "npm run lint:lit-analyzer && npm run lint:eslint", 25 | "lint:eslint": "eslint 'src/*.js'", 26 | "lint:lit-analyzer": "lit-analyzer src/*-element.js", 27 | "format": "prettier \"**/*.{js,json}\" --ignore-path ./.eslintignore --write", 28 | "build": "rollup -c", 29 | "watch": "rollup -c -w", 30 | "dev": "npm-run-all --parallel start watch", 31 | "start": "serve" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import terser from '@rollup/plugin-terser'; 3 | import json from '@rollup/plugin-json'; 4 | 5 | // `npm run build` -> `production` is true 6 | // `npm run dev` -> `production` is false 7 | const production = !process.env.ROLLUP_WATCH; 8 | 9 | export default { 10 | input: 'src/main.js', 11 | output: { 12 | file: 'dist/bundle.js', 13 | format: 'iife', 14 | sourcemap: true, 15 | }, 16 | plugins: [ 17 | json(), 18 | resolve(), // tells Rollup how to find date-fns in node_modules 19 | production && terser(), // minify, but only in production 20 | ], 21 | }; 22 | -------------------------------------------------------------------------------- /src/dis-table-element.js: -------------------------------------------------------------------------------- 1 | import {LitElement, html, css} from 'lit'; 2 | 3 | export class DisTable extends LitElement { 4 | static properties = { 5 | operations: {type: Array}, 6 | activeLine: {type: Number}, 7 | links: {type: Object}, 8 | }; 9 | 10 | static styles = css` 11 | .highlighted { 12 | background-color: #d2ffff; 13 | } 14 | `; 15 | 16 | constructor() { 17 | super(); 18 | } 19 | 20 | render() { 21 | if (!this.operations || !this.operations.length) return; 22 | 23 | return html` 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | ${this.operations.map( 36 | (operation) => html` this.onMouseover(operation.lineNo)} 38 | class=${operation.lineNo == this.activeLine ? 'highlighted' : ''}> 39 | 40 | 41 | 44 | 45 | 46 | ` 47 | )} 48 | 49 |
Line numberOffsetOpcode nameOpcode parametersInterpretation of parameters
${operation.lineNo}${operation.offset} 42 | ${operation.opcode} 43 | ${operation.param}${operation.paramD}
50 | `; 51 | } 52 | 53 | onMouseover(lineNo) { 54 | this.activeLine = lineNo; 55 | this.dispatchEvent(new CustomEvent('line-highlight', {detail: {line: lineNo}})); 56 | } 57 | } 58 | 59 | customElements.define('dis-table-element', DisTable); 60 | -------------------------------------------------------------------------------- /src/highlightable-editor.js: -------------------------------------------------------------------------------- 1 | import {basicSetup} from 'codemirror'; 2 | import {EditorState, StateField, StateEffect} from '@codemirror/state'; 3 | import {python} from '@codemirror/lang-python'; 4 | import {EditorView, Decoration} from '@codemirror/view'; 5 | 6 | const addLineHighlight = StateEffect.define(); 7 | 8 | const lineHighlightField = StateField.define({ 9 | create() { 10 | return Decoration.none; 11 | }, 12 | update(lines, tr) { 13 | lines = lines.map(tr.changes); 14 | for (let e of tr.effects) { 15 | if (e.is(addLineHighlight)) { 16 | lines = Decoration.none; 17 | lines = lines.update({add: [lineHighlightMark.range(e.value)]}); 18 | } 19 | } 20 | return lines; 21 | }, 22 | provide: (f) => EditorView.decorations.from(f), 23 | }); 24 | 25 | const lineHighlightMark = Decoration.line({ 26 | attributes: {style: 'background-color: #d2ffff'}, 27 | }); 28 | 29 | export default class HighlightableEditor { 30 | constructor(parent, code, onHighlight) { 31 | this.editorView = new EditorView({ 32 | state: EditorState.create({ 33 | doc: code, 34 | extensions: [basicSetup, lineHighlightField, python()], 35 | }), 36 | parent: parent, 37 | }); 38 | 39 | this.editorView.dom.addEventListener('mousemove', (event) => { 40 | const lastMove = { 41 | x: event.clientX, 42 | y: event.clientY, 43 | target: event.target, 44 | time: Date.now(), 45 | }; 46 | const pos = this.editorView.posAtCoords(lastMove); 47 | let lineNo = this.editorView.state.doc.lineAt(pos).number; 48 | const docPosition = this.editorView.state.doc.line(lineNo).from; 49 | this.editorView.dispatch({effects: addLineHighlight.of(docPosition)}); 50 | onHighlight(lineNo); 51 | }); 52 | } 53 | 54 | getCode() { 55 | return this.editorView.state.doc.toString(); 56 | } 57 | 58 | highlightLine(lineNo) { 59 | if (lineNo <= 0) return; 60 | const docPosition = this.editorView.state.doc.line(lineNo).from; 61 | this.editorView.dispatch({effects: addLineHighlight.of(docPosition)}); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/links.json: -------------------------------------------------------------------------------- 1 | { 2 | "3.9": { 3 | "NOP": "https://docs.python.org/3.9/library/dis.html#opcode-NOP", 4 | "POP_TOP": "https://docs.python.org/3.9/library/dis.html#opcode-POP_TOP", 5 | "ROT_TWO": "https://docs.python.org/3.9/library/dis.html#opcode-ROT_TWO", 6 | "ROT_THREE": "https://docs.python.org/3.9/library/dis.html#opcode-ROT_THREE", 7 | "ROT_FOUR": "https://docs.python.org/3.9/library/dis.html#opcode-ROT_FOUR", 8 | "DUP_TOP": "https://docs.python.org/3.9/library/dis.html#opcode-DUP_TOP", 9 | "DUP_TOP_TWO": "https://docs.python.org/3.9/library/dis.html#opcode-DUP_TOP_TWO", 10 | "UNARY_POSITIVE": "https://docs.python.org/3.9/library/dis.html#opcode-UNARY_POSITIVE", 11 | "UNARY_NEGATIVE": "https://docs.python.org/3.9/library/dis.html#opcode-UNARY_NEGATIVE", 12 | "UNARY_NOT": "https://docs.python.org/3.9/library/dis.html#opcode-UNARY_NOT", 13 | "UNARY_INVERT": "https://docs.python.org/3.9/library/dis.html#opcode-UNARY_INVERT", 14 | "GET_ITER": "https://docs.python.org/3.9/library/dis.html#opcode-GET_ITER", 15 | "GET_YIELD_FROM_ITER": "https://docs.python.org/3.9/library/dis.html#opcode-GET_YIELD_FROM_ITER", 16 | "BINARY_POWER": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_POWER", 17 | "BINARY_MULTIPLY": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_MULTIPLY", 18 | "BINARY_MATRIX_MULTIPLY": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_MATRIX_MULTIPLY", 19 | "BINARY_FLOOR_DIVIDE": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_FLOOR_DIVIDE", 20 | "BINARY_TRUE_DIVIDE": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_TRUE_DIVIDE", 21 | "BINARY_MODULO": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_MODULO", 22 | "BINARY_ADD": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_ADD", 23 | "BINARY_SUBTRACT": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_SUBTRACT", 24 | "BINARY_SUBSCR": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_SUBSCR", 25 | "BINARY_LSHIFT": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_LSHIFT", 26 | "BINARY_RSHIFT": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_RSHIFT", 27 | "BINARY_AND": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_AND", 28 | "BINARY_XOR": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_XOR", 29 | "BINARY_OR": "https://docs.python.org/3.9/library/dis.html#opcode-BINARY_OR", 30 | "INPLACE_POWER": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_POWER", 31 | "INPLACE_MULTIPLY": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_MULTIPLY", 32 | "INPLACE_MATRIX_MULTIPLY": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_MATRIX_MULTIPLY", 33 | "INPLACE_FLOOR_DIVIDE": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_FLOOR_DIVIDE", 34 | "INPLACE_TRUE_DIVIDE": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_TRUE_DIVIDE", 35 | "INPLACE_MODULO": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_MODULO", 36 | "INPLACE_ADD": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_ADD", 37 | "INPLACE_SUBTRACT": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_SUBTRACT", 38 | "INPLACE_LSHIFT": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_LSHIFT", 39 | "INPLACE_RSHIFT": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_RSHIFT", 40 | "INPLACE_AND": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_AND", 41 | "INPLACE_XOR": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_XOR", 42 | "INPLACE_OR": "https://docs.python.org/3.9/library/dis.html#opcode-INPLACE_OR", 43 | "STORE_SUBSCR": "https://docs.python.org/3.9/library/dis.html#opcode-STORE_SUBSCR", 44 | "DELETE_SUBSCR": "https://docs.python.org/3.9/library/dis.html#opcode-DELETE_SUBSCR", 45 | "GET_AWAITABLE": "https://docs.python.org/3.9/library/dis.html#opcode-GET_AWAITABLE", 46 | "GET_AITER": "https://docs.python.org/3.9/library/dis.html#opcode-GET_AITER", 47 | "GET_ANEXT": "https://docs.python.org/3.9/library/dis.html#opcode-GET_ANEXT", 48 | "END_ASYNC_FOR": "https://docs.python.org/3.9/library/dis.html#opcode-END_ASYNC_FOR", 49 | "BEFORE_ASYNC_WITH": "https://docs.python.org/3.9/library/dis.html#opcode-BEFORE_ASYNC_WITH", 50 | "SETUP_ASYNC_WITH": "https://docs.python.org/3.9/library/dis.html#opcode-SETUP_ASYNC_WITH", 51 | "PRINT_EXPR": "https://docs.python.org/3.9/library/dis.html#opcode-PRINT_EXPR", 52 | "SET_ADD": "https://docs.python.org/3.9/library/dis.html#opcode-SET_ADD", 53 | "LIST_APPEND": "https://docs.python.org/3.9/library/dis.html#opcode-LIST_APPEND", 54 | "MAP_ADD": "https://docs.python.org/3.9/library/dis.html#opcode-MAP_ADD", 55 | "RETURN_VALUE": "https://docs.python.org/3.9/library/dis.html#opcode-RETURN_VALUE", 56 | "YIELD_VALUE": "https://docs.python.org/3.9/library/dis.html#opcode-YIELD_VALUE", 57 | "YIELD_FROM": "https://docs.python.org/3.9/library/dis.html#opcode-YIELD_FROM", 58 | "SETUP_ANNOTATIONS": "https://docs.python.org/3.9/library/dis.html#opcode-SETUP_ANNOTATIONS", 59 | "IMPORT_STAR": "https://docs.python.org/3.9/library/dis.html#opcode-IMPORT_STAR", 60 | "POP_BLOCK": "https://docs.python.org/3.9/library/dis.html#opcode-POP_BLOCK", 61 | "POP_EXCEPT": "https://docs.python.org/3.9/library/dis.html#opcode-POP_EXCEPT", 62 | "RERAISE": "https://docs.python.org/3.9/library/dis.html#opcode-RERAISE", 63 | "WITH_EXCEPT_START": "https://docs.python.org/3.9/library/dis.html#opcode-WITH_EXCEPT_START", 64 | "LOAD_ASSERTION_ERROR": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_ASSERTION_ERROR", 65 | "LOAD_BUILD_CLASS": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_BUILD_CLASS", 66 | "SETUP_WITH": "https://docs.python.org/3.9/library/dis.html#opcode-SETUP_WITH", 67 | "STORE_NAME": "https://docs.python.org/3.9/library/dis.html#opcode-STORE_NAME", 68 | "DELETE_NAME": "https://docs.python.org/3.9/library/dis.html#opcode-DELETE_NAME", 69 | "UNPACK_SEQUENCE": "https://docs.python.org/3.9/library/dis.html#opcode-UNPACK_SEQUENCE", 70 | "UNPACK_EX": "https://docs.python.org/3.9/library/dis.html#opcode-UNPACK_EX", 71 | "STORE_ATTR": "https://docs.python.org/3.9/library/dis.html#opcode-STORE_ATTR", 72 | "DELETE_ATTR": "https://docs.python.org/3.9/library/dis.html#opcode-DELETE_ATTR", 73 | "STORE_GLOBAL": "https://docs.python.org/3.9/library/dis.html#opcode-STORE_GLOBAL", 74 | "DELETE_GLOBAL": "https://docs.python.org/3.9/library/dis.html#opcode-DELETE_GLOBAL", 75 | "LOAD_CONST": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_CONST", 76 | "LOAD_NAME": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_NAME", 77 | "BUILD_TUPLE": "https://docs.python.org/3.9/library/dis.html#opcode-BUILD_TUPLE", 78 | "BUILD_LIST": "https://docs.python.org/3.9/library/dis.html#opcode-BUILD_LIST", 79 | "BUILD_SET": "https://docs.python.org/3.9/library/dis.html#opcode-BUILD_SET", 80 | "BUILD_MAP": "https://docs.python.org/3.9/library/dis.html#opcode-BUILD_MAP", 81 | "BUILD_CONST_KEY_MAP": "https://docs.python.org/3.9/library/dis.html#opcode-BUILD_CONST_KEY_MAP", 82 | "BUILD_STRING": "https://docs.python.org/3.9/library/dis.html#opcode-BUILD_STRING", 83 | "LIST_TO_TUPLE": "https://docs.python.org/3.9/library/dis.html#opcode-LIST_TO_TUPLE", 84 | "LIST_EXTEND": "https://docs.python.org/3.9/library/dis.html#opcode-LIST_EXTEND", 85 | "SET_UPDATE": "https://docs.python.org/3.9/library/dis.html#opcode-SET_UPDATE", 86 | "DICT_UPDATE": "https://docs.python.org/3.9/library/dis.html#opcode-DICT_UPDATE", 87 | "DICT_MERGE": "https://docs.python.org/3.9/library/dis.html#opcode-DICT_MERGE", 88 | "LOAD_ATTR": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_ATTR", 89 | "COMPARE_OP": "https://docs.python.org/3.9/library/dis.html#opcode-COMPARE_OP", 90 | "IS_OP": "https://docs.python.org/3.9/library/dis.html#opcode-IS_OP", 91 | "CONTAINS_OP": "https://docs.python.org/3.9/library/dis.html#opcode-CONTAINS_OP", 92 | "IMPORT_NAME": "https://docs.python.org/3.9/library/dis.html#opcode-IMPORT_NAME", 93 | "IMPORT_FROM": "https://docs.python.org/3.9/library/dis.html#opcode-IMPORT_FROM", 94 | "JUMP_FORWARD": "https://docs.python.org/3.9/library/dis.html#opcode-JUMP_FORWARD", 95 | "POP_JUMP_IF_TRUE": "https://docs.python.org/3.9/library/dis.html#opcode-POP_JUMP_IF_TRUE", 96 | "POP_JUMP_IF_FALSE": "https://docs.python.org/3.9/library/dis.html#opcode-POP_JUMP_IF_FALSE", 97 | "JUMP_IF_NOT_EXC_MATCH": "https://docs.python.org/3.9/library/dis.html#opcode-JUMP_IF_NOT_EXC_MATCH", 98 | "JUMP_IF_TRUE_OR_POP": "https://docs.python.org/3.9/library/dis.html#opcode-JUMP_IF_TRUE_OR_POP", 99 | "JUMP_IF_FALSE_OR_POP": "https://docs.python.org/3.9/library/dis.html#opcode-JUMP_IF_FALSE_OR_POP", 100 | "JUMP_ABSOLUTE": "https://docs.python.org/3.9/library/dis.html#opcode-JUMP_ABSOLUTE", 101 | "FOR_ITER": "https://docs.python.org/3.9/library/dis.html#opcode-FOR_ITER", 102 | "LOAD_GLOBAL": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_GLOBAL", 103 | "SETUP_FINALLY": "https://docs.python.org/3.9/library/dis.html#opcode-SETUP_FINALLY", 104 | "LOAD_FAST": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_FAST", 105 | "STORE_FAST": "https://docs.python.org/3.9/library/dis.html#opcode-STORE_FAST", 106 | "DELETE_FAST": "https://docs.python.org/3.9/library/dis.html#opcode-DELETE_FAST", 107 | "LOAD_CLOSURE": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_CLOSURE", 108 | "LOAD_DEREF": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_DEREF", 109 | "LOAD_CLASSDEREF": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_CLASSDEREF", 110 | "STORE_DEREF": "https://docs.python.org/3.9/library/dis.html#opcode-STORE_DEREF", 111 | "DELETE_DEREF": "https://docs.python.org/3.9/library/dis.html#opcode-DELETE_DEREF", 112 | "RAISE_VARARGS": "https://docs.python.org/3.9/library/dis.html#opcode-RAISE_VARARGS", 113 | "CALL_FUNCTION": "https://docs.python.org/3.9/library/dis.html#opcode-CALL_FUNCTION", 114 | "CALL_FUNCTION_KW": "https://docs.python.org/3.9/library/dis.html#opcode-CALL_FUNCTION_KW", 115 | "CALL_FUNCTION_EX": "https://docs.python.org/3.9/library/dis.html#opcode-CALL_FUNCTION_EX", 116 | "LOAD_METHOD": "https://docs.python.org/3.9/library/dis.html#opcode-LOAD_METHOD", 117 | "CALL_METHOD": "https://docs.python.org/3.9/library/dis.html#opcode-CALL_METHOD", 118 | "MAKE_FUNCTION": "https://docs.python.org/3.9/library/dis.html#opcode-MAKE_FUNCTION", 119 | "BUILD_SLICE": "https://docs.python.org/3.9/library/dis.html#opcode-BUILD_SLICE", 120 | "EXTENDED_ARG": "https://docs.python.org/3.9/library/dis.html#opcode-EXTENDED_ARG", 121 | "FORMAT_VALUE": "https://docs.python.org/3.9/library/dis.html#opcode-FORMAT_VALUE", 122 | "HAVE_ARGUMENT": "https://docs.python.org/3.9/library/dis.html#opcode-HAVE_ARGUMENT" 123 | }, 124 | "3.10": { 125 | "NOP": "https://docs.python.org/3.10/library/dis.html#opcode-NOP", 126 | "POP_TOP": "https://docs.python.org/3.10/library/dis.html#opcode-POP_TOP", 127 | "ROT_TWO": "https://docs.python.org/3.10/library/dis.html#opcode-ROT_TWO", 128 | "ROT_THREE": "https://docs.python.org/3.10/library/dis.html#opcode-ROT_THREE", 129 | "ROT_FOUR": "https://docs.python.org/3.10/library/dis.html#opcode-ROT_FOUR", 130 | "DUP_TOP": "https://docs.python.org/3.10/library/dis.html#opcode-DUP_TOP", 131 | "DUP_TOP_TWO": "https://docs.python.org/3.10/library/dis.html#opcode-DUP_TOP_TWO", 132 | "UNARY_POSITIVE": "https://docs.python.org/3.10/library/dis.html#opcode-UNARY_POSITIVE", 133 | "UNARY_NEGATIVE": "https://docs.python.org/3.10/library/dis.html#opcode-UNARY_NEGATIVE", 134 | "UNARY_NOT": "https://docs.python.org/3.10/library/dis.html#opcode-UNARY_NOT", 135 | "UNARY_INVERT": "https://docs.python.org/3.10/library/dis.html#opcode-UNARY_INVERT", 136 | "GET_ITER": "https://docs.python.org/3.10/library/dis.html#opcode-GET_ITER", 137 | "GET_YIELD_FROM_ITER": "https://docs.python.org/3.10/library/dis.html#opcode-GET_YIELD_FROM_ITER", 138 | "BINARY_POWER": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_POWER", 139 | "BINARY_MULTIPLY": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_MULTIPLY", 140 | "BINARY_MATRIX_MULTIPLY": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_MATRIX_MULTIPLY", 141 | "BINARY_FLOOR_DIVIDE": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_FLOOR_DIVIDE", 142 | "BINARY_TRUE_DIVIDE": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_TRUE_DIVIDE", 143 | "BINARY_MODULO": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_MODULO", 144 | "BINARY_ADD": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_ADD", 145 | "BINARY_SUBTRACT": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_SUBTRACT", 146 | "BINARY_SUBSCR": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_SUBSCR", 147 | "BINARY_LSHIFT": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_LSHIFT", 148 | "BINARY_RSHIFT": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_RSHIFT", 149 | "BINARY_AND": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_AND", 150 | "BINARY_XOR": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_XOR", 151 | "BINARY_OR": "https://docs.python.org/3.10/library/dis.html#opcode-BINARY_OR", 152 | "INPLACE_POWER": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_POWER", 153 | "INPLACE_MULTIPLY": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_MULTIPLY", 154 | "INPLACE_MATRIX_MULTIPLY": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_MATRIX_MULTIPLY", 155 | "INPLACE_FLOOR_DIVIDE": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_FLOOR_DIVIDE", 156 | "INPLACE_TRUE_DIVIDE": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_TRUE_DIVIDE", 157 | "INPLACE_MODULO": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_MODULO", 158 | "INPLACE_ADD": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_ADD", 159 | "INPLACE_SUBTRACT": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_SUBTRACT", 160 | "INPLACE_LSHIFT": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_LSHIFT", 161 | "INPLACE_RSHIFT": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_RSHIFT", 162 | "INPLACE_AND": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_AND", 163 | "INPLACE_XOR": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_XOR", 164 | "INPLACE_OR": "https://docs.python.org/3.10/library/dis.html#opcode-INPLACE_OR", 165 | "STORE_SUBSCR": "https://docs.python.org/3.10/library/dis.html#opcode-STORE_SUBSCR", 166 | "DELETE_SUBSCR": "https://docs.python.org/3.10/library/dis.html#opcode-DELETE_SUBSCR", 167 | "GET_AWAITABLE": "https://docs.python.org/3.10/library/dis.html#opcode-GET_AWAITABLE", 168 | "GET_AITER": "https://docs.python.org/3.10/library/dis.html#opcode-GET_AITER", 169 | "GET_ANEXT": "https://docs.python.org/3.10/library/dis.html#opcode-GET_ANEXT", 170 | "END_ASYNC_FOR": "https://docs.python.org/3.10/library/dis.html#opcode-END_ASYNC_FOR", 171 | "BEFORE_ASYNC_WITH": "https://docs.python.org/3.10/library/dis.html#opcode-BEFORE_ASYNC_WITH", 172 | "SETUP_ASYNC_WITH": "https://docs.python.org/3.10/library/dis.html#opcode-SETUP_ASYNC_WITH", 173 | "PRINT_EXPR": "https://docs.python.org/3.10/library/dis.html#opcode-PRINT_EXPR", 174 | "SET_ADD": "https://docs.python.org/3.10/library/dis.html#opcode-SET_ADD", 175 | "LIST_APPEND": "https://docs.python.org/3.10/library/dis.html#opcode-LIST_APPEND", 176 | "MAP_ADD": "https://docs.python.org/3.10/library/dis.html#opcode-MAP_ADD", 177 | "RETURN_VALUE": "https://docs.python.org/3.10/library/dis.html#opcode-RETURN_VALUE", 178 | "YIELD_VALUE": "https://docs.python.org/3.10/library/dis.html#opcode-YIELD_VALUE", 179 | "YIELD_FROM": "https://docs.python.org/3.10/library/dis.html#opcode-YIELD_FROM", 180 | "SETUP_ANNOTATIONS": "https://docs.python.org/3.10/library/dis.html#opcode-SETUP_ANNOTATIONS", 181 | "IMPORT_STAR": "https://docs.python.org/3.10/library/dis.html#opcode-IMPORT_STAR", 182 | "POP_BLOCK": "https://docs.python.org/3.10/library/dis.html#opcode-POP_BLOCK", 183 | "POP_EXCEPT": "https://docs.python.org/3.10/library/dis.html#opcode-POP_EXCEPT", 184 | "RERAISE": "https://docs.python.org/3.10/library/dis.html#opcode-RERAISE", 185 | "WITH_EXCEPT_START": "https://docs.python.org/3.10/library/dis.html#opcode-WITH_EXCEPT_START", 186 | "LOAD_ASSERTION_ERROR": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_ASSERTION_ERROR", 187 | "LOAD_BUILD_CLASS": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_BUILD_CLASS", 188 | "SETUP_WITH": "https://docs.python.org/3.10/library/dis.html#opcode-SETUP_WITH", 189 | "COPY_DICT_WITHOUT_KEYS": "https://docs.python.org/3.10/library/dis.html#opcode-COPY_DICT_WITHOUT_KEYS", 190 | "GET_LEN": "https://docs.python.org/3.10/library/dis.html#opcode-GET_LEN", 191 | "MATCH_MAPPING": "https://docs.python.org/3.10/library/dis.html#opcode-MATCH_MAPPING", 192 | "MATCH_SEQUENCE": "https://docs.python.org/3.10/library/dis.html#opcode-MATCH_SEQUENCE", 193 | "MATCH_KEYS": "https://docs.python.org/3.10/library/dis.html#opcode-MATCH_KEYS", 194 | "STORE_NAME": "https://docs.python.org/3.10/library/dis.html#opcode-STORE_NAME", 195 | "DELETE_NAME": "https://docs.python.org/3.10/library/dis.html#opcode-DELETE_NAME", 196 | "UNPACK_SEQUENCE": "https://docs.python.org/3.10/library/dis.html#opcode-UNPACK_SEQUENCE", 197 | "UNPACK_EX": "https://docs.python.org/3.10/library/dis.html#opcode-UNPACK_EX", 198 | "STORE_ATTR": "https://docs.python.org/3.10/library/dis.html#opcode-STORE_ATTR", 199 | "DELETE_ATTR": "https://docs.python.org/3.10/library/dis.html#opcode-DELETE_ATTR", 200 | "STORE_GLOBAL": "https://docs.python.org/3.10/library/dis.html#opcode-STORE_GLOBAL", 201 | "DELETE_GLOBAL": "https://docs.python.org/3.10/library/dis.html#opcode-DELETE_GLOBAL", 202 | "LOAD_CONST": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_CONST", 203 | "LOAD_NAME": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_NAME", 204 | "BUILD_TUPLE": "https://docs.python.org/3.10/library/dis.html#opcode-BUILD_TUPLE", 205 | "BUILD_LIST": "https://docs.python.org/3.10/library/dis.html#opcode-BUILD_LIST", 206 | "BUILD_SET": "https://docs.python.org/3.10/library/dis.html#opcode-BUILD_SET", 207 | "BUILD_MAP": "https://docs.python.org/3.10/library/dis.html#opcode-BUILD_MAP", 208 | "BUILD_CONST_KEY_MAP": "https://docs.python.org/3.10/library/dis.html#opcode-BUILD_CONST_KEY_MAP", 209 | "BUILD_STRING": "https://docs.python.org/3.10/library/dis.html#opcode-BUILD_STRING", 210 | "LIST_TO_TUPLE": "https://docs.python.org/3.10/library/dis.html#opcode-LIST_TO_TUPLE", 211 | "LIST_EXTEND": "https://docs.python.org/3.10/library/dis.html#opcode-LIST_EXTEND", 212 | "SET_UPDATE": "https://docs.python.org/3.10/library/dis.html#opcode-SET_UPDATE", 213 | "DICT_UPDATE": "https://docs.python.org/3.10/library/dis.html#opcode-DICT_UPDATE", 214 | "DICT_MERGE": "https://docs.python.org/3.10/library/dis.html#opcode-DICT_MERGE", 215 | "LOAD_ATTR": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_ATTR", 216 | "COMPARE_OP": "https://docs.python.org/3.10/library/dis.html#opcode-COMPARE_OP", 217 | "IS_OP": "https://docs.python.org/3.10/library/dis.html#opcode-IS_OP", 218 | "CONTAINS_OP": "https://docs.python.org/3.10/library/dis.html#opcode-CONTAINS_OP", 219 | "IMPORT_NAME": "https://docs.python.org/3.10/library/dis.html#opcode-IMPORT_NAME", 220 | "IMPORT_FROM": "https://docs.python.org/3.10/library/dis.html#opcode-IMPORT_FROM", 221 | "JUMP_FORWARD": "https://docs.python.org/3.10/library/dis.html#opcode-JUMP_FORWARD", 222 | "POP_JUMP_IF_TRUE": "https://docs.python.org/3.10/library/dis.html#opcode-POP_JUMP_IF_TRUE", 223 | "POP_JUMP_IF_FALSE": "https://docs.python.org/3.10/library/dis.html#opcode-POP_JUMP_IF_FALSE", 224 | "JUMP_IF_NOT_EXC_MATCH": "https://docs.python.org/3.10/library/dis.html#opcode-JUMP_IF_NOT_EXC_MATCH", 225 | "JUMP_IF_TRUE_OR_POP": "https://docs.python.org/3.10/library/dis.html#opcode-JUMP_IF_TRUE_OR_POP", 226 | "JUMP_IF_FALSE_OR_POP": "https://docs.python.org/3.10/library/dis.html#opcode-JUMP_IF_FALSE_OR_POP", 227 | "JUMP_ABSOLUTE": "https://docs.python.org/3.10/library/dis.html#opcode-JUMP_ABSOLUTE", 228 | "FOR_ITER": "https://docs.python.org/3.10/library/dis.html#opcode-FOR_ITER", 229 | "LOAD_GLOBAL": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_GLOBAL", 230 | "SETUP_FINALLY": "https://docs.python.org/3.10/library/dis.html#opcode-SETUP_FINALLY", 231 | "LOAD_FAST": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_FAST", 232 | "STORE_FAST": "https://docs.python.org/3.10/library/dis.html#opcode-STORE_FAST", 233 | "DELETE_FAST": "https://docs.python.org/3.10/library/dis.html#opcode-DELETE_FAST", 234 | "LOAD_CLOSURE": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_CLOSURE", 235 | "LOAD_DEREF": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_DEREF", 236 | "LOAD_CLASSDEREF": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_CLASSDEREF", 237 | "STORE_DEREF": "https://docs.python.org/3.10/library/dis.html#opcode-STORE_DEREF", 238 | "DELETE_DEREF": "https://docs.python.org/3.10/library/dis.html#opcode-DELETE_DEREF", 239 | "RAISE_VARARGS": "https://docs.python.org/3.10/library/dis.html#opcode-RAISE_VARARGS", 240 | "CALL_FUNCTION": "https://docs.python.org/3.10/library/dis.html#opcode-CALL_FUNCTION", 241 | "CALL_FUNCTION_KW": "https://docs.python.org/3.10/library/dis.html#opcode-CALL_FUNCTION_KW", 242 | "CALL_FUNCTION_EX": "https://docs.python.org/3.10/library/dis.html#opcode-CALL_FUNCTION_EX", 243 | "LOAD_METHOD": "https://docs.python.org/3.10/library/dis.html#opcode-LOAD_METHOD", 244 | "CALL_METHOD": "https://docs.python.org/3.10/library/dis.html#opcode-CALL_METHOD", 245 | "MAKE_FUNCTION": "https://docs.python.org/3.10/library/dis.html#opcode-MAKE_FUNCTION", 246 | "BUILD_SLICE": "https://docs.python.org/3.10/library/dis.html#opcode-BUILD_SLICE", 247 | "EXTENDED_ARG": "https://docs.python.org/3.10/library/dis.html#opcode-EXTENDED_ARG", 248 | "FORMAT_VALUE": "https://docs.python.org/3.10/library/dis.html#opcode-FORMAT_VALUE", 249 | "MATCH_CLASS": "https://docs.python.org/3.10/library/dis.html#opcode-MATCH_CLASS", 250 | "GEN_START": "https://docs.python.org/3.10/library/dis.html#opcode-GEN_START", 251 | "ROT_N": "https://docs.python.org/3.10/library/dis.html#opcode-ROT_N", 252 | "HAVE_ARGUMENT": "https://docs.python.org/3.10/library/dis.html#opcode-HAVE_ARGUMENT" 253 | }, 254 | "3.11": { 255 | "NOP": "https://docs.python.org/3.11/library/dis.html#opcode-NOP", 256 | "POP_TOP": "https://docs.python.org/3.11/library/dis.html#opcode-POP_TOP", 257 | "COPY": "https://docs.python.org/3.11/library/dis.html#opcode-COPY", 258 | "SWAP": "https://docs.python.org/3.11/library/dis.html#opcode-SWAP", 259 | "CACHE": "https://docs.python.org/3.11/library/dis.html#opcode-CACHE", 260 | "UNARY_POSITIVE": "https://docs.python.org/3.11/library/dis.html#opcode-UNARY_POSITIVE", 261 | "UNARY_NEGATIVE": "https://docs.python.org/3.11/library/dis.html#opcode-UNARY_NEGATIVE", 262 | "UNARY_NOT": "https://docs.python.org/3.11/library/dis.html#opcode-UNARY_NOT", 263 | "UNARY_INVERT": "https://docs.python.org/3.11/library/dis.html#opcode-UNARY_INVERT", 264 | "GET_ITER": "https://docs.python.org/3.11/library/dis.html#opcode-GET_ITER", 265 | "GET_YIELD_FROM_ITER": "https://docs.python.org/3.11/library/dis.html#opcode-GET_YIELD_FROM_ITER", 266 | "BINARY_OP": "https://docs.python.org/3.11/library/dis.html#opcode-BINARY_OP", 267 | "BINARY_SUBSCR": "https://docs.python.org/3.11/library/dis.html#opcode-BINARY_SUBSCR", 268 | "STORE_SUBSCR": "https://docs.python.org/3.11/library/dis.html#opcode-STORE_SUBSCR", 269 | "DELETE_SUBSCR": "https://docs.python.org/3.11/library/dis.html#opcode-DELETE_SUBSCR", 270 | "GET_AWAITABLE": "https://docs.python.org/3.11/library/dis.html#opcode-GET_AWAITABLE", 271 | "GET_AITER": "https://docs.python.org/3.11/library/dis.html#opcode-GET_AITER", 272 | "GET_ANEXT": "https://docs.python.org/3.11/library/dis.html#opcode-GET_ANEXT", 273 | "END_ASYNC_FOR": "https://docs.python.org/3.11/library/dis.html#opcode-END_ASYNC_FOR", 274 | "BEFORE_ASYNC_WITH": "https://docs.python.org/3.11/library/dis.html#opcode-BEFORE_ASYNC_WITH", 275 | "PRINT_EXPR": "https://docs.python.org/3.11/library/dis.html#opcode-PRINT_EXPR", 276 | "SET_ADD": "https://docs.python.org/3.11/library/dis.html#opcode-SET_ADD", 277 | "LIST_APPEND": "https://docs.python.org/3.11/library/dis.html#opcode-LIST_APPEND", 278 | "MAP_ADD": "https://docs.python.org/3.11/library/dis.html#opcode-MAP_ADD", 279 | "RETURN_VALUE": "https://docs.python.org/3.11/library/dis.html#opcode-RETURN_VALUE", 280 | "YIELD_VALUE": "https://docs.python.org/3.11/library/dis.html#opcode-YIELD_VALUE", 281 | "SETUP_ANNOTATIONS": "https://docs.python.org/3.11/library/dis.html#opcode-SETUP_ANNOTATIONS", 282 | "IMPORT_STAR": "https://docs.python.org/3.11/library/dis.html#opcode-IMPORT_STAR", 283 | "POP_EXCEPT": "https://docs.python.org/3.11/library/dis.html#opcode-POP_EXCEPT", 284 | "RERAISE": "https://docs.python.org/3.11/library/dis.html#opcode-RERAISE", 285 | "PUSH_EXC_INFO": "https://docs.python.org/3.11/library/dis.html#opcode-PUSH_EXC_INFO", 286 | "CHECK_EXC_MATCH": "https://docs.python.org/3.11/library/dis.html#opcode-CHECK_EXC_MATCH", 287 | "CHECK_EG_MATCH": "https://docs.python.org/3.11/library/dis.html#opcode-CHECK_EG_MATCH", 288 | "PREP_RERAISE_STAR": "https://docs.python.org/3.11/library/dis.html#opcode-PREP_RERAISE_STAR", 289 | "WITH_EXCEPT_START": "https://docs.python.org/3.11/library/dis.html#opcode-WITH_EXCEPT_START", 290 | "LOAD_ASSERTION_ERROR": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_ASSERTION_ERROR", 291 | "LOAD_BUILD_CLASS": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_BUILD_CLASS", 292 | "BEFORE_WITH": "https://docs.python.org/3.11/library/dis.html#opcode-BEFORE_WITH", 293 | "GET_LEN": "https://docs.python.org/3.11/library/dis.html#opcode-GET_LEN", 294 | "MATCH_MAPPING": "https://docs.python.org/3.11/library/dis.html#opcode-MATCH_MAPPING", 295 | "MATCH_SEQUENCE": "https://docs.python.org/3.11/library/dis.html#opcode-MATCH_SEQUENCE", 296 | "MATCH_KEYS": "https://docs.python.org/3.11/library/dis.html#opcode-MATCH_KEYS", 297 | "STORE_NAME": "https://docs.python.org/3.11/library/dis.html#opcode-STORE_NAME", 298 | "DELETE_NAME": "https://docs.python.org/3.11/library/dis.html#opcode-DELETE_NAME", 299 | "UNPACK_SEQUENCE": "https://docs.python.org/3.11/library/dis.html#opcode-UNPACK_SEQUENCE", 300 | "UNPACK_EX": "https://docs.python.org/3.11/library/dis.html#opcode-UNPACK_EX", 301 | "STORE_ATTR": "https://docs.python.org/3.11/library/dis.html#opcode-STORE_ATTR", 302 | "DELETE_ATTR": "https://docs.python.org/3.11/library/dis.html#opcode-DELETE_ATTR", 303 | "STORE_GLOBAL": "https://docs.python.org/3.11/library/dis.html#opcode-STORE_GLOBAL", 304 | "DELETE_GLOBAL": "https://docs.python.org/3.11/library/dis.html#opcode-DELETE_GLOBAL", 305 | "LOAD_CONST": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_CONST", 306 | "LOAD_NAME": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_NAME", 307 | "BUILD_TUPLE": "https://docs.python.org/3.11/library/dis.html#opcode-BUILD_TUPLE", 308 | "BUILD_LIST": "https://docs.python.org/3.11/library/dis.html#opcode-BUILD_LIST", 309 | "BUILD_SET": "https://docs.python.org/3.11/library/dis.html#opcode-BUILD_SET", 310 | "BUILD_MAP": "https://docs.python.org/3.11/library/dis.html#opcode-BUILD_MAP", 311 | "BUILD_CONST_KEY_MAP": "https://docs.python.org/3.11/library/dis.html#opcode-BUILD_CONST_KEY_MAP", 312 | "BUILD_STRING": "https://docs.python.org/3.11/library/dis.html#opcode-BUILD_STRING", 313 | "LIST_TO_TUPLE": "https://docs.python.org/3.11/library/dis.html#opcode-LIST_TO_TUPLE", 314 | "LIST_EXTEND": "https://docs.python.org/3.11/library/dis.html#opcode-LIST_EXTEND", 315 | "SET_UPDATE": "https://docs.python.org/3.11/library/dis.html#opcode-SET_UPDATE", 316 | "DICT_UPDATE": "https://docs.python.org/3.11/library/dis.html#opcode-DICT_UPDATE", 317 | "DICT_MERGE": "https://docs.python.org/3.11/library/dis.html#opcode-DICT_MERGE", 318 | "LOAD_ATTR": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_ATTR", 319 | "COMPARE_OP": "https://docs.python.org/3.11/library/dis.html#opcode-COMPARE_OP", 320 | "IS_OP": "https://docs.python.org/3.11/library/dis.html#opcode-IS_OP", 321 | "CONTAINS_OP": "https://docs.python.org/3.11/library/dis.html#opcode-CONTAINS_OP", 322 | "IMPORT_NAME": "https://docs.python.org/3.11/library/dis.html#opcode-IMPORT_NAME", 323 | "IMPORT_FROM": "https://docs.python.org/3.11/library/dis.html#opcode-IMPORT_FROM", 324 | "JUMP_FORWARD": "https://docs.python.org/3.11/library/dis.html#opcode-JUMP_FORWARD", 325 | "JUMP_BACKWARD": "https://docs.python.org/3.11/library/dis.html#opcode-JUMP_BACKWARD", 326 | "JUMP_BACKWARD_NO_INTERRUPT": "https://docs.python.org/3.11/library/dis.html#opcode-JUMP_BACKWARD_NO_INTERRUPT", 327 | "POP_JUMP_FORWARD_IF_TRUE": "https://docs.python.org/3.11/library/dis.html#opcode-POP_JUMP_FORWARD_IF_TRUE", 328 | "POP_JUMP_BACKWARD_IF_TRUE": "https://docs.python.org/3.11/library/dis.html#opcode-POP_JUMP_BACKWARD_IF_TRUE", 329 | "POP_JUMP_FORWARD_IF_FALSE": "https://docs.python.org/3.11/library/dis.html#opcode-POP_JUMP_FORWARD_IF_FALSE", 330 | "POP_JUMP_BACKWARD_IF_FALSE": "https://docs.python.org/3.11/library/dis.html#opcode-POP_JUMP_BACKWARD_IF_FALSE", 331 | "POP_JUMP_FORWARD_IF_NOT_NONE": "https://docs.python.org/3.11/library/dis.html#opcode-POP_JUMP_FORWARD_IF_NOT_NONE", 332 | "POP_JUMP_BACKWARD_IF_NOT_NONE": "https://docs.python.org/3.11/library/dis.html#opcode-POP_JUMP_BACKWARD_IF_NOT_NONE", 333 | "POP_JUMP_FORWARD_IF_NONE": "https://docs.python.org/3.11/library/dis.html#opcode-POP_JUMP_FORWARD_IF_NONE", 334 | "POP_JUMP_BACKWARD_IF_NONE": "https://docs.python.org/3.11/library/dis.html#opcode-POP_JUMP_BACKWARD_IF_NONE", 335 | "JUMP_IF_TRUE_OR_POP": "https://docs.python.org/3.11/library/dis.html#opcode-JUMP_IF_TRUE_OR_POP", 336 | "JUMP_IF_FALSE_OR_POP": "https://docs.python.org/3.11/library/dis.html#opcode-JUMP_IF_FALSE_OR_POP", 337 | "FOR_ITER": "https://docs.python.org/3.11/library/dis.html#opcode-FOR_ITER", 338 | "LOAD_GLOBAL": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_GLOBAL", 339 | "LOAD_FAST": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_FAST", 340 | "STORE_FAST": "https://docs.python.org/3.11/library/dis.html#opcode-STORE_FAST", 341 | "DELETE_FAST": "https://docs.python.org/3.11/library/dis.html#opcode-DELETE_FAST", 342 | "MAKE_CELL": "https://docs.python.org/3.11/library/dis.html#opcode-MAKE_CELL", 343 | "LOAD_CLOSURE": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_CLOSURE", 344 | "LOAD_DEREF": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_DEREF", 345 | "LOAD_CLASSDEREF": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_CLASSDEREF", 346 | "STORE_DEREF": "https://docs.python.org/3.11/library/dis.html#opcode-STORE_DEREF", 347 | "DELETE_DEREF": "https://docs.python.org/3.11/library/dis.html#opcode-DELETE_DEREF", 348 | "COPY_FREE_VARS": "https://docs.python.org/3.11/library/dis.html#opcode-COPY_FREE_VARS", 349 | "RAISE_VARARGS": "https://docs.python.org/3.11/library/dis.html#opcode-RAISE_VARARGS", 350 | "CALL": "https://docs.python.org/3.11/library/dis.html#opcode-CALL", 351 | "CALL_FUNCTION_EX": "https://docs.python.org/3.11/library/dis.html#opcode-CALL_FUNCTION_EX", 352 | "LOAD_METHOD": "https://docs.python.org/3.11/library/dis.html#opcode-LOAD_METHOD", 353 | "PRECALL": "https://docs.python.org/3.11/library/dis.html#opcode-PRECALL", 354 | "PUSH_NULL": "https://docs.python.org/3.11/library/dis.html#opcode-PUSH_NULL", 355 | "KW_NAMES": "https://docs.python.org/3.11/library/dis.html#opcode-KW_NAMES", 356 | "MAKE_FUNCTION": "https://docs.python.org/3.11/library/dis.html#opcode-MAKE_FUNCTION", 357 | "BUILD_SLICE": "https://docs.python.org/3.11/library/dis.html#opcode-BUILD_SLICE", 358 | "EXTENDED_ARG": "https://docs.python.org/3.11/library/dis.html#opcode-EXTENDED_ARG", 359 | "FORMAT_VALUE": "https://docs.python.org/3.11/library/dis.html#opcode-FORMAT_VALUE", 360 | "MATCH_CLASS": "https://docs.python.org/3.11/library/dis.html#opcode-MATCH_CLASS", 361 | "RESUME": "https://docs.python.org/3.11/library/dis.html#opcode-RESUME", 362 | "RETURN_GENERATOR": "https://docs.python.org/3.11/library/dis.html#opcode-RETURN_GENERATOR", 363 | "SEND": "https://docs.python.org/3.11/library/dis.html#opcode-SEND", 364 | "ASYNC_GEN_WRAP": "https://docs.python.org/3.11/library/dis.html#opcode-ASYNC_GEN_WRAP", 365 | "HAVE_ARGUMENT": "https://docs.python.org/3.11/library/dis.html#opcode-HAVE_ARGUMENT", 366 | "NB_ADD": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L872", 367 | "NB_AND": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L873", 368 | "NB_FLOOR_DIVIDE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L874", 369 | "NB_LSHIFT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L875", 370 | "NB_MATRIX_MULTIPLY": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L876", 371 | "NB_MULTIPLY": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L877", 372 | "NB_REMAINDER": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L878", 373 | "NB_OR": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L879", 374 | "NB_POWER": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L880", 375 | "NB_RSHIFT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L881", 376 | "NB_SUBTRACT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L882", 377 | "NB_TRUE_DIVIDE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L883", 378 | "NB_XOR": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L884", 379 | "NB_INPLACE_ADD": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L885", 380 | "NB_INPLACE_AND": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L886", 381 | "NB_INPLACE_FLOOR_DIVIDE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L887", 382 | "NB_INPLACE_LSHIFT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L888", 383 | "NB_INPLACE_MATRIX_MULTIPLY": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L889", 384 | "NB_INPLACE_MULTIPLY": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L890", 385 | "NB_INPLACE_REMAINDER": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L891", 386 | "NB_INPLACE_OR": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L892", 387 | "NB_INPLACE_POWER": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L893", 388 | "NB_INPLACE_RSHIFT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L894", 389 | "NB_INPLACE_SUBTRACT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L895", 390 | "NB_INPLACE_TRUE_DIVIDE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L896", 391 | "NB_INPLACE_XOR": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L897", 392 | "RESUME_QUICK": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1780", 393 | "LOAD_FAST__LOAD_FAST": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1826", 394 | "LOAD_FAST__LOAD_CONST": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1844", 395 | "STORE_FAST__LOAD_FAST": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1859", 396 | "STORE_FAST__STORE_FAST": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1873", 397 | "LOAD_CONST__LOAD_FAST": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1883", 398 | "BINARY_OP_MULTIPLY_INT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1958", 399 | "BINARY_OP_MULTIPLY_FLOAT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1977", 400 | "BINARY_OP_SUBTRACT_INT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L1998", 401 | "BINARY_OP_SUBTRACT_FLOAT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2017", 402 | "BINARY_OP_ADD_UNICODE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2037", 403 | "BINARY_OP_INPLACE_ADD_UNICODE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2056", 404 | "BINARY_OP_ADD_FLOAT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2092", 405 | "BINARY_OP_ADD_INT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2113", 406 | "BINARY_SUBSCR_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2146", 407 | "BINARY_SUBSCR_LIST_INT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2165", 408 | "BINARY_SUBSCR_TUPLE_INT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2190", 409 | "BINARY_SUBSCR_DICT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2215", 410 | "BINARY_SUBSCR_GETITEM": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2234", 411 | "STORE_SUBSCR_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2312", 412 | "STORE_SUBSCR_LIST_INT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2331", 413 | "STORE_SUBSCR_DICT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2357", 414 | "UNPACK_SEQUENCE_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2808", 415 | "UNPACK_SEQUENCE_TWO_TUPLE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2824", 416 | "UNPACK_SEQUENCE_TUPLE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2836", 417 | "UNPACK_SEQUENCE_LIST": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L2851", 418 | "LOAD_GLOBAL_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3049", 419 | "LOAD_GLOBAL_MODULE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3068", 420 | "LOAD_GLOBAL_BUILTIN": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3089", 421 | "LOAD_ATTR_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3474", 422 | "LOAD_ATTR_INSTANCE_VALUE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3494", 423 | "LOAD_ATTR_MODULE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3517", 424 | "LOAD_ATTR_WITH_HINT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3529", 425 | "LOAD_ATTR_SLOT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3564", 426 | "STORE_ATTR_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3584", 427 | "STORE_ATTR_INSTANCE_VALUE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3604", 428 | "STORE_ATTR_WITH_HINT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3632", 429 | "STORE_ATTR_SLOT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3679", 430 | "COMPARE_OP_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3715", 431 | "COMPARE_OP_FLOAT_JUMP": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3732", 432 | "COMPARE_OP_INT_JUMP": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3774", 433 | "COMPARE_OP_STR_JUMP": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L3817", 434 | "JUMP_BACKWARD_QUICK": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4205", 435 | "LOAD_METHOD_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4522", 436 | "LOAD_METHOD_WITH_VALUES": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4542", 437 | "LOAD_METHOD_WITH_DICT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4568", 438 | "LOAD_METHOD_NO_DICT": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4600", 439 | "LOAD_METHOD_MODULE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4619", 440 | "LOAD_METHOD_CLASS": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4632", 441 | "PRECALL_BOUND_METHOD": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4701", 442 | "PRECALL_PYFUNC": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4717", 443 | "PRECALL_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4795", 444 | "CALL_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4817", 445 | "CALL_PY_EXACT_ARGS": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4839", 446 | "CALL_PY_WITH_DEFAULTS": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4873", 447 | "PRECALL_NO_KW_TYPE_1": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4915", 448 | "PRECALL_NO_KW_STR_1": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4933", 449 | "PRECALL_NO_KW_TUPLE_1": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4955", 450 | "PRECALL_BUILTIN_CLASS": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L4976", 451 | "PRECALL_NO_KW_BUILTIN_O": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5004", 452 | "PRECALL_NO_KW_BUILTIN_FAST": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5038", 453 | "PRECALL_BUILTIN_FAST_WITH_KEYWORDS": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5078", 454 | "PRECALL_NO_KW_LEN": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5117", 455 | "PRECALL_NO_KW_ISINSTANCE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5147", 456 | "PRECALL_NO_KW_LIST_APPEND": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5180", 457 | "PRECALL_NO_KW_METHOD_DESCRIPTOR_O": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5203", 458 | "PRECALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5239", 459 | "PRECALL_NO_KW_METHOD_DESCRIPTOR_NOARGS": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5276", 460 | "PRECALL_NO_KW_METHOD_DESCRIPTOR_FAST": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5310", 461 | "BINARY_OP_ADAPTIVE": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5562", 462 | "EXTENDED_ARG_QUICK": "https://github.com/python/cpython/blob/v3.11.1/Python/ceval.c#L5604" 463 | } 464 | } 465 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | import './dis-table-element.js'; 2 | import './permalink-element.js'; 3 | import HighlightableEditor from './highlightable-editor.js'; 4 | import opcodeLinks from './links.json'; 5 | 6 | async function main() { 7 | let pyodide, 8 | editor, 9 | ops = [], 10 | disTable, 11 | callMode = false, 12 | permalink, 13 | pythonVersion; 14 | const codeDiv = document.getElementById('code-area'); 15 | const button = document.getElementById('button'); 16 | const statusDiv = document.getElementById('status'); 17 | const tableDiv = document.getElementById('table-area'); 18 | const permalinkDiv = document.getElementById('permalink-area'); 19 | const errorDiv = document.getElementById('error-area'); 20 | const outputDiv = document.getElementById('output-area'); 21 | 22 | function disassembleCode() { 23 | statusDiv.innerText = 'Disassembling...'; 24 | const code = editor.getCode(); 25 | const functionCall = document.getElementById('call-input').value; 26 | const functionName = functionCall.split('(')[0]; 27 | ops = []; 28 | const enableAdaptive = document.getElementById('adaptive-checkbox').checked ? 'True' : 'False'; 29 | // Support the old way of disassembling a sequence of statements 30 | if (!functionCall) { 31 | callMode = false; 32 | pyodide.runPython(`import dis; dis.dis('''${code}''');`); 33 | } else { 34 | callMode = true; 35 | try { 36 | let disLine = `dis.dis(${functionName})`; 37 | if (enableAdaptive === 'True') { 38 | disLine = `dis.dis(${functionName}, adaptive=${enableAdaptive}, show_caches=False)`; 39 | } 40 | 41 | pyodide.runPython(` 42 | import sys, dis 43 | print(sys.version) 44 | ${code} 45 | for _ in range(10): 46 | ${functionCall} 47 | ${disLine} 48 | `); 49 | } catch (e) { 50 | statusDiv.innerText = ''; 51 | errorDiv.style.display = 'block'; 52 | outputDiv.style.display = 'none'; 53 | errorDiv.innerText = e; 54 | return; 55 | } 56 | } 57 | statusDiv.innerText = ''; 58 | errorDiv.style.display = 'none'; 59 | outputDiv.style.display = 'block'; 60 | disTable.setAttribute('operations', JSON.stringify(ops)); 61 | permalink.setAttribute('code', code); 62 | permalink.setAttribute('call', functionCall); 63 | permalink.setAttribute('adaptive', enableAdaptive); 64 | permalink.setAttribute('version', pythonVersion); 65 | } 66 | 67 | function handleStdOut(output) { 68 | if (output.startsWith('3.')) { 69 | // Python version 70 | document.getElementById('version-number').innerText = output.split(' ')[0]; 71 | return; 72 | } 73 | const matches = output.match(/\s*(\d+)?\s+(\d+)\s+([A-Z_]+)\s*(\d+)?\s*(\([^\)]+\))?/); 74 | if (!matches) { 75 | return; 76 | } 77 | let lineNo; 78 | if (typeof matches[1] !== 'undefined') { 79 | // Some instructions start with a line number 80 | lineNo = parseInt(matches[1], 10) - (callMode ? 3 : 0); 81 | } else { 82 | // If not, assume line number is same as most recent line number 83 | lineNo = ops[ops.length - 1].lineNo; 84 | } 85 | const offset = matches[2]; 86 | const opcode = matches[3]; 87 | const param = matches[4] || ''; 88 | const paramD = matches[5] || ''; 89 | ops.push({lineNo, offset, opcode, param, paramD}); 90 | } 91 | 92 | async function loadPyodideScript() { 93 | const versionMap = { 94 | 3.11: 'dev', 95 | '3.10': 'v0.22.1', 96 | 3.9: 'v0.19.1', 97 | }; 98 | if (pythonVersion !== '3.11') { 99 | document.getElementById('adaptive-area').style.display = 'none'; 100 | } 101 | const pyodideVersion = versionMap[pythonVersion]; 102 | const scriptUrl = `https://cdn.jsdelivr.net/pyodide/${pyodideVersion}/full/pyodide.js`; 103 | 104 | const script = document.createElement('script'); 105 | script.src = scriptUrl; 106 | script.onload = async () => { 107 | pyodide = await loadPyodide({ 108 | indexURL: `https://cdn.jsdelivr.net/pyodide/${pyodideVersion}/full/`, 109 | stdout: handleStdOut, 110 | }); 111 | statusDiv.innerText = ''; 112 | button.removeAttribute('disabled'); 113 | button.addEventListener('click', disassembleCode); 114 | code && disassembleCode(); 115 | }; 116 | document.head.appendChild(script); 117 | } 118 | 119 | let code = new URLSearchParams(window.location.search).get('code'); 120 | let call = new URLSearchParams(window.location.search).get('call'); 121 | if (!code) { 122 | code = `def feet_to_meters(feet): 123 | result = 0.3048 * feet 124 | return result`; 125 | call = 'feet_to_meters(10)'; 126 | } 127 | pythonVersion = new URLSearchParams(window.location.search).get('version') || '3.11'; 128 | document.getElementById('version-select').value = pythonVersion; 129 | let adaptive = new URLSearchParams(window.location.search).get('adaptive'); 130 | document.getElementById('adaptive-checkbox').checked = pythonVersion == '3.11' && adaptive === 'True'; 131 | 132 | editor = new HighlightableEditor(codeDiv, code, (lineNo) => { 133 | disTable.setAttribute('activeLine', lineNo); 134 | }); 135 | document.getElementById('call-input').value = call; 136 | disTable = document.createElement('dis-table-element'); 137 | disTable.setAttribute('links', JSON.stringify(opcodeLinks[pythonVersion])); 138 | disTable.setAttribute('operations', JSON.stringify(ops)); 139 | disTable.addEventListener('line-highlight', (e) => { 140 | editor.highlightLine(e.detail.line); 141 | }); 142 | tableDiv.appendChild(disTable); 143 | permalink = document.createElement('permalink-element'); 144 | permalinkDiv.appendChild(permalink); 145 | 146 | document.getElementById('version-select').addEventListener('change', async () => { 147 | pythonVersion = document.getElementById('version-select').value; 148 | permalink.setAttribute('version', pythonVersion); 149 | window.location.search = permalink.path; 150 | }); 151 | await loadPyodideScript(); 152 | } 153 | 154 | main(); 155 | -------------------------------------------------------------------------------- /src/opcode_links_gen.py: -------------------------------------------------------------------------------- 1 | # Run this in cpython repo when tag is checked out for version 2 | # This will generate a json file with opcode links for that version 3 | 4 | opcode_links = {} 5 | 6 | file = open("Include/patchlevel.h", "r") 7 | for line in file.readlines(): 8 | if line.startswith("#define PY_VERSION"): 9 | full_version = line.split()[2].strip('"') 10 | major_version = full_version.rsplit(".", 1)[0] 11 | break 12 | file.close() 13 | 14 | file = open("Include/opcode.h", "r") 15 | lines = file.readlines() 16 | file.close() 17 | 18 | opcodes = [] 19 | for line in lines: 20 | if line.startswith("#define"): 21 | opcodes.append(line.split()[1]) # get opcode name 22 | 23 | file = open("Doc/library/dis.rst", "r") 24 | lines = file.readlines() 25 | file.close() 26 | 27 | for line in lines: 28 | if line.strip().startswith(".. opcode:: "): 29 | opcode = line.split(".. opcode:: ")[1].split()[0].strip() 30 | if opcode in opcodes: 31 | opcodes.remove(opcode) 32 | opcode_links[opcode] = f"https://docs.python.org/{major_version}/library/dis.html#opcode-%s" % opcode 33 | 34 | file = open("Python/ceval.c", "r") 35 | lines = file.readlines() 36 | for line_no, line in enumerate(lines): 37 | if line.strip().startswith("TARGET("): 38 | opcode = line.split("TARGET(")[1].split(")")[0].strip() 39 | elif line.strip().startswith("[NB"): 40 | opcode = line.split("[")[1].split("]")[0].strip() 41 | if opcode in opcodes: 42 | opcode_links[opcode] = f"https://github.com/python/cpython/blob/v{full_version}/Python/ceval.c#L{line_no + 1}" 43 | opcodes.remove(opcode) 44 | 45 | print("Remaining opcodes:") 46 | print(opcodes) 47 | 48 | # save opcode links to file, as json 49 | import json 50 | with open(f"opcodes_{major_version}.json", "w") as file: 51 | json.dump(opcode_links, file, indent=4) -------------------------------------------------------------------------------- /src/permalink-element.js: -------------------------------------------------------------------------------- 1 | import {LitElement, html} from 'lit'; 2 | 3 | export class Permalink extends LitElement { 4 | static properties = { 5 | code: {type: String}, 6 | call: {type: String}, 7 | adaptive: {type: String}, 8 | version: {type: String}, 9 | }; 10 | 11 | constructor() { 12 | super(); 13 | } 14 | 15 | get path() { 16 | let pathParams = []; 17 | Object.keys(Permalink.properties).forEach((key) => { 18 | if (this[key]) { 19 | pathParams.push(`${key}=${encodeURIComponent(this[key])}`); 20 | } 21 | }); 22 | return pathParams.join('&'); 23 | } 24 | 25 | render() { 26 | if (!this.code) return; 27 | 28 | const url = `${window.location.origin}/?${this.path.replace(/\(/g, '%28').replace(/\)/g, '%29')}`; 29 | return html` 30 | 31 | 32 | `; 33 | } 34 | } 35 | 36 | customElements.define('permalink-element', Permalink); 37 | --------------------------------------------------------------------------------