feat(tazjin/generator-example): add an example for genawaiter crate
This is an experiment for tvix-eval. Change-Id: Ic752b5b125cefefeb1343e38a70beb364478e6eb Reviewed-on: https://cl.tvl.fyi/c/depot/+/8131 Tested-by: BuildkiteCI Reviewed-by: tazjin <tazjin@tvl.su>
This commit is contained in:
parent
f2624f1028
commit
006ab204fa
5 changed files with 260 additions and 0 deletions
1
users/tazjin/generator-example/.gitignore
vendored
Normal file
1
users/tazjin/generator-example/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/target
|
124
users/tazjin/generator-example/Cargo.lock
generated
Normal file
124
users/tazjin/generator-example/Cargo.lock
generated
Normal file
|
@ -0,0 +1,124 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "genawaiter"
|
||||
version = "0.99.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0"
|
||||
dependencies = [
|
||||
"genawaiter-macro",
|
||||
"genawaiter-proc-macro",
|
||||
"proc-macro-hack",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "genawaiter-macro"
|
||||
version = "0.99.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc"
|
||||
|
||||
[[package]]
|
||||
name = "genawaiter-proc-macro"
|
||||
version = "0.99.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "784f84eebc366e15251c4a8c3acee82a6a6f427949776ecb88377362a9621738"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro-hack",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generator-example"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"genawaiter",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn-mid",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-hack"
|
||||
version = "0.5.20+deprecated"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.51"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.107"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn-mid"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
version = "1.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
|
||||
|
||||
[[package]]
|
||||
name = "version_check"
|
||||
version = "0.9.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
9
users/tazjin/generator-example/Cargo.toml
Normal file
9
users/tazjin/generator-example/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "generator-example"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
genawaiter = "0.99.1"
|
11
users/tazjin/generator-example/README.md
Normal file
11
users/tazjin/generator-example/README.md
Normal file
|
@ -0,0 +1,11 @@
|
|||
generator-example
|
||||
=================
|
||||
|
||||
This is an experiment with the [`genawaiter`][] crate, to see if it
|
||||
could be suitable for dealing with the execution flattening problem in
|
||||
Tvix.
|
||||
|
||||
It constructs a dummy example that is similar to some of the problems
|
||||
we have in Tvix that require generator-like thunk forcing.
|
||||
|
||||
[`genawaiter`]: https://docs.rs/genawaiter/latest/genawaiter/index.html
|
115
users/tazjin/generator-example/src/main.rs
Normal file
115
users/tazjin/generator-example/src/main.rs
Normal file
|
@ -0,0 +1,115 @@
|
|||
use genawaiter::rc::{Co, Gen};
|
||||
use std::cell::RefCell;
|
||||
use std::future::Future;
|
||||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug)]
|
||||
enum ValueRepr {
|
||||
Int(i64),
|
||||
Thunk((i64, i64)),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Value(Rc<RefCell<ValueRepr>>);
|
||||
|
||||
impl Value {
|
||||
fn force(&self) {
|
||||
let mut inner = self.0.borrow_mut();
|
||||
match *inner {
|
||||
ValueRepr::Int(_) => return,
|
||||
ValueRepr::Thunk((a, b)) => {
|
||||
*inner = ValueRepr::Int(a + b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_forced(&self) -> bool {
|
||||
matches!(*self.0.borrow(), ValueRepr::Int(_))
|
||||
}
|
||||
|
||||
fn int(&self) -> i64 {
|
||||
match *self.0.borrow() {
|
||||
ValueRepr::Int(i) => i,
|
||||
ValueRepr::Thunk(_) => panic!("unforced thunk!"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i64> for Value {
|
||||
fn from(value: i64) -> Self {
|
||||
Value(Rc::new(RefCell::new(ValueRepr::Int(value))))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<(i64, i64)> for Value {
|
||||
fn from(value: (i64, i64)) -> Self {
|
||||
Value(Rc::new(RefCell::new(ValueRepr::Thunk(value))))
|
||||
}
|
||||
}
|
||||
|
||||
async fn list_maker(values: Vec<Value>, co: Co<Value>) -> Vec<i64> {
|
||||
let mut output: Vec<i64> = vec![];
|
||||
|
||||
for value in values {
|
||||
if !value.is_forced() {
|
||||
co.yield_(value.clone()).await;
|
||||
}
|
||||
|
||||
output.push(value.int());
|
||||
}
|
||||
|
||||
output
|
||||
}
|
||||
|
||||
async fn list_reverser(values: Vec<Value>, co: Co<Value>) -> Vec<i64> {
|
||||
let mut output = list_maker(values, co).await;
|
||||
output.reverse();
|
||||
output
|
||||
}
|
||||
|
||||
struct Frame {
|
||||
gen: Gen<Value, (), Pin<Box<dyn Future<Output = Vec<i64>>>>>,
|
||||
}
|
||||
|
||||
fn pin_future(
|
||||
f: impl Future<Output = Vec<i64>> + 'static,
|
||||
) -> Pin<Box<dyn Future<Output = Vec<i64>>>> {
|
||||
Box::pin(f)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut frames: Vec<Frame> = vec![];
|
||||
|
||||
let values: Vec<Value> = vec![
|
||||
42.into(),
|
||||
(12, 54).into(),
|
||||
4.into(),
|
||||
(40, 2).into(),
|
||||
2.into(),
|
||||
];
|
||||
let second = values.clone();
|
||||
|
||||
frames.push(Frame {
|
||||
gen: Gen::new(|co| pin_future(list_maker(values, co))),
|
||||
});
|
||||
|
||||
frames.push(Frame {
|
||||
gen: Gen::new(|co| pin_future(list_reverser(second, co))),
|
||||
});
|
||||
|
||||
for (idx, mut frame) in frames.into_iter().enumerate() {
|
||||
loop {
|
||||
match frame.gen.resume() {
|
||||
genawaiter::GeneratorState::Yielded(val) => {
|
||||
println!("yielded {:?} in frame {}", val, idx);
|
||||
val.force();
|
||||
}
|
||||
genawaiter::GeneratorState::Complete(list) => {
|
||||
println!("result {}: {:?}", idx, list);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue