diff --git a/src/protocol/eval/executor.rs b/src/protocol/eval/executor.rs index 68dc3eec80a2ebb90159a4d62401f7eb6c5a727d..3b16522574521e6ec3bdb70b57ee34b22073a949 100644 --- a/src/protocol/eval/executor.rs +++ b/src/protocol/eval/executor.rs @@ -200,6 +200,7 @@ pub enum EvalContinuation { SyncBlockEnd, NewComponent(DefinitionId, i32, ValueGroup), NewChannel, + NewFork, BlockFires(PortId), BlockGet(PortId), Put(PortId, Value), @@ -584,7 +585,7 @@ impl Prompt { unreachable!("executor calling 'get' on value {:?}", value) }; - match ctx.get(port_id) { + match ctx.performed_get(port_id) { Some(result) => { // We have the result. Merge the `ValueGroup` with the // stack/heap storage. @@ -613,11 +614,12 @@ impl Prompt { let msg_value = cur_frame.expr_values.pop_front().unwrap(); let deref_msg_value = self.store.maybe_read_ref(&msg_value).clone(); - if ctx.did_put(port_id) { + if ctx.performed_put(port_id) { // We're fine, deallocate in case the expression value stack // held an owned value self.store.drop_value(msg_value.get_heap_pos()); } else { + // Prepare to execute again cur_frame.expr_values.push_front(msg_value); cur_frame.expr_values.push_front(port_value); cur_frame.expr_stack.push_back(ExprInstruction::EvalExpr(expr_id)); @@ -810,7 +812,7 @@ impl Prompt { LocalStatement::Channel(stmt) => { // Need to create a new channel by requesting it from // the runtime. - match ctx.get_channel() { + match ctx.created_channel() { None => { // No channel is pending. So request one Ok(EvalContinuation::NewChannel) @@ -886,6 +888,33 @@ impl Prompt { Ok(EvalContinuation::SyncBlockEnd) }, + Statement::Fork(stmt) => { + if stmt.right_body.is_none() { + // No reason to fork + cur_frame.position = stmt.left_body.upcast(); + } else { + // Need to fork + if let Some(go_left) = ctx.performed_fork() { + // Runtime has created a fork + if go_left { + cur_frame.position = stmt.left_body.upcast(); + } else { + cur_frame.position = stmt.right_body.unwrap().upcast(); + } + } else { + // Request the runtime to create a fork of the current + // branch + return Ok(EvalContinuation::NewFork); + } + } + + Ok(EvalContinuation::Stepping) + }, + Statement::EndFork(stmt) => { + cur_frame.position = stmt.next; + + Ok(EvalContinuation::Stepping) + } Statement::Return(_stmt) => { debug_assert!(heap[cur_frame.definition].is_function()); debug_assert_eq!(cur_frame.expr_values.len(), 1, "expected one expr value for return statement");