diff --git a/src/protocol/eval/executor.rs b/src/protocol/eval/executor.rs index 913be03fa88e408a2ac4bc3b71832f87bfbfaf8d..25782476114ff1097fca333d48ad04a7afb1c099 100644 --- a/src/protocol/eval/executor.rs +++ b/src/protocol/eval/executor.rs @@ -207,6 +207,9 @@ pub enum EvalContinuation { BlockFires(PortId), BlockGet(PortId), Put(PortId, ValueGroup), + SelectStart(u32, u32), // (num_cases, num_ports_total) + SelectRegisterPort(u32, u32, PortId), // (case_index, port_index_in_case, port_id) + SelectWait, // wait until select can continue // Returned only in non-sync mode ComponentTerminated, SyncBlockStart, @@ -652,12 +655,7 @@ impl Prompt { Method::Fires => { let port_value = cur_frame.expr_values.pop_front().unwrap(); let port_value_deref = self.store.maybe_read_ref(&port_value).clone(); - - let port_id = match port_value_deref { - Value::Input(port_id) => port_id, - Value::Output(port_id) => port_id, - _ => unreachable!("executor calling 'fires' on value {:?}", port_value_deref), - }; + let port_id = port_value_deref.as_port_id(); match ctx.fires(port_id) { None => { @@ -736,13 +734,28 @@ impl Prompt { println!("{}", message); }, Method::SelectStart => { - todo!("select start"); + let num_cases = self.store.maybe_read_ref(&cur_frame.expr_values.pop_front().unwrap()).as_uint32(); + let num_ports = self.store.maybe_read_ref(&cur_frame.expr_values.pop_front().unwrap()).as_uint32(); + if !ctx.select_start(num_cases, num_ports) { + return Ok(EvalContinuation::SelectStart(num_cases, num_ports)) + } }, Method::SelectRegisterCasePort => { - todo!("select register"); + let case_index = self.store.maybe_read_ref(&cur_frame.expr_values.pop_front().unwrap()).as_uint32(); + let port_index = self.store.maybe_read_ref(&cur_frame.expr_values.pop_front().unwrap()).as_uint32(); + let port_value = self.store.maybe_read_ref(&cur_frame.expr_values.pop_front().unwrap()).as_port_id(); + + if !ctx.performed_select_start() { + return Ok(EvalContinuation::SelectRegisterPort(case_index, port_index, port_value)); + } }, Method::SelectWait => { - todo!("select wait"); + match ctx.performed_select_wait() { + Some(select_index) => { + cur_frame.expr_values.push_back(Value::UInt32(select_index)); + }, + None => return Ok(EvalContinuation::SelectWait), + } }, Method::UserComponent => { // This is actually handled by the evaluation @@ -965,8 +978,12 @@ impl Prompt { Ok(EvalContinuation::Stepping) }, - Statement::Select(_stmt) => { - todo!("implement select evaluation") + Statement::Select(stmt) => { + // This is a trampoline for the statements that were placed by + // the AST transformation pass + cur_frame.position = stmt.next; + + Ok(EvalContinuation::Stepping) }, Statement::EndSelect(stmt) => { cur_frame.position = stmt.next;