Skip to content

Commit 3a6b595

Browse files
committed
pd-vm: codex: restore zero-result assert semantics
1 parent ea0dfe1 commit 3a6b595

1 file changed

Lines changed: 28 additions & 3 deletions

File tree

  • pd-vm/src/vm/builtins_impl

‎pd-vm/src/vm/builtins_impl/mod.rs‎

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,10 @@ pub(super) fn execute_builtin_call(
6868
BuiltinFunction::TypeOf => {
6969
core::builtin_type_of(&args).map(IntoBuiltinCallOutcome::into_builtin_call_outcome)
7070
}
71-
BuiltinFunction::Assert => {
72-
core::builtin_assert(&args).map(IntoBuiltinCallOutcome::into_builtin_call_outcome)
73-
}
71+
BuiltinFunction::Assert => core::builtin_assert(&args).map(|()| {
72+
// Successful asserts are control checks, not value-producing expressions.
73+
BuiltinCallOutcome::Return(Vec::new())
74+
}),
7475
_ => execute_namespaced_builtin_call(vm, builtin, args),
7576
}
7677
}
@@ -86,3 +87,27 @@ pub(super) fn poll_builtin_io_op(
8687
pub(super) fn close_all_handles(vm: &mut Vm) {
8788
io::close_all_handles(vm);
8889
}
90+
91+
#[cfg(test)]
92+
mod tests {
93+
use super::*;
94+
use crate::{OpCode, Program};
95+
96+
#[test]
97+
fn builtin_assert_success_returns_no_stack_value() {
98+
let mut vm = Vm::new(Program::new(Vec::new(), vec![OpCode::Ret as u8]));
99+
100+
let outcome = execute_builtin_call(&mut vm, BuiltinFunction::Assert, vec![Value::Bool(true)])
101+
.expect("assert should succeed");
102+
103+
match outcome {
104+
BuiltinCallOutcome::Return(values) => assert!(
105+
values.is_empty(),
106+
"successful assert should not push a null sentinel"
107+
),
108+
BuiltinCallOutcome::Pending(op_id) => {
109+
panic!("assert should not yield pending host op {op_id}")
110+
}
111+
}
112+
}
113+
}

0 commit comments

Comments
 (0)