shellsim 0.1.8__tar.gz → 0.1.9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. {shellsim-0.1.8 → shellsim-0.1.9}/Cargo.lock +1 -1
  2. {shellsim-0.1.8 → shellsim-0.1.9}/Cargo.toml +1 -1
  3. {shellsim-0.1.8 → shellsim-0.1.9}/PKG-INFO +1 -1
  4. {shellsim-0.1.8 → shellsim-0.1.9}/python/native/Cargo.lock +2 -2
  5. {shellsim-0.1.8 → shellsim-0.1.9}/python/native/Cargo.toml +1 -1
  6. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/ast.rs +2 -3
  7. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/compiler.rs +88 -9
  8. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/mod.rs +443 -28
  9. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/native.rs +7 -0
  10. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/object_model.rs +4 -0
  11. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/parser.rs +7 -0
  12. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/core.rs +45 -2
  13. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/frozen.rs +1 -0
  14. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/mod.rs +1 -1
  15. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/pytest.rs +4 -4
  16. shellsim-0.1.9/src/python/stdlib/source/pytest.py +36 -0
  17. shellsim-0.1.9/src/python/stdlib/typing.rs +136 -0
  18. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm/iteration.rs +12 -3
  19. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm/native_runtime.rs +62 -1
  20. shellsim-0.1.8/src/python/stdlib/typing.rs +0 -45
  21. {shellsim-0.1.8 → shellsim-0.1.9}/LICENSE +0 -0
  22. {shellsim-0.1.8 → shellsim-0.1.9}/README.md +0 -0
  23. {shellsim-0.1.8 → shellsim-0.1.9}/pyproject.toml +0 -0
  24. {shellsim-0.1.8 → shellsim-0.1.9}/python/native/src/lib.rs +0 -0
  25. {shellsim-0.1.8 → shellsim-0.1.9}/python/shellsim/__init__.py +0 -0
  26. {shellsim-0.1.8 → shellsim-0.1.9}/python/shellsim/__main__.py +0 -0
  27. {shellsim-0.1.8 → shellsim-0.1.9}/python/shellsim/_api.py +0 -0
  28. {shellsim-0.1.8 → shellsim-0.1.9}/python/shellsim/_cli.py +0 -0
  29. {shellsim-0.1.8 → shellsim-0.1.9}/python/shellsim/py.typed +0 -0
  30. {shellsim-0.1.8 → shellsim-0.1.9}/python/shellsim/python.py +0 -0
  31. {shellsim-0.1.8 → shellsim-0.1.9}/rust-toolchain.toml +0 -0
  32. {shellsim-0.1.8 → shellsim-0.1.9}/src/bin/shellsim-python.rs +0 -0
  33. {shellsim-0.1.8 → shellsim-0.1.9}/src/clock.rs +0 -0
  34. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/archives.rs +0 -0
  35. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/awk/ast.rs +0 -0
  36. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/awk/eval.rs +0 -0
  37. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/awk/lexer.rs +0 -0
  38. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/awk/parser.rs +0 -0
  39. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/awk.rs +0 -0
  40. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/builtins.rs +0 -0
  41. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/dd.rs +0 -0
  42. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/echo.rs +0 -0
  43. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/find.rs +0 -0
  44. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/fs.rs +0 -0
  45. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/apply.rs +0 -0
  46. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/commit.rs +0 -0
  47. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/compare.rs +0 -0
  48. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/config.rs +0 -0
  49. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/conflict.rs +0 -0
  50. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/diff.rs +0 -0
  51. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/ignore.rs +0 -0
  52. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/import.rs +0 -0
  53. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/log.rs +0 -0
  54. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/merge.rs +0 -0
  55. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/mod.rs +0 -0
  56. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/plumbing.rs +0 -0
  57. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/rebase.rs +0 -0
  58. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/refs.rs +0 -0
  59. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/repo.rs +0 -0
  60. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/stash.rs +0 -0
  61. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/switch.rs +0 -0
  62. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/git/worktree.rs +0 -0
  63. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/hashing.rs +0 -0
  64. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/makecmd.rs +0 -0
  65. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/mod.rs +0 -0
  66. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/net.rs +0 -0
  67. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/options.rs +0 -0
  68. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/patch.rs +0 -0
  69. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/pkg.rs +0 -0
  70. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/printf.rs +0 -0
  71. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/proc.rs +0 -0
  72. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/regex_compat.rs +0 -0
  73. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/rgcmd.rs +0 -0
  74. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/sed.rs +0 -0
  75. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/sort.rs +0 -0
  76. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/system.rs +0 -0
  77. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/tarcmd.rs +0 -0
  78. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/text.rs +0 -0
  79. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/unavailable.rs +0 -0
  80. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/util.rs +0 -0
  81. {shellsim-0.1.8 → shellsim-0.1.9}/src/commands/zipcmd.rs +0 -0
  82. {shellsim-0.1.8 → shellsim-0.1.9}/src/descriptors.rs +0 -0
  83. {shellsim-0.1.8 → shellsim-0.1.9}/src/exec.rs +0 -0
  84. {shellsim-0.1.8 → shellsim-0.1.9}/src/expand.rs +0 -0
  85. {shellsim-0.1.8 → shellsim-0.1.9}/src/harness.rs +0 -0
  86. {shellsim-0.1.8 → shellsim-0.1.9}/src/harness_manager.rs +0 -0
  87. {shellsim-0.1.8 → shellsim-0.1.9}/src/hashes.rs +0 -0
  88. {shellsim-0.1.8 → shellsim-0.1.9}/src/host_ingest.rs +0 -0
  89. {shellsim-0.1.8 → shellsim-0.1.9}/src/interp.rs +0 -0
  90. {shellsim-0.1.8 → shellsim-0.1.9}/src/jqcmd.rs +0 -0
  91. {shellsim-0.1.8 → shellsim-0.1.9}/src/lib.rs +0 -0
  92. {shellsim-0.1.8 → shellsim-0.1.9}/src/main.rs +0 -0
  93. {shellsim-0.1.8 → shellsim-0.1.9}/src/mcp.rs +0 -0
  94. {shellsim-0.1.8 → shellsim-0.1.9}/src/net.rs +0 -0
  95. {shellsim-0.1.8 → shellsim-0.1.9}/src/netcmd.rs +0 -0
  96. {shellsim-0.1.8 → shellsim-0.1.9}/src/process.rs +0 -0
  97. {shellsim-0.1.8 → shellsim-0.1.9}/src/pseudo_fs.rs +0 -0
  98. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/bytecode.rs +0 -0
  99. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/filesystem.rs +0 -0
  100. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/heap.rs +0 -0
  101. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/http.rs +0 -0
  102. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/lexer.rs +0 -0
  103. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/mapping.rs +0 -0
  104. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/number.rs +0 -0
  105. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/process.rs +0 -0
  106. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/protocol.rs +0 -0
  107. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/slice.rs +0 -0
  108. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/source.rs +0 -0
  109. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/argparse.rs +0 -0
  110. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/base64.rs +0 -0
  111. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/bisect.rs +0 -0
  112. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/collections.rs +0 -0
  113. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/dataclasses.rs +0 -0
  114. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/enum.rs +0 -0
  115. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/functools.rs +0 -0
  116. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/hashlib.rs +0 -0
  117. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/heapq.rs +0 -0
  118. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/http.rs +0 -0
  119. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/importlib.rs +0 -0
  120. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/itertools.rs +0 -0
  121. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/json.rs +0 -0
  122. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/math.rs +0 -0
  123. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/numpy.rs +0 -0
  124. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/os.rs +0 -0
  125. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/re.rs +0 -0
  126. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/abc.py +0 -0
  127. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/base64.py +0 -0
  128. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/cmath.py +0 -0
  129. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/codecs.py +0 -0
  130. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/collections.py +0 -0
  131. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/complex.py +0 -0
  132. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/copy.py +0 -0
  133. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/csv.py +0 -0
  134. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/datetime.py +0 -0
  135. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/glob.py +0 -0
  136. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/hashlib.py +0 -0
  137. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/http.py +0 -0
  138. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/http_client.py +0 -0
  139. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/importlib.py +0 -0
  140. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/io.py +0 -0
  141. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/json.py +0 -0
  142. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/logging.py +0 -0
  143. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/numpy_random.py +0 -0
  144. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/os.py +0 -0
  145. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/pathlib.py +0 -0
  146. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/random.py +0 -0
  147. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/shutil.py +0 -0
  148. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/statistics.py +0 -0
  149. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/struct.py +0 -0
  150. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/subprocess.py +0 -0
  151. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/tempfile.py +0 -0
  152. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/textwrap.py +0 -0
  153. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/urllib.py +0 -0
  154. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/urllib_error.py +0 -0
  155. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/urllib_request.py +0 -0
  156. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/uuid.py +0 -0
  157. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/zipfile.py +0 -0
  158. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/source/zlib.py +0 -0
  159. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/string.rs +0 -0
  160. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/struct.rs +0 -0
  161. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/subprocess.rs +0 -0
  162. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/sys.rs +0 -0
  163. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/time.rs +0 -0
  164. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/unittest.rs +0 -0
  165. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/vfs.rs +0 -0
  166. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/stdlib/zlib.rs +0 -0
  167. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/string.rs +0 -0
  168. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/token.rs +0 -0
  169. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm/calls.rs +0 -0
  170. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm/dispatch.rs +0 -0
  171. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm/host.rs +0 -0
  172. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm/namespace.rs +0 -0
  173. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm/objects.rs +0 -0
  174. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm/operations.rs +0 -0
  175. {shellsim-0.1.8 → shellsim-0.1.9}/src/python/vm.rs +0 -0
  176. {shellsim-0.1.8 → shellsim-0.1.9}/src/resources.rs +0 -0
  177. {shellsim-0.1.8 → shellsim-0.1.9}/src/sandbox.rs +0 -0
  178. {shellsim-0.1.8 → shellsim-0.1.9}/src/scenario.rs +0 -0
  179. {shellsim-0.1.8 → shellsim-0.1.9}/src/scheduler.rs +0 -0
  180. {shellsim-0.1.8 → shellsim-0.1.9}/src/shell.rs +0 -0
  181. {shellsim-0.1.8 → shellsim-0.1.9}/src/telemetry.rs +0 -0
  182. {shellsim-0.1.8 → shellsim-0.1.9}/src/vfs.rs +0 -0
@@ -330,7 +330,7 @@ dependencies = [
330
330
 
331
331
  [[package]]
332
332
  name = "shellsim"
333
- version = "0.1.8"
333
+ version = "0.1.9"
334
334
  dependencies = [
335
335
  "base64",
336
336
  "crc32fast",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "shellsim"
3
- version = "0.1.8"
3
+ version = "0.1.9"
4
4
  edition = "2021"
5
5
  description = "In-process BusyBox-like environment for RL rollouts and agent tests"
6
6
  license = "Apache-2.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: shellsim
3
- Version: 0.1.8
3
+ Version: 0.1.9
4
4
  Classifier: Development Status :: 3 - Alpha
5
5
  Classifier: License :: OSI Approved :: Apache Software License
6
6
  Classifier: Operating System :: MacOS :: MacOS X
@@ -406,7 +406,7 @@ dependencies = [
406
406
 
407
407
  [[package]]
408
408
  name = "shellsim"
409
- version = "0.1.8"
409
+ version = "0.1.9"
410
410
  dependencies = [
411
411
  "base64",
412
412
  "crc32fast",
@@ -427,7 +427,7 @@ dependencies = [
427
427
 
428
428
  [[package]]
429
429
  name = "shellsim-python-bindings"
430
- version = "0.1.8"
430
+ version = "0.1.9"
431
431
  dependencies = [
432
432
  "pyo3",
433
433
  "serde",
@@ -2,7 +2,7 @@
2
2
 
3
3
  [package]
4
4
  name = "shellsim-python-bindings"
5
- version = "0.1.8"
5
+ version = "0.1.9"
6
6
  edition = "2021"
7
7
  description = "Python bindings for shellsim"
8
8
  license = "Apache-2.0"
@@ -173,14 +173,13 @@ pub enum ExpressionKind {
173
173
  value: Box<Expression>,
174
174
  clauses: Vec<ComprehensionClause>,
175
175
  },
176
- /// The VM deliberately materializes this as a list for now. This gives
177
- /// generator expressions an ordinary iterable and isolated comprehension
178
- /// scope while keeping the bounded-resource contract simple and explicit.
176
+ /// A lazy comprehension evaluated in its own generator frame.
179
177
  GeneratorExpression {
180
178
  element: Box<Expression>,
181
179
  clauses: Vec<ComprehensionClause>,
182
180
  },
183
181
  Yield(Option<Box<Expression>>),
182
+ YieldFrom(Box<Expression>),
184
183
  Attribute {
185
184
  value: Box<Expression>,
186
185
  name: String,
@@ -936,10 +936,7 @@ impl Compiler {
936
936
  self.emit_dict_comprehension(*key, *value, clauses, span);
937
937
  }
938
938
  ExpressionKind::GeneratorExpression { element, clauses } => {
939
- // The first implementation intentionally materializes generator expressions.
940
- // It is still a separate function scope (like CPython's generator frame), and
941
- // all iteration remains metered by the ordinary bytecode loop.
942
- self.emit_comprehension(ComprehensionKind::List, *element, clauses, span);
939
+ self.emit_generator_expression(*element, clauses, span);
943
940
  }
944
941
  ExpressionKind::Yield(value) => {
945
942
  if !self.in_function {
@@ -947,11 +944,6 @@ impl Compiler {
947
944
  Operation::RuntimeError("'yield' outside function".into()),
948
945
  span,
949
946
  );
950
- } else if let Some(region) = self.protected_regions.last() {
951
- self.emit(
952
- Operation::RuntimeError(format!("yield is not supported inside a {region} cleanup region; suspending here would lose exception or context-manager state")),
953
- span,
954
- );
955
947
  } else {
956
948
  if let Some(value) = value {
957
949
  self.expression(*value);
@@ -961,6 +953,24 @@ impl Compiler {
961
953
  self.emit(Operation::Yield, span);
962
954
  }
963
955
  }
956
+ ExpressionKind::YieldFrom(value) => {
957
+ if !self.in_function {
958
+ self.emit(
959
+ Operation::RuntimeError("'yield from' outside function".into()),
960
+ span,
961
+ );
962
+ } else {
963
+ self.expression(*value);
964
+ self.emit(Operation::GetIterator, span);
965
+ let next = self.emit(Operation::ForIterator(usize::MAX), span);
966
+ self.emit(Operation::Yield, span);
967
+ self.emit(Operation::PopTop, span);
968
+ self.emit(Operation::Jump(next), span);
969
+ let exhausted = self.instructions.len();
970
+ self.patch_jump(next, exhausted);
971
+ self.emit(Operation::LoadConstant(Constant::None), span);
972
+ }
973
+ }
964
974
  ExpressionKind::Attribute { value, name } => {
965
975
  self.expression(*value);
966
976
  self.emit(Operation::LoadAttribute(name), span);
@@ -1216,6 +1226,46 @@ impl Compiler {
1216
1226
  );
1217
1227
  }
1218
1228
 
1229
+ fn emit_generator_expression(
1230
+ &mut self,
1231
+ element: Expression,
1232
+ clauses: Vec<ComprehensionClause>,
1233
+ span: Span,
1234
+ ) {
1235
+ let named_expression = self.comprehension_named_expression_context();
1236
+ let mut nested = Compiler {
1237
+ instructions: Vec::new(),
1238
+ loops: Vec::new(),
1239
+ finalizers: Vec::new(),
1240
+ protected_regions: Vec::new(),
1241
+ in_function: true,
1242
+ globals: HashSet::new(),
1243
+ nonlocals: HashSet::new(),
1244
+ named_expression,
1245
+ is_class_scope: false,
1246
+ structural_depth: self.structural_depth,
1247
+ };
1248
+ nested.emit_generator_comprehension_body(&clauses, 0, &element, span);
1249
+ nested.emit(Operation::LoadConstant(Constant::None), span);
1250
+ nested.emit(Operation::Return, span);
1251
+ self.emit(
1252
+ Operation::MakeFunction {
1253
+ name: "<genexpr>".into(),
1254
+ code: nested.finish(Vec::new()),
1255
+ defaults: 0,
1256
+ },
1257
+ span,
1258
+ );
1259
+ self.emit(
1260
+ Operation::Call {
1261
+ positional: 0,
1262
+ keywords: Vec::new(),
1263
+ starred: Vec::new(),
1264
+ },
1265
+ span,
1266
+ );
1267
+ }
1268
+
1219
1269
  fn emit_dict_comprehension(
1220
1270
  &mut self,
1221
1271
  key: Expression,
@@ -1307,6 +1357,35 @@ impl Compiler {
1307
1357
  self.patch_jump(next, exhausted);
1308
1358
  }
1309
1359
 
1360
+ fn emit_generator_comprehension_body(
1361
+ &mut self,
1362
+ clauses: &[ComprehensionClause],
1363
+ index: usize,
1364
+ element: &Expression,
1365
+ span: Span,
1366
+ ) {
1367
+ let clause = &clauses[index];
1368
+ self.expression(clause.iterable.clone());
1369
+ self.emit(Operation::GetIterator, span);
1370
+ let next = self.emit(Operation::ForIterator(usize::MAX), span);
1371
+ self.store_target(clause.target.clone(), span);
1372
+ for condition in &clause.conditions {
1373
+ self.expression(condition.clone());
1374
+ let skip = self.emit(Operation::PopJumpIfFalse(usize::MAX), span);
1375
+ self.patch_jump(skip, next);
1376
+ }
1377
+ if index + 1 < clauses.len() {
1378
+ self.emit_generator_comprehension_body(clauses, index + 1, element, span);
1379
+ } else {
1380
+ self.expression(element.clone());
1381
+ self.emit(Operation::Yield, span);
1382
+ self.emit(Operation::PopTop, span);
1383
+ }
1384
+ self.emit(Operation::Jump(next), span);
1385
+ let exhausted = self.instructions.len();
1386
+ self.patch_jump(next, exhausted);
1387
+ }
1388
+
1310
1389
  fn emit_dict_comprehension_body(
1311
1390
  &mut self,
1312
1391
  clauses: &[ComprehensionClause],