shellsim 0.1.9__tar.gz → 0.1.10__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.
- {shellsim-0.1.9 → shellsim-0.1.10}/Cargo.lock +1 -1
- {shellsim-0.1.9 → shellsim-0.1.10}/Cargo.toml +1 -1
- {shellsim-0.1.9 → shellsim-0.1.10}/PKG-INFO +1 -1
- {shellsim-0.1.9 → shellsim-0.1.10}/python/native/Cargo.lock +2 -2
- {shellsim-0.1.9 → shellsim-0.1.10}/python/native/Cargo.toml +1 -1
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/ast.rs +15 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/bytecode.rs +13 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/compiler.rs +135 -1
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/heap.rs +8 -1
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/lexer.rs +2 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/mod.rs +1 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/native.rs +3 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/parser.rs +40 -9
- shellsim-0.1.10/src/python/stdlib/asyncio.rs +47 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/frozen.rs +1 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/mod.rs +2 -0
- shellsim-0.1.10/src/python/stdlib/source/asyncio.py +364 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/token.rs +2 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm/calls.rs +2 -1
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm/dispatch.rs +65 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm/iteration.rs +15 -1
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm/namespace.rs +10 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm/native_runtime.rs +37 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm/objects.rs +26 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm.rs +4 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/LICENSE +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/README.md +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/pyproject.toml +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/python/native/src/lib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/python/shellsim/__init__.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/python/shellsim/__main__.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/python/shellsim/_api.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/python/shellsim/_cli.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/python/shellsim/py.typed +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/python/shellsim/python.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/rust-toolchain.toml +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/bin/shellsim-python.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/clock.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/archives.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/awk/ast.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/awk/eval.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/awk/lexer.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/awk/parser.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/awk.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/builtins.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/dd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/echo.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/find.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/fs.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/apply.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/commit.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/compare.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/config.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/conflict.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/diff.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/ignore.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/import.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/log.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/merge.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/mod.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/plumbing.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/rebase.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/refs.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/repo.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/stash.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/switch.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/git/worktree.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/hashing.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/makecmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/mod.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/net.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/options.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/patch.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/pkg.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/printf.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/proc.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/regex_compat.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/rgcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/sed.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/sort.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/system.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/tarcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/text.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/unavailable.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/util.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/commands/zipcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/descriptors.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/exec.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/expand.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/harness.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/harness_manager.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/hashes.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/host_ingest.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/interp.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/jqcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/lib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/main.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/mcp.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/net.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/netcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/process.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/pseudo_fs.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/filesystem.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/http.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/mapping.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/number.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/object_model.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/process.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/protocol.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/slice.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/source.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/argparse.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/base64.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/bisect.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/collections.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/core.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/dataclasses.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/enum.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/functools.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/hashlib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/heapq.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/http.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/importlib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/itertools.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/json.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/math.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/numpy.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/os.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/pytest.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/re.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/abc.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/base64.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/cmath.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/codecs.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/collections.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/complex.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/copy.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/csv.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/datetime.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/glob.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/hashlib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/http.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/http_client.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/importlib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/io.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/json.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/logging.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/numpy_random.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/os.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/pathlib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/pytest.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/random.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/shutil.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/statistics.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/struct.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/subprocess.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/tempfile.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/textwrap.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/urllib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/urllib_error.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/urllib_request.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/uuid.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/zipfile.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/source/zlib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/string.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/struct.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/subprocess.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/sys.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/time.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/typing.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/unittest.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/vfs.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/stdlib/zlib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/string.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm/host.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/python/vm/operations.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/resources.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/sandbox.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/scenario.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/scheduler.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/shell.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/telemetry.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.10}/src/vfs.rs +0 -0
|
@@ -406,7 +406,7 @@ dependencies = [
|
|
|
406
406
|
|
|
407
407
|
[[package]]
|
|
408
408
|
name = "shellsim"
|
|
409
|
-
version = "0.1.
|
|
409
|
+
version = "0.1.10"
|
|
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.
|
|
430
|
+
version = "0.1.10"
|
|
431
431
|
dependencies = [
|
|
432
432
|
"pyo3",
|
|
433
433
|
"serde",
|
|
@@ -50,10 +50,17 @@ pub enum StatementKind {
|
|
|
50
50
|
body: Vec<Statement>,
|
|
51
51
|
otherwise: Vec<Statement>,
|
|
52
52
|
},
|
|
53
|
+
AsyncFor {
|
|
54
|
+
target: AssignmentTarget,
|
|
55
|
+
iterable: Expression,
|
|
56
|
+
body: Vec<Statement>,
|
|
57
|
+
otherwise: Vec<Statement>,
|
|
58
|
+
},
|
|
53
59
|
Function {
|
|
54
60
|
name: String,
|
|
55
61
|
parameters: Vec<Parameter>,
|
|
56
62
|
body: Vec<Statement>,
|
|
63
|
+
is_async: bool,
|
|
57
64
|
},
|
|
58
65
|
Class {
|
|
59
66
|
name: String,
|
|
@@ -91,6 +98,11 @@ pub enum StatementKind {
|
|
|
91
98
|
target: Option<AssignmentTarget>,
|
|
92
99
|
body: Vec<Statement>,
|
|
93
100
|
},
|
|
101
|
+
AsyncWith {
|
|
102
|
+
context: Expression,
|
|
103
|
+
target: Option<AssignmentTarget>,
|
|
104
|
+
body: Vec<Statement>,
|
|
105
|
+
},
|
|
94
106
|
}
|
|
95
107
|
|
|
96
108
|
#[derive(Clone, Debug, PartialEq)]
|
|
@@ -122,11 +134,13 @@ impl StatementKind {
|
|
|
122
134
|
Self::If { .. }
|
|
123
135
|
| Self::While { .. }
|
|
124
136
|
| Self::For { .. }
|
|
137
|
+
| Self::AsyncFor { .. }
|
|
125
138
|
| Self::Function { .. }
|
|
126
139
|
| Self::Class { .. }
|
|
127
140
|
| Self::Decorated { .. }
|
|
128
141
|
| Self::Try { .. }
|
|
129
142
|
| Self::With { .. }
|
|
143
|
+
| Self::AsyncWith { .. }
|
|
130
144
|
)
|
|
131
145
|
}
|
|
132
146
|
}
|
|
@@ -180,6 +194,7 @@ pub enum ExpressionKind {
|
|
|
180
194
|
},
|
|
181
195
|
Yield(Option<Box<Expression>>),
|
|
182
196
|
YieldFrom(Box<Expression>),
|
|
197
|
+
Await(Box<Expression>),
|
|
183
198
|
Attribute {
|
|
184
199
|
value: Box<Expression>,
|
|
185
200
|
name: String,
|
|
@@ -65,6 +65,7 @@ pub struct Code {
|
|
|
65
65
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
66
66
|
pub struct CallSignature {
|
|
67
67
|
pub is_generator: bool,
|
|
68
|
+
pub is_coroutine: bool,
|
|
68
69
|
pub positional_count: usize,
|
|
69
70
|
pub variadic_slot: Option<usize>,
|
|
70
71
|
pub default_slots: Box<[usize]>,
|
|
@@ -223,9 +224,12 @@ pub enum Opcode {
|
|
|
223
224
|
Reraise,
|
|
224
225
|
Raise(bool),
|
|
225
226
|
Yield,
|
|
227
|
+
AwaitResult,
|
|
226
228
|
WithEnter,
|
|
227
229
|
WithExit,
|
|
228
230
|
WithExitException,
|
|
231
|
+
AsyncWithExitException,
|
|
232
|
+
AsyncWithFinishException,
|
|
229
233
|
PopExpression,
|
|
230
234
|
Halt,
|
|
231
235
|
}
|
|
@@ -321,9 +325,13 @@ pub enum Operation {
|
|
|
321
325
|
Raise(bool),
|
|
322
326
|
/// Suspend a generator frame and return the value on top of the stack.
|
|
323
327
|
Yield,
|
|
328
|
+
/// Unwrap the scheduler outcome sent into a suspended coroutine.
|
|
329
|
+
AwaitResult,
|
|
324
330
|
WithEnter,
|
|
325
331
|
WithExit,
|
|
326
332
|
WithExitException,
|
|
333
|
+
AsyncWithExitException,
|
|
334
|
+
AsyncWithFinishException,
|
|
327
335
|
PopExpression,
|
|
328
336
|
Halt,
|
|
329
337
|
}
|
|
@@ -489,9 +497,12 @@ impl CodeBuilder {
|
|
|
489
497
|
Operation::Reraise => Opcode::Reraise,
|
|
490
498
|
Operation::Raise(cause) => Opcode::Raise(cause),
|
|
491
499
|
Operation::Yield => Opcode::Yield,
|
|
500
|
+
Operation::AwaitResult => Opcode::AwaitResult,
|
|
492
501
|
Operation::WithEnter => Opcode::WithEnter,
|
|
493
502
|
Operation::WithExit => Opcode::WithExit,
|
|
494
503
|
Operation::WithExitException => Opcode::WithExitException,
|
|
504
|
+
Operation::AsyncWithExitException => Opcode::AsyncWithExitException,
|
|
505
|
+
Operation::AsyncWithFinishException => Opcode::AsyncWithFinishException,
|
|
495
506
|
Operation::PopExpression => Opcode::PopExpression,
|
|
496
507
|
Operation::Halt => Opcode::Halt,
|
|
497
508
|
}
|
|
@@ -503,6 +514,7 @@ impl CodeBuilder {
|
|
|
503
514
|
spans: Vec<Span>,
|
|
504
515
|
parameters: Vec<Parameter>,
|
|
505
516
|
local_names: Vec<String>,
|
|
517
|
+
is_coroutine: bool,
|
|
506
518
|
) -> CodeRef {
|
|
507
519
|
let positional_count = parameters
|
|
508
520
|
.iter()
|
|
@@ -512,6 +524,7 @@ impl CodeBuilder {
|
|
|
512
524
|
is_generator: instructions
|
|
513
525
|
.iter()
|
|
514
526
|
.any(|instruction| matches!(instruction.opcode, Opcode::Yield)),
|
|
527
|
+
is_coroutine,
|
|
515
528
|
positional_count,
|
|
516
529
|
variadic_slot: parameters.iter().position(|parameter| parameter.variadic),
|
|
517
530
|
default_slots: parameters
|
|
@@ -15,6 +15,7 @@ pub fn compile(program: Program) -> CodeRef {
|
|
|
15
15
|
finalizers: Vec::new(),
|
|
16
16
|
protected_regions: Vec::new(),
|
|
17
17
|
in_function: false,
|
|
18
|
+
is_coroutine: false,
|
|
18
19
|
globals: HashSet::new(),
|
|
19
20
|
nonlocals: HashSet::new(),
|
|
20
21
|
named_expression: NamedExpressionContext::local(),
|
|
@@ -38,6 +39,7 @@ struct Compiler {
|
|
|
38
39
|
/// at compile time rather than losing that state in a suspended generator.
|
|
39
40
|
protected_regions: Vec<&'static str>,
|
|
40
41
|
in_function: bool,
|
|
42
|
+
is_coroutine: bool,
|
|
41
43
|
globals: HashSet<String>,
|
|
42
44
|
nonlocals: HashSet<String>,
|
|
43
45
|
named_expression: NamedExpressionContext,
|
|
@@ -155,7 +157,7 @@ impl Compiler {
|
|
|
155
157
|
});
|
|
156
158
|
spans.push(instruction.span);
|
|
157
159
|
}
|
|
158
|
-
builder.finish(bytecode, spans, parameters, local_names)
|
|
160
|
+
builder.finish(bytecode, spans, parameters, local_names, self.is_coroutine)
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
fn statements(&mut self, statements: Vec<Statement>) {
|
|
@@ -320,10 +322,70 @@ impl Compiler {
|
|
|
320
322
|
let finished = self.instructions.len();
|
|
321
323
|
self.finish_loop(finished);
|
|
322
324
|
}
|
|
325
|
+
StatementKind::AsyncFor {
|
|
326
|
+
target,
|
|
327
|
+
iterable,
|
|
328
|
+
body,
|
|
329
|
+
otherwise,
|
|
330
|
+
} => {
|
|
331
|
+
let iterator_name =
|
|
332
|
+
format!("$__shellsim_async_iterator_{}", self.instructions.len());
|
|
333
|
+
self.expression(iterable);
|
|
334
|
+
self.emit(Operation::LoadAttribute("__aiter__".into()), span);
|
|
335
|
+
self.emit(
|
|
336
|
+
Operation::Call {
|
|
337
|
+
positional: 0,
|
|
338
|
+
keywords: Vec::new(),
|
|
339
|
+
starred: Vec::new(),
|
|
340
|
+
},
|
|
341
|
+
span,
|
|
342
|
+
);
|
|
343
|
+
self.emit(Operation::StoreName(iterator_name.clone()), span);
|
|
344
|
+
let next = self.instructions.len();
|
|
345
|
+
let begin = self.emit(Operation::TryBegin(usize::MAX), span);
|
|
346
|
+
self.emit(Operation::LoadName(iterator_name), span);
|
|
347
|
+
self.emit(Operation::LoadAttribute("__anext__".into()), span);
|
|
348
|
+
self.emit(
|
|
349
|
+
Operation::Call {
|
|
350
|
+
positional: 0,
|
|
351
|
+
keywords: Vec::new(),
|
|
352
|
+
starred: Vec::new(),
|
|
353
|
+
},
|
|
354
|
+
span,
|
|
355
|
+
);
|
|
356
|
+
self.emit(Operation::Yield, span);
|
|
357
|
+
self.emit(Operation::AwaitResult, span);
|
|
358
|
+
self.emit(Operation::TryEnd, span);
|
|
359
|
+
self.store_target(target, span);
|
|
360
|
+
self.loops.push(LoopContext {
|
|
361
|
+
continue_target: next,
|
|
362
|
+
iterator_on_stack: false,
|
|
363
|
+
finalizer_depth: self.finalizers.len(),
|
|
364
|
+
breaks: Vec::new(),
|
|
365
|
+
});
|
|
366
|
+
self.statements(body);
|
|
367
|
+
self.emit(Operation::Jump(next), span);
|
|
368
|
+
let handler = self.instructions.len();
|
|
369
|
+
self.patch_try_begin(begin, handler);
|
|
370
|
+
self.emit(Operation::LoadName("StopAsyncIteration".into()), span);
|
|
371
|
+
self.emit(Operation::MatchException { typed: true }, span);
|
|
372
|
+
let rethrow = self.emit(Operation::PopJumpIfFalse(usize::MAX), span);
|
|
373
|
+
self.emit(Operation::PopTop, span);
|
|
374
|
+
self.emit(Operation::ClearException, span);
|
|
375
|
+
self.statements(otherwise);
|
|
376
|
+
let done = self.emit(Operation::Jump(usize::MAX), span);
|
|
377
|
+
self.patch_jump(rethrow, self.instructions.len());
|
|
378
|
+
self.emit(Operation::PopTop, span);
|
|
379
|
+
self.emit(Operation::Reraise, span);
|
|
380
|
+
let finished = self.instructions.len();
|
|
381
|
+
self.patch_jump(done, finished);
|
|
382
|
+
self.finish_loop(finished);
|
|
383
|
+
}
|
|
323
384
|
StatementKind::Function {
|
|
324
385
|
name,
|
|
325
386
|
parameters,
|
|
326
387
|
body,
|
|
388
|
+
is_async,
|
|
327
389
|
} => {
|
|
328
390
|
let defaults = parameters
|
|
329
391
|
.iter()
|
|
@@ -338,6 +400,7 @@ impl Compiler {
|
|
|
338
400
|
finalizers: Vec::new(),
|
|
339
401
|
protected_regions: Vec::new(),
|
|
340
402
|
in_function: true,
|
|
403
|
+
is_coroutine: is_async,
|
|
341
404
|
globals: HashSet::new(),
|
|
342
405
|
nonlocals: HashSet::new(),
|
|
343
406
|
named_expression: NamedExpressionContext::local(),
|
|
@@ -391,6 +454,7 @@ impl Compiler {
|
|
|
391
454
|
finalizers: Vec::new(),
|
|
392
455
|
protected_regions: Vec::new(),
|
|
393
456
|
in_function: false,
|
|
457
|
+
is_coroutine: false,
|
|
394
458
|
globals: HashSet::new(),
|
|
395
459
|
nonlocals: HashSet::new(),
|
|
396
460
|
named_expression: NamedExpressionContext::local(),
|
|
@@ -660,6 +724,60 @@ impl Compiler {
|
|
|
660
724
|
self.emit(Operation::WithExitException, span);
|
|
661
725
|
self.patch_jump(done, self.instructions.len());
|
|
662
726
|
}
|
|
727
|
+
StatementKind::AsyncWith {
|
|
728
|
+
context,
|
|
729
|
+
target,
|
|
730
|
+
body,
|
|
731
|
+
} => {
|
|
732
|
+
let context_name = format!("$__shellsim_async_context_{}", self.instructions.len());
|
|
733
|
+
self.expression(context);
|
|
734
|
+
self.emit(Operation::StoreName(context_name.clone()), span);
|
|
735
|
+
self.emit(Operation::LoadName(context_name.clone()), span);
|
|
736
|
+
self.emit(Operation::LoadAttribute("__aenter__".into()), span);
|
|
737
|
+
self.emit(
|
|
738
|
+
Operation::Call {
|
|
739
|
+
positional: 0,
|
|
740
|
+
keywords: Vec::new(),
|
|
741
|
+
starred: Vec::new(),
|
|
742
|
+
},
|
|
743
|
+
span,
|
|
744
|
+
);
|
|
745
|
+
self.emit(Operation::Yield, span);
|
|
746
|
+
self.emit(Operation::AwaitResult, span);
|
|
747
|
+
if let Some(target) = target {
|
|
748
|
+
self.store_target(target, span);
|
|
749
|
+
} else {
|
|
750
|
+
self.emit(Operation::PopTop, span);
|
|
751
|
+
}
|
|
752
|
+
let begin = self.emit(Operation::TryBegin(usize::MAX), span);
|
|
753
|
+
self.statements(body);
|
|
754
|
+
self.emit(Operation::TryEnd, span);
|
|
755
|
+
self.emit(Operation::LoadName(context_name.clone()), span);
|
|
756
|
+
self.emit(Operation::LoadAttribute("__aexit__".into()), span);
|
|
757
|
+
for _ in 0..3 {
|
|
758
|
+
self.emit(Operation::LoadConstant(Constant::None), span);
|
|
759
|
+
}
|
|
760
|
+
self.emit(
|
|
761
|
+
Operation::Call {
|
|
762
|
+
positional: 3,
|
|
763
|
+
keywords: Vec::new(),
|
|
764
|
+
starred: vec![false; 3],
|
|
765
|
+
},
|
|
766
|
+
span,
|
|
767
|
+
);
|
|
768
|
+
self.emit(Operation::Yield, span);
|
|
769
|
+
self.emit(Operation::AwaitResult, span);
|
|
770
|
+
self.emit(Operation::PopTop, span);
|
|
771
|
+
let done = self.emit(Operation::Jump(usize::MAX), span);
|
|
772
|
+
let handler = self.instructions.len();
|
|
773
|
+
self.patch_try_begin(begin, handler);
|
|
774
|
+
self.emit(Operation::LoadName(context_name), span);
|
|
775
|
+
self.emit(Operation::AsyncWithExitException, span);
|
|
776
|
+
self.emit(Operation::Yield, span);
|
|
777
|
+
self.emit(Operation::AwaitResult, span);
|
|
778
|
+
self.emit(Operation::AsyncWithFinishException, span);
|
|
779
|
+
self.patch_jump(done, self.instructions.len());
|
|
780
|
+
}
|
|
663
781
|
}
|
|
664
782
|
}
|
|
665
783
|
|
|
@@ -971,6 +1089,18 @@ impl Compiler {
|
|
|
971
1089
|
self.emit(Operation::LoadConstant(Constant::None), span);
|
|
972
1090
|
}
|
|
973
1091
|
}
|
|
1092
|
+
ExpressionKind::Await(value) => {
|
|
1093
|
+
if !self.is_coroutine {
|
|
1094
|
+
self.emit(
|
|
1095
|
+
Operation::RuntimeError("'await' outside async function".into()),
|
|
1096
|
+
span,
|
|
1097
|
+
);
|
|
1098
|
+
} else {
|
|
1099
|
+
self.expression(*value);
|
|
1100
|
+
self.emit(Operation::Yield, span);
|
|
1101
|
+
self.emit(Operation::AwaitResult, span);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
974
1104
|
ExpressionKind::Attribute { value, name } => {
|
|
975
1105
|
self.expression(*value);
|
|
976
1106
|
self.emit(Operation::LoadAttribute(name), span);
|
|
@@ -1042,6 +1172,7 @@ impl Compiler {
|
|
|
1042
1172
|
finalizers: Vec::new(),
|
|
1043
1173
|
protected_regions: Vec::new(),
|
|
1044
1174
|
in_function: true,
|
|
1175
|
+
is_coroutine: false,
|
|
1045
1176
|
globals: HashSet::new(),
|
|
1046
1177
|
nonlocals: HashSet::new(),
|
|
1047
1178
|
named_expression: NamedExpressionContext::local(),
|
|
@@ -1190,6 +1321,7 @@ impl Compiler {
|
|
|
1190
1321
|
finalizers: Vec::new(),
|
|
1191
1322
|
protected_regions: Vec::new(),
|
|
1192
1323
|
in_function: true,
|
|
1324
|
+
is_coroutine: false,
|
|
1193
1325
|
globals: HashSet::new(),
|
|
1194
1326
|
nonlocals: HashSet::new(),
|
|
1195
1327
|
named_expression,
|
|
@@ -1239,6 +1371,7 @@ impl Compiler {
|
|
|
1239
1371
|
finalizers: Vec::new(),
|
|
1240
1372
|
protected_regions: Vec::new(),
|
|
1241
1373
|
in_function: true,
|
|
1374
|
+
is_coroutine: false,
|
|
1242
1375
|
globals: HashSet::new(),
|
|
1243
1376
|
nonlocals: HashSet::new(),
|
|
1244
1377
|
named_expression,
|
|
@@ -1280,6 +1413,7 @@ impl Compiler {
|
|
|
1280
1413
|
finalizers: Vec::new(),
|
|
1281
1414
|
protected_regions: Vec::new(),
|
|
1282
1415
|
in_function: true,
|
|
1416
|
+
is_coroutine: false,
|
|
1283
1417
|
globals: HashSet::new(),
|
|
1284
1418
|
nonlocals: HashSet::new(),
|
|
1285
1419
|
named_expression,
|
|
@@ -212,6 +212,7 @@ pub enum Object {
|
|
|
212
212
|
stack: Vec<Value>,
|
|
213
213
|
exhausted: bool,
|
|
214
214
|
running: bool,
|
|
215
|
+
return_value: Value,
|
|
215
216
|
},
|
|
216
217
|
Module {
|
|
217
218
|
name: String,
|
|
@@ -1430,9 +1431,15 @@ fn trace_object(
|
|
|
1430
1431
|
trace_value(*callable, object_work);
|
|
1431
1432
|
trace_value(*sentinel, object_work);
|
|
1432
1433
|
}
|
|
1433
|
-
Object::Generator {
|
|
1434
|
+
Object::Generator {
|
|
1435
|
+
scope,
|
|
1436
|
+
stack,
|
|
1437
|
+
return_value,
|
|
1438
|
+
..
|
|
1439
|
+
} => {
|
|
1434
1440
|
scope_work.push(*scope);
|
|
1435
1441
|
trace_values(stack.iter().copied(), object_work);
|
|
1442
|
+
trace_value(*return_value, object_work);
|
|
1436
1443
|
}
|
|
1437
1444
|
Object::Module { scope, .. } => scope_work.push(*scope),
|
|
1438
1445
|
Object::Array { storage, .. } => object_work.push(*storage),
|
|
@@ -452,6 +452,9 @@ pub(super) trait PyRuntime {
|
|
|
452
452
|
generator: PyIterator,
|
|
453
453
|
value: PyValue,
|
|
454
454
|
) -> PyResult<Option<PyValue>>;
|
|
455
|
+
fn generator_return_value(&self, generator: PyIterator) -> PyResult<PyValue>;
|
|
456
|
+
/// Resume a coroutine and return 0 for yield, 1 for return, or 2 for an exception.
|
|
457
|
+
fn coroutine_step(&mut self, coroutine: PyIterator, value: PyValue) -> PyResult<(u8, PyValue)>;
|
|
455
458
|
fn generator_close(&mut self, generator: PyIterator) -> PyResult<()>;
|
|
456
459
|
fn generator_throw(&mut self, generator: PyIterator, exception: PyValue) -> PyResult;
|
|
457
460
|
fn new_iterator(&mut self, values: Vec<PyValue>) -> PyResult<PyValue>;
|
|
@@ -90,6 +90,12 @@ impl Parser {
|
|
|
90
90
|
)?;
|
|
91
91
|
self.separators();
|
|
92
92
|
}
|
|
93
|
+
let is_async = self.take(|kind| matches!(kind, TokenKind::Async)).is_some();
|
|
94
|
+
if is_async
|
|
95
|
+
&& !self.at(|kind| matches!(kind, TokenKind::Def | TokenKind::For | TokenKind::With))
|
|
96
|
+
{
|
|
97
|
+
return Err(self.error("expected 'def', 'for', or 'with' after 'async'"));
|
|
98
|
+
}
|
|
93
99
|
let kind = if self.take(|kind| matches!(kind, TokenKind::If)).is_some() {
|
|
94
100
|
self.if_statement(start)?
|
|
95
101
|
} else if self.take(|kind| matches!(kind, TokenKind::Try)).is_some() {
|
|
@@ -145,10 +151,18 @@ impl Parser {
|
|
|
145
151
|
None
|
|
146
152
|
};
|
|
147
153
|
let body = self.suite()?;
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
154
|
+
if is_async {
|
|
155
|
+
StatementKind::AsyncWith {
|
|
156
|
+
context,
|
|
157
|
+
target,
|
|
158
|
+
body,
|
|
159
|
+
}
|
|
160
|
+
} else {
|
|
161
|
+
StatementKind::With {
|
|
162
|
+
context,
|
|
163
|
+
target,
|
|
164
|
+
body,
|
|
165
|
+
}
|
|
152
166
|
}
|
|
153
167
|
} else if self.take(|kind| matches!(kind, TokenKind::While)).is_some() {
|
|
154
168
|
let test = self.expression()?;
|
|
@@ -176,11 +190,20 @@ impl Parser {
|
|
|
176
190
|
} else {
|
|
177
191
|
Vec::new()
|
|
178
192
|
};
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
193
|
+
if is_async {
|
|
194
|
+
StatementKind::AsyncFor {
|
|
195
|
+
target,
|
|
196
|
+
iterable,
|
|
197
|
+
body,
|
|
198
|
+
otherwise,
|
|
199
|
+
}
|
|
200
|
+
} else {
|
|
201
|
+
StatementKind::For {
|
|
202
|
+
target,
|
|
203
|
+
iterable,
|
|
204
|
+
body,
|
|
205
|
+
otherwise,
|
|
206
|
+
}
|
|
184
207
|
}
|
|
185
208
|
} else if self.take(|kind| matches!(kind, TokenKind::Def)).is_some() {
|
|
186
209
|
let name = self.name("expected a function name after 'def'")?;
|
|
@@ -257,6 +280,7 @@ impl Parser {
|
|
|
257
280
|
name,
|
|
258
281
|
parameters,
|
|
259
282
|
body: self.suite()?,
|
|
283
|
+
is_async,
|
|
260
284
|
}
|
|
261
285
|
} else if self.take(|kind| matches!(kind, TokenKind::Class)).is_some() {
|
|
262
286
|
let name = self.name("expected a class name after 'class'")?;
|
|
@@ -1180,6 +1204,13 @@ impl Parser {
|
|
|
1180
1204
|
|
|
1181
1205
|
fn unary(&mut self) -> Result<Expression, ParseError> {
|
|
1182
1206
|
let start = self.peek().span;
|
|
1207
|
+
if self.take(|kind| matches!(kind, TokenKind::Await)).is_some() {
|
|
1208
|
+
let value = self.postfix()?;
|
|
1209
|
+
return Ok(Expression {
|
|
1210
|
+
span: start.through(value.span),
|
|
1211
|
+
kind: ExpressionKind::Await(Box::new(value)),
|
|
1212
|
+
});
|
|
1213
|
+
}
|
|
1183
1214
|
let operator = if self.take(|kind| matches!(kind, TokenKind::Plus)).is_some() {
|
|
1184
1215
|
Some(UnaryOperator::Positive)
|
|
1185
1216
|
} else if self.take(|kind| matches!(kind, TokenKind::Minus)).is_some() {
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
//! VM primitives used by the capability-free `asyncio` compatibility module.
|
|
2
|
+
//!
|
|
3
|
+
//! Scheduling policy stays in frozen Python. This module exposes only bounded coroutine frame
|
|
4
|
+
//! stepping so the facade cannot acquire host threads, clocks, or I/O capabilities.
|
|
5
|
+
|
|
6
|
+
use super::super::native::{
|
|
7
|
+
CallArgs, FunctionDef, ModuleDef, PyError, PyIterator, PyKind, PyResult, PyRuntime, PyValueCast,
|
|
8
|
+
};
|
|
9
|
+
use super::super::Value;
|
|
10
|
+
|
|
11
|
+
pub(super) static MODULE: ModuleDef = ModuleDef {
|
|
12
|
+
name: "_asyncio",
|
|
13
|
+
functions: &[
|
|
14
|
+
FunctionDef {
|
|
15
|
+
module: "_asyncio",
|
|
16
|
+
name: "_step",
|
|
17
|
+
call: step,
|
|
18
|
+
},
|
|
19
|
+
FunctionDef {
|
|
20
|
+
module: "_asyncio",
|
|
21
|
+
name: "_is_coroutine",
|
|
22
|
+
call: is_coroutine,
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
values: &[],
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
fn step(runtime: &mut dyn PyRuntime, args: CallArgs) -> PyResult {
|
|
29
|
+
args.expect_positional("_asyncio._step", 2, 2)?;
|
|
30
|
+
args.reject_keywords("_asyncio._step")?;
|
|
31
|
+
let coroutine = args.positional()[0];
|
|
32
|
+
if runtime.kind(&coroutine)? != PyKind::Generator {
|
|
33
|
+
return Err(PyError::type_error("expected a coroutine"));
|
|
34
|
+
}
|
|
35
|
+
let iterator = coroutine.cast::<PyIterator>(runtime)?;
|
|
36
|
+
let sent = args.positional()[1];
|
|
37
|
+
let (status, value) = runtime.coroutine_step(iterator, sent)?;
|
|
38
|
+
runtime.new_tuple(vec![Value::Int(i64::from(status)), value])
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fn is_coroutine(runtime: &mut dyn PyRuntime, args: CallArgs) -> PyResult {
|
|
42
|
+
args.expect_positional("_asyncio._is_coroutine", 1, 1)?;
|
|
43
|
+
args.reject_keywords("_asyncio._is_coroutine")?;
|
|
44
|
+
Ok(Value::Bool(
|
|
45
|
+
runtime.kind(&args.positional()[0])? == PyKind::Generator,
|
|
46
|
+
))
|
|
47
|
+
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
/// cannot accidentally expose build-machine files at runtime.
|
|
8
8
|
pub(super) fn module_source(name: &str) -> Option<&'static str> {
|
|
9
9
|
match name {
|
|
10
|
+
"asyncio" => Some(include_str!("source/asyncio.py")),
|
|
10
11
|
"abc" => Some(include_str!("source/abc.py")),
|
|
11
12
|
"base64" => Some(include_str!("source/base64.py")),
|
|
12
13
|
"codecs" => Some(include_str!("source/codecs.py")),
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
//! Keeping this directory self-contained makes each shim straightforward to review and test.
|
|
5
5
|
|
|
6
6
|
pub mod argparse;
|
|
7
|
+
mod asyncio;
|
|
7
8
|
mod base64;
|
|
8
9
|
pub mod bisect;
|
|
9
10
|
pub mod collections;
|
|
@@ -57,6 +58,7 @@ pub(super) fn frozen_builtin(name: &str) -> Option<(&'static str, &'static str)>
|
|
|
57
58
|
/// Resolve one capability-free module through the declarative native registry.
|
|
58
59
|
pub(super) fn native_module(name: &str) -> Option<&'static ModuleDef> {
|
|
59
60
|
match name {
|
|
61
|
+
"_asyncio" => Some(&asyncio::MODULE),
|
|
60
62
|
"argparse" => Some(&argparse::MODULE),
|
|
61
63
|
"_base64" => Some(&base64::MODULE),
|
|
62
64
|
"_json" => Some(&json::MODULE),
|