shellsim 0.1.9__tar.gz → 0.1.11__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.11}/Cargo.lock +1 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/Cargo.toml +1 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/PKG-INFO +1 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/python/native/Cargo.lock +2 -2
- {shellsim-0.1.9 → shellsim-0.1.11}/python/native/Cargo.toml +1 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/src/exec.rs +8 -16
- {shellsim-0.1.9 → shellsim-0.1.11}/src/harness.rs +5 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/ast.rs +15 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/bytecode.rs +13 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/compiler.rs +135 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/heap.rs +8 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/lexer.rs +2 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/mod.rs +1 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/native.rs +23 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/parser.rs +40 -9
- shellsim-0.1.11/src/python/stdlib/asyncio.rs +232 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/frozen.rs +1 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/mod.rs +2 -0
- shellsim-0.1.11/src/python/stdlib/source/asyncio.py +555 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/token.rs +2 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm/calls.rs +2 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm/dispatch.rs +65 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm/host.rs +25 -2
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm/iteration.rs +15 -1
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm/namespace.rs +10 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm/native_runtime.rs +108 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm/objects.rs +26 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm.rs +10 -5
- {shellsim-0.1.9 → shellsim-0.1.11}/src/scheduler.rs +84 -31
- {shellsim-0.1.9 → shellsim-0.1.11}/LICENSE +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/README.md +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/pyproject.toml +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/python/native/src/lib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/python/shellsim/__init__.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/python/shellsim/__main__.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/python/shellsim/_api.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/python/shellsim/_cli.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/python/shellsim/py.typed +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/python/shellsim/python.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/rust-toolchain.toml +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/bin/shellsim-python.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/clock.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/archives.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/awk/ast.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/awk/eval.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/awk/lexer.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/awk/parser.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/awk.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/builtins.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/dd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/echo.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/find.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/fs.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/apply.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/commit.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/compare.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/config.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/conflict.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/diff.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/ignore.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/import.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/log.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/merge.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/mod.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/plumbing.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/rebase.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/refs.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/repo.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/stash.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/switch.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/git/worktree.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/hashing.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/makecmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/mod.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/net.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/options.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/patch.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/pkg.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/printf.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/proc.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/regex_compat.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/rgcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/sed.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/sort.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/system.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/tarcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/text.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/unavailable.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/util.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/commands/zipcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/descriptors.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/expand.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/harness_manager.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/hashes.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/host_ingest.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/interp.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/jqcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/lib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/main.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/mcp.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/net.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/netcmd.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/process.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/pseudo_fs.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/filesystem.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/http.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/mapping.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/number.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/object_model.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/process.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/protocol.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/slice.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/source.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/argparse.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/base64.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/bisect.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/collections.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/core.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/dataclasses.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/enum.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/functools.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/hashlib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/heapq.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/http.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/importlib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/itertools.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/json.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/math.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/numpy.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/os.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/pytest.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/re.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/abc.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/base64.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/cmath.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/codecs.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/collections.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/complex.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/copy.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/csv.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/datetime.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/glob.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/hashlib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/http.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/http_client.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/importlib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/io.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/json.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/logging.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/numpy_random.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/os.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/pathlib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/pytest.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/random.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/shutil.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/statistics.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/struct.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/subprocess.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/tempfile.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/textwrap.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/urllib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/urllib_error.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/urllib_request.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/uuid.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/zipfile.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/source/zlib.py +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/string.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/struct.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/subprocess.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/sys.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/time.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/typing.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/unittest.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/vfs.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/stdlib/zlib.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/string.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/python/vm/operations.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/resources.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/sandbox.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/scenario.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/shell.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/src/telemetry.rs +0 -0
- {shellsim-0.1.9 → shellsim-0.1.11}/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.11"
|
|
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.11"
|
|
431
431
|
dependencies = [
|
|
432
432
|
"pyo3",
|
|
433
433
|
"serde",
|
|
@@ -405,7 +405,7 @@ enum ExpansionLocation {
|
|
|
405
405
|
Redirect(usize),
|
|
406
406
|
}
|
|
407
407
|
|
|
408
|
-
#[derive(Clone,
|
|
408
|
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
409
409
|
pub(crate) enum ShellPoll {
|
|
410
410
|
Pending,
|
|
411
411
|
Blocked(crate::scheduler::WaitReason),
|
|
@@ -2507,21 +2507,13 @@ fn handle_ready_events(interp: &mut Interp) -> Result<(), String> {
|
|
|
2507
2507
|
continue;
|
|
2508
2508
|
};
|
|
2509
2509
|
let deadline = event.id.deadline_ns();
|
|
2510
|
-
let timed_wait =
|
|
2511
|
-
|
|
2512
|
-
Some(crate::scheduler::TaskState::
|
|
2513
|
-
crate::scheduler::
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
| Some(crate::scheduler::TaskState::Stopped(
|
|
2518
|
-
crate::scheduler::StoppedTask::Blocked(
|
|
2519
|
-
crate::scheduler::WaitReason::Timer(value)
|
|
2520
|
-
| crate::scheduler::WaitReason::ChildDeadline(_, value)
|
|
2521
|
-
| crate::scheduler::WaitReason::ChildActivityDeadline(_, value)
|
|
2522
|
-
)
|
|
2523
|
-
)) if value == deadline
|
|
2524
|
-
);
|
|
2510
|
+
let timed_wait = match interp.scheduler.state(pid) {
|
|
2511
|
+
Some(crate::scheduler::TaskState::Blocked(reason))
|
|
2512
|
+
| Some(crate::scheduler::TaskState::Stopped(
|
|
2513
|
+
crate::scheduler::StoppedTask::Blocked(reason),
|
|
2514
|
+
)) => reason.accepts_timer(deadline),
|
|
2515
|
+
_ => false,
|
|
2516
|
+
};
|
|
2525
2517
|
if timed_wait {
|
|
2526
2518
|
interp
|
|
2527
2519
|
.scheduler
|
|
@@ -304,7 +304,7 @@ pub enum ProcessViewStatus {
|
|
|
304
304
|
}
|
|
305
305
|
|
|
306
306
|
/// Serializable scheduler wait reason without exposing implementation strings.
|
|
307
|
-
#[derive(Clone,
|
|
307
|
+
#[derive(Clone, Debug, PartialEq, Eq, Serialize)]
|
|
308
308
|
#[serde(tag = "kind", rename_all = "snake_case")]
|
|
309
309
|
pub enum WaitReasonView {
|
|
310
310
|
Timer { deadline_ns: u64 },
|
|
@@ -315,6 +315,7 @@ pub enum WaitReasonView {
|
|
|
315
315
|
ChildActivity { pid: u32 },
|
|
316
316
|
ChildDeadline { pid: u32, deadline_ns: u64 },
|
|
317
317
|
ChildActivityDeadline { pid: u32, deadline_ns: u64 },
|
|
318
|
+
Any { reasons: Vec<WaitReasonView> },
|
|
318
319
|
}
|
|
319
320
|
|
|
320
321
|
/// One stable path-level difference from the last checkpoint.
|
|
@@ -1259,6 +1260,9 @@ fn wait_reason_view(reason: WaitReason) -> WaitReasonView {
|
|
|
1259
1260
|
WaitReason::ChildActivityDeadline(pid, deadline_ns) => {
|
|
1260
1261
|
WaitReasonView::ChildActivityDeadline { pid, deadline_ns }
|
|
1261
1262
|
}
|
|
1263
|
+
WaitReason::Any(reasons) => WaitReasonView::Any {
|
|
1264
|
+
reasons: reasons.into_iter().map(wait_reason_view).collect(),
|
|
1265
|
+
},
|
|
1262
1266
|
}
|
|
1263
1267
|
}
|
|
1264
1268
|
|
|
@@ -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),
|
|
@@ -81,7 +81,7 @@ impl fmt::Debug for ValueKindDef {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
/// Stable error categories produced by native Python operations.
|
|
84
|
-
#[derive(Clone,
|
|
84
|
+
#[derive(Clone, Debug, PartialEq, Eq)]
|
|
85
85
|
pub(super) enum PyErrorKind {
|
|
86
86
|
Type,
|
|
87
87
|
Value,
|
|
@@ -298,6 +298,12 @@ pub(super) struct PyProcessOutput {
|
|
|
298
298
|
pub inherited_stderr: Vec<u8>,
|
|
299
299
|
}
|
|
300
300
|
|
|
301
|
+
/// Result of probing a modeled process operation without driving the scheduler.
|
|
302
|
+
pub(super) enum PyProcessPoll<T> {
|
|
303
|
+
Ready(T),
|
|
304
|
+
Blocked(crate::scheduler::WaitReason),
|
|
305
|
+
}
|
|
306
|
+
|
|
301
307
|
/// Fully-owned request for a child that outlives the native launch call.
|
|
302
308
|
pub(super) struct PyProcessStartRequest {
|
|
303
309
|
pub argv: Vec<String>,
|
|
@@ -339,8 +345,19 @@ pub(super) trait PyProcessRunner {
|
|
|
339
345
|
fd: i32,
|
|
340
346
|
amount: Option<usize>,
|
|
341
347
|
) -> PyResult<Vec<u8>>;
|
|
348
|
+
fn try_read_pipe(
|
|
349
|
+
&mut self,
|
|
350
|
+
handle: PyProcessHandle,
|
|
351
|
+
fd: i32,
|
|
352
|
+
amount: Option<usize>,
|
|
353
|
+
) -> PyResult<PyProcessPoll<Vec<u8>>>;
|
|
342
354
|
/// Write bytes to a captured child stdin, cooperatively scheduling while the pipe is full.
|
|
343
355
|
fn write_pipe(&mut self, handle: PyProcessHandle, input: Vec<u8>) -> PyResult<usize>;
|
|
356
|
+
fn try_write_pipe(
|
|
357
|
+
&mut self,
|
|
358
|
+
handle: PyProcessHandle,
|
|
359
|
+
input: Vec<u8>,
|
|
360
|
+
) -> PyResult<PyProcessPoll<usize>>;
|
|
344
361
|
/// Close one parent-side captured stream endpoint.
|
|
345
362
|
fn close_pipe(&mut self, handle: PyProcessHandle, fd: i32) -> PyResult<()>;
|
|
346
363
|
fn send_signal(
|
|
@@ -452,6 +469,9 @@ pub(super) trait PyRuntime {
|
|
|
452
469
|
generator: PyIterator,
|
|
453
470
|
value: PyValue,
|
|
454
471
|
) -> PyResult<Option<PyValue>>;
|
|
472
|
+
fn generator_return_value(&self, generator: PyIterator) -> PyResult<PyValue>;
|
|
473
|
+
/// Resume a coroutine and return 0 for yield, 1 for return, or 2 for an exception.
|
|
474
|
+
fn coroutine_step(&mut self, coroutine: PyIterator, value: PyValue) -> PyResult<(u8, PyValue)>;
|
|
455
475
|
fn generator_close(&mut self, generator: PyIterator) -> PyResult<()>;
|
|
456
476
|
fn generator_throw(&mut self, generator: PyIterator, exception: PyValue) -> PyResult;
|
|
457
477
|
fn new_iterator(&mut self, values: Vec<PyValue>) -> PyResult<PyValue>;
|
|
@@ -554,6 +574,8 @@ pub(super) trait PyRuntime {
|
|
|
554
574
|
fn exception_type_name(&self, value: &PyValue) -> Option<&'static str>;
|
|
555
575
|
/// Return one interpreter-owned exception class from the runtime's closed type table.
|
|
556
576
|
fn exception_type(&self, name: &'static str) -> PyValue;
|
|
577
|
+
/// Suspend the enclosing logical process until any modeled resource becomes ready.
|
|
578
|
+
fn wait_on(&mut self, reasons: Vec<crate::scheduler::WaitReason>) -> PyResult<()>;
|
|
557
579
|
fn clock(&mut self) -> &mut dyn PyClock;
|
|
558
580
|
fn environment(&self) -> &dyn PyEnvironment;
|
|
559
581
|
fn filesystem(&mut self) -> &mut dyn PyFilesystem;
|
|
@@ -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() {
|