diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs index 45f880fbe64dec700ef72086e324877299969e5b..d0dd2453c06c9f49d1cce7f935c3c0f092dba0ce 100644 --- a/src/protocol/mod.rs +++ b/src/protocol/mod.rs @@ -5,12 +5,13 @@ mod parser; #[cfg(test)] mod tests; pub(crate) mod ast; -pub(crate) mod ast_printer; +pub(crate) mod ast_writer; +mod token_writer; use std::sync::Mutex; use crate::collections::{StringPool, StringRef}; -use crate::protocol::ast::*; +pub use crate::protocol::ast::*; use crate::protocol::eval::*; use crate::protocol::input_source::*; use crate::protocol::parser::*; @@ -51,7 +52,7 @@ pub enum ComponentCreationError { impl ProtocolDescription { pub fn parse(buffer: &[u8]) -> Result { let source = InputSource::new(String::new(), Vec::from(buffer)); - let mut parser = Parser::new(); + let mut parser = Parser::new(None)?; parser.feed(source).expect("failed to feed source"); if let Err(err) = parser.parse() { @@ -59,7 +60,6 @@ impl ProtocolDescription { return Err(format!("{}", err)) } - debug_assert_eq!(parser.modules.len(), 1, "only supporting one module here for now"); let modules: Vec = parser.modules.into_iter() .map(|module| Module{ source: module.source, @@ -87,7 +87,7 @@ impl ProtocolDescription { let module_root = module_root.unwrap(); let root = &self.heap[module_root]; - let definition_id = root.get_definition_ident(&self.heap, identifier); + let definition_id = root.get_definition_by_ident(&self.heap, identifier); if definition_id.is_none() { return Err(ComponentCreationError::DefinitionDoesntExist); } @@ -108,7 +108,7 @@ impl ProtocolDescription { // - 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_procedure_monomorph_type_id(&definition_id, &concrete_type.parts).unwrap(); + 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() { @@ -130,6 +130,36 @@ impl ProtocolDescription { 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> { + // 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 + }); + } + fn lookup_module_root(&self, module_name: &[u8]) -> Option { for module in self.modules.iter() { match &module.name { @@ -223,10 +253,9 @@ pub struct ProtocolDescriptionBuilder { } impl ProtocolDescriptionBuilder { - pub fn new() -> Self { - return Self{ - parser: Parser::new(), - } + pub fn new(std_lib_dir: Option) -> Result { + let mut parser = Parser::new(std_lib_dir)?; + return Ok(Self{ parser }) } pub fn add(&mut self, filename: String, buffer: Vec) -> Result<(), ParseError> { @@ -255,3 +284,30 @@ impl ProtocolDescriptionBuilder { }); } } + +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 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 { + let variant_index = self.heap.variants.iter() + .position(|v| v.identifier.value.as_bytes() == variant_name)?; + return Some(variant_index as i64); + } +} \ No newline at end of file