use std::time::Duration;
use crate::harness::{HarnessKind, VmHarness};
use crate::stdlib::io::{write_stderr, write_stdout};
use crate::value::{VmError, VmValue};
impl crate::vm::Vm {
pub(super) async fn call_harness_method(
&mut self,
handle: &VmHarness,
method: &str,
args: &[VmValue],
) -> Result<VmValue, VmError> {
match handle.kind() {
HarnessKind::Root => Err(method_unsupported(handle, method)),
HarnessKind::Stdio => self.call_harness_stdio_method(handle, method, args),
HarnessKind::Clock => self.call_harness_clock_method(handle, method, args).await,
HarnessKind::Fs | HarnessKind::Env | HarnessKind::Random | HarnessKind::Net => {
Err(VmError::TypeError(format!(
"{}::{method} is not yet implemented — wired by the E4.2-E4.4 migration tickets",
handle.type_name(),
)))
}
}
}
fn call_harness_stdio_method(
&mut self,
handle: &VmHarness,
method: &str,
args: &[VmValue],
) -> Result<VmValue, VmError> {
match method {
"println" => {
let msg = args.first().map(|a| a.display()).unwrap_or_default();
write_stdout(&mut self.output, &format!("{msg}\n"));
Ok(VmValue::Nil)
}
"print" => {
let msg = args.first().map(|a| a.display()).unwrap_or_default();
write_stdout(&mut self.output, &msg);
Ok(VmValue::Nil)
}
"eprintln" => {
let msg = args.first().map(|a| a.display()).unwrap_or_default();
write_stderr(&format!("{msg}\n"));
Ok(VmValue::Nil)
}
"eprint" => {
let msg = args.first().map(|a| a.display()).unwrap_or_default();
write_stderr(&msg);
Ok(VmValue::Nil)
}
_ => Err(method_unsupported(handle, method)),
}
}
async fn call_harness_clock_method(
&mut self,
handle: &VmHarness,
method: &str,
args: &[VmValue],
) -> Result<VmValue, VmError> {
let clock = handle.inner().clock();
match method {
"now_ms" => Ok(VmValue::Int(crate::clock::now_wall_ms(clock.as_ref()))),
"monotonic_ms" => Ok(VmValue::Int(clock.monotonic_ms())),
"sleep_ms" => {
let ms = args
.first()
.and_then(|v| match v {
VmValue::Int(n) => Some(*n),
VmValue::Duration(ms) => Some(*ms),
_ => None,
})
.ok_or_else(|| {
VmError::TypeError(
"HarnessClock.sleep_ms expects an int or duration argument".into(),
)
})?;
if ms > 0 {
clock.sleep(Duration::from_millis(ms as u64)).await;
}
Ok(VmValue::Nil)
}
_ => Err(method_unsupported(handle, method)),
}
}
}
fn method_unsupported(handle: &VmHarness, method: &str) -> VmError {
VmError::TypeError(format!(
"value of type {} has no method `{method}`",
handle.type_name()
))
}