diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 81973bff7792a6fe583d7f2c8fce163993217622..ee0c5aed2fcc0282a9526d5b434bc963a111f434 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -26,14 +26,14 @@ pub struct Module { /// Description of a protocol object, used to configure new connectors. #[repr(C)] pub struct ProtocolDescription { - modules: Vec, - heap: Heap, - types: TypeTable, - pool: Mutex, + pub(crate) modules: Vec, + pub(crate) heap: Heap, + pub(crate) types: TypeTable, + pub(crate) pool: Mutex, } #[derive(Debug, Clone)] pub(crate) struct ComponentState { - prompt: Prompt, + pub(crate) prompt: Prompt, } #[allow(dead_code)] @@ -143,6 +143,7 @@ impl ProtocolDescription { let module_root = self.lookup_module_root(module_name).unwrap(); let root = &self.heap[module_root]; let def = root.get_definition_ident(&self.heap, identifier).unwrap(); + // TODO: Check for polymorph ComponentState { prompt: Prompt::new(&self.types, &self.heap, def, 0, ValueGroup::new_stack(args)) } } @@ -161,6 +162,67 @@ impl ProtocolDescription { return None; } } + +// TODO: @temp Should just become a concrete thing that is passed in +pub trait RunContext { + fn did_put(&self, port: PortId) -> bool; + fn get(&self, port: PortId) -> Option; // None if still waiting on message + fn fires(&self, port: PortId) -> Option; // None if not yet branched + fn get_channel(&self) -> Option<(Value, Value)>; // None if not yet prepared +} + +#[derive(Debug)] +pub enum RunResult { + // Can only occur outside sync blocks + ComponentTerminated, // component has exited its procedure + ComponentAtSyncStart, + NewComponent(DefinitionId, i32, ValueGroup), // should also be possible inside sync + NewChannel, // should also be possible inside sync + // Can only occur inside sync blocks + BranchInconsistent, // branch has inconsistent behaviour + BranchMissingPortState(PortId), // branch doesn't know about port firing + BranchMissingPortValue(PortId), // branch hasn't received message on input port yet + BranchAtSyncEnd, + BranchPut(PortId, ValueGroup), +} + +impl ComponentState { + pub(crate) fn run(&mut self, ctx: &mut impl RunContext, pd: &ProtocolDescription) -> RunResult { + use EvalContinuation as EC; + use RunResult as RR; + + loop { + let step_result = self.prompt.step(&pd.types, &pd.heap, &pd.modules, ctx); + match step_result { + Err(reason) => { + // TODO: @temp + println!("Evaluation error:\n{}", reason); + todo!("proper error handling/bubbling up"); + }, + Ok(continuation) => match continuation { + // TODO: Probably want to remove this translation + EC::Stepping => continue, + EC::Inconsistent => return RR::BranchInconsistent, + EC::Terminal => return RR::ComponentTerminated, + EC::SyncBlockStart => return RR::ComponentAtSyncStart, + EC::SyncBlockEnd => return RR::BranchAtSyncEnd, + EC::NewComponent(definition_id, monomorph_idx, args) => + return RR::NewComponent(definition_id, monomorph_idx, arg), + EC::NewChannel => + return RR::NewChannel, + EC::BlockFires(port_id) => return RR::BranchMissingPortState(port_id), + EC::BlockGet(port_id) => return RR::BranchMissingPortValue(port_id), + EC::Put(port_id, value) => { + let value_group = ValueGroup::from_store(&self.prompt.store, &[value]); + return RR::BranchPut(port_id, value_group); + }, + } + } + } + } +} + +// TODO: @remove the old stuff impl ComponentState { pub(crate) fn nonsync_run<'a: 'b, 'b>( &'a mut self, @@ -261,16 +323,6 @@ impl ComponentState { _ => unreachable!(), }, EvalContinuation::Put(port, message) => { - let value; - match port { - Value::Output(port_value) => { - value = port_value; - } - Value::Input(port_value) => { - value = port_value; - } - _ => unreachable!(), - } let payload; match message { Value::Null => { @@ -287,7 +339,7 @@ impl ComponentState { } _ => unreachable!(), } - return SyncBlocker::PutMsg(value, payload); + return SyncBlocker::PutMsg(port, payload); } }, }