Files @ 49b9c766fe5a
Branch filter:

Location: CSY/reowolf/src/protocol/mod.rs - annotation

49b9c766fe5a 9.8 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
Christopher Esterhuyse
tracking new channel ekeys
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
0fb83f27a238
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
935120e93ef1
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
935120e93ef1
3af8b6eaec1b
935120e93ef1
3af8b6eaec1b
935120e93ef1
3af8b6eaec1b
935120e93ef1
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
06f259bf8031
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
0fb83f27a238
06f259bf8031
06f259bf8031
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
0fb83f27a238
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
a226385adc2d
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
a226385adc2d
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
a226385adc2d
a226385adc2d
06f259bf8031
a226385adc2d
a226385adc2d
06f259bf8031
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
a226385adc2d
a226385adc2d
06f259bf8031
a226385adc2d
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
a226385adc2d
mod ast;
mod eval;
pub mod inputsource;
mod lexer;
mod library;
mod parser;

use crate::common::*;
use crate::protocol::ast::*;
use crate::protocol::eval::*;
use crate::protocol::inputsource::*;
use crate::protocol::parser::*;
use std::hint::unreachable_unchecked;

pub struct ProtocolDescriptionImpl {
    heap: Heap,
    source: InputSource,
    root: RootId,
}

impl std::fmt::Debug for ProtocolDescriptionImpl {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "Protocol")
    }
}

impl ProtocolDescription for ProtocolDescriptionImpl {
    type S = ComponentStateImpl;

    fn parse(buffer: &[u8]) -> Result<Self, String> {
        let mut heap = Heap::new();
        let mut source = InputSource::from_buffer(buffer).unwrap();
        let mut parser = Parser::new(&mut source);
        match parser.parse(&mut heap) {
            Ok(root) => {
                return Ok(ProtocolDescriptionImpl { heap, source, root });
            }
            Err(err) => {
                let mut vec: Vec<u8> = Vec::new();
                err.write(&source, &mut vec).unwrap();
                Err(String::from_utf8_lossy(&vec).to_string())
            }
        }
    }
    fn component_polarities(&self, identifier: &[u8]) -> Result<Vec<Polarity>, MainComponentErr> {
        let h = &self.heap;
        let root = &h[self.root];
        let def = root.get_definition_ident(h, identifier);
        if def.is_none() {
            return Err(MainComponentErr::NoSuchComponent);
        }
        let def = &h[def.unwrap()];
        if !def.is_component() {
            return Err(MainComponentErr::NoSuchComponent);
        }
        for &param in def.parameters().iter() {
            let param = &h[param];
            let type_annot = &h[param.type_annotation];
            if type_annot.the_type.array {
                return Err(MainComponentErr::NonPortTypeParameters);
            }
            match type_annot.the_type.primitive {
                PrimitiveType::Input | PrimitiveType::Output => continue,
                _ => {
                    return Err(MainComponentErr::NonPortTypeParameters);
                }
            }
        }
        let mut result = Vec::new();
        for &param in def.parameters().iter() {
            let param = &h[param];
            let type_annot = &h[param.type_annotation];
            let ptype = &type_annot.the_type.primitive;
            if ptype == &PrimitiveType::Input {
                result.push(Polarity::Getter)
            } else if ptype == &PrimitiveType::Output {
                result.push(Polarity::Putter)
            } else {
                unreachable!()
            }
        }
        Ok(result)
    }
    fn new_main_component(&self, identifier: &[u8], ports: &[Key]) -> ComponentStateImpl {
        let mut args = Vec::new();
        for (&x, y) in ports.iter().zip(self.component_polarities(identifier).unwrap()) {
            match y {
                Polarity::Getter => args.push(Value::Input(InputValue(x))),
                Polarity::Putter => args.push(Value::Output(OutputValue(x))),
            }
        }
        let h = &self.heap;
        let root = &h[self.root];
        let def = root.get_definition_ident(h, identifier).unwrap();
        ComponentStateImpl { prompt: Prompt::new(h, def, &args) }
    }
}

#[derive(Debug, Clone)]
pub struct ComponentStateImpl {
    prompt: Prompt,
}
impl ComponentState for ComponentStateImpl {
    type D = ProtocolDescriptionImpl;

    fn pre_sync_run<C: MonoContext<D = ProtocolDescriptionImpl, S = Self>>(
        &mut self,
        context: &mut C,
        pd: &ProtocolDescriptionImpl,
    ) -> MonoBlocker {
        let mut context = EvalContext::Mono(context);
        loop {
            let result = self.prompt.step(&pd.heap, &mut context);
            match result {
                // In component definitions, there are no return statements
                Ok(_) => unreachable!(),
                Err(cont) => match cont {
                    EvalContinuation::Stepping => continue,
                    EvalContinuation::Inconsistent => return MonoBlocker::Inconsistent,
                    EvalContinuation::Terminal => return MonoBlocker::ComponentExit,
                    EvalContinuation::SyncBlockStart => return MonoBlocker::SyncBlockStart,
                    // Not possible to end sync block if never entered one
                    EvalContinuation::SyncBlockEnd => unreachable!(),
                    EvalContinuation::NewComponent(args) => {
                        todo!();
                        continue;
                    }
                    // Outside synchronous blocks, no fires/get/put happens
                    EvalContinuation::BlockFires(val) => unreachable!(),
                    EvalContinuation::BlockGet(val) => unreachable!(),
                    EvalContinuation::Put(port, msg) => unreachable!(),
                },
            }
        }
    }

    fn sync_run<C: PolyContext<D = ProtocolDescriptionImpl>>(
        &mut self,
        context: &mut C,
        pd: &ProtocolDescriptionImpl,
    ) -> PolyBlocker {
        let mut context = EvalContext::Poly(context);
        loop {
            let result = self.prompt.step(&pd.heap, &mut context);
            match result {
                // Inside synchronous blocks, there are no return statements
                Ok(_) => unreachable!(),
                Err(cont) => match cont {
                    EvalContinuation::Stepping => continue,
                    EvalContinuation::Inconsistent => return PolyBlocker::Inconsistent,
                    // First need to exit synchronous block before definition may end
                    EvalContinuation::Terminal => unreachable!(),
                    // No nested synchronous blocks
                    EvalContinuation::SyncBlockStart => unreachable!(),
                    EvalContinuation::SyncBlockEnd => return PolyBlocker::SyncBlockEnd,
                    // Not possible to create component in sync block
                    EvalContinuation::NewComponent(args) => unreachable!(),
                    EvalContinuation::BlockFires(port) => match port {
                        Value::Output(OutputValue(key)) => {
                            return PolyBlocker::CouldntCheckFiring(key);
                        }
                        Value::Input(InputValue(key)) => {
                            return PolyBlocker::CouldntCheckFiring(key);
                        }
                        _ => unreachable!(),
                    },
                    EvalContinuation::BlockGet(port) => match port {
                        Value::Output(OutputValue(key)) => {
                            return PolyBlocker::CouldntReadMsg(key);
                        }
                        Value::Input(InputValue(key)) => {
                            return PolyBlocker::CouldntReadMsg(key);
                        }
                        _ => unreachable!(),
                    },
                    EvalContinuation::Put(port, message) => {
                        let key;
                        match port {
                            Value::Output(OutputValue(the_key)) => {
                                key = the_key;
                            }
                            Value::Input(InputValue(the_key)) => {
                                key = the_key;
                            }
                            _ => unreachable!(),
                        }
                        let payload;
                        match message {
                            Value::Message(MessageValue(None)) => {
                                // Putting a null message is inconsistent
                                return PolyBlocker::Inconsistent;
                            }
                            Value::Message(MessageValue(Some(buffer))) => {
                                // Create a copy of the payload
                                payload = buffer.clone();
                            }
                            _ => unreachable!(),
                        }
                        return PolyBlocker::PutMsg(key, payload);
                    }
                },
            }
        }
    }
}

pub enum EvalContext<'a> {
    Mono(&'a mut dyn MonoContext<D = ProtocolDescriptionImpl, S = ComponentStateImpl>),
    Poly(&'a mut dyn PolyContext<D = ProtocolDescriptionImpl>),
    None,
}
impl EvalContext<'_> {
    fn random(&mut self) -> LongValue {
        match self {
            EvalContext::None => unreachable!(),
            EvalContext::Mono(context) => todo!(),
            EvalContext::Poly(context) => unreachable!(),
        }
    }
    fn channel(&mut self) -> (Value, Value) {
        match self {
            EvalContext::None => unreachable!(),
            EvalContext::Mono(context) => unreachable!(),
            EvalContext::Poly(context) => todo!(),
        }
    }
    fn fires(&mut self, port: Value) -> Option<Value> {
        match self {
            EvalContext::None => unreachable!(),
            EvalContext::Mono(context) => unreachable!(),
            EvalContext::Poly(context) => match port {
                Value::Output(OutputValue(key)) => context.is_firing(key).map(Value::from),
                Value::Input(InputValue(key)) => context.is_firing(key).map(Value::from),
                _ => unreachable!(),
            },
        }
    }
    fn get(&mut self, port: Value) -> Option<Value> {
        match self {
            EvalContext::None => unreachable!(),
            EvalContext::Mono(context) => unreachable!(),
            EvalContext::Poly(context) => match port {
                Value::Output(OutputValue(key)) => {
                    context.read_msg(key).map(Value::receive_message)
                }
                Value::Input(InputValue(key)) => context.read_msg(key).map(Value::receive_message),
                _ => unreachable!(),
            },
        }
    }
}