Files @ b374c6bff853
Branch filter:

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

b374c6bff853 8.6 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
MH
Fix introduced bugs
3f236d37dad1
cc687c3f75c5
012b61623f5a
06f259bf8031
aaeaf5986496
06f259bf8031
814be01095d9
729feec4d37a
6c04a99de862
b69f417a9972
b69f417a9972
b69f417a9972
06f259bf8031
a226385adc2d
012b61623f5a
06f259bf8031
ef37386d0c6f
06f259bf8031
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
d3835a56401d
d600dd299dde
44a98be4e4b4
cc8030b35903
cc8030b35903
cc8030b35903
cc8030b35903
06f259bf8031
9b32fa307ceb
4c9116f4253b
cc8030b35903
44a98be4e4b4
120857c65991
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
58dfabd1be9f
2d2a4eb3c08e
daf15df0f8ca
daf15df0f8ca
44a98be4e4b4
06f259bf8031
d23010006486
06f259bf8031
06f259bf8031
44a98be4e4b4
44a98be4e4b4
012b61623f5a
33ea10021de4
012b61623f5a
9774ef9fe888
9774ef9fe888
9774ef9fe888
9774ef9fe888
06f259bf8031
9774ef9fe888
9774ef9fe888
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
ef37386d0c6f
b69f417a9972
b69f417a9972
06f259bf8031
daf15df0f8ca
c1b2442f23b2
daf15df0f8ca
e771fee620aa
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
a43d61913724
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
d23aebafc979
d23aebafc979
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
d23aebafc979
d23aebafc979
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
d23aebafc979
d23aebafc979
d23aebafc979
d23aebafc979
d23aebafc979
d23aebafc979
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
d23aebafc979
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
b374c6bff853
daf15df0f8ca
daf15df0f8ca
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
06f259bf8031
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
a43d61913724
a43d61913724
a43d61913724
a43d61913724
a43d61913724
a43d61913724
a43d61913724
a43d61913724
a43d61913724
a43d61913724
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
a43d61913724
a43d61913724
40a57c0668a0
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
03f278e76a41
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
06f259bf8031
cc8030b35903
cc8030b35903
088be7630245
088be7630245
ff6ade8b8097
088be7630245
088be7630245
cc8030b35903
mod arena;
pub(crate) mod eval;
pub(crate) mod input_source;
mod parser;
#[cfg(test)] mod tests;

pub(crate) mod ast;
pub(crate) mod ast_printer;

use std::sync::Mutex;

use crate::collections::{StringPool, StringRef};
use crate::protocol::ast::*;
use crate::protocol::eval::*;
use crate::protocol::input_source::*;
use crate::protocol::parser::*;
use crate::protocol::type_table::*;

/// A protocol description module
pub struct Module {
    pub(crate) source: InputSource,
    pub(crate) root_id: RootId,
    pub(crate) name: Option<StringRef<'static>>,
}
/// Description of a protocol object, used to configure new connectors.
#[repr(C)]
pub struct ProtocolDescription {
    pub(crate) modules: Vec<Module>,
    pub(crate) heap: Heap,
    pub(crate) types: TypeTable,
    pub(crate) pool: Mutex<StringPool>,
}
#[derive(Debug, Clone)]
pub(crate) struct ComponentState {
    pub(crate) prompt: Prompt,
}

#[derive(Debug)]
pub enum ComponentCreationError {
    ModuleDoesntExist,
    DefinitionDoesntExist,
    DefinitionNotComponent,
    InvalidNumArguments,
    InvalidArgumentType(usize),
    UnownedPort,
    InSync,
}

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 {
    pub fn parse(buffer: &[u8]) -> Result<Self, String> {
        let source = InputSource::new(String::new(), Vec::from(buffer));
        let mut parser = Parser::new();
        parser.feed(source).expect("failed to feed 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 modules: Vec<Module> = parser.modules.into_iter()
            .map(|module| Module{
                source: module.source,
                root_id: module.root_id,
                name: module.name.map(|(_, name)| name)
            })
            .collect();

        return Ok(ProtocolDescription {
            modules,
            heap: parser.heap,
            types: parser.type_table,
            pool: Mutex::new(parser.string_pool),
        });
    }

    pub(crate) fn new_component(
        &self, module_name: &[u8], identifier: &[u8], arguments: ValueGroup
    ) -> Result<Prompt, ComponentCreationError> {
        // Find the module in which the definition can be found
        let module_root = self.lookup_module_root(module_name);
        if module_root.is_none() {
            return Err(ComponentCreationError::ModuleDoesntExist);
        }
        let module_root = module_root.unwrap();

        let root = &self.heap[module_root];
        let definition_id = root.get_definition_ident(&self.heap, identifier);
        if definition_id.is_none() {
            return Err(ComponentCreationError::DefinitionDoesntExist);
        }
        let definition_id = definition_id.unwrap();

        let ast_definition = &self.heap[definition_id];
        if !ast_definition.is_component() {
            return Err(ComponentCreationError::DefinitionNotComponent);
        }

        // Make sure that the types of the provided value group matches that of
        // the expected types.
        let ast_definition = ast_definition.as_component();
        if !ast_definition.poly_vars.is_empty() {
            return Err(ComponentCreationError::DefinitionNotComponent);
        }

        // - check number of arguments by retrieving the one instantiated
        //   monomorph
        let concrete_type = ConcreteType{ parts: vec![ConcreteTypePart::Component(definition_id, 0)] };
        let mono_index = self.types.get_procedure_monomorph_index(&definition_id, &concrete_type.parts).unwrap();
        let mono_type = self.types.get_procedure_monomorph(mono_index);
        if mono_type.arg_types.len() != arguments.values.len() {
            return Err(ComponentCreationError::InvalidNumArguments);
        }

        // - for each argument try to make sure the types match
        for arg_idx in 0..arguments.values.len() {
            let expected_type = &mono_type.arg_types[arg_idx];
            let provided_value = &arguments.values[arg_idx];
            if !self.verify_same_type(expected_type, 0, &arguments, provided_value) {
                return Err(ComponentCreationError::InvalidArgumentType(arg_idx));
            }
        }

        // By now we're sure that all of the arguments are correct. So create
        // the connector.
        return Ok(Prompt::new(&self.types, &self.heap, definition_id, mono_index, arguments));
    }

    fn lookup_module_root(&self, module_name: &[u8]) -> Option<RootId> {
        for module in self.modules.iter() {
            match &module.name {
                Some(name) => if name.as_bytes() == module_name {
                    return Some(module.root_id);
                },
                None => if module_name.is_empty() {
                    return Some(module.root_id);
                }
            }
        }

        return None;
    }

    fn verify_same_type(&self, expected: &ConcreteType, expected_idx: usize, arguments: &ValueGroup, argument: &Value) -> bool {
        use ConcreteTypePart as CTP;

        match &expected.parts[expected_idx] {
            CTP::Void | CTP::Message | CTP::Slice | CTP::Function(_, _) | CTP::Component(_, _) => unreachable!(),
            CTP::Bool => if let Value::Bool(_) = argument { true } else { false },
            CTP::UInt8 => if let Value::UInt8(_) = argument { true } else { false },
            CTP::UInt16 => if let Value::UInt16(_) = argument { true } else { false },
            CTP::UInt32 => if let Value::UInt32(_) = argument { true } else { false },
            CTP::UInt64 => if let Value::UInt64(_) = argument { true } else { false },
            CTP::SInt8 => if let Value::SInt8(_) = argument { true } else { false },
            CTP::SInt16 => if let Value::SInt16(_) = argument { true } else { false },
            CTP::SInt32 => if let Value::SInt32(_) = argument { true } else { false },
            CTP::SInt64 => if let Value::SInt64(_) = argument { true } else { false },
            CTP::Character => if let Value::Char(_) = argument { true } else { false },
            CTP::String => {
                // Match outer string type and embedded character types
                if let Value::String(heap_pos) = argument {
                    for element in &arguments.regions[*heap_pos as usize] {
                        if let Value::Char(_) = element {} else {
                            return false;
                        }
                    }
                } else {
                    return false;
                }

                return true;
            },
            CTP::Array => {
                if let Value::Array(heap_pos) = argument {
                    let heap_pos = *heap_pos;
                    for element in &arguments.regions[heap_pos as usize] {
                        if !self.verify_same_type(expected, expected_idx + 1, arguments, element) {
                            return false;
                        }
                    }
                    return true;
                } else {
                    return false;
                }
            },
            CTP::Input => if let Value::Input(_) = argument { true } else { false },
            CTP::Output => if let Value::Output(_) = argument { true } else { false },
            CTP::Tuple(_) => todo!("implement full type checking on user-supplied arguments"),
            CTP::Instance(definition_id, _num_embedded) => {
                let definition = self.types.get_base_definition(definition_id).unwrap();
                match &definition.definition {
                    DefinedTypeVariant::Enum(definition) => {
                        if let Value::Enum(variant_value) = argument {
                            let is_valid = definition.variants.iter()
                                .any(|v| v.value == *variant_value);
                            return is_valid;
                        }
                    },
                    _ => todo!("implement full type checking on user-supplied arguments"),
                }

                return false;
            },
        }
    }
}

pub trait RunContext {
    fn performed_put(&mut self, port: PortId) -> bool;
    fn performed_get(&mut self, port: PortId) -> Option<ValueGroup>; // None if still waiting on message
    fn fires(&mut self, port: PortId) -> Option<Value>; // None if not yet branched
    fn performed_fork(&mut self) -> Option<bool>; // None if not yet forked
    fn created_channel(&mut self) -> Option<(Value, Value)>; // None if not yet prepared
}