Files @ 339b493050e2
Branch filter:

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

339b493050e2 13.8 KiB application/rls-services+xml Show Source Show as Raw Download as Raw
MH
WIP on tcp listener/socket test
3f236d37dad1
cc687c3f75c5
012b61623f5a
06f259bf8031
aaeaf5986496
06f259bf8031
814be01095d9
113e4349a706
113e4349a706
6c04a99de862
b69f417a9972
b69f417a9972
b69f417a9972
113e4349a706
a226385adc2d
012b61623f5a
06f259bf8031
ef37386d0c6f
06f259bf8031
637115283740
637115283740
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
44a98be4e4b4
012b61623f5a
113e4349a706
012b61623f5a
9774ef9fe888
9774ef9fe888
9774ef9fe888
9774ef9fe888
06f259bf8031
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
113e4349a706
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
d23aebafc979
637115283740
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
637115283740
637115283740
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
d23aebafc979
d23aebafc979
637115283740
113e4349a706
637115283740
637115283740
637115283740
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
637115283740
637115283740
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
637115283740
daf15df0f8ca
daf15df0f8ca
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
339b493050e2
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
b69f417a9972
06f259bf8031
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
daf15df0f8ca
637115283740
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
637115283740
cc8030b35903
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
113e4349a706
113e4349a706
113e4349a706
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
560ed3c4dc1d
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
113e4349a706
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
9a4f36415198
9a4f36415198
9a4f36415198
9a4f36415198
9a4f36415198
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
1cc3bd69b119
113e4349a706
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_writer;
mod token_writer;

use std::sync::Mutex;

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

pub use parser::type_table::TypeId;

/// 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 ProtocolDescription {
    pub fn parse(buffer: &[u8]) -> Result<Self, String> {
        let source = InputSource::new(String::new(), Vec::from(buffer));
        let mut parser = Parser::new(None)?;
        parser.feed(source).expect("failed to feed source");
        
        if let Err(err) = parser.parse() {
            println!("ERROR:\n{}", err);
            return Err(format!("{}", err))
        }

        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_by_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_procedure() {
            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_procedure();
        if !ast_definition.poly_vars.is_empty() || ast_definition.kind == ProcedureKind::Function {
            return Err(ComponentCreationError::DefinitionNotComponent);
        }

        // - check number of arguments by retrieving the one instantiated
        //   monomorph
        let concrete_type = ConcreteType{ parts: vec![ConcreteTypePart::Component(ast_definition.this, 0)] };
        let procedure_type_id = self.types.get_monomorph_type_id(&definition_id, &concrete_type.parts).unwrap();
        let procedure_monomorph_index = self.types.get_monomorph(procedure_type_id).variant.as_procedure().monomorph_index;
        let monomorph_info = &ast_definition.monomorphs[procedure_monomorph_index as usize];
        if monomorph_info.argument_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_id = monomorph_info.argument_types[arg_idx];
            let expected_type = &self.types.get_monomorph(expected_type_id).concrete_type;
            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, ast_definition.this, procedure_type_id, arguments));
    }

    /// A somewhat temporary method. Can be used by components to lookup type
    /// definitions by their name (to have their implementation somewhat
    /// resistant to changes in the standard library)
    pub(crate) fn find_type<'a>(&'a self, module_name: &[u8], type_name: &[u8]) -> Option<TypeInspector<'a>> {
        // Lookup type definition in module
        let root_id = self.lookup_module_root(module_name)?;
        let module = &self.heap[root_id];
        let definition_id = module.get_definition_by_ident(&self.heap, type_name)?;
        let definition = &self.heap[definition_id];

        // Make sure type is not polymorphic and is not a procedure
        if !definition.poly_vars().is_empty() {
            return None;
        }
        if definition.is_procedure() {
            return None;
        }

        // Lookup type in type table
        let type_parts = [ConcreteTypePart::Instance(definition_id, 0)];
        let type_id = self.types.get_monomorph_type_id(&definition_id, &type_parts)
            .expect("type ID for non-polymorphic type");
        let type_monomorph = self.types.get_monomorph(type_id);

        return Some(TypeInspector{
            heap: definition,
            type_table: type_monomorph
        });
    }

    /// Again a somewhat temporary method. Can be used by components to look up
    /// the definition of a particular procedure. Intended use is to find the
    /// DefinitionId/TypeId of builtin components.
    pub(crate) fn find_procedure(&self, module_name: &[u8], proc_name: &[u8]) -> Option<(ProcedureDefinitionId, TypeId)> {
        // Lookup type definition in module
        let root_id = self.lookup_module_root(module_name)?;
        let module = &self.heap[root_id];
        let definition_id = module.get_definition_by_ident(&self.heap, proc_name)?;
        let definition = &self.heap[definition_id];

        // Make sure the procedure is not polymorphic
        if !definition.poly_vars().is_empty() {
            return None;
        }
        if !definition.is_procedure() {
            return None;
        }

        // Lookup in type table
        let definition = definition.as_procedure();
        let type_parts = [ConcreteTypePart::Component(definition.this, 0)];
        let type_id = self.types.get_monomorph_type_id(&definition.this.upcast(), &type_parts)
            .expect("type ID for non-polymorphic procedure");
        return Some((definition.this, type_id));
    }

    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::Pointer | 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
    fn performed_select_wait(&mut self) -> Option<u32>; // None if not yet notified runtime of select blocker
}

pub struct ProtocolDescriptionBuilder {
    parser: Parser,
}

impl ProtocolDescriptionBuilder {
    pub fn new(std_lib_dir: Option<String>) -> Result<Self, String> {
        let mut parser = Parser::new(std_lib_dir)?;
        return Ok(Self{ parser })
    }

    pub fn add(&mut self, filename: String, buffer: Vec<u8>) -> Result<(), ParseError> {
        let input = InputSource::new(filename, buffer);
        self.parser.feed(input)?;

        return Ok(())
    }

    pub fn compile(mut self) -> Result<ProtocolDescription, ParseError> {
        self.parser.parse()?;

        let modules: Vec<Module> = self.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: self.parser.heap,
            types: self.parser.type_table,
            pool: Mutex::new(self.parser.string_pool),
        });
    }
}

pub struct TypeInspector<'a> {
    heap: &'a Definition,
    type_table: &'a MonoType,
}

impl<'a> TypeInspector<'a> {
    pub fn as_union(&'a self) -> UnionTypeInspector<'a> {
        let heap = self.heap.as_union();
        let type_table = self.type_table.variant.as_union();
        return UnionTypeInspector{ heap, type_table };
    }

    pub fn as_struct(&'a self) -> StructTypeInspector<'a> {
        let heap = self.heap.as_struct();
        let type_table = self.type_table.variant.as_struct();
        return StructTypeInspector{ heap, type_table };
    }
}

pub struct UnionTypeInspector<'a> {
    heap: &'a UnionDefinition,
    type_table: &'a UnionMonomorph,
}

impl UnionTypeInspector<'_> {
    /// Retrieves union variant tag value.
    pub fn get_variant_tag_value(&self, variant_name: &[u8]) -> Option<i64> {
        let variant_index = self.heap.variants.iter()
            .position(|v| v.identifier.value.as_bytes() == variant_name)?;
        return Some(variant_index as i64);
    }
}

pub struct StructTypeInspector<'a> {
    heap: &'a StructDefinition,
    type_table: &'a StructMonomorph,
}

impl StructTypeInspector<'_> {
    /// Retrieves number of struct fields
    pub fn get_num_struct_fields(&self) -> usize {
        return self.heap.fields.len();
    }

    /// Retrieves struct field index
    pub fn get_struct_field_index(&self, field_name: &[u8]) -> Option<usize> {
        let field_index = self.heap.fields.iter()
            .position(|v| v.field.value.as_bytes() == field_name)?;
        return Some(field_index);
    }
}