Files @ fcf8c30ed335
Branch filter:

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

fcf8c30ed335 12.2 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
mh
WIP on fixing type inferencer
3f236d37dad1
814be01095d9
06f259bf8031
4c9116f4253b
13bac4f35619
814be01095d9
06f259bf8031
aaeaf5986496
06f259bf8031
814be01095d9
814be01095d9
729feec4d37a
814be01095d9
814be01095d9
6c04a99de862
d3835a56401d
d3835a56401d
6c04a99de862
6c04a99de862
6c04a99de862
6c04a99de862
6c04a99de862
06f259bf8031
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
d3835a56401d
d600dd299dde
44a98be4e4b4
06f259bf8031
06f259bf8031
0fb83f27a238
06f259bf8031
03af3095927d
4c9116f4253b
44a98be4e4b4
44a98be4e4b4
4c9116f4253b
cecf94fdb875
cecf94fdb875
175721d796d7
44a98be4e4b4
44a98be4e4b4
06f259bf8031
44a98be4e4b4
06f259bf8031
d23010006486
06f259bf8031
06f259bf8031
44a98be4e4b4
9774ef9fe888
44a98be4e4b4
33ea10021de4
33ea10021de4
33ea10021de4
33ea10021de4
9774ef9fe888
9774ef9fe888
9774ef9fe888
9774ef9fe888
9774ef9fe888
06f259bf8031
9774ef9fe888
9774ef9fe888
9774ef9fe888
9774ef9fe888
06f259bf8031
4c9116f4253b
44a98be4e4b4
44a98be4e4b4
44a98be4e4b4
44a98be4e4b4
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
935120e93ef1
44a98be4e4b4
935120e93ef1
3af8b6eaec1b
935120e93ef1
44a98be4e4b4
935120e93ef1
3af8b6eaec1b
3af8b6eaec1b
fdaf709bf0ca
fdaf709bf0ca
fdaf709bf0ca
fdaf709bf0ca
3af8b6eaec1b
44a98be4e4b4
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
fdaf709bf0ca
fdaf709bf0ca
fdaf709bf0ca
3af8b6eaec1b
fdaf709bf0ca
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
4776bcc45b33
4bfd6d133687
06f259bf8031
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
0fb83f27a238
06f259bf8031
06f259bf8031
3af8b6eaec1b
3af8b6eaec1b
3af8b6eaec1b
44a98be4e4b4
06f259bf8031
06f259bf8031
44a98be4e4b4
4c9116f4253b
44a98be4e4b4
cecf94fdb875
44a98be4e4b4
44a98be4e4b4
44a98be4e4b4
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
44a98be4e4b4
44a98be4e4b4
44a98be4e4b4
06f259bf8031
06f259bf8031
6717437470eb
5e11ebce9bc0
5e11ebce9bc0
6717437470eb
5e11ebce9bc0
5e11ebce9bc0
a226385adc2d
06f259bf8031
06f259bf8031
ac7f49602455
ac7f49602455
ac7f49602455
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
4c9116f4253b
44a98be4e4b4
cecf94fdb875
44a98be4e4b4
44a98be4e4b4
44a98be4e4b4
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
44a98be4e4b4
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
44a98be4e4b4
06f259bf8031
5e11ebce9bc0
a226385adc2d
dedf89df1602
44a98be4e4b4
06f259bf8031
dedf89df1602
44a98be4e4b4
06f259bf8031
a226385adc2d
a226385adc2d
a226385adc2d
dedf89df1602
44a98be4e4b4
a226385adc2d
dedf89df1602
44a98be4e4b4
a226385adc2d
a226385adc2d
a226385adc2d
06f259bf8031
dedf89df1602
06f259bf8031
dedf89df1602
dedf89df1602
06f259bf8031
dedf89df1602
dedf89df1602
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
44a98be4e4b4
06f259bf8031
06f259bf8031
06f259bf8031
fd175763a0f7
06f259bf8031
a226385adc2d
06f259bf8031
44a98be4e4b4
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
dedf89df1602
dedf89df1602
175721d796d7
44a98be4e4b4
44a98be4e4b4
dedf89df1602
dedf89df1602
44a98be4e4b4
06f259bf8031
175721d796d7
44a98be4e4b4
dedf89df1602
5e11ebce9bc0
5e11ebce9bc0
dedf89df1602
dedf89df1602
02eb59c6fd66
dedf89df1602
dedf89df1602
02eb59c6fd66
5e11ebce9bc0
5e11ebce9bc0
5e11ebce9bc0
dedf89df1602
5e11ebce9bc0
44a98be4e4b4
5e11ebce9bc0
5e11ebce9bc0
5e11ebce9bc0
5e11ebce9bc0
175721d796d7
44a98be4e4b4
8642f7a7bf01
5e11ebce9bc0
5e11ebce9bc0
5e11ebce9bc0
5e11ebce9bc0
44a98be4e4b4
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
175721d796d7
44a98be4e4b4
44a98be4e4b4
dedf89df1602
dedf89df1602
a226385adc2d
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
06f259bf8031
175721d796d7
44a98be4e4b4
44a98be4e4b4
dedf89df1602
dedf89df1602
dedf89df1602
dedf89df1602
dedf89df1602
06f259bf8031
a226385adc2d
06f259bf8031
06f259bf8031
06f259bf8031
6938bcacc41e
6938bcacc41e
6938bcacc41e
6938bcacc41e
6938bcacc41e
6ec2e0261a03
6938bcacc41e
6938bcacc41e
6938bcacc41e
6938bcacc41e
6938bcacc41e
6938bcacc41e
a226385adc2d
mod arena;
// mod ast;
mod eval;
pub(crate) mod inputsource;
pub(crate) mod input_source2;
// mod lexer;
mod parser;
#[cfg(test)] mod tests;

// TODO: Remove when not benchmarking
pub(crate) mod ast;
pub(crate) mod ast_printer;
pub(crate) mod lexer;

lazy_static::lazy_static! {
    /// Conveniently-provided protocol description initialized with a zero-length PDL string.
    /// Exposed to minimize repeated initializations of this common protocol description.
    pub static ref TRIVIAL_PD: std::sync::Arc<ProtocolDescription> = {
        std::sync::Arc::new(ProtocolDescription::parse(b"").unwrap())
    };
}

use crate::common::*;
use crate::protocol::ast::*;
use crate::protocol::eval::*;
use crate::protocol::inputsource::*;
use crate::protocol::parser::*;

/// Description of a protocol object, used to configure new connectors.
#[repr(C)]
pub struct ProtocolDescription {
    heap: Heap,
    source: InputSource,
    root: RootId,
}
#[derive(Debug, Clone)]
pub(crate) struct ComponentState {
    prompt: Prompt,
}
pub(crate) enum EvalContext<'a> {
    Nonsync(&'a mut NonsyncProtoContext<'a>),
    Sync(&'a mut SyncProtoContext<'a>),
    // None,
}
//////////////////////////////////////////////

impl std::fmt::Debug for ProtocolDescription {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "(An opaque protocol description)")
    }
}
impl ProtocolDescription {
    // TODO: Allow for multi-file compilation
    pub fn parse(buffer: &[u8]) -> Result<Self, String> {
        // TODO: @fixme, keep code compilable, but needs support for multiple
        //  input files.
        let source = InputSource::from_buffer(buffer).unwrap();
        let mut parser = Parser::new();
        parser.feed(source).expect("failed to lex source");
        
        if let Err(err) = parser.parse() {
            println!("ERROR:\n{}", err);
            return Err(format!("{}", err))
        }

        debug_assert_eq!(parser.modules.len(), 1, "only supporting one module here for now");
        let root = parser.modules[0].root_id;
        return Ok(ProtocolDescription { heap: parser.heap, source: parser.modules[0].source.clone(), root });
    }
    pub(crate) fn component_polarities(
        &self,
        identifier: &[u8],
    ) -> Result<Vec<Polarity>, AddComponentError> {
        use AddComponentError::*;
        let h = &self.heap;
        let root = &h[self.root];
        let def = root.get_definition_ident(h, identifier);
        if def.is_none() {
            return Err(NoSuchComponent);
        }
        let def = &h[def.unwrap()];
        if !def.is_component() {
            return Err(NoSuchComponent);
        }
        for &param in def.parameters().iter() {
            let param = &h[param];
            let parser_type = &h[param.parser_type];

            match parser_type.variant {
                ParserTypeVariant::Input(_) | ParserTypeVariant::Output(_) => continue,
                _ => {
                    return Err(NonPortTypeParameters);
                }
            }
        }
        let mut result = Vec::new();
        for &param in def.parameters().iter() {
            let param = &h[param];
            let parser_type = &h[param.parser_type];

            if let ParserTypeVariant::Input(_) = parser_type.variant {
                result.push(Polarity::Getter)
            } else if let ParserTypeVariant::Output(_) = parser_type.variant {
                result.push(Polarity::Putter)
            } else {
                unreachable!()
            }
        }
        Ok(result)
    }
    // expects port polarities to be correct
    pub(crate) fn new_component(&self, identifier: &[u8], ports: &[PortId]) -> ComponentState {
        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();
        ComponentState { prompt: Prompt::new(h, def, &args) }
    }
}
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.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 NonsyncBlocker::Inconsistent,
                    EvalContinuation::Terminal => 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, args) => {
                        // Look up definition (TODO for now, assume it is a definition)
                        let h = &pd.heap;
                        let init_state = ComponentState { prompt: Prompt::new(h, definition_id, &args) };
                        context.new_component(&args, init_state);
                        // Continue stepping
                        continue;
                    }
                    // 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.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 SyncBlocker::Inconsistent,
                    // First need to exit synchronous block before definition may end
                    EvalContinuation::Terminal => 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::BlockFires(port) => match port {
                        Value::Output(OutputValue(port)) => {
                            return SyncBlocker::CouldntCheckFiring(port);
                        }
                        Value::Input(InputValue(port)) => {
                            return SyncBlocker::CouldntCheckFiring(port);
                        }
                        _ => unreachable!(),
                    },
                    EvalContinuation::BlockGet(port) => match port {
                        Value::Output(OutputValue(port)) => {
                            return SyncBlocker::CouldntReadMsg(port);
                        }
                        Value::Input(InputValue(port)) => {
                            return SyncBlocker::CouldntReadMsg(port);
                        }
                        _ => unreachable!(),
                    },
                    EvalContinuation::Put(port, message) => {
                        let value;
                        match port {
                            Value::Output(OutputValue(port_value)) => {
                                value = port_value;
                            }
                            Value::Input(InputValue(port_value)) => {
                                value = port_value;
                            }
                            _ => unreachable!(),
                        }
                        let payload;
                        match message {
                            Value::Message(MessageValue(None)) => {
                                // Putting a null message is inconsistent
                                return SyncBlocker::Inconsistent;
                            }
                            Value::Message(MessageValue(Some(buffer))) => {
                                // Create a copy of the payload
                                payload = buffer;
                            }
                            _ => unreachable!(),
                        }
                        return SyncBlocker::PutMsg(value, payload);
                    }
                },
            }
        }
    }
}
impl EvalContext<'_> {
    // fn random(&mut self) -> LongValue {
    //     match self {
    //         // EvalContext::None => unreachable!(),
    //         EvalContext::Nonsync(_context) => todo!(),
    //         EvalContext::Sync(_) => unreachable!(),
    //     }
    // }
    fn new_component(&mut self, args: &[Value], init_state: ComponentState) -> () {
        match self {
            // EvalContext::None => unreachable!(),
            EvalContext::Nonsync(context) => {
                let mut moved_ports = HashSet::new();
                for arg in args.iter() {
                    match arg {
                        Value::Output(OutputValue(port)) => {
                            moved_ports.insert(*port);
                        }
                        Value::Input(InputValue(port)) => {
                            moved_ports.insert(*port);
                        }
                        _ => {}
                    }
                }
                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(OutputValue(from));
                let to = Value::Input(InputValue(to));
                return [from, to];
            }
            EvalContext::Sync(_) => unreachable!(),
        }
    }
    fn fires(&mut self, port: Value) -> Option<Value> {
        match self {
            // EvalContext::None => unreachable!(),
            EvalContext::Nonsync(_) => unreachable!(),
            EvalContext::Sync(context) => match port {
                Value::Output(OutputValue(port)) => context.is_firing(port).map(Value::from),
                Value::Input(InputValue(port)) => context.is_firing(port).map(Value::from),
                _ => unreachable!(),
            },
        }
    }
    fn get(&mut self, port: Value) -> Option<Value> {
        match self {
            // EvalContext::None => unreachable!(),
            EvalContext::Nonsync(_) => unreachable!(),
            EvalContext::Sync(context) => match port {
                Value::Output(OutputValue(port)) => {
                    context.read_msg(port).map(Value::receive_message)
                }
                Value::Input(InputValue(port)) => {
                    context.read_msg(port).map(Value::receive_message)
                }
                _ => unreachable!(),
            },
        }
    }
    fn did_put(&mut self, port: Value) -> bool {
        match self {
            EvalContext::Nonsync(_) => unreachable!("did_put in nonsync context"),
            EvalContext::Sync(context) => match port {
                Value::Output(OutputValue(port)) => {
                    context.did_put_or_get(port)
                },
                Value::Input(_) => unreachable!("did_put on input port"),
                _ => unreachable!("did_put on non-port value")
            }
        }
    }
}