Skip to content

Commit ced2b30

Browse files
committed
feat: add stateful multi-turn execution demo binary
Signed-off-by: danbugs <danilochiarlone@gmail.com>
1 parent 4611081 commit ced2b30

2 files changed

Lines changed: 101 additions & 0 deletions

File tree

host/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ path = "src/bin/pydriver_run.rs"
2626
name = "pyhl"
2727
path = "src/bin/pyhl.rs"
2828

29+
[[bin]]
30+
name = "stateful-demo"
31+
path = "src/bin/stateful_demo.rs"
32+
2933
[dependencies]
3034
# danbugs/hyperlight feat/whp-no-surrogate — testing runtime no-surrogate mode.
3135
hyperlight-host = { git = "https://github.com/danbugs/hyperlight", rev = "212f20a5", features = ["executable_heap", "hw-interrupts"] }

host/src/bin/stateful_demo.rs

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use anyhow::{anyhow, Context, Result};
2+
use hyperlight_unikraft::pyhl;
3+
use std::path::PathBuf;
4+
use std::time::Instant;
5+
6+
fn resolve_home() -> Result<PathBuf> {
7+
if let Ok(h) = std::env::var("PYHL_HOME") {
8+
return Ok(PathBuf::from(h));
9+
}
10+
let cwd = std::env::current_dir().context("read cwd")?.join(".pyhl");
11+
if cwd.join("snapshot").is_dir() {
12+
return Ok(cwd);
13+
}
14+
#[cfg(unix)]
15+
{
16+
let xdg = std::env::var_os("XDG_DATA_HOME")
17+
.map(PathBuf::from)
18+
.filter(|p| p.is_absolute())
19+
.unwrap_or_else(|| {
20+
let home = std::env::var_os("HOME")
21+
.map(PathBuf::from)
22+
.unwrap_or_else(|| PathBuf::from("/"));
23+
home.join(".local/share")
24+
})
25+
.join("pyhl");
26+
if xdg.join("snapshot").is_dir() {
27+
return Ok(xdg);
28+
}
29+
}
30+
#[cfg(windows)]
31+
{
32+
if let Ok(local) = std::env::var("LOCALAPPDATA") {
33+
let win = PathBuf::from(local).join("pyhl");
34+
if win.join("snapshot").is_dir() {
35+
return Ok(win);
36+
}
37+
}
38+
let home_dir = std::env::var("USERPROFILE").unwrap_or_else(|_| "C:\\Users\\Default".into());
39+
let dotpyhl = PathBuf::from(home_dir).join(".pyhl");
40+
if dotpyhl.join("snapshot").is_dir() {
41+
return Ok(dotpyhl);
42+
}
43+
}
44+
Err(anyhow!(
45+
"no pyhl image found. run `pyhl setup` first, or set PYHL_HOME."
46+
))
47+
}
48+
49+
fn main() -> Result<()> {
50+
let home = resolve_home()?;
51+
52+
println!("Stateful multi-turn execution demo");
53+
println!("==================================\n");
54+
55+
let t_init = Instant::now();
56+
let mut rt = pyhl::Runtime::new(&home, &[], None, None, Some(0))?;
57+
println!(
58+
"[init] runtime created in {:.0}ms\n",
59+
t_init.elapsed().as_secs_f64() * 1000.0
60+
);
61+
62+
let turns: &[(&str, &str)] = &[
63+
(
64+
"Turn 1: Create variables",
65+
"x = 42\ny = 'hello from turn 1'\nprint(f' x = {x}, y = {y!r}')",
66+
),
67+
(
68+
"Turn 2: Access previous state + compute",
69+
"z = x * 2\nprint(f' z = x * 2 = {z}')\nprint(f' y from turn 1: {y!r}')",
70+
),
71+
(
72+
"Turn 3: Import library, build on prior state",
73+
"import pandas as pd\ndf = pd.DataFrame({'val': [x, z, x + z]})\nprint(df.to_string(index=False))",
74+
),
75+
(
76+
"Turn 4: Use everything from all prior turns",
77+
"total = df['val'].sum()\nprint(f' x={x}, z={z}, df_sum={total}')\nprint(f' All state persisted across {4} turns!')",
78+
),
79+
];
80+
81+
for (i, (label, code)) in turns.iter().enumerate() {
82+
println!("--- {} ---", label);
83+
let t = rt.run_code_stateful(code)?;
84+
println!(
85+
" [{:.0}ms{}]\n",
86+
t.call_ms,
87+
if i == 0 {
88+
format!(" (includes initial restore: {:.0}ms)", t.restore_ms)
89+
} else {
90+
String::new()
91+
}
92+
);
93+
}
94+
95+
println!("Session complete — sandbox torn down.");
96+
Ok(())
97+
}

0 commit comments

Comments
 (0)