diff --git a/Cargo.lock b/Cargo.lock index b3b8da765..acf545efa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1007,6 +1007,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -1051,12 +1060,6 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "lalrpop-util" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" - [[package]] name = "lambert_w" version = "1.0.17" @@ -1958,6 +1961,90 @@ dependencies = [ "syn 2.0.98", ] +[[package]] +name = "ruff_python_ast" +version = "0.0.0" +source = "git+https://github.com/astral-sh/ruff.git?tag=v0.4.10#b54922fd7394c36cdc390fd21aaee99206ebc361" +dependencies = [ + "aho-corasick", + "bitflags 2.8.0", + "is-macro", + "itertools 0.13.0", + "once_cell", + "ruff_python_trivia", + "ruff_source_file", + "ruff_text_size", + "rustc-hash 1.1.0", +] + +[[package]] +name = "ruff_python_codegen" +version = "0.0.0" +source = "git+https://github.com/astral-sh/ruff.git?tag=v0.4.10#b54922fd7394c36cdc390fd21aaee99206ebc361" +dependencies = [ + "once_cell", + "ruff_python_ast", + "ruff_python_literal", + "ruff_python_parser", + "ruff_source_file", + "ruff_text_size", +] + +[[package]] +name = "ruff_python_literal" +version = "0.0.0" +source = "git+https://github.com/astral-sh/ruff.git?tag=v0.4.10#b54922fd7394c36cdc390fd21aaee99206ebc361" +dependencies = [ + "bitflags 2.8.0", + "itertools 0.13.0", + "ruff_python_ast", + "unic-ucd-category", +] + +[[package]] +name = "ruff_python_parser" +version = "0.0.0" +source = "git+https://github.com/astral-sh/ruff.git?tag=v0.4.10#b54922fd7394c36cdc390fd21aaee99206ebc361" +dependencies = [ + "bitflags 2.8.0", + "bstr", + "memchr", + "ruff_python_ast", + "ruff_python_trivia", + "ruff_text_size", + "rustc-hash 1.1.0", + "static_assertions", + "unicode-ident", + "unicode-normalization", + "unicode_names2", +] + +[[package]] +name = "ruff_python_trivia" +version = "0.0.0" +source = "git+https://github.com/astral-sh/ruff.git?tag=v0.4.10#b54922fd7394c36cdc390fd21aaee99206ebc361" +dependencies = [ + "itertools 0.13.0", + "ruff_source_file", + "ruff_text_size", + "unicode-ident", +] + +[[package]] +name = "ruff_source_file" +version = "0.0.0" +source = "git+https://github.com/astral-sh/ruff.git?tag=v0.4.10#b54922fd7394c36cdc390fd21aaee99206ebc361" +dependencies = [ + "memchr", + "once_cell", + "ruff_text_size", +] + +[[package]] +name = "ruff_text_size" +version = "0.0.0" +source = "git+https://github.com/astral-sh/ruff.git?tag=v0.4.10#b54922fd7394c36cdc390fd21aaee99206ebc361" + [[package]] name = "rustc-hash" version = "1.1.0" @@ -2006,26 +2093,14 @@ dependencies = [ "libc", "log", "pyo3", + "ruff_python_parser", "rustpython-compiler", - "rustpython-parser", "rustpython-pylib", "rustpython-stdlib", "rustpython-vm", "rustyline", ] -[[package]] -name = "rustpython-ast" -version = "0.4.0" -source = "git+https://github.com/RustPython/Parser.git?rev=d2f137b372ec08ce4a243564a80f8f9153c45a23#d2f137b372ec08ce4a243564a80f8f9153c45a23" -dependencies = [ - "is-macro", - "malachite-bigint", - "rustpython-literal", - "rustpython-parser-core", - "static_assertions", -] - [[package]] name = "rustpython-codegen" version = "0.4.0" @@ -2036,13 +2111,18 @@ dependencies = [ "insta", "itertools 0.14.0", "log", + "malachite-bigint", "num-complex", "num-traits", - "rustpython-ast", + "ruff_python_ast", + "ruff_python_codegen", + "ruff_python_parser", + "ruff_source_file", + "ruff_text_size", "rustpython-common", "rustpython-compiler-core", - "rustpython-parser", - "rustpython-parser-core", + "rustpython-compiler-source", + "thiserror 2.0.11", ] [[package]] @@ -2075,9 +2155,14 @@ dependencies = [ name = "rustpython-compiler" version = "0.4.0" dependencies = [ + "ruff_python_ast", + "ruff_python_parser", + "ruff_source_file", + "ruff_text_size", "rustpython-codegen", "rustpython-compiler-core", - "rustpython-parser", + "rustpython-compiler-source", + "thiserror 2.0.11", ] [[package]] @@ -2089,10 +2174,20 @@ dependencies = [ "lz4_flex", "malachite-bigint", "num-complex", - "rustpython-parser-core", + "ruff_python_ast", + "ruff_python_parser", + "ruff_source_file", "serde", ] +[[package]] +name = "rustpython-compiler-source" +version = "0.4.0" +dependencies = [ + "ruff_source_file", + "ruff_text_size", +] + [[package]] name = "rustpython-derive" version = "0.4.0" @@ -2113,7 +2208,6 @@ dependencies = [ "quote", "rustpython-compiler-core", "rustpython-doc", - "rustpython-parser-core", "syn 2.0.98", "syn-ext", "textwrap 0.16.1", @@ -2166,48 +2260,6 @@ dependencies = [ "unic-ucd-category", ] -[[package]] -name = "rustpython-parser" -version = "0.4.0" -source = "git+https://github.com/RustPython/Parser.git?rev=d2f137b372ec08ce4a243564a80f8f9153c45a23#d2f137b372ec08ce4a243564a80f8f9153c45a23" -dependencies = [ - "anyhow", - "is-macro", - "itertools 0.11.0", - "lalrpop-util", - "log", - "malachite-bigint", - "num-traits", - "phf", - "phf_codegen", - "rustc-hash 1.1.0", - "rustpython-ast", - "rustpython-parser-core", - "tiny-keccak", - "unic-emoji-char", - "unic-ucd-ident", - "unicode_names2", -] - -[[package]] -name = "rustpython-parser-core" -version = "0.4.0" -source = "git+https://github.com/RustPython/Parser.git?rev=d2f137b372ec08ce4a243564a80f8f9153c45a23#d2f137b372ec08ce4a243564a80f8f9153c45a23" -dependencies = [ - "is-macro", - "memchr", - "rustpython-parser-vendored", -] - -[[package]] -name = "rustpython-parser-vendored" -version = "0.4.0" -source = "git+https://github.com/RustPython/Parser.git?rev=d2f137b372ec08ce4a243564a80f8f9153c45a23#d2f137b372ec08ce4a243564a80f8f9153c45a23" -dependencies = [ - "memchr", - "once_cell", -] - [[package]] name = "rustpython-pylib" version = "0.4.0" @@ -2344,19 +2396,21 @@ dependencies = [ "paste", "rand 0.9.0", "result-like", + "ruff_python_ast", + "ruff_python_parser", + "ruff_source_file", + "ruff_text_size", "rustc_version", "rustix", - "rustpython-ast", "rustpython-codegen", "rustpython-common", "rustpython-compiler", "rustpython-compiler-core", + "rustpython-compiler-source", "rustpython-derive", "rustpython-format", "rustpython-jit", "rustpython-literal", - "rustpython-parser", - "rustpython-parser-core", "rustpython-sre_engine", "rustyline", "schannel", @@ -2388,8 +2442,8 @@ dependencies = [ "console_error_panic_hook", "getrandom 0.2.15", "js-sys", + "ruff_python_parser", "rustpython-common", - "rustpython-parser", "rustpython-pylib", "rustpython-stdlib", "rustpython-vm", @@ -2793,15 +2847,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "639ce8ef6d2ba56be0383a94dd13b92138d58de44c62618303bb798fa92bdc00" -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -2879,17 +2924,6 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d7ff825a6a654ee85a63e80f92f054f904f21e7d12da4e22f9834a4aaa35bc" -[[package]] -name = "unic-emoji-char" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b07221e68897210270a38bde4babb655869637af0f69407f96053a34f76494d" -dependencies = [ - "unic-char-property", - "unic-char-range", - "unic-ucd-version", -] - [[package]] name = "unic-normal" version = "0.9.0" diff --git a/Cargo.toml b/Cargo.toml index 2d66f9775..ab5e56fa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ rustpython-compiler = { workspace = true } rustpython-pylib = { workspace = true, optional = true } rustpython-stdlib = { workspace = true, optional = true, features = ["compiler"] } rustpython-vm = { workspace = true, features = ["compiler"] } -rustpython-parser = { workspace = true } +ruff_python_parser = { workspace = true } cfg-if = { workspace = true } log = { workspace = true } @@ -94,7 +94,7 @@ x86_64-pc-windows-msvc = { triplet = "x64-windows-static-md", dev-dependencies = [workspace] resolver = "2" members = [ - "compiler", "compiler/core", "compiler/codegen", + "compiler", "compiler/core", "compiler/codegen", "compiler/source", ".", "common", "derive", "jit", "vm", "vm/sre_engine", "pylib", "stdlib", "derive-impl", "wasm/lib", ] @@ -108,6 +108,7 @@ repository = "https://github.com/RustPython/RustPython" license = "MIT" [workspace.dependencies] +rustpython-compiler-source = { path = "compiler/source" } rustpython-compiler-core = { path = "compiler/core", version = "0.4.0" } rustpython-compiler = { path = "compiler", version = "0.4.0" } rustpython-codegen = { path = "compiler/codegen", version = "0.4.0" } @@ -121,15 +122,20 @@ rustpython-stdlib = { path = "stdlib", default-features = false, version = "0.4. rustpython-sre_engine = { path = "vm/sre_engine", version = "0.4.0" } rustpython-doc = { git = "https://github.com/RustPython/__doc__", tag = "0.3.0", version = "0.3.0" } +ruff_python_parser = { git = "https://github.com/astral-sh/ruff.git", tag = "v0.4.10" } +ruff_python_ast = { git = "https://github.com/astral-sh/ruff.git", tag = "v0.4.10" } +ruff_text_size = { git = "https://github.com/astral-sh/ruff.git", tag = "v0.4.10" } +ruff_source_file = { git = "https://github.com/astral-sh/ruff.git", tag = "v0.4.10" } +ruff_python_codegen = { git = "https://github.com/astral-sh/ruff.git", tag = "v0.4.10" } # rustpython-literal = { version = "0.4.0" } # rustpython-parser-core = { version = "0.4.0" } # rustpython-parser = { version = "0.4.0" } # rustpython-ast = { version = "0.4.0" } # rustpython-format= { version = "0.4.0" } rustpython-literal = { git = "https://github.com/RustPython/Parser.git", version = "0.4.0", rev = "d2f137b372ec08ce4a243564a80f8f9153c45a23" } -rustpython-parser-core = { git = "https://github.com/RustPython/Parser.git", version = "0.4.0", rev = "d2f137b372ec08ce4a243564a80f8f9153c45a23" } -rustpython-parser = { git = "https://github.com/RustPython/Parser.git", version = "0.4.0", rev = "d2f137b372ec08ce4a243564a80f8f9153c45a23" } -rustpython-ast = { git = "https://github.com/RustPython/Parser.git", version = "0.4.0", rev = "d2f137b372ec08ce4a243564a80f8f9153c45a23" } +# rustpython-parser-core = { git = "https://github.com/RustPython/Parser.git", version = "0.4.0", rev = "d2f137b372ec08ce4a243564a80f8f9153c45a23" } +# rustpython-parser = { git = "https://github.com/RustPython/Parser.git", version = "0.4.0", rev = "d2f137b372ec08ce4a243564a80f8f9153c45a23" } +# rustpython-ast = { git = "https://github.com/RustPython/Parser.git", version = "0.4.0", rev = "d2f137b372ec08ce4a243564a80f8f9153c45a23" } rustpython-format = { git = "https://github.com/RustPython/Parser.git", version = "0.4.0", rev = "d2f137b372ec08ce4a243564a80f8f9153c45a23" } # rustpython-literal = { path = "../RustPython-parser/literal" } # rustpython-parser-core = { path = "../RustPython-parser/core" } diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py index af3e2bb5e..8b28686fd 100644 --- a/Lib/test/test_ast.py +++ b/Lib/test/test_ast.py @@ -388,6 +388,8 @@ class AST_Tests(unittest.TestCase): with self.assertRaises(ValueError): compile(tree, '', 'exec') + # XXX RUSTPYTHON: we always require that end ranges be present + @unittest.expectedFailure def test_compilation_of_ast_nodes_with_default_end_position_values(self): tree = ast.Module(body=[ ast.Import(names=[ast.alias(name='builtins', lineno=1, col_offset=0)], lineno=1, col_offset=0), @@ -1531,6 +1533,8 @@ Module( malformed = ast.Dict(keys=[ast.Constant(1)], values=[ast.Constant(2), ast.Constant(3)]) self.assertRaises(ValueError, ast.literal_eval, malformed) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_literal_eval_trailing_ws(self): self.assertEqual(ast.literal_eval(" -1"), -1) self.assertEqual(ast.literal_eval("\t\t-1"), -1) @@ -1549,6 +1553,8 @@ Module( with self.assertRaisesRegex(ValueError, msg): ast.literal_eval(node) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_literal_eval_syntax_errors(self): with self.assertRaisesRegex(SyntaxError, "unexpected indent"): ast.literal_eval(r''' @@ -1569,6 +1575,8 @@ Module( compile(mod, 'test', 'exec') self.assertIn("invalid integer value: None", str(cm.exception)) + # XXX RUSTPYTHON: we always require that end ranges be present + @unittest.expectedFailure def test_level_as_none(self): body = [ast.ImportFrom(module='time', names=[ast.alias(name='sleep', @@ -2034,8 +2042,6 @@ class ASTValidatorTests(unittest.TestCase): call = ast.Call(func, args, bad_keywords) self.expr(call, "must have Load context") - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_num(self): with warnings.catch_warnings(record=True) as wlog: warnings.filterwarnings('ignore', '', DeprecationWarning) @@ -2733,8 +2739,6 @@ class EndPositionTests(unittest.TestCase): binop = self._parse_value(s_orig) self.assertEqual(ast.get_source_segment(s_orig, binop.left), s_tuple) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_source_segment_padded(self): s_orig = dedent(''' class C: @@ -2756,8 +2760,6 @@ class EndPositionTests(unittest.TestCase): self._check_content(s, y, 'y = 1') self._check_content(s, z, 'z = 1') - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_source_segment_tabs(self): s = dedent(''' class C: diff --git a/Lib/test/test_codeop.py b/Lib/test/test_codeop.py index 19117fa40..1036b970c 100644 --- a/Lib/test/test_codeop.py +++ b/Lib/test/test_codeop.py @@ -323,6 +323,8 @@ class CodeopTests(unittest.TestCase): with self.assertRaisesRegex(SyntaxError, message): compile_command(code, symbol='exec') + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_syntax_errors(self): self.assertSyntaxErrorMatches( dedent("""\ diff --git a/Lib/test/test_eof.py b/Lib/test/test_eof.py index cf12dd3d5..082103b33 100644 --- a/Lib/test/test_eof.py +++ b/Lib/test/test_eof.py @@ -7,9 +7,9 @@ from test.support import script_helper from test.support import warnings_helper import unittest -# TODO: RUSTPYTHON -@unittest.expectedFailure class EOFTestCase(unittest.TestCase): + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_EOF_single_quote(self): expect = "unterminated string literal (detected at line 1) (, line 1)" for quote in ("'", "\""): @@ -22,6 +22,8 @@ class EOFTestCase(unittest.TestCase): else: raise support.TestFailed + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_EOFS(self): expect = ("unterminated triple-quoted string literal (detected at line 1) (, line 1)") try: @@ -32,6 +34,8 @@ class EOFTestCase(unittest.TestCase): else: raise support.TestFailed + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_EOFS_with_file(self): expect = ("(, line 1)") with os_helper.temp_dir() as temp_dir: @@ -39,6 +43,8 @@ class EOFTestCase(unittest.TestCase): rc, out, err = script_helper.assert_python_failure(file_name) self.assertIn(b'unterminated triple-quoted string literal (detected at line 3)', err) + # TODO: RUSTPYTHON + @unittest.expectedFailure @warnings_helper.ignore_warnings(category=SyntaxWarning) def test_eof_with_line_continuation(self): expect = "unexpected EOF while parsing (, line 1)" @@ -49,6 +55,8 @@ class EOFTestCase(unittest.TestCase): else: raise support.TestFailed + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_line_continuation_EOF(self): """A continuation at the end of input must be an error; bpo2180.""" expect = 'unexpected EOF while parsing (, line 1)' diff --git a/Lib/test/test_exceptions.py b/Lib/test/test_exceptions.py index 47e789496..8be812250 100644 --- a/Lib/test/test_exceptions.py +++ b/Lib/test/test_exceptions.py @@ -50,6 +50,8 @@ class ExceptionTests(unittest.TestCase): self.assertEqual(buf1, buf2) self.assertEqual(exc.__name__, excname) + # TODO: RUSTPYTHON + @unittest.expectedFailure def testRaising(self): self.raise_catch(AttributeError, "AttributeError") self.assertRaises(AttributeError, getattr, sys, "undefined_attribute") diff --git a/Lib/test/test_fstring.py b/Lib/test/test_fstring.py index b3a38dd65..c0c987ca2 100644 --- a/Lib/test/test_fstring.py +++ b/Lib/test/test_fstring.py @@ -305,8 +305,6 @@ f'{a * x()} {a * x()} {a * x()}' self.assertEqual(name.col_offset, 22) self.assertEqual(name.end_col_offset, 25) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_ast_line_numbers_multiline_fstring(self): # See bpo-30465 for details. expr = """ @@ -509,8 +507,6 @@ x = ( self.assertEqual(type(format_spec), ast.JoinedStr) self.assertEqual(len(format_spec.values), 0) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_docstring(self): def f(): f"""Not a docstring""" @@ -535,6 +531,8 @@ x = ( exec(c) self.assertEqual(x[0], "foo3") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_compile_time_concat_errors(self): self.assertAllRaise( SyntaxError, @@ -550,6 +548,8 @@ x = ( self.assertEqual(f"a", "a") self.assertEqual(f" ", " ") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_unterminated_string(self): self.assertAllRaise( SyntaxError, @@ -562,6 +562,8 @@ x = ( ], ) + # TODO: RUSTPYTHON + @unittest.expectedFailure @unittest.skipIf(support.is_wasi, "exhausts limited stack on WASI") def test_mismatched_parens(self): self.assertAllRaise( @@ -666,6 +668,8 @@ x = ( ], ) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_compile_time_concat(self): x = "def" self.assertEqual("abc" f"## {x}ghi", "abc## defghi") @@ -1516,6 +1520,8 @@ x = ( ], ) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_del(self): self.assertAllRaise( SyntaxError, diff --git a/Lib/test/test_future_stmt/test_future.py b/Lib/test/test_future_stmt/test_future.py index 4a978cef4..ad9b5d5a8 100644 --- a/Lib/test/test_future_stmt/test_future.py +++ b/Lib/test/test_future_stmt/test_future.py @@ -67,6 +67,8 @@ class FutureTest(unittest.TestCase): from test.test_future_stmt import badsyntax_future5 self.check_syntax_error(cm.exception, "badsyntax_future5", 4) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_badfuture6(self): with self.assertRaises(SyntaxError) as cm: from test.test_future_stmt import badsyntax_future6 @@ -132,8 +134,6 @@ class FutureTest(unittest.TestCase): exec("from __future__ import unicode_literals; x = ''", {}, scope) self.assertIsInstance(scope["x"], str) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_syntactical_future_repl(self): p = spawn_python('-i') p.stdin.write(b"from __future__ import barry_as_FLUFL\n") @@ -198,6 +198,8 @@ class AnnotationsFutureTestCase(unittest.TestCase): ) return scope + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_annotations(self): eq = self.assertAnnotationEqual eq('...') @@ -362,6 +364,8 @@ class AnnotationsFutureTestCase(unittest.TestCase): eq('(((a, b)))', '(a, b)') eq("1 + 2 + 3") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_fstring_debug_annotations(self): # f-strings with '=' don't round trip very well, so set the expected # result explicitly. @@ -372,6 +376,8 @@ class AnnotationsFutureTestCase(unittest.TestCase): self.assertAnnotationEqual("f'{x=!a}'", expected="f'x={x!a}'") self.assertAnnotationEqual("f'{x=!s:*^20}'", expected="f'x={x!s:*^20}'") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_infinity_numbers(self): inf = "1e" + repr(sys.float_info.max_10_exp + 1) infj = f"{inf}j" diff --git a/Lib/test/test_global.py b/Lib/test/test_global.py index f5b38c25e..4c1bb6c0c 100644 --- a/Lib/test/test_global.py +++ b/Lib/test/test_global.py @@ -12,6 +12,8 @@ class GlobalTests(unittest.TestCase): self.enterContext(check_warnings()) warnings.filterwarnings("error", module="") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test1(self): prog_text_1 = """\ def wrong1(): @@ -22,6 +24,8 @@ def wrong1(): """ check_syntax_error(self, prog_text_1, lineno=4, offset=5) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test2(self): prog_text_2 = """\ def wrong2(): @@ -30,6 +34,8 @@ def wrong2(): """ check_syntax_error(self, prog_text_2, lineno=3, offset=5) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test3(self): prog_text_3 = """\ def wrong3(): diff --git a/Lib/test/test_grammar.py b/Lib/test/test_grammar.py index a797fd2b2..f94d36fa0 100644 --- a/Lib/test/test_grammar.py +++ b/Lib/test/test_grammar.py @@ -1062,6 +1062,8 @@ class GrammarTests(unittest.TestCase): self.assertEqual(g2(False), 0) self.assertEqual(g2(True), ('end', 1)) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_yield(self): # Allowed as standalone statement def g(): yield 1 diff --git a/Lib/test/test_keywordonlyarg.py b/Lib/test/test_keywordonlyarg.py index 46dce636d..9e9c6651d 100644 --- a/Lib/test/test_keywordonlyarg.py +++ b/Lib/test/test_keywordonlyarg.py @@ -40,8 +40,6 @@ class KeywordOnlyArgTestCase(unittest.TestCase): compile(s, "", "single") self.assertRaises(SyntaxError, shouldRaiseSyntaxError, codestr) - # TODO: RUSTPYTHON - @unittest.expectedFailure def testSyntaxErrorForFunctionDefinition(self): self.assertRaisesSyntaxError("def f(p, *):\n pass\n") self.assertRaisesSyntaxError("def f(p1, *, p1=100):\n pass\n") diff --git a/Lib/test/test_named_expressions.py b/Lib/test/test_named_expressions.py index 797b0f512..03f5384b6 100644 --- a/Lib/test/test_named_expressions.py +++ b/Lib/test/test_named_expressions.py @@ -4,62 +4,80 @@ GLOBAL_VAR = None class NamedExpressionInvalidTest(unittest.TestCase): + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_01(self): code = """x := 0""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_02(self): code = """x = y := 0""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_03(self): code = """y := f(x)""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_04(self): code = """y0 = y1 := f(x)""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) - # TODO: RUSTPYTHON - @unittest.expectedFailure # wrong error message + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_06(self): code = """((a, b) := (1, 2))""" with self.assertRaisesRegex(SyntaxError, "cannot use assignment expressions with tuple"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_07(self): code = """def spam(a = b := 42): pass""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_08(self): code = """def spam(a: b := 42 = 5): pass""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_09(self): code = """spam(a=b := 'c')""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_10(self): code = """spam(x = y := f(x))""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_11(self): code = """spam(a=1, b := 2)""" @@ -67,6 +85,8 @@ class NamedExpressionInvalidTest(unittest.TestCase): "positional argument follows keyword argument"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_12(self): code = """spam(a=1, (b := 2))""" @@ -74,6 +94,8 @@ class NamedExpressionInvalidTest(unittest.TestCase): "positional argument follows keyword argument"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_13(self): code = """spam(a=1, (b := 2))""" @@ -81,14 +103,16 @@ class NamedExpressionInvalidTest(unittest.TestCase): "positional argument follows keyword argument"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_14(self): code = """(x := lambda: y := 1)""" with self.assertRaisesRegex(SyntaxError, "invalid syntax"): exec(code, {}, {}) - # TODO: RUSTPYTHON - @unittest.expectedFailure # wrong error message + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_15(self): code = """(lambda: x := 1)""" @@ -96,6 +120,8 @@ class NamedExpressionInvalidTest(unittest.TestCase): "cannot use assignment expressions with lambda"): exec(code, {}, {}) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_named_expression_invalid_16(self): code = "[i + 1 for i in i := [1,2]]" diff --git a/Lib/test/test_positional_only_arg.py b/Lib/test/test_positional_only_arg.py index d9d8b0306..e0d784325 100644 --- a/Lib/test/test_positional_only_arg.py +++ b/Lib/test/test_positional_only_arg.py @@ -22,6 +22,8 @@ class PositionalOnlyTestCase(unittest.TestCase): with self.assertRaisesRegex(SyntaxError, regex): compile(codestr + "\n", "", "single") + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_invalid_syntax_errors(self): check_syntax_error(self, "def f(a, b = 5, /, c): pass", "non-default argument follows default argument") check_syntax_error(self, "def f(a = 5, b, /, c): pass", "non-default argument follows default argument") @@ -43,6 +45,8 @@ class PositionalOnlyTestCase(unittest.TestCase): check_syntax_error(self, "def f(a, /, c, /, d, *, e): pass") check_syntax_error(self, "def f(a, *, c, /, d, e): pass") + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_invalid_syntax_errors_async(self): check_syntax_error(self, "async def f(a, b = 5, /, c): pass", "non-default argument follows default argument") check_syntax_error(self, "async def f(a = 5, b, /, c): pass", "non-default argument follows default argument") @@ -236,6 +240,8 @@ class PositionalOnlyTestCase(unittest.TestCase): x = lambda a, b, /, : a + b self.assertEqual(x(1, 2), 3) + # TODO: RUSTPYTHON: wrong error message + @unittest.expectedFailure def test_invalid_syntax_lambda(self): check_syntax_error(self, "lambda a, b = 5, /, c: None", "non-default argument follows default argument") check_syntax_error(self, "lambda a = 5, b, /, c: None", "non-default argument follows default argument") diff --git a/Lib/test/test_syntax.py b/Lib/test/test_syntax.py index 9726d3cc1..7e4677304 100644 --- a/Lib/test/test_syntax.py +++ b/Lib/test/test_syntax.py @@ -742,7 +742,8 @@ SyntaxError: expression cannot contain assignment, perhaps you meant "=="? >>> f(x.y=1) Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? ->>> f((x)=2) +# TODO: RUSTPYTHON +>>> f((x)=2) # doctest: +SKIP Traceback (most recent call last): SyntaxError: expression cannot contain assignment, perhaps you meant "=="? >>> f(True=1) @@ -1649,7 +1650,8 @@ Corner-cases that used to crash: Invalid pattern matching constructs: - >>> match ...: + # TODO: RUSTPYTHON nothing raised. + >>> match ...: # doctest: +SKIP ... case 42 as _: ... ... Traceback (most recent call last): @@ -1876,12 +1878,16 @@ class SyntaxTestCase(unittest.TestCase): offset=7 ) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_curly_brace_after_primary_raises_immediately(self): self._check_error("f{}", "invalid syntax", mode="single") def test_assign_call(self): self._check_error("f() = 1", "assign") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_assign_del(self): self._check_error("del (,)", "invalid syntax") self._check_error("del 1", "cannot delete literal") @@ -1994,6 +2000,8 @@ class SyntaxTestCase(unittest.TestCase): "unindent does not match .* level", subclass=IndentationError) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_kwargs_last(self): self._check_error("int(base=10, '2')", "positional argument follows keyword argument") @@ -2005,6 +2013,8 @@ class SyntaxTestCase(unittest.TestCase): "positional argument follows " "keyword argument unpacking") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_kwargs_last3(self): self._check_error("int(**{'base': 10}, *['2'])", "iterable argument unpacking follows " @@ -2073,8 +2083,6 @@ if x: code += f"{' '*4*12}pass" self._check_error(code, "too many statically nested blocks") - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_barry_as_flufl_with_syntax_errors(self): # The "barry_as_flufl" rule can produce some "bugs-at-a-distance" if # is reading the wrong token in the presence of syntax errors later @@ -2092,6 +2100,8 @@ def func2(): """ self._check_error(code, "expected ':'") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_invalid_line_continuation_error_position(self): self._check_error(r"a = 3 \ 4", "unexpected character after line continuation character", @@ -2103,6 +2113,8 @@ def func2(): "unexpected character after line continuation character", lineno=3, offset=4) + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_invalid_line_continuation_left_recursive(self): # Check bpo-42218: SyntaxErrors following left-recursive rules # (t_primary_raw in this case) need to be tested explicitly @@ -2146,6 +2158,8 @@ case(34) """ compile(code, "", "exec") + # TODO: RUSTPYTHON + @unittest.expectedFailure def test_multiline_compiler_error_points_to_the_end(self): self._check_error( "call(\na=1,\na=1\n)", diff --git a/Lib/test/test_timeit.py b/Lib/test/test_timeit.py index 17e880cb5..72a104fc1 100644 --- a/Lib/test/test_timeit.py +++ b/Lib/test/test_timeit.py @@ -91,8 +91,6 @@ class TestTimeit(unittest.TestCase): self.assertRaises(SyntaxError, timeit.Timer, setup='from timeit import *') self.assertRaises(SyntaxError, timeit.Timer, setup=' pass') - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_timer_empty_stmt(self): timeit.Timer(stmt='') timeit.Timer(stmt=' \n\t\f') diff --git a/Lib/test/test_unicode_identifiers.py b/Lib/test/test_unicode_identifiers.py index 9e611caf6..d7a0ece25 100644 --- a/Lib/test/test_unicode_identifiers.py +++ b/Lib/test/test_unicode_identifiers.py @@ -2,8 +2,6 @@ import unittest class PEP3131Test(unittest.TestCase): - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_valid(self): class T: รค = 1 @@ -15,8 +13,6 @@ class PEP3131Test(unittest.TestCase): self.assertEqual(getattr(T, '\u87d2'), 3) self.assertEqual(getattr(T, 'x\U000E0100'), 4) - # TODO: RUSTPYTHON - @unittest.expectedFailure def test_non_bmp_normalized(self): ๐”˜๐”ซ๐”ฆ๐” ๐”ฌ๐”ก๐”ข = 1 self.assertIn("Unicode", dir()) diff --git a/compiler/Cargo.toml b/compiler/Cargo.toml index cb98093c9..19ece85a1 100644 --- a/compiler/Cargo.toml +++ b/compiler/Cargo.toml @@ -11,7 +11,13 @@ license.workspace = true [dependencies] rustpython-codegen = { workspace = true } rustpython-compiler-core = { workspace = true } -rustpython-parser = { workspace = true } +rustpython-compiler-source = { workspace = true } +# rustpython-parser = { workspace = true } +ruff_python_parser = { workspace = true } +ruff_python_ast = { workspace = true } +ruff_source_file = { workspace = true } +ruff_text_size = { workspace = true } +thiserror = { workspace = true } [lints] workspace = true \ No newline at end of file diff --git a/compiler/codegen/Cargo.toml b/compiler/codegen/Cargo.toml index 0817a9589..9cf93bc22 100644 --- a/compiler/codegen/Cargo.toml +++ b/compiler/codegen/Cargo.toml @@ -10,10 +10,16 @@ license.workspace = true [dependencies] -rustpython-ast = { workspace = true, features=["unparse", "constant-optimization"] } +# rustpython-ast = { workspace = true, features=["unparse", "constant-optimization"] } rustpython-common = { workspace = true } -rustpython-parser-core = { workspace = true } +# rustpython-parser-core = { workspace = true } rustpython-compiler-core = { workspace = true } +rustpython-compiler-source = {workspace = true } +ruff_python_parser = { workspace = true } +ruff_python_ast = { workspace = true } +ruff_text_size = { workspace = true } +ruff_source_file = { workspace = true } +ruff_python_codegen = { workspace = true } ahash = { workspace = true } bitflags = { workspace = true } @@ -22,11 +28,13 @@ itertools = { workspace = true } log = { workspace = true } num-complex = { workspace = true } num-traits = { workspace = true } +thiserror = { workspace = true } +malachite-bigint = { workspace = true } [dev-dependencies] -rustpython-parser = { workspace = true } +# rustpython-parser = { workspace = true } insta = { workspace = true } [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/compiler/codegen/src/compile.rs b/compiler/codegen/src/compile.rs index ce2e5627f..21087fddd 100644 --- a/compiler/codegen/src/compile.rs +++ b/compiler/codegen/src/compile.rs @@ -8,23 +8,33 @@ #![deny(clippy::cast_possible_truncation)] use crate::{ - IndexSet, + IndexSet, ToPythonName, error::{CodegenError, CodegenErrorType}, ir, symboltable::{self, SymbolFlags, SymbolScope, SymbolTable}, }; use itertools::Itertools; -use num_complex::Complex64; -use num_traits::ToPrimitive; -use rustpython_ast::located::{self as located_ast, Located}; +use malachite_bigint::BigInt; +use num_complex::Complex; +use num_traits::{Num, ToPrimitive}; +use ruff_python_ast::{ + Alias, Arguments, BoolOp, CmpOp, Comprehension, ConversionFlag, DebugText, Decorator, DictItem, + ExceptHandler, ExceptHandlerExceptHandler, Expr, ExprAttribute, ExprBoolOp, ExprFString, + ExprList, ExprName, ExprStarred, ExprSubscript, ExprTuple, ExprUnaryOp, FString, + FStringElement, FStringElements, FStringPart, Int, Keyword, MatchCase, ModExpression, + ModModule, Operator, Parameters, Pattern, PatternMatchAs, PatternMatchValue, Stmt, StmtExpr, + TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, UnaryOp, + WithItem, +}; +use ruff_source_file::OneIndexed; +use ruff_text_size::{Ranged, TextRange}; +// use rustpython_ast::located::{self as located_ast, Located}; use rustpython_compiler_core::{ Mode, - bytecode::{ - self, Arg as OpArgMarker, CodeObject, ComparisonOperator, ConstantData, Instruction, OpArg, - OpArgType, - }, + bytecode::{self, Arg as OpArgMarker, CodeObject, ConstantData, Instruction, OpArg, OpArgType}, }; -use rustpython_parser_core::source_code::{LineNumber, SourceLocation}; +use rustpython_compiler_source::SourceCode; +// use rustpython_parser_core::source_code::{LineNumber, SourceLocation}; use std::borrow::Cow; type CompileResult = Result; @@ -50,19 +60,26 @@ fn is_forbidden_name(name: &str) -> bool { } /// Main structure holding the state of compilation. -struct Compiler { +struct Compiler<'src> { code_stack: Vec, symbol_table_stack: Vec, - source_path: String, - current_source_location: SourceLocation, + source_code: SourceCode<'src>, + // current_source_location: SourceLocation, + current_source_range: TextRange, qualified_path: Vec, - done_with_future_stmts: bool, + done_with_future_stmts: DoneWithFuture, future_annotations: bool, ctx: CompileContext, class_name: Option, opts: CompileOpts, } +enum DoneWithFuture { + No, + DoneWithDoc, + Yes, +} + #[derive(Debug, Clone, Default)] pub struct CompileOpts { /// How optimized the bytecode output should be; any optimize > 0 does @@ -98,105 +115,78 @@ enum ComprehensionType { Dict, } -/// Compile an located_ast::Mod produced from rustpython_parser::parse() +/// Compile an Mod produced from ruff parser pub fn compile_top( - ast: &located_ast::Mod, - source_path: String, + ast: ruff_python_ast::Mod, + source_code: SourceCode<'_>, mode: Mode, opts: CompileOpts, ) -> CompileResult { match ast { - located_ast::Mod::Module(located_ast::ModModule { body, .. }) => { - compile_program(body, source_path, opts) - } - located_ast::Mod::Interactive(located_ast::ModInteractive { body, .. }) => match mode { - Mode::Single => compile_program_single(body, source_path, opts), - Mode::BlockExpr => compile_block_expression(body, source_path, opts), - _ => unreachable!("only Single and BlockExpr parsed to Interactive"), + ruff_python_ast::Mod::Module(module) => match mode { + Mode::Exec | Mode::Eval => compile_program(&module, source_code, opts), + Mode::Single => compile_program_single(&module, source_code, opts), + Mode::BlockExpr => compile_block_expression(&module, source_code, opts), }, - located_ast::Mod::Expression(located_ast::ModExpression { body, .. }) => { - compile_expression(body, source_path, opts) - } - located_ast::Mod::FunctionType(_) => panic!("can't compile a FunctionType"), + ruff_python_ast::Mod::Expression(expr) => compile_expression(&expr, source_code, opts), } } -/// A helper function for the shared code of the different compile functions -fn compile_impl( - ast: &Ast, - source_path: String, +/// Compile a standard Python program to bytecode +pub fn compile_program( + ast: &ModModule, + source_code: SourceCode<'_>, opts: CompileOpts, - make_symbol_table: impl FnOnce(&Ast) -> Result, - compile: impl FnOnce(&mut Compiler, &Ast, SymbolTable) -> CompileResult<()>, ) -> CompileResult { - let symbol_table = match make_symbol_table(ast) { - Ok(x) => x, - Err(e) => return Err(e.into_codegen_error(source_path)), - }; - - let mut compiler = Compiler::new(opts, source_path, "".to_owned()); - compile(&mut compiler, ast, symbol_table)?; + let symbol_table = SymbolTable::scan_program(ast, source_code.clone()) + .map_err(|e| e.into_codegen_error(source_code.path.to_owned()))?; + let mut compiler = Compiler::new(opts, source_code, "".to_owned()); + compiler.compile_program(ast, symbol_table)?; let code = compiler.pop_code_object(); trace!("Compilation completed: {:?}", code); Ok(code) } -/// Compile a standard Python program to bytecode -pub fn compile_program( - ast: &[located_ast::Stmt], - source_path: String, - opts: CompileOpts, -) -> CompileResult { - compile_impl( - ast, - source_path, - opts, - SymbolTable::scan_program, - Compiler::compile_program, - ) -} - /// Compile a Python program to bytecode for the context of a REPL pub fn compile_program_single( - ast: &[located_ast::Stmt], - source_path: String, + ast: &ModModule, + source_code: SourceCode<'_>, opts: CompileOpts, ) -> CompileResult { - compile_impl( - ast, - source_path, - opts, - SymbolTable::scan_program, - Compiler::compile_program_single, - ) + let symbol_table = SymbolTable::scan_program(ast, source_code.clone()) + .map_err(|e| e.into_codegen_error(source_code.path.to_owned()))?; + let mut compiler = Compiler::new(opts, source_code, "".to_owned()); + compiler.compile_program_single(&ast.body, symbol_table)?; + let code = compiler.pop_code_object(); + trace!("Compilation completed: {:?}", code); + Ok(code) } pub fn compile_block_expression( - ast: &[located_ast::Stmt], - source_path: String, + ast: &ModModule, + source_code: SourceCode<'_>, opts: CompileOpts, ) -> CompileResult { - compile_impl( - ast, - source_path, - opts, - SymbolTable::scan_program, - Compiler::compile_block_expr, - ) + let symbol_table = SymbolTable::scan_program(ast, source_code.clone()) + .map_err(|e| e.into_codegen_error(source_code.path.to_owned()))?; + let mut compiler = Compiler::new(opts, source_code, "".to_owned()); + compiler.compile_block_expr(&ast.body, symbol_table)?; + let code = compiler.pop_code_object(); + trace!("Compilation completed: {:?}", code); + Ok(code) } pub fn compile_expression( - ast: &located_ast::Expr, - source_path: String, + ast: &ModExpression, + source_code: SourceCode<'_>, opts: CompileOpts, ) -> CompileResult { - compile_impl( - ast, - source_path, - opts, - SymbolTable::scan_expr, - Compiler::compile_eval, - ) + let symbol_table = SymbolTable::scan_expr(ast, source_code.clone()) + .map_err(|e| e.into_codegen_error(source_code.path.to_owned()))?; + let mut compiler = Compiler::new(opts, source_code, "".to_owned()); + compiler.compile_eval(ast, symbol_table)?; + let code = compiler.pop_code_object(); + Ok(code) } macro_rules! emit { @@ -220,15 +210,15 @@ struct PatternContext { allow_irrefutable: bool, } -impl Compiler { - fn new(opts: CompileOpts, source_path: String, code_name: String) -> Self { +impl<'src> Compiler<'src> { + fn new(opts: CompileOpts, source_code: SourceCode<'src>, code_name: String) -> Self { let module_code = ir::CodeInfo { flags: bytecode::CodeFlags::NEW_LOCALS, posonlyarg_count: 0, arg_count: 0, kwonlyarg_count: 0, - source_path: source_path.clone(), - first_line_number: LineNumber::MIN, + source_path: source_code.path.to_owned(), + first_line_number: OneIndexed::MIN, obj_name: code_name, blocks: vec![ir::Block::default()], @@ -242,10 +232,11 @@ impl Compiler { Compiler { code_stack: vec![module_code], symbol_table_stack: Vec::new(), - source_path, - current_source_location: SourceLocation::default(), + source_code, + // current_source_location: SourceLocation::default(), + current_source_range: TextRange::default(), qualified_path: Vec::new(), - done_with_future_stmts: false, + done_with_future_stmts: DoneWithFuture::No, future_annotations: false, ctx: CompileContext { loop_data: None, @@ -256,15 +247,18 @@ impl Compiler { opts, } } +} +impl Compiler<'_> { fn error(&mut self, error: CodegenErrorType) -> CodegenError { - self.error_loc(error, self.current_source_location) + self.error_ranged(error, self.current_source_range) } - fn error_loc(&mut self, error: CodegenErrorType, location: SourceLocation) -> CodegenError { + fn error_ranged(&mut self, error: CodegenErrorType, range: TextRange) -> CodegenError { + let location = self.source_code.source_location(range.start()); CodegenError { error, location: Some(location), - source_path: self.source_path.clone(), + source_path: self.source_code.path.to_owned(), } } @@ -296,7 +290,7 @@ impl Compiler { kwonlyarg_count: u32, obj_name: String, ) { - let source_path = self.source_path.clone(); + let source_path = self.source_code.path.to_owned(); let first_line_number = self.get_source_line_number(); let table = self.push_symbol_table(); @@ -373,13 +367,13 @@ impl Compiler { fn compile_program( &mut self, - body: &[located_ast::Stmt], + body: &ModModule, symbol_table: SymbolTable, ) -> CompileResult<()> { let size_before = self.code_stack.len(); self.symbol_table_stack.push(symbol_table); - let (doc, statements) = split_doc(body, &self.opts); + let (doc, statements) = split_doc(&body.body, &self.opts); if let Some(value) = doc { self.emit_load_const(ConstantData::Str { value }); let doc = self.name("__doc__"); @@ -401,14 +395,14 @@ impl Compiler { fn compile_program_single( &mut self, - body: &[located_ast::Stmt], + body: &[Stmt], symbol_table: SymbolTable, ) -> CompileResult<()> { self.symbol_table_stack.push(symbol_table); if let Some((last, body)) = body.split_last() { for statement in body { - if let located_ast::Stmt::Expr(located_ast::StmtExpr { value, .. }) = &statement { + if let Stmt::Expr(StmtExpr { value, .. }) = &statement { self.compile_expression(value)?; emit!(self, Instruction::PrintExpr); } else { @@ -416,7 +410,7 @@ impl Compiler { } } - if let located_ast::Stmt::Expr(located_ast::StmtExpr { value, .. }) = &last { + if let Stmt::Expr(StmtExpr { value, .. }) = &last { self.compile_expression(value)?; emit!(self, Instruction::Duplicate); emit!(self, Instruction::PrintExpr); @@ -434,7 +428,7 @@ impl Compiler { fn compile_block_expr( &mut self, - body: &[located_ast::Stmt], + body: &[Stmt], symbol_table: SymbolTable, ) -> CompileResult<()> { self.symbol_table_stack.push(symbol_table); @@ -443,12 +437,10 @@ impl Compiler { if let Some(last_statement) = body.last() { match last_statement { - located_ast::Stmt::Expr(_) => { + Stmt::Expr(_) => { self.current_block().instructions.pop(); // pop Instruction::Pop } - located_ast::Stmt::FunctionDef(_) - | located_ast::Stmt::AsyncFunctionDef(_) - | located_ast::Stmt::ClassDef(_) => { + Stmt::FunctionDef(_) | Stmt::ClassDef(_) => { let store_inst = self.current_block().instructions.pop().unwrap(); // pop Instruction::Store emit!(self, Instruction::Duplicate); self.current_block().instructions.push(store_inst); @@ -464,16 +456,16 @@ impl Compiler { // Compile statement in eval mode: fn compile_eval( &mut self, - expression: &located_ast::Expr, + expression: &ModExpression, symbol_table: SymbolTable, ) -> CompileResult<()> { self.symbol_table_stack.push(symbol_table); - self.compile_expression(expression)?; + self.compile_expression(&expression.body)?; self.emit_return_value(); Ok(()) } - fn compile_statements(&mut self, statements: &[located_ast::Stmt]) -> CompileResult<()> { + fn compile_statements(&mut self, statements: &[Stmt]) -> CompileResult<()> { for statement in statements { self.compile_statement(statement)? } @@ -508,7 +500,7 @@ impl Compiler { let symbol_table = self.symbol_table_stack.last().unwrap(); let symbol = symbol_table.lookup(name.as_ref()).unwrap_or_else(|| - panic!("The symbol '{name}' must be present in the symbol table, even when it is undefined in python."), + unreachable!("the symbol '{name}' should be present in the symbol table, even when it is undefined in python."), ); let info = self.code_stack.last_mut().unwrap(); let mut cache = &mut info.name_cache; @@ -583,22 +575,28 @@ impl Compiler { Ok(()) } - fn compile_statement(&mut self, statement: &located_ast::Stmt) -> CompileResult<()> { - use located_ast::*; - + fn compile_statement(&mut self, statement: &Stmt) -> CompileResult<()> { + use ruff_python_ast::*; trace!("Compiling {:?}", statement); - self.set_source_location(statement.location()); + self.set_source_range(statement.range()); match &statement { // we do this here because `from __future__` still executes that `from` statement at runtime, // we still need to compile the ImportFrom down below - Stmt::ImportFrom(located_ast::StmtImportFrom { module, names, .. }) + Stmt::ImportFrom(StmtImportFrom { module, names, .. }) if module.as_ref().map(|id| id.as_str()) == Some("__future__") => { self.compile_future_features(names)? } + // ignore module-level doc comments + Stmt::Expr(StmtExpr { value, .. }) + if matches!(&**value, Expr::StringLiteral(..)) + && matches!(self.done_with_future_stmts, DoneWithFuture::No) => + { + self.done_with_future_stmts = DoneWithFuture::DoneWithDoc + } // if we find any other statement, stop accepting future statements - _ => self.done_with_future_stmts = true, + _ => self.done_with_future_stmts = DoneWithFuture::Yes, } match &statement { @@ -633,9 +631,9 @@ impl Compiler { let from_list = if import_star { if self.ctx.in_func() { - return Err(self.error_loc( + return Err(self.error_ranged( CodegenErrorType::FunctionImportStar, - statement.location(), + statement.range(), )); } vec![ConstantData::Str { @@ -654,7 +652,7 @@ impl Compiler { // from .... import (*fromlist) self.emit_load_const(ConstantData::Integer { - value: level.as_ref().map_or(0, |level| level.to_u32()).into(), + value: (*level).into(), }); self.emit_load_const(ConstantData::Tuple { elements: from_list, @@ -699,52 +697,76 @@ impl Compiler { // Handled during symbol table construction. } Stmt::If(StmtIf { - test, body, orelse, .. + test, + body, + elif_else_clauses, + .. }) => { - let after_block = self.new_block(); - if orelse.is_empty() { - // Only if: - self.compile_jump_if(test, false, after_block)?; - self.compile_statements(body)?; - } else { - // if - else: - let else_block = self.new_block(); - self.compile_jump_if(test, false, else_block)?; - self.compile_statements(body)?; - emit!( - self, - Instruction::Jump { - target: after_block, - } - ); + match elif_else_clauses.as_slice() { + // Only if + [] => { + let after_block = self.new_block(); + self.compile_jump_if(test, false, after_block)?; + self.compile_statements(body)?; + self.switch_to_block(after_block); + } + // If, elif*, elif/else + [rest @ .., tail] => { + let after_block = self.new_block(); + let mut next_block = self.new_block(); - // else: - self.switch_to_block(else_block); - self.compile_statements(orelse)?; + self.compile_jump_if(test, false, next_block)?; + self.compile_statements(body)?; + emit!( + self, + Instruction::Jump { + target: after_block + } + ); + + for clause in rest { + self.switch_to_block(next_block); + next_block = self.new_block(); + if let Some(test) = &clause.test { + self.compile_jump_if(test, false, next_block)?; + } else { + unreachable!() // must be elif + } + self.compile_statements(&clause.body)?; + emit!( + self, + Instruction::Jump { + target: after_block + } + ); + } + + self.switch_to_block(next_block); + if let Some(test) = &tail.test { + self.compile_jump_if(test, false, after_block)?; + } + self.compile_statements(&tail.body)?; + self.switch_to_block(after_block); + } } - self.switch_to_block(after_block); } Stmt::While(StmtWhile { test, body, orelse, .. }) => self.compile_while(test, body, orelse)?, - Stmt::With(StmtWith { items, body, .. }) => self.compile_with(items, body, false)?, - Stmt::AsyncWith(StmtAsyncWith { items, body, .. }) => { - self.compile_with(items, body, true)? - } + Stmt::With(StmtWith { + items, + body, + is_async, + .. + }) => self.compile_with(items, body, *is_async)?, Stmt::For(StmtFor { target, iter, body, orelse, + is_async, .. - }) => self.compile_for(target, iter, body, orelse, false)?, - Stmt::AsyncFor(StmtAsyncFor { - target, - iter, - body, - orelse, - .. - }) => self.compile_for(target, iter, body, orelse, true)?, + }) => self.compile_for(target, iter, body, orelse, *is_async)?, Stmt::Match(StmtMatch { subject, cases, .. }) => self.compile_match(subject, cases)?, Stmt::Raise(StmtRaise { exc, cause, .. }) => { let kind = match exc { @@ -767,64 +789,46 @@ impl Compiler { handlers, orelse, finalbody, + is_star, .. - }) => self.compile_try_statement(body, handlers, orelse, finalbody)?, - Stmt::TryStar(StmtTryStar { - body, - handlers, - orelse, - finalbody, - .. - }) => self.compile_try_star_statement(body, handlers, orelse, finalbody)?, + }) => { + if *is_star { + self.compile_try_star_statement(body, handlers, orelse, finalbody)? + } else { + self.compile_try_statement(body, handlers, orelse, finalbody)? + } + } Stmt::FunctionDef(StmtFunctionDef { name, - args, + parameters, body, decorator_list, returns, type_params, + is_async, .. }) => self.compile_function_def( name.as_str(), - args, + parameters, body, decorator_list, returns.as_deref(), - false, - type_params, - )?, - Stmt::AsyncFunctionDef(StmtAsyncFunctionDef { - name, - args, - body, - decorator_list, - returns, - type_params, - .. - }) => self.compile_function_def( - name.as_str(), - args, - body, - decorator_list, - returns.as_deref(), - true, - type_params, + *is_async, + type_params.as_deref(), )?, Stmt::ClassDef(StmtClassDef { name, body, - bases, - keywords, decorator_list, type_params, + arguments, .. }) => self.compile_class_def( name.as_str(), body, - bases, - keywords, decorator_list, - type_params, + type_params.as_deref(), + arguments.as_deref(), )?, Stmt::Assert(StmtAssert { test, msg, .. }) => { // if some flag, ignore all assert statements! @@ -859,7 +863,7 @@ impl Compiler { } None => { return Err( - self.error_loc(CodegenErrorType::InvalidBreak, statement.location()) + self.error_ranged(CodegenErrorType::InvalidBreak, statement.range()) ); } }, @@ -869,14 +873,14 @@ impl Compiler { } None => { return Err( - self.error_loc(CodegenErrorType::InvalidContinue, statement.location()) + self.error_ranged(CodegenErrorType::InvalidContinue, statement.range()) ); } }, Stmt::Return(StmtReturn { value, .. }) => { if !self.ctx.in_func() { return Err( - self.error_loc(CodegenErrorType::InvalidReturn, statement.location()) + self.error_ranged(CodegenErrorType::InvalidReturn, statement.range()) ); } match value { @@ -887,9 +891,9 @@ impl Compiler { .flags .contains(bytecode::CodeFlags::IS_GENERATOR) { - return Err(self.error_loc( + return Err(self.error_ranged( CodegenErrorType::AsyncReturnValue, - statement.location(), + statement.range(), )); } self.compile_expression(v)?; @@ -933,13 +937,20 @@ impl Compiler { value, .. }) => { - let name_string = name.to_string(); - if !type_params.is_empty() { + // let name_string = name.to_string(); + let Some(name) = name.as_name_expr() else { + // FIXME: is error here? + return Err(self.error(CodegenErrorType::SyntaxError( + "type alias expect name".to_owned(), + ))); + }; + let name_string = name.id.to_string(); + if type_params.is_some() { self.push_symbol_table(); } self.compile_expression(value)?; - self.compile_type_params(type_params)?; - if !type_params.is_empty() { + if let Some(type_params) = type_params { + self.compile_type_params(type_params)?; self.pop_symbol_table(); } self.emit_load_const(ConstantData::Str { @@ -948,33 +959,32 @@ impl Compiler { emit!(self, Instruction::TypeAlias); self.store_name(&name_string)?; } + Stmt::IpyEscapeCommand(_) => todo!(), } Ok(()) } - fn compile_delete(&mut self, expression: &located_ast::Expr) -> CompileResult<()> { + fn compile_delete(&mut self, expression: &Expr) -> CompileResult<()> { + use ruff_python_ast::*; match &expression { - located_ast::Expr::Name(located_ast::ExprName { id, .. }) => { - self.compile_name(id.as_str(), NameUsage::Delete)? - } - located_ast::Expr::Attribute(located_ast::ExprAttribute { value, attr, .. }) => { + Expr::Name(ExprName { id, .. }) => self.compile_name(id.as_str(), NameUsage::Delete)?, + Expr::Attribute(ExprAttribute { value, attr, .. }) => { self.check_forbidden_name(attr.as_str(), NameUsage::Delete)?; self.compile_expression(value)?; let idx = self.name(attr.as_str()); emit!(self, Instruction::DeleteAttr { idx }); } - located_ast::Expr::Subscript(located_ast::ExprSubscript { value, slice, .. }) => { + Expr::Subscript(ExprSubscript { value, slice, .. }) => { self.compile_expression(value)?; self.compile_expression(slice)?; emit!(self, Instruction::DeleteSubscript); } - located_ast::Expr::Tuple(located_ast::ExprTuple { elts, .. }) - | located_ast::Expr::List(located_ast::ExprList { elts, .. }) => { + Expr::Tuple(ExprTuple { elts, .. }) | Expr::List(ExprList { elts, .. }) => { for element in elts { self.compile_delete(element)?; } } - located_ast::Expr::BinOp(_) | located_ast::Expr::UnaryOp(_) => { + Expr::BinOp(_) | Expr::UnaryOp(_) => { return Err(self.error(CodegenErrorType::Delete("expression"))); } _ => return Err(self.error(CodegenErrorType::Delete(expression.python_name()))), @@ -985,9 +995,13 @@ impl Compiler { fn enter_function( &mut self, name: &str, - args: &located_ast::Arguments, + parameters: &Parameters, ) -> CompileResult { - let defaults: Vec<_> = args.defaults().collect(); + let defaults: Vec<_> = std::iter::empty() + .chain(¶meters.posonlyargs) + .chain(¶meters.args) + .filter_map(|x| x.default.as_deref()) + .collect(); let have_defaults = !defaults.is_empty(); if have_defaults { // Construct a tuple: @@ -998,12 +1012,23 @@ impl Compiler { emit!(self, Instruction::BuildTuple { size }); } - let (kw_without_defaults, kw_with_defaults) = args.split_kwonlyargs(); + // TODO: partition_in_place + let mut kw_without_defaults = vec![]; + let mut kw_with_defaults = vec![]; + for kwonlyarg in ¶meters.kwonlyargs { + if let Some(default) = &kwonlyarg.default { + kw_with_defaults.push((&kwonlyarg.parameter, default)); + } else { + kw_without_defaults.push(&kwonlyarg.parameter); + } + } + + // let (kw_without_defaults, kw_with_defaults) = args.split_kwonlyargs(); if !kw_with_defaults.is_empty() { let default_kw_count = kw_with_defaults.len(); for (arg, default) in kw_with_defaults.iter() { self.emit_load_const(ConstantData::Str { - value: arg.arg.to_string(), + value: arg.name.to_string(), }); self.compile_expression(default)?; } @@ -1025,42 +1050,42 @@ impl Compiler { self.push_output( bytecode::CodeFlags::NEW_LOCALS | bytecode::CodeFlags::IS_OPTIMIZED, - args.posonlyargs.len().to_u32(), - (args.posonlyargs.len() + args.args.len()).to_u32(), - args.kwonlyargs.len().to_u32(), + parameters.posonlyargs.len().to_u32(), + (parameters.posonlyargs.len() + parameters.args.len()).to_u32(), + parameters.kwonlyargs.len().to_u32(), name.to_owned(), ); let args_iter = std::iter::empty() - .chain(&args.posonlyargs) - .chain(&args.args) - .map(|arg| arg.as_arg()) + .chain(¶meters.posonlyargs) + .chain(¶meters.args) + .map(|arg| &arg.parameter) .chain(kw_without_defaults) .chain(kw_with_defaults.into_iter().map(|(arg, _)| arg)); for name in args_iter { - self.varname(name.arg.as_str())?; + self.varname(name.name.as_str())?; } - if let Some(name) = args.vararg.as_deref() { + if let Some(name) = parameters.vararg.as_deref() { self.current_code_info().flags |= bytecode::CodeFlags::HAS_VARARGS; - self.varname(name.arg.as_str())?; + self.varname(name.name.as_str())?; } - if let Some(name) = args.kwarg.as_deref() { + if let Some(name) = parameters.kwarg.as_deref() { self.current_code_info().flags |= bytecode::CodeFlags::HAS_VARKEYWORDS; - self.varname(name.arg.as_str())?; + self.varname(name.name.as_str())?; } Ok(func_flags) } - fn prepare_decorators(&mut self, decorator_list: &[located_ast::Expr]) -> CompileResult<()> { + fn prepare_decorators(&mut self, decorator_list: &[Decorator]) -> CompileResult<()> { for decorator in decorator_list { - self.compile_expression(decorator)?; + self.compile_expression(&decorator.expression)?; } Ok(()) } - fn apply_decorators(&mut self, decorator_list: &[located_ast::Expr]) { + fn apply_decorators(&mut self, decorator_list: &[Decorator]) { // Apply decorators: for _ in decorator_list { emit!(self, Instruction::CallFunctionPositional { nargs: 1 }); @@ -1069,14 +1094,10 @@ impl Compiler { /// Store each type parameter so it is accessible to the current scope, and leave a tuple of /// all the type parameters on the stack. - fn compile_type_params(&mut self, type_params: &[located_ast::TypeParam]) -> CompileResult<()> { - for type_param in type_params { + fn compile_type_params(&mut self, type_params: &TypeParams) -> CompileResult<()> { + for type_param in &type_params.type_params { match type_param { - located_ast::TypeParam::TypeVar(located_ast::TypeParamTypeVar { - name, - bound, - .. - }) => { + TypeParam::TypeVar(TypeParamTypeVar { name, bound, .. }) => { if let Some(expr) = &bound { self.compile_expression(expr)?; self.emit_load_const(ConstantData::Str { @@ -1095,9 +1116,7 @@ impl Compiler { self.store_name(name.as_ref())?; } } - located_ast::TypeParam::ParamSpec(located_ast::TypeParamParamSpec { - name, .. - }) => { + TypeParam::ParamSpec(TypeParamParamSpec { name, .. }) => { self.emit_load_const(ConstantData::Str { value: name.to_string(), }); @@ -1105,10 +1124,7 @@ impl Compiler { emit!(self, Instruction::Duplicate); self.store_name(name.as_ref())?; } - located_ast::TypeParam::TypeVarTuple(located_ast::TypeParamTypeVarTuple { - name, - .. - }) => { + TypeParam::TypeVarTuple(TypeParamTypeVarTuple { name, .. }) => { self.emit_load_const(ConstantData::Str { value: name.to_string(), }); @@ -1129,10 +1145,10 @@ impl Compiler { fn compile_try_statement( &mut self, - body: &[located_ast::Stmt], - handlers: &[located_ast::ExceptHandler], - orelse: &[located_ast::Stmt], - finalbody: &[located_ast::Stmt], + body: &[Stmt], + handlers: &[ExceptHandler], + orelse: &[Stmt], + finalbody: &[Stmt], ) -> CompileResult<()> { let handler_block = self.new_block(); let finally_block = self.new_block(); @@ -1164,11 +1180,9 @@ impl Compiler { self.switch_to_block(handler_block); // Exception is on top of stack now for handler in handlers { - let located_ast::ExceptHandler::ExceptHandler( - located_ast::ExceptHandlerExceptHandler { - type_, name, body, .. - }, - ) = &handler; + let ExceptHandler::ExceptHandler(ExceptHandlerExceptHandler { + type_, name, body, .. + }) = &handler; let next_handler = self.new_block(); // If we gave a typ, @@ -1261,10 +1275,10 @@ impl Compiler { fn compile_try_star_statement( &mut self, - _body: &[located_ast::Stmt], - _handlers: &[located_ast::ExceptHandler], - _orelse: &[located_ast::Stmt], - _finalbody: &[located_ast::Stmt], + _body: &[Stmt], + _handlers: &[ExceptHandler], + _orelse: &[Stmt], + _finalbody: &[Stmt], ) -> CompileResult<()> { Err(self.error(CodegenErrorType::NotImplementedYet)) } @@ -1277,21 +1291,21 @@ impl Compiler { fn compile_function_def( &mut self, name: &str, - args: &located_ast::Arguments, - body: &[located_ast::Stmt], - decorator_list: &[located_ast::Expr], - returns: Option<&located_ast::Expr>, // TODO: use type hint somehow.. + parameters: &Parameters, + body: &[Stmt], + decorator_list: &[Decorator], + returns: Option<&Expr>, // TODO: use type hint somehow.. is_async: bool, - type_params: &[located_ast::TypeParam], + type_params: Option<&TypeParams>, ) -> CompileResult<()> { self.prepare_decorators(decorator_list)?; // If there are type params, we need to push a special symbol table just for them - if !type_params.is_empty() { + if type_params.is_some() { self.push_symbol_table(); } - let mut func_flags = self.enter_function(name, args)?; + let mut func_flags = self.enter_function(name, parameters)?; self.current_code_info() .flags .set(bytecode::CodeFlags::IS_COROUTINE, is_async); @@ -1323,7 +1337,7 @@ impl Compiler { // Emit None at end: match body.last() { - Some(located_ast::Stmt::Return(_)) => { + Some(Stmt::Return(_)) => { // the last instruction is a ReturnValue already, we don't need to emit it } _ => { @@ -1337,7 +1351,7 @@ impl Compiler { self.ctx = prev_ctx; // Prepare generic type parameters: - if !type_params.is_empty() { + if let Some(type_params) = type_params { self.compile_type_params(type_params)?; func_flags |= bytecode::MakeFunctionFlags::TYPE_PARAMS; } @@ -1356,17 +1370,17 @@ impl Compiler { num_annotations += 1; } - let args_iter = std::iter::empty() - .chain(&args.posonlyargs) - .chain(&args.args) - .chain(&args.kwonlyargs) - .map(|arg| arg.as_arg()) - .chain(args.vararg.as_deref()) - .chain(args.kwarg.as_deref()); - for arg in args_iter { - if let Some(annotation) = &arg.annotation { + let parameters_iter = std::iter::empty() + .chain(¶meters.posonlyargs) + .chain(¶meters.args) + .chain(¶meters.kwonlyargs) + .map(|x| &x.parameter) + .chain(parameters.vararg.as_deref()) + .chain(parameters.kwarg.as_deref()); + for param in parameters_iter { + if let Some(annotation) = ¶m.annotation { self.emit_load_const(ConstantData::Str { - value: self.mangle(arg.arg.as_str()).into_owned(), + value: self.mangle(param.name.as_str()).into_owned(), }); self.compile_annotation(annotation)?; num_annotations += 1; @@ -1388,7 +1402,7 @@ impl Compiler { } // Pop the special type params symbol table - if !type_params.is_empty() { + if type_params.is_some() { self.pop_symbol_table(); } @@ -1424,7 +1438,7 @@ impl Compiler { let symbol = table.lookup(var).unwrap_or_else(|| { panic!( "couldn't look up var {} in {} in {}", - var, code.obj_name, self.source_path + var, code.obj_name, self.source_code.path ) }); let parent_code = self.code_stack.last().unwrap(); @@ -1453,17 +1467,21 @@ impl Compiler { } // Python/compile.c find_ann - fn find_ann(body: &[located_ast::Stmt]) -> bool { - use located_ast::*; - + fn find_ann(body: &[Stmt]) -> bool { + use ruff_python_ast::*; for statement in body { let res = match &statement { Stmt::AnnAssign(_) => true, Stmt::For(StmtFor { body, orelse, .. }) => { Self::find_ann(body) || Self::find_ann(orelse) } - Stmt::If(StmtIf { body, orelse, .. }) => { - Self::find_ann(body) || Self::find_ann(orelse) + Stmt::If(StmtIf { + body, + elif_else_clauses, + .. + }) => { + Self::find_ann(body) + || elif_else_clauses.iter().any(|x| Self::find_ann(&x.body)) } Stmt::While(StmtWhile { body, orelse, .. }) => { Self::find_ann(body) || Self::find_ann(orelse) @@ -1487,16 +1505,13 @@ impl Compiler { fn compile_class_def( &mut self, name: &str, - body: &[located_ast::Stmt], - bases: &[located_ast::Expr], - keywords: &[located_ast::Keyword], - decorator_list: &[located_ast::Expr], - type_params: &[located_ast::TypeParam], + body: &[Stmt], + decorator_list: &[Decorator], + type_params: Option<&TypeParams>, + arguments: Option<&Arguments>, ) -> CompileResult<()> { self.prepare_decorators(decorator_list)?; - emit!(self, Instruction::LoadBuildClass); - let prev_ctx = self.ctx; self.ctx = CompileContext { func: FunctionContext::NoFunction, @@ -1519,7 +1534,7 @@ impl Compiler { let qualified_name = self.qualified_path.join("."); // If there are type params, we need to push a special symbol table just for them - if !type_params.is_empty() { + if type_params.is_some() { self.push_symbol_table(); } @@ -1571,10 +1586,12 @@ impl Compiler { self.qualified_path.append(global_path_prefix.as_mut()); self.ctx = prev_ctx; + emit!(self, Instruction::LoadBuildClass); + let mut func_flags = bytecode::MakeFunctionFlags::empty(); // Prepare generic type parameters: - if !type_params.is_empty() { + if let Some(type_params) = type_params { self.compile_type_params(type_params)?; func_flags |= bytecode::MakeFunctionFlags::TYPE_PARAMS; } @@ -1584,7 +1601,7 @@ impl Compiler { } // Pop the special type params symbol table - if !type_params.is_empty() { + if type_params.is_some() { self.pop_symbol_table(); } @@ -1602,7 +1619,12 @@ impl Compiler { value: name.to_owned(), }); - let call = self.compile_call_inner(2, bases, keywords)?; + // Call the __build_class__ builtin + let call = if let Some(arguments) = arguments { + self.compile_call_inner(2, arguments)? + } else { + CallType::Positional { nargs: 2 } + }; self.compile_normal_call(call); self.apply_decorators(decorator_list); @@ -1621,12 +1643,7 @@ impl Compiler { }); } - fn compile_while( - &mut self, - test: &located_ast::Expr, - body: &[located_ast::Stmt], - orelse: &[located_ast::Stmt], - ) -> CompileResult<()> { + fn compile_while(&mut self, test: &Expr, body: &[Stmt], orelse: &[Stmt]) -> CompileResult<()> { let while_block = self.new_block(); let else_block = self.new_block(); let after_block = self.new_block(); @@ -1654,11 +1671,11 @@ impl Compiler { fn compile_with( &mut self, - items: &[located_ast::WithItem], - body: &[located_ast::Stmt], + items: &[WithItem], + body: &[Stmt], is_async: bool, ) -> CompileResult<()> { - let with_location = self.current_source_location; + let with_range = self.current_source_range; let Some((item, items)) = items.split_first() else { return Err(self.error(CodegenErrorType::EmptyWithItems)); @@ -1668,7 +1685,7 @@ impl Compiler { let final_block = self.new_block(); self.compile_expression(&item.context_expr)?; - self.set_source_location(with_location); + self.set_source_range(with_range); if is_async { emit!(self, Instruction::BeforeAsyncWith); emit!(self, Instruction::GetAwaitable); @@ -1681,7 +1698,7 @@ impl Compiler { match &item.optional_vars { Some(var) => { - self.set_source_location(var.location()); + self.set_source_range(var.range()); self.compile_store(var)?; } None => { @@ -1697,13 +1714,13 @@ impl Compiler { } self.compile_statements(body)?; } else { - self.set_source_location(with_location); + self.set_source_range(with_range); self.compile_with(items, body, is_async)?; } // sort of "stack up" the layers of with blocks: // with a, b: body -> start_with(a) start_with(b) body() end_with(b) end_with(a) - self.set_source_location(with_location); + self.set_source_range(with_range); emit!(self, Instruction::PopBlock); emit!(self, Instruction::EnterFinally); @@ -1724,10 +1741,10 @@ impl Compiler { fn compile_for( &mut self, - target: &located_ast::Expr, - iter: &located_ast::Expr, - body: &[located_ast::Stmt], - orelse: &[located_ast::Stmt], + target: &Expr, + iter: &Expr, + body: &[Stmt], + orelse: &[Stmt], is_async: bool, ) -> CompileResult<()> { // Start loop @@ -1785,32 +1802,27 @@ impl Compiler { fn compile_pattern_value( &mut self, - value: &located_ast::PatternMatchValue, + value: &PatternMatchValue, _pattern_context: &mut PatternContext, ) -> CompileResult<()> { + use crate::compile::bytecode::ComparisonOperator::*; + self.compile_expression(&value.value)?; - emit!( - self, - Instruction::CompareOperation { - op: ComparisonOperator::Equal - } - ); + emit!(self, Instruction::CompareOperation { op: Equal }); Ok(()) } fn compile_pattern_as( &mut self, - as_pattern: &located_ast::PatternMatchAs, + as_pattern: &PatternMatchAs, pattern_context: &mut PatternContext, ) -> CompileResult<()> { if as_pattern.pattern.is_none() && !pattern_context.allow_irrefutable { // TODO: better error message if let Some(_name) = as_pattern.name.as_ref() { - return Err( - self.error_loc(CodegenErrorType::InvalidMatchCase, as_pattern.location()) - ); + return Err(self.error_ranged(CodegenErrorType::InvalidMatchCase, as_pattern.range)); } - return Err(self.error_loc(CodegenErrorType::InvalidMatchCase, as_pattern.location())); + return Err(self.error_ranged(CodegenErrorType::InvalidMatchCase, as_pattern.range)); } // Need to make a copy for (possibly) storing later: emit!(self, Instruction::Duplicate); @@ -1827,16 +1839,12 @@ impl Compiler { fn compile_pattern_inner( &mut self, - pattern_type: &located_ast::Pattern, + pattern_type: &Pattern, pattern_context: &mut PatternContext, ) -> CompileResult<()> { match &pattern_type { - located_ast::Pattern::MatchValue(value) => { - self.compile_pattern_value(value, pattern_context) - } - located_ast::Pattern::MatchAs(as_pattern) => { - self.compile_pattern_as(as_pattern, pattern_context) - } + Pattern::MatchValue(value) => self.compile_pattern_value(value, pattern_context), + Pattern::MatchAs(as_pattern) => self.compile_pattern_as(as_pattern, pattern_context), _ => { eprintln!("not implemented pattern type: {pattern_type:?}"); Err(self.error(CodegenErrorType::NotImplementedYet)) @@ -1846,7 +1854,7 @@ impl Compiler { fn compile_pattern( &mut self, - pattern_type: &located_ast::Pattern, + pattern_type: &Pattern, pattern_context: &mut PatternContext, ) -> CompileResult<()> { self.compile_pattern_inner(pattern_type, pattern_context)?; @@ -1861,8 +1869,8 @@ impl Compiler { fn compile_match_inner( &mut self, - subject: &located_ast::Expr, - cases: &[located_ast::MatchCase], + subject: &Expr, + cases: &[MatchCase], pattern_context: &mut PatternContext, ) -> CompileResult<()> { self.compile_expression(subject)?; @@ -1917,11 +1925,7 @@ impl Compiler { Ok(()) } - fn compile_match( - &mut self, - subject: &located_ast::Expr, - cases: &[located_ast::MatchCase], - ) -> CompileResult<()> { + fn compile_match(&mut self, subject: &Expr, cases: &[MatchCase]) -> CompileResult<()> { let mut pattern_context = PatternContext { current_block: usize::MAX, blocks: Vec::new(), @@ -1933,9 +1937,9 @@ impl Compiler { fn compile_chained_comparison( &mut self, - left: &located_ast::Expr, - ops: &[located_ast::CmpOp], - exprs: &[located_ast::Expr], + left: &Expr, + ops: &[CmpOp], + exprs: &[Expr], ) -> CompileResult<()> { assert!(!ops.is_empty()); assert_eq!(exprs.len(), ops.len()); @@ -1944,19 +1948,19 @@ impl Compiler { use bytecode::ComparisonOperator::*; use bytecode::TestOperator::*; - let compile_cmpop = |c: &mut Self, op: &located_ast::CmpOp| match op { - located_ast::CmpOp::Eq => emit!(c, Instruction::CompareOperation { op: Equal }), - located_ast::CmpOp::NotEq => emit!(c, Instruction::CompareOperation { op: NotEqual }), - located_ast::CmpOp::Lt => emit!(c, Instruction::CompareOperation { op: Less }), - located_ast::CmpOp::LtE => emit!(c, Instruction::CompareOperation { op: LessOrEqual }), - located_ast::CmpOp::Gt => emit!(c, Instruction::CompareOperation { op: Greater }), - located_ast::CmpOp::GtE => { + let compile_cmpop = |c: &mut Self, op: &CmpOp| match op { + CmpOp::Eq => emit!(c, Instruction::CompareOperation { op: Equal }), + CmpOp::NotEq => emit!(c, Instruction::CompareOperation { op: NotEqual }), + CmpOp::Lt => emit!(c, Instruction::CompareOperation { op: Less }), + CmpOp::LtE => emit!(c, Instruction::CompareOperation { op: LessOrEqual }), + CmpOp::Gt => emit!(c, Instruction::CompareOperation { op: Greater }), + CmpOp::GtE => { emit!(c, Instruction::CompareOperation { op: GreaterOrEqual }) } - located_ast::CmpOp::In => emit!(c, Instruction::TestOperation { op: In }), - located_ast::CmpOp::NotIn => emit!(c, Instruction::TestOperation { op: NotIn }), - located_ast::CmpOp::Is => emit!(c, Instruction::TestOperation { op: Is }), - located_ast::CmpOp::IsNot => emit!(c, Instruction::TestOperation { op: IsNot }), + CmpOp::In => emit!(c, Instruction::TestOperation { op: In }), + CmpOp::NotIn => emit!(c, Instruction::TestOperation { op: NotIn }), + CmpOp::Is => emit!(c, Instruction::TestOperation { op: Is }), + CmpOp::IsNot => emit!(c, Instruction::TestOperation { op: IsNot }), }; // a == b == c == d @@ -2021,10 +2025,14 @@ impl Compiler { Ok(()) } - fn compile_annotation(&mut self, annotation: &located_ast::Expr) -> CompileResult<()> { + fn compile_annotation(&mut self, annotation: &Expr) -> CompileResult<()> { if self.future_annotations { + // FIXME: codegen? + let ident = Default::default(); + let codegen = + ruff_python_codegen::Generator::new(&ident, Default::default(), Default::default()); self.emit_load_const(ConstantData::Str { - value: annotation.to_string(), + value: codegen.expr(annotation), }); } else { self.compile_expression(annotation)?; @@ -2034,9 +2042,9 @@ impl Compiler { fn compile_annotated_assign( &mut self, - target: &located_ast::Expr, - annotation: &located_ast::Expr, - value: Option<&located_ast::Expr>, + target: &Expr, + annotation: &Expr, + value: Option<&Expr>, ) -> CompileResult<()> { if let Some(value) = value { self.compile_expression(value)?; @@ -2051,7 +2059,7 @@ impl Compiler { // Compile annotation: self.compile_annotation(annotation)?; - if let located_ast::Expr::Name(located_ast::ExprName { id, .. }) = &target { + if let Expr::Name(ExprName { id, .. }) = &target { // Store as dict entry in __annotations__ dict: let annotations = self.name("__annotations__"); emit!(self, Instruction::LoadNameAny(annotations)); @@ -2067,29 +2075,26 @@ impl Compiler { Ok(()) } - fn compile_store(&mut self, target: &located_ast::Expr) -> CompileResult<()> { + fn compile_store(&mut self, target: &Expr) -> CompileResult<()> { match &target { - located_ast::Expr::Name(located_ast::ExprName { id, .. }) => { - self.store_name(id.as_str())? - } - located_ast::Expr::Subscript(located_ast::ExprSubscript { value, slice, .. }) => { + Expr::Name(ExprName { id, .. }) => self.store_name(id.as_str())?, + Expr::Subscript(ExprSubscript { value, slice, .. }) => { self.compile_expression(value)?; self.compile_expression(slice)?; emit!(self, Instruction::StoreSubscript); } - located_ast::Expr::Attribute(located_ast::ExprAttribute { value, attr, .. }) => { + Expr::Attribute(ExprAttribute { value, attr, .. }) => { self.check_forbidden_name(attr.as_str(), NameUsage::Store)?; self.compile_expression(value)?; let idx = self.name(attr.as_str()); emit!(self, Instruction::StoreAttr { idx }); } - located_ast::Expr::List(located_ast::ExprList { elts, .. }) - | located_ast::Expr::Tuple(located_ast::ExprTuple { elts, .. }) => { + Expr::List(ExprList { elts, .. }) | Expr::Tuple(ExprTuple { elts, .. }) => { let mut seen_star = false; // Scan for star args: for (i, element) in elts.iter().enumerate() { - if let located_ast::Expr::Starred(_) = &element { + if let Expr::Starred(_) = &element { if seen_star { return Err(self.error(CodegenErrorType::MultipleStarArgs)); } else { @@ -2098,9 +2103,9 @@ impl Compiler { let after = elts.len() - i - 1; let (before, after) = (|| Some((before.to_u8()?, after.to_u8()?)))() .ok_or_else(|| { - self.error_loc( + self.error_ranged( CodegenErrorType::TooManyStarUnpack, - target.location(), + target.range(), ) })?; let args = bytecode::UnpackExArgs { before, after }; @@ -2119,9 +2124,7 @@ impl Compiler { } for element in elts { - if let located_ast::Expr::Starred(located_ast::ExprStarred { value, .. }) = - &element - { + if let Expr::Starred(ExprStarred { value, .. }) = &element { self.compile_store(value)?; } else { self.compile_store(element)?; @@ -2130,7 +2133,7 @@ impl Compiler { } _ => { return Err(self.error(match target { - located_ast::Expr::Starred(_) => CodegenErrorType::SyntaxError( + Expr::Starred(_) => CodegenErrorType::SyntaxError( "starred assignment target must be in a list or tuple".to_owned(), ), _ => CodegenErrorType::Assign(target.python_name()), @@ -2143,9 +2146,9 @@ impl Compiler { fn compile_augassign( &mut self, - target: &located_ast::Expr, - op: &located_ast::Operator, - value: &located_ast::Expr, + target: &Expr, + op: &Operator, + value: &Expr, ) -> CompileResult<()> { enum AugAssignKind<'a> { Name { id: &'a str }, @@ -2154,19 +2157,19 @@ impl Compiler { } let kind = match &target { - located_ast::Expr::Name(located_ast::ExprName { id, .. }) => { + Expr::Name(ExprName { id, .. }) => { let id = id.as_str(); self.compile_name(id, NameUsage::Load)?; AugAssignKind::Name { id } } - located_ast::Expr::Subscript(located_ast::ExprSubscript { value, slice, .. }) => { + Expr::Subscript(ExprSubscript { value, slice, .. }) => { self.compile_expression(value)?; self.compile_expression(slice)?; emit!(self, Instruction::Duplicate2); emit!(self, Instruction::Subscript); AugAssignKind::Subscript } - located_ast::Expr::Attribute(located_ast::ExprAttribute { value, attr, .. }) => { + Expr::Attribute(ExprAttribute { value, attr, .. }) => { let attr = attr.as_str(); self.check_forbidden_name(attr, NameUsage::Store)?; self.compile_expression(value)?; @@ -2203,21 +2206,21 @@ impl Compiler { Ok(()) } - fn compile_op(&mut self, op: &located_ast::Operator, inplace: bool) { + fn compile_op(&mut self, op: &Operator, inplace: bool) { let op = match op { - located_ast::Operator::Add => bytecode::BinaryOperator::Add, - located_ast::Operator::Sub => bytecode::BinaryOperator::Subtract, - located_ast::Operator::Mult => bytecode::BinaryOperator::Multiply, - located_ast::Operator::MatMult => bytecode::BinaryOperator::MatrixMultiply, - located_ast::Operator::Div => bytecode::BinaryOperator::Divide, - located_ast::Operator::FloorDiv => bytecode::BinaryOperator::FloorDivide, - located_ast::Operator::Mod => bytecode::BinaryOperator::Modulo, - located_ast::Operator::Pow => bytecode::BinaryOperator::Power, - located_ast::Operator::LShift => bytecode::BinaryOperator::Lshift, - located_ast::Operator::RShift => bytecode::BinaryOperator::Rshift, - located_ast::Operator::BitOr => bytecode::BinaryOperator::Or, - located_ast::Operator::BitXor => bytecode::BinaryOperator::Xor, - located_ast::Operator::BitAnd => bytecode::BinaryOperator::And, + Operator::Add => bytecode::BinaryOperator::Add, + Operator::Sub => bytecode::BinaryOperator::Subtract, + Operator::Mult => bytecode::BinaryOperator::Multiply, + Operator::MatMult => bytecode::BinaryOperator::MatrixMultiply, + Operator::Div => bytecode::BinaryOperator::Divide, + Operator::FloorDiv => bytecode::BinaryOperator::FloorDivide, + Operator::Mod => bytecode::BinaryOperator::Modulo, + Operator::Pow => bytecode::BinaryOperator::Power, + Operator::LShift => bytecode::BinaryOperator::Lshift, + Operator::RShift => bytecode::BinaryOperator::Rshift, + Operator::BitOr => bytecode::BinaryOperator::Or, + Operator::BitXor => bytecode::BinaryOperator::Xor, + Operator::BitAnd => bytecode::BinaryOperator::And, }; if inplace { emit!(self, Instruction::BinaryOperationInplace { op }) @@ -2236,15 +2239,15 @@ impl Compiler { /// (indicated by the condition parameter). fn compile_jump_if( &mut self, - expression: &located_ast::Expr, + expression: &Expr, condition: bool, target_block: ir::BlockIdx, ) -> CompileResult<()> { // Compile expression for test, and jump to label if false match &expression { - located_ast::Expr::BoolOp(located_ast::ExprBoolOp { op, values, .. }) => { + Expr::BoolOp(ExprBoolOp { op, values, .. }) => { match op { - located_ast::BoolOp::And => { + BoolOp::And => { if condition { // If all values are true. let end_block = self.new_block(); @@ -2265,7 +2268,7 @@ impl Compiler { } } } - located_ast::BoolOp::Or => { + BoolOp::Or => { if condition { // If any of the values is true. for value in values { @@ -2288,8 +2291,8 @@ impl Compiler { } } } - located_ast::Expr::UnaryOp(located_ast::ExprUnaryOp { - op: located_ast::UnaryOp::Not, + Expr::UnaryOp(ExprUnaryOp { + op: UnaryOp::Not, operand, .. }) => { @@ -2320,11 +2323,7 @@ impl Compiler { /// Compile a boolean operation as an expression. /// This means, that the last value remains on the stack. - fn compile_bool_op( - &mut self, - op: &located_ast::BoolOp, - values: &[located_ast::Expr], - ) -> CompileResult<()> { + fn compile_bool_op(&mut self, op: &BoolOp, values: &[Expr]) -> CompileResult<()> { let after_block = self.new_block(); let (last_value, values) = values.split_last().unwrap(); @@ -2332,7 +2331,7 @@ impl Compiler { self.compile_expression(value)?; match op { - located_ast::BoolOp::And => { + BoolOp::And => { emit!( self, Instruction::JumpIfFalseOrPop { @@ -2340,7 +2339,7 @@ impl Compiler { } ); } - located_ast::BoolOp::Or => { + BoolOp::Or => { emit!( self, Instruction::JumpIfTrueOrPop { @@ -2357,44 +2356,36 @@ impl Compiler { Ok(()) } - fn compile_dict( - &mut self, - keys: &[Option], - values: &[located_ast::Expr], - ) -> CompileResult<()> { + fn compile_dict(&mut self, items: &[DictItem]) -> CompileResult<()> { + // FIXME: correct order to build map, etc d = {**a, 'key': 2} should override + // 'key' in dict a let mut size = 0; - let (packed, unpacked): (Vec<_>, Vec<_>) = keys - .iter() - .zip(values.iter()) - .partition(|(k, _)| k.is_some()); - for (key, value) in packed { - self.compile_expression(key.as_ref().unwrap())?; - self.compile_expression(value)?; + let (packed, unpacked): (Vec<_>, Vec<_>) = items.iter().partition(|x| x.key.is_some()); + for item in packed { + self.compile_expression(item.key.as_ref().unwrap())?; + self.compile_expression(&item.value)?; size += 1; } emit!(self, Instruction::BuildMap { size }); - for (_, value) in unpacked { - self.compile_expression(value)?; + for item in unpacked { + self.compile_expression(&item.value)?; emit!(self, Instruction::DictUpdate); } Ok(()) } - fn compile_expression(&mut self, expression: &located_ast::Expr) -> CompileResult<()> { - use located_ast::*; + fn compile_expression(&mut self, expression: &Expr) -> CompileResult<()> { + use ruff_python_ast::*; trace!("Compiling {:?}", expression); - let location = expression.location(); - self.set_source_location(location); + let range = expression.range(); + self.set_source_range(range); match &expression { Expr::Call(ExprCall { - func, - args, - keywords, - .. - }) => self.compile_call(func, args, keywords)?, + func, arguments, .. + }) => self.compile_call(func, arguments)?, Expr::BoolOp(ExprBoolOp { op, values, .. }) => self.compile_bool_op(op, values)?, Expr::BinOp(ExprBinOp { left, op, right, .. @@ -2435,9 +2426,9 @@ impl Compiler { }) => { self.compile_chained_comparison(left, ops, comparators)?; } - Expr::Constant(ExprConstant { value, .. }) => { - self.emit_load_const(compile_constant(value)); - } + // Expr::Constant(ExprConstant { value, .. }) => { + // self.emit_load_const(compile_constant(value)); + // } Expr::List(ExprList { elts, .. }) => { let (size, unpack) = self.gather_elements(0, elts)?; if unpack { @@ -2462,13 +2453,13 @@ impl Compiler { emit!(self, Instruction::BuildSet { size }); } } - Expr::Dict(ExprDict { keys, values, .. }) => { - self.compile_dict(keys, values)?; + Expr::Dict(ExprDict { items, .. }) => { + self.compile_dict(items)?; } Expr::Slice(ExprSlice { lower, upper, step, .. }) => { - let mut compile_bound = |bound: Option<&located_ast::Expr>| match bound { + let mut compile_bound = |bound: Option<&Expr>| match bound { Some(exp) => self.compile_expression(exp), None => { self.emit_load_const(ConstantData::None); @@ -2519,47 +2510,15 @@ impl Compiler { self.emit_load_const(ConstantData::None); emit!(self, Instruction::YieldFrom); } - Expr::JoinedStr(ExprJoinedStr { values, .. }) => { - if let Some(value) = try_get_constant_string(values) { - self.emit_load_const(ConstantData::Str { value }) - } else { - for value in values { - self.compile_expression(value)?; - } - emit!( - self, - Instruction::BuildString { - size: values.len().to_u32(), - } - ) - } - } - Expr::FormattedValue(ExprFormattedValue { - value, - conversion, - format_spec, - .. + Expr::Name(ExprName { id, .. }) => self.load_name(id.as_str())?, + Expr::Lambda(ExprLambda { + parameters, body, .. }) => { - match format_spec { - Some(spec) => self.compile_expression(spec)?, - None => self.emit_load_const(ConstantData::Str { - value: String::new(), - }), - }; - self.compile_expression(value)?; - emit!( - self, - Instruction::FormatValue { - conversion: *conversion, - }, - ); - } - Expr::Name(located_ast::ExprName { id, .. }) => self.load_name(id.as_str())?, - Expr::Lambda(located_ast::ExprLambda { args, body, .. }) => { let prev_ctx = self.ctx; let name = "".to_owned(); - let mut func_flags = self.enter_function(&name, args)?; + let mut func_flags = self + .enter_function(&name, parameters.as_deref().unwrap_or(&Default::default()))?; self.ctx = CompileContext { loop_data: Option::None, @@ -2586,7 +2545,7 @@ impl Compiler { self.ctx = prev_ctx; } - Expr::ListComp(located_ast::ExprListComp { + Expr::ListComp(ExprListComp { elt, generators, .. }) => { self.compile_comprehension( @@ -2609,7 +2568,7 @@ impl Compiler { Self::contains_await(elt), )?; } - Expr::SetComp(located_ast::ExprSetComp { + Expr::SetComp(ExprSetComp { elt, generators, .. }) => { self.compile_comprehension( @@ -2632,7 +2591,7 @@ impl Compiler { Self::contains_await(elt), )?; } - Expr::DictComp(located_ast::ExprDictComp { + Expr::DictComp(ExprDictComp { key, value, generators, @@ -2662,7 +2621,7 @@ impl Compiler { Self::contains_await(key) || Self::contains_await(value), )?; } - Expr::GeneratorExp(located_ast::ExprGeneratorExp { + Expr::Generator(ExprGenerator { elt, generators, .. }) => { self.compile_comprehension( @@ -2684,7 +2643,7 @@ impl Compiler { Expr::Starred(_) => { return Err(self.error(CodegenErrorType::InvalidStarExpr)); } - Expr::IfExp(located_ast::ExprIfExp { + Expr::If(ExprIf { test, body, orelse, .. }) => { let else_block = self.new_block(); @@ -2708,7 +2667,7 @@ impl Compiler { self.switch_to_block(after_block); } - Expr::NamedExpr(located_ast::ExprNamedExpr { + Expr::Named(ExprNamed { target, value, range: _, @@ -2717,11 +2676,50 @@ impl Compiler { emit!(self, Instruction::Duplicate); self.compile_store(target)?; } + Expr::FString(fstring) => { + self.compile_expr_fstring(fstring)?; + } + Expr::StringLiteral(string) => { + self.emit_load_const(ConstantData::Str { + value: string.value.to_str().to_owned(), + }); + } + Expr::BytesLiteral(bytes) => { + let iter = bytes.value.iter().flat_map(|x| x.iter().copied()); + let v: Vec = iter.collect(); + self.emit_load_const(ConstantData::Bytes { value: v }); + } + Expr::NumberLiteral(number) => match &number.value { + Number::Int(int) => { + let value = ruff_int_to_bigint(int).map_err(|e| self.error(e))?; + self.emit_load_const(ConstantData::Integer { value }); + } + Number::Float(float) => { + self.emit_load_const(ConstantData::Float { value: *float }); + } + Number::Complex { real, imag } => { + self.emit_load_const(ConstantData::Complex { + value: Complex::new(*real, *imag), + }); + } + }, + Expr::BooleanLiteral(b) => { + self.emit_load_const(ConstantData::Boolean { value: b.value }); + } + Expr::NoneLiteral(_) => { + self.emit_load_const(ConstantData::None); + } + Expr::EllipsisLiteral(_) => { + self.emit_load_const(ConstantData::Ellipsis); + } + Expr::IpyEscapeCommand(_) => { + panic!("unexpected ipy escape command"); + } } Ok(()) } - fn compile_keywords(&mut self, keywords: &[located_ast::Keyword]) -> CompileResult<()> { + fn compile_keywords(&mut self, keywords: &[Keyword]) -> CompileResult<()> { let mut size = 0; let groupby = keywords.iter().chunk_by(|e| e.arg.is_none()); for (is_unpacking, sub_keywords) in &groupby { @@ -2751,26 +2749,17 @@ impl Compiler { Ok(()) } - fn compile_call( - &mut self, - func: &located_ast::Expr, - args: &[located_ast::Expr], - keywords: &[located_ast::Keyword], - ) -> CompileResult<()> { - let method = - if let located_ast::Expr::Attribute(located_ast::ExprAttribute { - value, attr, .. - }) = &func - { - self.compile_expression(value)?; - let idx = self.name(attr.as_str()); - emit!(self, Instruction::LoadMethod { idx }); - true - } else { - self.compile_expression(func)?; - false - }; - let call = self.compile_call_inner(0, args, keywords)?; + fn compile_call(&mut self, func: &Expr, args: &Arguments) -> CompileResult<()> { + let method = if let Expr::Attribute(ExprAttribute { value, attr, .. }) = &func { + self.compile_expression(value)?; + let idx = self.name(attr.as_str()); + emit!(self, Instruction::LoadMethod { idx }); + true + } else { + self.compile_expression(func)?; + false + }; + let call = self.compile_call_inner(0, args)?; if method { self.compile_method_call(call) } else { @@ -2801,16 +2790,15 @@ impl Compiler { fn compile_call_inner( &mut self, additional_positional: u32, - args: &[located_ast::Expr], - keywords: &[located_ast::Keyword], + arguments: &Arguments, ) -> CompileResult { - let count = (args.len() + keywords.len()).to_u32() + additional_positional; + let count = u32::try_from(arguments.len()).unwrap() + additional_positional; // Normal arguments: - let (size, unpack) = self.gather_elements(additional_positional, args)?; - let has_double_star = keywords.iter().any(|k| k.arg.is_none()); + let (size, unpack) = self.gather_elements(additional_positional, &arguments.args)?; + let has_double_star = arguments.keywords.iter().any(|k| k.arg.is_none()); - for keyword in keywords { + for keyword in &arguments.keywords { if let Some(name) = &keyword.arg { self.check_forbidden_name(name.as_str(), NameUsage::Store)?; } @@ -2825,14 +2813,14 @@ impl Compiler { } // Create an optional map with kw-args: - let has_kwargs = !keywords.is_empty(); + let has_kwargs = !arguments.keywords.is_empty(); if has_kwargs { - self.compile_keywords(keywords)?; + self.compile_keywords(&arguments.keywords)?; } CallType::Ex { has_kwargs } - } else if !keywords.is_empty() { + } else if !arguments.keywords.is_empty() { let mut kwarg_names = vec![]; - for keyword in keywords { + for keyword in &arguments.keywords { if let Some(name) = &keyword.arg { kwarg_names.push(ConstantData::Str { value: name.to_string(), @@ -2857,15 +2845,9 @@ impl Compiler { // Given a vector of expr / star expr generate code which gives either // a list of expressions on the stack, or a list of tuples. - fn gather_elements( - &mut self, - before: u32, - elements: &[located_ast::Expr], - ) -> CompileResult<(u32, bool)> { + fn gather_elements(&mut self, before: u32, elements: &[Expr]) -> CompileResult<(u32, bool)> { // First determine if we have starred elements: - let has_stars = elements - .iter() - .any(|e| matches!(e, located_ast::Expr::Starred(_))); + let has_stars = elements.iter().any(|e| matches!(e, Expr::Starred(_))); let size = if has_stars { let mut size = 0; @@ -2878,9 +2860,7 @@ impl Compiler { let groups = elements .iter() .map(|element| { - if let located_ast::Expr::Starred(located_ast::ExprStarred { value, .. }) = - &element - { + if let Expr::Starred(ExprStarred { value, .. }) = &element { (true, value.as_ref()) } else { (false, element) @@ -2913,7 +2893,7 @@ impl Compiler { Ok((size, has_stars)) } - fn compile_comprehension_element(&mut self, element: &located_ast::Expr) -> CompileResult<()> { + fn compile_comprehension_element(&mut self, element: &Expr) -> CompileResult<()> { self.compile_expression(element).map_err(|e| { if let CodegenErrorType::InvalidStarExpr = e.error { self.error(CodegenErrorType::SyntaxError( @@ -2929,7 +2909,7 @@ impl Compiler { &mut self, name: &str, init_collection: Option, - generators: &[located_ast::Comprehension], + generators: &[Comprehension], compile_element: &dyn Fn(&mut Self) -> CompileResult<()>, comprehension_type: ComprehensionType, element_contains_await: bool, @@ -3110,13 +3090,11 @@ impl Compiler { Ok(()) } - fn compile_future_features( - &mut self, - features: &[located_ast::Alias], - ) -> Result<(), CodegenError> { - if self.done_with_future_stmts { + fn compile_future_features(&mut self, features: &[Alias]) -> Result<(), CodegenError> { + if let DoneWithFuture::Yes = self.done_with_future_stmts { return Err(self.error(CodegenErrorType::InvalidFuturePlacement)); } + self.done_with_future_stmts = DoneWithFuture::DoneWithDoc; for feature in features { match feature.name.as_str() { // Python 3 features; we've already implemented them by default @@ -3135,13 +3113,15 @@ impl Compiler { // Low level helper functions: fn _emit(&mut self, instr: Instruction, arg: OpArg, target: ir::BlockIdx) { - let location = self.current_source_location; + let range = self.current_source_range; + let location = self.source_code.source_location(range.start()); // TODO: insert source filename self.current_block().instructions.push(ir::InstructionInfo { instr, arg, target, location, + // range, }); } @@ -3220,13 +3200,13 @@ impl Compiler { code.current_block = block; } - fn set_source_location(&mut self, location: SourceLocation) { - self.current_source_location = location; + fn set_source_range(&mut self, range: TextRange) { + self.current_source_range = range; } - fn get_source_line_number(&mut self) -> LineNumber { - let location = self.current_source_location; - location.row + fn get_source_line_number(&mut self) -> OneIndexed { + self.source_code + .line_index(self.current_source_range.start()) } fn push_qualified_path(&mut self, name: &str) { @@ -3240,19 +3220,19 @@ impl Compiler { /// Whether the expression contains an await expression and /// thus requires the function to be async. /// Async with and async for are statements, so I won't check for them here - fn contains_await(expression: &located_ast::Expr) -> bool { - use located_ast::*; + fn contains_await(expression: &Expr) -> bool { + use ruff_python_ast::*; match &expression { Expr::Call(ExprCall { - func, - args, - keywords, - .. + func, arguments, .. }) => { Self::contains_await(func) - || args.iter().any(Self::contains_await) - || keywords.iter().any(|kw| Self::contains_await(&kw.value)) + || arguments.args.iter().any(Self::contains_await) + || arguments + .keywords + .iter() + .any(|kw| Self::contains_await(&kw.value)) } Expr::BoolOp(ExprBoolOp { values, .. }) => values.iter().any(Self::contains_await), Expr::BinOp(ExprBinOp { left, right, .. }) => { @@ -3266,14 +3246,13 @@ impl Compiler { Expr::Compare(ExprCompare { left, comparators, .. }) => Self::contains_await(left) || comparators.iter().any(Self::contains_await), - Expr::Constant(ExprConstant { .. }) => false, Expr::List(ExprList { elts, .. }) => elts.iter().any(Self::contains_await), Expr::Tuple(ExprTuple { elts, .. }) => elts.iter().any(Self::contains_await), Expr::Set(ExprSet { elts, .. }) => elts.iter().any(Self::contains_await), - Expr::Dict(ExprDict { keys, values, .. }) => { - keys.iter().flatten().any(Self::contains_await) - || values.iter().any(Self::contains_await) - } + Expr::Dict(ExprDict { items, .. }) => items + .iter() + .flat_map(|item| &item.key) + .any(Self::contains_await), Expr::Slice(ExprSlice { lower, upper, step, .. }) => { @@ -3286,33 +3265,21 @@ impl Compiler { } Expr::Await(ExprAwait { .. }) => true, Expr::YieldFrom(ExprYieldFrom { value, .. }) => Self::contains_await(value), - Expr::JoinedStr(ExprJoinedStr { values, .. }) => { - values.iter().any(Self::contains_await) - } - Expr::FormattedValue(ExprFormattedValue { - value, - conversion: _, - format_spec, - .. - }) => { - Self::contains_await(value) - || format_spec.as_deref().is_some_and(Self::contains_await) - } - Expr::Name(located_ast::ExprName { .. }) => false, - Expr::Lambda(located_ast::ExprLambda { body, .. }) => Self::contains_await(body), - Expr::ListComp(located_ast::ExprListComp { + Expr::Name(ExprName { .. }) => false, + Expr::Lambda(ExprLambda { body, .. }) => Self::contains_await(body), + Expr::ListComp(ExprListComp { elt, generators, .. }) => { Self::contains_await(elt) || generators.iter().any(|jen| Self::contains_await(&jen.iter)) } - Expr::SetComp(located_ast::ExprSetComp { + Expr::SetComp(ExprSetComp { elt, generators, .. }) => { Self::contains_await(elt) || generators.iter().any(|jen| Self::contains_await(&jen.iter)) } - Expr::DictComp(located_ast::ExprDictComp { + Expr::DictComp(ExprDictComp { key, value, generators, @@ -3322,14 +3289,14 @@ impl Compiler { || Self::contains_await(value) || generators.iter().any(|jen| Self::contains_await(&jen.iter)) } - Expr::GeneratorExp(located_ast::ExprGeneratorExp { + Expr::Generator(ExprGenerator { elt, generators, .. }) => { Self::contains_await(elt) || generators.iter().any(|jen| Self::contains_await(&jen.iter)) } Expr::Starred(expr) => Self::contains_await(&expr.value), - Expr::IfExp(located_ast::ExprIfExp { + Expr::If(ExprIf { test, body, orelse, .. }) => { Self::contains_await(test) @@ -3337,13 +3304,165 @@ impl Compiler { || Self::contains_await(orelse) } - Expr::NamedExpr(located_ast::ExprNamedExpr { + Expr::Named(ExprNamed { target, value, range: _, }) => Self::contains_await(target) || Self::contains_await(value), + Expr::FString(ExprFString { value, range: _ }) => { + fn expr_element_contains_await bool>( + expr_element: &FStringExpressionElement, + contains_await: F, + ) -> bool { + contains_await(&expr_element.expression) + || expr_element + .format_spec + .iter() + .flat_map(|spec| spec.elements.expressions()) + .any(|element| expr_element_contains_await(element, contains_await)) + } + + value.elements().any(|element| match element { + FStringElement::Expression(expr_element) => { + expr_element_contains_await(expr_element, Self::contains_await) + } + FStringElement::Literal(_) => false, + }) + } + Expr::StringLiteral(_) + | Expr::BytesLiteral(_) + | Expr::NumberLiteral(_) + | Expr::BooleanLiteral(_) + | Expr::NoneLiteral(_) + | Expr::EllipsisLiteral(_) + | Expr::IpyEscapeCommand(_) => false, } } + + fn compile_expr_fstring(&mut self, fstring: &ExprFString) -> CompileResult<()> { + let fstring = &fstring.value; + for part in fstring { + self.compile_fstring_part(part)?; + } + let part_count: u32 = fstring + .iter() + .len() + .try_into() + .expect("BuildString size overflowed"); + if part_count > 1 { + emit!(self, Instruction::BuildString { size: part_count }); + } + + Ok(()) + } + + fn compile_fstring_part(&mut self, part: &FStringPart) -> CompileResult<()> { + match part { + FStringPart::Literal(string) => { + self.emit_load_const(ConstantData::Str { + value: string.value.to_string(), + }); + Ok(()) + } + FStringPart::FString(fstring) => self.compile_fstring(fstring), + } + } + + fn compile_fstring(&mut self, fstring: &FString) -> CompileResult<()> { + self.compile_fstring_elements(&fstring.elements) + } + + fn compile_fstring_elements( + &mut self, + fstring_elements: &FStringElements, + ) -> CompileResult<()> { + for element in fstring_elements { + match element { + FStringElement::Literal(string) => { + self.emit_load_const(ConstantData::Str { + value: string.value.to_string(), + }); + } + FStringElement::Expression(fstring_expr) => { + let mut conversion = fstring_expr.conversion; + + let debug_text_count = match &fstring_expr.debug_text { + None => 0, + Some(DebugText { leading, trailing }) => { + let range = fstring_expr.expression.range(); + let source = self.source_code.get_range(range); + let source = source.to_string(); + + self.emit_load_const(ConstantData::Str { + value: leading.to_string(), + }); + self.emit_load_const(ConstantData::Str { value: source }); + self.emit_load_const(ConstantData::Str { + value: trailing.to_string(), + }); + + 3 + } + }; + + match &fstring_expr.format_spec { + None => { + self.emit_load_const(ConstantData::Str { + value: String::new(), + }); + // Match CPython behavior: If debug text is present, apply repr conversion. + // See: https://github.com/python/cpython/blob/f61afca262d3a0aa6a8a501db0b1936c60858e35/Parser/action_helpers.c#L1456 + if conversion == ConversionFlag::None && debug_text_count > 0 { + conversion = ConversionFlag::Repr; + } + } + Some(format_spec) => { + self.compile_fstring_elements(&format_spec.elements)?; + } + } + + self.compile_expression(&fstring_expr.expression)?; + + emit!( + self, + Instruction::FormatValue { + conversion: conversion + } + ); + + // concatenate formatted string and debug text (if present) + if debug_text_count > 0 { + emit!( + self, + Instruction::BuildString { + size: debug_text_count + 1 + } + ); + } + } + } + } + + let element_count: u32 = fstring_elements + .len() + .try_into() + .expect("BuildString size overflowed"); + if element_count == 0 { + // ensure to put an empty string on the stack if there aren't any fstring elements + self.emit_load_const(ConstantData::Str { + value: String::new(), + }); + } else if element_count > 1 { + emit!( + self, + Instruction::BuildString { + size: element_count + } + ); + } + + Ok(()) + } } trait EmitArg { @@ -3404,14 +3523,17 @@ fn clean_doc(doc: &str) -> String { } } -fn split_doc<'a>( - body: &'a [located_ast::Stmt], - opts: &CompileOpts, -) -> (Option, &'a [located_ast::Stmt]) { - if let Some((located_ast::Stmt::Expr(expr), body_rest)) = body.split_first() { - if let Some(doc) = try_get_constant_string(std::slice::from_ref(&expr.value)) { +fn split_doc<'a>(body: &'a [Stmt], opts: &CompileOpts) -> (Option, &'a [Stmt]) { + if let Some((Stmt::Expr(expr), body_rest)) = body.split_first() { + let doc_comment = match &*expr.value { + Expr::StringLiteral(value) => Some(&value.value), + // f-strings are not allowed in Python doc comments. + Expr::FString(_) => None, + _ => None, + }; + if let Some(doc) = doc_comment { return if opts.optimize < 2 { - (Some(clean_doc(&doc)), body_rest) + (Some(clean_doc(doc.to_str())), body_rest) } else { (None, body_rest) }; @@ -3420,49 +3542,43 @@ fn split_doc<'a>( (None, body) } -fn try_get_constant_string(values: &[located_ast::Expr]) -> Option { - fn get_constant_string_inner(out_string: &mut String, value: &located_ast::Expr) -> bool { - match value { - located_ast::Expr::Constant(located_ast::ExprConstant { - value: located_ast::Constant::Str(s), - .. - }) => { - out_string.push_str(s); - true - } - located_ast::Expr::JoinedStr(located_ast::ExprJoinedStr { values, .. }) => values - .iter() - .all(|value| get_constant_string_inner(out_string, value)), - _ => false, - } - } - let mut out_string = String::new(); - if values - .iter() - .all(|v| get_constant_string_inner(&mut out_string, v)) - { - Some(out_string) +pub fn ruff_int_to_bigint(int: &Int) -> Result { + if let Some(small) = int.as_u64() { + Ok(BigInt::from(small)) } else { - None + parse_big_integer(int) } } -fn compile_constant(value: &located_ast::Constant) -> ConstantData { - match value { - located_ast::Constant::None => ConstantData::None, - located_ast::Constant::Bool(b) => ConstantData::Boolean { value: *b }, - located_ast::Constant::Str(s) => ConstantData::Str { value: s.clone() }, - located_ast::Constant::Bytes(b) => ConstantData::Bytes { value: b.clone() }, - located_ast::Constant::Int(i) => ConstantData::Integer { value: i.clone() }, - located_ast::Constant::Tuple(t) => ConstantData::Tuple { - elements: t.iter().map(compile_constant).collect(), - }, - located_ast::Constant::Float(f) => ConstantData::Float { value: *f }, - located_ast::Constant::Complex { real, imag } => ConstantData::Complex { - value: Complex64::new(*real, *imag), - }, - located_ast::Constant::Ellipsis => ConstantData::Ellipsis, - } +/// Converts a `ruff` ast integer into a `BigInt`. +/// Unlike small integers, big integers may be stored in one of four possible radix representations. +fn parse_big_integer(int: &Int) -> Result { + // TODO: Improve ruff API + // Can we avoid this copy? + let s = format!("{}", int); + let mut s = s.as_str(); + // See: https://peps.python.org/pep-0515/#literal-grammar + let radix = match s.get(0..2) { + Some("0b" | "0B") => { + s = s.get(2..).unwrap_or(s); + 2 + } + Some("0o" | "0O") => { + s = s.get(2..).unwrap_or(s); + 8 + } + Some("0x" | "0X") => { + s = s.get(2..).unwrap_or(s); + 16 + } + _ => 10, + }; + + BigInt::from_str_radix(s, radix).map_err(|e| { + CodegenErrorType::SyntaxError(format!( + "unparsed integer literal (radix {radix}): {s} ({e})" + )) + }) } // Note: Not a good practice in general. Keep this trait private only for compiler @@ -3476,6 +3592,110 @@ impl ToU32 for usize { } } +#[cfg(test)] +mod tests { + use super::*; + use ruff_python_ast::*; + + /// Test if the compiler can correctly identify fstrings containing an `await` expression. + #[test] + fn test_fstring_contains_await() { + let range = TextRange::default(); + let flags = FStringFlags::default(); + + // f'{x}' + let expr_x = Expr::Name(ExprName { + range, + id: "x".to_owned(), + ctx: ExprContext::Load, + }); + let not_present = &Expr::FString(ExprFString { + range, + value: FStringValue::single(FString { + range, + elements: vec![FStringElement::Expression(FStringExpressionElement { + range, + expression: Box::new(expr_x), + debug_text: None, + conversion: ConversionFlag::None, + format_spec: None, + })] + .into(), + flags, + }), + }); + assert_eq!(Compiler::contains_await(not_present), false); + + // f'{await x}' + let expr_await_x = Expr::Await(ExprAwait { + range, + value: Box::new(Expr::Name(ExprName { + range, + id: "x".to_owned(), + ctx: ExprContext::Load, + })), + }); + let present = &Expr::FString(ExprFString { + range, + value: FStringValue::single(FString { + range, + elements: vec![FStringElement::Expression(FStringExpressionElement { + range, + expression: Box::new(expr_await_x), + debug_text: None, + conversion: ConversionFlag::None, + format_spec: None, + })] + .into(), + flags, + }), + }); + assert_eq!(Compiler::contains_await(present), true); + + // f'{x:{await y}}' + let expr_x = Expr::Name(ExprName { + range, + id: "x".to_owned(), + ctx: ExprContext::Load, + }); + let expr_await_y = Expr::Await(ExprAwait { + range, + value: Box::new(Expr::Name(ExprName { + range, + id: "y".to_owned(), + ctx: ExprContext::Load, + })), + }); + let present = &Expr::FString(ExprFString { + range, + value: FStringValue::single(FString { + range, + elements: vec![FStringElement::Expression(FStringExpressionElement { + range, + expression: Box::new(expr_x), + debug_text: None, + conversion: ConversionFlag::None, + format_spec: Some(Box::new(FStringFormatSpec { + range, + elements: vec![FStringElement::Expression(FStringExpressionElement { + range, + expression: Box::new(expr_await_y), + debug_text: None, + conversion: ConversionFlag::None, + format_spec: None, + })] + .into(), + })), + })] + .into(), + flags, + }), + }); + assert_eq!(Compiler::contains_await(present), true); + } +} + +/* #[cfg(test)] mod tests { use super::*; @@ -3555,3 +3775,4 @@ for stop_exc in (StopIteration('spam'), StopAsyncIteration('ham')): )); } } +*/ diff --git a/compiler/codegen/src/error.rs b/compiler/codegen/src/error.rs index 581f22971..8f38680de 100644 --- a/compiler/codegen/src/error.rs +++ b/compiler/codegen/src/error.rs @@ -1,6 +1,23 @@ +use ruff_source_file::SourceLocation; use std::fmt; +use thiserror::Error; -pub type CodegenError = rustpython_parser_core::source_code::LocatedError; +// pub type CodegenError = rustpython_parser_core::source_code::LocatedError; + +#[derive(Error, Debug)] +pub struct CodegenError { + pub location: Option, + #[source] + pub error: CodegenErrorType, + pub source_path: String, +} + +impl fmt::Display for CodegenError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // TODO: + self.error.fmt(f) + } +} #[derive(Debug)] #[non_exhaustive] diff --git a/compiler/codegen/src/ir.rs b/compiler/codegen/src/ir.rs index 08e68d283..2b3e49d03 100644 --- a/compiler/codegen/src/ir.rs +++ b/compiler/codegen/src/ir.rs @@ -1,10 +1,11 @@ use std::ops; use crate::IndexSet; +use ruff_source_file::{OneIndexed, SourceLocation}; use rustpython_compiler_core::bytecode::{ CodeFlags, CodeObject, CodeUnit, ConstantData, InstrDisplayContext, Instruction, Label, OpArg, }; -use rustpython_parser_core::source_code::{LineNumber, SourceLocation}; +// use rustpython_parser_core::source_code::{LineNumber, SourceLocation}; #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct BlockIdx(pub u32); @@ -37,11 +38,12 @@ impl ops::IndexMut for Vec { } } -#[derive(Debug, Copy, Clone)] +#[derive(Debug, Clone)] pub struct InstructionInfo { pub instr: Instruction, pub arg: OpArg, pub target: BlockIdx, + // pub range: TextRange, pub location: SourceLocation, } @@ -68,7 +70,7 @@ pub struct CodeInfo { pub arg_count: u32, pub kwonlyarg_count: u32, pub source_path: String, - pub first_line_number: LineNumber, + pub first_line_number: OneIndexed, pub obj_name: String, // Name of the object that created this code object pub blocks: Vec, @@ -134,7 +136,8 @@ impl CodeInfo { *arg = new_arg; } let (extras, lo_arg) = arg.split(); - locations.extend(std::iter::repeat(info.location).take(arg.instr_size())); + locations + .extend(std::iter::repeat(info.location.clone()).take(arg.instr_size())); instructions.extend( extras .map(|byte| CodeUnit::new(Instruction::ExtendedArg, byte)) diff --git a/compiler/codegen/src/lib.rs b/compiler/codegen/src/lib.rs index 910d015a3..ceadb3c36 100644 --- a/compiler/codegen/src/lib.rs +++ b/compiler/codegen/src/lib.rs @@ -14,3 +14,49 @@ pub mod ir; pub mod symboltable; pub use compile::CompileOpts; +use ruff_python_ast::Expr; + +pub trait ToPythonName { + /// Returns a short name for the node suitable for use in error messages. + fn python_name(&self) -> &'static str; +} + +impl ToPythonName for Expr { + fn python_name(&self) -> &'static str { + match self { + Expr::BoolOp { .. } | Expr::BinOp { .. } | Expr::UnaryOp { .. } => "operator", + Expr::Subscript { .. } => "subscript", + Expr::Await { .. } => "await expression", + Expr::Yield { .. } | Expr::YieldFrom { .. } => "yield expression", + Expr::Compare { .. } => "comparison", + Expr::Attribute { .. } => "attribute", + Expr::Call { .. } => "function call", + Expr::BooleanLiteral(b) => { + if b.value { + "True" + } else { + "False" + } + } + Expr::EllipsisLiteral(_) => "ellipsis", + Expr::NoneLiteral(_) => "None", + Expr::NumberLiteral(_) | Expr::BytesLiteral(_) | Expr::StringLiteral(_) => "literal", + Expr::Tuple(_) => "tuple", + Expr::List { .. } => "list", + Expr::Dict { .. } => "dict display", + Expr::Set { .. } => "set display", + Expr::ListComp { .. } => "list comprehension", + Expr::DictComp { .. } => "dict comprehension", + Expr::SetComp { .. } => "set comprehension", + Expr::Generator { .. } => "generator expression", + Expr::Starred { .. } => "starred", + Expr::Slice { .. } => "slice", + Expr::FString { .. } => "f-string expression", + Expr::Name { .. } => "name", + Expr::Lambda { .. } => "lambda", + Expr::If { .. } => "conditional expression", + Expr::Named { .. } => "named expression", + Expr::IpyEscapeCommand(_) => todo!(), + } + } +} diff --git a/compiler/codegen/src/symboltable.rs b/compiler/codegen/src/symboltable.rs index 53d4ff8eb..4246700ce 100644 --- a/compiler/codegen/src/symboltable.rs +++ b/compiler/codegen/src/symboltable.rs @@ -12,8 +12,16 @@ use crate::{ error::{CodegenError, CodegenErrorType}, }; use bitflags::bitflags; -use rustpython_ast::{self as ast, located::Located}; -use rustpython_parser_core::source_code::{LineNumber, SourceLocation}; +use ruff_python_ast::{ + self as ast, Comprehension, Decorator, Expr, Identifier, ModExpression, ModModule, Parameter, + ParameterWithDefault, Parameters, Pattern, PatternMatchAs, PatternMatchClass, + PatternMatchMapping, PatternMatchOr, PatternMatchSequence, PatternMatchStar, PatternMatchValue, + Stmt, TypeParam, TypeParamParamSpec, TypeParamTypeVar, TypeParamTypeVarTuple, TypeParams, +}; +use ruff_text_size::{Ranged, TextRange}; +use rustpython_compiler_source::{SourceCode, SourceLocation}; +// use rustpython_ast::{self as ast, located::Located}; +// use rustpython_parser_core::source_code::{LineNumber, SourceLocation}; use std::{borrow::Cow, fmt}; /// Captures all symbols in the current scope, and has a list of sub-scopes in this scope. @@ -51,15 +59,18 @@ impl SymbolTable { } } - pub fn scan_program(program: &[ast::located::Stmt]) -> SymbolTableResult { - let mut builder = SymbolTableBuilder::new(); - builder.scan_statements(program)?; + pub fn scan_program( + program: &ModModule, + source_code: SourceCode<'_>, + ) -> SymbolTableResult { + let mut builder = SymbolTableBuilder::new(source_code); + builder.scan_statements(program.body.as_ref())?; builder.finish() } - pub fn scan_expr(expr: &ast::located::Expr) -> SymbolTableResult { - let mut builder = SymbolTableBuilder::new(); - builder.scan_expression(expr, ExpressionContext::Load)?; + pub fn scan_expr(expr: &ModExpression, source_code: SourceCode<'_>) -> SymbolTableResult { + let mut builder = SymbolTableBuilder::new(source_code); + builder.scan_expression(expr.body.as_ref(), ExpressionContext::Load)?; builder.finish() } } @@ -176,11 +187,8 @@ pub struct SymbolTableError { impl SymbolTableError { pub fn into_codegen_error(self, source_path: String) -> CodegenError { CodegenError { + location: self.location, error: CodegenErrorType::SyntaxError(self.error), - location: self.location.map(|l| SourceLocation { - row: l.row, - column: l.column, - }), source_path, } } @@ -551,11 +559,12 @@ enum SymbolUsage { Iter, } -struct SymbolTableBuilder { +struct SymbolTableBuilder<'src> { class_name: Option, // Scope stack. tables: Vec, future_annotations: bool, + source_code: SourceCode<'src>, } /// Enum to indicate in what mode an expression @@ -571,19 +580,20 @@ enum ExpressionContext { IterDefinitionExp, } -impl SymbolTableBuilder { - fn new() -> Self { +impl<'src> SymbolTableBuilder<'src> { + fn new(source_code: SourceCode<'src>) -> Self { let mut this = Self { class_name: None, tables: vec![], future_annotations: false, + source_code, }; this.enter_scope("top", SymbolTableType::Module, 0); this } } -impl SymbolTableBuilder { +impl SymbolTableBuilder<'_> { fn finish(mut self) -> Result { assert_eq!(self.tables.len(), 1); let mut symbol_table = self.tables.pop().unwrap(); @@ -607,38 +617,34 @@ impl SymbolTableBuilder { self.tables.last_mut().unwrap().sub_tables.push(table); } - fn scan_statements(&mut self, statements: &[ast::located::Stmt]) -> SymbolTableResult { + fn line_index_start(&self, range: TextRange) -> u32 { + self.source_code.line_index(range.start()).get() as _ + } + + fn scan_statements(&mut self, statements: &[Stmt]) -> SymbolTableResult { for statement in statements { self.scan_statement(statement)?; } Ok(()) } - fn scan_parameters( - &mut self, - parameters: &[ast::located::ArgWithDefault], - ) -> SymbolTableResult { + fn scan_parameters(&mut self, parameters: &[ParameterWithDefault]) -> SymbolTableResult { for parameter in parameters { - let usage = if parameter.def.annotation.is_some() { - SymbolUsage::AnnotationParameter - } else { - SymbolUsage::Parameter - }; - self.register_name(parameter.def.arg.as_str(), usage, parameter.def.location())?; + self.scan_parameter(¶meter.parameter)?; } Ok(()) } - fn scan_parameter(&mut self, parameter: &ast::located::Arg) -> SymbolTableResult { + fn scan_parameter(&mut self, parameter: &Parameter) -> SymbolTableResult { let usage = if parameter.annotation.is_some() { SymbolUsage::AnnotationParameter } else { SymbolUsage::Parameter }; - self.register_name(parameter.arg.as_str(), usage, parameter.location()) + self.register_ident(¶meter.name, usage) } - fn scan_annotation(&mut self, annotation: &ast::located::Expr) -> SymbolTableResult { + fn scan_annotation(&mut self, annotation: &Expr) -> SymbolTableResult { if self.future_annotations { Ok(()) } else { @@ -646,8 +652,8 @@ impl SymbolTableBuilder { } } - fn scan_statement(&mut self, statement: &ast::located::Stmt) -> SymbolTableResult { - use ast::located::*; + fn scan_statement(&mut self, statement: &Stmt) -> SymbolTableResult { + use ruff_python_ast::*; if let Stmt::ImportFrom(StmtImportFrom { module, names, .. }) = &statement { if module.as_ref().map(|id| id.as_str()) == Some("__future__") { for feature in names { @@ -658,101 +664,109 @@ impl SymbolTableBuilder { } } match &statement { - Stmt::Global(StmtGlobal { names, range }) => { + Stmt::Global(StmtGlobal { names, .. }) => { for name in names { - self.register_name(name.as_str(), SymbolUsage::Global, range.start)?; + self.register_ident(name, SymbolUsage::Global)?; } } - Stmt::Nonlocal(StmtNonlocal { names, range }) => { + Stmt::Nonlocal(StmtNonlocal { names, .. }) => { for name in names { - self.register_name(name.as_str(), SymbolUsage::Nonlocal, range.start)?; + self.register_ident(name, SymbolUsage::Nonlocal)?; } } Stmt::FunctionDef(StmtFunctionDef { name, body, - args, - decorator_list, - type_params, - returns, - range, - .. - }) - | Stmt::AsyncFunctionDef(StmtAsyncFunctionDef { - name, - body, - args, + parameters, decorator_list, type_params, returns, range, .. }) => { - self.scan_expressions(decorator_list, ExpressionContext::Load)?; - self.register_name(name.as_str(), SymbolUsage::Assigned, range.start)?; + self.scan_decorators(decorator_list, ExpressionContext::Load)?; + self.register_ident(name, SymbolUsage::Assigned)?; if let Some(expression) = returns { self.scan_annotation(expression)?; } - if !type_params.is_empty() { + if let Some(type_params) = type_params { self.enter_scope( &format!("", name.as_str()), SymbolTableType::TypeParams, - range.start.row.get(), + // FIXME: line no + self.line_index_start(*range), ); self.scan_type_params(type_params)?; } - self.enter_function(name.as_str(), args, range.start.row)?; + self.enter_scope_with_parameters( + name.as_str(), + parameters, + self.line_index_start(*range), + )?; self.scan_statements(body)?; self.leave_scope(); - if !type_params.is_empty() { + if type_params.is_some() { self.leave_scope(); } } Stmt::ClassDef(StmtClassDef { name, body, - bases, - keywords, + arguments, decorator_list, type_params, range, }) => { - if !type_params.is_empty() { + if let Some(type_params) = type_params { self.enter_scope( &format!("", name.as_str()), SymbolTableType::TypeParams, - range.start.row.get(), + self.line_index_start(type_params.range), ); self.scan_type_params(type_params)?; } - self.enter_scope(name.as_str(), SymbolTableType::Class, range.start.row.get()); + self.enter_scope( + name.as_str(), + SymbolTableType::Class, + self.line_index_start(*range), + ); let prev_class = std::mem::replace(&mut self.class_name, Some(name.to_string())); - self.register_name("__module__", SymbolUsage::Assigned, range.start)?; - self.register_name("__qualname__", SymbolUsage::Assigned, range.start)?; - self.register_name("__doc__", SymbolUsage::Assigned, range.start)?; - self.register_name("__class__", SymbolUsage::Assigned, range.start)?; + self.register_name("__module__", SymbolUsage::Assigned, *range)?; + self.register_name("__qualname__", SymbolUsage::Assigned, *range)?; + self.register_name("__doc__", SymbolUsage::Assigned, *range)?; + self.register_name("__class__", SymbolUsage::Assigned, *range)?; self.scan_statements(body)?; self.leave_scope(); self.class_name = prev_class; - self.scan_expressions(bases, ExpressionContext::Load)?; - for keyword in keywords { - self.scan_expression(&keyword.value, ExpressionContext::Load)?; + if let Some(arguments) = arguments { + self.scan_expressions(&arguments.args, ExpressionContext::Load)?; + for keyword in &arguments.keywords { + self.scan_expression(&keyword.value, ExpressionContext::Load)?; + } } - if !type_params.is_empty() { + if type_params.is_some() { self.leave_scope(); } - self.scan_expressions(decorator_list, ExpressionContext::Load)?; - self.register_name(name.as_str(), SymbolUsage::Assigned, range.start)?; + self.scan_decorators(decorator_list, ExpressionContext::Load)?; + self.register_ident(name, SymbolUsage::Assigned)?; } Stmt::Expr(StmtExpr { value, .. }) => { self.scan_expression(value, ExpressionContext::Load)? } Stmt::If(StmtIf { - test, body, orelse, .. + test, + body, + elif_else_clauses, + .. }) => { self.scan_expression(test, ExpressionContext::Load)?; self.scan_statements(body)?; - self.scan_statements(orelse)?; + for elif in elif_else_clauses { + if let Some(test) = &elif.test { + self.scan_expression(test, ExpressionContext::Load)?; + } + self.scan_statements(&elif.body)?; + } } Stmt::For(StmtFor { target, @@ -760,13 +774,6 @@ impl SymbolTableBuilder { body, orelse, .. - }) - | Stmt::AsyncFor(StmtAsyncFor { - target, - iter, - body, - orelse, - .. }) => { self.scan_expression(target, ExpressionContext::Store)?; self.scan_expression(iter, ExpressionContext::Load)?; @@ -783,18 +790,18 @@ impl SymbolTableBuilder { Stmt::Break(_) | Stmt::Continue(_) | Stmt::Pass(_) => { // No symbols here. } - Stmt::Import(StmtImport { names, range }) - | Stmt::ImportFrom(StmtImportFrom { names, range, .. }) => { + Stmt::Import(StmtImport { names, .. }) + | Stmt::ImportFrom(StmtImportFrom { names, .. }) => { for name in names { if let Some(alias) = &name.asname { // `import my_module as my_alias` - self.register_name(alias.as_str(), SymbolUsage::Imported, range.start)?; + self.register_ident(alias, SymbolUsage::Imported)?; } else { // `import module` self.register_name( name.name.split('.').next().unwrap(), SymbolUsage::Imported, - range.start, + name.name.range, )?; } } @@ -831,11 +838,7 @@ impl SymbolTableBuilder { // https://github.com/python/cpython/blob/main/Python/symtable.c#L1233 match &**target { Expr::Name(ast::ExprName { id, .. }) if *simple => { - self.register_name( - id.as_str(), - SymbolUsage::AnnotationAssigned, - range.start, - )?; + self.register_name(id.as_str(), SymbolUsage::AnnotationAssigned, *range)?; } _ => { self.scan_expression(target, ExpressionContext::Store)?; @@ -846,8 +849,7 @@ impl SymbolTableBuilder { self.scan_expression(value, ExpressionContext::Load)?; } } - Stmt::With(StmtWith { items, body, .. }) - | Stmt::AsyncWith(StmtAsyncWith { items, body, .. }) => { + Stmt::With(StmtWith { items, body, .. }) => { for item in items { self.scan_expression(&item.context_expr, ExpressionContext::Load)?; if let Some(expression) = &item.optional_vars { @@ -861,14 +863,7 @@ impl SymbolTableBuilder { handlers, orelse, finalbody, - range, - }) - | Stmt::TryStar(StmtTryStar { - body, - handlers, - orelse, - finalbody, - range, + .. }) => { self.scan_statements(body)?; for handler in handlers { @@ -882,7 +877,7 @@ impl SymbolTableBuilder { self.scan_expression(expression, ExpressionContext::Load)?; } if let Some(name) = name { - self.register_name(name.as_str(), SymbolUsage::Assigned, range.start)?; + self.register_ident(name, SymbolUsage::Assigned)?; } self.scan_statements(body)?; } @@ -892,8 +887,10 @@ impl SymbolTableBuilder { Stmt::Match(StmtMatch { subject, cases, .. }) => { self.scan_expression(subject, ExpressionContext::Load)?; for case in cases { - // TODO: below - // self.scan_pattern(&case.pattern, ExpressionContext::Load)?; + self.scan_pattern(&case.pattern)?; + if let Some(guard) = &case.guard { + self.scan_expression(guard, ExpressionContext::Load)?; + } self.scan_statements(&case.body)?; } } @@ -909,13 +906,14 @@ impl SymbolTableBuilder { name, value, type_params, - range, + .. }) => { - if !type_params.is_empty() { + if let Some(type_params) = type_params { self.enter_scope( - &name.to_string(), + // &name.to_string(), + "TypeAlias", SymbolTableType::TypeParams, - range.start.row.get(), + self.line_index_start(type_params.range), ); self.scan_type_params(type_params)?; self.scan_expression(value, ExpressionContext::Load)?; @@ -925,13 +923,25 @@ impl SymbolTableBuilder { } self.scan_expression(name, ExpressionContext::Store)?; } + Stmt::IpyEscapeCommand(_) => todo!(), + } + Ok(()) + } + + fn scan_decorators( + &mut self, + decorators: &[Decorator], + context: ExpressionContext, + ) -> SymbolTableResult { + for decorator in decorators { + self.scan_expression(&decorator.expression, context)?; } Ok(()) } fn scan_expressions( &mut self, - expressions: &[ast::located::Expr], + expressions: &[Expr], context: ExpressionContext, ) -> SymbolTableResult { for expression in expressions { @@ -942,10 +952,10 @@ impl SymbolTableBuilder { fn scan_expression( &mut self, - expression: &ast::located::Expr, + expression: &Expr, context: ExpressionContext, ) -> SymbolTableResult { - use ast::located::*; + use ruff_python_ast::*; match expression { Expr::BinOp(ExprBinOp { left, @@ -984,16 +994,12 @@ impl SymbolTableBuilder { }) => { self.scan_expression(value, ExpressionContext::Load)?; } - Expr::Dict(ExprDict { - keys, - values, - range: _, - }) => { - for (key, value) in keys.iter().zip(values.iter()) { - if let Some(key) = key { + Expr::Dict(ExprDict { items, range: _ }) => { + for item in items { + if let Some(key) = &item.key { self.scan_expression(key, context)?; } - self.scan_expression(value, context)?; + self.scan_expression(&item.value, context)?; } } Expr::Await(ExprAwait { value, range: _ }) => { @@ -1012,7 +1018,6 @@ impl SymbolTableBuilder { }) => { self.scan_expression(operand, context)?; } - Expr::Constant(ExprConstant { range: _, .. }) => {} Expr::Starred(ExprStarred { value, range: _, .. }) => { @@ -1039,26 +1044,27 @@ impl SymbolTableBuilder { self.scan_expression(step, context)?; } } - Expr::GeneratorExp(ExprGeneratorExp { + Expr::Generator(ExprGenerator { elt, generators, range, + .. }) => { - self.scan_comprehension("genexpr", elt, None, generators, range.start)?; + self.scan_comprehension("genexpr", elt, None, generators, *range)?; } Expr::ListComp(ExprListComp { elt, generators, range, }) => { - self.scan_comprehension("genexpr", elt, None, generators, range.start)?; + self.scan_comprehension("genexpr", elt, None, generators, *range)?; } Expr::SetComp(ExprSetComp { elt, generators, range, }) => { - self.scan_comprehension("genexpr", elt, None, generators, range.start)?; + self.scan_comprehension("genexpr", elt, None, generators, *range)?; } Expr::DictComp(ExprDictComp { key, @@ -1066,12 +1072,11 @@ impl SymbolTableBuilder { generators, range, }) => { - self.scan_comprehension("genexpr", key, Some(value), generators, range.start)?; + self.scan_comprehension("genexpr", key, Some(value), generators, *range)?; } Expr::Call(ExprCall { func, - args, - keywords, + arguments, range: _, }) => { match context { @@ -1083,43 +1088,27 @@ impl SymbolTableBuilder { } } - self.scan_expressions(args, ExpressionContext::Load)?; - for keyword in keywords { + self.scan_expressions(&arguments.args, ExpressionContext::Load)?; + for keyword in &arguments.keywords { self.scan_expression(&keyword.value, ExpressionContext::Load)?; } } - Expr::FormattedValue(ExprFormattedValue { - value, - format_spec, - range: _, - .. - }) => { - self.scan_expression(value, ExpressionContext::Load)?; - if let Some(spec) = format_spec { - self.scan_expression(spec, ExpressionContext::Load)?; - } - } - Expr::JoinedStr(ExprJoinedStr { values, range: _ }) => { - for value in values { - self.scan_expression(value, ExpressionContext::Load)?; - } - } Expr::Name(ExprName { id, range, .. }) => { let id = id.as_str(); // Determine the contextual usage of this symbol: match context { ExpressionContext::Delete => { - self.register_name(id, SymbolUsage::Assigned, range.start)?; - self.register_name(id, SymbolUsage::Used, range.start)?; + self.register_name(id, SymbolUsage::Assigned, *range)?; + self.register_name(id, SymbolUsage::Used, *range)?; } ExpressionContext::Load | ExpressionContext::IterDefinitionExp => { - self.register_name(id, SymbolUsage::Used, range.start)?; + self.register_name(id, SymbolUsage::Used, *range)?; } ExpressionContext::Store => { - self.register_name(id, SymbolUsage::Assigned, range.start)?; + self.register_name(id, SymbolUsage::Assigned, *range)?; } ExpressionContext::Iter => { - self.register_name(id, SymbolUsage::Iter, range.start)?; + self.register_name(id, SymbolUsage::Iter, *range)?; } } // Interesting stuff about the __class__ variable: @@ -1128,15 +1117,27 @@ impl SymbolTableBuilder { && self.tables.last().unwrap().typ == SymbolTableType::Function && id == "super" { - self.register_name("__class__", SymbolUsage::Used, range.start)?; + self.register_name("__class__", SymbolUsage::Used, *range)?; } } Expr::Lambda(ExprLambda { - args, body, + parameters, range: _, }) => { - self.enter_function("lambda", args, expression.location().row)?; + if let Some(parameters) = parameters { + self.enter_scope_with_parameters( + "lambda", + parameters, + self.line_index_start(expression.range()), + )?; + } else { + self.enter_scope( + "lambda", + SymbolTableType::Function, + self.line_index_start(expression.range()), + ); + } match context { ExpressionContext::IterDefinitionExp => { self.scan_expression(body, ExpressionContext::IterDefinitionExp)?; @@ -1147,7 +1148,25 @@ impl SymbolTableBuilder { } self.leave_scope(); } - Expr::IfExp(ExprIfExp { + Expr::FString(ExprFString { value, .. }) => { + for expr in value.elements().filter_map(|x| x.as_expression()) { + self.scan_expression(&expr.expression, ExpressionContext::Load)?; + if let Some(format_spec) = &expr.format_spec { + for element in format_spec.elements.expressions() { + self.scan_expression(&element.expression, ExpressionContext::Load)? + } + } + } + } + // Constants + Expr::StringLiteral(_) + | Expr::BytesLiteral(_) + | Expr::NumberLiteral(_) + | Expr::BooleanLiteral(_) + | Expr::NoneLiteral(_) + | Expr::EllipsisLiteral(_) => {} + Expr::IpyEscapeCommand(_) => todo!(), + Expr::If(ExprIf { test, body, orelse, @@ -1158,7 +1177,7 @@ impl SymbolTableBuilder { self.scan_expression(orelse, ExpressionContext::Load)?; } - Expr::NamedExpr(ExprNamedExpr { + Expr::Named(ExprNamed { target, value, range, @@ -1167,9 +1186,9 @@ impl SymbolTableBuilder { // comprehension iterator definitions if let ExpressionContext::IterDefinitionExp = context { return Err(SymbolTableError { - error: "assignment expression cannot be used in a comprehension iterable expression".to_string(), - location: Some(target.location()), - }); + error: "assignment expression cannot be used in a comprehension iterable expression".to_string(), + location: Some(self.source_code.source_location(target.range().start())), + }); } self.scan_expression(value, ExpressionContext::Load)?; @@ -1185,13 +1204,13 @@ impl SymbolTableBuilder { self.register_name( id, SymbolUsage::AssignedNamedExprInComprehension, - range.start, + *range, )?; } else { // omit one recursion. When the handling of an store changes for // Identifiers this needs adapted - more forward safe would be // calling scan_expression directly. - self.register_name(id, SymbolUsage::Assigned, range.start)?; + self.register_name(id, SymbolUsage::Assigned, *range)?; } } else { self.scan_expression(target, ExpressionContext::Store)?; @@ -1204,20 +1223,20 @@ impl SymbolTableBuilder { fn scan_comprehension( &mut self, scope_name: &str, - elt1: &ast::located::Expr, - elt2: Option<&ast::located::Expr>, - generators: &[ast::located::Comprehension], - location: SourceLocation, + elt1: &Expr, + elt2: Option<&Expr>, + generators: &[Comprehension], + range: TextRange, ) -> SymbolTableResult { // Comprehensions are compiled as functions, so create a scope for them: self.enter_scope( scope_name, SymbolTableType::Comprehension, - location.row.get(), + self.line_index_start(range), ); // Register the passed argument to the generator function as the name ".0" - self.register_name(".0", SymbolUsage::Parameter, location)?; + self.register_name(".0", SymbolUsage::Parameter, range)?; self.scan_expression(elt1, ExpressionContext::Load)?; if let Some(elt2) = elt2 { @@ -1247,91 +1266,159 @@ impl SymbolTableBuilder { Ok(()) } - fn scan_type_params(&mut self, type_params: &[ast::located::TypeParam]) -> SymbolTableResult { - for type_param in type_params { + fn scan_type_params(&mut self, type_params: &TypeParams) -> SymbolTableResult { + for type_param in &type_params.type_params { match type_param { - ast::located::TypeParam::TypeVar(ast::TypeParamTypeVar { + TypeParam::TypeVar(TypeParamTypeVar { name, bound, range: type_var_range, + .. }) => { - self.register_name(name.as_str(), SymbolUsage::Assigned, type_var_range.start)?; + self.register_name(name.as_str(), SymbolUsage::Assigned, *type_var_range)?; if let Some(binding) = bound { self.scan_expression(binding, ExpressionContext::Load)?; } } - ast::located::TypeParam::ParamSpec(ast::TypeParamParamSpec { + TypeParam::ParamSpec(TypeParamParamSpec { name, range: param_spec_range, + .. }) => { - self.register_name(name, SymbolUsage::Assigned, param_spec_range.start)?; + self.register_name(name, SymbolUsage::Assigned, *param_spec_range)?; } - ast::located::TypeParam::TypeVarTuple(ast::TypeParamTypeVarTuple { + TypeParam::TypeVarTuple(TypeParamTypeVarTuple { name, range: type_var_tuple_range, + .. }) => { - self.register_name(name, SymbolUsage::Assigned, type_var_tuple_range.start)?; + self.register_name(name, SymbolUsage::Assigned, *type_var_tuple_range)?; } } } Ok(()) } - fn enter_function( + fn scan_patterns(&mut self, patterns: &[Pattern]) -> SymbolTableResult { + for pattern in patterns { + self.scan_pattern(pattern)?; + } + Ok(()) + } + + fn scan_pattern(&mut self, pattern: &Pattern) -> SymbolTableResult { + use Pattern::*; + match pattern { + MatchValue(PatternMatchValue { value, .. }) => { + self.scan_expression(value, ExpressionContext::Load)? + } + MatchSingleton(_) => {} + MatchSequence(PatternMatchSequence { patterns, .. }) => self.scan_patterns(patterns)?, + MatchMapping(PatternMatchMapping { + keys, + patterns, + rest, + .. + }) => { + self.scan_expressions(keys, ExpressionContext::Load)?; + self.scan_patterns(patterns)?; + if let Some(rest) = rest { + self.register_ident(rest, SymbolUsage::Assigned)?; + } + } + MatchClass(PatternMatchClass { cls, arguments, .. }) => { + self.scan_expression(cls, ExpressionContext::Load)?; + self.scan_patterns(&arguments.patterns)?; + for kw in &arguments.keywords { + self.scan_pattern(&kw.pattern)?; + } + } + MatchStar(PatternMatchStar { name, .. }) => { + if let Some(name) = name { + self.register_ident(name, SymbolUsage::Assigned)?; + } + } + MatchAs(PatternMatchAs { pattern, name, .. }) => { + if let Some(pattern) = pattern { + self.scan_pattern(pattern)?; + } + if let Some(name) = name { + self.register_ident(name, SymbolUsage::Assigned)?; + } + } + MatchOr(PatternMatchOr { patterns, .. }) => self.scan_patterns(patterns)?, + } + Ok(()) + } + + fn enter_scope_with_parameters( &mut self, name: &str, - args: &ast::located::Arguments, - line_number: LineNumber, + parameters: &Parameters, + line_number: u32, ) -> SymbolTableResult { // Evaluate eventual default parameters: - for default in args + for default in parameters .posonlyargs .iter() - .chain(args.args.iter()) - .chain(args.kwonlyargs.iter()) + .chain(parameters.args.iter()) + .chain(parameters.kwonlyargs.iter()) .filter_map(|arg| arg.default.as_ref()) { self.scan_expression(default, ExpressionContext::Load)?; // not ExprContext? } // Annotations are scanned in outer scope: - for annotation in args + for annotation in parameters .posonlyargs .iter() - .chain(args.args.iter()) - .chain(args.kwonlyargs.iter()) - .filter_map(|arg| arg.def.annotation.as_ref()) + .chain(parameters.args.iter()) + .chain(parameters.kwonlyargs.iter()) + .filter_map(|arg| arg.parameter.annotation.as_ref()) { self.scan_annotation(annotation)?; } - if let Some(annotation) = args.vararg.as_ref().and_then(|arg| arg.annotation.as_ref()) { + if let Some(annotation) = parameters + .vararg + .as_ref() + .and_then(|arg| arg.annotation.as_ref()) + { self.scan_annotation(annotation)?; } - if let Some(annotation) = args.kwarg.as_ref().and_then(|arg| arg.annotation.as_ref()) { + if let Some(annotation) = parameters + .kwarg + .as_ref() + .and_then(|arg| arg.annotation.as_ref()) + { self.scan_annotation(annotation)?; } - self.enter_scope(name, SymbolTableType::Function, line_number.get()); + self.enter_scope(name, SymbolTableType::Function, line_number); // Fill scope with parameter names: - self.scan_parameters(&args.posonlyargs)?; - self.scan_parameters(&args.args)?; - self.scan_parameters(&args.kwonlyargs)?; - if let Some(name) = &args.vararg { + self.scan_parameters(¶meters.posonlyargs)?; + self.scan_parameters(¶meters.args)?; + self.scan_parameters(¶meters.kwonlyargs)?; + if let Some(name) = ¶meters.vararg { self.scan_parameter(name)?; } - if let Some(name) = &args.kwarg { + if let Some(name) = ¶meters.kwarg { self.scan_parameter(name)?; } Ok(()) } + fn register_ident(&mut self, ident: &Identifier, role: SymbolUsage) -> SymbolTableResult { + self.register_name(ident.as_str(), role, ident.range) + } + fn register_name( &mut self, name: &str, role: SymbolUsage, - location: SourceLocation, + range: TextRange, ) -> SymbolTableResult { + let location = self.source_code.source_location(range.start()); let location = Some(location); let scope_depth = self.tables.len(); let table = self.tables.last_mut().unwrap(); diff --git a/compiler/core/Cargo.toml b/compiler/core/Cargo.toml index 619ffcf61..7621c643d 100644 --- a/compiler/core/Cargo.toml +++ b/compiler/core/Cargo.toml @@ -9,7 +9,10 @@ repository.workspace = true license.workspace = true [dependencies] -rustpython-parser-core = { workspace = true, features=["location"] } +# rustpython-parser-core = { workspace = true, features=["location"] } +ruff_python_ast = { workspace = true } +ruff_python_parser = { workspace = true } +ruff_source_file = { workspace = true } bitflags = { workspace = true } itertools = { workspace = true } diff --git a/compiler/core/src/bytecode.rs b/compiler/core/src/bytecode.rs index 66284efdc..4cb80020e 100644 --- a/compiler/core/src/bytecode.rs +++ b/compiler/core/src/bytecode.rs @@ -5,11 +5,13 @@ use bitflags::bitflags; use itertools::Itertools; use malachite_bigint::BigInt; use num_complex::Complex64; -use rustpython_parser_core::source_code::{OneIndexed, SourceLocation}; +pub use ruff_python_ast::ConversionFlag; +// use rustpython_parser_core::source_code::{OneIndexed, SourceLocation}; +use ruff_source_file::{OneIndexed, SourceLocation}; use std::marker::PhantomData; use std::{collections::BTreeSet, fmt, hash, mem}; -pub use rustpython_parser_core::ConversionFlag; +// pub use rustpython_parser_core::ConversionFlag; pub trait Constant: Sized { type Name: AsRef; diff --git a/compiler/core/src/marshal.rs b/compiler/core/src/marshal.rs index cdc8b8e4e..1e47a6cac 100644 --- a/compiler/core/src/marshal.rs +++ b/compiler/core/src/marshal.rs @@ -1,7 +1,7 @@ use crate::bytecode::*; use malachite_bigint::{BigInt, Sign}; use num_complex::Complex64; -use rustpython_parser_core::source_code::{OneIndexed, SourceLocation}; +use ruff_source_file::{OneIndexed, SourceLocation}; use std::convert::Infallible; pub const FORMAT_VERSION: u32 = 4; @@ -185,8 +185,8 @@ pub fn deserialize_code( let locations = (0..len) .map(|_| { Ok(SourceLocation { - row: OneIndexed::new(rdr.read_u32()?).ok_or(MarshalError::InvalidLocation)?, - column: OneIndexed::from_zero_indexed(rdr.read_u32()?), + row: OneIndexed::new(rdr.read_u32()? as _).ok_or(MarshalError::InvalidLocation)?, + column: OneIndexed::from_zero_indexed(rdr.read_u32()? as _), }) }) .collect::>>()?; @@ -200,7 +200,7 @@ pub fn deserialize_code( let len = rdr.read_u32()?; let source_path = bag.make_name(rdr.read_str(len)?); - let first_line_number = OneIndexed::new(rdr.read_u32()?); + let first_line_number = OneIndexed::new(rdr.read_u32()? as _); let max_stackdepth = rdr.read_u32()?; let len = rdr.read_u32()?; @@ -589,8 +589,8 @@ pub fn serialize_code(buf: &mut W, code: &CodeObject) write_len(buf, code.locations.len()); for loc in &*code.locations { - buf.write_u32(loc.row.get()); - buf.write_u32(loc.column.to_zero_indexed()); + buf.write_u32(loc.row.get() as _); + buf.write_u32(loc.column.to_zero_indexed() as _); } buf.write_u16(code.flags.bits()); @@ -601,7 +601,7 @@ pub fn serialize_code(buf: &mut W, code: &CodeObject) write_vec(buf, code.source_path.as_ref().as_bytes()); - buf.write_u32(code.first_line_number.map_or(0, |x| x.get())); + buf.write_u32(code.first_line_number.map_or(0, |x| x.get() as _)); buf.write_u32(code.max_stackdepth); write_vec(buf, code.obj_name.as_ref().as_bytes()); diff --git a/compiler/core/src/mode.rs b/compiler/core/src/mode.rs index 6682540c0..13cea42b1 100644 --- a/compiler/core/src/mode.rs +++ b/compiler/core/src/mode.rs @@ -1,4 +1,4 @@ -pub use rustpython_parser_core::mode::ModeParseError; +pub use ruff_python_parser::ModeParseError; #[derive(Clone, Copy)] pub enum Mode { @@ -22,12 +22,14 @@ impl std::str::FromStr for Mode { } } -impl From for rustpython_parser_core::Mode { +impl From for ruff_python_parser::Mode { fn from(mode: Mode) -> Self { match mode { Mode::Exec => Self::Module, Mode::Eval => Self::Expression, - Mode::Single | Mode::BlockExpr => Self::Interactive, + // TODO: Improve ruff API + // ruff does not have an interactive mode + Mode::Single | Mode::BlockExpr => Self::Ipython, } } } diff --git a/compiler/source/Cargo.toml b/compiler/source/Cargo.toml new file mode 100644 index 000000000..373af47cf --- /dev/null +++ b/compiler/source/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "rustpython-compiler-source" +description = "RustPython Source and Index" +version.workspace = true +authors.workspace = true +edition.workspace = true +rust-version.workspace = true +repository.workspace = true +license.workspace = true + +[dependencies] +ruff_source_file = { workspace = true } +ruff_text_size = { workspace = true } + +[lints] +workspace = true \ No newline at end of file diff --git a/compiler/source/src/lib.rs b/compiler/source/src/lib.rs new file mode 100644 index 000000000..2d967e218 --- /dev/null +++ b/compiler/source/src/lib.rs @@ -0,0 +1,42 @@ +pub use ruff_source_file::{LineIndex, OneIndexed as LineNumber, SourceLocation}; +use ruff_text_size::TextRange; +pub use ruff_text_size::TextSize; + +#[derive(Clone)] +pub struct SourceCode<'src> { + pub path: &'src str, + pub text: &'src str, + pub index: LineIndex, +} + +impl<'src> SourceCode<'src> { + pub fn new(path: &'src str, text: &'src str) -> Self { + let index = LineIndex::from_source_text(text); + Self { path, text, index } + } + + pub fn line_index(&self, offset: TextSize) -> LineNumber { + self.index.line_index(offset) + } + + pub fn source_location(&self, offset: TextSize) -> SourceLocation { + self.index.source_location(offset, self.text) + } + + pub fn get_range(&'src self, range: TextRange) -> &'src str { + &self.text[range.start().to_usize()..range.end().to_usize()] + } +} + +pub struct SourceCodeOwned { + pub path: String, + pub text: String, + pub index: LineIndex, +} + +impl SourceCodeOwned { + pub fn new(path: String, text: String) -> Self { + let index = LineIndex::from_source_text(&text); + Self { path, text, index } + } +} diff --git a/compiler/src/lib.rs b/compiler/src/lib.rs index 659dc9974..9c64de261 100644 --- a/compiler/src/lib.rs +++ b/compiler/src/lib.rs @@ -1,69 +1,128 @@ +use ruff_source_file::SourceLocation; use rustpython_codegen::{compile, symboltable}; -use rustpython_parser::ast::{self as ast, ConstantOptimizer, fold::Fold}; pub use rustpython_codegen::compile::CompileOpts; pub use rustpython_compiler_core::{Mode, bytecode::CodeObject}; -pub use rustpython_parser::{Parse, source_code::LinearLocator}; +use rustpython_compiler_source::SourceCode; // these modules are out of repository. re-exporting them here for convenience. +pub use ruff_python_ast as ast; +pub use ruff_python_parser as parser; pub use rustpython_codegen as codegen; pub use rustpython_compiler_core as core; -pub use rustpython_parser as parser; +pub use rustpython_compiler_source as source; +use thiserror::Error; -#[derive(Debug)] +#[derive(Error, Debug)] pub enum CompileErrorType { - Codegen(rustpython_codegen::error::CodegenErrorType), - Parse(parser::ParseErrorType), + #[error(transparent)] + Codegen(#[from] codegen::error::CodegenErrorType), + #[error(transparent)] + Parse(#[from] parser::ParseErrorType), } -impl std::error::Error for CompileErrorType { - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - match self { - CompileErrorType::Codegen(e) => e.source(), - CompileErrorType::Parse(e) => e.source(), - } - } +#[derive(Error, Debug)] +pub struct ParseError { + #[source] + pub error: parser::ParseErrorType, + pub location: SourceLocation, + pub source_path: String, } -impl std::fmt::Display for CompileErrorType { + +impl std::fmt::Display for ParseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - CompileErrorType::Codegen(e) => e.fmt(f), - CompileErrorType::Parse(e) => e.fmt(f), - } - } -} -impl From for CompileErrorType { - fn from(source: rustpython_codegen::error::CodegenErrorType) -> Self { - CompileErrorType::Codegen(source) - } -} -impl From for CompileErrorType { - fn from(source: parser::ParseErrorType) -> Self { - CompileErrorType::Parse(source) + self.error.fmt(f) } } -pub type CompileError = rustpython_parser::source_code::LocatedError; +#[derive(Error, Debug)] +pub enum CompileError { + #[error(transparent)] + Codegen(#[from] codegen::error::CodegenError), + #[error(transparent)] + Parse(#[from] ParseError), +} + +impl CompileError { + pub fn from_ruff_parse_error(error: parser::ParseError, source_code: &SourceCode<'_>) -> Self { + let location = source_code.source_location(error.location.start()); + Self::Parse(ParseError { + error: error.error, + location, + source_path: source_code.path.to_owned(), + }) + } + + pub fn location(&self) -> Option { + match self { + CompileError::Codegen(codegen_error) => codegen_error.location.clone(), + CompileError::Parse(parse_error) => Some(parse_error.location.clone()), + } + } + + pub fn python_location(&self) -> (usize, usize) { + match self { + CompileError::Codegen(codegen_error) => { + if let Some(location) = &codegen_error.location { + (location.row.get(), location.column.get()) + } else { + (0, 0) + } + } + CompileError::Parse(parse_error) => ( + parse_error.location.row.get(), + parse_error.location.column.get(), + ), + } + } + + pub fn source_path(&self) -> &str { + match self { + CompileError::Codegen(codegen_error) => &codegen_error.source_path, + CompileError::Parse(parse_error) => &parse_error.source_path, + } + } +} /// Compile a given source code into a bytecode object. pub fn compile( source: &str, mode: Mode, - source_path: String, + source_path: &str, opts: CompileOpts, ) -> Result { - let mut locator = LinearLocator::new(source); - let mut ast = match parser::parse(source, mode.into(), &source_path) { - Ok(x) => x, - Err(e) => return Err(locator.locate_error(e)), - }; - if opts.optimize > 0 { - ast = ConstantOptimizer::new() - .fold_mod(ast) - .unwrap_or_else(|e| match e {}); - } - let ast = locator.fold_mod(ast).unwrap_or_else(|e| match e {}); - compile::compile_top(&ast, source_path, mode, opts).map_err(|e| e.into()) + // TODO: do this less hackily; ruff's parser should translate a CRLF line + // break in a multiline string into just an LF in the parsed value + #[cfg(windows)] + let source = &source.replace("\r\n", "\n"); + let source_code = SourceCode::new(source_path, source); + _compile(source_code, mode, opts) + // let index = LineIndex::from_source_text(source); + // let source_code = SourceCode::new(source, &index); + // let mut locator = LinearLocator::new(source); + // let mut ast = match parser::parse(source, mode.into(), &source_path) { + // Ok(x) => x, + // Err(e) => return Err(locator.locate_error(e)), + // }; + + // TODO: + // if opts.optimize > 0 { + // ast = ConstantOptimizer::new() + // .fold_mod(ast) + // .unwrap_or_else(|e| match e {}); + // } + // let ast = locator.fold_mod(ast).unwrap_or_else(|e| match e {}); +} + +fn _compile( + source_code: SourceCode<'_>, + mode: Mode, + opts: CompileOpts, +) -> Result { + let parsed = parser::parse(source_code.text, mode.into()) + .map_err(|err| CompileError::from_ruff_parse_error(err, &source_code))?; + let ast = parsed.into_syntax(); + compile::compile_top(ast, source_code, mode, opts).map_err(|e| e.into()) } pub fn compile_symtable( @@ -71,20 +130,170 @@ pub fn compile_symtable( mode: Mode, source_path: &str, ) -> Result { - let mut locator = LinearLocator::new(source); + let source_code = SourceCode::new(source_path, source); + _compile_symtable(source_code, mode) +} + +pub fn _compile_symtable( + source_code: SourceCode<'_>, + mode: Mode, +) -> Result { let res = match mode { Mode::Exec | Mode::Single | Mode::BlockExpr => { - let ast = - ast::Suite::parse(source, source_path).map_err(|e| locator.locate_error(e))?; - let ast = locator.fold(ast).unwrap(); - symboltable::SymbolTable::scan_program(&ast) + let ast = ruff_python_parser::parse_module(source_code.text) + .map_err(|e| CompileError::from_ruff_parse_error(e, &source_code))?; + symboltable::SymbolTable::scan_program(&ast.into_syntax(), source_code.clone()) } Mode::Eval => { - let expr = - ast::Expr::parse(source, source_path).map_err(|e| locator.locate_error(e))?; - let expr = locator.fold(expr).unwrap(); - symboltable::SymbolTable::scan_expr(&expr) + let ast = + ruff_python_parser::parse(source_code.text, ruff_python_parser::Mode::Expression) + .map_err(|e| CompileError::from_ruff_parse_error(e, &source_code))?; + symboltable::SymbolTable::scan_expr( + &ast.into_syntax().expect_expression(), + source_code.clone(), + ) } }; - res.map_err(|e| e.into_codegen_error(source_path.to_owned()).into()) + res.map_err(|e| e.into_codegen_error(source_code.path.to_owned()).into()) +} + +#[test] +fn test_compile() { + let code = "x = 'abc'"; + let compiled = compile(&code, Mode::Single, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_compile_phello() { + let code = r#" +initialized = True +def main(): + print("Hello world!") +if __name__ == '__main__': + main() +"#; + let compiled = compile(&code, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_compile_if_elif_else() { + let code = r#" +if False: + pass +elif False: + pass +elif False: + pass +else: + pass +"#; + let compiled = compile(&code, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_compile_lambda() { + let code = r#" +lambda: 'a' +"#; + let compiled = compile(&code, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_compile_lambda2() { + let code = r#" +(lambda x: f'hello, {x}')('world}') +"#; + let compiled = compile(&code, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_compile_lambda3() { + let code = r#" +def g(): + pass +def f(): + if False: + return lambda x: g(x) + elif False: + return g + else: + return g +"#; + let compiled = compile(&code, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_compile_int() { + let code = r#" +a = 0xFF +"#; + let compiled = compile(&code, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_compile_bigint() { + let code = r#" +a = 0xFFFFFFFFFFFFFFFFFFFFFFFF +"#; + let compiled = compile(&code, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_compile_fstring() { + let code1 = r#" +assert f"1" == '1' + "#; + let compiled = compile(&code1, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); + + let code2 = r#" +assert f"{1}" == '1' + "#; + let compiled = compile(&code2, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); + let code3 = r#" +assert f"{1+1}" == '2' + "#; + let compiled = compile(&code3, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); + + let code4 = r#" +assert f"{{{(lambda: f'{1}')}" == '{1' + "#; + let compiled = compile(&code4, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); + + let code5 = r#" +assert f"a{1}" == 'a1' + "#; + let compiled = compile(&code5, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); + + let code6 = r#" +assert f"{{{(lambda x: f'hello, {x}')('world}')}" == '{hello, world}' + "#; + let compiled = compile(&code6, Mode::Exec, "<>", CompileOpts::default()); + dbg!(compiled.expect("compile error")); +} + +#[test] +fn test_simple_enum() { + let code = r#" +import enum +@enum._simple_enum(enum.IntFlag, boundary=enum.KEEP) +class RegexFlag: + NOFLAG = 0 + DEBUG = 1 +print(RegexFlag.NOFLAG & RegexFlag.DEBUG) +"#; + let compiled = compile(&code, Mode::Exec, "", CompileOpts::default()); + dbg!(compiled.expect("compile error")); } diff --git a/derive-impl/Cargo.toml b/derive-impl/Cargo.toml index debe58106..ca415dc54 100644 --- a/derive-impl/Cargo.toml +++ b/derive-impl/Cargo.toml @@ -10,7 +10,7 @@ license.workspace = true [dependencies] rustpython-compiler-core = { workspace = true } -rustpython-parser-core = { workspace = true } +# rustpython-parser-core = { workspace = true } rustpython-doc = { workspace = true } itertools = { workspace = true } diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 97ca026e7..a9a3123a5 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -246,7 +246,7 @@ impl derive_impl::Compiler for Compiler { module_name: String, ) -> Result> { use rustpython_compiler::{CompileOpts, compile}; - Ok(compile(source, mode, module_name, CompileOpts::default())?) + Ok(compile(source, mode, &module_name, CompileOpts::default())?) } } diff --git a/examples/dis.rs b/examples/dis.rs index ee424f7b3..5b8826fdf 100644 --- a/examples/dis.rs +++ b/examples/dis.rs @@ -79,7 +79,7 @@ fn display_script( expand_code_objects: bool, ) -> Result<(), Box> { let source = fs::read_to_string(path)?; - let code = compiler::compile(&source, mode, path.to_string_lossy().into_owned(), opts)?; + let code = compiler::compile(&source, mode, &path.to_string_lossy(), opts)?; println!("{}:", path.display()); if expand_code_objects { println!("{}", code.display_expand_code_objects()); diff --git a/examples/parse_folder.rs b/examples/parse_folder.rs index 97a1eaf03..acad76ad7 100644 --- a/examples/parse_folder.rs +++ b/examples/parse_folder.rs @@ -8,7 +8,8 @@ extern crate env_logger; #[macro_use] extern crate log; -use rustpython_parser::{Parse, ast}; +use ruff_python_parser::parse_module; +use rustpython_compiler::ast; use std::{ path::{Path, PathBuf}, time::{Duration, Instant}, @@ -68,18 +69,19 @@ fn parse_python_file(filename: &Path) -> ParsedFile { info!("Parsing file {:?}", filename); match std::fs::read_to_string(filename) { Err(e) => ParsedFile { - // filename: Box::new(filename.to_path_buf()), - // code: "".to_owned(), + filename: Box::new(filename.to_path_buf()), + code: "".to_owned(), num_lines: 0, result: Err(e.to_string()), }, Ok(source) => { let num_lines = source.lines().count(); - let result = - ast::Suite::parse(&source, &filename.to_string_lossy()).map_err(|e| e.to_string()); + let result = parse_module(&source) + .map(|x| x.into_suite()) + .map_err(|e| e.to_string()); ParsedFile { - // filename: Box::new(filename.to_path_buf()), - // code: source.to_string(), + filename: Box::new(filename.to_path_buf()), + code: source.to_string(), num_lines, result, } @@ -132,8 +134,8 @@ struct ScanResult { } struct ParsedFile { - // filename: Box, - // code: String, + filename: Box, + code: String, num_lines: usize, result: ParseResult, } diff --git a/src/shell.rs b/src/shell.rs index 00b671006..f920b4d01 100644 --- a/src/shell.rs +++ b/src/shell.rs @@ -1,10 +1,12 @@ mod helper; -use rustpython_parser::{ParseErrorType, Tok, lexer::LexicalErrorType}; +use rustpython_compiler::{ + CompileError, ParseError, parser::ParseErrorType, parser::lexer::LexicalErrorType, +}; use rustpython_vm::{ AsObject, PyResult, VirtualMachine, builtins::PyBaseExceptionRef, - compiler::{self, CompileError, CompileErrorType}, + compiler::{self}, readline::{Readline, ReadlineResult}, scope::Scope, }; @@ -35,29 +37,25 @@ fn shell_exec( ShellExecResult::Ok } } - Err(CompileError { - error: CompileErrorType::Parse(ParseErrorType::Lexical(LexicalErrorType::Eof)), + Err(CompileError::Parse(ParseError { + error: ParseErrorType::Lexical(LexicalErrorType::Eof), .. - }) - | Err(CompileError { - error: CompileErrorType::Parse(ParseErrorType::Eof), - .. - }) => ShellExecResult::Continue, + })) => ShellExecResult::Continue, Err(err) => { // bad_error == true if we are handling an error that should be thrown even if we are continuing // if its an indentation error, set to true if we are continuing and the error is on column 0, // since indentations errors on columns other than 0 should be ignored. // if its an unrecognized token for dedent, set to false - let bad_error = match err.error { - CompileErrorType::Parse(ref p) => { + let bad_error = match err { + CompileError::Parse(ref p) => { if matches!( - p, + p.error, ParseErrorType::Lexical(LexicalErrorType::IndentationError) ) { - continuing && err.location.is_some() + continuing // && p.location.is_some() } else { - !matches!(p, ParseErrorType::UnrecognizedToken(Tok::Dedent, _)) + true // !matches!(p, ParseErrorType::UnrecognizedToken(Tok::Dedent, _)) } } _ => true, // It is a bad error for everything else diff --git a/stdlib/src/faulthandler.rs b/stdlib/src/faulthandler.rs index 9ffd93129..e3cd43473 100644 --- a/stdlib/src/faulthandler.rs +++ b/stdlib/src/faulthandler.rs @@ -10,7 +10,7 @@ mod decl { stderr, " File \"{}\", line {} in {}", frame.code.source_path, - frame.current_location().row.to_usize(), + frame.current_location().row, frame.code.obj_name ) } diff --git a/vm/Cargo.toml b/vm/Cargo.toml index a0e357baa..49b0883bb 100644 --- a/vm/Cargo.toml +++ b/vm/Cargo.toml @@ -19,9 +19,9 @@ freeze-stdlib = ["encodings"] jit = ["rustpython-jit"] threading = ["rustpython-common/threading"] compiler = ["parser", "codegen", "rustpython-compiler"] -ast = ["rustpython-ast"] +ast = ["ruff_python_ast", "ruff_text_size", "ruff_source_file"] codegen = ["rustpython-codegen", "ast"] -parser = ["rustpython-parser", "ast"] +parser = ["ast"] serde = ["dep:serde"] wasmbind = ["chrono/wasmbind", "getrandom/wasm_js", "wasm-bindgen"] @@ -32,10 +32,15 @@ rustpython-common = { workspace = true } rustpython-derive = { workspace = true } rustpython-jit = { workspace = true, optional = true } -rustpython-ast = { workspace = true, optional = true } -rustpython-parser = { workspace = true, optional = true } +ruff_python_ast = { workspace = true, optional = true } +ruff_python_parser = { workspace = true } +ruff_text_size = { workspace = true, optional = true } +ruff_source_file = { workspace = true, optional = true } +# rustpython-ast = { workspace = true, optional = true } +# rustpython-parser = { workspace = true, optional = true } rustpython-compiler-core = { workspace = true } -rustpython-parser-core = { workspace = true } +rustpython-compiler-source = { workspace = true } +# rustpython-parser-core = { workspace = true } rustpython-literal = { workspace = true } rustpython-format = { workspace = true } rustpython-sre_engine = { workspace = true } @@ -87,9 +92,9 @@ unicode_names2 = { workspace = true } # https://github.com/RustPython/RustPython/pull/832#discussion_r275428939 unicode-casing = "0.1.0" # update version all at the same time -unic-ucd-bidi = "0.9.0" -unic-ucd-category = "0.9.0" -unic-ucd-ident = "0.9.0" +unic-ucd-bidi = "0.9.0" +unic-ucd-category = "0.9.0" +unic-ucd-ident = "0.9.0" [target.'cfg(unix)'.dependencies] rustix = { workspace = true } diff --git a/vm/src/builtins/code.rs b/vm/src/builtins/code.rs index 3fa332b2f..ba2d2dd5c 100644 --- a/vm/src/builtins/code.rs +++ b/vm/src/builtins/code.rs @@ -11,7 +11,7 @@ use crate::{ convert::ToPyObject, frozen, function::{FuncArgs, OptionalArg}, - source_code::OneIndexed, + source::LineNumber, types::Representable, }; use malachite_bigint::BigInt; @@ -279,7 +279,7 @@ impl PyCode { #[pygetset] fn co_firstlineno(&self) -> u32 { - self.code.first_line_number.map_or(0, |n| n.get()) + self.code.first_line_number.map_or(0, |n| n.get() as _) } #[pygetset] @@ -351,7 +351,7 @@ impl PyCode { }; let first_line_number = match args.co_firstlineno { - OptionalArg::Present(first_line_number) => OneIndexed::new(first_line_number), + OptionalArg::Present(first_line_number) => LineNumber::new(first_line_number as _), OptionalArg::Missing => self.code.first_line_number, }; diff --git a/vm/src/builtins/frame.rs b/vm/src/builtins/frame.rs index 1fd031984..1b7385019 100644 --- a/vm/src/builtins/frame.rs +++ b/vm/src/builtins/frame.rs @@ -60,7 +60,7 @@ impl Frame { #[pygetset] pub fn f_lineno(&self) -> usize { - self.current_location().row.to_usize() + self.current_location().row.get() } #[pygetset] diff --git a/vm/src/builtins/traceback.rs b/vm/src/builtins/traceback.rs index b0abbd006..6d88821ae 100644 --- a/vm/src/builtins/traceback.rs +++ b/vm/src/builtins/traceback.rs @@ -2,7 +2,7 @@ use rustpython_common::lock::PyMutex; use super::PyType; use crate::{ - Context, Py, PyPayload, PyRef, class::PyClassImpl, frame::FrameRef, source_code::LineNumber, + Context, Py, PyPayload, PyRef, class::PyClassImpl, frame::FrameRef, source::LineNumber, }; #[pyclass(module = false, name = "traceback", traverse)] @@ -47,7 +47,7 @@ impl PyTraceback { #[pygetset] fn tb_lineno(&self) -> usize { - self.lineno.to_usize() + self.lineno.get() } #[pygetset] diff --git a/vm/src/compiler.rs b/vm/src/compiler.rs index c81475b6d..b819fd9a4 100644 --- a/vm/src/compiler.rs +++ b/vm/src/compiler.rs @@ -1,37 +1,49 @@ -#[cfg(feature = "rustpython-codegen")] +#[cfg(feature = "codegen")] pub use rustpython_codegen::CompileOpts; -#[cfg(feature = "rustpython-compiler")] +#[cfg(feature = "compiler")] pub use rustpython_compiler::*; -#[cfg(not(feature = "rustpython-compiler"))] + +#[cfg(not(feature = "compiler"))] +pub use rustpython_compiler_source as source; + +#[cfg(not(feature = "compiler"))] pub use rustpython_compiler_core::Mode; -#[cfg(not(feature = "rustpython-compiler"))] +#[cfg(not(feature = "compiler"))] pub use rustpython_compiler_core as core; -#[cfg(not(feature = "rustpython-compiler"))] -pub use rustpython_parser_core as parser; +#[cfg(not(feature = "compiler"))] +pub use ruff_python_parser as parser; -#[cfg(not(feature = "rustpython-compiler"))] +#[cfg(not(feature = "compiler"))] mod error { - #[cfg(all(feature = "rustpython-parser", feature = "rustpython-codegen"))] + #[cfg(all(feature = "parser", feature = "codegen"))] panic!("Use --features=compiler to enable both parser and codegen"); #[derive(Debug, thiserror::Error)] pub enum CompileErrorType { - #[cfg(feature = "rustpython-codegen")] + #[cfg(feature = "codegen")] #[error(transparent)] - Codegen(#[from] rustpython_codegen::error::CodegenErrorType), - #[cfg(feature = "rustpython-parser")] + Codegen(#[from] super::codegen::error::CodegenErrorType), + #[cfg(feature = "parser")] #[error(transparent)] - Parse(#[from] rustpython_parser::error::ParseErrorType), + Parse(#[from] super::parser::ParseErrorType), } - pub type CompileError = rustpython_parser_core::source_code::LocatedError; + #[derive(Debug, thiserror::Error)] + pub enum CompileError { + #[cfg(feature = "codegen")] + #[error(transparent)] + Codegen(#[from] super::codegen::error::CodegenError), + #[cfg(feature = "parser")] + #[error(transparent)] + Parse(#[from] super::parser::ParseError), + } } -#[cfg(not(feature = "rustpython-compiler"))] +#[cfg(not(feature = "compiler"))] pub use error::{CompileError, CompileErrorType}; -#[cfg(any(feature = "rustpython-parser", feature = "rustpython-codegen"))] +#[cfg(any(feature = "parser", feature = "codegen"))] impl crate::convert::ToPyException for (CompileError, Option<&str>) { fn to_pyexception(&self, vm: &crate::VirtualMachine) -> crate::builtins::PyBaseExceptionRef { vm.new_syntax_error(&self.0, self.1) diff --git a/vm/src/exceptions.rs b/vm/src/exceptions.rs index d2f410b30..9bf737279 100644 --- a/vm/src/exceptions.rs +++ b/vm/src/exceptions.rs @@ -378,7 +378,7 @@ fn write_traceback_entry( tb_entry.lineno, tb_entry.frame.code.obj_name )?; - print_source_line(output, filename, tb_entry.lineno.to_usize())?; + print_source_line(output, filename, tb_entry.lineno.get())?; Ok(()) } diff --git a/vm/src/frame.rs b/vm/src/frame.rs index ec5dad10a..cf695cd87 100644 --- a/vm/src/frame.rs +++ b/vm/src/frame.rs @@ -15,7 +15,7 @@ use crate::{ function::{ArgMapping, Either, FuncArgs}, protocol::{PyIter, PyIterReturn}, scope::Scope, - source_code::SourceLocation, + source::SourceLocation, stdlib::{builtins, typing::_typing}, vm::{Context, PyMethod}, }; @@ -166,7 +166,7 @@ impl Frame { } pub fn current_location(&self) -> SourceLocation { - self.code.locations[self.lasti() as usize - 1] + self.code.locations[self.lasti() as usize - 1].clone() } pub fn lasti(&self) -> u32 { @@ -380,7 +380,7 @@ impl ExecutingFrame<'_> { // 2. Add new entry with current execution position (filename, lineno, code_object) to traceback. // 3. Unwind block stack till appropriate handler is found. - let loc = frame.code.locations[idx]; + let loc = frame.code.locations[idx].clone(); let next = exception.traceback(); let new_traceback = PyTraceback::new(next, frame.object.to_owned(), frame.lasti(), loc.row); diff --git a/vm/src/lib.rs b/vm/src/lib.rs index 93adaa13f..2e4afa3ea 100644 --- a/vm/src/lib.rs +++ b/vm/src/lib.rs @@ -84,7 +84,7 @@ pub mod warn; #[cfg(windows)] pub mod windows; -pub use self::compiler::parser::source_code; +pub use self::compiler::source; pub use self::convert::{TryFromBorrowedObject, TryFromObject}; pub use self::object::{ AsObject, Py, PyAtomicRef, PyExact, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, diff --git a/vm/src/stdlib/ast.rs b/vm/src/stdlib/ast.rs index 7dd893646..b5445c65f 100644 --- a/vm/src/stdlib/ast.rs +++ b/vm/src/stdlib/ast.rs @@ -3,81 +3,55 @@ //! This module makes use of the parser logic, and translates all ast nodes //! into python ast.AST objects. -mod r#gen; +mod pyast; +use crate::builtins::{PyInt, PyStr}; +use crate::stdlib::ast::module::{Mod, ModInteractive}; +use crate::stdlib::ast::node::BoxedSlice; +use crate::stdlib::ast::python::_ast; use crate::{ - AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject, - VirtualMachine, - builtins::{self, PyDict, PyModule, PyStrRef, PyType}, + AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyRefExact, PyResult, + TryFromObject, VirtualMachine, + builtins::PyIntRef, + builtins::{PyDict, PyModule, PyStrRef, PyType}, class::{PyClassImpl, StaticType}, - compiler::CompileError, compiler::core::bytecode::OpArgType, - convert::ToPyException, - source_code::{LinearLocator, OneIndexed, SourceLocation, SourceRange}, + compiler::{CompileError, ParseError}, + convert::ToPyObject, + source::SourceCode, + source::SourceLocation, }; -use num_complex::Complex64; -use num_traits::{ToPrimitive, Zero}; -use rustpython_ast::{self as ast, fold::Fold}; -#[cfg(feature = "rustpython-codegen")] +use node::Node; +use ruff_python_ast as ruff; +use ruff_source_file::OneIndexed; +use ruff_text_size::{Ranged, TextRange, TextSize}; +use rustpython_compiler_source::SourceCodeOwned; + +#[cfg(feature = "parser")] +use ruff_python_parser as parser; +#[cfg(feature = "codegen")] use rustpython_codegen as codegen; -#[cfg(feature = "rustpython-parser")] -use rustpython_parser as parser; -#[pymodule] -mod _ast { - use crate::{ - AsObject, Context, PyObjectRef, PyPayload, PyResult, VirtualMachine, - builtins::{PyStrRef, PyTupleRef}, - function::FuncArgs, - }; - #[pyattr] - #[pyclass(module = "_ast", name = "AST")] - #[derive(Debug, PyPayload)] - pub(crate) struct NodeAst; +pub(crate) use python::_ast::NodeAst; - #[pyclass(flags(BASETYPE, HAS_DICT))] - impl NodeAst { - #[pyslot] - #[pymethod(magic)] - fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { - let fields = zelf.get_attr("_fields", vm)?; - let fields: Vec = fields.try_to_value(vm)?; - let numargs = args.args.len(); - if numargs > fields.len() { - return Err(vm.new_type_error(format!( - "{} constructor takes at most {} positional argument{}", - zelf.class().name(), - fields.len(), - if fields.len() == 1 { "" } else { "s" }, - ))); - } - for (name, arg) in fields.iter().zip(args.args) { - zelf.set_attr(name, arg, vm)?; - } - for (key, value) in args.kwargs { - if let Some(pos) = fields.iter().position(|f| f.as_str() == key) { - if pos < numargs { - return Err(vm.new_type_error(format!( - "{} got multiple values for argument '{}'", - zelf.class().name(), - key - ))); - } - } - zelf.set_attr(vm.ctx.intern_str(key), value, vm)?; - } - Ok(()) - } +mod python; - #[pyattr(name = "_fields")] - fn fields(ctx: &Context) -> PyTupleRef { - ctx.empty_tuple.clone() - } - } - - #[pyattr(name = "PyCF_ONLY_AST")] - use super::PY_COMPILE_FLAG_AST_ONLY; -} +mod argument; +mod basic; +mod constant; +mod elif_else_clause; +mod exception; +mod expression; +mod module; +mod node; +mod operator; +mod other; +mod parameter; +mod pattern; +mod statement; +mod string; +mod type_ignore; +mod type_parameters; fn get_node_field(vm: &VirtualMachine, obj: &PyObject, field: &'static str, typ: &str) -> PyResult { vm.get_attribute_opt(obj.to_owned(), field)? @@ -94,248 +68,197 @@ fn get_node_field_opt( .filter(|obj| !vm.is_none(obj))) } -trait Node: Sized { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef; - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult; +fn get_int_field( + vm: &VirtualMachine, + obj: &PyObject, + field: &'static str, + typ: &str, +) -> PyResult> { + get_node_field(vm, obj, field, typ)? + .downcast_exact(vm) + .map_err(|_| vm.new_type_error(format!("field \"{field}\" must have integer type"))) } -impl Node for Vec { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - vm.ctx - .new_list( - self.into_iter() - .map(|node| node.ast_to_object(vm)) - .collect(), - ) - .into() - } - - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - vm.extract_elements_with(&object, |obj| Node::ast_from_object(vm, obj)) - } +struct PySourceRange { + start: PySourceLocation, + end: PySourceLocation, } -impl Node for Box { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - (*self).ast_to_object(vm) - } - - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - T::ast_from_object(vm, object).map(Box::new) - } +pub struct PySourceLocation { + row: Row, + column: Column, } -impl Node for Option { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - Some(node) => node.ast_to_object(vm), - None => vm.ctx.none(), +impl PySourceLocation { + fn to_source_location(&self) -> SourceLocation { + SourceLocation { + row: self.row.get_one_indexed(), + column: self.column.get_one_indexed(), } } +} - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - if vm.is_none(&object) { - Ok(None) - } else { - Ok(Some(T::ast_from_object(vm, object)?)) - } +/// A one-based index into the lines. +#[derive(Clone, Copy)] +struct Row(OneIndexed); + +impl Row { + fn get(self) -> usize { + self.0.get() + } + + fn get_one_indexed(self) -> OneIndexed { + self.0 + } +} + +/// An UTF-8 index into the line. +#[derive(Clone, Copy)] +struct Column(TextSize); + +impl Column { + fn get(self) -> usize { + self.0.to_usize() + } + + fn get_one_indexed(self) -> OneIndexed { + OneIndexed::from_zero_indexed(self.get()) + } +} + +fn text_range_to_source_range( + source_code: &SourceCodeOwned, + text_range: TextRange, +) -> PySourceRange { + let index = &source_code.index; + let source = &source_code.text; + + if source.is_empty() { + return PySourceRange { + start: PySourceLocation { + row: Row(OneIndexed::from_zero_indexed(0)), + column: Column(TextSize::new(0)), + }, + end: PySourceLocation { + row: Row(OneIndexed::from_zero_indexed(0)), + column: Column(TextSize::new(0)), + }, + }; + } + + let start_row = index.line_index(text_range.start()); + let end_row = index.line_index(text_range.end()); + let start_col = text_range.start() - index.line_start(start_row, source); + let end_col = text_range.end() - index.line_start(end_row, source); + + PySourceRange { + start: PySourceLocation { + row: Row(start_row), + column: Column(start_col), + }, + end: PySourceLocation { + row: Row(end_row), + column: Column(end_col), + }, } } fn range_from_object( vm: &VirtualMachine, + source_code: &SourceCodeOwned, object: PyObjectRef, name: &str, -) -> PyResult { - fn make_location(row: u32, column: u32) -> Option { - Some(SourceLocation { - row: OneIndexed::new(row)?, - column: OneIndexed::from_zero_indexed(column), - }) - } - let row = ast::Int::ast_from_object(vm, get_node_field(vm, &object, "lineno", name)?)?; - let column = ast::Int::ast_from_object(vm, get_node_field(vm, &object, "col_offset", name)?)?; - let location = make_location(row.to_u32(), column.to_u32()); - let end_row = get_node_field_opt(vm, &object, "end_lineno")? - .map(|obj| ast::Int::ast_from_object(vm, obj)) - .transpose()?; - let end_column = get_node_field_opt(vm, &object, "end_col_offset")? - .map(|obj| ast::Int::ast_from_object(vm, obj)) - .transpose()?; - let end_location = if let (Some(row), Some(column)) = (end_row, end_column) { - make_location(row.to_u32(), column.to_u32()) - } else { - None +) -> PyResult { + let start_row = get_int_field(vm, &object, "lineno", name)?; + let start_column = get_int_field(vm, &object, "col_offset", name)?; + let end_row = get_int_field(vm, &object, "end_lineno", name)?; + let end_column = get_int_field(vm, &object, "end_col_offset", name)?; + + let location = PySourceRange { + start: PySourceLocation { + row: Row(OneIndexed::new(start_row.try_to_primitive(vm)?).unwrap()), + column: Column(TextSize::new(start_column.try_to_primitive(vm)?)), + }, + end: PySourceLocation { + row: Row(OneIndexed::new(end_row.try_to_primitive(vm)?).unwrap()), + column: Column(TextSize::new(end_column.try_to_primitive(vm)?)), + }, }; - let range = SourceRange { - start: location.unwrap_or_default(), - end: end_location, - }; - Ok(range) + + Ok(source_range_to_text_range(source_code, location)) } -fn node_add_location(dict: &Py, range: SourceRange, vm: &VirtualMachine) { +fn source_range_to_text_range(source_code: &SourceCodeOwned, location: PySourceRange) -> TextRange { + let source = &source_code.text; + let index = &source_code.index; + + if source.is_empty() { + return TextRange::new(TextSize::new(0), TextSize::new(0)); + } + + let start = index.offset( + location.start.row.get_one_indexed(), + location.start.column.get_one_indexed(), + source, + ); + let end = index.offset( + location.end.row.get_one_indexed(), + location.end.column.get_one_indexed(), + source, + ); + + TextRange::new(start, end) +} + +fn node_add_location( + dict: &Py, + range: TextRange, + vm: &VirtualMachine, + source_code: &SourceCodeOwned, +) { + let range = text_range_to_source_range(source_code, range); dict.set_item("lineno", vm.ctx.new_int(range.start.row.get()).into(), vm) .unwrap(); dict.set_item( "col_offset", - vm.ctx.new_int(range.start.column.to_zero_indexed()).into(), + vm.ctx.new_int(range.start.column.get()).into(), vm, ) .unwrap(); - if let Some(end_location) = range.end { - dict.set_item( - "end_lineno", - vm.ctx.new_int(end_location.row.get()).into(), - vm, - ) + dict.set_item("end_lineno", vm.ctx.new_int(range.end.row.get()).into(), vm) .unwrap(); - dict.set_item( - "end_col_offset", - vm.ctx.new_int(end_location.column.to_zero_indexed()).into(), - vm, - ) - .unwrap(); - }; + dict.set_item( + "end_col_offset", + vm.ctx.new_int(range.end.column.get()).into(), + vm, + ) + .unwrap(); } -impl Node for ast::String { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - vm.ctx.new_str(self).into() - } - - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - let py_str = PyStrRef::try_from_object(vm, object)?; - Ok(py_str.as_str().to_owned()) - } -} - -impl Node for ast::Identifier { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - let id: String = self.into(); - vm.ctx.new_str(id).into() - } - - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - let py_str = PyStrRef::try_from_object(vm, object)?; - Ok(ast::Identifier::new(py_str.as_str())) - } -} - -impl Node for ast::Int { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - vm.ctx.new_int(self.to_u32()).into() - } - - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - let value = object.try_into_value(vm)?; - Ok(ast::Int::new(value)) - } -} - -impl Node for bool { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - vm.ctx.new_int(self as u8).into() - } - - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - i32::try_from_object(vm, object).map(|i| i != 0) - } -} - -impl Node for ast::Constant { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - ast::Constant::None => vm.ctx.none(), - ast::Constant::Bool(b) => vm.ctx.new_bool(b).into(), - ast::Constant::Str(s) => vm.ctx.new_str(s).into(), - ast::Constant::Bytes(b) => vm.ctx.new_bytes(b).into(), - ast::Constant::Int(i) => vm.ctx.new_int(i).into(), - ast::Constant::Tuple(t) => vm - .ctx - .new_tuple(t.into_iter().map(|c| c.ast_to_object(vm)).collect()) - .into(), - ast::Constant::Float(f) => vm.ctx.new_float(f).into(), - ast::Constant::Complex { real, imag } => vm.new_pyobj(Complex64::new(real, imag)), - ast::Constant::Ellipsis => vm.ctx.ellipsis(), - } - } - - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - let constant = match_class!(match object { - ref i @ builtins::int::PyInt => { - let value = i.as_bigint(); - if object.class().is(vm.ctx.types.bool_type) { - ast::Constant::Bool(!value.is_zero()) - } else { - ast::Constant::Int(value.clone()) - } - } - ref f @ builtins::float::PyFloat => ast::Constant::Float(f.to_f64()), - ref c @ builtins::complex::PyComplex => { - let c = c.to_complex(); - ast::Constant::Complex { - real: c.re, - imag: c.im, - } - } - ref s @ builtins::pystr::PyStr => ast::Constant::Str(s.as_str().to_owned()), - ref b @ builtins::bytes::PyBytes => ast::Constant::Bytes(b.as_bytes().to_owned()), - ref t @ builtins::tuple::PyTuple => { - ast::Constant::Tuple( - t.iter() - .map(|elt| Self::ast_from_object(vm, elt.clone())) - .collect::>()?, - ) - } - builtins::singletons::PyNone => ast::Constant::None, - builtins::slice::PyEllipsis => ast::Constant::Ellipsis, - obj => - return Err(vm.new_type_error(format!( - "invalid type in Constant: type '{}'", - obj.class().name() - ))), - }); - Ok(constant) - } -} - -impl Node for ast::ConversionFlag { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - vm.ctx.new_int(self as u8).into() - } - - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - i32::try_from_object(vm, object)? - .to_u32() - .and_then(ast::ConversionFlag::from_op_arg) - .ok_or_else(|| vm.new_value_error("invalid conversion flag".to_owned())) - } -} - -impl Node for ast::located::Arguments { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - self.into_python_arguments().ast_to_object(vm) - } - fn ast_from_object(vm: &VirtualMachine, object: PyObjectRef) -> PyResult { - ast::located::PythonArguments::ast_from_object(vm, object) - .map(ast::located::PythonArguments::into_arguments) - } -} - -#[cfg(feature = "rustpython-parser")] +#[cfg(feature = "parser")] pub(crate) fn parse( vm: &VirtualMachine, source: &str, mode: parser::Mode, ) -> Result { - let mut locator = LinearLocator::new(source); - let top = parser::parse(source, mode, "").map_err(|e| locator.locate_error(e))?; - let top = locator.fold_mod(top).unwrap(); - Ok(top.ast_to_object(vm)) + let source_code = SourceCodeOwned::new("".to_owned(), source.to_owned()); + let top = parser::parse(source, mode) + .map_err(|parse_error| ParseError { + error: parse_error.error, + location: text_range_to_source_range(&source_code, parse_error.location) + .start + .to_source_location(), + source_path: "".to_string(), + })? + .into_syntax(); + let top = match top { + ruff::Mod::Module(m) => Mod::Module(m), + ruff::Mod::Expression(e) => Mod::Expression(e), + }; + Ok(top.ast_to_object(vm, &source_code)) } -#[cfg(feature = "rustpython-codegen")] +#[cfg(feature = "codegen")] pub(crate) fn compile( vm: &VirtualMachine, object: PyObjectRef, @@ -348,14 +271,24 @@ pub(crate) fn compile( opts.optimize = optimize; } - let ast = Node::ast_from_object(vm, object)?; - let code = codegen::compile::compile_top(&ast, filename.to_owned(), mode, opts) - .map_err(|err| (CompileError::from(err), None).to_pyexception(vm))?; // FIXME source + let source_code = SourceCodeOwned::new(filename.to_owned(), "".to_owned()); + let ast: Mod = Node::ast_from_object(vm, &source_code, object)?; + let ast = match ast { + Mod::Module(m) => ruff::Mod::Module(m), + Mod::Interactive(ModInteractive { range, body }) => { + ruff::Mod::Module(ruff::ModModule { range, body }) + } + Mod::Expression(e) => ruff::Mod::Expression(e), + Mod::FunctionType(_) => todo!(), + }; + // TODO: create a textual representation of the ast + let text = ""; + let source_code = SourceCode::new(filename, text); + let code = codegen::compile::compile_top(ast, source_code, mode, opts) + .map_err(|err| vm.new_syntax_error(&err.into(), None))?; // FIXME source Ok(vm.ctx.new_code(code).into()) } -// Required crate visibility for inclusion by gen.rs -pub(crate) use _ast::NodeAst; // Used by builtins::compile() pub const PY_COMPILE_FLAG_AST_ONLY: i32 = 0x0400; @@ -398,6 +331,6 @@ pub const PY_COMPILE_FLAGS_MASK: i32 = PY_COMPILE_FLAG_AST_ONLY pub fn make_module(vm: &VirtualMachine) -> PyRef { let module = _ast::make_module(vm); - r#gen::extend_module_nodes(vm, &module); + pyast::extend_module_nodes(vm, &module); module } diff --git a/vm/src/stdlib/ast/argument.rs b/vm/src/stdlib/ast/argument.rs new file mode 100644 index 000000000..dae2345f0 --- /dev/null +++ b/vm/src/stdlib/ast/argument.rs @@ -0,0 +1,161 @@ +use super::*; + +pub(super) struct PositionalArguments { + pub range: TextRange, + pub args: Box<[ruff::Expr]>, +} + +impl Node for PositionalArguments { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { args, range: _ } = self; + BoxedSlice(args).ast_to_object(vm, source_code) + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let args: BoxedSlice<_> = Node::ast_from_object(vm, source_code, object)?; + Ok(Self { + args: args.0, + range: TextRange::default(), // TODO + }) + } +} + +pub(super) struct KeywordArguments { + pub range: TextRange, + pub keywords: Box<[ruff::Keyword]>, +} + +impl Node for KeywordArguments { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { keywords, range: _ } = self; + // TODO: use range + BoxedSlice(keywords).ast_to_object(vm, source_code) + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let keywords: BoxedSlice<_> = Node::ast_from_object(vm, source_code, object)?; + Ok(Self { + keywords: keywords.0, + range: TextRange::default(), // TODO + }) + } +} + +pub(super) fn merge_function_call_arguments( + pos_args: PositionalArguments, + key_args: KeywordArguments, +) -> ruff::Arguments { + let range = pos_args.range.cover(key_args.range); + + ruff::Arguments { + range, + args: pos_args.args, + keywords: key_args.keywords, + } +} + +pub(super) fn split_function_call_arguments( + args: ruff::Arguments, +) -> (PositionalArguments, KeywordArguments) { + let ruff::Arguments { + range: _, + args, + keywords, + } = args; + + let positional_arguments_range = args + .iter() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(); + // debug_assert!(range.contains_range(positional_arguments_range)); + let positional_arguments = PositionalArguments { + range: positional_arguments_range, + args, + }; + + let keyword_arguments_range = keywords + .iter() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(); + // debug_assert!(range.contains_range(keyword_arguments_range)); + let keyword_arguments = KeywordArguments { + range: keyword_arguments_range, + keywords, + }; + + (positional_arguments, keyword_arguments) +} + +pub(super) fn split_class_def_args( + args: Option>, +) -> (Option, Option) { + let args = match args { + None => return (None, None), + Some(args) => *args, + }; + let ruff::Arguments { + range: _, + args, + keywords, + } = args; + + let positional_arguments_range = args + .iter() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(); + // debug_assert!(range.contains_range(positional_arguments_range)); + let positional_arguments = PositionalArguments { + range: positional_arguments_range, + args, + }; + + let keyword_arguments_range = keywords + .iter() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(); + // debug_assert!(range.contains_range(keyword_arguments_range)); + let keyword_arguments = KeywordArguments { + range: keyword_arguments_range, + keywords, + }; + + (Some(positional_arguments), Some(keyword_arguments)) +} + +pub(super) fn merge_class_def_args( + positional_arguments: Option, + keyword_arguments: Option, +) -> Option> { + if positional_arguments.is_none() && keyword_arguments.is_none() { + return None; + } + + let args = if let Some(positional_arguments) = positional_arguments { + positional_arguments.args + } else { + vec![].into_boxed_slice() + }; + let keywords = if let Some(keyword_arguments) = keyword_arguments { + keyword_arguments.keywords + } else { + vec![].into_boxed_slice() + }; + + Some(Box::new(ruff::Arguments { + range: Default::default(), // TODO + args, + keywords, + })) +} diff --git a/vm/src/stdlib/ast/basic.rs b/vm/src/stdlib/ast/basic.rs new file mode 100644 index 000000000..4ed1e9e03 --- /dev/null +++ b/vm/src/stdlib/ast/basic.rs @@ -0,0 +1,50 @@ +use rustpython_codegen::compile::ruff_int_to_bigint; + +use super::*; + +impl Node for ruff::Identifier { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + let id = self.as_str(); + vm.ctx.new_str(id).into() + } + + fn ast_from_object( + vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let py_str = PyStrRef::try_from_object(vm, object)?; + Ok(ruff::Identifier::new(py_str.as_str(), TextRange::default())) + } +} + +impl Node for ruff::Int { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + vm.ctx.new_int(ruff_int_to_bigint(&self).unwrap()).into() + } + + fn ast_from_object( + vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + // FIXME: performance + let value: PyIntRef = object.try_into_value(vm)?; + let value = value.as_bigint().to_string(); + Ok(value.parse().unwrap()) + } +} + +impl Node for bool { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + vm.ctx.new_int(self as u8).into() + } + + fn ast_from_object( + vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + i32::try_from_object(vm, object).map(|i| i != 0) + } +} diff --git a/vm/src/stdlib/ast/constant.rs b/vm/src/stdlib/ast/constant.rs new file mode 100644 index 000000000..29c29b466 --- /dev/null +++ b/vm/src/stdlib/ast/constant.rs @@ -0,0 +1,396 @@ +use super::*; +use crate::builtins::{PyComplex, PyFrozenSet, PyTuple}; +use ruff::str_prefix::StringLiteralPrefix; + +#[derive(Debug)] +pub(super) struct Constant { + pub(super) range: TextRange, + pub(super) value: ConstantLiteral, +} + +impl Constant { + pub(super) fn new_str( + value: impl Into>, + prefix: StringLiteralPrefix, + range: TextRange, + ) -> Self { + let value = value.into(); + Self { + range, + value: ConstantLiteral::Str { value, prefix }, + } + } + + pub(super) fn new_int(value: ruff::Int, range: TextRange) -> Self { + Self { + range, + value: ConstantLiteral::Int(value), + } + } + + pub(super) fn new_float(value: f64, range: TextRange) -> Self { + Self { + range, + value: ConstantLiteral::Float(value), + } + } + pub(super) fn new_complex(real: f64, imag: f64, range: TextRange) -> Self { + Self { + range, + value: ConstantLiteral::Complex { real, imag }, + } + } + + pub(super) fn new_bytes(value: Box<[u8]>, range: TextRange) -> Self { + Self { + range, + value: ConstantLiteral::Bytes(value), + } + } + + pub(super) fn new_bool(value: bool, range: TextRange) -> Self { + Self { + range, + value: ConstantLiteral::Bool(value), + } + } + + pub(super) fn new_none(range: TextRange) -> Self { + Self { + range, + value: ConstantLiteral::None, + } + } + + pub(super) fn new_ellipsis(range: TextRange) -> Self { + Self { + range, + value: ConstantLiteral::Ellipsis, + } + } + + pub(crate) fn into_expr(self) -> ruff::Expr { + constant_to_ruff_expr(self) + } +} + +#[derive(Debug)] +pub(crate) enum ConstantLiteral { + None, + Bool(bool), + Str { + value: Box, + prefix: StringLiteralPrefix, + }, + Bytes(Box<[u8]>), + Int(ruff::Int), + Tuple(Vec), + FrozenSet(Vec), + Float(f64), + Complex { + real: f64, + imag: f64, + }, + Ellipsis, +} + +// constructor +impl Node for Constant { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { range, value } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprConstant::static_type().to_owned()) + .unwrap(); + let kind = match &value { + ConstantLiteral::Str { + prefix: StringLiteralPrefix::Unicode, + .. + } => vm.ctx.new_str("u").into(), + _ => vm.ctx.none(), + }; + let value = value.ast_to_object(vm, source_code); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value, vm).unwrap(); + dict.set_item("kind", kind, vm).unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let value_object = get_node_field(vm, &object, "value", "Constant")?; + let value = Node::ast_from_object(vm, source_code, value_object)?; + + Ok(Self { + value, + // kind: get_node_field_opt(_vm, &_object, "kind")? + // .map(|obj| Node::ast_from_object(_vm, obj)) + // .transpose()?, + range: range_from_object(vm, source_code, object, "Constant")?, + }) + } +} + +impl Node for ConstantLiteral { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + ConstantLiteral::None => vm.ctx.none(), + ConstantLiteral::Bool(value) => vm.ctx.new_bool(value).to_pyobject(vm), + ConstantLiteral::Str { value, .. } => vm.ctx.new_str(value).to_pyobject(vm), + ConstantLiteral::Bytes(value) => vm.ctx.new_bytes(value.into()).to_pyobject(vm), + ConstantLiteral::Int(value) => value.ast_to_object(vm, source_code), + ConstantLiteral::Tuple(value) => { + let value = value + .into_iter() + .map(|c| c.ast_to_object(vm, source_code)) + .collect(); + vm.ctx.new_tuple(value).to_pyobject(vm) + } + ConstantLiteral::FrozenSet(value) => PyFrozenSet::from_iter( + vm, + value.into_iter().map(|c| c.ast_to_object(vm, source_code)), + ) + .unwrap() + .into_pyobject(vm), + ConstantLiteral::Float(value) => vm.ctx.new_float(value).into_pyobject(vm), + ConstantLiteral::Complex { real, imag } => vm + .ctx + .new_complex(num_complex::Complex::new(real, imag)) + .into_pyobject(vm), + ConstantLiteral::Ellipsis => vm.ctx.ellipsis(), + } + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + value_object: PyObjectRef, + ) -> PyResult { + let cls = value_object.class(); + let value = if cls.is(vm.ctx.types.none_type) { + ConstantLiteral::None + } else if cls.is(vm.ctx.types.bool_type) { + ConstantLiteral::Bool(if value_object.is(&vm.ctx.true_value) { + true + } else if value_object.is(&vm.ctx.false_value) { + false + } else { + value_object.try_to_value(vm)? + }) + } else if cls.is(vm.ctx.types.str_type) { + ConstantLiteral::Str { + value: value_object.try_to_value::(vm)?.into(), + prefix: StringLiteralPrefix::Empty, + } + } else if cls.is(vm.ctx.types.bytes_type) { + ConstantLiteral::Bytes(value_object.try_to_value::>(vm)?.into()) + } else if cls.is(vm.ctx.types.int_type) { + ConstantLiteral::Int(Node::ast_from_object(vm, source_code, value_object)?) + } else if cls.is(vm.ctx.types.tuple_type) { + let tuple = value_object.downcast::().map_err(|obj| { + vm.new_type_error(format!( + "Expected type {}, not {}", + PyTuple::static_type().name(), + obj.class().name() + )) + })?; + let tuple = tuple + .into_iter() + .cloned() + .map(|object| Node::ast_from_object(vm, source_code, object)) + .collect::>()?; + ConstantLiteral::Tuple(tuple) + } else if cls.is(vm.ctx.types.frozenset_type) { + let set = value_object.downcast::().unwrap(); + let elements = set + .elements() + .into_iter() + .map(|object| Node::ast_from_object(vm, source_code, object)) + .collect::>()?; + ConstantLiteral::FrozenSet(elements) + } else if cls.is(vm.ctx.types.float_type) { + let float = value_object.try_into_value(vm)?; + ConstantLiteral::Float(float) + } else if cls.is(vm.ctx.types.complex_type) { + let complex = value_object.try_complex(vm)?; + let complex = match complex { + None => { + return Err(vm.new_type_error(format!( + "Expected type {}, not {}", + PyComplex::static_type().name(), + value_object.class().name() + ))); + } + Some((value, _was_coerced)) => value, + }; + ConstantLiteral::Complex { + real: complex.re, + imag: complex.im, + } + } else if cls.is(vm.ctx.types.ellipsis_type) { + ConstantLiteral::Ellipsis + } else { + return Err(vm.new_type_error(format!( + "invalid type in Constant: {}", + value_object.class().name() + ))); + }; + Ok(value) + } +} + +fn constant_to_ruff_expr(value: Constant) -> ruff::Expr { + let Constant { value, range } = value; + match value { + ConstantLiteral::None => ruff::Expr::NoneLiteral(ruff::ExprNoneLiteral { range }), + ConstantLiteral::Bool(value) => { + ruff::Expr::BooleanLiteral(ruff::ExprBooleanLiteral { range, value }) + } + ConstantLiteral::Str { value, prefix } => { + ruff::Expr::StringLiteral(ruff::ExprStringLiteral { + range, + value: ruff::StringLiteralValue::single(ruff::StringLiteral { + range, + value, + flags: ruff::StringLiteralFlags::default().with_prefix(prefix), + }), + }) + } + ConstantLiteral::Bytes(value) => { + ruff::Expr::BytesLiteral(ruff::ExprBytesLiteral { + range, + value: ruff::BytesLiteralValue::single(ruff::BytesLiteral { + range, + value, + flags: Default::default(), // TODO + }), + }) + } + ConstantLiteral::Int(value) => ruff::Expr::NumberLiteral(ruff::ExprNumberLiteral { + range, + value: ruff::Number::Int(value), + }), + ConstantLiteral::Tuple(value) => ruff::Expr::Tuple(ruff::ExprTuple { + range, + elts: value + .into_iter() + .map(|value| { + constant_to_ruff_expr(Constant { + range: TextRange::default(), + value, + }) + }) + .collect(), + ctx: ruff::ExprContext::Load, + // TODO: Does this matter? + parenthesized: true, + }), + ConstantLiteral::FrozenSet(value) => ruff::Expr::Call(ruff::ExprCall { + range, + // idk lol + func: Box::new(ruff::Expr::Name(ruff::ExprName { + range: TextRange::default(), + id: "frozenset".to_owned(), + ctx: ruff::ExprContext::Load, + })), + arguments: ruff::Arguments { + range, + args: value + .into_iter() + .map(|value| { + constant_to_ruff_expr(Constant { + range: TextRange::default(), + value, + }) + }) + .collect(), + keywords: Box::default(), + }, + }), + ConstantLiteral::Float(value) => ruff::Expr::NumberLiteral(ruff::ExprNumberLiteral { + range, + value: ruff::Number::Float(value), + }), + ConstantLiteral::Complex { real, imag } => { + ruff::Expr::NumberLiteral(ruff::ExprNumberLiteral { + range, + value: ruff::Number::Complex { real, imag }, + }) + } + ConstantLiteral::Ellipsis => { + ruff::Expr::EllipsisLiteral(ruff::ExprEllipsisLiteral { range }) + } + } +} + +pub(super) fn number_literal_to_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + constant: ruff::ExprNumberLiteral, +) -> PyObjectRef { + let ruff::ExprNumberLiteral { range, value } = constant; + let c = match value { + ruff::Number::Int(n) => Constant::new_int(n, range), + ruff::Number::Float(n) => Constant::new_float(n, range), + ruff::Number::Complex { real, imag } => Constant::new_complex(real, imag, range), + }; + c.ast_to_object(vm, source_code) +} + +pub(super) fn string_literal_to_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + constant: ruff::ExprStringLiteral, +) -> PyObjectRef { + let ruff::ExprStringLiteral { range, value } = constant; + let prefix = value + .iter() + .next() + .map_or(StringLiteralPrefix::Empty, |part| part.flags.prefix()); + let c = Constant::new_str(value.to_str(), prefix, range); + c.ast_to_object(vm, source_code) +} + +pub(super) fn bytes_literal_to_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + constant: ruff::ExprBytesLiteral, +) -> PyObjectRef { + let ruff::ExprBytesLiteral { range, value } = constant; + let bytes = value.as_slice().iter().flat_map(|b| b.value.iter()); + let c = Constant::new_bytes(bytes.copied().collect(), range); + c.ast_to_object(vm, source_code) +} + +pub(super) fn boolean_literal_to_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + constant: ruff::ExprBooleanLiteral, +) -> PyObjectRef { + let ruff::ExprBooleanLiteral { range, value } = constant; + let c = Constant::new_bool(value, range); + c.ast_to_object(vm, source_code) +} + +pub(super) fn none_literal_to_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + constant: ruff::ExprNoneLiteral, +) -> PyObjectRef { + let ruff::ExprNoneLiteral { range } = constant; + let c = Constant::new_none(range); + c.ast_to_object(vm, source_code) +} + +pub(super) fn ellipsis_literal_to_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + constant: ruff::ExprEllipsisLiteral, +) -> PyObjectRef { + let ruff::ExprEllipsisLiteral { range } = constant; + let c = Constant::new_ellipsis(range); + c.ast_to_object(vm, source_code) +} diff --git a/vm/src/stdlib/ast/elif_else_clause.rs b/vm/src/stdlib/ast/elif_else_clause.rs new file mode 100644 index 000000000..13f6865ea --- /dev/null +++ b/vm/src/stdlib/ast/elif_else_clause.rs @@ -0,0 +1,88 @@ +use super::*; + +pub(super) fn ast_to_object( + clause: ruff::ElifElseClause, + mut rest: std::vec::IntoIter, + vm: &VirtualMachine, + source_code: &SourceCodeOwned, +) -> PyObjectRef { + let ruff::ElifElseClause { range, test, body } = clause; + let Some(test) = test else { + assert!(rest.len() == 0); + return body.ast_to_object(vm, source_code); + }; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeStmtIf::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + + dict.set_item("test", test.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(vm, source_code), vm) + .unwrap(); + + let orelse = if let Some(next) = rest.next() { + if next.test.is_some() { + vm.ctx + .new_list(vec![ast_to_object(next, rest, vm, source_code)]) + .into() + } else { + next.body.ast_to_object(vm, source_code) + } + } else { + vm.ctx.new_list(vec![]).into() + }; + dict.set_item("orelse", orelse, vm).unwrap(); + + node_add_location(&dict, range, vm, source_code); + node.into() +} + +pub(super) fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, +) -> PyResult { + let test = Node::ast_from_object(vm, source_code, get_node_field(vm, &object, "test", "If")?)?; + let body = Node::ast_from_object(vm, source_code, get_node_field(vm, &object, "body", "If")?)?; + let orelse: Vec = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "orelse", "If")?, + )?; + let range = range_from_object(vm, source_code, object, "If")?; + + let elif_else_clauses = if let [ruff::Stmt::If(_)] = &*orelse { + let Some(ruff::Stmt::If(ruff::StmtIf { + range, + test, + body, + mut elif_else_clauses, + })) = orelse.into_iter().next() + else { + unreachable!() + }; + elif_else_clauses.insert( + 0, + ruff::ElifElseClause { + range, + test: Some(*test), + body, + }, + ); + elif_else_clauses + } else { + vec![ruff::ElifElseClause { + range, + test: None, + body: orelse, + }] + }; + + Ok(ruff::StmtIf { + test, + body, + elif_else_clauses, + range, + }) +} diff --git a/vm/src/stdlib/ast/exception.rs b/vm/src/stdlib/ast/exception.rs new file mode 100644 index 000000000..a76e7b569 --- /dev/null +++ b/vm/src/stdlib/ast/exception.rs @@ -0,0 +1,75 @@ +use super::*; + +// sum +impl Node for ruff::ExceptHandler { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + ruff::ExceptHandler::ExceptHandler(cons) => cons.ast_to_object(vm, source_code), + } + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok( + if _cls.is(pyast::NodeExceptHandlerExceptHandler::static_type()) { + ruff::ExceptHandler::ExceptHandler( + ruff::ExceptHandlerExceptHandler::ast_from_object(_vm, source_code, _object)?, + ) + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of excepthandler, but got {}", + _object.repr(_vm)? + ))); + }, + ) + } +} +// constructor +impl Node for ruff::ExceptHandlerExceptHandler { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::ExceptHandlerExceptHandler { + type_, + name, + body, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type( + _vm, + pyast::NodeExceptHandlerExceptHandler::static_type().to_owned(), + ) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("type", type_.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("name", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::ExceptHandlerExceptHandler { + type_: get_node_field_opt(_vm, &_object, "type")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + name: get_node_field_opt(_vm, &_object, "name")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + body: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "body", "ExceptHandler")?, + )?, + range: range_from_object(_vm, source_code, _object, "ExceptHandler")?, + }) + } +} diff --git a/vm/src/stdlib/ast/expression.rs b/vm/src/stdlib/ast/expression.rs new file mode 100644 index 000000000..b4c9124ad --- /dev/null +++ b/vm/src/stdlib/ast/expression.rs @@ -0,0 +1,1197 @@ +use super::*; +use crate::stdlib::ast::argument::{merge_function_call_arguments, split_function_call_arguments}; +use crate::stdlib::ast::constant::Constant; +use crate::stdlib::ast::string::JoinedStr; + +// sum +impl Node for ruff::Expr { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + ruff::Expr::BoolOp(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Name(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::BinOp(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::UnaryOp(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Lambda(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::If(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Dict(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Set(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::ListComp(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::SetComp(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::DictComp(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Generator(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Await(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Yield(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::YieldFrom(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Compare(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Call(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Attribute(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Subscript(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Starred(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::List(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Tuple(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::Slice(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::NumberLiteral(cons) => { + constant::number_literal_to_object(vm, source_code, cons) + } + ruff::Expr::StringLiteral(cons) => { + constant::string_literal_to_object(vm, source_code, cons) + } + ruff::Expr::FString(cons) => string::fstring_to_object(vm, source_code, cons), + ruff::Expr::BytesLiteral(cons) => { + constant::bytes_literal_to_object(vm, source_code, cons) + } + ruff::Expr::BooleanLiteral(cons) => { + constant::boolean_literal_to_object(vm, source_code, cons) + } + ruff::Expr::NoneLiteral(cons) => { + constant::none_literal_to_object(vm, source_code, cons) + } + ruff::Expr::EllipsisLiteral(cons) => { + constant::ellipsis_literal_to_object(vm, source_code, cons) + } + ruff::Expr::Named(cons) => cons.ast_to_object(vm, source_code), + ruff::Expr::IpyEscapeCommand(_) => { + unimplemented!("IPython escape command is not allowed in Python AST") + } + } + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let cls = object.class(); + Ok(if cls.is(pyast::NodeExprBoolOp::static_type()) { + ruff::Expr::BoolOp(ruff::ExprBoolOp::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprNamedExpr::static_type()) { + ruff::Expr::Named(ruff::ExprNamed::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprBinOp::static_type()) { + ruff::Expr::BinOp(ruff::ExprBinOp::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprUnaryOp::static_type()) { + ruff::Expr::UnaryOp(ruff::ExprUnaryOp::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprLambda::static_type()) { + ruff::Expr::Lambda(ruff::ExprLambda::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprIfExp::static_type()) { + ruff::Expr::If(ruff::ExprIf::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprDict::static_type()) { + ruff::Expr::Dict(ruff::ExprDict::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprSet::static_type()) { + ruff::Expr::Set(ruff::ExprSet::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprListComp::static_type()) { + ruff::Expr::ListComp(ruff::ExprListComp::ast_from_object( + vm, + source_code, + object, + )?) + } else if cls.is(pyast::NodeExprSetComp::static_type()) { + ruff::Expr::SetComp(ruff::ExprSetComp::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprDictComp::static_type()) { + ruff::Expr::DictComp(ruff::ExprDictComp::ast_from_object( + vm, + source_code, + object, + )?) + } else if cls.is(pyast::NodeExprGeneratorExp::static_type()) { + ruff::Expr::Generator(ruff::ExprGenerator::ast_from_object( + vm, + source_code, + object, + )?) + } else if cls.is(pyast::NodeExprAwait::static_type()) { + ruff::Expr::Await(ruff::ExprAwait::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprYield::static_type()) { + ruff::Expr::Yield(ruff::ExprYield::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprYieldFrom::static_type()) { + ruff::Expr::YieldFrom(ruff::ExprYieldFrom::ast_from_object( + vm, + source_code, + object, + )?) + } else if cls.is(pyast::NodeExprCompare::static_type()) { + ruff::Expr::Compare(ruff::ExprCompare::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprCall::static_type()) { + ruff::Expr::Call(ruff::ExprCall::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprAttribute::static_type()) { + ruff::Expr::Attribute(ruff::ExprAttribute::ast_from_object( + vm, + source_code, + object, + )?) + } else if cls.is(pyast::NodeExprSubscript::static_type()) { + ruff::Expr::Subscript(ruff::ExprSubscript::ast_from_object( + vm, + source_code, + object, + )?) + } else if cls.is(pyast::NodeExprStarred::static_type()) { + ruff::Expr::Starred(ruff::ExprStarred::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprName::static_type()) { + ruff::Expr::Name(ruff::ExprName::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprList::static_type()) { + ruff::Expr::List(ruff::ExprList::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprTuple::static_type()) { + ruff::Expr::Tuple(ruff::ExprTuple::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprSlice::static_type()) { + ruff::Expr::Slice(ruff::ExprSlice::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeExprConstant::static_type()) { + Constant::ast_from_object(vm, source_code, object)?.into_expr() + } else if cls.is(pyast::NodeExprJoinedStr::static_type()) { + JoinedStr::ast_from_object(vm, source_code, object)?.into_expr() + } else { + return Err(vm.new_type_error(format!( + "expected some sort of expr, but got {}", + object.repr(vm)? + ))); + }) + } +} +// constructor +impl Node for ruff::ExprBoolOp { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { op, values, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprBoolOp::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("op", op.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("values", values.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + op: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "op", "BoolOp")?, + )?, + values: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "values", "BoolOp")?, + )?, + range: range_from_object(vm, source_code, object, "BoolOp")?, + }) + } +} +// constructor +impl Node for ruff::ExprNamed { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + target, + value, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprNamedExpr::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("target", target.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + target: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "target", "NamedExpr")?, + )?, + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "NamedExpr")?, + )?, + range: range_from_object(vm, source_code, object, "NamedExpr")?, + }) + } +} +// constructor +impl Node for ruff::ExprBinOp { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + left, + op, + right, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprBinOp::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("left", left.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("op", op.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("right", right.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + left: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "left", "BinOp")?, + )?, + op: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "op", "BinOp")?, + )?, + right: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "right", "BinOp")?, + )?, + range: range_from_object(vm, source_code, object, "BinOp")?, + }) + } +} +// constructor +impl Node for ruff::ExprUnaryOp { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { op, operand, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprUnaryOp::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("op", op.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("operand", operand.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + op: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "op", "UnaryOp")?, + )?, + operand: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "operand", "UnaryOp")?, + )?, + range: range_from_object(vm, source_code, object, "UnaryOp")?, + }) + } +} +// constructor +impl Node for ruff::ExprLambda { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + parameters, + body, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprLambda::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("args", parameters.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, _range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + parameters: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "args", "Lambda")?, + )?, + body: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "body", "Lambda")?, + )?, + range: range_from_object(vm, source_code, object, "Lambda")?, + }) + } +} +// constructor +impl Node for ruff::ExprIf { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + test, + body, + orelse, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprIfExp::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("test", test.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("orelse", orelse.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + test: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "test", "IfExp")?, + )?, + body: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "body", "IfExp")?, + )?, + orelse: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "orelse", "IfExp")?, + )?, + range: range_from_object(vm, source_code, object, "IfExp")?, + }) + } +} +// constructor +impl Node for ruff::ExprDict { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { items, range } = self; + let (keys, values) = + items + .into_iter() + .fold((vec![], vec![]), |(mut keys, mut values), item| { + keys.push(item.key); + values.push(item.value); + (keys, values) + }); + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprDict::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("keys", keys.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("values", values.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let keys: Vec> = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "keys", "Dict")?, + )?; + let values: Vec<_> = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "values", "Dict")?, + )?; + let items = keys + .into_iter() + .zip(values) + .map(|(key, value)| ruff::DictItem { key, value }) + .collect(); + Ok(Self { + items, + range: range_from_object(vm, source_code, object, "Dict")?, + }) + } +} +// constructor +impl Node for ruff::ExprSet { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { elts, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprSet::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("elts", elts.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + elts: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "elts", "Set")?, + )?, + range: range_from_object(vm, source_code, object, "Set")?, + }) + } +} +// constructor +impl Node for ruff::ExprListComp { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + elt, + generators, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprListComp::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("elt", elt.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("generators", generators.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + elt: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "elt", "ListComp")?, + )?, + generators: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "generators", "ListComp")?, + )?, + range: range_from_object(vm, source_code, object, "ListComp")?, + }) + } +} +// constructor +impl Node for ruff::ExprSetComp { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + elt, + generators, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprSetComp::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("elt", elt.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("generators", generators.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + elt: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "elt", "SetComp")?, + )?, + generators: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "generators", "SetComp")?, + )?, + range: range_from_object(vm, source_code, object, "SetComp")?, + }) + } +} +// constructor +impl Node for ruff::ExprDictComp { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + key, + value, + generators, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprDictComp::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("key", key.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("generators", generators.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + key: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "key", "DictComp")?, + )?, + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "DictComp")?, + )?, + generators: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "generators", "DictComp")?, + )?, + range: range_from_object(vm, source_code, object, "DictComp")?, + }) + } +} +// constructor +impl Node for ruff::ExprGenerator { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + elt, + generators, + range, + parenthesized: _, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprGeneratorExp::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("elt", elt.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("generators", generators.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + elt: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "elt", "GeneratorExp")?, + )?, + generators: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "generators", "GeneratorExp")?, + )?, + range: range_from_object(vm, source_code, object, "GeneratorExp")?, + // TODO: Is this correct? + parenthesized: true, + }) + } +} +// constructor +impl Node for ruff::ExprAwait { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { value, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprAwait::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "Await")?, + )?, + range: range_from_object(vm, source_code, object, "Await")?, + }) + } +} +// constructor +impl Node for ruff::ExprYield { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::ExprYield { value, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprYield::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(ruff::ExprYield { + value: get_node_field_opt(vm, &object, "value")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + range: range_from_object(vm, source_code, object, "Yield")?, + }) + } +} +// constructor +impl Node for ruff::ExprYieldFrom { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { value, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprYieldFrom::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "YieldFrom")?, + )?, + range: range_from_object(vm, source_code, object, "YieldFrom")?, + }) + } +} +// constructor +impl Node for ruff::ExprCompare { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + left, + ops, + comparators, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprCompare::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("left", left.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("ops", BoxedSlice(ops).ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item( + "comparators", + BoxedSlice(comparators).ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + left: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "left", "Compare")?, + )?, + ops: { + let ops: BoxedSlice<_> = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "ops", "Compare")?, + )?; + ops.0 + }, + comparators: { + let comparators: BoxedSlice<_> = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "comparators", "Compare")?, + )?; + comparators.0 + }, + range: range_from_object(vm, source_code, object, "Compare")?, + }) + } +} +// constructor +impl Node for ruff::ExprCall { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + func, + arguments, + range, + } = self; + let (positional_arguments, keyword_arguments) = split_function_call_arguments(arguments); + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprCall::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("func", func.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item( + "args", + positional_arguments.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + dict.set_item( + "keywords", + keyword_arguments.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + func: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "func", "Call")?, + )?, + arguments: merge_function_call_arguments( + Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "args", "Call")?, + )?, + Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "keywords", "Call")?, + )?, + ), + range: range_from_object(vm, source_code, object, "Call")?, + }) + } +} + +// constructor +impl Node for ruff::ExprAttribute { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + value, + attr, + ctx, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprAttribute::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("attr", attr.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("ctx", ctx.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "Attribute")?, + )?, + attr: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "attr", "Attribute")?, + )?, + ctx: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "ctx", "Attribute")?, + )?, + range: range_from_object(vm, source_code, object, "Attribute")?, + }) + } +} +// constructor +impl Node for ruff::ExprSubscript { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + value, + slice, + ctx, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprSubscript::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("slice", slice.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("ctx", ctx.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, _range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "Subscript")?, + )?, + slice: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "slice", "Subscript")?, + )?, + ctx: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "ctx", "Subscript")?, + )?, + range: range_from_object(vm, source_code, object, "Subscript")?, + }) + } +} +// constructor +impl Node for ruff::ExprStarred { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { value, ctx, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprStarred::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("ctx", ctx.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "Starred")?, + )?, + ctx: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "ctx", "Starred")?, + )?, + range: range_from_object(vm, source_code, object, "Starred")?, + }) + } +} +// constructor +impl Node for ruff::ExprName { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { id, ctx, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprName::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("id", id.to_pyobject(vm), vm).unwrap(); + dict.set_item("ctx", ctx.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + id: get_node_field(vm, &object, "id", "Name")?.try_into_value(vm)?, + ctx: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "ctx", "Name")?, + )?, + range: range_from_object(vm, source_code, object, "Name")?, + }) + } +} +// constructor +impl Node for ruff::ExprList { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::ExprList { elts, ctx, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprList::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("elts", elts.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("ctx", ctx.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(ruff::ExprList { + elts: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "elts", "List")?, + )?, + ctx: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "ctx", "List")?, + )?, + range: range_from_object(vm, source_code, object, "List")?, + }) + } +} +// constructor +impl Node for ruff::ExprTuple { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + elts, + ctx, + range: _range, + parenthesized: _, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprTuple::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("elts", elts.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("ctx", ctx.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, _range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + elts: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "elts", "Tuple")?, + )?, + ctx: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "ctx", "Tuple")?, + )?, + range: range_from_object(vm, source_code, object, "Tuple")?, + parenthesized: true, // TODO: is this correct? + }) + } +} +// constructor +impl Node for ruff::ExprSlice { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + lower, + upper, + step, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprSlice::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("lower", lower.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("upper", upper.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("step", step.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, _range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + lower: get_node_field_opt(vm, &object, "lower")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + upper: get_node_field_opt(vm, &object, "upper")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + step: get_node_field_opt(vm, &object, "step")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + range: range_from_object(vm, source_code, object, "Slice")?, + }) + } +} +// sum +impl Node for ruff::ExprContext { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + let node_type = match self { + ruff::ExprContext::Load => pyast::NodeExprContextLoad::static_type(), + ruff::ExprContext::Store => pyast::NodeExprContextStore::static_type(), + ruff::ExprContext::Del => pyast::NodeExprContextDel::static_type(), + ruff::ExprContext::Invalid => { + unimplemented!("Invalid expression context is not allowed in Python AST") + } + }; + NodeAst + .into_ref_with_type(vm, node_type.to_owned()) + .unwrap() + .into() + } + fn ast_from_object( + vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let _cls = object.class(); + Ok(if _cls.is(pyast::NodeExprContextLoad::static_type()) { + ruff::ExprContext::Load + } else if _cls.is(pyast::NodeExprContextStore::static_type()) { + ruff::ExprContext::Store + } else if _cls.is(pyast::NodeExprContextDel::static_type()) { + ruff::ExprContext::Del + } else { + return Err(vm.new_type_error(format!( + "expected some sort of expr_context, but got {}", + object.repr(vm)? + ))); + }) + } +} + +// product +impl Node for ruff::Comprehension { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + target, + iter, + ifs, + is_async, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeComprehension::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("target", target.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("iter", iter.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("ifs", ifs.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("is_async", is_async.ast_to_object(vm, source_code), vm) + .unwrap(); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + target: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "target", "comprehension")?, + )?, + iter: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "iter", "comprehension")?, + )?, + ifs: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "ifs", "comprehension")?, + )?, + is_async: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "is_async", "comprehension")?, + )?, + range: Default::default(), + }) + } +} diff --git a/vm/src/stdlib/ast/gen.rs b/vm/src/stdlib/ast/gen.rs deleted file mode 100644 index d3969b902..000000000 --- a/vm/src/stdlib/ast/gen.rs +++ /dev/null @@ -1,5496 +0,0 @@ -// File automatically generated by ast/asdl_rs.py. - -#![allow(clippy::all)] - -use super::*; -use crate::common::ascii; -#[pyclass(module = "_ast", name = "mod", base = "NodeAst")] -struct NodeMod; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeMod {} -#[pyclass(module = "_ast", name = "Module", base = "NodeMod")] -struct NodeModModule; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeModModule { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("type_ignores")).into(), - ]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Interactive", base = "NodeMod")] -struct NodeModInteractive; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeModInteractive { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("body")).into()]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Expression", base = "NodeMod")] -struct NodeModExpression; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeModExpression { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("body")).into()]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "FunctionType", base = "NodeMod")] -struct NodeModFunctionType; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeModFunctionType { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("argtypes")).into(), - ctx.new_str(ascii!("returns")).into(), - ]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "stmt", base = "NodeAst")] -struct NodeStmt; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmt {} -#[pyclass(module = "_ast", name = "FunctionDef", base = "NodeStmt")] -struct NodeStmtFunctionDef; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtFunctionDef { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("name")).into(), - ctx.new_str(ascii!("args")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("decorator_list")).into(), - ctx.new_str(ascii!("returns")).into(), - ctx.new_str(ascii!("type_comment")).into(), - ctx.new_str(ascii!("type_params")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "AsyncFunctionDef", base = "NodeStmt")] -struct NodeStmtAsyncFunctionDef; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtAsyncFunctionDef { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("name")).into(), - ctx.new_str(ascii!("args")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("decorator_list")).into(), - ctx.new_str(ascii!("returns")).into(), - ctx.new_str(ascii!("type_comment")).into(), - ctx.new_str(ascii!("type_params")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "ClassDef", base = "NodeStmt")] -struct NodeStmtClassDef; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtClassDef { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("name")).into(), - ctx.new_str(ascii!("bases")).into(), - ctx.new_str(ascii!("keywords")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("decorator_list")).into(), - ctx.new_str(ascii!("type_params")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Return", base = "NodeStmt")] -struct NodeStmtReturn; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtReturn { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Delete", base = "NodeStmt")] -struct NodeStmtDelete; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtDelete { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("targets")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Assign", base = "NodeStmt")] -struct NodeStmtAssign; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtAssign { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("targets")).into(), - ctx.new_str(ascii!("value")).into(), - ctx.new_str(ascii!("type_comment")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "TypeAlias", base = "NodeStmt")] -struct NodeStmtTypeAlias; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtTypeAlias { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("name")).into(), - ctx.new_str(ascii!("type_params")).into(), - ctx.new_str(ascii!("value")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "AugAssign", base = "NodeStmt")] -struct NodeStmtAugAssign; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtAugAssign { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("target")).into(), - ctx.new_str(ascii!("op")).into(), - ctx.new_str(ascii!("value")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "AnnAssign", base = "NodeStmt")] -struct NodeStmtAnnAssign; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtAnnAssign { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("target")).into(), - ctx.new_str(ascii!("annotation")).into(), - ctx.new_str(ascii!("value")).into(), - ctx.new_str(ascii!("simple")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "For", base = "NodeStmt")] -struct NodeStmtFor; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtFor { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("target")).into(), - ctx.new_str(ascii!("iter")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("orelse")).into(), - ctx.new_str(ascii!("type_comment")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "AsyncFor", base = "NodeStmt")] -struct NodeStmtAsyncFor; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtAsyncFor { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("target")).into(), - ctx.new_str(ascii!("iter")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("orelse")).into(), - ctx.new_str(ascii!("type_comment")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "While", base = "NodeStmt")] -struct NodeStmtWhile; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtWhile { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("test")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("orelse")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "If", base = "NodeStmt")] -struct NodeStmtIf; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtIf { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("test")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("orelse")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "With", base = "NodeStmt")] -struct NodeStmtWith; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtWith { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("items")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("type_comment")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "AsyncWith", base = "NodeStmt")] -struct NodeStmtAsyncWith; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtAsyncWith { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("items")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("type_comment")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Match", base = "NodeStmt")] -struct NodeStmtMatch; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtMatch { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("subject")).into(), - ctx.new_str(ascii!("cases")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Raise", base = "NodeStmt")] -struct NodeStmtRaise; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtRaise { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("exc")).into(), - ctx.new_str(ascii!("cause")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Try", base = "NodeStmt")] -struct NodeStmtTry; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtTry { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("handlers")).into(), - ctx.new_str(ascii!("orelse")).into(), - ctx.new_str(ascii!("finalbody")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "TryStar", base = "NodeStmt")] -struct NodeStmtTryStar; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtTryStar { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("handlers")).into(), - ctx.new_str(ascii!("orelse")).into(), - ctx.new_str(ascii!("finalbody")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Assert", base = "NodeStmt")] -struct NodeStmtAssert; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtAssert { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("test")).into(), - ctx.new_str(ascii!("msg")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Import", base = "NodeStmt")] -struct NodeStmtImport; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtImport { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("names")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "ImportFrom", base = "NodeStmt")] -struct NodeStmtImportFrom; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtImportFrom { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("module")).into(), - ctx.new_str(ascii!("names")).into(), - ctx.new_str(ascii!("level")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Global", base = "NodeStmt")] -struct NodeStmtGlobal; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtGlobal { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("names")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Nonlocal", base = "NodeStmt")] -struct NodeStmtNonlocal; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtNonlocal { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("names")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Expr", base = "NodeStmt")] -struct NodeStmtExpr; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtExpr { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Pass", base = "NodeStmt")] -struct NodeStmtPass; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtPass { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Break", base = "NodeStmt")] -struct NodeStmtBreak; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtBreak { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Continue", base = "NodeStmt")] -struct NodeStmtContinue; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeStmtContinue { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "expr", base = "NodeAst")] -struct NodeExpr; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExpr {} -#[pyclass(module = "_ast", name = "BoolOp", base = "NodeExpr")] -struct NodeExprBoolOp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprBoolOp { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("op")).into(), - ctx.new_str(ascii!("values")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "NamedExpr", base = "NodeExpr")] -struct NodeExprNamedExpr; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprNamedExpr { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("target")).into(), - ctx.new_str(ascii!("value")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "BinOp", base = "NodeExpr")] -struct NodeExprBinOp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprBinOp { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("left")).into(), - ctx.new_str(ascii!("op")).into(), - ctx.new_str(ascii!("right")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "UnaryOp", base = "NodeExpr")] -struct NodeExprUnaryOp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprUnaryOp { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("op")).into(), - ctx.new_str(ascii!("operand")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Lambda", base = "NodeExpr")] -struct NodeExprLambda; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprLambda { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("args")).into(), - ctx.new_str(ascii!("body")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "IfExp", base = "NodeExpr")] -struct NodeExprIfExp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprIfExp { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("test")).into(), - ctx.new_str(ascii!("body")).into(), - ctx.new_str(ascii!("orelse")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Dict", base = "NodeExpr")] -struct NodeExprDict; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprDict { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("keys")).into(), - ctx.new_str(ascii!("values")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Set", base = "NodeExpr")] -struct NodeExprSet; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprSet { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("elts")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "ListComp", base = "NodeExpr")] -struct NodeExprListComp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprListComp { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("elt")).into(), - ctx.new_str(ascii!("generators")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "SetComp", base = "NodeExpr")] -struct NodeExprSetComp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprSetComp { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("elt")).into(), - ctx.new_str(ascii!("generators")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "DictComp", base = "NodeExpr")] -struct NodeExprDictComp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprDictComp { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("key")).into(), - ctx.new_str(ascii!("value")).into(), - ctx.new_str(ascii!("generators")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "GeneratorExp", base = "NodeExpr")] -struct NodeExprGeneratorExp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprGeneratorExp { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("elt")).into(), - ctx.new_str(ascii!("generators")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Await", base = "NodeExpr")] -struct NodeExprAwait; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprAwait { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Yield", base = "NodeExpr")] -struct NodeExprYield; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprYield { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "YieldFrom", base = "NodeExpr")] -struct NodeExprYieldFrom; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprYieldFrom { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Compare", base = "NodeExpr")] -struct NodeExprCompare; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprCompare { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("left")).into(), - ctx.new_str(ascii!("ops")).into(), - ctx.new_str(ascii!("comparators")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Call", base = "NodeExpr")] -struct NodeExprCall; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprCall { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("func")).into(), - ctx.new_str(ascii!("args")).into(), - ctx.new_str(ascii!("keywords")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "FormattedValue", base = "NodeExpr")] -struct NodeExprFormattedValue; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprFormattedValue { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("value")).into(), - ctx.new_str(ascii!("conversion")).into(), - ctx.new_str(ascii!("format_spec")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "JoinedStr", base = "NodeExpr")] -struct NodeExprJoinedStr; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprJoinedStr { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("values")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Constant", base = "NodeExpr")] -struct NodeExprConstant; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprConstant { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("value")).into(), - ctx.new_str(ascii!("kind")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Attribute", base = "NodeExpr")] -struct NodeExprAttribute; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprAttribute { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("value")).into(), - ctx.new_str(ascii!("attr")).into(), - ctx.new_str(ascii!("ctx")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Subscript", base = "NodeExpr")] -struct NodeExprSubscript; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprSubscript { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("value")).into(), - ctx.new_str(ascii!("slice")).into(), - ctx.new_str(ascii!("ctx")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Starred", base = "NodeExpr")] -struct NodeExprStarred; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprStarred { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("value")).into(), - ctx.new_str(ascii!("ctx")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Name", base = "NodeExpr")] -struct NodeExprName; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprName { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("id")).into(), - ctx.new_str(ascii!("ctx")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "List", base = "NodeExpr")] -struct NodeExprList; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprList { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("elts")).into(), - ctx.new_str(ascii!("ctx")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Tuple", base = "NodeExpr")] -struct NodeExprTuple; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprTuple { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("elts")).into(), - ctx.new_str(ascii!("ctx")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "Slice", base = "NodeExpr")] -struct NodeExprSlice; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprSlice { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("lower")).into(), - ctx.new_str(ascii!("upper")).into(), - ctx.new_str(ascii!("step")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "expr_context", base = "NodeAst")] -struct NodeExprContext; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprContext {} -#[pyclass(module = "_ast", name = "Load", base = "NodeExprContext")] -struct NodeExprContextLoad; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprContextLoad { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Store", base = "NodeExprContext")] -struct NodeExprContextStore; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprContextStore { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Del", base = "NodeExprContext")] -struct NodeExprContextDel; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExprContextDel { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "boolop", base = "NodeAst")] -struct NodeBoolOp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeBoolOp {} -#[pyclass(module = "_ast", name = "And", base = "NodeBoolOp")] -struct NodeBoolOpAnd; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeBoolOpAnd { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Or", base = "NodeBoolOp")] -struct NodeBoolOpOr; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeBoolOpOr { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "operator", base = "NodeAst")] -struct NodeOperator; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperator {} -#[pyclass(module = "_ast", name = "Add", base = "NodeOperator")] -struct NodeOperatorAdd; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorAdd { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Sub", base = "NodeOperator")] -struct NodeOperatorSub; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorSub { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Mult", base = "NodeOperator")] -struct NodeOperatorMult; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorMult { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "MatMult", base = "NodeOperator")] -struct NodeOperatorMatMult; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorMatMult { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Div", base = "NodeOperator")] -struct NodeOperatorDiv; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorDiv { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Mod", base = "NodeOperator")] -struct NodeOperatorMod; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorMod { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Pow", base = "NodeOperator")] -struct NodeOperatorPow; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorPow { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "LShift", base = "NodeOperator")] -struct NodeOperatorLShift; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorLShift { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "RShift", base = "NodeOperator")] -struct NodeOperatorRShift; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorRShift { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "BitOr", base = "NodeOperator")] -struct NodeOperatorBitOr; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorBitOr { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "BitXor", base = "NodeOperator")] -struct NodeOperatorBitXor; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorBitXor { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "BitAnd", base = "NodeOperator")] -struct NodeOperatorBitAnd; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorBitAnd { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "FloorDiv", base = "NodeOperator")] -struct NodeOperatorFloorDiv; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeOperatorFloorDiv { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "unaryop", base = "NodeAst")] -struct NodeUnaryOp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeUnaryOp {} -#[pyclass(module = "_ast", name = "Invert", base = "NodeUnaryOp")] -struct NodeUnaryOpInvert; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeUnaryOpInvert { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Not", base = "NodeUnaryOp")] -struct NodeUnaryOpNot; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeUnaryOpNot { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "UAdd", base = "NodeUnaryOp")] -struct NodeUnaryOpUAdd; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeUnaryOpUAdd { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "USub", base = "NodeUnaryOp")] -struct NodeUnaryOpUSub; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeUnaryOpUSub { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "cmpop", base = "NodeAst")] -struct NodeCmpOp; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOp {} -#[pyclass(module = "_ast", name = "Eq", base = "NodeCmpOp")] -struct NodeCmpOpEq; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpEq { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "NotEq", base = "NodeCmpOp")] -struct NodeCmpOpNotEq; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpNotEq { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Lt", base = "NodeCmpOp")] -struct NodeCmpOpLt; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpLt { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "LtE", base = "NodeCmpOp")] -struct NodeCmpOpLtE; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpLtE { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Gt", base = "NodeCmpOp")] -struct NodeCmpOpGt; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpGt { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "GtE", base = "NodeCmpOp")] -struct NodeCmpOpGtE; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpGtE { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "Is", base = "NodeCmpOp")] -struct NodeCmpOpIs; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpIs { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "IsNot", base = "NodeCmpOp")] -struct NodeCmpOpIsNot; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpIsNot { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "In", base = "NodeCmpOp")] -struct NodeCmpOpIn; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpIn { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "NotIn", base = "NodeCmpOp")] -struct NodeCmpOpNotIn; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeCmpOpNotIn { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "comprehension", base = "NodeAst")] -struct NodeComprehension; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeComprehension { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("target")).into(), - ctx.new_str(ascii!("iter")).into(), - ctx.new_str(ascii!("ifs")).into(), - ctx.new_str(ascii!("is_async")).into(), - ]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "excepthandler", base = "NodeAst")] -struct NodeExceptHandler; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExceptHandler {} -#[pyclass(module = "_ast", name = "ExceptHandler", base = "NodeExceptHandler")] -struct NodeExceptHandlerExceptHandler; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeExceptHandlerExceptHandler { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("type")).into(), - ctx.new_str(ascii!("name")).into(), - ctx.new_str(ascii!("body")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "arguments", base = "NodeAst")] -struct NodeArguments; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeArguments { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("posonlyargs")).into(), - ctx.new_str(ascii!("args")).into(), - ctx.new_str(ascii!("vararg")).into(), - ctx.new_str(ascii!("kwonlyargs")).into(), - ctx.new_str(ascii!("kw_defaults")).into(), - ctx.new_str(ascii!("kwarg")).into(), - ctx.new_str(ascii!("defaults")).into(), - ]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "arg", base = "NodeAst")] -struct NodeArg; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeArg { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("arg")).into(), - ctx.new_str(ascii!("annotation")).into(), - ctx.new_str(ascii!("type_comment")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "keyword", base = "NodeAst")] -struct NodeKeyword; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeKeyword { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("arg")).into(), - ctx.new_str(ascii!("value")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "alias", base = "NodeAst")] -struct NodeAlias; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeAlias { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("name")).into(), - ctx.new_str(ascii!("asname")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "withitem", base = "NodeAst")] -struct NodeWithItem; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeWithItem { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("context_expr")).into(), - ctx.new_str(ascii!("optional_vars")).into(), - ]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "match_case", base = "NodeAst")] -struct NodeMatchCase; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeMatchCase { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("pattern")).into(), - ctx.new_str(ascii!("guard")).into(), - ctx.new_str(ascii!("body")).into(), - ]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "pattern", base = "NodeAst")] -struct NodePattern; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePattern {} -#[pyclass(module = "_ast", name = "MatchValue", base = "NodePattern")] -struct NodePatternMatchValue; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePatternMatchValue { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "MatchSingleton", base = "NodePattern")] -struct NodePatternMatchSingleton; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePatternMatchSingleton { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "MatchSequence", base = "NodePattern")] -struct NodePatternMatchSequence; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePatternMatchSequence { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("patterns")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "MatchMapping", base = "NodePattern")] -struct NodePatternMatchMapping; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePatternMatchMapping { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("keys")).into(), - ctx.new_str(ascii!("patterns")).into(), - ctx.new_str(ascii!("rest")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "MatchClass", base = "NodePattern")] -struct NodePatternMatchClass; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePatternMatchClass { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("cls")).into(), - ctx.new_str(ascii!("patterns")).into(), - ctx.new_str(ascii!("kwd_attrs")).into(), - ctx.new_str(ascii!("kwd_patterns")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "MatchStar", base = "NodePattern")] -struct NodePatternMatchStar; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePatternMatchStar { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("name")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "MatchAs", base = "NodePattern")] -struct NodePatternMatchAs; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePatternMatchAs { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("pattern")).into(), - ctx.new_str(ascii!("name")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "MatchOr", base = "NodePattern")] -struct NodePatternMatchOr; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodePatternMatchOr { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("patterns")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "type_ignore", base = "NodeAst")] -struct NodeTypeIgnore; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeTypeIgnore {} -#[pyclass(module = "_ast", name = "TypeIgnore", base = "NodeTypeIgnore")] -struct NodeTypeIgnoreTypeIgnore; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeTypeIgnoreTypeIgnore { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("tag")).into(), - ]) - .into(), - ); - class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); - } -} -#[pyclass(module = "_ast", name = "type_param", base = "NodeAst")] -struct NodeTypeParam; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeTypeParam {} -#[pyclass(module = "_ast", name = "TypeVar", base = "NodeTypeParam")] -struct NodeTypeParamTypeVar; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeTypeParamTypeVar { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ - ctx.new_str(ascii!("name")).into(), - ctx.new_str(ascii!("bound")).into(), - ]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "ParamSpec", base = "NodeTypeParam")] -struct NodeTypeParamParamSpec; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeTypeParamParamSpec { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("name")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} -#[pyclass(module = "_ast", name = "TypeVarTuple", base = "NodeTypeParam")] -struct NodeTypeParamTypeVarTuple; -#[pyclass(flags(HAS_DICT, BASETYPE))] -impl NodeTypeParamTypeVarTuple { - #[extend_class] - fn extend_class_with_fields(ctx: &Context, class: &'static Py) { - class.set_attr( - identifier!(ctx, _fields), - ctx.new_tuple(vec![ctx.new_str(ascii!("name")).into()]) - .into(), - ); - class.set_attr( - identifier!(ctx, _attributes), - ctx.new_list(vec![ - ctx.new_str(ascii!("lineno")).into(), - ctx.new_str(ascii!("col_offset")).into(), - ctx.new_str(ascii!("end_lineno")).into(), - ctx.new_str(ascii!("end_col_offset")).into(), - ]) - .into(), - ); - } -} - -// sum -impl Node for ast::located::Mod { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - ast::located::Mod::Module(cons) => cons.ast_to_object(vm), - ast::located::Mod::Interactive(cons) => cons.ast_to_object(vm), - ast::located::Mod::Expression(cons) => cons.ast_to_object(vm), - ast::located::Mod::FunctionType(cons) => cons.ast_to_object(vm), - } - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeModModule::static_type()) { - ast::located::Mod::Module(ast::located::ModModule::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeModInteractive::static_type()) { - ast::located::Mod::Interactive(ast::located::ModInteractive::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeModExpression::static_type()) { - ast::located::Mod::Expression(ast::located::ModExpression::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeModFunctionType::static_type()) { - ast::located::Mod::FunctionType(ast::located::ModFunctionType::ast_from_object( - _vm, _object, - )?) - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of mod, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// constructor -impl Node for ast::located::ModModule { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ModModule { - body, - type_ignores, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeModModule::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("type_ignores", type_ignores.ast_to_object(_vm), _vm) - .unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ModModule { - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "Module")?)?, - type_ignores: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "type_ignores", "Module")?, - )?, - range: Default::default(), - }) - } -} -// constructor -impl Node for ast::located::ModInteractive { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ModInteractive { - body, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeModInteractive::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ModInteractive { - body: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "body", "Interactive")?, - )?, - range: Default::default(), - }) - } -} -// constructor -impl Node for ast::located::ModExpression { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ModExpression { - body, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeModExpression::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ModExpression { - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "Expression")?)?, - range: Default::default(), - }) - } -} -// constructor -impl Node for ast::located::ModFunctionType { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ModFunctionType { - argtypes, - returns, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeModFunctionType::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("argtypes", argtypes.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("returns", returns.ast_to_object(_vm), _vm) - .unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ModFunctionType { - argtypes: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "argtypes", "FunctionType")?, - )?, - returns: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "returns", "FunctionType")?, - )?, - range: Default::default(), - }) - } -} -// sum -impl Node for ast::located::Stmt { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - ast::located::Stmt::FunctionDef(cons) => cons.ast_to_object(vm), - ast::located::Stmt::AsyncFunctionDef(cons) => cons.ast_to_object(vm), - ast::located::Stmt::ClassDef(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Return(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Delete(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Assign(cons) => cons.ast_to_object(vm), - ast::located::Stmt::TypeAlias(cons) => cons.ast_to_object(vm), - ast::located::Stmt::AugAssign(cons) => cons.ast_to_object(vm), - ast::located::Stmt::AnnAssign(cons) => cons.ast_to_object(vm), - ast::located::Stmt::For(cons) => cons.ast_to_object(vm), - ast::located::Stmt::AsyncFor(cons) => cons.ast_to_object(vm), - ast::located::Stmt::While(cons) => cons.ast_to_object(vm), - ast::located::Stmt::If(cons) => cons.ast_to_object(vm), - ast::located::Stmt::With(cons) => cons.ast_to_object(vm), - ast::located::Stmt::AsyncWith(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Match(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Raise(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Try(cons) => cons.ast_to_object(vm), - ast::located::Stmt::TryStar(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Assert(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Import(cons) => cons.ast_to_object(vm), - ast::located::Stmt::ImportFrom(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Global(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Nonlocal(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Expr(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Pass(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Break(cons) => cons.ast_to_object(vm), - ast::located::Stmt::Continue(cons) => cons.ast_to_object(vm), - } - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeStmtFunctionDef::static_type()) { - ast::located::Stmt::FunctionDef(ast::located::StmtFunctionDef::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeStmtAsyncFunctionDef::static_type()) { - ast::located::Stmt::AsyncFunctionDef( - ast::located::StmtAsyncFunctionDef::ast_from_object(_vm, _object)?, - ) - } else if _cls.is(NodeStmtClassDef::static_type()) { - ast::located::Stmt::ClassDef(ast::located::StmtClassDef::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtReturn::static_type()) { - ast::located::Stmt::Return(ast::located::StmtReturn::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtDelete::static_type()) { - ast::located::Stmt::Delete(ast::located::StmtDelete::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtAssign::static_type()) { - ast::located::Stmt::Assign(ast::located::StmtAssign::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtTypeAlias::static_type()) { - ast::located::Stmt::TypeAlias(ast::located::StmtTypeAlias::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeStmtAugAssign::static_type()) { - ast::located::Stmt::AugAssign(ast::located::StmtAugAssign::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeStmtAnnAssign::static_type()) { - ast::located::Stmt::AnnAssign(ast::located::StmtAnnAssign::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeStmtFor::static_type()) { - ast::located::Stmt::For(ast::located::StmtFor::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtAsyncFor::static_type()) { - ast::located::Stmt::AsyncFor(ast::located::StmtAsyncFor::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtWhile::static_type()) { - ast::located::Stmt::While(ast::located::StmtWhile::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtIf::static_type()) { - ast::located::Stmt::If(ast::located::StmtIf::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtWith::static_type()) { - ast::located::Stmt::With(ast::located::StmtWith::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtAsyncWith::static_type()) { - ast::located::Stmt::AsyncWith(ast::located::StmtAsyncWith::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeStmtMatch::static_type()) { - ast::located::Stmt::Match(ast::located::StmtMatch::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtRaise::static_type()) { - ast::located::Stmt::Raise(ast::located::StmtRaise::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtTry::static_type()) { - ast::located::Stmt::Try(ast::located::StmtTry::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtTryStar::static_type()) { - ast::located::Stmt::TryStar(ast::located::StmtTryStar::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtAssert::static_type()) { - ast::located::Stmt::Assert(ast::located::StmtAssert::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtImport::static_type()) { - ast::located::Stmt::Import(ast::located::StmtImport::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtImportFrom::static_type()) { - ast::located::Stmt::ImportFrom(ast::located::StmtImportFrom::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeStmtGlobal::static_type()) { - ast::located::Stmt::Global(ast::located::StmtGlobal::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtNonlocal::static_type()) { - ast::located::Stmt::Nonlocal(ast::located::StmtNonlocal::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtExpr::static_type()) { - ast::located::Stmt::Expr(ast::located::StmtExpr::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtPass::static_type()) { - ast::located::Stmt::Pass(ast::located::StmtPass::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtBreak::static_type()) { - ast::located::Stmt::Break(ast::located::StmtBreak::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeStmtContinue::static_type()) { - ast::located::Stmt::Continue(ast::located::StmtContinue::ast_from_object(_vm, _object)?) - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of stmt, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// constructor -impl Node for ast::located::StmtFunctionDef { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtFunctionDef { - name, - args, - body, - decorator_list, - returns, - type_comment, - type_params, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtFunctionDef::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("decorator_list", decorator_list.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("returns", returns.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_params", type_params.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtFunctionDef { - name: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "name", "FunctionDef")?, - )?, - args: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "args", "FunctionDef")?, - )?, - body: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "body", "FunctionDef")?, - )?, - decorator_list: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "decorator_list", "FunctionDef")?, - )?, - returns: get_node_field_opt(_vm, &_object, "returns")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - type_comment: get_node_field_opt(_vm, &_object, "type_comment")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - type_params: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "type_params", "FunctionDef")?, - )?, - range: range_from_object(_vm, _object, "FunctionDef")?, - }) - } -} -// constructor -impl Node for ast::located::StmtAsyncFunctionDef { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtAsyncFunctionDef { - name, - args, - body, - decorator_list, - returns, - type_comment, - type_params, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtAsyncFunctionDef::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("decorator_list", decorator_list.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("returns", returns.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_params", type_params.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtAsyncFunctionDef { - name: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "name", "AsyncFunctionDef")?, - )?, - args: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "args", "AsyncFunctionDef")?, - )?, - body: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "body", "AsyncFunctionDef")?, - )?, - decorator_list: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "decorator_list", "AsyncFunctionDef")?, - )?, - returns: get_node_field_opt(_vm, &_object, "returns")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - type_comment: get_node_field_opt(_vm, &_object, "type_comment")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - type_params: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "type_params", "AsyncFunctionDef")?, - )?, - range: range_from_object(_vm, _object, "AsyncFunctionDef")?, - }) - } -} -// constructor -impl Node for ast::located::StmtClassDef { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtClassDef { - name, - bases, - keywords, - body, - decorator_list, - type_params, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtClassDef::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("bases", bases.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("keywords", keywords.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("decorator_list", decorator_list.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_params", type_params.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtClassDef { - name: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "name", "ClassDef")?)?, - bases: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "bases", "ClassDef")?)?, - keywords: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "keywords", "ClassDef")?, - )?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "ClassDef")?)?, - decorator_list: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "decorator_list", "ClassDef")?, - )?, - type_params: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "type_params", "ClassDef")?, - )?, - range: range_from_object(_vm, _object, "ClassDef")?, - }) - } -} -// constructor -impl Node for ast::located::StmtReturn { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtReturn { - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtReturn::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtReturn { - value: get_node_field_opt(_vm, &_object, "value")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "Return")?, - }) - } -} -// constructor -impl Node for ast::located::StmtDelete { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtDelete { - targets, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtDelete::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("targets", targets.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtDelete { - targets: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "targets", "Delete")?, - )?, - range: range_from_object(_vm, _object, "Delete")?, - }) - } -} -// constructor -impl Node for ast::located::StmtAssign { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtAssign { - targets, - value, - type_comment, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtAssign::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("targets", targets.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtAssign { - targets: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "targets", "Assign")?, - )?, - value: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "value", "Assign")?)?, - type_comment: get_node_field_opt(_vm, &_object, "type_comment")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "Assign")?, - }) - } -} -// constructor -impl Node for ast::located::StmtTypeAlias { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtTypeAlias { - name, - type_params, - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtTypeAlias::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("type_params", type_params.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtTypeAlias { - name: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "name", "TypeAlias")?)?, - type_params: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "type_params", "TypeAlias")?, - )?, - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "TypeAlias")?, - )?, - range: range_from_object(_vm, _object, "TypeAlias")?, - }) - } -} -// constructor -impl Node for ast::located::StmtAugAssign { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtAugAssign { - target, - op, - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtAugAssign::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("target", target.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("op", op.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtAugAssign { - target: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "target", "AugAssign")?, - )?, - op: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "op", "AugAssign")?)?, - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "AugAssign")?, - )?, - range: range_from_object(_vm, _object, "AugAssign")?, - }) - } -} -// constructor -impl Node for ast::located::StmtAnnAssign { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtAnnAssign { - target, - annotation, - value, - simple, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtAnnAssign::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("target", target.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("annotation", annotation.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("simple", simple.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtAnnAssign { - target: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "target", "AnnAssign")?, - )?, - annotation: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "annotation", "AnnAssign")?, - )?, - value: get_node_field_opt(_vm, &_object, "value")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - simple: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "simple", "AnnAssign")?, - )?, - range: range_from_object(_vm, _object, "AnnAssign")?, - }) - } -} -// constructor -impl Node for ast::located::StmtFor { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtFor { - target, - iter, - body, - orelse, - type_comment, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtFor::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("target", target.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("iter", iter.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("orelse", orelse.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtFor { - target: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "target", "For")?)?, - iter: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "iter", "For")?)?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "For")?)?, - orelse: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "orelse", "For")?)?, - type_comment: get_node_field_opt(_vm, &_object, "type_comment")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "For")?, - }) - } -} -// constructor -impl Node for ast::located::StmtAsyncFor { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtAsyncFor { - target, - iter, - body, - orelse, - type_comment, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtAsyncFor::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("target", target.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("iter", iter.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("orelse", orelse.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtAsyncFor { - target: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "target", "AsyncFor")?, - )?, - iter: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "iter", "AsyncFor")?)?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "AsyncFor")?)?, - orelse: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "orelse", "AsyncFor")?, - )?, - type_comment: get_node_field_opt(_vm, &_object, "type_comment")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "AsyncFor")?, - }) - } -} -// constructor -impl Node for ast::located::StmtWhile { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtWhile { - test, - body, - orelse, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtWhile::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("test", test.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("orelse", orelse.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtWhile { - test: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "test", "While")?)?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "While")?)?, - orelse: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "orelse", "While")?)?, - range: range_from_object(_vm, _object, "While")?, - }) - } -} -// constructor -impl Node for ast::located::StmtIf { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtIf { - test, - body, - orelse, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtIf::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("test", test.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("orelse", orelse.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtIf { - test: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "test", "If")?)?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "If")?)?, - orelse: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "orelse", "If")?)?, - range: range_from_object(_vm, _object, "If")?, - }) - } -} -// constructor -impl Node for ast::located::StmtWith { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtWith { - items, - body, - type_comment, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtWith::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("items", items.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtWith { - items: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "items", "With")?)?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "With")?)?, - type_comment: get_node_field_opt(_vm, &_object, "type_comment")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "With")?, - }) - } -} -// constructor -impl Node for ast::located::StmtAsyncWith { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtAsyncWith { - items, - body, - type_comment, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtAsyncWith::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("items", items.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtAsyncWith { - items: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "items", "AsyncWith")?, - )?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "AsyncWith")?)?, - type_comment: get_node_field_opt(_vm, &_object, "type_comment")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "AsyncWith")?, - }) - } -} -// constructor -impl Node for ast::located::StmtMatch { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtMatch { - subject, - cases, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtMatch::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("subject", subject.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("cases", cases.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtMatch { - subject: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "subject", "Match")?, - )?, - cases: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "cases", "Match")?)?, - range: range_from_object(_vm, _object, "Match")?, - }) - } -} -// constructor -impl Node for ast::located::StmtRaise { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtRaise { - exc, - cause, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtRaise::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("exc", exc.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("cause", cause.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtRaise { - exc: get_node_field_opt(_vm, &_object, "exc")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - cause: get_node_field_opt(_vm, &_object, "cause")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "Raise")?, - }) - } -} -// constructor -impl Node for ast::located::StmtTry { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtTry { - body, - handlers, - orelse, - finalbody, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtTry::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("handlers", handlers.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("orelse", orelse.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("finalbody", finalbody.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtTry { - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "Try")?)?, - handlers: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "handlers", "Try")?, - )?, - orelse: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "orelse", "Try")?)?, - finalbody: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "finalbody", "Try")?, - )?, - range: range_from_object(_vm, _object, "Try")?, - }) - } -} -// constructor -impl Node for ast::located::StmtTryStar { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtTryStar { - body, - handlers, - orelse, - finalbody, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtTryStar::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("handlers", handlers.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("orelse", orelse.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("finalbody", finalbody.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtTryStar { - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "TryStar")?)?, - handlers: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "handlers", "TryStar")?, - )?, - orelse: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "orelse", "TryStar")?, - )?, - finalbody: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "finalbody", "TryStar")?, - )?, - range: range_from_object(_vm, _object, "TryStar")?, - }) - } -} -// constructor -impl Node for ast::located::StmtAssert { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtAssert { - test, - msg, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtAssert::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("test", test.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("msg", msg.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtAssert { - test: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "test", "Assert")?)?, - msg: get_node_field_opt(_vm, &_object, "msg")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "Assert")?, - }) - } -} -// constructor -impl Node for ast::located::StmtImport { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtImport { - names, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtImport::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("names", names.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtImport { - names: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "names", "Import")?)?, - range: range_from_object(_vm, _object, "Import")?, - }) - } -} -// constructor -impl Node for ast::located::StmtImportFrom { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtImportFrom { - module, - names, - level, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtImportFrom::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("module", module.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("names", names.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("level", level.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtImportFrom { - module: get_node_field_opt(_vm, &_object, "module")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - names: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "names", "ImportFrom")?, - )?, - level: get_node_field_opt(_vm, &_object, "level")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "ImportFrom")?, - }) - } -} -// constructor -impl Node for ast::located::StmtGlobal { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtGlobal { - names, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtGlobal::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("names", names.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtGlobal { - names: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "names", "Global")?)?, - range: range_from_object(_vm, _object, "Global")?, - }) - } -} -// constructor -impl Node for ast::located::StmtNonlocal { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtNonlocal { - names, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtNonlocal::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("names", names.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtNonlocal { - names: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "names", "Nonlocal")?)?, - range: range_from_object(_vm, _object, "Nonlocal")?, - }) - } -} -// constructor -impl Node for ast::located::StmtExpr { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtExpr { - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtExpr::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtExpr { - value: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "value", "Expr")?)?, - range: range_from_object(_vm, _object, "Expr")?, - }) - } -} -// constructor -impl Node for ast::located::StmtPass { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtPass { range: _range } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtPass::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtPass { - range: range_from_object(_vm, _object, "Pass")?, - }) - } -} -// constructor -impl Node for ast::located::StmtBreak { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtBreak { range: _range } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtBreak::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtBreak { - range: range_from_object(_vm, _object, "Break")?, - }) - } -} -// constructor -impl Node for ast::located::StmtContinue { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::StmtContinue { range: _range } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeStmtContinue::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::StmtContinue { - range: range_from_object(_vm, _object, "Continue")?, - }) - } -} -// sum -impl Node for ast::located::Expr { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - ast::located::Expr::BoolOp(cons) => cons.ast_to_object(vm), - ast::located::Expr::NamedExpr(cons) => cons.ast_to_object(vm), - ast::located::Expr::BinOp(cons) => cons.ast_to_object(vm), - ast::located::Expr::UnaryOp(cons) => cons.ast_to_object(vm), - ast::located::Expr::Lambda(cons) => cons.ast_to_object(vm), - ast::located::Expr::IfExp(cons) => cons.ast_to_object(vm), - ast::located::Expr::Dict(cons) => cons.ast_to_object(vm), - ast::located::Expr::Set(cons) => cons.ast_to_object(vm), - ast::located::Expr::ListComp(cons) => cons.ast_to_object(vm), - ast::located::Expr::SetComp(cons) => cons.ast_to_object(vm), - ast::located::Expr::DictComp(cons) => cons.ast_to_object(vm), - ast::located::Expr::GeneratorExp(cons) => cons.ast_to_object(vm), - ast::located::Expr::Await(cons) => cons.ast_to_object(vm), - ast::located::Expr::Yield(cons) => cons.ast_to_object(vm), - ast::located::Expr::YieldFrom(cons) => cons.ast_to_object(vm), - ast::located::Expr::Compare(cons) => cons.ast_to_object(vm), - ast::located::Expr::Call(cons) => cons.ast_to_object(vm), - ast::located::Expr::FormattedValue(cons) => cons.ast_to_object(vm), - ast::located::Expr::JoinedStr(cons) => cons.ast_to_object(vm), - ast::located::Expr::Constant(cons) => cons.ast_to_object(vm), - ast::located::Expr::Attribute(cons) => cons.ast_to_object(vm), - ast::located::Expr::Subscript(cons) => cons.ast_to_object(vm), - ast::located::Expr::Starred(cons) => cons.ast_to_object(vm), - ast::located::Expr::Name(cons) => cons.ast_to_object(vm), - ast::located::Expr::List(cons) => cons.ast_to_object(vm), - ast::located::Expr::Tuple(cons) => cons.ast_to_object(vm), - ast::located::Expr::Slice(cons) => cons.ast_to_object(vm), - } - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeExprBoolOp::static_type()) { - ast::located::Expr::BoolOp(ast::located::ExprBoolOp::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprNamedExpr::static_type()) { - ast::located::Expr::NamedExpr(ast::located::ExprNamedExpr::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeExprBinOp::static_type()) { - ast::located::Expr::BinOp(ast::located::ExprBinOp::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprUnaryOp::static_type()) { - ast::located::Expr::UnaryOp(ast::located::ExprUnaryOp::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprLambda::static_type()) { - ast::located::Expr::Lambda(ast::located::ExprLambda::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprIfExp::static_type()) { - ast::located::Expr::IfExp(ast::located::ExprIfExp::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprDict::static_type()) { - ast::located::Expr::Dict(ast::located::ExprDict::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprSet::static_type()) { - ast::located::Expr::Set(ast::located::ExprSet::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprListComp::static_type()) { - ast::located::Expr::ListComp(ast::located::ExprListComp::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprSetComp::static_type()) { - ast::located::Expr::SetComp(ast::located::ExprSetComp::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprDictComp::static_type()) { - ast::located::Expr::DictComp(ast::located::ExprDictComp::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprGeneratorExp::static_type()) { - ast::located::Expr::GeneratorExp(ast::located::ExprGeneratorExp::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeExprAwait::static_type()) { - ast::located::Expr::Await(ast::located::ExprAwait::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprYield::static_type()) { - ast::located::Expr::Yield(ast::located::ExprYield::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprYieldFrom::static_type()) { - ast::located::Expr::YieldFrom(ast::located::ExprYieldFrom::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeExprCompare::static_type()) { - ast::located::Expr::Compare(ast::located::ExprCompare::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprCall::static_type()) { - ast::located::Expr::Call(ast::located::ExprCall::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprFormattedValue::static_type()) { - ast::located::Expr::FormattedValue(ast::located::ExprFormattedValue::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeExprJoinedStr::static_type()) { - ast::located::Expr::JoinedStr(ast::located::ExprJoinedStr::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeExprConstant::static_type()) { - ast::located::Expr::Constant(ast::located::ExprConstant::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprAttribute::static_type()) { - ast::located::Expr::Attribute(ast::located::ExprAttribute::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeExprSubscript::static_type()) { - ast::located::Expr::Subscript(ast::located::ExprSubscript::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeExprStarred::static_type()) { - ast::located::Expr::Starred(ast::located::ExprStarred::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprName::static_type()) { - ast::located::Expr::Name(ast::located::ExprName::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprList::static_type()) { - ast::located::Expr::List(ast::located::ExprList::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprTuple::static_type()) { - ast::located::Expr::Tuple(ast::located::ExprTuple::ast_from_object(_vm, _object)?) - } else if _cls.is(NodeExprSlice::static_type()) { - ast::located::Expr::Slice(ast::located::ExprSlice::ast_from_object(_vm, _object)?) - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of expr, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// constructor -impl Node for ast::located::ExprBoolOp { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprBoolOp { - op, - values, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprBoolOp::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("op", op.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("values", values.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprBoolOp { - op: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "op", "BoolOp")?)?, - values: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "values", "BoolOp")?)?, - range: range_from_object(_vm, _object, "BoolOp")?, - }) - } -} -// constructor -impl Node for ast::located::ExprNamedExpr { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprNamedExpr { - target, - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprNamedExpr::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("target", target.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprNamedExpr { - target: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "target", "NamedExpr")?, - )?, - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "NamedExpr")?, - )?, - range: range_from_object(_vm, _object, "NamedExpr")?, - }) - } -} -// constructor -impl Node for ast::located::ExprBinOp { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprBinOp { - left, - op, - right, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprBinOp::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("left", left.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("op", op.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("right", right.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprBinOp { - left: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "left", "BinOp")?)?, - op: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "op", "BinOp")?)?, - right: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "right", "BinOp")?)?, - range: range_from_object(_vm, _object, "BinOp")?, - }) - } -} -// constructor -impl Node for ast::located::ExprUnaryOp { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprUnaryOp { - op, - operand, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprUnaryOp::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("op", op.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("operand", operand.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprUnaryOp { - op: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "op", "UnaryOp")?)?, - operand: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "operand", "UnaryOp")?, - )?, - range: range_from_object(_vm, _object, "UnaryOp")?, - }) - } -} -// constructor -impl Node for ast::located::ExprLambda { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprLambda { - args, - body, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprLambda::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprLambda { - args: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "args", "Lambda")?)?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "Lambda")?)?, - range: range_from_object(_vm, _object, "Lambda")?, - }) - } -} -// constructor -impl Node for ast::located::ExprIfExp { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprIfExp { - test, - body, - orelse, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprIfExp::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("test", test.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("orelse", orelse.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprIfExp { - test: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "test", "IfExp")?)?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "IfExp")?)?, - orelse: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "orelse", "IfExp")?)?, - range: range_from_object(_vm, _object, "IfExp")?, - }) - } -} -// constructor -impl Node for ast::located::ExprDict { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprDict { - keys, - values, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprDict::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("keys", keys.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("values", values.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprDict { - keys: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "keys", "Dict")?)?, - values: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "values", "Dict")?)?, - range: range_from_object(_vm, _object, "Dict")?, - }) - } -} -// constructor -impl Node for ast::located::ExprSet { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprSet { - elts, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprSet::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("elts", elts.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprSet { - elts: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "elts", "Set")?)?, - range: range_from_object(_vm, _object, "Set")?, - }) - } -} -// constructor -impl Node for ast::located::ExprListComp { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprListComp { - elt, - generators, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprListComp::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("elt", elt.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("generators", generators.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprListComp { - elt: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "elt", "ListComp")?)?, - generators: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "generators", "ListComp")?, - )?, - range: range_from_object(_vm, _object, "ListComp")?, - }) - } -} -// constructor -impl Node for ast::located::ExprSetComp { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprSetComp { - elt, - generators, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprSetComp::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("elt", elt.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("generators", generators.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprSetComp { - elt: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "elt", "SetComp")?)?, - generators: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "generators", "SetComp")?, - )?, - range: range_from_object(_vm, _object, "SetComp")?, - }) - } -} -// constructor -impl Node for ast::located::ExprDictComp { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprDictComp { - key, - value, - generators, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprDictComp::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("key", key.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("generators", generators.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprDictComp { - key: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "key", "DictComp")?)?, - value: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "value", "DictComp")?)?, - generators: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "generators", "DictComp")?, - )?, - range: range_from_object(_vm, _object, "DictComp")?, - }) - } -} -// constructor -impl Node for ast::located::ExprGeneratorExp { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprGeneratorExp { - elt, - generators, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprGeneratorExp::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("elt", elt.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("generators", generators.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprGeneratorExp { - elt: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "elt", "GeneratorExp")?)?, - generators: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "generators", "GeneratorExp")?, - )?, - range: range_from_object(_vm, _object, "GeneratorExp")?, - }) - } -} -// constructor -impl Node for ast::located::ExprAwait { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprAwait { - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprAwait::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprAwait { - value: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "value", "Await")?)?, - range: range_from_object(_vm, _object, "Await")?, - }) - } -} -// constructor -impl Node for ast::located::ExprYield { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprYield { - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprYield::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprYield { - value: get_node_field_opt(_vm, &_object, "value")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "Yield")?, - }) - } -} -// constructor -impl Node for ast::located::ExprYieldFrom { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprYieldFrom { - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprYieldFrom::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprYieldFrom { - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "YieldFrom")?, - )?, - range: range_from_object(_vm, _object, "YieldFrom")?, - }) - } -} -// constructor -impl Node for ast::located::ExprCompare { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprCompare { - left, - ops, - comparators, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprCompare::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("left", left.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("ops", ops.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("comparators", comparators.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprCompare { - left: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "left", "Compare")?)?, - ops: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "ops", "Compare")?)?, - comparators: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "comparators", "Compare")?, - )?, - range: range_from_object(_vm, _object, "Compare")?, - }) - } -} -// constructor -impl Node for ast::located::ExprCall { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprCall { - func, - args, - keywords, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprCall::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("func", func.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("keywords", keywords.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprCall { - func: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "func", "Call")?)?, - args: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "args", "Call")?)?, - keywords: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "keywords", "Call")?, - )?, - range: range_from_object(_vm, _object, "Call")?, - }) - } -} -// constructor -impl Node for ast::located::ExprFormattedValue { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprFormattedValue { - value, - conversion, - format_spec, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprFormattedValue::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("conversion", conversion.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("format_spec", format_spec.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprFormattedValue { - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "FormattedValue")?, - )?, - conversion: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "conversion", "FormattedValue")?, - )?, - format_spec: get_node_field_opt(_vm, &_object, "format_spec")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "FormattedValue")?, - }) - } -} -// constructor -impl Node for ast::located::ExprJoinedStr { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprJoinedStr { - values, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprJoinedStr::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("values", values.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprJoinedStr { - values: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "values", "JoinedStr")?, - )?, - range: range_from_object(_vm, _object, "JoinedStr")?, - }) - } -} -// constructor -impl Node for ast::located::ExprConstant { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprConstant { - value, - kind, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprConstant::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("kind", kind.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprConstant { - value: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "value", "Constant")?)?, - kind: get_node_field_opt(_vm, &_object, "kind")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "Constant")?, - }) - } -} -// constructor -impl Node for ast::located::ExprAttribute { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprAttribute { - value, - attr, - ctx, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprAttribute::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("attr", attr.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprAttribute { - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "Attribute")?, - )?, - attr: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "attr", "Attribute")?)?, - ctx: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "ctx", "Attribute")?)?, - range: range_from_object(_vm, _object, "Attribute")?, - }) - } -} -// constructor -impl Node for ast::located::ExprSubscript { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprSubscript { - value, - slice, - ctx, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprSubscript::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("slice", slice.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprSubscript { - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "Subscript")?, - )?, - slice: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "slice", "Subscript")?, - )?, - ctx: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "ctx", "Subscript")?)?, - range: range_from_object(_vm, _object, "Subscript")?, - }) - } -} -// constructor -impl Node for ast::located::ExprStarred { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprStarred { - value, - ctx, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprStarred::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprStarred { - value: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "value", "Starred")?)?, - ctx: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "ctx", "Starred")?)?, - range: range_from_object(_vm, _object, "Starred")?, - }) - } -} -// constructor -impl Node for ast::located::ExprName { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprName { - id, - ctx, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprName::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("id", id.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprName { - id: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "id", "Name")?)?, - ctx: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "ctx", "Name")?)?, - range: range_from_object(_vm, _object, "Name")?, - }) - } -} -// constructor -impl Node for ast::located::ExprList { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprList { - elts, - ctx, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprList::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("elts", elts.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprList { - elts: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "elts", "List")?)?, - ctx: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "ctx", "List")?)?, - range: range_from_object(_vm, _object, "List")?, - }) - } -} -// constructor -impl Node for ast::located::ExprTuple { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprTuple { - elts, - ctx, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprTuple::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("elts", elts.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("ctx", ctx.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprTuple { - elts: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "elts", "Tuple")?)?, - ctx: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "ctx", "Tuple")?)?, - range: range_from_object(_vm, _object, "Tuple")?, - }) - } -} -// constructor -impl Node for ast::located::ExprSlice { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExprSlice { - lower, - upper, - step, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeExprSlice::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("lower", lower.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("upper", upper.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("step", step.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExprSlice { - lower: get_node_field_opt(_vm, &_object, "lower")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - upper: get_node_field_opt(_vm, &_object, "upper")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - step: get_node_field_opt(_vm, &_object, "step")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "Slice")?, - }) - } -} -// sum -impl Node for ast::located::ExprContext { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - let node_type = match self { - ast::located::ExprContext::Load => NodeExprContextLoad::static_type(), - ast::located::ExprContext::Store => NodeExprContextStore::static_type(), - ast::located::ExprContext::Del => NodeExprContextDel::static_type(), - }; - NodeAst - .into_ref_with_type(vm, node_type.to_owned()) - .unwrap() - .into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeExprContextLoad::static_type()) { - ast::located::ExprContext::Load - } else if _cls.is(NodeExprContextStore::static_type()) { - ast::located::ExprContext::Store - } else if _cls.is(NodeExprContextDel::static_type()) { - ast::located::ExprContext::Del - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of expr_context, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// sum -impl Node for ast::located::BoolOp { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - let node_type = match self { - ast::located::BoolOp::And => NodeBoolOpAnd::static_type(), - ast::located::BoolOp::Or => NodeBoolOpOr::static_type(), - }; - NodeAst - .into_ref_with_type(vm, node_type.to_owned()) - .unwrap() - .into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeBoolOpAnd::static_type()) { - ast::located::BoolOp::And - } else if _cls.is(NodeBoolOpOr::static_type()) { - ast::located::BoolOp::Or - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of boolop, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// sum -impl Node for ast::located::Operator { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - let node_type = match self { - ast::located::Operator::Add => NodeOperatorAdd::static_type(), - ast::located::Operator::Sub => NodeOperatorSub::static_type(), - ast::located::Operator::Mult => NodeOperatorMult::static_type(), - ast::located::Operator::MatMult => NodeOperatorMatMult::static_type(), - ast::located::Operator::Div => NodeOperatorDiv::static_type(), - ast::located::Operator::Mod => NodeOperatorMod::static_type(), - ast::located::Operator::Pow => NodeOperatorPow::static_type(), - ast::located::Operator::LShift => NodeOperatorLShift::static_type(), - ast::located::Operator::RShift => NodeOperatorRShift::static_type(), - ast::located::Operator::BitOr => NodeOperatorBitOr::static_type(), - ast::located::Operator::BitXor => NodeOperatorBitXor::static_type(), - ast::located::Operator::BitAnd => NodeOperatorBitAnd::static_type(), - ast::located::Operator::FloorDiv => NodeOperatorFloorDiv::static_type(), - }; - NodeAst - .into_ref_with_type(vm, node_type.to_owned()) - .unwrap() - .into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeOperatorAdd::static_type()) { - ast::located::Operator::Add - } else if _cls.is(NodeOperatorSub::static_type()) { - ast::located::Operator::Sub - } else if _cls.is(NodeOperatorMult::static_type()) { - ast::located::Operator::Mult - } else if _cls.is(NodeOperatorMatMult::static_type()) { - ast::located::Operator::MatMult - } else if _cls.is(NodeOperatorDiv::static_type()) { - ast::located::Operator::Div - } else if _cls.is(NodeOperatorMod::static_type()) { - ast::located::Operator::Mod - } else if _cls.is(NodeOperatorPow::static_type()) { - ast::located::Operator::Pow - } else if _cls.is(NodeOperatorLShift::static_type()) { - ast::located::Operator::LShift - } else if _cls.is(NodeOperatorRShift::static_type()) { - ast::located::Operator::RShift - } else if _cls.is(NodeOperatorBitOr::static_type()) { - ast::located::Operator::BitOr - } else if _cls.is(NodeOperatorBitXor::static_type()) { - ast::located::Operator::BitXor - } else if _cls.is(NodeOperatorBitAnd::static_type()) { - ast::located::Operator::BitAnd - } else if _cls.is(NodeOperatorFloorDiv::static_type()) { - ast::located::Operator::FloorDiv - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of operator, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// sum -impl Node for ast::located::UnaryOp { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - let node_type = match self { - ast::located::UnaryOp::Invert => NodeUnaryOpInvert::static_type(), - ast::located::UnaryOp::Not => NodeUnaryOpNot::static_type(), - ast::located::UnaryOp::UAdd => NodeUnaryOpUAdd::static_type(), - ast::located::UnaryOp::USub => NodeUnaryOpUSub::static_type(), - }; - NodeAst - .into_ref_with_type(vm, node_type.to_owned()) - .unwrap() - .into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeUnaryOpInvert::static_type()) { - ast::located::UnaryOp::Invert - } else if _cls.is(NodeUnaryOpNot::static_type()) { - ast::located::UnaryOp::Not - } else if _cls.is(NodeUnaryOpUAdd::static_type()) { - ast::located::UnaryOp::UAdd - } else if _cls.is(NodeUnaryOpUSub::static_type()) { - ast::located::UnaryOp::USub - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of unaryop, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// sum -impl Node for ast::located::CmpOp { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - let node_type = match self { - ast::located::CmpOp::Eq => NodeCmpOpEq::static_type(), - ast::located::CmpOp::NotEq => NodeCmpOpNotEq::static_type(), - ast::located::CmpOp::Lt => NodeCmpOpLt::static_type(), - ast::located::CmpOp::LtE => NodeCmpOpLtE::static_type(), - ast::located::CmpOp::Gt => NodeCmpOpGt::static_type(), - ast::located::CmpOp::GtE => NodeCmpOpGtE::static_type(), - ast::located::CmpOp::Is => NodeCmpOpIs::static_type(), - ast::located::CmpOp::IsNot => NodeCmpOpIsNot::static_type(), - ast::located::CmpOp::In => NodeCmpOpIn::static_type(), - ast::located::CmpOp::NotIn => NodeCmpOpNotIn::static_type(), - }; - NodeAst - .into_ref_with_type(vm, node_type.to_owned()) - .unwrap() - .into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeCmpOpEq::static_type()) { - ast::located::CmpOp::Eq - } else if _cls.is(NodeCmpOpNotEq::static_type()) { - ast::located::CmpOp::NotEq - } else if _cls.is(NodeCmpOpLt::static_type()) { - ast::located::CmpOp::Lt - } else if _cls.is(NodeCmpOpLtE::static_type()) { - ast::located::CmpOp::LtE - } else if _cls.is(NodeCmpOpGt::static_type()) { - ast::located::CmpOp::Gt - } else if _cls.is(NodeCmpOpGtE::static_type()) { - ast::located::CmpOp::GtE - } else if _cls.is(NodeCmpOpIs::static_type()) { - ast::located::CmpOp::Is - } else if _cls.is(NodeCmpOpIsNot::static_type()) { - ast::located::CmpOp::IsNot - } else if _cls.is(NodeCmpOpIn::static_type()) { - ast::located::CmpOp::In - } else if _cls.is(NodeCmpOpNotIn::static_type()) { - ast::located::CmpOp::NotIn - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of cmpop, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// product -impl Node for ast::located::Comprehension { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::Comprehension { - target, - iter, - ifs, - is_async, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeComprehension::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("target", target.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("iter", iter.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("ifs", ifs.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("is_async", is_async.ast_to_object(_vm), _vm) - .unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::Comprehension { - target: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "target", "comprehension")?, - )?, - iter: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "iter", "comprehension")?, - )?, - ifs: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "ifs", "comprehension")?, - )?, - is_async: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "is_async", "comprehension")?, - )?, - range: Default::default(), - }) - } -} -// sum -impl Node for ast::located::ExceptHandler { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - ast::located::ExceptHandler::ExceptHandler(cons) => cons.ast_to_object(vm), - } - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeExceptHandlerExceptHandler::static_type()) { - ast::located::ExceptHandler::ExceptHandler( - ast::located::ExceptHandlerExceptHandler::ast_from_object(_vm, _object)?, - ) - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of excepthandler, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// constructor -impl Node for ast::located::ExceptHandlerExceptHandler { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::ExceptHandlerExceptHandler { - type_, - name, - body, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type( - _vm, - NodeExceptHandlerExceptHandler::static_type().to_owned(), - ) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("type", type_.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::ExceptHandlerExceptHandler { - type_: get_node_field_opt(_vm, &_object, "type")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - name: get_node_field_opt(_vm, &_object, "name")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - body: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "body", "ExceptHandler")?, - )?, - range: range_from_object(_vm, _object, "ExceptHandler")?, - }) - } -} -// product -impl Node for ast::located::PythonArguments { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PythonArguments { - posonlyargs, - args, - vararg, - kwonlyargs, - kw_defaults, - kwarg, - defaults, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeArguments::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("posonlyargs", posonlyargs.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("args", args.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("vararg", vararg.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("kwonlyargs", kwonlyargs.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("kw_defaults", kw_defaults.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("kwarg", kwarg.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("defaults", defaults.ast_to_object(_vm), _vm) - .unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PythonArguments { - posonlyargs: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "posonlyargs", "arguments")?, - )?, - args: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "args", "arguments")?)?, - vararg: get_node_field_opt(_vm, &_object, "vararg")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - kwonlyargs: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "kwonlyargs", "arguments")?, - )?, - kw_defaults: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "kw_defaults", "arguments")?, - )?, - kwarg: get_node_field_opt(_vm, &_object, "kwarg")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - defaults: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "defaults", "arguments")?, - )?, - range: Default::default(), - }) - } -} -// product -impl Node for ast::located::Arg { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::Arg { - arg, - annotation, - type_comment, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeArg::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("arg", arg.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("annotation", annotation.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::Arg { - arg: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "arg", "arg")?)?, - annotation: get_node_field_opt(_vm, &_object, "annotation")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - type_comment: get_node_field_opt(_vm, &_object, "type_comment")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "arg")?, - }) - } -} -// product -impl Node for ast::located::Keyword { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::Keyword { - arg, - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeKeyword::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("arg", arg.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::Keyword { - arg: get_node_field_opt(_vm, &_object, "arg")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - value: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "value", "keyword")?)?, - range: range_from_object(_vm, _object, "keyword")?, - }) - } -} -// product -impl Node for ast::located::Alias { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::Alias { - name, - asname, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeAlias::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("asname", asname.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::Alias { - name: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "name", "alias")?)?, - asname: get_node_field_opt(_vm, &_object, "asname")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "alias")?, - }) - } -} -// product -impl Node for ast::located::WithItem { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::WithItem { - context_expr, - optional_vars, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeWithItem::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("context_expr", context_expr.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("optional_vars", optional_vars.ast_to_object(_vm), _vm) - .unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::WithItem { - context_expr: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "context_expr", "withitem")?, - )?, - optional_vars: get_node_field_opt(_vm, &_object, "optional_vars")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: Default::default(), - }) - } -} -// product -impl Node for ast::located::MatchCase { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::MatchCase { - pattern, - guard, - body, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeMatchCase::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("pattern", pattern.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("guard", guard.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("body", body.ast_to_object(_vm), _vm).unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::MatchCase { - pattern: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "pattern", "match_case")?, - )?, - guard: get_node_field_opt(_vm, &_object, "guard")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - body: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "body", "match_case")?)?, - range: Default::default(), - }) - } -} -// sum -impl Node for ast::located::Pattern { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - ast::located::Pattern::MatchValue(cons) => cons.ast_to_object(vm), - ast::located::Pattern::MatchSingleton(cons) => cons.ast_to_object(vm), - ast::located::Pattern::MatchSequence(cons) => cons.ast_to_object(vm), - ast::located::Pattern::MatchMapping(cons) => cons.ast_to_object(vm), - ast::located::Pattern::MatchClass(cons) => cons.ast_to_object(vm), - ast::located::Pattern::MatchStar(cons) => cons.ast_to_object(vm), - ast::located::Pattern::MatchAs(cons) => cons.ast_to_object(vm), - ast::located::Pattern::MatchOr(cons) => cons.ast_to_object(vm), - } - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodePatternMatchValue::static_type()) { - ast::located::Pattern::MatchValue(ast::located::PatternMatchValue::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodePatternMatchSingleton::static_type()) { - ast::located::Pattern::MatchSingleton( - ast::located::PatternMatchSingleton::ast_from_object(_vm, _object)?, - ) - } else if _cls.is(NodePatternMatchSequence::static_type()) { - ast::located::Pattern::MatchSequence( - ast::located::PatternMatchSequence::ast_from_object(_vm, _object)?, - ) - } else if _cls.is(NodePatternMatchMapping::static_type()) { - ast::located::Pattern::MatchMapping(ast::located::PatternMatchMapping::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodePatternMatchClass::static_type()) { - ast::located::Pattern::MatchClass(ast::located::PatternMatchClass::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodePatternMatchStar::static_type()) { - ast::located::Pattern::MatchStar(ast::located::PatternMatchStar::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodePatternMatchAs::static_type()) { - ast::located::Pattern::MatchAs(ast::located::PatternMatchAs::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodePatternMatchOr::static_type()) { - ast::located::Pattern::MatchOr(ast::located::PatternMatchOr::ast_from_object( - _vm, _object, - )?) - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of pattern, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// constructor -impl Node for ast::located::PatternMatchValue { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PatternMatchValue { - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodePatternMatchValue::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PatternMatchValue { - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "MatchValue")?, - )?, - range: range_from_object(_vm, _object, "MatchValue")?, - }) - } -} -// constructor -impl Node for ast::located::PatternMatchSingleton { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PatternMatchSingleton { - value, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodePatternMatchSingleton::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("value", value.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PatternMatchSingleton { - value: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "value", "MatchSingleton")?, - )?, - range: range_from_object(_vm, _object, "MatchSingleton")?, - }) - } -} -// constructor -impl Node for ast::located::PatternMatchSequence { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PatternMatchSequence { - patterns, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodePatternMatchSequence::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("patterns", patterns.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PatternMatchSequence { - patterns: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "patterns", "MatchSequence")?, - )?, - range: range_from_object(_vm, _object, "MatchSequence")?, - }) - } -} -// constructor -impl Node for ast::located::PatternMatchMapping { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PatternMatchMapping { - keys, - patterns, - rest, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodePatternMatchMapping::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("keys", keys.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("patterns", patterns.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("rest", rest.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PatternMatchMapping { - keys: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "keys", "MatchMapping")?, - )?, - patterns: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "patterns", "MatchMapping")?, - )?, - rest: get_node_field_opt(_vm, &_object, "rest")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "MatchMapping")?, - }) - } -} -// constructor -impl Node for ast::located::PatternMatchClass { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PatternMatchClass { - cls, - patterns, - kwd_attrs, - kwd_patterns, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodePatternMatchClass::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("cls", cls.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("patterns", patterns.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("kwd_attrs", kwd_attrs.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("kwd_patterns", kwd_patterns.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PatternMatchClass { - cls: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "cls", "MatchClass")?)?, - patterns: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "patterns", "MatchClass")?, - )?, - kwd_attrs: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "kwd_attrs", "MatchClass")?, - )?, - kwd_patterns: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "kwd_patterns", "MatchClass")?, - )?, - range: range_from_object(_vm, _object, "MatchClass")?, - }) - } -} -// constructor -impl Node for ast::located::PatternMatchStar { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PatternMatchStar { - name, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodePatternMatchStar::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PatternMatchStar { - name: get_node_field_opt(_vm, &_object, "name")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "MatchStar")?, - }) - } -} -// constructor -impl Node for ast::located::PatternMatchAs { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PatternMatchAs { - pattern, - name, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodePatternMatchAs::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("pattern", pattern.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PatternMatchAs { - pattern: get_node_field_opt(_vm, &_object, "pattern")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - name: get_node_field_opt(_vm, &_object, "name")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "MatchAs")?, - }) - } -} -// constructor -impl Node for ast::located::PatternMatchOr { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::PatternMatchOr { - patterns, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodePatternMatchOr::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("patterns", patterns.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::PatternMatchOr { - patterns: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "patterns", "MatchOr")?, - )?, - range: range_from_object(_vm, _object, "MatchOr")?, - }) - } -} -// sum -impl Node for ast::located::TypeIgnore { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - ast::located::TypeIgnore::TypeIgnore(cons) => cons.ast_to_object(vm), - } - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeTypeIgnoreTypeIgnore::static_type()) { - ast::located::TypeIgnore::TypeIgnore( - ast::located::TypeIgnoreTypeIgnore::ast_from_object(_vm, _object)?, - ) - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of type_ignore, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// constructor -impl Node for ast::located::TypeIgnoreTypeIgnore { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::TypeIgnoreTypeIgnore { - lineno, - tag, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeTypeIgnoreTypeIgnore::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("lineno", lineno.ast_to_object(_vm), _vm) - .unwrap(); - dict.set_item("tag", tag.ast_to_object(_vm), _vm).unwrap(); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::TypeIgnoreTypeIgnore { - lineno: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "lineno", "TypeIgnore")?, - )?, - tag: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "tag", "TypeIgnore")?)?, - range: Default::default(), - }) - } -} -// sum -impl Node for ast::located::TypeParam { - fn ast_to_object(self, vm: &VirtualMachine) -> PyObjectRef { - match self { - ast::located::TypeParam::TypeVar(cons) => cons.ast_to_object(vm), - ast::located::TypeParam::ParamSpec(cons) => cons.ast_to_object(vm), - ast::located::TypeParam::TypeVarTuple(cons) => cons.ast_to_object(vm), - } - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - let _cls = _object.class(); - Ok(if _cls.is(NodeTypeParamTypeVar::static_type()) { - ast::located::TypeParam::TypeVar(ast::located::TypeParamTypeVar::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeTypeParamParamSpec::static_type()) { - ast::located::TypeParam::ParamSpec(ast::located::TypeParamParamSpec::ast_from_object( - _vm, _object, - )?) - } else if _cls.is(NodeTypeParamTypeVarTuple::static_type()) { - ast::located::TypeParam::TypeVarTuple( - ast::located::TypeParamTypeVarTuple::ast_from_object(_vm, _object)?, - ) - } else { - return Err(_vm.new_type_error(format!( - "expected some sort of type_param, but got {}", - _object.repr(_vm)? - ))); - }) - } -} -// constructor -impl Node for ast::located::TypeParamTypeVar { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::TypeParamTypeVar { - name, - bound, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeTypeParamTypeVar::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - dict.set_item("bound", bound.ast_to_object(_vm), _vm) - .unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::TypeParamTypeVar { - name: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "name", "TypeVar")?)?, - bound: get_node_field_opt(_vm, &_object, "bound")? - .map(|obj| Node::ast_from_object(_vm, obj)) - .transpose()?, - range: range_from_object(_vm, _object, "TypeVar")?, - }) - } -} -// constructor -impl Node for ast::located::TypeParamParamSpec { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::TypeParamParamSpec { - name, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeTypeParamParamSpec::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::TypeParamParamSpec { - name: Node::ast_from_object(_vm, get_node_field(_vm, &_object, "name", "ParamSpec")?)?, - range: range_from_object(_vm, _object, "ParamSpec")?, - }) - } -} -// constructor -impl Node for ast::located::TypeParamTypeVarTuple { - fn ast_to_object(self, _vm: &VirtualMachine) -> PyObjectRef { - let ast::located::TypeParamTypeVarTuple { - name, - range: _range, - } = self; - let node = NodeAst - .into_ref_with_type(_vm, NodeTypeParamTypeVarTuple::static_type().to_owned()) - .unwrap(); - let dict = node.as_object().dict().unwrap(); - dict.set_item("name", name.ast_to_object(_vm), _vm).unwrap(); - node_add_location(&dict, _range, _vm); - node.into() - } - fn ast_from_object(_vm: &VirtualMachine, _object: PyObjectRef) -> PyResult { - Ok(ast::located::TypeParamTypeVarTuple { - name: Node::ast_from_object( - _vm, - get_node_field(_vm, &_object, "name", "TypeVarTuple")?, - )?, - range: range_from_object(_vm, _object, "TypeVarTuple")?, - }) - } -} - -pub fn extend_module_nodes(vm: &VirtualMachine, module: &Py) { - extend_module!(vm, module, { - "mod" => NodeMod::make_class(&vm.ctx), - "Module" => NodeModModule::make_class(&vm.ctx), - "Interactive" => NodeModInteractive::make_class(&vm.ctx), - "Expression" => NodeModExpression::make_class(&vm.ctx), - "FunctionType" => NodeModFunctionType::make_class(&vm.ctx), - "stmt" => NodeStmt::make_class(&vm.ctx), - "FunctionDef" => NodeStmtFunctionDef::make_class(&vm.ctx), - "AsyncFunctionDef" => NodeStmtAsyncFunctionDef::make_class(&vm.ctx), - "ClassDef" => NodeStmtClassDef::make_class(&vm.ctx), - "Return" => NodeStmtReturn::make_class(&vm.ctx), - "Delete" => NodeStmtDelete::make_class(&vm.ctx), - "Assign" => NodeStmtAssign::make_class(&vm.ctx), - "TypeAlias" => NodeStmtTypeAlias::make_class(&vm.ctx), - "AugAssign" => NodeStmtAugAssign::make_class(&vm.ctx), - "AnnAssign" => NodeStmtAnnAssign::make_class(&vm.ctx), - "For" => NodeStmtFor::make_class(&vm.ctx), - "AsyncFor" => NodeStmtAsyncFor::make_class(&vm.ctx), - "While" => NodeStmtWhile::make_class(&vm.ctx), - "If" => NodeStmtIf::make_class(&vm.ctx), - "With" => NodeStmtWith::make_class(&vm.ctx), - "AsyncWith" => NodeStmtAsyncWith::make_class(&vm.ctx), - "Match" => NodeStmtMatch::make_class(&vm.ctx), - "Raise" => NodeStmtRaise::make_class(&vm.ctx), - "Try" => NodeStmtTry::make_class(&vm.ctx), - "TryStar" => NodeStmtTryStar::make_class(&vm.ctx), - "Assert" => NodeStmtAssert::make_class(&vm.ctx), - "Import" => NodeStmtImport::make_class(&vm.ctx), - "ImportFrom" => NodeStmtImportFrom::make_class(&vm.ctx), - "Global" => NodeStmtGlobal::make_class(&vm.ctx), - "Nonlocal" => NodeStmtNonlocal::make_class(&vm.ctx), - "Expr" => NodeStmtExpr::make_class(&vm.ctx), - "Pass" => NodeStmtPass::make_class(&vm.ctx), - "Break" => NodeStmtBreak::make_class(&vm.ctx), - "Continue" => NodeStmtContinue::make_class(&vm.ctx), - "expr" => NodeExpr::make_class(&vm.ctx), - "BoolOp" => NodeExprBoolOp::make_class(&vm.ctx), - "NamedExpr" => NodeExprNamedExpr::make_class(&vm.ctx), - "BinOp" => NodeExprBinOp::make_class(&vm.ctx), - "UnaryOp" => NodeExprUnaryOp::make_class(&vm.ctx), - "Lambda" => NodeExprLambda::make_class(&vm.ctx), - "IfExp" => NodeExprIfExp::make_class(&vm.ctx), - "Dict" => NodeExprDict::make_class(&vm.ctx), - "Set" => NodeExprSet::make_class(&vm.ctx), - "ListComp" => NodeExprListComp::make_class(&vm.ctx), - "SetComp" => NodeExprSetComp::make_class(&vm.ctx), - "DictComp" => NodeExprDictComp::make_class(&vm.ctx), - "GeneratorExp" => NodeExprGeneratorExp::make_class(&vm.ctx), - "Await" => NodeExprAwait::make_class(&vm.ctx), - "Yield" => NodeExprYield::make_class(&vm.ctx), - "YieldFrom" => NodeExprYieldFrom::make_class(&vm.ctx), - "Compare" => NodeExprCompare::make_class(&vm.ctx), - "Call" => NodeExprCall::make_class(&vm.ctx), - "FormattedValue" => NodeExprFormattedValue::make_class(&vm.ctx), - "JoinedStr" => NodeExprJoinedStr::make_class(&vm.ctx), - "Constant" => NodeExprConstant::make_class(&vm.ctx), - "Attribute" => NodeExprAttribute::make_class(&vm.ctx), - "Subscript" => NodeExprSubscript::make_class(&vm.ctx), - "Starred" => NodeExprStarred::make_class(&vm.ctx), - "Name" => NodeExprName::make_class(&vm.ctx), - "List" => NodeExprList::make_class(&vm.ctx), - "Tuple" => NodeExprTuple::make_class(&vm.ctx), - "Slice" => NodeExprSlice::make_class(&vm.ctx), - "expr_context" => NodeExprContext::make_class(&vm.ctx), - "Load" => NodeExprContextLoad::make_class(&vm.ctx), - "Store" => NodeExprContextStore::make_class(&vm.ctx), - "Del" => NodeExprContextDel::make_class(&vm.ctx), - "boolop" => NodeBoolOp::make_class(&vm.ctx), - "And" => NodeBoolOpAnd::make_class(&vm.ctx), - "Or" => NodeBoolOpOr::make_class(&vm.ctx), - "operator" => NodeOperator::make_class(&vm.ctx), - "Add" => NodeOperatorAdd::make_class(&vm.ctx), - "Sub" => NodeOperatorSub::make_class(&vm.ctx), - "Mult" => NodeOperatorMult::make_class(&vm.ctx), - "MatMult" => NodeOperatorMatMult::make_class(&vm.ctx), - "Div" => NodeOperatorDiv::make_class(&vm.ctx), - "Mod" => NodeOperatorMod::make_class(&vm.ctx), - "Pow" => NodeOperatorPow::make_class(&vm.ctx), - "LShift" => NodeOperatorLShift::make_class(&vm.ctx), - "RShift" => NodeOperatorRShift::make_class(&vm.ctx), - "BitOr" => NodeOperatorBitOr::make_class(&vm.ctx), - "BitXor" => NodeOperatorBitXor::make_class(&vm.ctx), - "BitAnd" => NodeOperatorBitAnd::make_class(&vm.ctx), - "FloorDiv" => NodeOperatorFloorDiv::make_class(&vm.ctx), - "unaryop" => NodeUnaryOp::make_class(&vm.ctx), - "Invert" => NodeUnaryOpInvert::make_class(&vm.ctx), - "Not" => NodeUnaryOpNot::make_class(&vm.ctx), - "UAdd" => NodeUnaryOpUAdd::make_class(&vm.ctx), - "USub" => NodeUnaryOpUSub::make_class(&vm.ctx), - "cmpop" => NodeCmpOp::make_class(&vm.ctx), - "Eq" => NodeCmpOpEq::make_class(&vm.ctx), - "NotEq" => NodeCmpOpNotEq::make_class(&vm.ctx), - "Lt" => NodeCmpOpLt::make_class(&vm.ctx), - "LtE" => NodeCmpOpLtE::make_class(&vm.ctx), - "Gt" => NodeCmpOpGt::make_class(&vm.ctx), - "GtE" => NodeCmpOpGtE::make_class(&vm.ctx), - "Is" => NodeCmpOpIs::make_class(&vm.ctx), - "IsNot" => NodeCmpOpIsNot::make_class(&vm.ctx), - "In" => NodeCmpOpIn::make_class(&vm.ctx), - "NotIn" => NodeCmpOpNotIn::make_class(&vm.ctx), - "comprehension" => NodeComprehension::make_class(&vm.ctx), - "excepthandler" => NodeExceptHandler::make_class(&vm.ctx), - "ExceptHandler" => NodeExceptHandlerExceptHandler::make_class(&vm.ctx), - "arguments" => NodeArguments::make_class(&vm.ctx), - "arg" => NodeArg::make_class(&vm.ctx), - "keyword" => NodeKeyword::make_class(&vm.ctx), - "alias" => NodeAlias::make_class(&vm.ctx), - "withitem" => NodeWithItem::make_class(&vm.ctx), - "match_case" => NodeMatchCase::make_class(&vm.ctx), - "pattern" => NodePattern::make_class(&vm.ctx), - "MatchValue" => NodePatternMatchValue::make_class(&vm.ctx), - "MatchSingleton" => NodePatternMatchSingleton::make_class(&vm.ctx), - "MatchSequence" => NodePatternMatchSequence::make_class(&vm.ctx), - "MatchMapping" => NodePatternMatchMapping::make_class(&vm.ctx), - "MatchClass" => NodePatternMatchClass::make_class(&vm.ctx), - "MatchStar" => NodePatternMatchStar::make_class(&vm.ctx), - "MatchAs" => NodePatternMatchAs::make_class(&vm.ctx), - "MatchOr" => NodePatternMatchOr::make_class(&vm.ctx), - "type_ignore" => NodeTypeIgnore::make_class(&vm.ctx), - "TypeIgnore" => NodeTypeIgnoreTypeIgnore::make_class(&vm.ctx), - "type_param" => NodeTypeParam::make_class(&vm.ctx), - "TypeVar" => NodeTypeParamTypeVar::make_class(&vm.ctx), - "ParamSpec" => NodeTypeParamParamSpec::make_class(&vm.ctx), - "TypeVarTuple" => NodeTypeParamTypeVarTuple::make_class(&vm.ctx), - }) -} diff --git a/vm/src/stdlib/ast/module.rs b/vm/src/stdlib/ast/module.rs new file mode 100644 index 000000000..480ced0b6 --- /dev/null +++ b/vm/src/stdlib/ast/module.rs @@ -0,0 +1,221 @@ +use super::*; +use crate::stdlib::ast::type_ignore::TypeIgnore; + +/// Represents the different types of Python module structures. +/// +/// This enum is used to represent the various possible forms of a Python module +/// in an Abstract Syntax Tree (AST). It can correspond to: +/// +/// - `Module`: A standard Python script, containing a sequence of statements +/// (e.g., assignments, function calls), possibly with type ignores. +/// - `Interactive`: A representation of code executed in an interactive +/// Python session (e.g., the REPL or Jupyter notebooks), where statements +/// are evaluated one at a time. +/// - `Expression`: A single expression without any surrounding statements. +/// This is typically used in scenarios like `eval()` or in expression-only +/// contexts. +/// - `FunctionType`: A function signature with argument and return type +/// annotations, representing the type hints of a function (e.g., `def add(x: int, y: int) -> int`). +pub(super) enum Mod { + Module(ruff::ModModule), + Interactive(ModInteractive), + Expression(ruff::ModExpression), + FunctionType(ModFunctionType), +} + +// sum +impl Node for Mod { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + Self::Module(cons) => cons.ast_to_object(vm, source_code), + Self::Interactive(cons) => cons.ast_to_object(vm, source_code), + Self::Expression(cons) => cons.ast_to_object(vm, source_code), + Self::FunctionType(cons) => cons.ast_to_object(vm, source_code), + } + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let cls = object.class(); + Ok(if cls.is(pyast::NodeModModule::static_type()) { + Self::Module(ruff::ModModule::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeModInteractive::static_type()) { + Self::Interactive(ModInteractive::ast_from_object(vm, source_code, object)?) + } else if cls.is(pyast::NodeModExpression::static_type()) { + Self::Expression(ruff::ModExpression::ast_from_object( + vm, + source_code, + object, + )?) + } else if cls.is(pyast::NodeModFunctionType::static_type()) { + Self::FunctionType(ModFunctionType::ast_from_object(vm, source_code, object)?) + } else { + return Err(vm.new_type_error(format!( + "expected some sort of mod, but got {}", + object.repr(vm)? + ))); + }) + } +} +// constructor +impl Node for ruff::ModModule { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::ModModule { + body, + // type_ignores, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeModModule::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("body", body.ast_to_object(vm, source_code), vm) + .unwrap(); + // TODO: Improve ruff API + // ruff ignores type_ignore comments currently. + let type_ignores: Vec = vec![]; + dict.set_item( + "type_ignores", + type_ignores.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(ruff::ModModule { + body: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "body", "Module")?, + )?, + // type_ignores: Node::ast_from_object( + // _vm, + // get_node_field(_vm, &_object, "type_ignores", "Module")?, + // )?, + range: Default::default(), + }) + } +} + +pub(super) struct ModInteractive { + pub(crate) range: TextRange, + pub(crate) body: Vec, +} + +// constructor +impl Node for ModInteractive { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { body, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeModInteractive::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("body", body.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + body: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "body", "Interactive")?, + )?, + range: Default::default(), + }) + } +} +// constructor +impl Node for ruff::ModExpression { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { body, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeModExpression::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("body", body.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + body: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "body", "Expression")?, + )?, + range: Default::default(), + }) + } +} + +pub(super) struct ModFunctionType { + pub(crate) argtypes: Box<[ruff::Expr]>, + pub(crate) returns: ruff::Expr, + pub(crate) range: TextRange, +} + +// constructor +impl Node for ModFunctionType { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ModFunctionType { + argtypes, + returns, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeModFunctionType::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item( + "argtypes", + BoxedSlice(argtypes).ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + dict.set_item("returns", returns.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(ModFunctionType { + argtypes: { + let argtypes: BoxedSlice<_> = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "argtypes", "FunctionType")?, + )?; + argtypes.0 + }, + returns: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "returns", "FunctionType")?, + )?, + range: Default::default(), + }) + } +} diff --git a/vm/src/stdlib/ast/node.rs b/vm/src/stdlib/ast/node.rs new file mode 100644 index 000000000..03c62d7eb --- /dev/null +++ b/vm/src/stdlib/ast/node.rs @@ -0,0 +1,93 @@ +use crate::{PyObjectRef, PyResult, VirtualMachine}; +use rustpython_compiler_source::SourceCodeOwned; + +pub(crate) trait Node: Sized { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef; + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult; + /// Used in `Option::ast_from_object`; if `true`, that impl will return None. + fn is_none(&self) -> bool { + false + } +} + +impl Node for Vec { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + vm.ctx + .new_list( + self.into_iter() + .map(|node| node.ast_to_object(vm, source_code)) + .collect(), + ) + .into() + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + vm.extract_elements_with(&object, |obj| Node::ast_from_object(vm, source_code, obj)) + } +} + +impl Node for Box { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + (*self).ast_to_object(vm, source_code) + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + T::ast_from_object(vm, source_code, object).map(Box::new) + } + + fn is_none(&self) -> bool { + (**self).is_none() + } +} + +impl Node for Option { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + Some(node) => node.ast_to_object(vm, source_code), + None => vm.ctx.none(), + } + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + if vm.is_none(&object) { + Ok(None) + } else { + let x = T::ast_from_object(vm, source_code, object)?; + Ok((!x.is_none()).then_some(x)) + } + } +} + +pub(super) struct BoxedSlice(pub(super) Box<[T]>); + +impl Node for BoxedSlice { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + self.0.into_vec().ast_to_object(vm, source_code) + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self( + as Node>::ast_from_object(vm, source_code, object)?.into_boxed_slice(), + )) + } +} diff --git a/vm/src/stdlib/ast/operator.rs b/vm/src/stdlib/ast/operator.rs new file mode 100644 index 000000000..bf11c5e1c --- /dev/null +++ b/vm/src/stdlib/ast/operator.rs @@ -0,0 +1,185 @@ +use super::*; + +// sum +impl Node for ruff::BoolOp { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + let node_type = match self { + ruff::BoolOp::And => pyast::NodeBoolOpAnd::static_type(), + ruff::BoolOp::Or => pyast::NodeBoolOpOr::static_type(), + }; + NodeAst + .into_ref_with_type(vm, node_type.to_owned()) + .unwrap() + .into() + } + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok(if _cls.is(pyast::NodeBoolOpAnd::static_type()) { + ruff::BoolOp::And + } else if _cls.is(pyast::NodeBoolOpOr::static_type()) { + ruff::BoolOp::Or + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of boolop, but got {}", + _object.repr(_vm)? + ))); + }) + } +} +// sum +impl Node for ruff::Operator { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + let node_type = match self { + ruff::Operator::Add => pyast::NodeOperatorAdd::static_type(), + ruff::Operator::Sub => pyast::NodeOperatorSub::static_type(), + ruff::Operator::Mult => pyast::NodeOperatorMult::static_type(), + ruff::Operator::MatMult => pyast::NodeOperatorMatMult::static_type(), + ruff::Operator::Div => pyast::NodeOperatorDiv::static_type(), + ruff::Operator::Mod => pyast::NodeOperatorMod::static_type(), + ruff::Operator::Pow => pyast::NodeOperatorPow::static_type(), + ruff::Operator::LShift => pyast::NodeOperatorLShift::static_type(), + ruff::Operator::RShift => pyast::NodeOperatorRShift::static_type(), + ruff::Operator::BitOr => pyast::NodeOperatorBitOr::static_type(), + ruff::Operator::BitXor => pyast::NodeOperatorBitXor::static_type(), + ruff::Operator::BitAnd => pyast::NodeOperatorBitAnd::static_type(), + ruff::Operator::FloorDiv => pyast::NodeOperatorFloorDiv::static_type(), + }; + NodeAst + .into_ref_with_type(vm, node_type.to_owned()) + .unwrap() + .into() + } + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok(if _cls.is(pyast::NodeOperatorAdd::static_type()) { + ruff::Operator::Add + } else if _cls.is(pyast::NodeOperatorSub::static_type()) { + ruff::Operator::Sub + } else if _cls.is(pyast::NodeOperatorMult::static_type()) { + ruff::Operator::Mult + } else if _cls.is(pyast::NodeOperatorMatMult::static_type()) { + ruff::Operator::MatMult + } else if _cls.is(pyast::NodeOperatorDiv::static_type()) { + ruff::Operator::Div + } else if _cls.is(pyast::NodeOperatorMod::static_type()) { + ruff::Operator::Mod + } else if _cls.is(pyast::NodeOperatorPow::static_type()) { + ruff::Operator::Pow + } else if _cls.is(pyast::NodeOperatorLShift::static_type()) { + ruff::Operator::LShift + } else if _cls.is(pyast::NodeOperatorRShift::static_type()) { + ruff::Operator::RShift + } else if _cls.is(pyast::NodeOperatorBitOr::static_type()) { + ruff::Operator::BitOr + } else if _cls.is(pyast::NodeOperatorBitXor::static_type()) { + ruff::Operator::BitXor + } else if _cls.is(pyast::NodeOperatorBitAnd::static_type()) { + ruff::Operator::BitAnd + } else if _cls.is(pyast::NodeOperatorFloorDiv::static_type()) { + ruff::Operator::FloorDiv + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of operator, but got {}", + _object.repr(_vm)? + ))); + }) + } +} +// sum +impl Node for ruff::UnaryOp { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + let node_type = match self { + ruff::UnaryOp::Invert => pyast::NodeUnaryOpInvert::static_type(), + ruff::UnaryOp::Not => pyast::NodeUnaryOpNot::static_type(), + ruff::UnaryOp::UAdd => pyast::NodeUnaryOpUAdd::static_type(), + ruff::UnaryOp::USub => pyast::NodeUnaryOpUSub::static_type(), + }; + NodeAst + .into_ref_with_type(vm, node_type.to_owned()) + .unwrap() + .into() + } + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok(if _cls.is(pyast::NodeUnaryOpInvert::static_type()) { + ruff::UnaryOp::Invert + } else if _cls.is(pyast::NodeUnaryOpNot::static_type()) { + ruff::UnaryOp::Not + } else if _cls.is(pyast::NodeUnaryOpUAdd::static_type()) { + ruff::UnaryOp::UAdd + } else if _cls.is(pyast::NodeUnaryOpUSub::static_type()) { + ruff::UnaryOp::USub + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of unaryop, but got {}", + _object.repr(_vm)? + ))); + }) + } +} +// sum +impl Node for ruff::CmpOp { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + let node_type = match self { + ruff::CmpOp::Eq => pyast::NodeCmpOpEq::static_type(), + ruff::CmpOp::NotEq => pyast::NodeCmpOpNotEq::static_type(), + ruff::CmpOp::Lt => pyast::NodeCmpOpLt::static_type(), + ruff::CmpOp::LtE => pyast::NodeCmpOpLtE::static_type(), + ruff::CmpOp::Gt => pyast::NodeCmpOpGt::static_type(), + ruff::CmpOp::GtE => pyast::NodeCmpOpGtE::static_type(), + ruff::CmpOp::Is => pyast::NodeCmpOpIs::static_type(), + ruff::CmpOp::IsNot => pyast::NodeCmpOpIsNot::static_type(), + ruff::CmpOp::In => pyast::NodeCmpOpIn::static_type(), + ruff::CmpOp::NotIn => pyast::NodeCmpOpNotIn::static_type(), + }; + NodeAst + .into_ref_with_type(vm, node_type.to_owned()) + .unwrap() + .into() + } + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok(if _cls.is(pyast::NodeCmpOpEq::static_type()) { + ruff::CmpOp::Eq + } else if _cls.is(pyast::NodeCmpOpNotEq::static_type()) { + ruff::CmpOp::NotEq + } else if _cls.is(pyast::NodeCmpOpLt::static_type()) { + ruff::CmpOp::Lt + } else if _cls.is(pyast::NodeCmpOpLtE::static_type()) { + ruff::CmpOp::LtE + } else if _cls.is(pyast::NodeCmpOpGt::static_type()) { + ruff::CmpOp::Gt + } else if _cls.is(pyast::NodeCmpOpGtE::static_type()) { + ruff::CmpOp::GtE + } else if _cls.is(pyast::NodeCmpOpIs::static_type()) { + ruff::CmpOp::Is + } else if _cls.is(pyast::NodeCmpOpIsNot::static_type()) { + ruff::CmpOp::IsNot + } else if _cls.is(pyast::NodeCmpOpIn::static_type()) { + ruff::CmpOp::In + } else if _cls.is(pyast::NodeCmpOpNotIn::static_type()) { + ruff::CmpOp::NotIn + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of cmpop, but got {}", + _object.repr(_vm)? + ))); + }) + } +} diff --git a/vm/src/stdlib/ast/other.rs b/vm/src/stdlib/ast/other.rs new file mode 100644 index 000000000..09ffbd407 --- /dev/null +++ b/vm/src/stdlib/ast/other.rs @@ -0,0 +1,131 @@ +use super::*; +use num_traits::ToPrimitive; + +impl Node for ruff::ConversionFlag { + fn ast_to_object(self, vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + vm.ctx.new_int(self as u8).into() + } + + fn ast_from_object( + vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + i32::try_from_object(vm, object)? + .to_u32() + .and_then(ruff::ConversionFlag::from_op_arg) + .ok_or_else(|| vm.new_value_error("invalid conversion flag".to_owned())) + } +} + +// /// This is just a string, not strictly an AST node. But it makes AST conversions easier. +// impl Node for ruff::name::Name { +// fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { +// vm.ctx.new_str(self.as_str()).to_pyobject(vm) +// } + +// fn ast_from_object(vm: &VirtualMachine, source_code: &SourceCodeOwned, object: PyObjectRef) -> PyResult { +// match object.downcast::() { +// Ok(name) => Ok(Self::new(name)), +// Err(_) => Err(vm.new_value_error("expected str for name".to_owned())), +// } +// } +// } + +impl Node for ruff::Decorator { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + ruff::Expr::ast_to_object(self.expression, vm, source_code) + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let expression = ruff::Expr::ast_from_object(vm, source_code, object)?; + let range = expression.range(); + Ok(ruff::Decorator { expression, range }) + } +} + +// product +impl Node for ruff::Alias { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + name, + asname, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeAlias::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("name", name.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("asname", asname.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, _range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + name: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "name", "alias")?, + )?, + asname: get_node_field_opt(vm, &object, "asname")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + range: range_from_object(vm, source_code, object, "alias")?, + }) + } +} +// product +impl Node for ruff::WithItem { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + context_expr, + optional_vars, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeWithItem::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item( + "context_expr", + context_expr.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + dict.set_item( + "optional_vars", + optional_vars.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + context_expr: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "context_expr", "withitem")?, + )?, + optional_vars: get_node_field_opt(vm, &object, "optional_vars")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + range: Default::default(), + }) + } +} diff --git a/vm/src/stdlib/ast/parameter.rs b/vm/src/stdlib/ast/parameter.rs new file mode 100644 index 000000000..82c22d020 --- /dev/null +++ b/vm/src/stdlib/ast/parameter.rs @@ -0,0 +1,401 @@ +use super::*; + +// product +impl Node for ruff::Parameters { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + posonlyargs, + args, + vararg, + kwonlyargs, + kwarg, + range, + } = self; + let (posonlyargs, args, defaults) = + extract_positional_parameter_defaults(posonlyargs, args); + let (kwonlyargs, kw_defaults) = extract_keyword_parameter_defaults(kwonlyargs); + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeArguments::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item( + "posonlyargs", + posonlyargs.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + dict.set_item("args", args.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("vararg", vararg.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("kwonlyargs", kwonlyargs.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item( + "kw_defaults", + kw_defaults.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + dict.set_item("kwarg", kwarg.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("defaults", defaults.ast_to_object(vm, source_code), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let kwonlyargs = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "kwonlyargs", "arguments")?, + )?; + let kw_defaults = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "kw_defaults", "arguments")?, + )?; + let kwonlyargs = merge_keyword_parameter_defaults(kwonlyargs, kw_defaults); + + let posonlyargs = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "posonlyargs", "arguments")?, + )?; + let args = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "args", "arguments")?, + )?; + let defaults = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "defaults", "arguments")?, + )?; + let (posonlyargs, args) = merge_positional_parameter_defaults(posonlyargs, args, defaults); + + Ok(Self { + posonlyargs, + args, + vararg: get_node_field_opt(vm, &object, "vararg")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + kwonlyargs, + kwarg: get_node_field_opt(vm, &object, "kwarg")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + range: Default::default(), + }) + } + + fn is_none(&self) -> bool { + self.is_empty() + } +} +// product +impl Node for ruff::Parameter { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + name, + annotation, + // type_comment, + range, + } = self; + + // ruff covers the ** in range but python expects it to start at the ident + let range = TextRange::new(name.start(), range.end()); + + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeArg::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("arg", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item( + "annotation", + annotation.ast_to_object(_vm, source_code), + _vm, + ) + .unwrap(); + // dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) + // .unwrap(); + node_add_location(&dict, range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + name: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "arg", "arg")?, + )?, + annotation: get_node_field_opt(_vm, &_object, "annotation")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + // type_comment: get_node_field_opt(_vm, &_object, "type_comment")? + // .map(|obj| Node::ast_from_object(_vm, obj)) + // .transpose()?, + range: range_from_object(_vm, source_code, _object, "arg")?, + }) + } +} + +// product +impl Node for ruff::Keyword { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + arg, + value, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeKeyword::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("arg", arg.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("value", value.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + arg: get_node_field_opt(_vm, &_object, "arg")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + value: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "value", "keyword")?, + )?, + range: range_from_object(_vm, source_code, _object, "keyword")?, + }) + } +} + +struct PositionalParameters { + pub _range: TextRange, // TODO: Use this + pub args: Box<[ruff::Parameter]>, +} + +impl Node for PositionalParameters { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + BoxedSlice(self.args).ast_to_object(vm, source_code) + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let args: BoxedSlice<_> = Node::ast_from_object(vm, source_code, object)?; + Ok(Self { + args: args.0, + _range: TextRange::default(), // TODO + }) + } +} + +struct KeywordParameters { + pub _range: TextRange, // TODO: Use this + pub keywords: Box<[ruff::Parameter]>, +} + +impl Node for KeywordParameters { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + BoxedSlice(self.keywords).ast_to_object(vm, source_code) + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let keywords: BoxedSlice<_> = Node::ast_from_object(vm, source_code, object)?; + Ok(Self { + keywords: keywords.0, + _range: TextRange::default(), // TODO + }) + } +} + +struct ParameterDefaults { + pub _range: TextRange, // TODO: Use this + defaults: Box<[Option>]>, +} + +impl Node for ParameterDefaults { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + BoxedSlice(self.defaults).ast_to_object(vm, source_code) + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let defaults: BoxedSlice<_> = Node::ast_from_object(vm, source_code, object)?; + Ok(Self { + defaults: defaults.0, + _range: TextRange::default(), // TODO + }) + } +} + +fn extract_positional_parameter_defaults( + pos_only_args: Vec, + args: Vec, +) -> ( + PositionalParameters, + PositionalParameters, + ParameterDefaults, +) { + let mut defaults = vec![]; + defaults.extend(pos_only_args.iter().map(|item| item.default.clone())); + defaults.extend(args.iter().map(|item| item.default.clone())); + // If some positional parameters have no default value, + // the "defaults" list contains only the defaults of the last "n" parameters. + // Remove all positional parameters without a default value. + defaults.retain(Option::is_some); + let defaults = ParameterDefaults { + _range: defaults + .iter() + .flatten() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(), + defaults: defaults.into_boxed_slice(), + }; + + let pos_only_args = PositionalParameters { + _range: pos_only_args + .iter() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(), + args: { + let pos_only_args: Vec<_> = pos_only_args + .iter() + .map(|item| item.parameter.clone()) + .collect(); + pos_only_args.into_boxed_slice() + }, + }; + + let args = PositionalParameters { + _range: args + .iter() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(), + args: { + let args: Vec<_> = args.iter().map(|item| item.parameter.clone()).collect(); + args.into_boxed_slice() + }, + }; + + (pos_only_args, args, defaults) +} + +/// Merges the keyword parameters with their default values, opposite of [`extract_positional_parameter_defaults`]. +fn merge_positional_parameter_defaults( + posonlyargs: PositionalParameters, + args: PositionalParameters, + defaults: ParameterDefaults, +) -> ( + Vec, + Vec, +) { + let posonlyargs = posonlyargs.args; + let args = args.args; + let defaults = defaults.defaults; + + let mut posonlyargs: Vec<_> = as IntoIterator>::into_iter(posonlyargs) + .map(|parameter| ruff::ParameterWithDefault { + range: Default::default(), + parameter, + default: None, + }) + .collect(); + let mut args: Vec<_> = as IntoIterator>::into_iter(args) + .map(|parameter| ruff::ParameterWithDefault { + range: Default::default(), + parameter, + default: None, + }) + .collect(); + + // If an argument has a default value, insert it + // Note that "defaults" will only contain default values for the last "n" parameters + // so we need to skip the first "total_argument_count - n" arguments. + let default_argument_count = posonlyargs.len() + args.len() - defaults.len(); + for (arg, default) in posonlyargs + .iter_mut() + .chain(args.iter_mut()) + .skip(default_argument_count) + .zip(defaults) + { + arg.default = default; + } + + (posonlyargs, args) +} + +fn extract_keyword_parameter_defaults( + kw_only_args: Vec, +) -> (KeywordParameters, ParameterDefaults) { + let mut defaults = vec![]; + defaults.extend(kw_only_args.iter().map(|item| item.default.clone())); + let defaults = ParameterDefaults { + _range: defaults + .iter() + .flatten() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(), + defaults: defaults.into_boxed_slice(), + }; + + let kw_only_args = KeywordParameters { + _range: kw_only_args + .iter() + .map(|item| item.range()) + .reduce(|acc, next| acc.cover(next)) + .unwrap_or_default(), + keywords: { + let kw_only_args: Vec<_> = kw_only_args + .iter() + .map(|item| item.parameter.clone()) + .collect(); + kw_only_args.into_boxed_slice() + }, + }; + + (kw_only_args, defaults) +} + +/// Merges the keyword parameters with their default values, opposite of [`extract_keyword_parameter_defaults`]. +fn merge_keyword_parameter_defaults( + kw_only_args: KeywordParameters, + defaults: ParameterDefaults, +) -> Vec { + std::iter::zip(kw_only_args.keywords, defaults.defaults) + .map(|(parameter, default)| ruff::ParameterWithDefault { + parameter, + default, + range: Default::default(), + }) + .collect() +} diff --git a/vm/src/stdlib/ast/pattern.rs b/vm/src/stdlib/ast/pattern.rs new file mode 100644 index 000000000..df5adefeb --- /dev/null +++ b/vm/src/stdlib/ast/pattern.rs @@ -0,0 +1,515 @@ +use super::*; + +// product +impl Node for ruff::MatchCase { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + pattern, + guard, + body, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeMatchCase::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("pattern", pattern.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("guard", guard.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + pattern: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "pattern", "match_case")?, + )?, + guard: get_node_field_opt(_vm, &_object, "guard")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + body: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "body", "match_case")?, + )?, + range: Default::default(), + }) + } +} +// sum +impl Node for ruff::Pattern { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + ruff::Pattern::MatchValue(cons) => cons.ast_to_object(vm, source_code), + ruff::Pattern::MatchSingleton(cons) => cons.ast_to_object(vm, source_code), + ruff::Pattern::MatchSequence(cons) => cons.ast_to_object(vm, source_code), + ruff::Pattern::MatchMapping(cons) => cons.ast_to_object(vm, source_code), + ruff::Pattern::MatchClass(cons) => cons.ast_to_object(vm, source_code), + ruff::Pattern::MatchStar(cons) => cons.ast_to_object(vm, source_code), + ruff::Pattern::MatchAs(cons) => cons.ast_to_object(vm, source_code), + ruff::Pattern::MatchOr(cons) => cons.ast_to_object(vm, source_code), + } + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok(if _cls.is(pyast::NodePatternMatchValue::static_type()) { + ruff::Pattern::MatchValue(ruff::PatternMatchValue::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodePatternMatchSingleton::static_type()) { + ruff::Pattern::MatchSingleton(ruff::PatternMatchSingleton::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodePatternMatchSequence::static_type()) { + ruff::Pattern::MatchSequence(ruff::PatternMatchSequence::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodePatternMatchMapping::static_type()) { + ruff::Pattern::MatchMapping(ruff::PatternMatchMapping::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodePatternMatchClass::static_type()) { + ruff::Pattern::MatchClass(ruff::PatternMatchClass::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodePatternMatchStar::static_type()) { + ruff::Pattern::MatchStar(ruff::PatternMatchStar::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodePatternMatchAs::static_type()) { + ruff::Pattern::MatchAs(ruff::PatternMatchAs::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodePatternMatchOr::static_type()) { + ruff::Pattern::MatchOr(ruff::PatternMatchOr::ast_from_object( + _vm, + source_code, + _object, + )?) + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of pattern, but got {}", + _object.repr(_vm)? + ))); + }) + } +} +// constructor +impl Node for ruff::PatternMatchValue { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + value, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodePatternMatchValue::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + value: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "value", "MatchValue")?, + )?, + range: range_from_object(_vm, source_code, _object, "MatchValue")?, + }) + } +} +// constructor +impl Node for ruff::PatternMatchSingleton { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + value, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type( + _vm, + pyast::NodePatternMatchSingleton::static_type().to_owned(), + ) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + value: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "value", "MatchSingleton")?, + )?, + range: range_from_object(_vm, source_code, _object, "MatchSingleton")?, + }) + } +} +impl Node for ruff::Singleton { + fn ast_to_object(self, _vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + todo!() + } + + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + todo!() + } +} +// constructor +impl Node for ruff::PatternMatchSequence { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + patterns, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type( + _vm, + pyast::NodePatternMatchSequence::static_type().to_owned(), + ) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("patterns", patterns.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + patterns: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "patterns", "MatchSequence")?, + )?, + range: range_from_object(_vm, source_code, _object, "MatchSequence")?, + }) + } +} +// constructor +impl Node for ruff::PatternMatchMapping { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + keys, + patterns, + rest, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type( + _vm, + pyast::NodePatternMatchMapping::static_type().to_owned(), + ) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("keys", keys.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("patterns", patterns.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("rest", rest.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + keys: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "keys", "MatchMapping")?, + )?, + patterns: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "patterns", "MatchMapping")?, + )?, + rest: get_node_field_opt(_vm, &_object, "rest")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + range: range_from_object(_vm, source_code, _object, "MatchMapping")?, + }) + } +} +// constructor +impl Node for ruff::PatternMatchClass { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + cls, + arguments, + range: _range, + } = self; + let (patterns, kwd_attrs, kwd_patterns) = split_pattern_match_class(arguments); + let node = NodeAst + .into_ref_with_type(vm, pyast::NodePatternMatchClass::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("cls", cls.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("patterns", patterns.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("kwd_attrs", kwd_attrs.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item( + "kwd_patterns", + kwd_patterns.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + node_add_location(&dict, _range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let patterns = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "patterns", "MatchClass")?, + )?; + let kwd_attrs = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "kwd_attrs", "MatchClass")?, + )?; + let kwd_patterns = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "kwd_patterns", "MatchClass")?, + )?; + let (patterns, keywords) = merge_pattern_match_class(patterns, kwd_attrs, kwd_patterns); + + Ok(Self { + cls: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "cls", "MatchClass")?, + )?, + range: range_from_object(vm, source_code, object, "MatchClass")?, + arguments: ruff::PatternArguments { + range: Default::default(), + patterns, + keywords, + }, + }) + } +} + +struct PatternMatchClassPatterns { + pub _range: TextRange, // TODO: Use this +} + +impl Node for PatternMatchClassPatterns { + fn ast_to_object(self, _vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + todo!() + } + + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + todo!() + } +} + +struct PatternMatchClassKeywordAttributes { + pub _range: TextRange, // TODO: Use this +} + +impl Node for PatternMatchClassKeywordAttributes { + fn ast_to_object(self, _vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + todo!() + } + + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + todo!() + } +} + +struct PatternMatchClassKeywordPatterns { + pub _range: TextRange, // TODO: Use this +} + +impl Node for PatternMatchClassKeywordPatterns { + fn ast_to_object(self, _vm: &VirtualMachine, _source_code: &SourceCodeOwned) -> PyObjectRef { + todo!() + } + + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + todo!() + } +} +// constructor +impl Node for ruff::PatternMatchStar { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + name, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodePatternMatchStar::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("name", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + name: get_node_field_opt(_vm, &_object, "name")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + range: range_from_object(_vm, source_code, _object, "MatchStar")?, + }) + } +} +// constructor +impl Node for ruff::PatternMatchAs { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + pattern, + name, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodePatternMatchAs::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("pattern", pattern.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("name", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + pattern: get_node_field_opt(_vm, &_object, "pattern")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + name: get_node_field_opt(_vm, &_object, "name")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + range: range_from_object(_vm, source_code, _object, "MatchAs")?, + }) + } +} +// constructor +impl Node for ruff::PatternMatchOr { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + patterns, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodePatternMatchOr::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("patterns", patterns.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + patterns: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "patterns", "MatchOr")?, + )?, + range: range_from_object(_vm, source_code, _object, "MatchOr")?, + }) + } +} + +fn split_pattern_match_class( + _arguments: ruff::PatternArguments, +) -> ( + PatternMatchClassPatterns, + PatternMatchClassKeywordAttributes, + PatternMatchClassKeywordPatterns, +) { + todo!() +} + +/// Merges the pattern match class attributes and patterns, opposite of [`split_pattern_match_class`]. +fn merge_pattern_match_class( + _patterns: PatternMatchClassPatterns, + _kwd_attrs: PatternMatchClassKeywordAttributes, + _kwd_patterns: PatternMatchClassKeywordPatterns, +) -> (Vec, Vec) { + todo!() +} diff --git a/vm/src/stdlib/ast/pyast.rs b/vm/src/stdlib/ast/pyast.rs new file mode 100644 index 000000000..3692b0a2c --- /dev/null +++ b/vm/src/stdlib/ast/pyast.rs @@ -0,0 +1,2448 @@ +#![allow(clippy::all)] + +use super::*; +use crate::common::ascii; +#[pyclass(module = "_ast", name = "mod", base = "NodeAst")] +pub(crate) struct NodeMod; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeMod {} +#[pyclass(module = "_ast", name = "Module", base = "NodeMod")] +pub(crate) struct NodeModModule; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeModModule { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("type_ignores")).into(), + ]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Interactive", base = "NodeMod")] +pub(crate) struct NodeModInteractive; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeModInteractive { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("body")).into()]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Expression", base = "NodeMod")] +pub(crate) struct NodeModExpression; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeModExpression { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("body")).into()]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "FunctionType", base = "NodeMod")] +pub(crate) struct NodeModFunctionType; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeModFunctionType { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("argtypes")).into(), + ctx.new_str(ascii!("returns")).into(), + ]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "stmt", base = "NodeAst")] +pub(crate) struct NodeStmt; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmt {} +#[pyclass(module = "_ast", name = "FunctionDef", base = "NodeStmt")] +pub(crate) struct NodeStmtFunctionDef; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtFunctionDef { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("name")).into(), + ctx.new_str(ascii!("args")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("decorator_list")).into(), + ctx.new_str(ascii!("returns")).into(), + ctx.new_str(ascii!("type_comment")).into(), + ctx.new_str(ascii!("type_params")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "AsyncFunctionDef", base = "NodeStmt")] +pub(crate) struct NodeStmtAsyncFunctionDef; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtAsyncFunctionDef { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("name")).into(), + ctx.new_str(ascii!("args")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("decorator_list")).into(), + ctx.new_str(ascii!("returns")).into(), + ctx.new_str(ascii!("type_comment")).into(), + ctx.new_str(ascii!("type_params")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "ClassDef", base = "NodeStmt")] +pub(crate) struct NodeStmtClassDef; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtClassDef { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("name")).into(), + ctx.new_str(ascii!("bases")).into(), + ctx.new_str(ascii!("keywords")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("decorator_list")).into(), + ctx.new_str(ascii!("type_params")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Return", base = "NodeStmt")] +pub(crate) struct NodeStmtReturn; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtReturn { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Delete", base = "NodeStmt")] +pub(crate) struct NodeStmtDelete; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtDelete { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("targets")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Assign", base = "NodeStmt")] +pub(crate) struct NodeStmtAssign; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtAssign { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("targets")).into(), + ctx.new_str(ascii!("value")).into(), + ctx.new_str(ascii!("type_comment")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "TypeAlias", base = "NodeStmt")] +pub(crate) struct NodeStmtTypeAlias; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtTypeAlias { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("name")).into(), + ctx.new_str(ascii!("type_params")).into(), + ctx.new_str(ascii!("value")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "AugAssign", base = "NodeStmt")] +pub(crate) struct NodeStmtAugAssign; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtAugAssign { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("target")).into(), + ctx.new_str(ascii!("op")).into(), + ctx.new_str(ascii!("value")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "AnnAssign", base = "NodeStmt")] +pub(crate) struct NodeStmtAnnAssign; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtAnnAssign { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("target")).into(), + ctx.new_str(ascii!("annotation")).into(), + ctx.new_str(ascii!("value")).into(), + ctx.new_str(ascii!("simple")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "For", base = "NodeStmt")] +pub(crate) struct NodeStmtFor; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtFor { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("target")).into(), + ctx.new_str(ascii!("iter")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("orelse")).into(), + ctx.new_str(ascii!("type_comment")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "AsyncFor", base = "NodeStmt")] +pub(crate) struct NodeStmtAsyncFor; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtAsyncFor { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("target")).into(), + ctx.new_str(ascii!("iter")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("orelse")).into(), + ctx.new_str(ascii!("type_comment")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "While", base = "NodeStmt")] +pub(crate) struct NodeStmtWhile; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtWhile { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("test")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("orelse")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "If", base = "NodeStmt")] +pub(crate) struct NodeStmtIf; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtIf { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("test")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("orelse")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "With", base = "NodeStmt")] +pub(crate) struct NodeStmtWith; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtWith { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("items")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("type_comment")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "AsyncWith", base = "NodeStmt")] +pub(crate) struct NodeStmtAsyncWith; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtAsyncWith { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("items")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("type_comment")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Match", base = "NodeStmt")] +pub(crate) struct NodeStmtMatch; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtMatch { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("subject")).into(), + ctx.new_str(ascii!("cases")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Raise", base = "NodeStmt")] +pub(crate) struct NodeStmtRaise; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtRaise { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("exc")).into(), + ctx.new_str(ascii!("cause")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Try", base = "NodeStmt")] +pub(crate) struct NodeStmtTry; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtTry { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("handlers")).into(), + ctx.new_str(ascii!("orelse")).into(), + ctx.new_str(ascii!("finalbody")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "TryStar", base = "NodeStmt")] +pub(crate) struct NodeStmtTryStar; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtTryStar { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("handlers")).into(), + ctx.new_str(ascii!("orelse")).into(), + ctx.new_str(ascii!("finalbody")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Assert", base = "NodeStmt")] +pub(crate) struct NodeStmtAssert; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtAssert { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("test")).into(), + ctx.new_str(ascii!("msg")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Import", base = "NodeStmt")] +pub(crate) struct NodeStmtImport; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtImport { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("names")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "ImportFrom", base = "NodeStmt")] +pub(crate) struct NodeStmtImportFrom; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtImportFrom { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("module")).into(), + ctx.new_str(ascii!("names")).into(), + ctx.new_str(ascii!("level")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Global", base = "NodeStmt")] +pub(crate) struct NodeStmtGlobal; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtGlobal { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("names")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Nonlocal", base = "NodeStmt")] +pub(crate) struct NodeStmtNonlocal; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtNonlocal { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("names")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Expr", base = "NodeStmt")] +pub(crate) struct NodeStmtExpr; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtExpr { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Pass", base = "NodeStmt")] +pub(crate) struct NodeStmtPass; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtPass { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Break", base = "NodeStmt")] +pub(crate) struct NodeStmtBreak; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtBreak { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Continue", base = "NodeStmt")] +pub(crate) struct NodeStmtContinue; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeStmtContinue { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "expr", base = "NodeAst")] +pub(crate) struct NodeExpr; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExpr {} +#[pyclass(module = "_ast", name = "BoolOp", base = "NodeExpr")] +pub(crate) struct NodeExprBoolOp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprBoolOp { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("op")).into(), + ctx.new_str(ascii!("values")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "NamedExpr", base = "NodeExpr")] +pub(crate) struct NodeExprNamedExpr; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprNamedExpr { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("target")).into(), + ctx.new_str(ascii!("value")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "BinOp", base = "NodeExpr")] +pub(crate) struct NodeExprBinOp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprBinOp { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("left")).into(), + ctx.new_str(ascii!("op")).into(), + ctx.new_str(ascii!("right")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "UnaryOp", base = "NodeExpr")] +pub(crate) struct NodeExprUnaryOp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprUnaryOp { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("op")).into(), + ctx.new_str(ascii!("operand")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Lambda", base = "NodeExpr")] +pub(crate) struct NodeExprLambda; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprLambda { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("args")).into(), + ctx.new_str(ascii!("body")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "IfExp", base = "NodeExpr")] +pub(crate) struct NodeExprIfExp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprIfExp { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("test")).into(), + ctx.new_str(ascii!("body")).into(), + ctx.new_str(ascii!("orelse")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Dict", base = "NodeExpr")] +pub(crate) struct NodeExprDict; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprDict { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("keys")).into(), + ctx.new_str(ascii!("values")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Set", base = "NodeExpr")] +pub(crate) struct NodeExprSet; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprSet { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("elts")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "ListComp", base = "NodeExpr")] +pub(crate) struct NodeExprListComp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprListComp { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("elt")).into(), + ctx.new_str(ascii!("generators")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "SetComp", base = "NodeExpr")] +pub(crate) struct NodeExprSetComp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprSetComp { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("elt")).into(), + ctx.new_str(ascii!("generators")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "DictComp", base = "NodeExpr")] +pub(crate) struct NodeExprDictComp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprDictComp { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("key")).into(), + ctx.new_str(ascii!("value")).into(), + ctx.new_str(ascii!("generators")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "GeneratorExp", base = "NodeExpr")] +pub(crate) struct NodeExprGeneratorExp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprGeneratorExp { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("elt")).into(), + ctx.new_str(ascii!("generators")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Await", base = "NodeExpr")] +pub(crate) struct NodeExprAwait; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprAwait { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Yield", base = "NodeExpr")] +pub(crate) struct NodeExprYield; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprYield { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "YieldFrom", base = "NodeExpr")] +pub(crate) struct NodeExprYieldFrom; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprYieldFrom { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Compare", base = "NodeExpr")] +pub(crate) struct NodeExprCompare; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprCompare { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("left")).into(), + ctx.new_str(ascii!("ops")).into(), + ctx.new_str(ascii!("comparators")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Call", base = "NodeExpr")] +pub(crate) struct NodeExprCall; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprCall { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("func")).into(), + ctx.new_str(ascii!("args")).into(), + ctx.new_str(ascii!("keywords")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "FormattedValue", base = "NodeExpr")] +pub(crate) struct NodeExprFormattedValue; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprFormattedValue { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("value")).into(), + ctx.new_str(ascii!("conversion")).into(), + ctx.new_str(ascii!("format_spec")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "JoinedStr", base = "NodeExpr")] +pub(crate) struct NodeExprJoinedStr; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprJoinedStr { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("values")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Constant", base = "NodeExpr")] +pub(crate) struct NodeExprConstant; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprConstant { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("value")).into(), + ctx.new_str(ascii!("kind")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Attribute", base = "NodeExpr")] +pub(crate) struct NodeExprAttribute; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprAttribute { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("value")).into(), + ctx.new_str(ascii!("attr")).into(), + ctx.new_str(ascii!("ctx")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Subscript", base = "NodeExpr")] +pub(crate) struct NodeExprSubscript; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprSubscript { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("value")).into(), + ctx.new_str(ascii!("slice")).into(), + ctx.new_str(ascii!("ctx")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Starred", base = "NodeExpr")] +pub(crate) struct NodeExprStarred; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprStarred { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("value")).into(), + ctx.new_str(ascii!("ctx")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Name", base = "NodeExpr")] +pub(crate) struct NodeExprName; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprName { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("id")).into(), + ctx.new_str(ascii!("ctx")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "List", base = "NodeExpr")] +pub(crate) struct NodeExprList; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprList { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("elts")).into(), + ctx.new_str(ascii!("ctx")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Tuple", base = "NodeExpr")] +pub(crate) struct NodeExprTuple; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprTuple { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("elts")).into(), + ctx.new_str(ascii!("ctx")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "Slice", base = "NodeExpr")] +pub(crate) struct NodeExprSlice; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprSlice { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("lower")).into(), + ctx.new_str(ascii!("upper")).into(), + ctx.new_str(ascii!("step")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "expr_context", base = "NodeAst")] +pub(crate) struct NodeExprContext; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprContext {} +#[pyclass(module = "_ast", name = "Load", base = "NodeExprContext")] +pub(crate) struct NodeExprContextLoad; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprContextLoad { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Store", base = "NodeExprContext")] +pub(crate) struct NodeExprContextStore; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprContextStore { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Del", base = "NodeExprContext")] +pub(crate) struct NodeExprContextDel; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExprContextDel { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "boolop", base = "NodeAst")] +pub(crate) struct NodeBoolOp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeBoolOp {} +#[pyclass(module = "_ast", name = "And", base = "NodeBoolOp")] +pub(crate) struct NodeBoolOpAnd; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeBoolOpAnd { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Or", base = "NodeBoolOp")] +pub(crate) struct NodeBoolOpOr; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeBoolOpOr { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "operator", base = "NodeAst")] +pub(crate) struct NodeOperator; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperator {} +#[pyclass(module = "_ast", name = "Add", base = "NodeOperator")] +pub(crate) struct NodeOperatorAdd; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorAdd { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Sub", base = "NodeOperator")] +pub(crate) struct NodeOperatorSub; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorSub { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Mult", base = "NodeOperator")] +pub(crate) struct NodeOperatorMult; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorMult { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "MatMult", base = "NodeOperator")] +pub(crate) struct NodeOperatorMatMult; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorMatMult { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Div", base = "NodeOperator")] +pub(crate) struct NodeOperatorDiv; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorDiv { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Mod", base = "NodeOperator")] +pub(crate) struct NodeOperatorMod; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorMod { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Pow", base = "NodeOperator")] +pub(crate) struct NodeOperatorPow; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorPow { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "LShift", base = "NodeOperator")] +pub(crate) struct NodeOperatorLShift; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorLShift { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "RShift", base = "NodeOperator")] +pub(crate) struct NodeOperatorRShift; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorRShift { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "BitOr", base = "NodeOperator")] +pub(crate) struct NodeOperatorBitOr; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorBitOr { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "BitXor", base = "NodeOperator")] +pub(crate) struct NodeOperatorBitXor; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorBitXor { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "BitAnd", base = "NodeOperator")] +pub(crate) struct NodeOperatorBitAnd; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorBitAnd { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "FloorDiv", base = "NodeOperator")] +pub(crate) struct NodeOperatorFloorDiv; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeOperatorFloorDiv { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "unaryop", base = "NodeAst")] +pub(crate) struct NodeUnaryOp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeUnaryOp {} +#[pyclass(module = "_ast", name = "Invert", base = "NodeUnaryOp")] +pub(crate) struct NodeUnaryOpInvert; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeUnaryOpInvert { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Not", base = "NodeUnaryOp")] +pub(crate) struct NodeUnaryOpNot; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeUnaryOpNot { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "UAdd", base = "NodeUnaryOp")] +pub(crate) struct NodeUnaryOpUAdd; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeUnaryOpUAdd { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "USub", base = "NodeUnaryOp")] +pub(crate) struct NodeUnaryOpUSub; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeUnaryOpUSub { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "cmpop", base = "NodeAst")] +pub(crate) struct NodeCmpOp; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOp {} +#[pyclass(module = "_ast", name = "Eq", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpEq; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpEq { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "NotEq", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpNotEq; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpNotEq { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Lt", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpLt; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpLt { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "LtE", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpLtE; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpLtE { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Gt", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpGt; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpGt { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "GtE", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpGtE; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpGtE { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "Is", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpIs; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpIs { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "IsNot", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpIsNot; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpIsNot { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "In", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpIn; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpIn { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "NotIn", base = "NodeCmpOp")] +pub(crate) struct NodeCmpOpNotIn; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeCmpOpNotIn { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr(identifier!(ctx, _fields), ctx.new_tuple(vec![]).into()); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "comprehension", base = "NodeAst")] +pub(crate) struct NodeComprehension; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeComprehension { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("target")).into(), + ctx.new_str(ascii!("iter")).into(), + ctx.new_str(ascii!("ifs")).into(), + ctx.new_str(ascii!("is_async")).into(), + ]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "excepthandler", base = "NodeAst")] +pub(crate) struct NodeExceptHandler; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExceptHandler {} +#[pyclass(module = "_ast", name = "ExceptHandler", base = "NodeExceptHandler")] +pub(crate) struct NodeExceptHandlerExceptHandler; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeExceptHandlerExceptHandler { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("type")).into(), + ctx.new_str(ascii!("name")).into(), + ctx.new_str(ascii!("body")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "arguments", base = "NodeAst")] +pub(crate) struct NodeArguments; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeArguments { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("posonlyargs")).into(), + ctx.new_str(ascii!("args")).into(), + ctx.new_str(ascii!("vararg")).into(), + ctx.new_str(ascii!("kwonlyargs")).into(), + ctx.new_str(ascii!("kw_defaults")).into(), + ctx.new_str(ascii!("kwarg")).into(), + ctx.new_str(ascii!("defaults")).into(), + ]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "arg", base = "NodeAst")] +pub(crate) struct NodeArg; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeArg { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("arg")).into(), + ctx.new_str(ascii!("annotation")).into(), + ctx.new_str(ascii!("type_comment")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "keyword", base = "NodeAst")] +pub(crate) struct NodeKeyword; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeKeyword { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("arg")).into(), + ctx.new_str(ascii!("value")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "alias", base = "NodeAst")] +pub(crate) struct NodeAlias; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeAlias { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("name")).into(), + ctx.new_str(ascii!("asname")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "withitem", base = "NodeAst")] +pub(crate) struct NodeWithItem; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeWithItem { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("context_expr")).into(), + ctx.new_str(ascii!("optional_vars")).into(), + ]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "match_case", base = "NodeAst")] +pub(crate) struct NodeMatchCase; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeMatchCase { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("pattern")).into(), + ctx.new_str(ascii!("guard")).into(), + ctx.new_str(ascii!("body")).into(), + ]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "pattern", base = "NodeAst")] +pub(crate) struct NodePattern; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePattern {} +#[pyclass(module = "_ast", name = "MatchValue", base = "NodePattern")] +pub(crate) struct NodePatternMatchValue; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePatternMatchValue { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "MatchSingleton", base = "NodePattern")] +pub(crate) struct NodePatternMatchSingleton; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePatternMatchSingleton { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("value")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "MatchSequence", base = "NodePattern")] +pub(crate) struct NodePatternMatchSequence; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePatternMatchSequence { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("patterns")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "MatchMapping", base = "NodePattern")] +pub(crate) struct NodePatternMatchMapping; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePatternMatchMapping { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("keys")).into(), + ctx.new_str(ascii!("patterns")).into(), + ctx.new_str(ascii!("rest")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "MatchClass", base = "NodePattern")] +pub(crate) struct NodePatternMatchClass; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePatternMatchClass { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("cls")).into(), + ctx.new_str(ascii!("patterns")).into(), + ctx.new_str(ascii!("kwd_attrs")).into(), + ctx.new_str(ascii!("kwd_patterns")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "MatchStar", base = "NodePattern")] +pub(crate) struct NodePatternMatchStar; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePatternMatchStar { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("name")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "MatchAs", base = "NodePattern")] +pub(crate) struct NodePatternMatchAs; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePatternMatchAs { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("pattern")).into(), + ctx.new_str(ascii!("name")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "MatchOr", base = "NodePattern")] +pub(crate) struct NodePatternMatchOr; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodePatternMatchOr { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("patterns")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "type_ignore", base = "NodeAst")] +pub(crate) struct NodeTypeIgnore; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeTypeIgnore {} +#[pyclass(module = "_ast", name = "TypeIgnore", base = "NodeTypeIgnore")] +pub(crate) struct NodeTypeIgnoreTypeIgnore; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeTypeIgnoreTypeIgnore { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("tag")).into(), + ]) + .into(), + ); + class.set_attr(identifier!(ctx, _attributes), ctx.new_list(vec![]).into()); + } +} +#[pyclass(module = "_ast", name = "type_param", base = "NodeAst")] +pub(crate) struct NodeTypeParam; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeTypeParam {} +#[pyclass(module = "_ast", name = "TypeVar", base = "NodeTypeParam")] +pub(crate) struct NodeTypeParamTypeVar; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeTypeParamTypeVar { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ + ctx.new_str(ascii!("name")).into(), + ctx.new_str(ascii!("bound")).into(), + ]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "ParamSpec", base = "NodeTypeParam")] +pub(crate) struct NodeTypeParamParamSpec; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeTypeParamParamSpec { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("name")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} +#[pyclass(module = "_ast", name = "TypeVarTuple", base = "NodeTypeParam")] +pub(crate) struct NodeTypeParamTypeVarTuple; +#[pyclass(flags(HAS_DICT, BASETYPE))] +impl NodeTypeParamTypeVarTuple { + #[extend_class] + fn extend_class_with_fields(ctx: &Context, class: &'static Py) { + class.set_attr( + identifier!(ctx, _fields), + ctx.new_tuple(vec![ctx.new_str(ascii!("name")).into()]) + .into(), + ); + class.set_attr( + identifier!(ctx, _attributes), + ctx.new_list(vec![ + ctx.new_str(ascii!("lineno")).into(), + ctx.new_str(ascii!("col_offset")).into(), + ctx.new_str(ascii!("end_lineno")).into(), + ctx.new_str(ascii!("end_col_offset")).into(), + ]) + .into(), + ); + } +} + +pub fn extend_module_nodes(vm: &VirtualMachine, module: &Py) { + extend_module!(vm, module, { + "mod" => NodeMod::make_class(&vm.ctx), + "Module" => NodeModModule::make_class(&vm.ctx), + "Interactive" => NodeModInteractive::make_class(&vm.ctx), + "Expression" => NodeModExpression::make_class(&vm.ctx), + "FunctionType" => NodeModFunctionType::make_class(&vm.ctx), + "stmt" => NodeStmt::make_class(&vm.ctx), + "FunctionDef" => NodeStmtFunctionDef::make_class(&vm.ctx), + "AsyncFunctionDef" => NodeStmtAsyncFunctionDef::make_class(&vm.ctx), + "ClassDef" => NodeStmtClassDef::make_class(&vm.ctx), + "Return" => NodeStmtReturn::make_class(&vm.ctx), + "Delete" => NodeStmtDelete::make_class(&vm.ctx), + "Assign" => NodeStmtAssign::make_class(&vm.ctx), + "TypeAlias" => NodeStmtTypeAlias::make_class(&vm.ctx), + "AugAssign" => NodeStmtAugAssign::make_class(&vm.ctx), + "AnnAssign" => NodeStmtAnnAssign::make_class(&vm.ctx), + "For" => NodeStmtFor::make_class(&vm.ctx), + "AsyncFor" => NodeStmtAsyncFor::make_class(&vm.ctx), + "While" => NodeStmtWhile::make_class(&vm.ctx), + "If" => NodeStmtIf::make_class(&vm.ctx), + "With" => NodeStmtWith::make_class(&vm.ctx), + "AsyncWith" => NodeStmtAsyncWith::make_class(&vm.ctx), + "Match" => NodeStmtMatch::make_class(&vm.ctx), + "Raise" => NodeStmtRaise::make_class(&vm.ctx), + "Try" => NodeStmtTry::make_class(&vm.ctx), + "TryStar" => NodeStmtTryStar::make_class(&vm.ctx), + "Assert" => NodeStmtAssert::make_class(&vm.ctx), + "Import" => NodeStmtImport::make_class(&vm.ctx), + "ImportFrom" => NodeStmtImportFrom::make_class(&vm.ctx), + "Global" => NodeStmtGlobal::make_class(&vm.ctx), + "Nonlocal" => NodeStmtNonlocal::make_class(&vm.ctx), + "Expr" => NodeStmtExpr::make_class(&vm.ctx), + "Pass" => NodeStmtPass::make_class(&vm.ctx), + "Break" => NodeStmtBreak::make_class(&vm.ctx), + "Continue" => NodeStmtContinue::make_class(&vm.ctx), + "expr" => NodeExpr::make_class(&vm.ctx), + "BoolOp" => NodeExprBoolOp::make_class(&vm.ctx), + "NamedExpr" => NodeExprNamedExpr::make_class(&vm.ctx), + "BinOp" => NodeExprBinOp::make_class(&vm.ctx), + "UnaryOp" => NodeExprUnaryOp::make_class(&vm.ctx), + "Lambda" => NodeExprLambda::make_class(&vm.ctx), + "IfExp" => NodeExprIfExp::make_class(&vm.ctx), + "Dict" => NodeExprDict::make_class(&vm.ctx), + "Set" => NodeExprSet::make_class(&vm.ctx), + "ListComp" => NodeExprListComp::make_class(&vm.ctx), + "SetComp" => NodeExprSetComp::make_class(&vm.ctx), + "DictComp" => NodeExprDictComp::make_class(&vm.ctx), + "GeneratorExp" => NodeExprGeneratorExp::make_class(&vm.ctx), + "Await" => NodeExprAwait::make_class(&vm.ctx), + "Yield" => NodeExprYield::make_class(&vm.ctx), + "YieldFrom" => NodeExprYieldFrom::make_class(&vm.ctx), + "Compare" => NodeExprCompare::make_class(&vm.ctx), + "Call" => NodeExprCall::make_class(&vm.ctx), + "FormattedValue" => NodeExprFormattedValue::make_class(&vm.ctx), + "JoinedStr" => NodeExprJoinedStr::make_class(&vm.ctx), + "Constant" => NodeExprConstant::make_class(&vm.ctx), + "Attribute" => NodeExprAttribute::make_class(&vm.ctx), + "Subscript" => NodeExprSubscript::make_class(&vm.ctx), + "Starred" => NodeExprStarred::make_class(&vm.ctx), + "Name" => NodeExprName::make_class(&vm.ctx), + "List" => NodeExprList::make_class(&vm.ctx), + "Tuple" => NodeExprTuple::make_class(&vm.ctx), + "Slice" => NodeExprSlice::make_class(&vm.ctx), + "expr_context" => NodeExprContext::make_class(&vm.ctx), + "Load" => NodeExprContextLoad::make_class(&vm.ctx), + "Store" => NodeExprContextStore::make_class(&vm.ctx), + "Del" => NodeExprContextDel::make_class(&vm.ctx), + "boolop" => NodeBoolOp::make_class(&vm.ctx), + "And" => NodeBoolOpAnd::make_class(&vm.ctx), + "Or" => NodeBoolOpOr::make_class(&vm.ctx), + "operator" => NodeOperator::make_class(&vm.ctx), + "Add" => NodeOperatorAdd::make_class(&vm.ctx), + "Sub" => NodeOperatorSub::make_class(&vm.ctx), + "Mult" => NodeOperatorMult::make_class(&vm.ctx), + "MatMult" => NodeOperatorMatMult::make_class(&vm.ctx), + "Div" => NodeOperatorDiv::make_class(&vm.ctx), + "Mod" => NodeOperatorMod::make_class(&vm.ctx), + "Pow" => NodeOperatorPow::make_class(&vm.ctx), + "LShift" => NodeOperatorLShift::make_class(&vm.ctx), + "RShift" => NodeOperatorRShift::make_class(&vm.ctx), + "BitOr" => NodeOperatorBitOr::make_class(&vm.ctx), + "BitXor" => NodeOperatorBitXor::make_class(&vm.ctx), + "BitAnd" => NodeOperatorBitAnd::make_class(&vm.ctx), + "FloorDiv" => NodeOperatorFloorDiv::make_class(&vm.ctx), + "unaryop" => NodeUnaryOp::make_class(&vm.ctx), + "Invert" => NodeUnaryOpInvert::make_class(&vm.ctx), + "Not" => NodeUnaryOpNot::make_class(&vm.ctx), + "UAdd" => NodeUnaryOpUAdd::make_class(&vm.ctx), + "USub" => NodeUnaryOpUSub::make_class(&vm.ctx), + "cmpop" => NodeCmpOp::make_class(&vm.ctx), + "Eq" => NodeCmpOpEq::make_class(&vm.ctx), + "NotEq" => NodeCmpOpNotEq::make_class(&vm.ctx), + "Lt" => NodeCmpOpLt::make_class(&vm.ctx), + "LtE" => NodeCmpOpLtE::make_class(&vm.ctx), + "Gt" => NodeCmpOpGt::make_class(&vm.ctx), + "GtE" => NodeCmpOpGtE::make_class(&vm.ctx), + "Is" => NodeCmpOpIs::make_class(&vm.ctx), + "IsNot" => NodeCmpOpIsNot::make_class(&vm.ctx), + "In" => NodeCmpOpIn::make_class(&vm.ctx), + "NotIn" => NodeCmpOpNotIn::make_class(&vm.ctx), + "comprehension" => NodeComprehension::make_class(&vm.ctx), + "excepthandler" => NodeExceptHandler::make_class(&vm.ctx), + "ExceptHandler" => NodeExceptHandlerExceptHandler::make_class(&vm.ctx), + "arguments" => NodeArguments::make_class(&vm.ctx), + "arg" => NodeArg::make_class(&vm.ctx), + "keyword" => NodeKeyword::make_class(&vm.ctx), + "alias" => NodeAlias::make_class(&vm.ctx), + "withitem" => NodeWithItem::make_class(&vm.ctx), + "match_case" => NodeMatchCase::make_class(&vm.ctx), + "pattern" => NodePattern::make_class(&vm.ctx), + "MatchValue" => NodePatternMatchValue::make_class(&vm.ctx), + "MatchSingleton" => NodePatternMatchSingleton::make_class(&vm.ctx), + "MatchSequence" => NodePatternMatchSequence::make_class(&vm.ctx), + "MatchMapping" => NodePatternMatchMapping::make_class(&vm.ctx), + "MatchClass" => NodePatternMatchClass::make_class(&vm.ctx), + "MatchStar" => NodePatternMatchStar::make_class(&vm.ctx), + "MatchAs" => NodePatternMatchAs::make_class(&vm.ctx), + "MatchOr" => NodePatternMatchOr::make_class(&vm.ctx), + "type_ignore" => NodeTypeIgnore::make_class(&vm.ctx), + "TypeIgnore" => NodeTypeIgnoreTypeIgnore::make_class(&vm.ctx), + "type_param" => NodeTypeParam::make_class(&vm.ctx), + "TypeVar" => NodeTypeParamTypeVar::make_class(&vm.ctx), + "ParamSpec" => NodeTypeParamParamSpec::make_class(&vm.ctx), + "TypeVarTuple" => NodeTypeParamTypeVarTuple::make_class(&vm.ctx), + }) +} diff --git a/vm/src/stdlib/ast/python.rs b/vm/src/stdlib/ast/python.rs new file mode 100644 index 000000000..50f8294c7 --- /dev/null +++ b/vm/src/stdlib/ast/python.rs @@ -0,0 +1,57 @@ +use super::PY_COMPILE_FLAG_AST_ONLY; + +#[pymodule] +pub(crate) mod _ast { + use crate::{ + AsObject, Context, PyObjectRef, PyPayload, PyResult, VirtualMachine, + builtins::{PyStrRef, PyTupleRef}, + function::FuncArgs, + }; + #[pyattr] + #[pyclass(module = "_ast", name = "AST")] + #[derive(Debug, PyPayload)] + pub(crate) struct NodeAst; + + #[pyclass(flags(BASETYPE, HAS_DICT))] + impl NodeAst { + #[pyslot] + #[pymethod(magic)] + fn init(zelf: PyObjectRef, args: FuncArgs, vm: &VirtualMachine) -> PyResult<()> { + let fields = zelf.get_attr("_fields", vm)?; + let fields: Vec = fields.try_to_value(vm)?; + let numargs = args.args.len(); + if numargs > fields.len() { + return Err(vm.new_type_error(format!( + "{} constructor takes at most {} positional argument{}", + zelf.class().name(), + fields.len(), + if fields.len() == 1 { "" } else { "s" }, + ))); + } + for (name, arg) in fields.iter().zip(args.args) { + zelf.set_attr(name, arg, vm)?; + } + for (key, value) in args.kwargs { + if let Some(pos) = fields.iter().position(|f| f.as_str() == key) { + if pos < numargs { + return Err(vm.new_type_error(format!( + "{} got multiple values for argument '{}'", + zelf.class().name(), + key + ))); + } + } + zelf.set_attr(vm.ctx.intern_str(key), value, vm)?; + } + Ok(()) + } + + #[pyattr(name = "_fields")] + fn fields(ctx: &Context) -> PyTupleRef { + ctx.empty_tuple.clone() + } + } + + #[pyattr(name = "PyCF_ONLY_AST")] + use super::PY_COMPILE_FLAG_AST_ONLY; +} diff --git a/vm/src/stdlib/ast/statement.rs b/vm/src/stdlib/ast/statement.rs new file mode 100644 index 000000000..61b6c0eaf --- /dev/null +++ b/vm/src/stdlib/ast/statement.rs @@ -0,0 +1,1222 @@ +use super::*; +use crate::stdlib::ast::argument::{merge_class_def_args, split_class_def_args}; +// sum +impl Node for ruff::Stmt { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + ruff::Stmt::FunctionDef(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::ClassDef(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Return(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Delete(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Assign(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::TypeAlias(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::AugAssign(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::AnnAssign(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::For(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::While(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::If(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::With(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Match(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Raise(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Try(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Assert(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Import(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::ImportFrom(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Global(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Nonlocal(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Expr(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Pass(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Break(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::Continue(cons) => cons.ast_to_object(vm, source_code), + ruff::Stmt::IpyEscapeCommand(_) => { + unimplemented!("IPython escape command is not allowed in Python AST") + } + } + } + + #[allow(clippy::if_same_then_else)] + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok(if _cls.is(pyast::NodeStmtFunctionDef::static_type()) { + ruff::Stmt::FunctionDef(ruff::StmtFunctionDef::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtAsyncFunctionDef::static_type()) { + ruff::Stmt::FunctionDef(ruff::StmtFunctionDef::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtClassDef::static_type()) { + ruff::Stmt::ClassDef(ruff::StmtClassDef::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtReturn::static_type()) { + ruff::Stmt::Return(ruff::StmtReturn::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtDelete::static_type()) { + ruff::Stmt::Delete(ruff::StmtDelete::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtAssign::static_type()) { + ruff::Stmt::Assign(ruff::StmtAssign::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtTypeAlias::static_type()) { + ruff::Stmt::TypeAlias(ruff::StmtTypeAlias::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtAugAssign::static_type()) { + ruff::Stmt::AugAssign(ruff::StmtAugAssign::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtAnnAssign::static_type()) { + ruff::Stmt::AnnAssign(ruff::StmtAnnAssign::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtFor::static_type()) { + ruff::Stmt::For(ruff::StmtFor::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtAsyncFor::static_type()) { + ruff::Stmt::For(ruff::StmtFor::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtWhile::static_type()) { + ruff::Stmt::While(ruff::StmtWhile::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtIf::static_type()) { + ruff::Stmt::If(ruff::StmtIf::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtWith::static_type()) { + ruff::Stmt::With(ruff::StmtWith::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtAsyncWith::static_type()) { + ruff::Stmt::With(ruff::StmtWith::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtMatch::static_type()) { + ruff::Stmt::Match(ruff::StmtMatch::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtRaise::static_type()) { + ruff::Stmt::Raise(ruff::StmtRaise::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtTry::static_type()) { + ruff::Stmt::Try(ruff::StmtTry::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtTryStar::static_type()) { + ruff::Stmt::Try(ruff::StmtTry::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtAssert::static_type()) { + ruff::Stmt::Assert(ruff::StmtAssert::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtImport::static_type()) { + ruff::Stmt::Import(ruff::StmtImport::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtImportFrom::static_type()) { + ruff::Stmt::ImportFrom(ruff::StmtImportFrom::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtGlobal::static_type()) { + ruff::Stmt::Global(ruff::StmtGlobal::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtNonlocal::static_type()) { + ruff::Stmt::Nonlocal(ruff::StmtNonlocal::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeStmtExpr::static_type()) { + ruff::Stmt::Expr(ruff::StmtExpr::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtPass::static_type()) { + ruff::Stmt::Pass(ruff::StmtPass::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtBreak::static_type()) { + ruff::Stmt::Break(ruff::StmtBreak::ast_from_object(_vm, source_code, _object)?) + } else if _cls.is(pyast::NodeStmtContinue::static_type()) { + ruff::Stmt::Continue(ruff::StmtContinue::ast_from_object( + _vm, + source_code, + _object, + )?) + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of stmt, but got {}", + _object.repr(_vm)? + ))); + }) + } +} +// constructor +impl Node for ruff::StmtFunctionDef { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + name, + parameters, + body, + decorator_list, + returns, + // type_comment, + type_params, + is_async, + range: _range, + } = self; + + let cls = if !is_async { + pyast::NodeStmtFunctionDef::static_type().to_owned() + } else { + pyast::NodeStmtAsyncFunctionDef::static_type().to_owned() + }; + + let node = NodeAst.into_ref_with_type(vm, cls).unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("name", vm.ctx.new_str(name.as_str()).to_pyobject(vm), vm) + .unwrap(); + dict.set_item("args", parameters.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item( + "decorator_list", + decorator_list.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + dict.set_item("returns", returns.ast_to_object(vm, source_code), vm) + .unwrap(); + // TODO: Ruff ignores type_comment during parsing + // dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) + // .unwrap(); + dict.set_item( + "type_params", + type_params.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + node_add_location(&dict, _range, vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + let is_async = _cls.is(pyast::NodeStmtAsyncFunctionDef::static_type()); + Ok(Self { + name: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "name", "FunctionDef")?, + )?, + parameters: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "args", "FunctionDef")?, + )?, + body: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "body", "FunctionDef")?, + )?, + decorator_list: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "decorator_list", "FunctionDef")?, + )?, + returns: get_node_field_opt(_vm, &_object, "returns")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + // TODO: Ruff ignores type_comment during parsing + // type_comment: get_node_field_opt(_vm, &_object, "type_comment")? + // .map(|obj| Node::ast_from_object(_vm, obj)) + // .transpose()?, + type_params: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "type_params", "FunctionDef")?, + )?, + range: range_from_object(_vm, source_code, _object, "FunctionDef")?, + is_async, + }) + } +} +// constructor +impl Node for ruff::StmtClassDef { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + name, + arguments, + body, + decorator_list, + type_params, + range: _range, + } = self; + let (bases, keywords) = split_class_def_args(arguments); + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtClassDef::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("name", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("bases", bases.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("keywords", keywords.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item( + "decorator_list", + decorator_list.ast_to_object(_vm, source_code), + _vm, + ) + .unwrap(); + dict.set_item( + "type_params", + type_params.ast_to_object(_vm, source_code), + _vm, + ) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let bases = Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "bases", "ClassDef")?, + )?; + let keywords = Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "keywords", "ClassDef")?, + )?; + Ok(Self { + name: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "name", "ClassDef")?, + )?, + arguments: merge_class_def_args(bases, keywords), + body: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "body", "ClassDef")?, + )?, + decorator_list: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "decorator_list", "ClassDef")?, + )?, + type_params: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "type_params", "ClassDef")?, + )?, + range: range_from_object(_vm, source_code, _object, "ClassDef")?, + }) + } +} +// constructor +impl Node for ruff::StmtReturn { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtReturn { + value, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtReturn::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtReturn { + value: get_node_field_opt(_vm, &_object, "value")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + range: range_from_object(_vm, source_code, _object, "Return")?, + }) + } +} +// constructor +impl Node for ruff::StmtDelete { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtDelete { + targets, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtDelete::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("targets", targets.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtDelete { + targets: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "targets", "Delete")?, + )?, + range: range_from_object(_vm, source_code, _object, "Delete")?, + }) + } +} +// constructor +impl Node for ruff::StmtAssign { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + targets, + value, + // type_comment, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeStmtAssign::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("targets", targets.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + // TODO + dict.set_item("type_comment", vm.ctx.none(), vm).unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + targets: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "targets", "Assign")?, + )?, + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "Assign")?, + )?, + // type_comment: get_node_field_opt(_vm, &_object, "type_comment")? + // .map(|obj| Node::ast_from_object(_vm, obj)) + // .transpose()?, + range: range_from_object(vm, source_code, object, "Assign")?, + }) + } +} +// constructor +impl Node for ruff::StmtTypeAlias { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtTypeAlias { + name, + type_params, + value, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtTypeAlias::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("name", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item( + "type_params", + type_params.ast_to_object(_vm, source_code), + _vm, + ) + .unwrap(); + dict.set_item("value", value.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtTypeAlias { + name: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "name", "TypeAlias")?, + )?, + type_params: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "type_params", "TypeAlias")?, + )?, + value: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "value", "TypeAlias")?, + )?, + range: range_from_object(_vm, source_code, _object, "TypeAlias")?, + }) + } +} +// constructor +impl Node for ruff::StmtAugAssign { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + target, + op, + value, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtAugAssign::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("target", target.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("op", op.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("value", value.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + target: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "target", "AugAssign")?, + )?, + op: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "op", "AugAssign")?, + )?, + value: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "value", "AugAssign")?, + )?, + range: range_from_object(_vm, source_code, _object, "AugAssign")?, + }) + } +} +// constructor +impl Node for ruff::StmtAnnAssign { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + target, + annotation, + value, + simple, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtAnnAssign::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("target", target.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item( + "annotation", + annotation.ast_to_object(_vm, source_code), + _vm, + ) + .unwrap(); + dict.set_item("value", value.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("simple", simple.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + target: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "target", "AnnAssign")?, + )?, + annotation: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "annotation", "AnnAssign")?, + )?, + value: get_node_field_opt(_vm, &_object, "value")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + simple: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "simple", "AnnAssign")?, + )?, + range: range_from_object(_vm, source_code, _object, "AnnAssign")?, + }) + } +} +// constructor +impl Node for ruff::StmtFor { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + is_async, + target, + iter, + body, + orelse, + // type_comment, + range: _range, + } = self; + + let cls = if !is_async { + pyast::NodeStmtFor::static_type().to_owned() + } else { + pyast::NodeStmtAsyncFor::static_type().to_owned() + }; + + let node = NodeAst.into_ref_with_type(_vm, cls).unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("target", target.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("iter", iter.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("orelse", orelse.ast_to_object(_vm, source_code), _vm) + .unwrap(); + // dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) + // .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + debug_assert!( + _cls.is(pyast::NodeStmtFor::static_type()) + || _cls.is(pyast::NodeStmtAsyncFor::static_type()) + ); + let is_async = _cls.is(pyast::NodeStmtAsyncFor::static_type()); + Ok(Self { + target: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "target", "For")?, + )?, + iter: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "iter", "For")?, + )?, + body: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "body", "For")?, + )?, + orelse: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "orelse", "For")?, + )?, + // type_comment: get_node_field_opt(_vm, &_object, "type_comment")? + // .map(|obj| Node::ast_from_object(_vm, obj)) + // .transpose()?, + range: range_from_object(_vm, source_code, _object, "For")?, + is_async, + }) + } +} +// constructor +impl Node for ruff::StmtWhile { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + test, + body, + orelse, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtWhile::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("test", test.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("orelse", orelse.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + test: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "test", "While")?, + )?, + body: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "body", "While")?, + )?, + orelse: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "orelse", "While")?, + )?, + range: range_from_object(_vm, source_code, _object, "While")?, + }) + } +} +// constructor +impl Node for ruff::StmtIf { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + test, + body, + range, + elif_else_clauses, + } = self; + elif_else_clause::ast_to_object( + ruff::ElifElseClause { + range, + test: Some(*test), + body, + }, + elif_else_clauses.into_iter(), + _vm, + source_code, + ) + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + elif_else_clause::ast_from_object(vm, source_code, object) + } +} +// constructor +impl Node for ruff::StmtWith { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + is_async, + items, + body, + // type_comment, + range: _range, + } = self; + + let cls = if !is_async { + pyast::NodeStmtWith::static_type().to_owned() + } else { + pyast::NodeStmtAsyncWith::static_type().to_owned() + }; + + let node = NodeAst.into_ref_with_type(_vm, cls).unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("items", items.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("body", body.ast_to_object(_vm, source_code), _vm) + .unwrap(); + // dict.set_item("type_comment", type_comment.ast_to_object(_vm), _vm) + // .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + debug_assert!( + _cls.is(pyast::NodeStmtWith::static_type()) + || _cls.is(pyast::NodeStmtAsyncWith::static_type()) + ); + let is_async = _cls.is(pyast::NodeStmtAsyncWith::static_type()); + Ok(Self { + items: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "items", "With")?, + )?, + body: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "body", "With")?, + )?, + // type_comment: get_node_field_opt(_vm, &_object, "type_comment")? + // .map(|obj| Node::ast_from_object(_vm, obj)) + // .transpose()?, + range: range_from_object(_vm, source_code, _object, "With")?, + is_async, + }) + } +} +// constructor +impl Node for ruff::StmtMatch { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + subject, + cases, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtMatch::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("subject", subject.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("cases", cases.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + subject: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "subject", "Match")?, + )?, + cases: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "cases", "Match")?, + )?, + range: range_from_object(_vm, source_code, _object, "Match")?, + }) + } +} +// constructor +impl Node for ruff::StmtRaise { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + exc, + cause, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtRaise::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("exc", exc.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("cause", cause.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + exc: get_node_field_opt(_vm, &_object, "exc")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + cause: get_node_field_opt(_vm, &_object, "cause")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + range: range_from_object(_vm, source_code, _object, "Raise")?, + }) + } +} +// constructor +impl Node for ruff::StmtTry { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + body, + handlers, + orelse, + finalbody, + range: _range, + is_star, + } = self; + + // let cls = gen::NodeStmtTry::static_type().to_owned(); + let cls = if is_star { + pyast::NodeStmtTryStar::static_type() + } else { + pyast::NodeStmtTry::static_type() + } + .to_owned(); + + let node = NodeAst.into_ref_with_type(_vm, cls).unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("body", body.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("handlers", handlers.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("orelse", orelse.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("finalbody", finalbody.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + let is_star = _cls.is(pyast::NodeStmtTryStar::static_type()); + let _cls = _object.class(); + debug_assert!( + _cls.is(pyast::NodeStmtTry::static_type()) + || _cls.is(pyast::NodeStmtTryStar::static_type()) + ); + + Ok(Self { + body: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "body", "Try")?, + )?, + handlers: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "handlers", "Try")?, + )?, + orelse: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "orelse", "Try")?, + )?, + finalbody: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "finalbody", "Try")?, + )?, + range: range_from_object(_vm, source_code, _object, "Try")?, + is_star, + }) + } +} +// constructor +impl Node for ruff::StmtAssert { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtAssert { + test, + msg, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtAssert::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("test", test.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("msg", msg.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtAssert { + test: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "test", "Assert")?, + )?, + msg: get_node_field_opt(_vm, &_object, "msg")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + range: range_from_object(_vm, source_code, _object, "Assert")?, + }) + } +} +// constructor +impl Node for ruff::StmtImport { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtImport { + names, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtImport::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("names", names.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtImport { + names: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "names", "Import")?, + )?, + range: range_from_object(_vm, source_code, _object, "Import")?, + }) + } +} +// constructor +impl Node for ruff::StmtImportFrom { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + module, + names, + level, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeStmtImportFrom::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("module", module.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("names", names.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("level", vm.ctx.new_int(level).to_pyobject(vm), vm) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + module: get_node_field_opt(vm, &_object, "module")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + names: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &_object, "names", "ImportFrom")?, + )?, + level: get_node_field(vm, &_object, "level", "ImportFrom")? + .downcast_exact::(vm) + .unwrap() + .try_to_primitive::(vm)?, + range: range_from_object(vm, source_code, _object, "ImportFrom")?, + }) + } +} +// constructor +impl Node for ruff::StmtGlobal { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtGlobal { + names, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtGlobal::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("names", names.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtGlobal { + names: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "names", "Global")?, + )?, + range: range_from_object(_vm, source_code, _object, "Global")?, + }) + } +} +// constructor +impl Node for ruff::StmtNonlocal { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtNonlocal { + names, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtNonlocal::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("names", names.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtNonlocal { + names: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "names", "Nonlocal")?, + )?, + range: range_from_object(_vm, source_code, _object, "Nonlocal")?, + }) + } +} +// constructor +impl Node for ruff::StmtExpr { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtExpr { + value, + range: _range, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtExpr::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtExpr { + value: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "value", "Expr")?, + )?, + range: range_from_object(_vm, source_code, _object, "Expr")?, + }) + } +} +// constructor +impl Node for ruff::StmtPass { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtPass { range: _range } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtPass::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtPass { + range: range_from_object(_vm, source_code, _object, "Pass")?, + }) + } +} +// constructor +impl Node for ruff::StmtBreak { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtBreak { range: _range } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtBreak::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtBreak { + range: range_from_object(_vm, source_code, _object, "Break")?, + }) + } +} +// constructor +impl Node for ruff::StmtContinue { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let ruff::StmtContinue { range: _range } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeStmtContinue::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(ruff::StmtContinue { + range: range_from_object(_vm, source_code, _object, "Continue")?, + }) + } +} diff --git a/vm/src/stdlib/ast/string.rs b/vm/src/stdlib/ast/string.rs new file mode 100644 index 000000000..5b7896797 --- /dev/null +++ b/vm/src/stdlib/ast/string.rs @@ -0,0 +1,354 @@ +use super::constant::{Constant, ConstantLiteral}; +use super::*; + +fn ruff_fstring_value_into_iter( + mut fstring_value: ruff::FStringValue, +) -> impl Iterator + 'static { + let default = ruff::FStringPart::FString(ruff::FString { + range: Default::default(), + elements: Default::default(), + flags: Default::default(), + }); + (0..fstring_value.as_slice().len()).map(move |i| { + let fstring_value = &mut fstring_value; + let tmp = fstring_value.into_iter().nth(i).unwrap(); + std::mem::replace(tmp, default.clone()) + }) +} + +fn ruff_fstring_element_into_iter( + mut fstring_element: ruff::FStringElements, +) -> impl Iterator + 'static { + let default = ruff::FStringElement::Literal(ruff::FStringLiteralElement { + range: Default::default(), + value: Default::default(), + }); + (0..fstring_element.into_iter().len()).map(move |i| { + let fstring_element = &mut fstring_element; + let tmp = fstring_element.into_iter().nth(i).unwrap(); + std::mem::replace(tmp, default.clone()) + }) +} + +fn fstring_part_to_joined_str_part(fstring_part: ruff::FStringPart) -> Vec { + match fstring_part { + ruff::FStringPart::Literal(ruff::StringLiteral { + range, + value, + flags, + }) => { + vec![JoinedStrPart::Constant(Constant::new_str( + value, + flags.prefix(), + range, + ))] + } + ruff::FStringPart::FString(ruff::FString { + range: _, + elements, + flags: _, // TODO + }) => ruff_fstring_element_into_iter(elements) + .map(ruff_fstring_element_to_joined_str_part) + .collect(), + } +} + +fn ruff_fstring_element_to_joined_str_part(element: ruff::FStringElement) -> JoinedStrPart { + match element { + ruff::FStringElement::Literal(ruff::FStringLiteralElement { range, value }) => { + JoinedStrPart::Constant(Constant::new_str( + value, + ruff::str_prefix::StringLiteralPrefix::Empty, + range, + )) + } + ruff::FStringElement::Expression(ruff::FStringExpressionElement { + range, + expression, + debug_text: _, // TODO: What is this? + conversion, + format_spec, + }) => JoinedStrPart::FormattedValue(FormattedValue { + value: expression, + conversion, + format_spec: ruff_format_spec_to_joined_str(format_spec), + range, + }), + } +} + +fn ruff_format_spec_to_joined_str( + format_spec: Option>, +) -> Option> { + match format_spec { + None => None, + Some(format_spec) => { + let ruff::FStringFormatSpec { range, elements } = *format_spec; + let values: Vec<_> = ruff_fstring_element_into_iter(elements) + .map(ruff_fstring_element_to_joined_str_part) + .collect(); + let values = values.into_boxed_slice(); + Some(Box::new(JoinedStr { values, range })) + } + } +} + +fn ruff_fstring_element_to_ruff_fstring_part(element: ruff::FStringElement) -> ruff::FStringPart { + match element { + ruff::FStringElement::Literal(value) => { + let ruff::FStringLiteralElement { range, value } = value; + ruff::FStringPart::Literal(ruff::StringLiteral { + range, + value, + flags: Default::default(), + }) + } + ruff::FStringElement::Expression(value) => { + let ruff::FStringExpressionElement { + range, + expression, + debug_text, + conversion, + format_spec, + } = value; + ruff::FStringPart::FString(ruff::FString { + range, + elements: vec![ruff::FStringElement::Expression( + ruff::FStringExpressionElement { + range, + expression, + debug_text, + conversion, + format_spec, + }, + )] + .into(), + flags: Default::default(), + }) + } + } +} + +fn joined_str_to_ruff_format_spec( + joined_str: Option>, +) -> Option> { + match joined_str { + None => None, + Some(joined_str) => { + let JoinedStr { range, values } = *joined_str; + let elements: Vec<_> = Box::into_iter(values) + .map(joined_str_part_to_ruff_fstring_element) + .collect(); + let format_spec = ruff::FStringFormatSpec { + range, + elements: elements.into(), + }; + Some(Box::new(format_spec)) + } + } +} + +#[derive(Debug)] +pub(super) struct JoinedStr { + pub(super) range: TextRange, + pub(super) values: Box<[JoinedStrPart]>, +} + +impl JoinedStr { + pub(super) fn into_expr(self) -> ruff::Expr { + let Self { range, values } = self; + ruff::Expr::FString(ruff::ExprFString { + range: Default::default(), + value: match values.len() { + // ruff represents an empty fstring like this: + 0 => ruff::FStringValue::single(ruff::FString { + range, + elements: vec![].into(), + flags: Default::default(), + }), + 1 => ruff::FStringValue::single( + Box::<[_]>::into_iter(values) + .map(joined_str_part_to_ruff_fstring_element) + .map(|element| ruff::FString { + range, + elements: vec![element].into(), + flags: Default::default(), + }) + .next() + .expect("FString has exactly one part"), + ), + _ => ruff::FStringValue::concatenated( + Box::<[_]>::into_iter(values) + .map(joined_str_part_to_ruff_fstring_element) + .map(ruff_fstring_element_to_ruff_fstring_part) + .collect(), + ), + }, + }) + } +} + +fn joined_str_part_to_ruff_fstring_element(part: JoinedStrPart) -> ruff::FStringElement { + match part { + JoinedStrPart::FormattedValue(value) => { + ruff::FStringElement::Expression(ruff::FStringExpressionElement { + range: value.range, + expression: value.value.clone(), + debug_text: None, // TODO: What is this? + conversion: value.conversion, + format_spec: joined_str_to_ruff_format_spec(value.format_spec), + }) + } + JoinedStrPart::Constant(value) => { + ruff::FStringElement::Literal(ruff::FStringLiteralElement { + range: value.range, + value: match value.value { + ConstantLiteral::Str { value, .. } => value, + _ => todo!(), + }, + }) + } + } +} + +// constructor +impl Node for JoinedStr { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { values, range } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprJoinedStr::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item( + "values", + BoxedSlice(values).ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let values: BoxedSlice<_> = Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "values", "JoinedStr")?, + )?; + Ok(Self { + values: values.0, + range: range_from_object(vm, source_code, object, "JoinedStr")?, + }) + } +} + +#[derive(Debug)] +pub(super) enum JoinedStrPart { + FormattedValue(FormattedValue), + Constant(Constant), +} + +// constructor +impl Node for JoinedStrPart { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + JoinedStrPart::FormattedValue(value) => value.ast_to_object(vm, source_code), + JoinedStrPart::Constant(value) => value.ast_to_object(vm, source_code), + } + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + let cls = object.class(); + if cls.is(pyast::NodeExprFormattedValue::static_type()) { + Ok(Self::FormattedValue(Node::ast_from_object( + vm, + source_code, + object, + )?)) + } else { + Ok(Self::Constant(Node::ast_from_object( + vm, + source_code, + object, + )?)) + } + } +} + +#[derive(Debug)] +pub(super) struct FormattedValue { + value: Box, + conversion: ruff::ConversionFlag, + format_spec: Option>, + range: TextRange, +} + +// constructor +impl Node for FormattedValue { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + value, + conversion, + format_spec, + range, + } = self; + let node = NodeAst + .into_ref_with_type(vm, pyast::NodeExprFormattedValue::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("value", value.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item("conversion", conversion.ast_to_object(vm, source_code), vm) + .unwrap(); + dict.set_item( + "format_spec", + format_spec.ast_to_object(vm, source_code), + vm, + ) + .unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + value: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "value", "FormattedValue")?, + )?, + conversion: Node::ast_from_object( + vm, + source_code, + get_node_field(vm, &object, "conversion", "FormattedValue")?, + )?, + format_spec: get_node_field_opt(vm, &object, "format_spec")? + .map(|obj| Node::ast_from_object(vm, source_code, obj)) + .transpose()?, + range: range_from_object(vm, source_code, object, "FormattedValue")?, + }) + } +} + +pub(super) fn fstring_to_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + expression: ruff::ExprFString, +) -> PyObjectRef { + let ruff::ExprFString { range, value } = expression; + let values: Vec<_> = ruff_fstring_value_into_iter(value) + .flat_map(fstring_part_to_joined_str_part) + .collect(); + let values = values.into_boxed_slice(); + let c = JoinedStr { range, values }; + c.ast_to_object(vm, source_code) +} diff --git a/vm/src/stdlib/ast/type_ignore.rs b/vm/src/stdlib/ast/type_ignore.rs new file mode 100644 index 000000000..7e318f694 --- /dev/null +++ b/vm/src/stdlib/ast/type_ignore.rs @@ -0,0 +1,73 @@ +use super::*; + +pub(super) enum TypeIgnore { + TypeIgnore(TypeIgnoreTypeIgnore), +} + +// sum +impl Node for TypeIgnore { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + TypeIgnore::TypeIgnore(cons) => cons.ast_to_object(vm, source_code), + } + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok(if _cls.is(pyast::NodeTypeIgnoreTypeIgnore::static_type()) { + TypeIgnore::TypeIgnore(TypeIgnoreTypeIgnore::ast_from_object( + _vm, + source_code, + _object, + )?) + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of type_ignore, but got {}", + _object.repr(_vm)? + ))); + }) + } +} + +pub(super) struct TypeIgnoreTypeIgnore { + range: TextRange, + lineno: PyRefExact, + tag: PyRefExact, +} + +// constructor +impl Node for TypeIgnoreTypeIgnore { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { lineno, tag, range } = self; + let node = NodeAst + .into_ref_with_type( + vm, + pyast::NodeTypeIgnoreTypeIgnore::static_type().to_owned(), + ) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("lineno", lineno.to_pyobject(vm), vm).unwrap(); + dict.set_item("tag", tag.to_pyobject(vm), vm).unwrap(); + node_add_location(&dict, range, vm, source_code); + node.into() + } + + fn ast_from_object( + vm: &VirtualMachine, + source_code: &SourceCodeOwned, + object: PyObjectRef, + ) -> PyResult { + Ok(Self { + lineno: get_node_field(vm, &object, "lineno", "TypeIgnore")? + .downcast_exact(vm) + .unwrap(), + tag: get_node_field(vm, &object, "tag", "TypeIgnore")? + .downcast_exact(vm) + .unwrap(), + range: range_from_object(vm, source_code, object, "TypeIgnore")?, + }) + } +} diff --git a/vm/src/stdlib/ast/type_parameters.rs b/vm/src/stdlib/ast/type_parameters.rs new file mode 100644 index 000000000..686cee81f --- /dev/null +++ b/vm/src/stdlib/ast/type_parameters.rs @@ -0,0 +1,197 @@ +use super::*; + +impl Node for ruff::TypeParams { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + self.type_params.ast_to_object(vm, source_code) + } + + fn ast_from_object( + _vm: &VirtualMachine, + _source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let type_params: Vec = Node::ast_from_object(_vm, _source_code, _object)?; + let range = Option::zip(type_params.first(), type_params.last()) + .map(|(first, last)| first.range().cover(last.range())) + .unwrap_or_default(); + Ok(Self { type_params, range }) + } + + fn is_none(&self) -> bool { + self.type_params.is_empty() + } +} +// sum +impl Node for ruff::TypeParam { + fn ast_to_object(self, vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + match self { + Self::TypeVar(cons) => cons.ast_to_object(vm, source_code), + Self::ParamSpec(cons) => cons.ast_to_object(vm, source_code), + Self::TypeVarTuple(cons) => cons.ast_to_object(vm, source_code), + } + } + + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + let _cls = _object.class(); + Ok(if _cls.is(pyast::NodeTypeParamTypeVar::static_type()) { + ruff::TypeParam::TypeVar(ruff::TypeParamTypeVar::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeTypeParamParamSpec::static_type()) { + ruff::TypeParam::ParamSpec(ruff::TypeParamParamSpec::ast_from_object( + _vm, + source_code, + _object, + )?) + } else if _cls.is(pyast::NodeTypeParamTypeVarTuple::static_type()) { + ruff::TypeParam::TypeVarTuple(ruff::TypeParamTypeVarTuple::ast_from_object( + _vm, + source_code, + _object, + )?) + } else { + return Err(_vm.new_type_error(format!( + "expected some sort of type_param, but got {}", + _object.repr(_vm)? + ))); + }) + } +} +// constructor +impl Node for ruff::TypeParamTypeVar { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + name, + bound, + range: _range, + default: _, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeTypeParamTypeVar::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("name", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item("bound", bound.ast_to_object(_vm, source_code), _vm) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + name: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "name", "TypeVar")?, + )?, + bound: get_node_field_opt(_vm, &_object, "bound")? + .map(|obj| Node::ast_from_object(_vm, source_code, obj)) + .transpose()?, + default: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "default_value", "TypeVar")?, + )?, + range: range_from_object(_vm, source_code, _object, "TypeVar")?, + }) + } +} +// constructor +impl Node for ruff::TypeParamParamSpec { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + name, + range: _range, + default, + } = self; + let node = NodeAst + .into_ref_with_type(_vm, pyast::NodeTypeParamParamSpec::static_type().to_owned()) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("name", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item( + "default_value", + default.ast_to_object(_vm, source_code), + _vm, + ) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + name: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "name", "ParamSpec")?, + )?, + default: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "default_value", "ParamSpec")?, + )?, + range: range_from_object(_vm, source_code, _object, "ParamSpec")?, + }) + } +} +// constructor +impl Node for ruff::TypeParamTypeVarTuple { + fn ast_to_object(self, _vm: &VirtualMachine, source_code: &SourceCodeOwned) -> PyObjectRef { + let Self { + name, + range: _range, + default, + } = self; + let node = NodeAst + .into_ref_with_type( + _vm, + pyast::NodeTypeParamTypeVarTuple::static_type().to_owned(), + ) + .unwrap(); + let dict = node.as_object().dict().unwrap(); + dict.set_item("name", name.ast_to_object(_vm, source_code), _vm) + .unwrap(); + dict.set_item( + "default_value", + default.ast_to_object(_vm, source_code), + _vm, + ) + .unwrap(); + node_add_location(&dict, _range, _vm, source_code); + node.into() + } + fn ast_from_object( + _vm: &VirtualMachine, + source_code: &SourceCodeOwned, + _object: PyObjectRef, + ) -> PyResult { + Ok(Self { + name: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "name", "TypeVarTuple")?, + )?, + default: Node::ast_from_object( + _vm, + source_code, + get_node_field(_vm, &_object, "default_value", "TypeVarTuple")?, + )?, + range: range_from_object(_vm, source_code, _object, "TypeVarTuple")?, + }) + } +} diff --git a/vm/src/stdlib/builtins.rs b/vm/src/stdlib/builtins.rs index 22aa11dc4..9c2826a1e 100644 --- a/vm/src/stdlib/builtins.rs +++ b/vm/src/stdlib/builtins.rs @@ -110,10 +110,15 @@ mod builtins { _feature_version: OptionalArg, } - #[cfg(any(feature = "rustpython-parser", feature = "rustpython-codegen"))] + #[cfg(any(feature = "parser", feature = "compiler"))] #[pyfunction] fn compile(args: CompileArgs, vm: &VirtualMachine) -> PyResult { - #[cfg(feature = "rustpython-ast")] + #[cfg(not(feature = "ast"))] + { + _ = args; // to disable unused warning + return Err(vm.new_type_error("AST Not Supported".to_owned())); + } + #[cfg(feature = "ast")] { use crate::{class::PyClassImpl, stdlib::ast}; @@ -155,16 +160,16 @@ mod builtins { } } - #[cfg(not(feature = "rustpython-parser"))] + #[cfg(not(feature = "parser"))] { const PARSER_NOT_SUPPORTED: &str = "can't compile() source code when the `parser` feature of rustpython is disabled"; Err(vm.new_type_error(PARSER_NOT_SUPPORTED.to_owned())) } - #[cfg(feature = "rustpython-parser")] + #[cfg(feature = "parser")] { use crate::convert::ToPyException; use num_traits::Zero; - use rustpython_parser as parser; + use ruff_python_parser as parser; let source = ArgStrOrBytesLike::try_from_object(vm, args.source)?; let source = source.borrow_bytes(); @@ -180,11 +185,11 @@ mod builtins { } if (flags & ast::PY_COMPILE_FLAG_AST_ONLY).is_zero() { - #[cfg(not(feature = "rustpython-compiler"))] + #[cfg(not(feature = "compiler"))] { Err(vm.new_value_error(CODEGEN_NOT_SUPPORTED.to_owned())) } - #[cfg(feature = "rustpython-compiler")] + #[cfg(feature = "compiler")] { let mode = mode_str .parse::() diff --git a/vm/src/stdlib/mod.rs b/vm/src/stdlib/mod.rs index a3180c1c0..382a8e055 100644 --- a/vm/src/stdlib/mod.rs +++ b/vm/src/stdlib/mod.rs @@ -1,4 +1,4 @@ -#[cfg(feature = "rustpython-ast")] +#[cfg(feature = "ast")] pub(crate) mod ast; pub mod atexit; pub mod builtins; @@ -15,7 +15,7 @@ mod operator; // mod re; mod sre; mod string; -#[cfg(feature = "rustpython-compiler")] +#[cfg(feature = "compiler")] mod symtable; mod sysconfigdata; #[cfg(feature = "threading")] @@ -98,12 +98,12 @@ pub fn get_module_inits() -> StdlibMap { sys::sysconfigdata_name() => sysconfigdata::make_module, } // parser related modules: - #[cfg(feature = "rustpython-ast")] + #[cfg(feature = "ast")] { "_ast" => ast::make_module, } // compiler related modules: - #[cfg(feature = "rustpython-compiler")] + #[cfg(feature = "compiler")] { "symtable" => symtable::make_module, } diff --git a/vm/src/vm/compile.rs b/vm/src/vm/compile.rs index a14e986da..f5145e473 100644 --- a/vm/src/vm/compile.rs +++ b/vm/src/vm/compile.rs @@ -23,7 +23,7 @@ impl VirtualMachine { source_path: String, opts: CompileOpts, ) -> Result, CompileError> { - compiler::compile(source, mode, source_path, opts).map(|code| self.ctx.new_code(code)) + compiler::compile(source, mode, &source_path, opts).map(|code| self.ctx.new_code(code)) } pub fn run_script(&self, scope: Scope, path: &str) -> PyResult<()> { diff --git a/vm/src/vm/vm_new.rs b/vm/src/vm/vm_new.rs index bd4239629..01709b687 100644 --- a/vm/src/vm/vm_new.rs +++ b/vm/src/vm/vm_new.rs @@ -256,22 +256,39 @@ impl VirtualMachine { self.new_exception_msg(overflow_error, msg) } - #[cfg(any(feature = "rustpython-parser", feature = "rustpython-codegen"))] + #[cfg(any(feature = "parser", feature = "compiler"))] pub fn new_syntax_error( &self, error: &crate::compiler::CompileError, source: Option<&str>, ) -> PyBaseExceptionRef { - use crate::source_code::SourceLocation; + use crate::source::SourceLocation; - let syntax_error_type = match &error.error { - #[cfg(feature = "rustpython-parser")] - crate::compiler::CompileErrorType::Parse(p) if p.is_indentation_error() => { - self.ctx.exceptions.indentation_error - } - #[cfg(feature = "rustpython-parser")] - crate::compiler::CompileErrorType::Parse(p) if p.is_tab_error() => { - self.ctx.exceptions.tab_error + let syntax_error_type = match &error { + #[cfg(feature = "parser")] + // FIXME: this condition will cause TabError even when the matching actual error is IndentationError + crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { + error: + ruff_python_parser::ParseErrorType::Lexical( + ruff_python_parser::lexer::LexicalErrorType::IndentationError, + ), + .. + }) => self.ctx.exceptions.tab_error, + #[cfg(feature = "parser")] + crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { + error: ruff_python_parser::ParseErrorType::UnexpectedIndentation, + .. + }) => self.ctx.exceptions.indentation_error, + #[cfg(feature = "parser")] + crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { + error: ruff_python_parser::ParseErrorType::OtherError(s), + .. + }) => { + if s.starts_with("Expected an indented block after") { + self.ctx.exceptions.indentation_error + } else { + self.ctx.exceptions.syntax_error + } } _ => self.ctx.exceptions.syntax_error, } @@ -281,18 +298,32 @@ impl VirtualMachine { fn get_statement(source: &str, loc: Option) -> Option { let line = source .split('\n') - .nth(loc?.row.to_zero_indexed_usize())? + .nth(loc?.row.to_zero_indexed())? .to_owned(); Some(line + "\n") } let statement = if let Some(source) = source { - get_statement(source, error.location) + get_statement(source, error.location()) } else { None }; - let syntax_error = self.new_exception_msg(syntax_error_type, error.error.to_string()); + let mut msg = error.to_string(); + if let Some(msg) = msg.get_mut(..1) { + msg.make_ascii_lowercase(); + } + match error { + #[cfg(feature = "parser")] + crate::compiler::CompileError::Parse(rustpython_compiler::ParseError { + error: + ruff_python_parser::ParseErrorType::FStringError(_) + | ruff_python_parser::ParseErrorType::UnexpectedExpressionToken, + .. + }) => msg.insert_str(0, "invalid syntax: "), + _ => {} + } + let syntax_error = self.new_exception_msg(syntax_error_type, msg); let (lineno, offset) = error.python_location(); let lineno = self.ctx.new_int(lineno); let offset = self.ctx.new_int(offset); @@ -311,11 +342,7 @@ impl VirtualMachine { .unwrap(); syntax_error .as_object() - .set_attr( - "filename", - self.ctx.new_str(error.source_path.clone()), - self, - ) + .set_attr("filename", self.ctx.new_str(error.source_path()), self) .unwrap(); syntax_error } diff --git a/wasm/lib/Cargo.toml b/wasm/lib/Cargo.toml index 4703cb9f4..0e35292a2 100644 --- a/wasm/lib/Cargo.toml +++ b/wasm/lib/Cargo.toml @@ -23,7 +23,7 @@ rustpython-stdlib = { workspace = true, default-features = false, optional = tru # make sure no threading! otherwise wasm build will fail rustpython-vm = { workspace = true, features = ["compiler", "encodings", "serde", "wasmbind"] } -rustpython-parser = { workspace = true } +ruff_python_parser = { workspace = true } serde = { workspace = true } wasm-bindgen = { workspace = true } diff --git a/wasm/lib/src/convert.rs b/wasm/lib/src/convert.rs index d4fb068e6..2f8077031 100644 --- a/wasm/lib/src/convert.rs +++ b/wasm/lib/src/convert.rs @@ -3,11 +3,10 @@ use crate::js_module; use crate::vm_class::{WASMVirtualMachine, stored_vm_from_wasm}; use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, SyntaxError, Uint8Array}; -use rustpython_parser::{ParseErrorType, lexer::LexicalErrorType}; use rustpython_vm::{ AsObject, PyObjectRef, PyPayload, PyResult, TryFromBorrowedObject, VirtualMachine, builtins::PyBaseExceptionRef, - compiler::{CompileError, CompileErrorType}, + compiler::{CompileError, ParseError, parser::ParseErrorType, parser::lexer::LexicalErrorType}, exceptions, function::{ArgBytesLike, FuncArgs}, py_serde, @@ -252,21 +251,21 @@ pub fn syntax_err(err: CompileError) -> SyntaxError { let _ = Reflect::set( &js_err, &"row".into(), - &(err.location.unwrap().row.get()).into(), + &(err.location().unwrap().row.get()).into(), ); let _ = Reflect::set( &js_err, &"col".into(), - &(err.location.unwrap().column.get()).into(), + &(err.location().unwrap().column.get()).into(), ); + // | ParseErrorType::UnrecognizedToken(Token::Dedent, _) let can_continue = matches!( - &err.error, - CompileErrorType::Parse( - ParseErrorType::Eof - | ParseErrorType::Lexical(LexicalErrorType::Eof) - | ParseErrorType::Lexical(LexicalErrorType::IndentationError) - | ParseErrorType::UnrecognizedToken(rustpython_parser::Tok::Dedent, _) - ) + &err, + CompileError::Parse(ParseError { + error: ParseErrorType::Lexical(LexicalErrorType::Eof) + | ParseErrorType::Lexical(LexicalErrorType::IndentationError), + .. + }) ); let _ = Reflect::set(&js_err, &"canContinue".into(), &can_continue.into()); js_err