diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 1f2b33ede745d27fc1336470d05211b5532a8ccf..f9d1295140a2ace7cbcc910ac216758e5510aed5 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -10,7 +10,6 @@ pub(crate) mod ast_printer; use std::sync::Mutex; use crate::collections::{StringPool, StringRef}; -use crate::common::*; use crate::protocol::ast::*; use crate::protocol::eval::*; use crate::protocol::input_source::*; @@ -36,14 +35,6 @@ pub(crate) struct ComponentState { pub(crate) prompt: Prompt, } -#[allow(dead_code)] -pub(crate) enum EvalContext<'a> { - Nonsync(&'a mut NonsyncProtoContext<'a>), - Sync(&'a mut SyncProtoContext<'a>), - None, -} -////////////////////////////////////////////// - #[derive(Debug)] pub enum ComponentCreationError { ModuleDoesntExist, @@ -88,80 +79,7 @@ impl ProtocolDescription { }); } - #[deprecated] - pub(crate) fn component_polarities( - &self, - module_name: &[u8], - identifier: &[u8], - ) -> Result, AddComponentError> { - use AddComponentError::*; - - let module_root = self.lookup_module_root(module_name); - if module_root.is_none() { - return Err(AddComponentError::NoSuchModule); - } - let module_root = module_root.unwrap(); - - let root = &self.heap[module_root]; - let def = root.get_definition_ident(&self.heap, identifier); - if def.is_none() { - return Err(NoSuchComponent); - } - - let def = &self.heap[def.unwrap()]; - if !def.is_component() { - return Err(NoSuchComponent); - } - - for ¶m in def.parameters().iter() { - let param = &self.heap[param]; - let first_element = ¶m.parser_type.elements[0]; - - match first_element.variant { - ParserTypeVariant::Input | ParserTypeVariant::Output => continue, - _ => { - return Err(NonPortTypeParameters); - } - } - } - - let mut result = Vec::new(); - for ¶m in def.parameters().iter() { - let param = &self.heap[param]; - let first_element = ¶m.parser_type.elements[0]; - - if first_element.variant == ParserTypeVariant::Input { - result.push(Polarity::Getter) - } else if first_element.variant == ParserTypeVariant::Output { - result.push(Polarity::Putter) - } else { - unreachable!() - } - } - Ok(result) - } - - // expects port polarities to be correct - #[deprecated] - pub(crate) fn new_component(&self, module_name: &[u8], identifier: &[u8], ports: &[PortId]) -> ComponentState { - let mut args = Vec::new(); - for (&x, y) in ports.iter().zip(self.component_polarities(module_name, identifier).unwrap()) { - match y { - Polarity::Getter => args.push(Value::Input(x)), - Polarity::Putter => args.push(Value::Output(x)), - } - } - - 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(); - - ComponentState { prompt: Prompt::new(&self.types, &self.heap, def, 0, ValueGroup::new_stack(args)) } - } - - // TODO: Ofcourse, rename this at some point, perhaps even remove it in its - // entirety. Find some way to interface with the parameter's types. - pub(crate) fn new_component_v2( + pub(crate) fn new_component( &self, module_name: &[u8], identifier: &[u8], arguments: ValueGroup ) -> Result { // Find the module in which the definition can be found @@ -295,319 +213,3 @@ pub trait RunContext { fn performed_fork(&mut self) -> Option; // None if not yet forked fn created_channel(&mut 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 - BranchGet(PortId), // branch hasn't received message on input port yet - BranchAtSyncEnd, - BranchFork, - 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) => { - println!("Evaluation error:\n{}", reason); - todo!("proper error handling/bubbling up"); - }, - Ok(continuation) => match continuation { - EC::Stepping => continue, - EC::BranchInconsistent => return RR::BranchInconsistent, - EC::ComponentTerminated => 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, args), - EC::NewChannel => - return RR::NewChannel, - EC::NewFork => - return RR::BranchFork, - EC::BlockFires(port_id) => return RR::BranchMissingPortState(port_id), - EC::BlockGet(port_id) => return RR::BranchGet(port_id), - EC::Put(port_id, value_group) => { - 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, - context: &'b mut NonsyncProtoContext<'b>, - pd: &'a ProtocolDescription, - ) -> NonsyncBlocker { - let mut context = EvalContext::Nonsync(context); - loop { - let result = self.prompt.step(&pd.types, &pd.heap, &pd.modules, &mut context); - match result { - Err(err) => { - println!("Evaluation error:\n{}", err); - panic!("proper error handling when component fails"); - }, - Ok(cont) => match cont { - EvalContinuation::Stepping => continue, - EvalContinuation::BranchInconsistent => return NonsyncBlocker::Inconsistent, - EvalContinuation::ComponentTerminated => return NonsyncBlocker::ComponentExit, - EvalContinuation::SyncBlockStart => return NonsyncBlocker::SyncBlockStart, - // Not possible to end sync block if never entered one - EvalContinuation::SyncBlockEnd => unreachable!(), - EvalContinuation::NewComponent(definition_id, monomorph_idx, args) => { - // Look up definition - let mut moved_ports = HashSet::new(); - for arg in args.values.iter() { - match arg { - Value::Output(port) => { - moved_ports.insert(*port); - } - Value::Input(port) => { - moved_ports.insert(*port); - } - _ => {} - } - } - for region in args.regions.iter() { - for arg in region { - match arg { - Value::Output(port) => { moved_ports.insert(*port); }, - Value::Input(port) => { moved_ports.insert(*port); }, - _ => {}, - } - } - } - let init_state = ComponentState { prompt: Prompt::new(&pd.types, &pd.heap, definition_id, monomorph_idx, args) }; - context.new_component(moved_ports, init_state); - // Continue stepping - continue; - }, - EvalContinuation::NewChannel => { - // Because of the way we emulate the old context for now, we can safely - // assume that this will never happen. The old context thingamajig always - // creates a channel, it never bubbles a "need to create a channel" message - // to the runtime - unreachable!(); - }, - EvalContinuation::NewFork => unreachable!(), - // Outside synchronous blocks, no fires/get/put happens - EvalContinuation::BlockFires(_) => unreachable!(), - EvalContinuation::BlockGet(_) => unreachable!(), - EvalContinuation::Put(_, _) => unreachable!(), - }, - } - } - } - - pub(crate) fn sync_run<'a: 'b, 'b>( - &'a mut self, - context: &'b mut SyncProtoContext<'b>, - pd: &'a ProtocolDescription, - ) -> SyncBlocker { - let mut context = EvalContext::Sync(context); - loop { - let result = self.prompt.step(&pd.types, &pd.heap, &pd.modules, &mut context); - match result { - Err(err) => { - println!("Evaluation error:\n{}", err); - panic!("proper error handling when component fails"); - }, - Ok(cont) => match cont { - EvalContinuation::Stepping => continue, - EvalContinuation::BranchInconsistent => return SyncBlocker::Inconsistent, - // First need to exit synchronous block before definition may end - EvalContinuation::ComponentTerminated => unreachable!(), - // No nested synchronous blocks - EvalContinuation::SyncBlockStart => unreachable!(), - EvalContinuation::SyncBlockEnd => return SyncBlocker::SyncBlockEnd, - // Not possible to create component in sync block - EvalContinuation::NewComponent(_, _, _) => unreachable!(), - EvalContinuation::NewChannel => unreachable!(), - EvalContinuation::NewFork => unreachable!(), - EvalContinuation::BlockFires(port) => { - return SyncBlocker::CouldntCheckFiring(port); - }, - EvalContinuation::BlockGet(port) => { - return SyncBlocker::CouldntReadMsg(port); - }, - EvalContinuation::Put(port, message) => { - let payload; - - // Extract bytes from `put` - match &message.values[0] { - Value::Null => { - return SyncBlocker::Inconsistent; - }, - Value::Message(heap_pos) => { - // Create a copy of the payload - let values = &message.regions[*heap_pos as usize]; - let mut bytes = Vec::with_capacity(values.len()); - for value in values { - bytes.push(value.as_uint8()); - } - payload = Payload(Arc::new(bytes)); - } - _ => unreachable!(), - } - return SyncBlocker::PutMsg(port, payload); - } - }, - } - } - } -} - -impl RunContext for EvalContext<'_> { - fn performed_put(&mut self, port: PortId) -> bool { - match self { - EvalContext::None => unreachable!(), - EvalContext::Nonsync(_) => unreachable!(), - EvalContext::Sync(ctx) => { - ctx.did_put_or_get(port) - } - } - } - - fn performed_get(&mut self, port: PortId) -> Option { - match self { - EvalContext::None => unreachable!(), - EvalContext::Nonsync(_) => unreachable!(), - EvalContext::Sync(ctx) => { - let payload = ctx.read_msg(port); - if payload.is_none() { - return None; - } - - let payload = payload.unwrap(); - let mut transformed = Vec::with_capacity(payload.len()); - for byte in payload.0.iter() { - transformed.push(Value::UInt8(*byte)); - } - - let value_group = ValueGroup{ - values: vec![Value::Message(0)], - regions: vec![transformed], - }; - - return Some(value_group); - } - } - } - - fn fires(&mut self, port: PortId) -> Option { - match self { - EvalContext::None => unreachable!(), - EvalContext::Nonsync(_) => unreachable!(), - EvalContext::Sync(context) => { - match context.is_firing(port) { - Some(did_fire) => Some(Value::Bool(did_fire)), - None => None, - } - } - } - } - - fn created_channel(&mut self) -> Option<(Value, Value)> { - match self { - EvalContext::None => unreachable!(), - EvalContext::Nonsync(context) => { - let [from, to] = context.new_port_pair(); - let from = Value::Output(from); - let to = Value::Input(to); - return Some((from, to)); - }, - EvalContext::Sync(_) => unreachable!(), - } - } - - fn performed_fork(&mut self) -> Option { - // Never actually used in the old runtime - return None; - } -} - -// TODO: @remove once old runtime has disappeared -impl EvalContext<'_> { - fn new_component(&mut self, moved_ports: HashSet, init_state: ComponentState) -> () { - match self { - EvalContext::None => unreachable!(), - EvalContext::Nonsync(context) => { - context.new_component(moved_ports, init_state) - } - EvalContext::Sync(_) => unreachable!(), - } - } - fn new_channel(&mut self) -> [Value; 2] { - match self { - EvalContext::None => unreachable!(), - EvalContext::Nonsync(context) => { - let [from, to] = context.new_port_pair(); - let from = Value::Output(from); - let to = Value::Input(to); - return [from, to]; - } - EvalContext::Sync(_) => unreachable!(), - } - } - fn fires(&mut self, port: Value) -> Option { - match self { - EvalContext::None => unreachable!(), - EvalContext::Nonsync(_) => unreachable!(), - EvalContext::Sync(context) => match port { - Value::Output(port) => context.is_firing(port).map(Value::Bool), - Value::Input(port) => context.is_firing(port).map(Value::Bool), - _ => unreachable!(), - }, - } - } - fn get(&mut self, port: Value, store: &mut Store) -> Option { - match self { - EvalContext::None => unreachable!(), - EvalContext::Nonsync(_) => unreachable!(), - EvalContext::Sync(context) => match port { - Value::Input(port) => { - let payload = context.read_msg(port); - if payload.is_none() { return None; } - - let heap_pos = store.alloc_heap(); - let heap_pos_usize = heap_pos as usize; - let payload = payload.unwrap(); - store.heap_regions[heap_pos_usize].values.reserve(payload.0.len()); - for value in payload.0.iter() { - store.heap_regions[heap_pos_usize].values.push(Value::UInt8(*value)); - } - - return Some(Value::Message(heap_pos)); - } - _ => unreachable!(), - }, - } - } - fn did_put(&mut self, port: Value) -> bool { - match self { - EvalContext::None => unreachable!("did_put in None context"), - EvalContext::Nonsync(_) => unreachable!("did_put in nonsync context"), - EvalContext::Sync(context) => match port { - Value::Output(port) => { - context.did_put_or_get(port) - }, - _ => unreachable!("did_put on non-output port value") - } - } - } -}