Changeset - 935120e93ef1
[Not reviewed]
0 3 0
Hans-Dieter Hiep - 5 years ago 2020-02-05 17:27:11
hdh@cwi.nl
Rework setup of protocol description
3 files changed with 26 insertions and 47 deletions:
0 comments (0 inline, 0 general)
src/protocol/ast.rs
Show inline comments
 
@@ -1199,48 +1199,56 @@ impl Index<DeclarationId> for Heap {
 
    }
 
}
 

	
 
#[derive(Debug, Clone)]
 
pub struct Root {
 
    pub this: RootId,
 
    // Phase 1: parser
 
    pub position: InputPosition,
 
    pub pragmas: Vec<PragmaId>,
 
    pub imports: Vec<ImportId>,
 
    pub definitions: Vec<DefinitionId>,
 
    // Pase 2: linker
 
    pub declarations: Vec<DeclarationId>,
 
}
 

	
 
impl Root {
 
    pub fn get_definition(&self, h: &Heap, id: IdentifierId) -> Option<DefinitionId> {
 
        for &def in self.definitions.iter() {
 
            if h[h[def].identifier()] == h[id] {
 
                return Some(def);
 
            }
 
        }
 
        None
 
    }
 
    pub fn get_definition_ident(&self, h: &Heap, id: &[u8]) -> Option<DefinitionId> {
 
        for &def in self.definitions.iter() {
 
            if h[h[def].identifier()].ident() == id {
 
                return Some(def);
 
            }
 
        }
 
        None
 
    }
 
    pub fn get_declaration(&self, h: &Heap, id: IdentifierId) -> Option<DeclarationId> {
 
        for &decl in self.declarations.iter() {
 
            if h[h[decl].identifier()] == h[id] {
 
                return Some(decl);
 
            }
 
        }
 
        None
 
    }
 
}
 

	
 
impl SyntaxElement for Root {
 
    fn position(&self) -> InputPosition {
 
        self.position
 
    }
 
}
 

	
 
#[derive(Debug, Clone)]
 
pub struct Pragma {
 
    pub this: PragmaId,
 
    // Phase 1: parser
 
    pub position: InputPosition,
 
    pub value: Vec<u8>,
 
}
 

	
src/protocol/mod.rs
Show inline comments
 
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,
 
    main: ComponentId,
 
    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) => {
 
                // Find main definition (grammar rule ensures this exists)
 
                let sym = heap.get_external_identifier(b"main");
 
                let def = heap[root].get_definition(&heap, sym.upcast()).unwrap();
 
                let main = heap[def].as_component().this();
 
                return Ok(ProtocolDescriptionImpl { heap, source, root, main });
 
                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 main_interface_polarities(&self) -> Vec<Polarity> {
 
    //     let def = &self.heap[self.main];
 
    //     let mut result = Vec::new();
 
    //     for &param in def.parameters().iter() {
 
    //         let param = &self.heap[param];
 
    //         let type_annot = &self.heap[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!()
 
    //         }
 
    //     }
 
    //     result
 
    // }
 
    fn new_main_component(&self, ports: &[Key]) -> ComponentStateImpl {
 
    fn new_main_component(&self, identifier: &[u8], ports: &[(Polarity, Key)]) -> Result<ComponentStateImpl, NewMainErr> {
 
        // Find symbol with identifier
 
        let def = self.heap[self.root].get_definition_ident(&heap, identifier);
 
        if def.is_none() {
 
            return Err(NewMainErr::NoSuchComponent);
 
        }
 
        let def = &self.heap[def.unwrap()];
 
        if !def.is_component() {
 
            return Err(NewMainErr::NoSuchComponent);
 
        }
 
        let main = def.as_component().this();
 
        //
 
        let mut args = Vec::new();
 
        for (&x, y) in ports.iter().zip(self.main_interface_polarities()) {
 
            match y {
 
                Polarity::Getter => args.push(Value::Input(InputValue(x))),
 
                Polarity::Putter => args.push(Value::Output(OutputValue(x))),
 
        for &(x, y) in ports.iter() {
 
            match x {
 
                Polarity::Getter => args.push(Value::Input(InputValue(y))),
 
                Polarity::Putter => args.push(Value::Output(OutputValue(y))),
 
            }
 
        }
 
        ComponentStateImpl { prompt: Prompt::new(&self.heap, self.main.upcast(), &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!(),
src/protocol/parser.rs
Show inline comments
 
@@ -1763,109 +1763,74 @@ impl Visitor for SelectableExpressions {
 
        recursive_array_expression(self, h, expr)?;
 
        self.selectable = old;
 
        Ok(())
 
    }
 
    fn visit_call_expression(&mut self, h: &mut Heap, expr: CallExpressionId) -> VisitorResult {
 
        let old = self.selectable;
 
        self.selectable = false;
 
        recursive_call_expression(self, h, expr)?;
 
        self.selectable = old;
 
        Ok(())
 
    }
 
    fn visit_constant_expression(
 
        &mut self,
 
        h: &mut Heap,
 
        expr: ConstantExpressionId,
 
    ) -> VisitorResult {
 
        if self.selectable {
 
            self.error(h[expr].position)
 
        } else {
 
            Ok(())
 
        }
 
    }
 
}
 

	
 
struct CheckMainComponent {}
 

	
 
impl CheckMainComponent {
 
    fn new() -> Self {
 
        CheckMainComponent {}
 
    }
 
    fn visit_protocol_description(&mut self, h: &mut Heap, root: RootId) -> VisitorResult {
 
        let sym = h.get_external_identifier(b"main");
 
        let root = &h[root];
 
        let def = root.get_definition(h, sym.upcast());
 
        if def.is_none() {
 
            return Err(ParseError::new(root.position, "Missing main definition"));
 
        }
 
        let def = &h[def.unwrap()];
 
        if !def.is_component() {
 
            return Err(ParseError::new(def.position(), "Main definition must be a component"));
 
        }
 
        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(ParseError::new(type_annot.position, "Illegal type"));
 
            }
 
            match type_annot.the_type.primitive {
 
                PrimitiveType::Input | PrimitiveType::Output => continue,
 
                _ => {
 
                    return Err(ParseError::new(type_annot.position, "Illegal type"));
 
                }
 
            }
 
        }
 
        Ok(())
 
    }
 
}
 

	
 
pub struct Parser<'a> {
 
    source: &'a mut InputSource,
 
}
 

	
 
impl<'a> Parser<'a> {
 
    pub fn new(source: &'a mut InputSource) -> Self {
 
        Parser { source }
 
    }
 
    pub fn parse(&mut self, h: &mut Heap) -> Result<RootId, ParseError> {
 
        let mut lex = Lexer::new(self.source);
 
        let pd = lex.consume_protocol_description(h)?;
 
        NestedSynchronousStatements::new().visit_protocol_description(h, pd)?;
 
        ChannelStatementOccurrences::new().visit_protocol_description(h, pd)?;
 
        FunctionStatementReturns::new().visit_protocol_description(h, pd)?;
 
        ComponentStatementReturnNew::new().visit_protocol_description(h, pd)?;
 
        CheckBuiltinOccurrences::new().visit_protocol_description(h, pd)?;
 
        BuildSymbolDeclarations::new().visit_protocol_description(h, pd)?;
 
        LinkCallExpressions::new().visit_protocol_description(h, pd)?;
 
        BuildScope::new().visit_protocol_description(h, pd)?;
 
        ResolveVariables::new().visit_protocol_description(h, pd)?;
 
        LinkStatements::new().visit_protocol_description(h, pd)?;
 
        BuildLabels::new().visit_protocol_description(h, pd)?;
 
        ResolveLabels::new().visit_protocol_description(h, pd)?;
 
        AssignableExpressions::new().visit_protocol_description(h, pd)?;
 
        IndexableExpressions::new().visit_protocol_description(h, pd)?;
 
        SelectableExpressions::new().visit_protocol_description(h, pd)?;
 
        CheckMainComponent::new().visit_protocol_description(h, pd)?;
 
        Ok(pd)
 
    }
 
}
 

	
 
#[cfg(test)]
 
mod tests {
 
    extern crate test_generator;
 

	
 
    use std::fs::File;
 
    use std::io::Read;
 
    use std::path::Path;
 

	
 
    use test_generator::test_resources;
 

	
 
    use super::*;
 

	
 
    #[test_resources("testdata/parser/positive/*.pdl")]
 
    fn batch1(resource: &str) {
 
        let path = Path::new(resource);
 
        let mut heap = Heap::new();
 
        let mut source = InputSource::from_file(&path).unwrap();
 
        let mut parser = Parser::new(&mut source);
 
        match parser.parse(&mut heap) {
 
            Ok(_) => {}
0 comments (0 inline, 0 general)